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/pipe_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::File DuplicatePlatformFile(base::File file) { 21 base::PlatformFile result; 22 #if defined(OS_WIN) 23 if (!DuplicateHandle(GetCurrentProcess(), 24 file.TakePlatformFile(), 25 GetCurrentProcess(), 26 &result, 27 0, 28 FALSE, 29 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { 30 PLOG(ERROR) << "Failed to duplicate handle " << file.GetPlatformFile(); 31 return base::File(); 32 } 33 return base::File(result); 34 #elif defined(OS_POSIX) 35 result = dup(file.GetPlatformFile()); 36 return base::File(result); 37 #else 38 #error Not implemented. 39 #endif 40 } 41 42 } // namespace 43 44 namespace remoting { 45 46 PipeMessagingChannel::PipeMessagingChannel( 47 base::File input, 48 base::File output) 49 : native_messaging_reader_(DuplicatePlatformFile(input.Pass())), 50 native_messaging_writer_(new NativeMessagingWriter( 51 DuplicatePlatformFile(output.Pass()))), 52 event_handler_(NULL), 53 weak_factory_(this) { 54 weak_ptr_ = weak_factory_.GetWeakPtr(); 55 } 56 57 PipeMessagingChannel::~PipeMessagingChannel() { 58 } 59 60 void PipeMessagingChannel::Start(EventHandler* event_handler) { 61 DCHECK(CalledOnValidThread()); 62 DCHECK(!event_handler_); 63 64 event_handler_ = event_handler; 65 DCHECK(event_handler_); 66 67 native_messaging_reader_.Start( 68 base::Bind(&PipeMessagingChannel::ProcessMessage, weak_ptr_), 69 base::Bind(&PipeMessagingChannel::Shutdown, weak_ptr_)); 70 } 71 72 void PipeMessagingChannel::ProcessMessage(scoped_ptr<base::Value> message) { 73 DCHECK(CalledOnValidThread()); 74 75 if (message->GetType() != base::Value::TYPE_DICTIONARY) { 76 LOG(ERROR) << "Expected DictionaryValue"; 77 Shutdown(); 78 return; 79 } 80 81 if (event_handler_) 82 event_handler_->OnMessage(message.Pass()); 83 } 84 85 void PipeMessagingChannel::SendMessage( 86 scoped_ptr<base::Value> message) { 87 DCHECK(CalledOnValidThread()); 88 89 bool success = message && native_messaging_writer_; 90 if (success) 91 success = native_messaging_writer_->WriteMessage(*message); 92 93 if (!success) { 94 // Close the write pipe so no more responses will be sent. 95 native_messaging_writer_.reset(); 96 Shutdown(); 97 } 98 } 99 100 void PipeMessagingChannel::Shutdown() { 101 DCHECK(CalledOnValidThread()); 102 103 if (event_handler_) { 104 // Set event_handler_ to NULL to indicate the object is in a shutdown cycle. 105 // Since event_handler->OnDisconnect() will destroy the current object, 106 // |event_handler_| will become a dangling pointer after OnDisconnect() 107 // returns. Therefore, we set |event_handler_| to NULL beforehand. 108 EventHandler* handler = event_handler_; 109 event_handler_ = NULL; 110 handler->OnDisconnect(); 111 } 112 } 113 114 } // namespace remoting 115