1 // 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.
5 #include "ipc/mojo/ipc_channel_mojo.h"
8 #include "base/bind_helpers.h"
9 #include "base/lazy_instance.h"
10 #include "ipc/ipc_listener.h"
11 #include "ipc/mojo/client_channel.mojom.h"
12 #include "ipc/mojo/ipc_channel_mojo_readers.h"
13 #include "ipc/mojo/ipc_mojo_bootstrap.h"
14 #include "mojo/edk/embedder/embedder.h"
15 #include "mojo/public/cpp/bindings/error_handler.h"
17 #if defined(OS_POSIX) && !defined(OS_NACL)
18 #include "ipc/file_descriptor_set_posix.h"
25 class MojoChannelFactory : public ChannelFactory {
27 MojoChannelFactory(ChannelMojo::Delegate* delegate,
28 ChannelHandle channel_handle,
30 : delegate_(delegate), channel_handle_(channel_handle), mode_(mode) {}
32 std::string GetName() const override {
33 return channel_handle_.name;
36 scoped_ptr<Channel> BuildChannel(Listener* listener) override {
37 return ChannelMojo::Create(delegate_, channel_handle_, mode_, listener);
41 ChannelMojo::Delegate* delegate_;
42 ChannelHandle channel_handle_;
46 //------------------------------------------------------------------------------
48 class ClientChannelMojo
50 public NON_EXPORTED_BASE(mojo::InterfaceImpl<ClientChannel>) {
52 ClientChannelMojo(ChannelMojo::Delegate* delegate,
53 const ChannelHandle& handle,
55 ~ClientChannelMojo() override;
56 // MojoBootstrap::Delegate implementation
57 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
58 // InterfaceImpl implementation
59 void OnConnectionError() override;
60 // ClientChannel implementation
62 mojo::ScopedMessagePipeHandle pipe,
64 const mojo::Callback<void(int32_t)>& callback) override;
66 DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo);
69 ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate* delegate,
70 const ChannelHandle& handle,
72 : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener) {
75 ClientChannelMojo::~ClientChannelMojo() {
78 void ClientChannelMojo::OnPipeAvailable(
79 mojo::embedder::ScopedPlatformHandle handle) {
80 mojo::WeakBindToPipe(this, CreateMessagingPipe(handle.Pass()));
83 void ClientChannelMojo::OnConnectionError() {
84 listener()->OnChannelError();
87 void ClientChannelMojo::Init(
88 mojo::ScopedMessagePipeHandle pipe,
90 const mojo::Callback<void(int32_t)>& callback) {
91 InitMessageReader(pipe.Pass(), static_cast<base::ProcessId>(peer_pid));
92 callback.Run(GetSelfPID());
95 //------------------------------------------------------------------------------
97 class ServerChannelMojo : public ChannelMojo, public mojo::ErrorHandler {
99 ServerChannelMojo(ChannelMojo::Delegate* delegate,
100 const ChannelHandle& handle,
102 ~ServerChannelMojo() override;
104 // MojoBootstrap::Delegate implementation
105 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
106 // ErrorHandler implementation
107 void OnConnectionError() override;
109 void Close() override;
112 // ClientChannelClient implementation
113 void ClientChannelWasInitialized(int32_t peer_pid);
115 mojo::InterfacePtr<ClientChannel> client_channel_;
116 mojo::ScopedMessagePipeHandle message_pipe_;
118 DISALLOW_COPY_AND_ASSIGN(ServerChannelMojo);
121 ServerChannelMojo::ServerChannelMojo(ChannelMojo::Delegate* delegate,
122 const ChannelHandle& handle,
124 : ChannelMojo(delegate, handle, Channel::MODE_SERVER, listener) {
127 ServerChannelMojo::~ServerChannelMojo() {
131 void ServerChannelMojo::OnPipeAvailable(
132 mojo::embedder::ScopedPlatformHandle handle) {
133 mojo::ScopedMessagePipeHandle peer;
134 MojoResult create_result =
135 mojo::CreateMessagePipe(nullptr, &message_pipe_, &peer);
136 if (create_result != MOJO_RESULT_OK) {
137 DLOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result;
138 listener()->OnChannelError();
142 client_channel_.Bind(CreateMessagingPipe(handle.Pass()));
143 client_channel_.set_error_handler(this);
144 client_channel_->Init(
146 static_cast<int32_t>(GetSelfPID()),
147 base::Bind(&ServerChannelMojo::ClientChannelWasInitialized,
148 base::Unretained(this)));
151 void ServerChannelMojo::ClientChannelWasInitialized(int32_t peer_pid) {
152 InitMessageReader(message_pipe_.Pass(), peer_pid);
155 void ServerChannelMojo::OnConnectionError() {
156 listener()->OnChannelError();
159 void ServerChannelMojo::Close() {
160 client_channel_.reset();
161 message_pipe_.reset();
162 ChannelMojo::Close();
167 //------------------------------------------------------------------------------
169 void ChannelMojo::ChannelInfoDeleter::operator()(
170 mojo::embedder::ChannelInfo* ptr) const {
171 mojo::embedder::DestroyChannelOnIOThread(ptr);
174 //------------------------------------------------------------------------------
177 bool ChannelMojo::ShouldBeUsed() {
178 // TODO(morrita): Turn this on for a set of platforms.
183 scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate,
184 const ChannelHandle& channel_handle,
186 Listener* listener) {
188 case Channel::MODE_CLIENT:
189 return make_scoped_ptr(
190 new ClientChannelMojo(delegate, channel_handle, listener));
191 case Channel::MODE_SERVER:
192 return make_scoped_ptr(
193 new ServerChannelMojo(delegate, channel_handle, listener));
201 scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
202 ChannelMojo::Delegate* delegate,
203 const ChannelHandle& channel_handle) {
204 return make_scoped_ptr(
205 new MojoChannelFactory(delegate, channel_handle, Channel::MODE_SERVER));
209 scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
210 const ChannelHandle& channel_handle) {
211 return make_scoped_ptr(
212 new MojoChannelFactory(NULL, channel_handle, Channel::MODE_CLIENT));
215 ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate,
216 const ChannelHandle& handle,
221 peer_pid_(base::kNullProcessId),
222 weak_factory_(this) {
223 // Create MojoBootstrap after all members are set as it touches
224 // ChannelMojo from a different thread.
225 bootstrap_ = MojoBootstrap::Create(handle, mode, this);
227 if (delegate->GetIOTaskRunner() ==
228 base::MessageLoop::current()->message_loop_proxy()) {
229 InitDelegate(delegate);
231 delegate->GetIOTaskRunner()->PostTask(
234 &ChannelMojo::InitDelegate, base::Unretained(this), delegate));
239 ChannelMojo::~ChannelMojo() {
243 void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) {
244 delegate_ = delegate->ToWeakPtr();
245 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr());
248 mojo::ScopedMessagePipeHandle ChannelMojo::CreateMessagingPipe(
249 mojo::embedder::ScopedPlatformHandle handle) {
250 DCHECK(!channel_info_.get());
251 mojo::embedder::ChannelInfo* channel_info;
252 mojo::ScopedMessagePipeHandle pipe =
253 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info);
254 channel_info_.reset(channel_info);
258 bool ChannelMojo::Connect() {
259 DCHECK(!message_reader_);
260 return bootstrap_->Connect();
263 void ChannelMojo::Close() {
264 message_reader_.reset();
265 channel_info_.reset();
268 void ChannelMojo::OnBootstrapError() {
269 listener_->OnChannelError();
272 void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe,
275 make_scoped_ptr(new internal::MessageReader(pipe.Pass(), this));
277 for (size_t i = 0; i < pending_messages_.size(); ++i) {
278 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i]));
279 pending_messages_[i] = NULL;
281 pending_messages_.clear();
282 listener_->OnChannelError();
287 pending_messages_.clear();
289 set_peer_pid(peer_pid);
290 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
293 void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
297 void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
298 listener_->OnChannelError();
302 bool ChannelMojo::Send(Message* message) {
303 if (!message_reader_) {
304 pending_messages_.push_back(message);
308 return message_reader_->Send(make_scoped_ptr(message));
311 base::ProcessId ChannelMojo::GetPeerPID() const {
315 base::ProcessId ChannelMojo::GetSelfPID() const {
316 return base::GetCurrentProcId();
319 void ChannelMojo::OnClientLaunched(base::ProcessHandle handle) {
320 bootstrap_->OnClientLaunched(handle);
323 void ChannelMojo::OnMessageReceived(Message& message) {
324 listener_->OnMessageReceived(message);
325 if (message.dispatch_error())
326 listener_->OnBadMessageReceived(message);
329 #if defined(OS_POSIX) && !defined(OS_NACL)
330 int ChannelMojo::GetClientFileDescriptor() const {
331 return bootstrap_->GetClientFileDescriptor();
334 base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
335 return bootstrap_->TakeClientFileDescriptor();
339 MojoResult ChannelMojo::WriteToFileDescriptorSet(
340 const std::vector<MojoHandle>& handle_buffer,
342 for (size_t i = 0; i < handle_buffer.size(); ++i) {
343 mojo::embedder::ScopedPlatformHandle platform_handle;
344 MojoResult unwrap_result = mojo::embedder::PassWrappedPlatformHandle(
345 handle_buffer[i], &platform_handle);
346 if (unwrap_result != MOJO_RESULT_OK) {
347 DLOG(WARNING) << "Pipe failed to covert handles. Closing: "
349 return unwrap_result;
352 bool ok = message->file_descriptor_set()->AddToOwn(
353 base::ScopedFD(platform_handle.release().fd));
357 return MOJO_RESULT_OK;
361 MojoResult ChannelMojo::ReadFromFileDescriptorSet(
363 std::vector<MojoHandle>* handles) {
364 // We dup() the handles in IPC::Message to transmit.
365 // IPC::FileDescriptorSet has intricate lifecycle semantics
366 // of FDs, so just to dup()-and-own them is the safest option.
367 if (message->HasFileDescriptors()) {
368 FileDescriptorSet* fdset = message->file_descriptor_set();
369 std::vector<base::PlatformFile> fds_to_send(fdset->size());
370 fdset->PeekDescriptors(&fds_to_send[0]);
371 for (size_t i = 0; i < fds_to_send.size(); ++i) {
372 int fd_to_send = dup(fds_to_send[i]);
373 if (-1 == fd_to_send) {
374 DPLOG(WARNING) << "Failed to dup FD to transmit.";
376 return MOJO_RESULT_UNKNOWN;
379 MojoHandle wrapped_handle;
380 MojoResult wrap_result = CreatePlatformHandleWrapper(
381 mojo::embedder::ScopedPlatformHandle(
382 mojo::embedder::PlatformHandle(fd_to_send)),
384 if (MOJO_RESULT_OK != wrap_result) {
385 DLOG(WARNING) << "Pipe failed to wrap handles. Closing: "
391 handles->push_back(wrapped_handle);
397 return MOJO_RESULT_OK;
400 #endif // defined(OS_POSIX) && !defined(OS_NACL)