blob: 419d8d5bf9b57068b73467afe0f117117f0a6d0a [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
[email protected]64860882014-08-04 23:44:1719namespace IPC {
20
21namespace {
22
[email protected]64860882014-08-04 23:44:1723class MojoChannelFactory : public ChannelFactory {
24 public:
morritae9453ea2014-09-26 03:20:4825 MojoChannelFactory(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:0026 ChannelHandle channel_handle,
27 Channel::Mode mode)
morritae9453ea2014-09-26 03:20:4828 : delegate_(delegate), channel_handle_(channel_handle), mode_(mode) {}
[email protected]64860882014-08-04 23:44:1729
dchengfe61fca2014-10-22 02:29:5230 std::string GetName() const override {
dchengf3076af2014-10-21 18:02:4231 return channel_handle_.name;
32 }
[email protected]64860882014-08-04 23:44:1733
dchengfe61fca2014-10-22 02:29:5234 scoped_ptr<Channel> BuildChannel(Listener* listener) override {
dchengecc340f2014-10-17 00:43:5435 return ChannelMojo::Create(delegate_, channel_handle_, mode_, listener);
[email protected]64860882014-08-04 23:44:1736 }
37
38 private:
morritae9453ea2014-09-26 03:20:4839 ChannelMojo::Delegate* delegate_;
[email protected]64860882014-08-04 23:44:1740 ChannelHandle channel_handle_;
41 Channel::Mode mode_;
[email protected]64860882014-08-04 23:44:1742};
43
morritaf8f92dcd2014-10-27 20:10:2544//------------------------------------------------------------------------------
45
46class ClientChannelMojo
47 : public ChannelMojo,
48 public NON_EXPORTED_BASE(mojo::InterfaceImpl<ClientChannel>) {
49 public:
50 ClientChannelMojo(ChannelMojo::Delegate* delegate,
51 const ChannelHandle& handle,
52 Listener* listener);
53 ~ClientChannelMojo() override;
54 // MojoBootstrap::Delegate implementation
55 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
56 // InterfaceImpl implementation
57 void OnConnectionError() override;
58 // ClientChannel implementation
59 void Init(
60 mojo::ScopedMessagePipeHandle pipe,
61 int32_t peer_pid,
62 const mojo::Callback<void(int32_t)>& callback) override;
63
64 DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo);
65};
66
67ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate* delegate,
68 const ChannelHandle& handle,
69 Listener* listener)
70 : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener) {
71}
72
73ClientChannelMojo::~ClientChannelMojo() {
74}
75
76void ClientChannelMojo::OnPipeAvailable(
77 mojo::embedder::ScopedPlatformHandle handle) {
78 mojo::WeakBindToPipe(this, CreateMessagingPipe(handle.Pass()));
79}
80
81void ClientChannelMojo::OnConnectionError() {
82 listener()->OnChannelError();
83}
84
85void ClientChannelMojo::Init(
86 mojo::ScopedMessagePipeHandle pipe,
87 int32_t peer_pid,
88 const mojo::Callback<void(int32_t)>& callback) {
89 InitMessageReader(pipe.Pass(), static_cast<base::ProcessId>(peer_pid));
90 callback.Run(GetSelfPID());
91}
92
93//------------------------------------------------------------------------------
94
95class ServerChannelMojo : public ChannelMojo, public mojo::ErrorHandler {
96 public:
97 ServerChannelMojo(ChannelMojo::Delegate* delegate,
98 const ChannelHandle& handle,
99 Listener* listener);
100 ~ServerChannelMojo() override;
101
102 // MojoBootstrap::Delegate implementation
103 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
104 // ErrorHandler implementation
105 void OnConnectionError() override;
106 // Channel override
107 void Close() override;
108
109 private:
110 // ClientChannelClient implementation
111 void ClientChannelWasInitialized(int32_t peer_pid);
112
113 mojo::InterfacePtr<ClientChannel> client_channel_;
114 mojo::ScopedMessagePipeHandle message_pipe_;
115
116 DISALLOW_COPY_AND_ASSIGN(ServerChannelMojo);
117};
118
119ServerChannelMojo::ServerChannelMojo(ChannelMojo::Delegate* delegate,
120 const ChannelHandle& handle,
121 Listener* listener)
122 : ChannelMojo(delegate, handle, Channel::MODE_SERVER, listener) {
123}
124
125ServerChannelMojo::~ServerChannelMojo() {
126 Close();
127}
128
129void ServerChannelMojo::OnPipeAvailable(
130 mojo::embedder::ScopedPlatformHandle handle) {
131 mojo::ScopedMessagePipeHandle peer;
132 MojoResult create_result =
133 mojo::CreateMessagePipe(nullptr, &message_pipe_, &peer);
134 if (create_result != MOJO_RESULT_OK) {
135 DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result;
136 listener()->OnChannelError();
137 return;
138 }
139
140 client_channel_.Bind(CreateMessagingPipe(handle.Pass()));
141 client_channel_.set_error_handler(this);
142 client_channel_->Init(
143 peer.Pass(),
144 static_cast<int32_t>(GetSelfPID()),
145 base::Bind(&ServerChannelMojo::ClientChannelWasInitialized,
146 base::Unretained(this)));
147}
148
149void ServerChannelMojo::ClientChannelWasInitialized(int32_t peer_pid) {
150 InitMessageReader(message_pipe_.Pass(), peer_pid);
151}
152
153void ServerChannelMojo::OnConnectionError() {
154 listener()->OnChannelError();
155}
156
157void ServerChannelMojo::Close() {
158 client_channel_.reset();
159 message_pipe_.reset();
160 ChannelMojo::Close();
161}
162
[email protected]64860882014-08-04 23:44:17163} // namespace
164
165//------------------------------------------------------------------------------
166
[email protected]64860882014-08-04 23:44:17167void ChannelMojo::ChannelInfoDeleter::operator()(
168 mojo::embedder::ChannelInfo* ptr) const {
jamesra9125262014-11-19 01:35:28169 mojo::embedder::DestroyChannel(ptr);
[email protected]64860882014-08-04 23:44:17170}
171
172//------------------------------------------------------------------------------
173
174// static
morrita49ca46d2014-10-21 01:16:35175bool ChannelMojo::ShouldBeUsed() {
morrita599be602015-01-27 18:56:47176 // TODO(morrita): Remove this if it sticks.
177 return true;
morrita49ca46d2014-10-21 01:16:35178}
179
180// static
morritae9453ea2014-09-26 03:20:48181scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00182 const ChannelHandle& channel_handle,
183 Mode mode,
184 Listener* listener) {
morritaf8f92dcd2014-10-27 20:10:25185 switch (mode) {
186 case Channel::MODE_CLIENT:
187 return make_scoped_ptr(
188 new ClientChannelMojo(delegate, channel_handle, listener));
189 case Channel::MODE_SERVER:
190 return make_scoped_ptr(
191 new ServerChannelMojo(delegate, channel_handle, listener));
192 default:
193 NOTREACHED();
194 return nullptr;
195 }
[email protected]64860882014-08-04 23:44:17196}
197
198// static
morrita54f6f80c2014-09-23 21:16:00199scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
morritae9453ea2014-09-26 03:20:48200 ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00201 const ChannelHandle& channel_handle) {
dchengecc340f2014-10-17 00:43:54202 return make_scoped_ptr(
203 new MojoChannelFactory(delegate, channel_handle, Channel::MODE_SERVER));
[email protected]64860882014-08-04 23:44:17204}
205
morrita54f6f80c2014-09-23 21:16:00206// static
207scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
208 const ChannelHandle& channel_handle) {
209 return make_scoped_ptr(
dchengecc340f2014-10-17 00:43:54210 new MojoChannelFactory(NULL, channel_handle, Channel::MODE_CLIENT));
morrita54f6f80c2014-09-23 21:16:00211}
212
morritae9453ea2014-09-26 03:20:48213ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:00214 const ChannelHandle& handle,
morrita3b41d6c2014-09-11 19:06:29215 Mode mode,
morrita54f6f80c2014-09-23 21:16:00216 Listener* listener)
morritae9453ea2014-09-26 03:20:48217 : mode_(mode),
morrita3b41d6c2014-09-11 19:06:29218 listener_(listener),
anujk.sharma0184ced2014-08-28 06:49:02219 peer_pid_(base::kNullProcessId),
220 weak_factory_(this) {
morrita54f6f80c2014-09-23 21:16:00221 // Create MojoBootstrap after all members are set as it touches
222 // ChannelMojo from a different thread.
223 bootstrap_ = MojoBootstrap::Create(handle, mode, this);
morritae9453ea2014-09-26 03:20:48224 if (delegate) {
225 if (delegate->GetIOTaskRunner() ==
226 base::MessageLoop::current()->message_loop_proxy()) {
227 InitDelegate(delegate);
228 } else {
229 delegate->GetIOTaskRunner()->PostTask(
230 FROM_HERE,
231 base::Bind(
232 &ChannelMojo::InitDelegate, base::Unretained(this), delegate));
233 }
234 }
[email protected]64860882014-08-04 23:44:17235}
236
237ChannelMojo::~ChannelMojo() {
238 Close();
morritae9453ea2014-09-26 03:20:48239}
morrita54f6f80c2014-09-23 21:16:00240
morritae9453ea2014-09-26 03:20:48241void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) {
242 delegate_ = delegate->ToWeakPtr();
243 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr());
[email protected]64860882014-08-04 23:44:17244}
245
morritaf8f92dcd2014-10-27 20:10:25246mojo::ScopedMessagePipeHandle ChannelMojo::CreateMessagingPipe(
morrita54f6f80c2014-09-23 21:16:00247 mojo::embedder::ScopedPlatformHandle handle) {
morritaf8f92dcd2014-10-27 20:10:25248 DCHECK(!channel_info_.get());
[email protected]efbf95d2014-08-12 21:44:01249 mojo::embedder::ChannelInfo* channel_info;
morritaf8f92dcd2014-10-27 20:10:25250 mojo::ScopedMessagePipeHandle pipe =
morrita54f6f80c2014-09-23 21:16:00251 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info);
[email protected]efbf95d2014-08-12 21:44:01252 channel_info_.reset(channel_info);
morritaf8f92dcd2014-10-27 20:10:25253 return pipe.Pass();
[email protected]64860882014-08-04 23:44:17254}
255
256bool ChannelMojo::Connect() {
257 DCHECK(!message_reader_);
morrita54f6f80c2014-09-23 21:16:00258 return bootstrap_->Connect();
[email protected]64860882014-08-04 23:44:17259}
260
261void ChannelMojo::Close() {
[email protected]64860882014-08-04 23:44:17262 message_reader_.reset();
263 channel_info_.reset();
264}
265
morrita54f6f80c2014-09-23 21:16:00266void ChannelMojo::OnBootstrapError() {
267 listener_->OnChannelError();
268}
269
morritaf8f92dcd2014-10-27 20:10:25270void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe,
271 int32_t peer_pid) {
morrita3b41d6c2014-09-11 19:06:29272 message_reader_ =
morritad68bedf42014-11-25 23:35:57273 make_scoped_ptr(new internal::MessagePipeReader(pipe.Pass(), this));
[email protected]64860882014-08-04 23:44:17274
275 for (size_t i = 0; i < pending_messages_.size(); ++i) {
morrita0a24cfc92014-09-16 03:20:48276 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i]));
[email protected]64860882014-08-04 23:44:17277 pending_messages_[i] = NULL;
morrita0a24cfc92014-09-16 03:20:48278 if (!sent) {
279 pending_messages_.clear();
280 listener_->OnChannelError();
281 return;
282 }
[email protected]64860882014-08-04 23:44:17283 }
284
285 pending_messages_.clear();
286
morritaf8f92dcd2014-10-27 20:10:25287 set_peer_pid(peer_pid);
288 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
morritadcc28ab2015-01-10 01:49:21289 if (message_reader_)
290 message_reader_->ReadMessagesThenWait();
[email protected]64860882014-08-04 23:44:17291}
292
293void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
294 Close();
295}
296
297void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
298 listener_->OnChannelError();
299}
300
301
302bool ChannelMojo::Send(Message* message) {
303 if (!message_reader_) {
304 pending_messages_.push_back(message);
305 return true;
306 }
307
308 return message_reader_->Send(make_scoped_ptr(message));
309}
310
311base::ProcessId ChannelMojo::GetPeerPID() const {
312 return peer_pid_;
313}
314
315base::ProcessId ChannelMojo::GetSelfPID() const {
morrita54f6f80c2014-09-23 21:16:00316 return base::GetCurrentProcId();
[email protected]64860882014-08-04 23:44:17317}
318
morrita54f6f80c2014-09-23 21:16:00319void ChannelMojo::OnClientLaunched(base::ProcessHandle handle) {
320 bootstrap_->OnClientLaunched(handle);
[email protected]64860882014-08-04 23:44:17321}
322
[email protected]64860882014-08-04 23:44:17323void ChannelMojo::OnMessageReceived(Message& message) {
morrita7126b7a2014-12-17 19:01:40324 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived",
325 "class", IPC_MESSAGE_ID_CLASS(message.type()),
326 "line", IPC_MESSAGE_ID_LINE(message.type()));
[email protected]64860882014-08-04 23:44:17327 listener_->OnMessageReceived(message);
328 if (message.dispatch_error())
329 listener_->OnBadMessageReceived(message);
330}
331
332#if defined(OS_POSIX) && !defined(OS_NACL)
333int ChannelMojo::GetClientFileDescriptor() const {
334 return bootstrap_->GetClientFileDescriptor();
335}
336
morritaa409ccc2014-10-20 23:53:25337base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
[email protected]64860882014-08-04 23:44:17338 return bootstrap_->TakeClientFileDescriptor();
339}
morrita3b41d6c2014-09-11 19:06:29340
341// static
morrita4b5c28e22015-01-14 21:17:06342MojoResult ChannelMojo::WriteToMessageAttachmentSet(
morrita3b41d6c2014-09-11 19:06:29343 const std::vector<MojoHandle>& handle_buffer,
344 Message* message) {
345 for (size_t i = 0; i < handle_buffer.size(); ++i) {
346 mojo::embedder::ScopedPlatformHandle platform_handle;
347 MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle(
348 handle_buffer[i], &platform_handle);
349 if (unwrap_result != MOJO_RESULT_OK) {
350 DLOG(WARNING) << "Pipe failed to covert handles. Closing: "
351 << unwrap_result;
352 return unwrap_result;
353 }
354
morrita4b5c28e22015-01-14 21:17:06355 bool ok = message->attachment_set()->AddToOwn(
morrita96693852014-09-24 20:11:45356 base::ScopedFD(platform_handle.release().fd));
morrita3b41d6c2014-09-11 19:06:29357 DCHECK(ok);
358 }
359
360 return MOJO_RESULT_OK;
361}
362
363// static
morrita4b5c28e22015-01-14 21:17:06364MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
morrita96693852014-09-24 20:11:45365 Message* message,
morrita3b41d6c2014-09-11 19:06:29366 std::vector<MojoHandle>* handles) {
367 // We dup() the handles in IPC::Message to transmit.
morrita4b5c28e22015-01-14 21:17:06368 // IPC::MessageAttachmentSet has intricate lifecycle semantics
morrita3b41d6c2014-09-11 19:06:29369 // of FDs, so just to dup()-and-own them is the safest option.
morrita96693852014-09-24 20:11:45370 if (message->HasFileDescriptors()) {
morrita4b5c28e22015-01-14 21:17:06371 MessageAttachmentSet* fdset = message->attachment_set();
morrita96693852014-09-24 20:11:45372 std::vector<base::PlatformFile> fds_to_send(fdset->size());
373 fdset->PeekDescriptors(&fds_to_send[0]);
374 for (size_t i = 0; i < fds_to_send.size(); ++i) {
375 int fd_to_send = dup(fds_to_send[i]);
morrita3b41d6c2014-09-11 19:06:29376 if (-1 == fd_to_send) {
377 DPLOG(WARNING) << "Failed to dup FD to transmit.";
morrita96693852014-09-24 20:11:45378 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29379 return MOJO_RESULT_UNKNOWN;
380 }
381
382 MojoHandle wrapped_handle;
383 MojoResult wrap_result = CreatePlatformHandleWrapper(
384 mojo::embedder::ScopedPlatformHandle(
385 mojo::embedder::PlatformHandle(fd_to_send)),
386 &wrapped_handle);
387 if (MOJO_RESULT_OK != wrap_result) {
388 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: "
389 << wrap_result;
morrita96693852014-09-24 20:11:45390 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29391 return wrap_result;
392 }
393
394 handles->push_back(wrapped_handle);
395 }
morrita96693852014-09-24 20:11:45396
397 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29398 }
399
400 return MOJO_RESULT_OK;
401}
402
[email protected]64860882014-08-04 23:44:17403#endif // defined(OS_POSIX) && !defined(OS_NACL)
404
405} // namespace IPC