1// Copyright (c) 2012 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 "ppapi/proxy/proxy_channel.h"
6
7#include "base/logging.h"
8#include "ipc/ipc_platform_file.h"
9#include "ipc/ipc_test_sink.h"
10
11#if defined(OS_NACL)
12#include <unistd.h>
13#endif
14
15namespace ppapi {
16namespace proxy {
17
18ProxyChannel::ProxyChannel()
19    : delegate_(NULL),
20      peer_pid_(base::kNullProcessId),
21      test_sink_(NULL) {
22}
23
24ProxyChannel::~ProxyChannel() {
25  DVLOG(1) << "ProxyChannel::~ProxyChannel()";
26}
27
28bool ProxyChannel::InitWithChannel(Delegate* delegate,
29                                   base::ProcessId peer_pid,
30                                   const IPC::ChannelHandle& channel_handle,
31                                   bool is_client) {
32  delegate_ = delegate;
33  peer_pid_ = peer_pid;
34  IPC::Channel::Mode mode = is_client
35      ? IPC::Channel::MODE_CLIENT
36      : IPC::Channel::MODE_SERVER;
37  channel_ = IPC::SyncChannel::Create(channel_handle, mode, this,
38                                      delegate->GetIPCMessageLoop(), true,
39                                      delegate->GetShutdownEvent());
40  return true;
41}
42
43void ProxyChannel::InitWithTestSink(IPC::TestSink* test_sink) {
44  DCHECK(!test_sink_);
45  test_sink_ = test_sink;
46#if !defined(OS_NACL)
47  peer_pid_ = base::GetCurrentProcId();
48#endif
49}
50
51void ProxyChannel::OnChannelError() {
52  channel_.reset();
53}
54
55#if defined(OS_POSIX) && !defined(OS_NACL)
56int ProxyChannel::TakeRendererFD() {
57  DCHECK(channel());
58  return channel()->TakeClientFileDescriptor();
59}
60#endif
61
62IPC::PlatformFileForTransit ProxyChannel::ShareHandleWithRemote(
63      base::PlatformFile handle,
64      bool should_close_source) {
65  // Channel could be closed if the plugin crashes.
66  if (!channel_.get()) {
67    if (should_close_source) {
68      base::File file_closer(handle);
69    }
70    return IPC::InvalidPlatformFileForTransit();
71  }
72  DCHECK(peer_pid_ != base::kNullProcessId);
73  return delegate_->ShareHandleWithRemote(handle, peer_pid_,
74                                          should_close_source);
75}
76
77bool ProxyChannel::Send(IPC::Message* msg) {
78  if (test_sink_)
79    return test_sink_->Send(msg);
80  if (channel_.get())
81    return channel_->Send(msg);
82
83  // Remote side crashed, drop this message.
84  delete msg;
85  return false;
86}
87
88}  // namespace proxy
89}  // namespace ppapi
90