blob: d2d7fe5b7bd84089bd821bd3b030ac282c88f6a1 [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"
blundell471b74f2015-01-23 16:27:1416#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
17#include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
[email protected]64860882014-08-04 23:44:1718
morrita1aa788c2015-01-31 05:45:4219#if defined(OS_POSIX) && !defined(OS_NACL)
20#include "ipc/ipc_platform_file_attachment_posix.h"
21#endif
22
[email protected]64860882014-08-04 23:44:1723namespace IPC {
24
25namespace {
26
[email protected]64860882014-08-04 23:44:1727class MojoChannelFactory : public ChannelFactory {
28 public:
morritae9453ea2014-09-26 03:20:4829 MojoChannelFactory(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:0030 ChannelHandle channel_handle,
31 Channel::Mode mode)
morritae9453ea2014-09-26 03:20:4832 : delegate_(delegate), channel_handle_(channel_handle), mode_(mode) {}
[email protected]64860882014-08-04 23:44:1733
dchengfe61fca2014-10-22 02:29:5234 std::string GetName() const override {
dchengf3076af2014-10-21 18:02:4235 return channel_handle_.name;
36 }
[email protected]64860882014-08-04 23:44:1737
dchengfe61fca2014-10-22 02:29:5238 scoped_ptr<Channel> BuildChannel(Listener* listener) override {
dchengecc340f2014-10-17 00:43:5439 return ChannelMojo::Create(delegate_, channel_handle_, mode_, listener);
[email protected]64860882014-08-04 23:44:1740 }
41
42 private:
morritae9453ea2014-09-26 03:20:4843 ChannelMojo::Delegate* delegate_;
[email protected]64860882014-08-04 23:44:1744 ChannelHandle channel_handle_;
45 Channel::Mode mode_;
[email protected]64860882014-08-04 23:44:1746};
47
morritaf8f92dcd2014-10-27 20:10:2548//------------------------------------------------------------------------------
49
50class ClientChannelMojo
51 : public ChannelMojo,
52 public NON_EXPORTED_BASE(mojo::InterfaceImpl<ClientChannel>) {
53 public:
54 ClientChannelMojo(ChannelMojo::Delegate* delegate,
55 const ChannelHandle& handle,
56 Listener* listener);
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
63 void Init(
64 mojo::ScopedMessagePipeHandle pipe,
65 int32_t peer_pid,
66 const mojo::Callback<void(int32_t)>& callback) override;
67
68 DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo);
69};
70
71ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate* delegate,
72 const ChannelHandle& handle,
73 Listener* listener)
74 : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener) {
75}
76
77ClientChannelMojo::~ClientChannelMojo() {
78}
79
80void ClientChannelMojo::OnPipeAvailable(
81 mojo::embedder::ScopedPlatformHandle handle) {
82 mojo::WeakBindToPipe(this, CreateMessagingPipe(handle.Pass()));
83}
84
85void ClientChannelMojo::OnConnectionError() {
86 listener()->OnChannelError();
87}
88
89void ClientChannelMojo::Init(
90 mojo::ScopedMessagePipeHandle pipe,
91 int32_t peer_pid,
92 const mojo::Callback<void(int32_t)>& callback) {
93 InitMessageReader(pipe.Pass(), static_cast<base::ProcessId>(peer_pid));
94 callback.Run(GetSelfPID());
95}
96
97//------------------------------------------------------------------------------
98
99class ServerChannelMojo : public ChannelMojo, public mojo::ErrorHandler {
100 public:
101 ServerChannelMojo(ChannelMojo::Delegate* delegate,
102 const ChannelHandle& handle,
103 Listener* listener);
104 ~ServerChannelMojo() override;
105
106 // MojoBootstrap::Delegate implementation
107 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
108 // ErrorHandler implementation
109 void OnConnectionError() override;
110 // Channel override
111 void Close() override;
112
113 private:
114 // ClientChannelClient implementation
115 void ClientChannelWasInitialized(int32_t peer_pid);
116
117 mojo::InterfacePtr<ClientChannel> client_channel_;
118 mojo::ScopedMessagePipeHandle message_pipe_;
119
120 DISALLOW_COPY_AND_ASSIGN(ServerChannelMojo);
121};
122
123ServerChannelMojo::ServerChannelMojo(ChannelMojo::Delegate* delegate,
124 const ChannelHandle& handle,
125 Listener* listener)
126 : ChannelMojo(delegate, handle, Channel::MODE_SERVER, listener) {
127}
128
129ServerChannelMojo::~ServerChannelMojo() {
130 Close();
131}
132
133void 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();
141 return;
142 }
143
144 client_channel_.Bind(CreateMessagingPipe(handle.Pass()));
145 client_channel_.set_error_handler(this);
146 client_channel_->Init(
147 peer.Pass(),
148 static_cast<int32_t>(GetSelfPID()),
149 base::Bind(&ServerChannelMojo::ClientChannelWasInitialized,
150 base::Unretained(this)));
151}
152
153void ServerChannelMojo::ClientChannelWasInitialized(int32_t peer_pid) {
154 InitMessageReader(message_pipe_.Pass(), peer_pid);
155}
156
157void ServerChannelMojo::OnConnectionError() {
158 listener()->OnChannelError();
159}
160
161void ServerChannelMojo::Close() {
162 client_channel_.reset();
163 message_pipe_.reset();
164 ChannelMojo::Close();
165}
166
[email protected]64860882014-08-04 23:44:17167} // namespace
168
169//------------------------------------------------------------------------------
170
[email protected]64860882014-08-04 23:44:17171void ChannelMojo::ChannelInfoDeleter::operator()(
172 mojo::embedder::ChannelInfo* ptr) const {
jamesra9125262014-11-19 01:35:28173 mojo::embedder::DestroyChannel(ptr);
[email protected]64860882014-08-04 23:44:17174}
175
176//------------------------------------------------------------------------------
177
178// static
morrita49ca46d2014-10-21 01:16:35179bool ChannelMojo::ShouldBeUsed() {
morrita599be602015-01-27 18:56:47180 // TODO(morrita): Remove this if it sticks.
181 return true;
morrita49ca46d2014-10-21 01:16:35182}
183
184// static
morritae9453ea2014-09-26 03:20:48185scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00186 const ChannelHandle& channel_handle,
187 Mode mode,
188 Listener* listener) {
morritaf8f92dcd2014-10-27 20:10:25189 switch (mode) {
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));
196 default:
197 NOTREACHED();
198 return nullptr;
199 }
[email protected]64860882014-08-04 23:44:17200}
201
202// static
morrita54f6f80c2014-09-23 21:16:00203scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
morritae9453ea2014-09-26 03:20:48204 ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00205 const ChannelHandle& channel_handle) {
dchengecc340f2014-10-17 00:43:54206 return make_scoped_ptr(
207 new MojoChannelFactory(delegate, channel_handle, Channel::MODE_SERVER));
[email protected]64860882014-08-04 23:44:17208}
209
morrita54f6f80c2014-09-23 21:16:00210// static
211scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
212 const ChannelHandle& channel_handle) {
213 return make_scoped_ptr(
dchengecc340f2014-10-17 00:43:54214 new MojoChannelFactory(NULL, channel_handle, Channel::MODE_CLIENT));
morrita54f6f80c2014-09-23 21:16:00215}
216
morritae9453ea2014-09-26 03:20:48217ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00218 const ChannelHandle& handle,
morrita3b41d6c2014-09-11 19:06:29219 Mode mode,
morrita54f6f80c2014-09-23 21:16:00220 Listener* listener)
morritae9453ea2014-09-26 03:20:48221 : mode_(mode),
morrita3b41d6c2014-09-11 19:06:29222 listener_(listener),
anujk.sharma0184ced2014-08-28 06:49:02223 peer_pid_(base::kNullProcessId),
224 weak_factory_(this) {
morrita54f6f80c2014-09-23 21:16:00225 // Create MojoBootstrap after all members are set as it touches
226 // ChannelMojo from a different thread.
227 bootstrap_ = MojoBootstrap::Create(handle, mode, this);
morritae9453ea2014-09-26 03:20:48228 if (delegate) {
229 if (delegate->GetIOTaskRunner() ==
230 base::MessageLoop::current()->message_loop_proxy()) {
231 InitDelegate(delegate);
232 } else {
233 delegate->GetIOTaskRunner()->PostTask(
234 FROM_HERE,
235 base::Bind(
236 &ChannelMojo::InitDelegate, base::Unretained(this), delegate));
237 }
238 }
[email protected]64860882014-08-04 23:44:17239}
240
241ChannelMojo::~ChannelMojo() {
242 Close();
morritae9453ea2014-09-26 03:20:48243}
morrita54f6f80c2014-09-23 21:16:00244
morritae9453ea2014-09-26 03:20:48245void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) {
246 delegate_ = delegate->ToWeakPtr();
247 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr());
[email protected]64860882014-08-04 23:44:17248}
249
morritaf8f92dcd2014-10-27 20:10:25250mojo::ScopedMessagePipeHandle ChannelMojo::CreateMessagingPipe(
morrita54f6f80c2014-09-23 21:16:00251 mojo::embedder::ScopedPlatformHandle handle) {
morritaf8f92dcd2014-10-27 20:10:25252 DCHECK(!channel_info_.get());
[email protected]efbf95d2014-08-12 21:44:01253 mojo::embedder::ChannelInfo* channel_info;
morritaf8f92dcd2014-10-27 20:10:25254 mojo::ScopedMessagePipeHandle pipe =
morrita54f6f80c2014-09-23 21:16:00255 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info);
[email protected]efbf95d2014-08-12 21:44:01256 channel_info_.reset(channel_info);
morritaf8f92dcd2014-10-27 20:10:25257 return pipe.Pass();
[email protected]64860882014-08-04 23:44:17258}
259
260bool ChannelMojo::Connect() {
261 DCHECK(!message_reader_);
morrita54f6f80c2014-09-23 21:16:00262 return bootstrap_->Connect();
[email protected]64860882014-08-04 23:44:17263}
264
265void ChannelMojo::Close() {
[email protected]64860882014-08-04 23:44:17266 message_reader_.reset();
267 channel_info_.reset();
268}
269
morrita54f6f80c2014-09-23 21:16:00270void ChannelMojo::OnBootstrapError() {
271 listener_->OnChannelError();
272}
273
morritaf8f92dcd2014-10-27 20:10:25274void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe,
275 int32_t peer_pid) {
morrita3b41d6c2014-09-11 19:06:29276 message_reader_ =
morritad68bedf42014-11-25 23:35:57277 make_scoped_ptr(new internal::MessagePipeReader(pipe.Pass(), this));
[email protected]64860882014-08-04 23:44:17278
279 for (size_t i = 0; i < pending_messages_.size(); ++i) {
morrita0a24cfc92014-09-16 03:20:48280 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i]));
[email protected]64860882014-08-04 23:44:17281 pending_messages_[i] = NULL;
morrita0a24cfc92014-09-16 03:20:48282 if (!sent) {
283 pending_messages_.clear();
284 listener_->OnChannelError();
285 return;
286 }
[email protected]64860882014-08-04 23:44:17287 }
288
289 pending_messages_.clear();
290
morritaf8f92dcd2014-10-27 20:10:25291 set_peer_pid(peer_pid);
292 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
morritadcc28ab2015-01-10 01:49:21293 if (message_reader_)
294 message_reader_->ReadMessagesThenWait();
[email protected]64860882014-08-04 23:44:17295}
296
297void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
298 Close();
299}
300
301void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
302 listener_->OnChannelError();
303}
304
305
306bool ChannelMojo::Send(Message* message) {
307 if (!message_reader_) {
308 pending_messages_.push_back(message);
309 return true;
310 }
311
312 return message_reader_->Send(make_scoped_ptr(message));
313}
314
315base::ProcessId ChannelMojo::GetPeerPID() const {
316 return peer_pid_;
317}
318
319base::ProcessId ChannelMojo::GetSelfPID() const {
morrita54f6f80c2014-09-23 21:16:00320 return base::GetCurrentProcId();
[email protected]64860882014-08-04 23:44:17321}
322
morrita54f6f80c2014-09-23 21:16:00323void ChannelMojo::OnClientLaunched(base::ProcessHandle handle) {
324 bootstrap_->OnClientLaunched(handle);
[email protected]64860882014-08-04 23:44:17325}
326
[email protected]64860882014-08-04 23:44:17327void ChannelMojo::OnMessageReceived(Message& message) {
morrita7126b7a2014-12-17 19:01:40328 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived",
329 "class", IPC_MESSAGE_ID_CLASS(message.type()),
330 "line", IPC_MESSAGE_ID_LINE(message.type()));
[email protected]64860882014-08-04 23:44:17331 listener_->OnMessageReceived(message);
332 if (message.dispatch_error())
333 listener_->OnBadMessageReceived(message);
334}
335
336#if defined(OS_POSIX) && !defined(OS_NACL)
337int ChannelMojo::GetClientFileDescriptor() const {
338 return bootstrap_->GetClientFileDescriptor();
339}
340
morritaa409ccc2014-10-20 23:53:25341base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
[email protected]64860882014-08-04 23:44:17342 return bootstrap_->TakeClientFileDescriptor();
343}
morrita3b41d6c2014-09-11 19:06:29344
345// static
morrita4b5c28e22015-01-14 21:17:06346MojoResult ChannelMojo::WriteToMessageAttachmentSet(
morrita3b41d6c2014-09-11 19:06:29347 const std::vector<MojoHandle>& handle_buffer,
348 Message* message) {
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: "
355 << unwrap_result;
356 return unwrap_result;
357 }
358
morrita1aa788c2015-01-31 05:45:42359 bool ok = message->attachment_set()->AddAttachment(
360 new internal::PlatformFileAttachment(
361 base::ScopedFD(platform_handle.release().fd)));
morrita3b41d6c2014-09-11 19:06:29362 DCHECK(ok);
363 }
364
365 return MOJO_RESULT_OK;
366}
367
368// static
morrita4b5c28e22015-01-14 21:17:06369MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
morrita96693852014-09-24 20:11:45370 Message* message,
morrita3b41d6c2014-09-11 19:06:29371 std::vector<MojoHandle>* handles) {
372 // We dup() the handles in IPC::Message to transmit.
morrita4b5c28e22015-01-14 21:17:06373 // IPC::MessageAttachmentSet has intricate lifecycle semantics
morrita3b41d6c2014-09-11 19:06:29374 // of FDs, so just to dup()-and-own them is the safest option.
morrita1aa788c2015-01-31 05:45:42375 if (message->HasAttachments()) {
morrita4b5c28e22015-01-14 21:17:06376 MessageAttachmentSet* fdset = message->attachment_set();
morrita96693852014-09-24 20:11:45377 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]);
morrita3b41d6c2014-09-11 19:06:29381 if (-1 == fd_to_send) {
382 DPLOG(WARNING) << "Failed to dup FD to transmit.";
morrita96693852014-09-24 20:11:45383 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29384 return MOJO_RESULT_UNKNOWN;
385 }
386
387 MojoHandle wrapped_handle;
388 MojoResult wrap_result = CreatePlatformHandleWrapper(
389 mojo::embedder::ScopedPlatformHandle(
390 mojo::embedder::PlatformHandle(fd_to_send)),
391 &wrapped_handle);
392 if (MOJO_RESULT_OK != wrap_result) {
393 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: "
394 << wrap_result;
morrita96693852014-09-24 20:11:45395 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29396 return wrap_result;
397 }
398
399 handles->push_back(wrapped_handle);
400 }
morrita96693852014-09-24 20:11:45401
402 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29403 }
404
405 return MOJO_RESULT_OK;
406}
407
[email protected]64860882014-08-04 23:44:17408#endif // defined(OS_POSIX) && !defined(OS_NACL)
409
410} // namespace IPC