Home | History | Annotate | Download | only in native_messaging
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "remoting/host/native_messaging/native_messaging_channel.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "base/bind.h"
      9 #include "base/callback.h"
     10 #include "base/callback_helpers.h"
     11 #include "base/location.h"
     12 #include "base/values.h"
     13 
     14 #if defined(OS_POSIX)
     15 #include <unistd.h>
     16 #endif
     17 
     18 namespace {
     19 
     20 base::PlatformFile DuplicatePlatformFile(base::PlatformFile handle) {
     21   base::PlatformFile result;
     22 #if defined(OS_WIN)
     23   if (!DuplicateHandle(GetCurrentProcess(),
     24                        handle,
     25                        GetCurrentProcess(),
     26                        &result,
     27                        0,
     28                        FALSE,
     29                        DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
     30     PLOG(ERROR) << "Failed to duplicate handle " << handle;
     31     return base::kInvalidPlatformFileValue;
     32   }
     33   return result;
     34 #elif defined(OS_POSIX)
     35   result = dup(handle);
     36   base::ClosePlatformFile(handle);
     37   return result;
     38 #else
     39 #error Not implemented.
     40 #endif
     41 }
     42 
     43 }  // namespace
     44 
     45 namespace remoting {
     46 
     47 NativeMessagingChannel::NativeMessagingChannel(
     48     base::PlatformFile input,
     49     base::PlatformFile output)
     50     : native_messaging_reader_(DuplicatePlatformFile(input)),
     51       native_messaging_writer_(new NativeMessagingWriter(
     52           DuplicatePlatformFile(output))),
     53       weak_factory_(this) {
     54   weak_ptr_ = weak_factory_.GetWeakPtr();
     55 }
     56 
     57 NativeMessagingChannel::~NativeMessagingChannel() {
     58 }
     59 
     60 void NativeMessagingChannel::Start(const SendMessageCallback& received_message,
     61                                    const base::Closure& quit_closure) {
     62   DCHECK(CalledOnValidThread());
     63   DCHECK(received_message_.is_null());
     64   DCHECK(quit_closure_.is_null());
     65 
     66   received_message_ = received_message;
     67   quit_closure_ = quit_closure;
     68 
     69   native_messaging_reader_.Start(
     70       base::Bind(&NativeMessagingChannel::ProcessMessage, weak_ptr_),
     71       base::Bind(&NativeMessagingChannel::Shutdown, weak_ptr_));
     72 }
     73 
     74 void NativeMessagingChannel::ProcessMessage(scoped_ptr<base::Value> message) {
     75   DCHECK(CalledOnValidThread());
     76 
     77   if (message->GetType() != base::Value::TYPE_DICTIONARY) {
     78     LOG(ERROR) << "Expected DictionaryValue";
     79     Shutdown();
     80     return;
     81   }
     82 
     83   scoped_ptr<base::DictionaryValue> message_dict(
     84       static_cast<base::DictionaryValue*>(message.release()));
     85   received_message_.Run(message_dict.Pass());
     86 }
     87 
     88 void NativeMessagingChannel::SendMessage(
     89     scoped_ptr<base::DictionaryValue> message) {
     90   DCHECK(CalledOnValidThread());
     91 
     92   bool success = message && native_messaging_writer_;
     93   if (success)
     94     success = native_messaging_writer_->WriteMessage(*message);
     95 
     96   if (!success) {
     97     // Close the write pipe so no more responses will be sent.
     98     native_messaging_writer_.reset();
     99     Shutdown();
    100   }
    101 }
    102 
    103 void NativeMessagingChannel::Shutdown() {
    104   DCHECK(CalledOnValidThread());
    105 
    106   if (!quit_closure_.is_null())
    107     base::ResetAndReturn(&quit_closure_).Run();
    108 }
    109 
    110 }  // namespace remoting
    111