blob: 8375cb44cc2da4e8fe6ffa6adb37fa83d19f0f7f [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"
12#include "ipc/ipc_message_macros.h"
morritaf8f92dcd2014-10-27 20:10:2513#include "ipc/mojo/client_channel.mojom.h"
morrita54f6f80c2014-09-23 21:16:0014#include "ipc/mojo/ipc_mojo_bootstrap.h"
jamesra03ae492014-10-03 04:26:4815#include "mojo/edk/embedder/embedder.h"
morritaf8f92dcd2014-10-27 20:10:2516#include "mojo/public/cpp/bindings/error_handler.h"
[email protected]64860882014-08-04 23:44:1717
18#if defined(OS_POSIX) && !defined(OS_NACL)
19#include "ipc/file_descriptor_set_posix.h"
20#endif
21
22namespace IPC {
23
24namespace {
25
[email protected]64860882014-08-04 23:44:1726class MojoChannelFactory : public ChannelFactory {
27 public:
morritae9453ea2014-09-26 03:20:4828 MojoChannelFactory(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:0029 ChannelHandle channel_handle,
30 Channel::Mode mode)
morritae9453ea2014-09-26 03:20:4831 : delegate_(delegate), channel_handle_(channel_handle), mode_(mode) {}
[email protected]64860882014-08-04 23:44:1732
dchengfe61fca2014-10-22 02:29:5233 std::string GetName() const override {
dchengf3076af2014-10-21 18:02:4234 return channel_handle_.name;
35 }
[email protected]64860882014-08-04 23:44:1736
dchengfe61fca2014-10-22 02:29:5237 scoped_ptr<Channel> BuildChannel(Listener* listener) override {
dchengecc340f2014-10-17 00:43:5438 return ChannelMojo::Create(delegate_, channel_handle_, mode_, listener);
[email protected]64860882014-08-04 23:44:1739 }
40
41 private:
morritae9453ea2014-09-26 03:20:4842 ChannelMojo::Delegate* delegate_;
[email protected]64860882014-08-04 23:44:1743 ChannelHandle channel_handle_;
44 Channel::Mode mode_;
[email protected]64860882014-08-04 23:44:1745};
46
morritaf8f92dcd2014-10-27 20:10:2547//------------------------------------------------------------------------------
48
49class ClientChannelMojo
50 : public ChannelMojo,
51 public NON_EXPORTED_BASE(mojo::InterfaceImpl<ClientChannel>) {
52 public:
53 ClientChannelMojo(ChannelMojo::Delegate* delegate,
54 const ChannelHandle& handle,
55 Listener* listener);
56 ~ClientChannelMojo() override;
57 // MojoBootstrap::Delegate implementation
58 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
59 // InterfaceImpl implementation
60 void OnConnectionError() override;
61 // ClientChannel implementation
62 void Init(
63 mojo::ScopedMessagePipeHandle pipe,
64 int32_t peer_pid,
65 const mojo::Callback<void(int32_t)>& callback) override;
66
67 DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo);
68};
69
70ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate* delegate,
71 const ChannelHandle& handle,
72 Listener* listener)
73 : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener) {
74}
75
76ClientChannelMojo::~ClientChannelMojo() {
77}
78
79void ClientChannelMojo::OnPipeAvailable(
80 mojo::embedder::ScopedPlatformHandle handle) {
81 mojo::WeakBindToPipe(this, CreateMessagingPipe(handle.Pass()));
82}
83
84void ClientChannelMojo::OnConnectionError() {
85 listener()->OnChannelError();
86}
87
88void ClientChannelMojo::Init(
89 mojo::ScopedMessagePipeHandle pipe,
90 int32_t peer_pid,
91 const mojo::Callback<void(int32_t)>& callback) {
92 InitMessageReader(pipe.Pass(), static_cast<base::ProcessId>(peer_pid));
93 callback.Run(GetSelfPID());
94}
95
96//------------------------------------------------------------------------------
97
98class ServerChannelMojo : public ChannelMojo, public mojo::ErrorHandler {
99 public:
100 ServerChannelMojo(ChannelMojo::Delegate* delegate,
101 const ChannelHandle& handle,
102 Listener* listener);
103 ~ServerChannelMojo() override;
104
105 // MojoBootstrap::Delegate implementation
106 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
107 // ErrorHandler implementation
108 void OnConnectionError() override;
109 // Channel override
110 void Close() override;
111
112 private:
113 // ClientChannelClient implementation
114 void ClientChannelWasInitialized(int32_t peer_pid);
115
116 mojo::InterfacePtr<ClientChannel> client_channel_;
117 mojo::ScopedMessagePipeHandle message_pipe_;
118
119 DISALLOW_COPY_AND_ASSIGN(ServerChannelMojo);
120};
121
122ServerChannelMojo::ServerChannelMojo(ChannelMojo::Delegate* delegate,
123 const ChannelHandle& handle,
124 Listener* listener)
125 : ChannelMojo(delegate, handle, Channel::MODE_SERVER, listener) {
126}
127
128ServerChannelMojo::~ServerChannelMojo() {
129 Close();
130}
131
132void ServerChannelMojo::OnPipeAvailable(
133 mojo::embedder::ScopedPlatformHandle handle) {
134 mojo::ScopedMessagePipeHandle peer;
135 MojoResult create_result =
136 mojo::CreateMessagePipe(nullptr, &message_pipe_, &peer);
137 if (create_result != MOJO_RESULT_OK) {
138 DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result;
139 listener()->OnChannelError();
140 return;
141 }
142
143 client_channel_.Bind(CreateMessagingPipe(handle.Pass()));
144 client_channel_.set_error_handler(this);
145 client_channel_->Init(
146 peer.Pass(),
147 static_cast<int32_t>(GetSelfPID()),
148 base::Bind(&ServerChannelMojo::ClientChannelWasInitialized,
149 base::Unretained(this)));
150}
151
152void ServerChannelMojo::ClientChannelWasInitialized(int32_t peer_pid) {
153 InitMessageReader(message_pipe_.Pass(), peer_pid);
154}
155
156void ServerChannelMojo::OnConnectionError() {
157 listener()->OnChannelError();
158}
159
160void ServerChannelMojo::Close() {
161 client_channel_.reset();
162 message_pipe_.reset();
163 ChannelMojo::Close();
164}
165
[email protected]64860882014-08-04 23:44:17166} // namespace
167
168//------------------------------------------------------------------------------
169
[email protected]64860882014-08-04 23:44:17170void ChannelMojo::ChannelInfoDeleter::operator()(
171 mojo::embedder::ChannelInfo* ptr) const {
jamesra9125262014-11-19 01:35:28172 mojo::embedder::DestroyChannel(ptr);
[email protected]64860882014-08-04 23:44:17173}
174
175//------------------------------------------------------------------------------
176
177// static
morrita49ca46d2014-10-21 01:16:35178bool ChannelMojo::ShouldBeUsed() {
morrita945ddbc2014-11-26 19:39:20179 // TODO(morrita): Turn this on for a set of platforms.
180 return false;
morrita49ca46d2014-10-21 01:16:35181}
182
183// static
morritae9453ea2014-09-26 03:20:48184scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00185 const ChannelHandle& channel_handle,
186 Mode mode,
187 Listener* listener) {
morritaf8f92dcd2014-10-27 20:10:25188 switch (mode) {
189 case Channel::MODE_CLIENT:
190 return make_scoped_ptr(
191 new ClientChannelMojo(delegate, channel_handle, listener));
192 case Channel::MODE_SERVER:
193 return make_scoped_ptr(
194 new ServerChannelMojo(delegate, channel_handle, listener));
195 default:
196 NOTREACHED();
197 return nullptr;
198 }
[email protected]64860882014-08-04 23:44:17199}
200
201// static
morrita54f6f80c2014-09-23 21:16:00202scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
morritae9453ea2014-09-26 03:20:48203 ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00204 const ChannelHandle& channel_handle) {
dchengecc340f2014-10-17 00:43:54205 return make_scoped_ptr(
206 new MojoChannelFactory(delegate, channel_handle, Channel::MODE_SERVER));
[email protected]64860882014-08-04 23:44:17207}
208
morrita54f6f80c2014-09-23 21:16:00209// static
210scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
211 const ChannelHandle& channel_handle) {
212 return make_scoped_ptr(
dchengecc340f2014-10-17 00:43:54213 new MojoChannelFactory(NULL, channel_handle, Channel::MODE_CLIENT));
morrita54f6f80c2014-09-23 21:16:00214}
215
morritae9453ea2014-09-26 03:20:48216ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00217 const ChannelHandle& handle,
morrita3b41d6c2014-09-11 19:06:29218 Mode mode,
morrita54f6f80c2014-09-23 21:16:00219 Listener* listener)
morritae9453ea2014-09-26 03:20:48220 : mode_(mode),
morrita3b41d6c2014-09-11 19:06:29221 listener_(listener),
anujk.sharma0184ced2014-08-28 06:49:02222 peer_pid_(base::kNullProcessId),
223 weak_factory_(this) {
morrita54f6f80c2014-09-23 21:16:00224 // Create MojoBootstrap after all members are set as it touches
225 // ChannelMojo from a different thread.
226 bootstrap_ = MojoBootstrap::Create(handle, mode, this);
morritae9453ea2014-09-26 03:20:48227 if (delegate) {
228 if (delegate->GetIOTaskRunner() ==
229 base::MessageLoop::current()->message_loop_proxy()) {
230 InitDelegate(delegate);
231 } else {
232 delegate->GetIOTaskRunner()->PostTask(
233 FROM_HERE,
234 base::Bind(
235 &ChannelMojo::InitDelegate, base::Unretained(this), delegate));
236 }
237 }
[email protected]64860882014-08-04 23:44:17238}
239
240ChannelMojo::~ChannelMojo() {
241 Close();
morritae9453ea2014-09-26 03:20:48242}
morrita54f6f80c2014-09-23 21:16:00243
morritae9453ea2014-09-26 03:20:48244void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) {
245 delegate_ = delegate->ToWeakPtr();
246 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr());
[email protected]64860882014-08-04 23:44:17247}
248
morritaf8f92dcd2014-10-27 20:10:25249mojo::ScopedMessagePipeHandle ChannelMojo::CreateMessagingPipe(
morrita54f6f80c2014-09-23 21:16:00250 mojo::embedder::ScopedPlatformHandle handle) {
morritaf8f92dcd2014-10-27 20:10:25251 DCHECK(!channel_info_.get());
[email protected]efbf95d2014-08-12 21:44:01252 mojo::embedder::ChannelInfo* channel_info;
morritaf8f92dcd2014-10-27 20:10:25253 mojo::ScopedMessagePipeHandle pipe =
morrita54f6f80c2014-09-23 21:16:00254 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info);
[email protected]efbf95d2014-08-12 21:44:01255 channel_info_.reset(channel_info);
morritaf8f92dcd2014-10-27 20:10:25256 return pipe.Pass();
[email protected]64860882014-08-04 23:44:17257}
258
259bool ChannelMojo::Connect() {
260 DCHECK(!message_reader_);
morrita54f6f80c2014-09-23 21:16:00261 return bootstrap_->Connect();
[email protected]64860882014-08-04 23:44:17262}
263
264void ChannelMojo::Close() {
[email protected]64860882014-08-04 23:44:17265 message_reader_.reset();
266 channel_info_.reset();
267}
268
morrita54f6f80c2014-09-23 21:16:00269void ChannelMojo::OnBootstrapError() {
270 listener_->OnChannelError();
271}
272
morritaf8f92dcd2014-10-27 20:10:25273void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe,
274 int32_t peer_pid) {
morrita3b41d6c2014-09-11 19:06:29275 message_reader_ =
morritad68bedf42014-11-25 23:35:57276 make_scoped_ptr(new internal::MessagePipeReader(pipe.Pass(), this));
[email protected]64860882014-08-04 23:44:17277
278 for (size_t i = 0; i < pending_messages_.size(); ++i) {
morrita0a24cfc92014-09-16 03:20:48279 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i]));
[email protected]64860882014-08-04 23:44:17280 pending_messages_[i] = NULL;
morrita0a24cfc92014-09-16 03:20:48281 if (!sent) {
282 pending_messages_.clear();
283 listener_->OnChannelError();
284 return;
285 }
[email protected]64860882014-08-04 23:44:17286 }
287
288 pending_messages_.clear();
289
morritaf8f92dcd2014-10-27 20:10:25290 set_peer_pid(peer_pid);
291 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
[email protected]64860882014-08-04 23:44:17292}
293
294void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
295 Close();
296}
297
298void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
299 listener_->OnChannelError();
300}
301
302
303bool ChannelMojo::Send(Message* message) {
304 if (!message_reader_) {
305 pending_messages_.push_back(message);
306 return true;
307 }
308
309 return message_reader_->Send(make_scoped_ptr(message));
310}
311
312base::ProcessId ChannelMojo::GetPeerPID() const {
313 return peer_pid_;
314}
315
316base::ProcessId ChannelMojo::GetSelfPID() const {
morrita54f6f80c2014-09-23 21:16:00317 return base::GetCurrentProcId();
[email protected]64860882014-08-04 23:44:17318}
319
morrita54f6f80c2014-09-23 21:16:00320void ChannelMojo::OnClientLaunched(base::ProcessHandle handle) {
321 bootstrap_->OnClientLaunched(handle);
[email protected]64860882014-08-04 23:44:17322}
323
[email protected]64860882014-08-04 23:44:17324void ChannelMojo::OnMessageReceived(Message& message) {
morrita7126b7a2014-12-17 19:01:40325 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived",
326 "class", IPC_MESSAGE_ID_CLASS(message.type()),
327 "line", IPC_MESSAGE_ID_LINE(message.type()));
[email protected]64860882014-08-04 23:44:17328 listener_->OnMessageReceived(message);
329 if (message.dispatch_error())
330 listener_->OnBadMessageReceived(message);
331}
332
333#if defined(OS_POSIX) && !defined(OS_NACL)
334int ChannelMojo::GetClientFileDescriptor() const {
335 return bootstrap_->GetClientFileDescriptor();
336}
337
morritaa409ccc2014-10-20 23:53:25338base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
[email protected]64860882014-08-04 23:44:17339 return bootstrap_->TakeClientFileDescriptor();
340}
morrita3b41d6c2014-09-11 19:06:29341
342// static
343MojoResult ChannelMojo::WriteToFileDescriptorSet(
344 const std::vector<MojoHandle>& handle_buffer,
345 Message* message) {
346 for (size_t i = 0; i < handle_buffer.size(); ++i) {
347 mojo::embedder::ScopedPlatformHandle platform_handle;
348 MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle(
349 handle_buffer[i], &platform_handle);
350 if (unwrap_result != MOJO_RESULT_OK) {
351 DLOG(WARNING) << "Pipe failed to covert handles. Closing: "
352 << unwrap_result;
353 return unwrap_result;
354 }
355
morrita96693852014-09-24 20:11:45356 bool ok = message->file_descriptor_set()->AddToOwn(
357 base::ScopedFD(platform_handle.release().fd));
morrita3b41d6c2014-09-11 19:06:29358 DCHECK(ok);
359 }
360
361 return MOJO_RESULT_OK;
362}
363
364// static
365MojoResult ChannelMojo::ReadFromFileDescriptorSet(
morrita96693852014-09-24 20:11:45366 Message* message,
morrita3b41d6c2014-09-11 19:06:29367 std::vector<MojoHandle>* handles) {
368 // We dup() the handles in IPC::Message to transmit.
369 // IPC::FileDescriptorSet has intricate lifecycle semantics
370 // of FDs, so just to dup()-and-own them is the safest option.
morrita96693852014-09-24 20:11:45371 if (message->HasFileDescriptors()) {
372 FileDescriptorSet* fdset = message->file_descriptor_set();
373 std::vector<base::PlatformFile> fds_to_send(fdset->size());
374 fdset->PeekDescriptors(&fds_to_send[0]);
375 for (size_t i = 0; i < fds_to_send.size(); ++i) {
376 int fd_to_send = dup(fds_to_send[i]);
morrita3b41d6c2014-09-11 19:06:29377 if (-1 == fd_to_send) {
378 DPLOG(WARNING) << "Failed to dup FD to transmit.";
morrita96693852014-09-24 20:11:45379 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29380 return MOJO_RESULT_UNKNOWN;
381 }
382
383 MojoHandle wrapped_handle;
384 MojoResult wrap_result = CreatePlatformHandleWrapper(
385 mojo::embedder::ScopedPlatformHandle(
386 mojo::embedder::PlatformHandle(fd_to_send)),
387 &wrapped_handle);
388 if (MOJO_RESULT_OK != wrap_result) {
389 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: "
390 << wrap_result;
morrita96693852014-09-24 20:11:45391 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29392 return wrap_result;
393 }
394
395 handles->push_back(wrapped_handle);
396 }
morrita96693852014-09-24 20:11:45397
398 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29399 }
400
401 return MOJO_RESULT_OK;
402}
403
[email protected]64860882014-08-04 23:44:17404#endif // defined(OS_POSIX) && !defined(OS_NACL)
405
406} // namespace IPC