18bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
28bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
38bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// found in the LICENSE file.
48bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "remoting/host/native_messaging/pipe_messaging_channel.h"
68bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
78bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/basictypes.h"
88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/bind.h"
98bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/callback.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/callback_helpers.h"
118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/location.h"
128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "base/values.h"
138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_POSIX)
158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <unistd.h>
168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace {
198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)base::File DuplicatePlatformFile(base::File file) {
218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  base::PlatformFile result;
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_WIN)
238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!DuplicateHandle(GetCurrentProcess(),
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       file.TakePlatformFile(),
258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       GetCurrentProcess(),
268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       &result,
278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       0,
288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       FALSE,
298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                       DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) {
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    PLOG(ERROR) << "Failed to duplicate handle " << file.GetPlatformFile();
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return base::File();
328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return base::File(result);
348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#elif defined(OS_POSIX)
35010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  result = dup(file.GetPlatformFile());
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return base::File(result);
378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#else
388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#error Not implemented.
398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace
438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)namespace remoting {
458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPipeMessagingChannel::PipeMessagingChannel(
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::File input,
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    base::File output)
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : native_messaging_reader_(DuplicatePlatformFile(input.Pass())),
508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      native_messaging_writer_(new NativeMessagingWriter(
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)          DuplicatePlatformFile(output.Pass()))),
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      event_handler_(NULL),
538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      weak_factory_(this) {
548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  weak_ptr_ = weak_factory_.GetWeakPtr();
558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciPipeMessagingChannel::~PipeMessagingChannel() {
588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PipeMessagingChannel::Start(EventHandler* event_handler) {
618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(CalledOnValidThread());
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!event_handler_);
638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  event_handler_ = event_handler;
651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(event_handler_);
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  native_messaging_reader_.Start(
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&PipeMessagingChannel::ProcessMessage, weak_ptr_),
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&PipeMessagingChannel::Shutdown, weak_ptr_));
708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PipeMessagingChannel::ProcessMessage(scoped_ptr<base::Value> message) {
738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(CalledOnValidThread());
748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (message->GetType() != base::Value::TYPE_DICTIONARY) {
768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(ERROR) << "Expected DictionaryValue";
778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    Shutdown();
788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (event_handler_)
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    event_handler_->OnMessage(message.Pass());
838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PipeMessagingChannel::SendMessage(
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<base::Value> message) {
878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(CalledOnValidThread());
888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool success = message && native_messaging_writer_;
908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (success)
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    success = native_messaging_writer_->WriteMessage(*message);
928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!success) {
948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Close the write pipe so no more responses will be sent.
958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    native_messaging_writer_.reset();
968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    Shutdown();
978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid PipeMessagingChannel::Shutdown() {
1018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (event_handler_) {
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Set event_handler_ to NULL to indicate the object is in a shutdown cycle.
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Since event_handler->OnDisconnect() will destroy the current object,
1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // |event_handler_| will become a dangling pointer after OnDisconnect()
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // returns. Therefore, we set |event_handler_| to NULL beforehand.
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EventHandler* handler = event_handler_;
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    event_handler_ = NULL;
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    handler->OnDisconnect();
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
1128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace remoting
115