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 18namespace { 19 20base::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 44namespace remoting { 45 46PipeMessagingChannel::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 57PipeMessagingChannel::~PipeMessagingChannel() { 58} 59 60void 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 72void 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 85void 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 100void 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