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_channel_mojo.h"
8 #include "base/bind_helpers.h"
9 #include "base/lazy_instance.h"
10 #include "ipc/ipc_listener.h"
11 #include "ipc/ipc_logging.h"
12 #include "ipc/ipc_message_attachment_set.h"
13 #include "ipc/ipc_message_macros.h"
14 #include "ipc/mojo/client_channel.mojom.h"
15 #include "ipc/mojo/ipc_mojo_bootstrap.h"
16 #include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
17 #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
19 #if defined(OS_POSIX) && !defined(OS_NACL)
20 #include "ipc/ipc_platform_file_attachment_posix.h"
27 class MojoChannelFactory
: public ChannelFactory
{
29 MojoChannelFactory(ChannelMojo::Delegate
* delegate
,
30 ChannelHandle channel_handle
,
32 : delegate_(delegate
), channel_handle_(channel_handle
), mode_(mode
) {}
34 std::string
GetName() const override
{
35 return channel_handle_
.name
;
38 scoped_ptr
<Channel
> BuildChannel(Listener
* listener
) override
{
39 return ChannelMojo::Create(delegate_
, channel_handle_
, mode_
, listener
);
43 ChannelMojo::Delegate
* delegate_
;
44 ChannelHandle channel_handle_
;
48 //------------------------------------------------------------------------------
50 class ClientChannelMojo
52 public NON_EXPORTED_BASE(mojo::InterfaceImpl
<ClientChannel
>) {
54 ClientChannelMojo(ChannelMojo::Delegate
* delegate
,
55 const ChannelHandle
& handle
,
57 ~ClientChannelMojo() override
;
58 // MojoBootstrap::Delegate implementation
59 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle
) override
;
60 // InterfaceImpl implementation
61 void OnConnectionError() override
;
62 // ClientChannel implementation
64 mojo::ScopedMessagePipeHandle pipe
,
66 const mojo::Callback
<void(int32_t)>& callback
) override
;
68 DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo
);
71 ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate
* delegate
,
72 const ChannelHandle
& handle
,
74 : ChannelMojo(delegate
, handle
, Channel::MODE_CLIENT
, listener
) {
77 ClientChannelMojo::~ClientChannelMojo() {
80 void ClientChannelMojo::OnPipeAvailable(
81 mojo::embedder::ScopedPlatformHandle handle
) {
82 mojo::WeakBindToPipe(this, CreateMessagingPipe(handle
.Pass()));
85 void ClientChannelMojo::OnConnectionError() {
86 listener()->OnChannelError();
89 void ClientChannelMojo::Init(
90 mojo::ScopedMessagePipeHandle pipe
,
92 const mojo::Callback
<void(int32_t)>& callback
) {
93 InitMessageReader(pipe
.Pass(), static_cast<base::ProcessId
>(peer_pid
));
94 callback
.Run(GetSelfPID());
97 //------------------------------------------------------------------------------
99 class ServerChannelMojo
: public ChannelMojo
, public mojo::ErrorHandler
{
101 ServerChannelMojo(ChannelMojo::Delegate
* delegate
,
102 const ChannelHandle
& handle
,
104 ~ServerChannelMojo() override
;
106 // MojoBootstrap::Delegate implementation
107 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle
) override
;
108 // ErrorHandler implementation
109 void OnConnectionError() override
;
111 void Close() override
;
114 // ClientChannelClient implementation
115 void ClientChannelWasInitialized(int32_t peer_pid
);
117 mojo::InterfacePtr
<ClientChannel
> client_channel_
;
118 mojo::ScopedMessagePipeHandle message_pipe_
;
120 DISALLOW_COPY_AND_ASSIGN(ServerChannelMojo
);
123 ServerChannelMojo::ServerChannelMojo(ChannelMojo::Delegate
* delegate
,
124 const ChannelHandle
& handle
,
126 : ChannelMojo(delegate
, handle
, Channel::MODE_SERVER
, listener
) {
129 ServerChannelMojo::~ServerChannelMojo() {
133 void ServerChannelMojo::OnPipeAvailable(
134 mojo::embedder::ScopedPlatformHandle handle
) {
135 mojo::ScopedMessagePipeHandle peer
;
136 MojoResult create_result
=
137 mojo::CreateMessagePipe(nullptr, &message_pipe_
, &peer
);
138 if (create_result
!= MOJO_RESULT_OK
) {
139 DLOG(WARNING
) << "mojo::CreateMessagePipe failed: " << create_result
;
140 listener()->OnChannelError();
144 client_channel_
.Bind(CreateMessagingPipe(handle
.Pass()));
145 client_channel_
.set_error_handler(this);
146 client_channel_
->Init(
148 static_cast<int32_t>(GetSelfPID()),
149 base::Bind(&ServerChannelMojo::ClientChannelWasInitialized
,
150 base::Unretained(this)));
153 void ServerChannelMojo::ClientChannelWasInitialized(int32_t peer_pid
) {
154 InitMessageReader(message_pipe_
.Pass(), peer_pid
);
157 void ServerChannelMojo::OnConnectionError() {
158 listener()->OnChannelError();
161 void ServerChannelMojo::Close() {
162 client_channel_
.reset();
163 message_pipe_
.reset();
164 ChannelMojo::Close();
169 //------------------------------------------------------------------------------
171 void ChannelMojo::ChannelInfoDeleter::operator()(
172 mojo::embedder::ChannelInfo
* ptr
) const {
173 mojo::embedder::DestroyChannel(ptr
);
176 //------------------------------------------------------------------------------
179 bool ChannelMojo::ShouldBeUsed() {
180 // TODO(morrita): Remove this if it sticks.
185 scoped_ptr
<ChannelMojo
> ChannelMojo::Create(ChannelMojo::Delegate
* delegate
,
186 const ChannelHandle
& channel_handle
,
188 Listener
* listener
) {
190 case Channel::MODE_CLIENT
:
191 return make_scoped_ptr(
192 new ClientChannelMojo(delegate
, channel_handle
, listener
));
193 case Channel::MODE_SERVER
:
194 return make_scoped_ptr(
195 new ServerChannelMojo(delegate
, channel_handle
, listener
));
203 scoped_ptr
<ChannelFactory
> ChannelMojo::CreateServerFactory(
204 ChannelMojo::Delegate
* delegate
,
205 const ChannelHandle
& channel_handle
) {
206 return make_scoped_ptr(
207 new MojoChannelFactory(delegate
, channel_handle
, Channel::MODE_SERVER
));
211 scoped_ptr
<ChannelFactory
> ChannelMojo::CreateClientFactory(
212 const ChannelHandle
& channel_handle
) {
213 return make_scoped_ptr(
214 new MojoChannelFactory(NULL
, channel_handle
, Channel::MODE_CLIENT
));
217 ChannelMojo::ChannelMojo(ChannelMojo::Delegate
* delegate
,
218 const ChannelHandle
& handle
,
223 peer_pid_(base::kNullProcessId
),
224 weak_factory_(this) {
225 // Create MojoBootstrap after all members are set as it touches
226 // ChannelMojo from a different thread.
227 bootstrap_
= MojoBootstrap::Create(handle
, mode
, this);
229 if (delegate
->GetIOTaskRunner() ==
230 base::MessageLoop::current()->message_loop_proxy()) {
231 InitDelegate(delegate
);
233 delegate
->GetIOTaskRunner()->PostTask(
236 &ChannelMojo::InitDelegate
, base::Unretained(this), delegate
));
241 ChannelMojo::~ChannelMojo() {
245 void ChannelMojo::InitDelegate(ChannelMojo::Delegate
* delegate
) {
246 delegate_
= delegate
->ToWeakPtr();
247 delegate_
->OnChannelCreated(weak_factory_
.GetWeakPtr());
250 mojo::ScopedMessagePipeHandle
ChannelMojo::CreateMessagingPipe(
251 mojo::embedder::ScopedPlatformHandle handle
) {
252 DCHECK(!channel_info_
.get());
253 mojo::embedder::ChannelInfo
* channel_info
;
254 mojo::ScopedMessagePipeHandle pipe
=
255 mojo::embedder::CreateChannelOnIOThread(handle
.Pass(), &channel_info
);
256 channel_info_
.reset(channel_info
);
260 bool ChannelMojo::Connect() {
261 DCHECK(!message_reader_
);
262 return bootstrap_
->Connect();
265 void ChannelMojo::Close() {
266 message_reader_
.reset();
267 channel_info_
.reset();
270 void ChannelMojo::OnBootstrapError() {
271 listener_
->OnChannelError();
274 void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe
,
277 make_scoped_ptr(new internal::MessagePipeReader(pipe
.Pass(), this));
279 for (size_t i
= 0; i
< pending_messages_
.size(); ++i
) {
280 bool sent
= message_reader_
->Send(make_scoped_ptr(pending_messages_
[i
]));
281 pending_messages_
[i
] = NULL
;
283 pending_messages_
.clear();
284 listener_
->OnChannelError();
289 pending_messages_
.clear();
291 set_peer_pid(peer_pid
);
292 listener_
->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
294 message_reader_
->ReadMessagesThenWait();
297 void ChannelMojo::OnPipeClosed(internal::MessagePipeReader
* reader
) {
301 void ChannelMojo::OnPipeError(internal::MessagePipeReader
* reader
) {
302 listener_
->OnChannelError();
306 bool ChannelMojo::Send(Message
* message
) {
307 if (!message_reader_
) {
308 pending_messages_
.push_back(message
);
312 return message_reader_
->Send(make_scoped_ptr(message
));
315 base::ProcessId
ChannelMojo::GetPeerPID() const {
319 base::ProcessId
ChannelMojo::GetSelfPID() const {
320 return base::GetCurrentProcId();
323 void ChannelMojo::OnClientLaunched(base::ProcessHandle handle
) {
324 bootstrap_
->OnClientLaunched(handle
);
327 void ChannelMojo::OnMessageReceived(Message
& message
) {
328 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived",
329 "class", IPC_MESSAGE_ID_CLASS(message
.type()),
330 "line", IPC_MESSAGE_ID_LINE(message
.type()));
331 listener_
->OnMessageReceived(message
);
332 if (message
.dispatch_error())
333 listener_
->OnBadMessageReceived(message
);
336 #if defined(OS_POSIX) && !defined(OS_NACL)
337 int ChannelMojo::GetClientFileDescriptor() const {
338 return bootstrap_
->GetClientFileDescriptor();
341 base::ScopedFD
ChannelMojo::TakeClientFileDescriptor() {
342 return bootstrap_
->TakeClientFileDescriptor();
346 MojoResult
ChannelMojo::WriteToMessageAttachmentSet(
347 const std::vector
<MojoHandle
>& handle_buffer
,
349 for (size_t i
= 0; i
< handle_buffer
.size(); ++i
) {
350 mojo::embedder::ScopedPlatformHandle platform_handle
;
351 MojoResult unwrap_result
= mojo::embedder::PassWrappedPlatformHandle(
352 handle_buffer
[i
], &platform_handle
);
353 if (unwrap_result
!= MOJO_RESULT_OK
) {
354 DLOG(WARNING
) << "Pipe failed to covert handles. Closing: "
356 return unwrap_result
;
359 bool ok
= message
->attachment_set()->AddAttachment(
360 new internal::PlatformFileAttachment(
361 base::ScopedFD(platform_handle
.release().fd
)));
365 return MOJO_RESULT_OK
;
369 MojoResult
ChannelMojo::ReadFromMessageAttachmentSet(
371 std::vector
<MojoHandle
>* handles
) {
372 // We dup() the handles in IPC::Message to transmit.
373 // IPC::MessageAttachmentSet has intricate lifecycle semantics
374 // of FDs, so just to dup()-and-own them is the safest option.
375 if (message
->HasAttachments()) {
376 MessageAttachmentSet
* fdset
= message
->attachment_set();
377 std::vector
<base::PlatformFile
> fds_to_send(fdset
->size());
378 fdset
->PeekDescriptors(&fds_to_send
[0]);
379 for (size_t i
= 0; i
< fds_to_send
.size(); ++i
) {
380 int fd_to_send
= dup(fds_to_send
[i
]);
381 if (-1 == fd_to_send
) {
382 DPLOG(WARNING
) << "Failed to dup FD to transmit.";
384 return MOJO_RESULT_UNKNOWN
;
387 MojoHandle wrapped_handle
;
388 MojoResult wrap_result
= CreatePlatformHandleWrapper(
389 mojo::embedder::ScopedPlatformHandle(
390 mojo::embedder::PlatformHandle(fd_to_send
)),
392 if (MOJO_RESULT_OK
!= wrap_result
) {
393 DLOG(WARNING
) << "Pipe failed to wrap handles. Closing: "
399 handles
->push_back(wrapped_handle
);
405 return MOJO_RESULT_OK
;
408 #endif // defined(OS_POSIX) && !defined(OS_NACL)