Revert of Remove Qualcomm MSAA from blacklist for versions >= Lollipop. (patchset...
[chromium-blink-merge.git] / ipc / mojo / ipc_channel_mojo.cc
blob0d77fb9b16878a041940c5aa40047572f0294baf
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"
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/lazy_instance.h"
10 #include "ipc/ipc_listener.h"
11 #include "ipc/ipc_logging.h"
12 #include "ipc/ipc_message_attachment_set.h"
13 #include "ipc/ipc_message_macros.h"
14 #include "ipc/mojo/client_channel.mojom.h"
15 #include "ipc/mojo/ipc_mojo_bootstrap.h"
16 #include "ipc/mojo/ipc_mojo_handle_attachment.h"
17 #include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
18 #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h"
20 #if defined(OS_POSIX) && !defined(OS_NACL)
21 #include "ipc/ipc_platform_file_attachment_posix.h"
22 #endif
24 namespace IPC {
26 namespace {
28 class MojoChannelFactory : public ChannelFactory {
29 public:
30 MojoChannelFactory(ChannelMojo::Delegate* delegate,
31 ChannelHandle channel_handle,
32 Channel::Mode mode)
33 : delegate_(delegate), channel_handle_(channel_handle), mode_(mode) {}
35 std::string GetName() const override {
36 return channel_handle_.name;
39 scoped_ptr<Channel> BuildChannel(Listener* listener) override {
40 return ChannelMojo::Create(delegate_, channel_handle_, mode_, listener);
43 private:
44 ChannelMojo::Delegate* delegate_;
45 ChannelHandle channel_handle_;
46 Channel::Mode mode_;
49 //------------------------------------------------------------------------------
51 class ClientChannelMojo : public ChannelMojo,
52 public ClientChannel,
53 public mojo::ErrorHandler {
54 public:
55 ClientChannelMojo(ChannelMojo::Delegate* delegate,
56 const ChannelHandle& handle,
57 Listener* listener);
58 ~ClientChannelMojo() override;
59 // MojoBootstrap::Delegate implementation
60 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
61 // mojo::ErrorHandler implementation
62 void OnConnectionError() override;
63 // ClientChannel implementation
64 void Init(
65 mojo::ScopedMessagePipeHandle pipe,
66 int32_t peer_pid,
67 const mojo::Callback<void(int32_t)>& callback) override;
69 private:
70 mojo::Binding<ClientChannel> binding_;
72 DISALLOW_COPY_AND_ASSIGN(ClientChannelMojo);
75 ClientChannelMojo::ClientChannelMojo(ChannelMojo::Delegate* delegate,
76 const ChannelHandle& handle,
77 Listener* listener)
78 : ChannelMojo(delegate, handle, Channel::MODE_CLIENT, listener),
79 binding_(this) {
82 ClientChannelMojo::~ClientChannelMojo() {
85 void ClientChannelMojo::OnPipeAvailable(
86 mojo::embedder::ScopedPlatformHandle handle) {
87 binding_.Bind(CreateMessagingPipe(handle.Pass()));
90 void ClientChannelMojo::OnConnectionError() {
91 listener()->OnChannelError();
94 void ClientChannelMojo::Init(
95 mojo::ScopedMessagePipeHandle pipe,
96 int32_t peer_pid,
97 const mojo::Callback<void(int32_t)>& callback) {
98 InitMessageReader(pipe.Pass(), static_cast<base::ProcessId>(peer_pid));
99 callback.Run(GetSelfPID());
102 //------------------------------------------------------------------------------
104 class ServerChannelMojo : public ChannelMojo, public mojo::ErrorHandler {
105 public:
106 ServerChannelMojo(ChannelMojo::Delegate* delegate,
107 const ChannelHandle& handle,
108 Listener* listener);
109 ~ServerChannelMojo() override;
111 // MojoBootstrap::Delegate implementation
112 void OnPipeAvailable(mojo::embedder::ScopedPlatformHandle handle) override;
113 // mojo::ErrorHandler implementation
114 void OnConnectionError() override;
115 // Channel override
116 void Close() override;
118 private:
119 // ClientChannelClient implementation
120 void ClientChannelWasInitialized(int32_t peer_pid);
122 mojo::InterfacePtr<ClientChannel> client_channel_;
123 mojo::ScopedMessagePipeHandle message_pipe_;
125 DISALLOW_COPY_AND_ASSIGN(ServerChannelMojo);
128 ServerChannelMojo::ServerChannelMojo(ChannelMojo::Delegate* delegate,
129 const ChannelHandle& handle,
130 Listener* listener)
131 : ChannelMojo(delegate, handle, Channel::MODE_SERVER, listener) {
134 ServerChannelMojo::~ServerChannelMojo() {
135 Close();
138 void ServerChannelMojo::OnPipeAvailable(
139 mojo::embedder::ScopedPlatformHandle handle) {
140 mojo::ScopedMessagePipeHandle peer;
141 MojoResult create_result =
142 mojo::CreateMessagePipe(nullptr, &message_pipe_, &peer);
143 if (create_result != MOJO_RESULT_OK) {
144 LOG(WARNING) << "mojo::CreateMessagePipe failed: " << create_result;
145 listener()->OnChannelError();
146 return;
149 client_channel_.Bind(CreateMessagingPipe(handle.Pass()));
150 client_channel_.set_error_handler(this);
151 client_channel_->Init(
152 peer.Pass(),
153 static_cast<int32_t>(GetSelfPID()),
154 base::Bind(&ServerChannelMojo::ClientChannelWasInitialized,
155 base::Unretained(this)));
158 void ServerChannelMojo::ClientChannelWasInitialized(int32_t peer_pid) {
159 InitMessageReader(message_pipe_.Pass(), peer_pid);
162 void ServerChannelMojo::OnConnectionError() {
163 listener()->OnChannelError();
166 void ServerChannelMojo::Close() {
167 client_channel_.reset();
168 message_pipe_.reset();
169 ChannelMojo::Close();
172 #if defined(OS_POSIX) && !defined(OS_NACL)
174 base::ScopedFD TakeOrDupFile(internal::PlatformFileAttachment* attachment) {
175 return attachment->Owns() ? base::ScopedFD(attachment->TakePlatformFile())
176 : base::ScopedFD(dup(attachment->file()));
179 #endif
181 } // namespace
183 //------------------------------------------------------------------------------
185 void ChannelMojo::ChannelInfoDeleter::operator()(
186 mojo::embedder::ChannelInfo* ptr) const {
187 mojo::embedder::DestroyChannel(ptr, base::Bind(&base::DoNothing), nullptr);
190 //------------------------------------------------------------------------------
192 // static
193 bool ChannelMojo::ShouldBeUsed() {
194 // TODO(morrita): Remove this if it sticks.
195 // ChannelMojo is currently disabled due to http://crbug.com/466814.
196 return false;
199 // static
200 scoped_ptr<ChannelMojo> ChannelMojo::Create(ChannelMojo::Delegate* delegate,
201 const ChannelHandle& channel_handle,
202 Mode mode,
203 Listener* listener) {
204 switch (mode) {
205 case Channel::MODE_CLIENT:
206 return make_scoped_ptr(
207 new ClientChannelMojo(delegate, channel_handle, listener));
208 case Channel::MODE_SERVER:
209 return make_scoped_ptr(
210 new ServerChannelMojo(delegate, channel_handle, listener));
211 default:
212 NOTREACHED();
213 return nullptr;
217 // static
218 scoped_ptr<ChannelFactory> ChannelMojo::CreateServerFactory(
219 ChannelMojo::Delegate* delegate,
220 const ChannelHandle& channel_handle) {
221 return make_scoped_ptr(
222 new MojoChannelFactory(delegate, channel_handle, Channel::MODE_SERVER));
225 // static
226 scoped_ptr<ChannelFactory> ChannelMojo::CreateClientFactory(
227 ChannelMojo::Delegate* delegate,
228 const ChannelHandle& channel_handle) {
229 return make_scoped_ptr(
230 new MojoChannelFactory(delegate, channel_handle, Channel::MODE_CLIENT));
233 ChannelMojo::ChannelMojo(ChannelMojo::Delegate* delegate,
234 const ChannelHandle& handle,
235 Mode mode,
236 Listener* listener)
237 : mode_(mode),
238 listener_(listener),
239 peer_pid_(base::kNullProcessId),
240 weak_factory_(this) {
241 // Create MojoBootstrap after all members are set as it touches
242 // ChannelMojo from a different thread.
243 bootstrap_ = MojoBootstrap::Create(handle, mode, this);
244 if (delegate) {
245 if (delegate->GetIOTaskRunner() ==
246 base::MessageLoop::current()->message_loop_proxy()) {
247 InitDelegate(delegate);
248 } else {
249 delegate->GetIOTaskRunner()->PostTask(
250 FROM_HERE,
251 base::Bind(
252 &ChannelMojo::InitDelegate, base::Unretained(this), delegate));
257 ChannelMojo::~ChannelMojo() {
258 Close();
261 void ChannelMojo::InitDelegate(ChannelMojo::Delegate* delegate) {
262 ipc_support_.reset(
263 new ScopedIPCSupport(base::MessageLoop::current()->task_runner()));
264 delegate_ = delegate->ToWeakPtr();
265 delegate_->OnChannelCreated(weak_factory_.GetWeakPtr());
268 mojo::ScopedMessagePipeHandle ChannelMojo::CreateMessagingPipe(
269 mojo::embedder::ScopedPlatformHandle handle) {
270 DCHECK(!channel_info_.get());
271 mojo::embedder::ChannelInfo* channel_info;
272 mojo::ScopedMessagePipeHandle pipe =
273 mojo::embedder::CreateChannelOnIOThread(handle.Pass(), &channel_info);
274 channel_info_.reset(channel_info);
275 return pipe.Pass();
278 bool ChannelMojo::Connect() {
279 DCHECK(!message_reader_);
280 return bootstrap_->Connect();
283 void ChannelMojo::Close() {
284 message_reader_.reset();
285 channel_info_.reset();
286 ipc_support_.reset();
289 void ChannelMojo::OnBootstrapError() {
290 listener_->OnChannelError();
293 void ChannelMojo::InitMessageReader(mojo::ScopedMessagePipeHandle pipe,
294 int32_t peer_pid) {
295 message_reader_ =
296 make_scoped_ptr(new internal::MessagePipeReader(pipe.Pass(), this));
298 for (size_t i = 0; i < pending_messages_.size(); ++i) {
299 bool sent = message_reader_->Send(make_scoped_ptr(pending_messages_[i]));
300 pending_messages_[i] = nullptr;
301 if (!sent) {
302 pending_messages_.clear();
303 listener_->OnChannelError();
304 return;
308 pending_messages_.clear();
310 set_peer_pid(peer_pid);
311 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID()));
312 if (message_reader_)
313 message_reader_->ReadMessagesThenWait();
316 void ChannelMojo::OnPipeClosed(internal::MessagePipeReader* reader) {
317 Close();
320 void ChannelMojo::OnPipeError(internal::MessagePipeReader* reader) {
321 listener_->OnChannelError();
325 bool ChannelMojo::Send(Message* message) {
326 if (!message_reader_) {
327 pending_messages_.push_back(message);
328 return true;
331 return message_reader_->Send(make_scoped_ptr(message));
334 base::ProcessId ChannelMojo::GetPeerPID() const {
335 return peer_pid_;
338 base::ProcessId ChannelMojo::GetSelfPID() const {
339 return bootstrap_->GetSelfPID();
342 void ChannelMojo::OnClientLaunched(base::ProcessHandle handle) {
343 bootstrap_->OnClientLaunched(handle);
346 void ChannelMojo::OnMessageReceived(Message& message) {
347 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived",
348 "class", IPC_MESSAGE_ID_CLASS(message.type()),
349 "line", IPC_MESSAGE_ID_LINE(message.type()));
350 listener_->OnMessageReceived(message);
351 if (message.dispatch_error())
352 listener_->OnBadMessageReceived(message);
355 #if defined(OS_POSIX) && !defined(OS_NACL)
356 int ChannelMojo::GetClientFileDescriptor() const {
357 return bootstrap_->GetClientFileDescriptor();
360 base::ScopedFD ChannelMojo::TakeClientFileDescriptor() {
361 return bootstrap_->TakeClientFileDescriptor();
363 #endif // defined(OS_POSIX) && !defined(OS_NACL)
365 // static
366 MojoResult ChannelMojo::ReadFromMessageAttachmentSet(
367 Message* message,
368 std::vector<MojoHandle>* handles) {
369 // We dup() the handles in IPC::Message to transmit.
370 // IPC::MessageAttachmentSet has intricate lifecycle semantics
371 // of FDs, so just to dup()-and-own them is the safest option.
372 if (message->HasAttachments()) {
373 MessageAttachmentSet* set = message->attachment_set();
374 for (unsigned i = 0; i < set->size(); ++i) {
375 scoped_refptr<MessageAttachment> attachment = set->GetAttachmentAt(i);
376 switch (attachment->GetType()) {
377 case MessageAttachment::TYPE_PLATFORM_FILE:
378 #if defined(OS_POSIX) && !defined(OS_NACL)
380 base::ScopedFD file =
381 TakeOrDupFile(static_cast<IPC::internal::PlatformFileAttachment*>(
382 attachment.get()));
383 if (!file.is_valid()) {
384 DPLOG(WARNING) << "Failed to dup FD to transmit.";
385 set->CommitAll();
386 return MOJO_RESULT_UNKNOWN;
389 MojoHandle wrapped_handle;
390 MojoResult wrap_result = CreatePlatformHandleWrapper(
391 mojo::embedder::ScopedPlatformHandle(
392 mojo::embedder::PlatformHandle(file.release())),
393 &wrapped_handle);
394 if (MOJO_RESULT_OK != wrap_result) {
395 LOG(WARNING) << "Pipe failed to wrap handles. Closing: "
396 << wrap_result;
397 set->CommitAll();
398 return wrap_result;
401 handles->push_back(wrapped_handle);
403 #else
404 NOTREACHED();
405 #endif // defined(OS_POSIX) && !defined(OS_NACL)
406 break;
407 case MessageAttachment::TYPE_MOJO_HANDLE: {
408 mojo::ScopedHandle handle =
409 static_cast<IPC::internal::MojoHandleAttachment*>(
410 attachment.get())->TakeHandle();
411 handles->push_back(handle.release().value());
412 } break;
416 set->CommitAll();
419 return MOJO_RESULT_OK;
422 // static
423 MojoResult ChannelMojo::WriteToMessageAttachmentSet(
424 const std::vector<MojoHandle>& handle_buffer,
425 Message* message) {
426 for (size_t i = 0; i < handle_buffer.size(); ++i) {
427 bool ok = message->attachment_set()->AddAttachment(
428 new IPC::internal::MojoHandleAttachment(
429 mojo::MakeScopedHandle(mojo::Handle(handle_buffer[i]))));
430 DCHECK(ok);
431 if (!ok) {
432 LOG(ERROR) << "Failed to add new Mojo handle.";
433 return MOJO_RESULT_UNKNOWN;
437 return MOJO_RESULT_OK;
440 } // namespace IPC