blob: 45dfb8419f4e5f167c046a4699e3e8ee249bf6e7 [file] [log] [blame]
[email protected]64860882014-08-04 23:44:171// 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_channel_mojo.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/lazy_instance.h"
10#include "ipc/ipc_listener.h"
morrita7126b7a2014-12-17 19:01:4011#include "ipc/ipc_logging.h"
morrita4b5c28e22015-01-14 21:17:0612#include "ipc/ipc_message_attachment_set.h"
morrita7126b7a2014-12-17 19:01:4013#include "ipc/ipc_message_macros.h"
morritaf8f92dcd2014-10-27 20:10:2514#include "ipc/mojo/client_channel.mojom.h"
morrita54f6f80c2014-09-23 21:16:0015#include "ipc/mojo/ipc_mojo_bootstrap.h"
morrita81b17e02015-02-06 00:58:3016#include "ipc/mojo/ipc_mojo_handle_attachment.h"
blundell471b74f2015-01-23 16:27:1417#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
18#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
[email protected]64860882014-08-04 23:44:1719
morrita1aa788c2015-01-31 05:45:4220#if defined(OS_POSIX) && !defined(OS_NACL)
21#include "ipc/ipc_platform_file_attachment_posix.h"
22#endif
23
[email protected]64860882014-08-04 23:44:1724namespace IPC {
25
26namespace {
27
[email protected]64860882014-08-04 23:44:1728class MojoChannelFactory : public ChannelFactory {
29 public:
morritae9453ea2014-09-26 03:20:4830 MojoChannelFactory(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:0031 ChannelHandle channel_handle,
32 Channel::Mode mode)
morritae9453ea2014-09-26 03:20:4833 : delegate_(delegate), channel_handle_(channel_handle), mode_(mode) {}
[email protected]64860882014-08-04 23:44:1734
dchengfe61fca2014-10-22 02:29:5235 std::string GetName() const override {
dchengf3076af2014-10-21 18:02:4236 return channel_handle_.name;
37 }
[email protected]64860882014-08-04 23:44:1738
dchengfe61fca2014-10-22 02:29:5239 scoped_ptr<Channel> BuildChannel(Listener* listener) override {
dchengecc340f2014-10-17 00:43:5440 return ChannelMojo::Create(delegate_, channel_handle_, mode_, listener);
[email protected]64860882014-08-04 23:44:1741 }
42
43 private:
morritae9453ea2014-09-26 03:20:4844 ChannelMojo::Delegate* delegate_;
[email protected]64860882014-08-04 23:44:1745 ChannelHandle channel_handle_;
46 Channel::Mode mode_;
[email protected]64860882014-08-04 23:44:1747};
48
morritaf8f92dcd2014-10-27 20:10:2549//------------------------------------------------------------------------------
50
51class ClientChannelMojo
52 : public ChannelMojo,
53 public NON_EXPORTED_BASE(mojo::InterfaceImpl<ClientChannel>) {
54 public:
55 ClientChannelMojo(ChannelMojo::Delegate* delegate,
56 const ChannelHandle& handle,
57 Listener* listener);
58 ~ClientChannelMojo() override;
59 // MojoBootstrap::Delegate implementation
60 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
61 // InterfaceImpl implementation
62 void OnConnectionError() override;
63 // ClientChannel implementation
64 void Init(
65 mojo::ScopedMessagePipeHandle pipe,
66 int32_t peer_pid,
67 const mojo::Callback<void(int32_t)>& callback) override;
68
69 DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo);
70};
71
72ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate* delegate,
73 const ChannelHandle& handle,
74 Listener* listener)
75 : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener) {
76}
77
78ClientChannelMojo::~ClientChannelMojo() {
79}
80
81void ClientChannelMojo::OnPipeAvailable(
82 mojo::embedder::ScopedPlatformHandle handle) {
83 mojo::WeakBindToPipe(this, CreateMessagingPipe(handle.Pass()));
84}
85
86void ClientChannelMojo::OnConnectionError() {
87 listener()->OnChannelError();
88}
89
90void ClientChannelMojo::Init(
91 mojo::ScopedMessagePipeHandle pipe,
92 int32_t peer_pid,
93 const mojo::Callback<void(int32_t)>& callback) {
94 InitMessageReader(pipe.Pass(), static_cast<base::ProcessId>(peer_pid));
95 callback.Run(GetSelfPID());
96}
97
98//------------------------------------------------------------------------------
99
100class ServerChannelMojo : public ChannelMojo, public mojo::ErrorHandler {
101 public:
102 ServerChannelMojo(ChannelMojo::Delegate* delegate,
103 const ChannelHandle& handle,
104 Listener* listener);
105 ~ServerChannelMojo() override;
106
107 // MojoBootstrap::Delegate implementation
108 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
109 // ErrorHandler implementation
110 void OnConnectionError() override;
111 // Channel override
112 void Close() override;
113
114 private:
115 // ClientChannelClient implementation
116 void ClientChannelWasInitialized(int32_t peer_pid);
117
118 mojo::InterfacePtr<ClientChannel> client_channel_;
119 mojo::ScopedMessagePipeHandle message_pipe_;
120
121 DISALLOW_COPY_AND_ASSIGN(ServerChannelMojo);
122};
123
124ServerChannelMojo::ServerChannelMojo(ChannelMojo::Delegate* delegate,
125 const ChannelHandle& handle,
126 Listener* listener)
127 : ChannelMojo(delegate, handle, Channel::MODE_SERVER, listener) {
128}
129
130ServerChannelMojo::~ServerChannelMojo() {
131 Close();
132}
133
134void ServerChannelMojo::OnPipeAvailable(
135 mojo::embedder::ScopedPlatformHandle handle) {
136 mojo::ScopedMessagePipeHandle peer;
137 MojoResult create_result =
138 mojo::CreateMessagePipe(nullptr, &message_pipe_, &peer);
139 if (create_result != MOJO_RESULT_OK) {
140 DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result;
141 listener()->OnChannelError();
142 return;
143 }
144
145 client_channel_.Bind(CreateMessagingPipe(handle.Pass()));
146 client_channel_.set_error_handler(this);
147 client_channel_->Init(
148 peer.Pass(),
149 static_cast<int32_t>(GetSelfPID()),
150 base::Bind(&ServerChannelMojo::ClientChannelWasInitialized,
151 base::Unretained(this)));
152}
153
154void ServerChannelMojo::ClientChannelWasInitialized(int32_t peer_pid) {
155 InitMessageReader(message_pipe_.Pass(), peer_pid);
156}
157
158void ServerChannelMojo::OnConnectionError() {
159 listener()->OnChannelError();
160}
161
162void ServerChannelMojo::Close() {
163 client_channel_.reset();
164 message_pipe_.reset();
165 ChannelMojo::Close();
166}
167
morrita98ac98f2015-02-25 02:55:04168#if defined(OS_POSIX) && !defined(OS_NACL)
169
170base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
171 return attachment->Owns() ? base::ScopedFD(attachment->TakePlatformFile())
172 : base::ScopedFD(dup(attachment->file()));
173}
174
175#endif
176
[email protected]64860882014-08-04 23:44:17177} // namespace
178
179//------------------------------------------------------------------------------
180
[email protected]64860882014-08-04 23:44:17181void ChannelMojo::ChannelInfoDeleter::operator()(
182 mojo::embedder::ChannelInfo* ptr) const {
jamesra9125262014-11-19 01:35:28183 mojo::embedder::DestroyChannel(ptr);
[email protected]64860882014-08-04 23:44:17184}
185
186//------------------------------------------------------------------------------
187
188// static
morrita49ca46d2014-10-21 01:16:35189bool ChannelMojo::ShouldBeUsed() {
morrita599be602015-01-27 18:56:47190 // TODO(morrita): Remove this if it sticks.
191 return true;
morrita49ca46d2014-10-21 01:16:35192}
193
194// static
morritae9453ea2014-09-26 03:20:48195scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00196 const ChannelHandle& channel_handle,
197 Mode mode,
198 Listener* listener) {
morritaf8f92dcd2014-10-27 20:10:25199 switch (mode) {
200 case Channel::MODE_CLIENT:
201 return make_scoped_ptr(
202 new ClientChannelMojo(delegate, channel_handle, listener));
203 case Channel::MODE_SERVER:
204 return make_scoped_ptr(
205 new ServerChannelMojo(delegate, channel_handle, listener));
206 default:
207 NOTREACHED();
208 return nullptr;
209 }
[email protected]64860882014-08-04 23:44:17210}
211
212// static
morrita54f6f80c2014-09-23 21:16:00213scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
morritae9453ea2014-09-26 03:20:48214 ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00215 const ChannelHandle& channel_handle) {
dchengecc340f2014-10-17 00:43:54216 return make_scoped_ptr(
217 new MojoChannelFactory(delegate, channel_handle, Channel::MODE_SERVER));
[email protected]64860882014-08-04 23:44:17218}
219
morrita54f6f80c2014-09-23 21:16:00220// static
221scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
222 const ChannelHandle& channel_handle) {
223 return make_scoped_ptr(
dchengecc340f2014-10-17 00:43:54224 new MojoChannelFactory(NULL, channel_handle, Channel::MODE_CLIENT));
morrita54f6f80c2014-09-23 21:16:00225}
226
morritae9453ea2014-09-26 03:20:48227ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00228 const ChannelHandle& handle,
morrita3b41d6c2014-09-11 19:06:29229 Mode mode,
morrita54f6f80c2014-09-23 21:16:00230 Listener* listener)
morritae9453ea2014-09-26 03:20:48231 : mode_(mode),
morrita3b41d6c2014-09-11 19:06:29232 listener_(listener),
anujk.sharma0184ced2014-08-28 06:49:02233 peer_pid_(base::kNullProcessId),
234 weak_factory_(this) {
morrita54f6f80c2014-09-23 21:16:00235 // Create MojoBootstrap after all members are set as it touches
236 // ChannelMojo from a different thread.
237 bootstrap_ = MojoBootstrap::Create(handle, mode, this);
morritae9453ea2014-09-26 03:20:48238 if (delegate) {
239 if (delegate->GetIOTaskRunner() ==
240 base::MessageLoop::current()->message_loop_proxy()) {
241 InitDelegate(delegate);
242 } else {
243 delegate->GetIOTaskRunner()->PostTask(
244 FROM_HERE,
245 base::Bind(
246 &ChannelMojo::InitDelegate, base::Unretained(this), delegate));
247 }
248 }
[email protected]64860882014-08-04 23:44:17249}
250
251ChannelMojo::~ChannelMojo() {
252 Close();
morritae9453ea2014-09-26 03:20:48253}
morrita54f6f80c2014-09-23 21:16:00254
morritae9453ea2014-09-26 03:20:48255void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) {
256 delegate_ = delegate->ToWeakPtr();
257 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr());
[email protected]64860882014-08-04 23:44:17258}
259
morritaf8f92dcd2014-10-27 20:10:25260mojo::ScopedMessagePipeHandle ChannelMojo::CreateMessagingPipe(
morrita54f6f80c2014-09-23 21:16:00261 mojo::embedder::ScopedPlatformHandle handle) {
morritaf8f92dcd2014-10-27 20:10:25262 DCHECK(!channel_info_.get());
[email protected]efbf95d2014-08-12 21:44:01263 mojo::embedder::ChannelInfo* channel_info;
morritaf8f92dcd2014-10-27 20:10:25264 mojo::ScopedMessagePipeHandle pipe =
morrita54f6f80c2014-09-23 21:16:00265 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info);
[email protected]efbf95d2014-08-12 21:44:01266 channel_info_.reset(channel_info);
morritaf8f92dcd2014-10-27 20:10:25267 return pipe.Pass();
[email protected]64860882014-08-04 23:44:17268}
269
270bool ChannelMojo::Connect() {
271 DCHECK(!message_reader_);
morrita54f6f80c2014-09-23 21:16:00272 return bootstrap_->Connect();
[email protected]64860882014-08-04 23:44:17273}
274
275void ChannelMojo::Close() {
[email protected]64860882014-08-04 23:44:17276 message_reader_.reset();
277 channel_info_.reset();
278}
279
morrita54f6f80c2014-09-23 21:16:00280void ChannelMojo::OnBootstrapError() {
281 listener_->OnChannelError();
282}
283
morritaf8f92dcd2014-10-27 20:10:25284void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe,
285 int32_t peer_pid) {
morrita3b41d6c2014-09-11 19:06:29286 message_reader_ =
morritad68bedf42014-11-25 23:35:57287 make_scoped_ptr(new internal::MessagePipeReader(pipe.Pass(), this));
[email protected]64860882014-08-04 23:44:17288
289 for (size_t i = 0; i < pending_messages_.size(); ++i) {
morrita0a24cfc92014-09-16 03:20:48290 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i]));
[email protected]64860882014-08-04 23:44:17291 pending_messages_[i] = NULL;
morrita0a24cfc92014-09-16 03:20:48292 if (!sent) {
293 pending_messages_.clear();
294 listener_->OnChannelError();
295 return;
296 }
[email protected]64860882014-08-04 23:44:17297 }
298
299 pending_messages_.clear();
300
morritaf8f92dcd2014-10-27 20:10:25301 set_peer_pid(peer_pid);
302 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
morritadcc28ab2015-01-10 01:49:21303 if (message_reader_)
304 message_reader_->ReadMessagesThenWait();
[email protected]64860882014-08-04 23:44:17305}
306
307void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
308 Close();
309}
310
311void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
312 listener_->OnChannelError();
313}
314
315
316bool ChannelMojo::Send(Message* message) {
317 if (!message_reader_) {
318 pending_messages_.push_back(message);
319 return true;
320 }
321
322 return message_reader_->Send(make_scoped_ptr(message));
323}
324
325base::ProcessId ChannelMojo::GetPeerPID() const {
326 return peer_pid_;
327}
328
329base::ProcessId ChannelMojo::GetSelfPID() const {
morrita54f6f80c2014-09-23 21:16:00330 return base::GetCurrentProcId();
[email protected]64860882014-08-04 23:44:17331}
332
morrita54f6f80c2014-09-23 21:16:00333void ChannelMojo::OnClientLaunched(base::ProcessHandle handle) {
334 bootstrap_->OnClientLaunched(handle);
[email protected]64860882014-08-04 23:44:17335}
336
[email protected]64860882014-08-04 23:44:17337void ChannelMojo::OnMessageReceived(Message& message) {
morrita7126b7a2014-12-17 19:01:40338 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived",
339 "class", IPC_MESSAGE_ID_CLASS(message.type()),
340 "line", IPC_MESSAGE_ID_LINE(message.type()));
[email protected]64860882014-08-04 23:44:17341 listener_->OnMessageReceived(message);
342 if (message.dispatch_error())
343 listener_->OnBadMessageReceived(message);
344}
345
346#if defined(OS_POSIX) && !defined(OS_NACL)
347int ChannelMojo::GetClientFileDescriptor() const {
348 return bootstrap_->GetClientFileDescriptor();
349}
350
morritaa409ccc2014-10-20 23:53:25351base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
[email protected]64860882014-08-04 23:44:17352 return bootstrap_->TakeClientFileDescriptor();
353}
morrita81b17e02015-02-06 00:58:30354#endif // defined(OS_POSIX) && !defined(OS_NACL)
morrita3b41d6c2014-09-11 19:06:29355
356// static
morrita4b5c28e22015-01-14 21:17:06357MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
morrita96693852014-09-24 20:11:45358 Message* message,
morrita3b41d6c2014-09-11 19:06:29359 std::vector<MojoHandle>* handles) {
360 // We dup() the handles in IPC::Message to transmit.
morrita4b5c28e22015-01-14 21:17:06361 // IPC::MessageAttachmentSet has intricate lifecycle semantics
morrita3b41d6c2014-09-11 19:06:29362 // of FDs, so just to dup()-and-own them is the safest option.
morrita1aa788c2015-01-31 05:45:42363 if (message->HasAttachments()) {
morrita81b17e02015-02-06 00:58:30364 MessageAttachmentSet* set = message->attachment_set();
365 for (unsigned i = 0; i < set->size(); ++i) {
366 scoped_refptr<MessageAttachment> attachment = set->GetAttachmentAt(i);
367 switch (attachment->GetType()) {
368 case MessageAttachment::TYPE_PLATFORM_FILE:
369#if defined(OS_POSIX) && !defined(OS_NACL)
370 {
morrita98ac98f2015-02-25 02:55:04371 base::ScopedFD file =
372 TakeOrDupFile(static_cast<IPC::internal::PlatformFileAttachment*>(
373 attachment.get()));
374 if (!file.is_valid()) {
morrita81b17e02015-02-06 00:58:30375 DPLOG(WARNING) << "Failed to dup FD to transmit.";
376 set->CommitAll();
377 return MOJO_RESULT_UNKNOWN;
378 }
morrita3b41d6c2014-09-11 19:06:29379
morrita81b17e02015-02-06 00:58:30380 MojoHandle wrapped_handle;
381 MojoResult wrap_result = CreatePlatformHandleWrapper(
382 mojo::embedder::ScopedPlatformHandle(
morrita98ac98f2015-02-25 02:55:04383 mojo::embedder::PlatformHandle(file.release())),
morrita81b17e02015-02-06 00:58:30384 &wrapped_handle);
385 if (MOJO_RESULT_OK != wrap_result) {
386 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: "
387 << wrap_result;
388 set->CommitAll();
389 return wrap_result;
390 }
morrita3b41d6c2014-09-11 19:06:29391
morrita81b17e02015-02-06 00:58:30392 handles->push_back(wrapped_handle);
393 }
394#else
395 NOTREACHED();
396#endif // defined(OS_POSIX) && !defined(OS_NACL)
397 break;
398 case MessageAttachment::TYPE_MOJO_HANDLE: {
399 mojo::ScopedHandle handle =
400 static_cast<IPC::internal::MojoHandleAttachment*>(
401 attachment.get())->TakeHandle();
402 handles->push_back(handle.release().value());
403 } break;
404 }
morrita3b41d6c2014-09-11 19:06:29405 }
morrita96693852014-09-24 20:11:45406
morrita81b17e02015-02-06 00:58:30407 set->CommitAll();
morrita3b41d6c2014-09-11 19:06:29408 }
409
410 return MOJO_RESULT_OK;
411}
412
morrita81b17e02015-02-06 00:58:30413// static
414MojoResult ChannelMojo::WriteToMessageAttachmentSet(
415 const std::vector<MojoHandle>& handle_buffer,
416 Message* message) {
417 for (size_t i = 0; i < handle_buffer.size(); ++i) {
418 bool ok = message->attachment_set()->AddAttachment(
419 new IPC::internal::MojoHandleAttachment(
420 mojo::MakeScopedHandle(mojo::Handle(handle_buffer[i]))));
421 DCHECK(ok);
422 if (!ok) {
423 DLOG(ERROR) << "Failed to add new Mojo handle.";
424 return MOJO_RESULT_UNKNOWN;
425 }
426 }
427
428 return MOJO_RESULT_OK;
429}
[email protected]64860882014-08-04 23:44:17430
431} // namespace IPC