blob: b668a7bcac2b6d9448757ba6a93c02146d7fe7aa [file] [log] [blame]
morrita54f6f80c2014-09-23 21:16:001// Copyright 2014 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 "ipc/mojo/ipc_mojo_bootstrap.h"
6
tfarina10a5c062015-09-04 18:47:577#include <stdint.h>
8
morrita54f6f80c2014-09-23 21:16:009#include "base/logging.h"
10#include "base/process/process_handle.h"
11#include "ipc/ipc_message_utils.h"
12#include "ipc/ipc_platform_file.h"
blundell471b74f2015-01-23 16:27:1413#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
morrita54f6f80c2014-09-23 21:16:0014
15namespace IPC {
16
17namespace {
18
19// MojoBootstrap for the server process. You should create the instance
20// using MojoBootstrap::Create().
hans573743f2014-10-15 18:14:3421class MojoServerBootstrap : public MojoBootstrap {
morrita54f6f80c2014-09-23 21:16:0022 public:
23 MojoServerBootstrap();
24
morrita54f6f80c2014-09-23 21:16:0025 private:
tfarina10a5c062015-09-04 18:47:5726 void SendClientPipe(int32_t peer_pid);
morrita54f6f80c2014-09-23 21:16:0027
28 // Listener implementations
dchengfe61fca2014-10-22 02:29:5229 bool OnMessageReceived(const Message& message) override;
tfarina10a5c062015-09-04 18:47:5730 void OnChannelConnected(int32_t peer_pid) override;
morrita54f6f80c2014-09-23 21:16:0031
32 mojo::embedder::ScopedPlatformHandle server_pipe_;
morrita54f6f80c2014-09-23 21:16:0033 bool connected_;
jam76bcf0c2015-10-02 21:01:2834 int32_t peer_pid_;
morrita54f6f80c2014-09-23 21:16:0035
36 DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap);
37};
38
jam76bcf0c2015-10-02 21:01:2839MojoServerBootstrap::MojoServerBootstrap() : connected_(false), peer_pid_(0) {
morrita54f6f80c2014-09-23 21:16:0040}
41
tfarina10a5c062015-09-04 18:47:5742void MojoServerBootstrap::SendClientPipe(int32_t peer_pid) {
morrita54f6f80c2014-09-23 21:16:0043 DCHECK_EQ(state(), STATE_INITIALIZED);
morrita54f6f80c2014-09-23 21:16:0044 DCHECK(connected_);
45
46 mojo::embedder::PlatformChannelPair channel_pair;
47 server_pipe_ = channel_pair.PassServerHandle();
leon.hand20a6c4c2015-06-19 02:25:4848
49 base::Process peer_process =
50#if defined(OS_WIN)
51 base::Process::OpenWithAccess(peer_pid, PROCESS_DUP_HANDLE);
52#else
53 base::Process::Open(peer_pid);
54#endif
morrita54f6f80c2014-09-23 21:16:0055 PlatformFileForTransit client_pipe = GetFileHandleForProcess(
56#if defined(OS_POSIX)
57 channel_pair.PassClientHandle().release().fd,
58#else
59 channel_pair.PassClientHandle().release().handle,
60#endif
leon.hand20a6c4c2015-06-19 02:25:4861 peer_process.Handle(), true);
morrita25803672014-10-15 18:50:1962 if (client_pipe == IPC::InvalidPlatformFileForTransit()) {
63#if !defined(OS_WIN)
64 // GetFileHandleForProcess() only fails on Windows.
65 NOTREACHED();
66#endif
morritaa3889aa2015-03-16 22:40:5167 LOG(WARNING) << "Failed to translate file handle for client process.";
morrita25803672014-10-15 18:50:1968 Fail();
69 return;
70 }
71
morrita54f6f80c2014-09-23 21:16:0072 scoped_ptr<Message> message(new Message());
73 ParamTraits<PlatformFileForTransit>::Write(message.get(), client_pipe);
74 Send(message.release());
75
76 set_state(STATE_WAITING_ACK);
77}
78
tfarina10a5c062015-09-04 18:47:5779void MojoServerBootstrap::OnChannelConnected(int32_t peer_pid) {
morrita54f6f80c2014-09-23 21:16:0080 DCHECK_EQ(state(), STATE_INITIALIZED);
81 connected_ = true;
jam76bcf0c2015-10-02 21:01:2882 peer_pid_ = peer_pid;
leon.hand20a6c4c2015-06-19 02:25:4883 SendClientPipe(peer_pid);
morrita54f6f80c2014-09-23 21:16:0084}
85
86bool MojoServerBootstrap::OnMessageReceived(const Message&) {
inferno1f289ac2015-01-29 20:47:5187 if (state() != STATE_WAITING_ACK) {
88 set_state(STATE_ERROR);
89 LOG(ERROR) << "Got inconsistent message from client.";
90 return false;
91 }
inferno726621f2015-01-29 20:37:1292
inferno1f289ac2015-01-29 20:47:5193 set_state(STATE_READY);
94 CHECK(server_pipe_.is_valid());
morrita54f6f80c2014-09-23 21:16:0095 delegate()->OnPipeAvailable(
jam76bcf0c2015-10-02 21:01:2896 mojo::embedder::ScopedPlatformHandle(server_pipe_.release()), peer_pid_);
morrita54f6f80c2014-09-23 21:16:0097
98 return true;
99}
100
101// MojoBootstrap for client processes. You should create the instance
102// using MojoBootstrap::Create().
hans573743f2014-10-15 18:14:34103class MojoClientBootstrap : public MojoBootstrap {
morrita54f6f80c2014-09-23 21:16:00104 public:
105 MojoClientBootstrap();
106
morrita54f6f80c2014-09-23 21:16:00107 private:
108 // Listener implementations
dchengfe61fca2014-10-22 02:29:52109 bool OnMessageReceived(const Message& message) override;
tfarina10a5c062015-09-04 18:47:57110 void OnChannelConnected(int32_t peer_pid) override;
morrita54f6f80c2014-09-23 21:16:00111
jam76bcf0c2015-10-02 21:01:28112 int32 peer_pid_;
113
morrita54f6f80c2014-09-23 21:16:00114 DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap);
115};
116
jam76bcf0c2015-10-02 21:01:28117MojoClientBootstrap::MojoClientBootstrap() : peer_pid_(0) {
morrita54f6f80c2014-09-23 21:16:00118}
119
120bool MojoClientBootstrap::OnMessageReceived(const Message& message) {
inferno1f289ac2015-01-29 20:47:51121 if (state() != STATE_INITIALIZED) {
122 set_state(STATE_ERROR);
123 LOG(ERROR) << "Got inconsistent message from server.";
124 return false;
125 }
126
morrita54f6f80c2014-09-23 21:16:00127 PlatformFileForTransit pipe;
brettwbd4d7112015-06-03 04:29:25128 base::PickleIterator iter(message);
morrita54f6f80c2014-09-23 21:16:00129 if (!ParamTraits<PlatformFileForTransit>::Read(&message, &iter, &pipe)) {
morritaa3889aa2015-03-16 22:40:51130 LOG(WARNING) << "Failed to read a file handle from bootstrap channel.";
morrita54f6f80c2014-09-23 21:16:00131 message.set_dispatch_error();
132 return false;
133 }
134
135 // Sends ACK back.
136 Send(new Message());
137 set_state(STATE_READY);
138 delegate()->OnPipeAvailable(
139 mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle(
jam76bcf0c2015-10-02 21:01:28140 PlatformFileForTransitToPlatformFile(pipe))), peer_pid_);
morrita54f6f80c2014-09-23 21:16:00141
142 return true;
143}
144
tfarina10a5c062015-09-04 18:47:57145void MojoClientBootstrap::OnChannelConnected(int32_t peer_pid) {
jam76bcf0c2015-10-02 21:01:28146 peer_pid_ = peer_pid;
morrita54f6f80c2014-09-23 21:16:00147}
148
149} // namespace
150
151// MojoBootstrap
152
153// static
154scoped_ptr<MojoBootstrap> MojoBootstrap::Create(ChannelHandle handle,
155 Channel::Mode mode,
erikchen30dc2812015-09-24 03:26:38156 Delegate* delegate) {
morrita54f6f80c2014-09-23 21:16:00157 CHECK(mode == Channel::MODE_CLIENT || mode == Channel::MODE_SERVER);
158 scoped_ptr<MojoBootstrap> self =
159 mode == Channel::MODE_CLIENT
160 ? scoped_ptr<MojoBootstrap>(new MojoClientBootstrap())
161 : scoped_ptr<MojoBootstrap>(new MojoServerBootstrap());
erikchen27aa7d82015-06-16 21:21:04162
morrita54f6f80c2014-09-23 21:16:00163 scoped_ptr<Channel> bootstrap_channel =
erikchen30dc2812015-09-24 03:26:38164 Channel::Create(handle, mode, self.get());
morrita54f6f80c2014-09-23 21:16:00165 self->Init(bootstrap_channel.Pass(), delegate);
166 return self.Pass();
167}
168
169MojoBootstrap::MojoBootstrap() : delegate_(NULL), state_(STATE_INITIALIZED) {
170}
171
172MojoBootstrap::~MojoBootstrap() {
173}
174
175void MojoBootstrap::Init(scoped_ptr<Channel> channel, Delegate* delegate) {
176 channel_ = channel.Pass();
177 delegate_ = delegate;
178}
179
180bool MojoBootstrap::Connect() {
181 return channel_->Connect();
182}
183
morrita0bd20bd2015-02-25 20:11:27184base::ProcessId MojoBootstrap::GetSelfPID() const {
185 return channel_->GetSelfPID();
186}
187
morrita54f6f80c2014-09-23 21:16:00188void MojoBootstrap::OnBadMessageReceived(const Message& message) {
morrita25803672014-10-15 18:50:19189 Fail();
morrita54f6f80c2014-09-23 21:16:00190}
191
192void MojoBootstrap::OnChannelError() {
morrita25803672014-10-15 18:50:19193 if (state_ == STATE_READY || state_ == STATE_ERROR)
morrita54f6f80c2014-09-23 21:16:00194 return;
195 DLOG(WARNING) << "Detected error on Mojo bootstrap channel.";
morrita25803672014-10-15 18:50:19196 Fail();
197}
198
199void MojoBootstrap::Fail() {
200 set_state(STATE_ERROR);
morrita54f6f80c2014-09-23 21:16:00201 delegate()->OnBootstrapError();
202}
203
morrita0076bcf2014-10-22 00:59:23204bool MojoBootstrap::HasFailed() const {
205 return state() == STATE_ERROR;
206}
207
morrita54f6f80c2014-09-23 21:16:00208bool MojoBootstrap::Send(Message* message) {
209 return channel_->Send(message);
210}
211
212#if defined(OS_POSIX) && !defined(OS_NACL)
213int MojoBootstrap::GetClientFileDescriptor() const {
214 return channel_->GetClientFileDescriptor();
215}
216
morritaa409ccc2014-10-20 23:53:25217base::ScopedFD MojoBootstrap::TakeClientFileDescriptor() {
morrita54f6f80c2014-09-23 21:16:00218 return channel_->TakeClientFileDescriptor();
219}
220#endif // defined(OS_POSIX) && !defined(OS_NACL)
221
222} // namespace IPC