1 // 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.
5 #include "ipc/mojo/ipc_mojo_bootstrap.h"
9 #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"
13 #include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
19 // MojoBootstrap for the server process. You should create the instance
20 // using MojoBootstrap::Create().
21 class MojoServerBootstrap
: public MojoBootstrap
{
23 MojoServerBootstrap();
26 void SendClientPipe(int32_t peer_pid
);
28 // Listener implementations
29 bool OnMessageReceived(const Message
& message
) override
;
30 void OnChannelConnected(int32_t peer_pid
) override
;
32 mojo::embedder::ScopedPlatformHandle server_pipe_
;
35 DISALLOW_COPY_AND_ASSIGN(MojoServerBootstrap
);
38 MojoServerBootstrap::MojoServerBootstrap() : connected_(false) {
41 void MojoServerBootstrap::SendClientPipe(int32_t peer_pid
) {
42 DCHECK_EQ(state(), STATE_INITIALIZED
);
45 mojo::embedder::PlatformChannelPair channel_pair
;
46 server_pipe_
= channel_pair
.PassServerHandle();
48 base::Process peer_process
=
50 base::Process::OpenWithAccess(peer_pid
, PROCESS_DUP_HANDLE
);
52 base::Process::Open(peer_pid
);
54 PlatformFileForTransit client_pipe
= GetFileHandleForProcess(
56 channel_pair
.PassClientHandle().release().fd
,
58 channel_pair
.PassClientHandle().release().handle
,
60 peer_process
.Handle(), true);
61 if (client_pipe
== IPC::InvalidPlatformFileForTransit()) {
63 // GetFileHandleForProcess() only fails on Windows.
66 LOG(WARNING
) << "Failed to translate file handle for client process.";
71 scoped_ptr
<Message
> message(new Message());
72 ParamTraits
<PlatformFileForTransit
>::Write(message
.get(), client_pipe
);
73 Send(message
.release());
75 set_state(STATE_WAITING_ACK
);
78 void MojoServerBootstrap::OnChannelConnected(int32_t peer_pid
) {
79 DCHECK_EQ(state(), STATE_INITIALIZED
);
81 SendClientPipe(peer_pid
);
84 bool MojoServerBootstrap::OnMessageReceived(const Message
&) {
85 if (state() != STATE_WAITING_ACK
) {
86 set_state(STATE_ERROR
);
87 LOG(ERROR
) << "Got inconsistent message from client.";
91 set_state(STATE_READY
);
92 CHECK(server_pipe_
.is_valid());
93 delegate()->OnPipeAvailable(
94 mojo::embedder::ScopedPlatformHandle(server_pipe_
.release()));
99 // MojoBootstrap for client processes. You should create the instance
100 // using MojoBootstrap::Create().
101 class MojoClientBootstrap
: public MojoBootstrap
{
103 MojoClientBootstrap();
106 // Listener implementations
107 bool OnMessageReceived(const Message
& message
) override
;
108 void OnChannelConnected(int32_t peer_pid
) override
;
110 DISALLOW_COPY_AND_ASSIGN(MojoClientBootstrap
);
113 MojoClientBootstrap::MojoClientBootstrap() {
116 bool MojoClientBootstrap::OnMessageReceived(const Message
& message
) {
117 if (state() != STATE_INITIALIZED
) {
118 set_state(STATE_ERROR
);
119 LOG(ERROR
) << "Got inconsistent message from server.";
123 PlatformFileForTransit pipe
;
124 base::PickleIterator
iter(message
);
125 if (!ParamTraits
<PlatformFileForTransit
>::Read(&message
, &iter
, &pipe
)) {
126 LOG(WARNING
) << "Failed to read a file handle from bootstrap channel.";
127 message
.set_dispatch_error();
133 set_state(STATE_READY
);
134 delegate()->OnPipeAvailable(
135 mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle(
136 PlatformFileForTransitToPlatformFile(pipe
))));
141 void MojoClientBootstrap::OnChannelConnected(int32_t peer_pid
) {
149 scoped_ptr
<MojoBootstrap
> MojoBootstrap::Create(ChannelHandle handle
,
152 AttachmentBroker
* broker
) {
153 CHECK(mode
== Channel::MODE_CLIENT
|| mode
== Channel::MODE_SERVER
);
154 scoped_ptr
<MojoBootstrap
> self
=
155 mode
== Channel::MODE_CLIENT
156 ? scoped_ptr
<MojoBootstrap
>(new MojoClientBootstrap())
157 : scoped_ptr
<MojoBootstrap
>(new MojoServerBootstrap());
159 scoped_ptr
<Channel
> bootstrap_channel
=
160 Channel::Create(handle
, mode
, self
.get(), broker
);
161 self
->Init(bootstrap_channel
.Pass(), delegate
);
165 MojoBootstrap::MojoBootstrap() : delegate_(NULL
), state_(STATE_INITIALIZED
) {
168 MojoBootstrap::~MojoBootstrap() {
171 void MojoBootstrap::Init(scoped_ptr
<Channel
> channel
, Delegate
* delegate
) {
172 channel_
= channel
.Pass();
173 delegate_
= delegate
;
176 bool MojoBootstrap::Connect() {
177 return channel_
->Connect();
180 base::ProcessId
MojoBootstrap::GetSelfPID() const {
181 return channel_
->GetSelfPID();
184 void MojoBootstrap::OnBadMessageReceived(const Message
& message
) {
188 void MojoBootstrap::OnChannelError() {
189 if (state_
== STATE_READY
|| state_
== STATE_ERROR
)
191 DLOG(WARNING
) << "Detected error on Mojo bootstrap channel.";
195 void MojoBootstrap::Fail() {
196 set_state(STATE_ERROR
);
197 delegate()->OnBootstrapError();
200 bool MojoBootstrap::HasFailed() const {
201 return state() == STATE_ERROR
;
204 bool MojoBootstrap::Send(Message
* message
) {
205 return channel_
->Send(message
);
208 #if defined(OS_POSIX) && !defined(OS_NACL)
209 int MojoBootstrap::GetClientFileDescriptor() const {
210 return channel_
->GetClientFileDescriptor();
213 base::ScopedFD
MojoBootstrap::TakeClientFileDescriptor() {
214 return channel_
->TakeClientFileDescriptor();
216 #endif // defined(OS_POSIX) && !defined(OS_NACL)