blob: 0672a229e016dd0f891c37a0a12e76bd92119a40 [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"
morrita3b41d6c2014-09-11 19:06:2911#include "ipc/mojo/ipc_channel_mojo_readers.h"
morrita54f6f80c2014-09-23 21:16:0012#include "ipc/mojo/ipc_mojo_bootstrap.h"
jamesra03ae492014-10-03 04:26:4813#include "mojo/edk/embedder/embedder.h"
[email protected]64860882014-08-04 23:44:1714
15#if defined(OS_POSIX) && !defined(OS_NACL)
16#include "ipc/file_descriptor_set_posix.h"
17#endif
18
19namespace 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
mostynb50a41f32014-10-07 07:17:1630 virtual std::string GetName() const override {
[email protected]64860882014-08-04 23:44:1731 return channel_handle_.name;
32 }
33
mostynb50a41f32014-10-07 07:17:1634 virtual 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
[email protected]64860882014-08-04 23:44:1744} // namespace
45
46//------------------------------------------------------------------------------
47
[email protected]64860882014-08-04 23:44:1748void ChannelMojo::ChannelInfoDeleter::operator()(
49 mojo::embedder::ChannelInfo* ptr) const {
50 mojo::embedder::DestroyChannelOnIOThread(ptr);
51}
52
53//------------------------------------------------------------------------------
54
55// static
morritae9453ea2014-09-26 03:20:4856scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:0057 const ChannelHandle& channel_handle,
58 Mode mode,
59 Listener* listener) {
morritae9453ea2014-09-26 03:20:4860 return make_scoped_ptr(
61 new ChannelMojo(delegate, channel_handle, mode, listener));
[email protected]64860882014-08-04 23:44:1762}
63
64// static
morrita54f6f80c2014-09-23 21:16:0065scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
morritae9453ea2014-09-26 03:20:4866 ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:0067 const ChannelHandle& channel_handle) {
dchengecc340f2014-10-17 00:43:5468 return make_scoped_ptr(
69 new MojoChannelFactory(delegate, channel_handle, Channel::MODE_SERVER));
[email protected]64860882014-08-04 23:44:1770}
71
morrita54f6f80c2014-09-23 21:16:0072// static
73scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
74 const ChannelHandle& channel_handle) {
75 return make_scoped_ptr(
dchengecc340f2014-10-17 00:43:5476 new MojoChannelFactory(NULL, channel_handle, Channel::MODE_CLIENT));
morrita54f6f80c2014-09-23 21:16:0077}
78
morritae9453ea2014-09-26 03:20:4879ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate,
morrita54f6f80c2014-09-23 21:16:0080 const ChannelHandle& handle,
morrita3b41d6c2014-09-11 19:06:2981 Mode mode,
morrita54f6f80c2014-09-23 21:16:0082 Listener* listener)
morritae9453ea2014-09-26 03:20:4883 : mode_(mode),
morrita3b41d6c2014-09-11 19:06:2984 listener_(listener),
anujk.sharma0184ced2014-08-28 06:49:0285 peer_pid_(base::kNullProcessId),
86 weak_factory_(this) {
morrita54f6f80c2014-09-23 21:16:0087 // Create MojoBootstrap after all members are set as it touches
88 // ChannelMojo from a different thread.
89 bootstrap_ = MojoBootstrap::Create(handle, mode, this);
morritae9453ea2014-09-26 03:20:4890 if (delegate) {
91 if (delegate->GetIOTaskRunner() ==
92 base::MessageLoop::current()->message_loop_proxy()) {
93 InitDelegate(delegate);
94 } else {
95 delegate->GetIOTaskRunner()->PostTask(
96 FROM_HERE,
97 base::Bind(
98 &ChannelMojo::InitDelegate, base::Unretained(this), delegate));
99 }
100 }
[email protected]64860882014-08-04 23:44:17101}
102
103ChannelMojo::~ChannelMojo() {
104 Close();
morritae9453ea2014-09-26 03:20:48105}
morrita54f6f80c2014-09-23 21:16:00106
morritae9453ea2014-09-26 03:20:48107void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) {
108 delegate_ = delegate->ToWeakPtr();
109 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr());
[email protected]64860882014-08-04 23:44:17110}
111
morrita54f6f80c2014-09-23 21:16:00112void ChannelMojo::InitControlReader(
113 mojo::embedder::ScopedPlatformHandle handle) {
114 DCHECK(base::MessageLoopForIO::IsCurrent());
[email protected]efbf95d2014-08-12 21:44:01115 mojo::embedder::ChannelInfo* channel_info;
116 mojo::ScopedMessagePipeHandle control_pipe =
morrita54f6f80c2014-09-23 21:16:00117 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info);
[email protected]efbf95d2014-08-12 21:44:01118 channel_info_.reset(channel_info);
[email protected]64860882014-08-04 23:44:17119
[email protected]efbf95d2014-08-12 21:44:01120 switch (mode_) {
121 case MODE_SERVER:
morrita3b41d6c2014-09-11 19:06:29122 control_reader_.reset(
123 new internal::ServerControlReader(control_pipe.Pass(), this));
[email protected]efbf95d2014-08-12 21:44:01124 break;
125 case MODE_CLIENT:
morrita3b41d6c2014-09-11 19:06:29126 control_reader_.reset(
127 new internal::ClientControlReader(control_pipe.Pass(), this));
[email protected]efbf95d2014-08-12 21:44:01128 break;
129 default:
130 NOTREACHED();
131 break;
[email protected]64860882014-08-04 23:44:17132 }
[email protected]64860882014-08-04 23:44:17133}
134
135bool ChannelMojo::Connect() {
136 DCHECK(!message_reader_);
morrita54f6f80c2014-09-23 21:16:00137 DCHECK(!control_reader_);
138 return bootstrap_->Connect();
[email protected]64860882014-08-04 23:44:17139}
140
141void ChannelMojo::Close() {
142 control_reader_.reset();
143 message_reader_.reset();
144 channel_info_.reset();
145}
146
morrita54f6f80c2014-09-23 21:16:00147void ChannelMojo::OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) {
148 InitControlReader(handle.Pass());
149 control_reader_->Connect();
150}
151
152void ChannelMojo::OnBootstrapError() {
153 listener_->OnChannelError();
154}
155
[email protected]64860882014-08-04 23:44:17156void ChannelMojo::OnConnected(mojo::ScopedMessagePipeHandle pipe) {
morrita3b41d6c2014-09-11 19:06:29157 message_reader_ =
158 make_scoped_ptr(new internal::MessageReader(pipe.Pass(), this));
[email protected]64860882014-08-04 23:44:17159
160 for (size_t i = 0; i < pending_messages_.size(); ++i) {
morrita0a24cfc92014-09-16 03:20:48161 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i]));
[email protected]64860882014-08-04 23:44:17162 pending_messages_[i] = NULL;
morrita0a24cfc92014-09-16 03:20:48163 if (!sent) {
164 pending_messages_.clear();
165 listener_->OnChannelError();
166 return;
167 }
[email protected]64860882014-08-04 23:44:17168 }
169
170 pending_messages_.clear();
171
172 listener_->OnChannelConnected(GetPeerPID());
173}
174
175void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
176 Close();
177}
178
179void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
180 listener_->OnChannelError();
181}
182
183
184bool ChannelMojo::Send(Message* message) {
185 if (!message_reader_) {
186 pending_messages_.push_back(message);
187 return true;
188 }
189
190 return message_reader_->Send(make_scoped_ptr(message));
191}
192
193base::ProcessId ChannelMojo::GetPeerPID() const {
194 return peer_pid_;
195}
196
197base::ProcessId ChannelMojo::GetSelfPID() const {
morrita54f6f80c2014-09-23 21:16:00198 return base::GetCurrentProcId();
[email protected]64860882014-08-04 23:44:17199}
200
morrita54f6f80c2014-09-23 21:16:00201void ChannelMojo::OnClientLaunched(base::ProcessHandle handle) {
202 bootstrap_->OnClientLaunched(handle);
[email protected]64860882014-08-04 23:44:17203}
204
[email protected]64860882014-08-04 23:44:17205void ChannelMojo::OnMessageReceived(Message& message) {
206 listener_->OnMessageReceived(message);
207 if (message.dispatch_error())
208 listener_->OnBadMessageReceived(message);
209}
210
211#if defined(OS_POSIX) && !defined(OS_NACL)
212int ChannelMojo::GetClientFileDescriptor() const {
213 return bootstrap_->GetClientFileDescriptor();
214}
215
morritaa409ccc2014-10-20 23:53:25216base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
[email protected]64860882014-08-04 23:44:17217 return bootstrap_->TakeClientFileDescriptor();
218}
morrita3b41d6c2014-09-11 19:06:29219
220// static
221MojoResult ChannelMojo::WriteToFileDescriptorSet(
222 const std::vector<MojoHandle>& handle_buffer,
223 Message* message) {
224 for (size_t i = 0; i < handle_buffer.size(); ++i) {
225 mojo::embedder::ScopedPlatformHandle platform_handle;
226 MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle(
227 handle_buffer[i], &platform_handle);
228 if (unwrap_result != MOJO_RESULT_OK) {
229 DLOG(WARNING) << "Pipe failed to covert handles. Closing: "
230 << unwrap_result;
231 return unwrap_result;
232 }
233
morrita96693852014-09-24 20:11:45234 bool ok = message->file_descriptor_set()->AddToOwn(
235 base::ScopedFD(platform_handle.release().fd));
morrita3b41d6c2014-09-11 19:06:29236 DCHECK(ok);
237 }
238
239 return MOJO_RESULT_OK;
240}
241
242// static
243MojoResult ChannelMojo::ReadFromFileDescriptorSet(
morrita96693852014-09-24 20:11:45244 Message* message,
morrita3b41d6c2014-09-11 19:06:29245 std::vector<MojoHandle>* handles) {
246 // We dup() the handles in IPC::Message to transmit.
247 // IPC::FileDescriptorSet has intricate lifecycle semantics
248 // of FDs, so just to dup()-and-own them is the safest option.
morrita96693852014-09-24 20:11:45249 if (message->HasFileDescriptors()) {
250 FileDescriptorSet* fdset = message->file_descriptor_set();
251 std::vector<base::PlatformFile> fds_to_send(fdset->size());
252 fdset->PeekDescriptors(&fds_to_send[0]);
253 for (size_t i = 0; i < fds_to_send.size(); ++i) {
254 int fd_to_send = dup(fds_to_send[i]);
morrita3b41d6c2014-09-11 19:06:29255 if (-1 == fd_to_send) {
256 DPLOG(WARNING) << "Failed to dup FD to transmit.";
morrita96693852014-09-24 20:11:45257 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29258 return MOJO_RESULT_UNKNOWN;
259 }
260
261 MojoHandle wrapped_handle;
262 MojoResult wrap_result = CreatePlatformHandleWrapper(
263 mojo::embedder::ScopedPlatformHandle(
264 mojo::embedder::PlatformHandle(fd_to_send)),
265 &wrapped_handle);
266 if (MOJO_RESULT_OK != wrap_result) {
267 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: "
268 << wrap_result;
morrita96693852014-09-24 20:11:45269 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29270 return wrap_result;
271 }
272
273 handles->push_back(wrapped_handle);
274 }
morrita96693852014-09-24 20:11:45275
276 fdset->CommitAll();
morrita3b41d6c2014-09-11 19:06:29277 }
278
279 return MOJO_RESULT_OK;
280}
281
[email protected]64860882014-08-04 23:44:17282#endif // defined(OS_POSIX) && !defined(OS_NACL)
283
284} // namespace IPC