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