OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ipc/ipc_channel_mojo.h" | 5 #include "ipc/ipc_channel_mojo.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
11 #include <utility> | 11 #include <utility> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
16 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" |
17 #include "base/macros.h" | 17 #include "base/macros.h" |
18 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
| 19 #include "base/process/process_handle.h" |
19 #include "base/threading/thread_task_runner_handle.h" | 20 #include "base/threading/thread_task_runner_handle.h" |
20 #include "build/build_config.h" | 21 #include "build/build_config.h" |
21 #include "ipc/ipc_listener.h" | 22 #include "ipc/ipc_listener.h" |
22 #include "ipc/ipc_logging.h" | 23 #include "ipc/ipc_logging.h" |
23 #include "ipc/ipc_message_attachment_set.h" | 24 #include "ipc/ipc_message_attachment_set.h" |
24 #include "ipc/ipc_message_macros.h" | 25 #include "ipc/ipc_message_macros.h" |
25 #include "ipc/ipc_mojo_bootstrap.h" | 26 #include "ipc/ipc_mojo_bootstrap.h" |
26 #include "ipc/ipc_mojo_handle_attachment.h" | 27 #include "ipc/ipc_mojo_handle_attachment.h" |
27 #include "mojo/public/cpp/bindings/binding.h" | 28 #include "mojo/public/cpp/bindings/binding.h" |
28 #include "mojo/public/cpp/system/platform_handle.h" | 29 #include "mojo/public/cpp/system/platform_handle.h" |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) { | 263 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) { |
263 return base::WrapUnique(new MojoChannelFactory( | 264 return base::WrapUnique(new MojoChannelFactory( |
264 std::move(handle), Channel::MODE_CLIENT, ipc_task_runner)); | 265 std::move(handle), Channel::MODE_CLIENT, ipc_task_runner)); |
265 } | 266 } |
266 | 267 |
267 ChannelMojo::ChannelMojo( | 268 ChannelMojo::ChannelMojo( |
268 mojo::ScopedMessagePipeHandle handle, | 269 mojo::ScopedMessagePipeHandle handle, |
269 Mode mode, | 270 Mode mode, |
270 Listener* listener, | 271 Listener* listener, |
271 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) | 272 const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner) |
272 : pipe_(handle.get()), | 273 : pipe_(handle.get()), listener_(listener), weak_factory_(this) { |
273 listener_(listener), | |
274 waiting_connect_(true), | |
275 weak_factory_(this) { | |
276 // Create MojoBootstrap after all members are set as it touches | 274 // Create MojoBootstrap after all members are set as it touches |
277 // ChannelMojo from a different thread. | 275 // ChannelMojo from a different thread. |
278 bootstrap_ = MojoBootstrap::Create(std::move(handle), mode, this); | 276 bootstrap_ = |
| 277 MojoBootstrap::Create(std::move(handle), mode, this, ipc_task_runner); |
279 } | 278 } |
280 | 279 |
281 ChannelMojo::~ChannelMojo() { | 280 ChannelMojo::~ChannelMojo() { |
282 Close(); | 281 Close(); |
283 } | 282 } |
284 | 283 |
285 bool ChannelMojo::Connect() { | 284 bool ChannelMojo::Connect() { |
286 WillConnect(); | 285 WillConnect(); |
287 { | 286 |
288 base::AutoLock lock(lock_); | 287 DCHECK(!task_runner_); |
289 DCHECK(!task_runner_); | 288 task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
290 task_runner_ = base::ThreadTaskRunnerHandle::Get(); | 289 DCHECK(!message_reader_); |
291 DCHECK(!message_reader_); | 290 |
292 } | |
293 bootstrap_->Connect(); | 291 bootstrap_->Connect(); |
294 return true; | 292 return true; |
295 } | 293 } |
296 | 294 |
297 void ChannelMojo::Close() { | 295 void ChannelMojo::Close() { |
298 std::unique_ptr<internal::MessagePipeReader, ReaderDeleter> reader; | 296 // NOTE: The MessagePipeReader's destructor may re-enter this function. Use |
299 { | 297 // caution when changing this method. |
300 base::AutoLock lock(lock_); | 298 std::unique_ptr<internal::MessagePipeReader> reader = |
301 if (!message_reader_) | 299 std::move(message_reader_); |
302 return; | 300 reader.reset(); |
303 // The reader's destructor may re-enter Close, so we swap it out first to | |
304 // avoid deadlock when freeing it below. | |
305 std::swap(message_reader_, reader); | |
306 | 301 |
307 // We might Close() before we Connect(). | 302 base::AutoLock lock(associated_interface_lock_); |
308 waiting_connect_ = false; | 303 associated_interfaces_.clear(); |
309 } | |
310 | |
311 reader.reset(); | |
312 } | 304 } |
313 | 305 |
314 // MojoBootstrap::Delegate implementation | 306 // MojoBootstrap::Delegate implementation |
315 void ChannelMojo::OnPipesAvailable( | 307 void ChannelMojo::OnPipesAvailable(mojom::ChannelAssociatedPtr sender, |
316 mojom::ChannelAssociatedPtrInfo send_channel, | 308 mojom::ChannelAssociatedRequest receiver) { |
317 mojom::ChannelAssociatedRequest receive_channel, | 309 sender->SetPeerPid(GetSelfPID()); |
318 int32_t peer_pid) { | 310 message_reader_.reset(new internal::MessagePipeReader( |
319 InitMessageReader(std::move(send_channel), std::move(receive_channel), | 311 pipe_, std::move(sender), std::move(receiver), this)); |
320 peer_pid); | |
321 } | |
322 | |
323 void ChannelMojo::OnBootstrapError() { | |
324 listener_->OnChannelError(); | |
325 } | |
326 | |
327 void ChannelMojo::OnAssociatedInterfaceRequest( | |
328 const std::string& name, | |
329 mojo::ScopedInterfaceEndpointHandle handle) { | |
330 auto iter = associated_interfaces_.find(name); | |
331 if (iter != associated_interfaces_.end()) | |
332 iter->second.Run(std::move(handle)); | |
333 } | |
334 | |
335 void ChannelMojo::InitMessageReader(mojom::ChannelAssociatedPtrInfo sender, | |
336 mojom::ChannelAssociatedRequest receiver, | |
337 base::ProcessId peer_pid) { | |
338 mojom::ChannelAssociatedPtr sender_ptr; | |
339 sender_ptr.Bind(std::move(sender)); | |
340 std::unique_ptr<internal::MessagePipeReader, ChannelMojo::ReaderDeleter> | |
341 reader(new internal::MessagePipeReader( | |
342 pipe_, std::move(sender_ptr), std::move(receiver), peer_pid, this)); | |
343 | |
344 bool connected = true; | |
345 { | |
346 base::AutoLock lock(lock_); | |
347 for (size_t i = 0; i < pending_messages_.size(); ++i) { | |
348 if (!reader->Send(std::move(pending_messages_[i]))) { | |
349 LOG(ERROR) << "Failed to flush pending messages"; | |
350 pending_messages_.clear(); | |
351 connected = false; | |
352 break; | |
353 } | |
354 } | |
355 | |
356 if (connected) { | |
357 // We set |message_reader_| here and won't get any |pending_messages_| | |
358 // hereafter. Although we might have some if there is an error, we don't | |
359 // care. They cannot be sent anyway. | |
360 message_reader_ = std::move(reader); | |
361 pending_messages_.clear(); | |
362 waiting_connect_ = false; | |
363 } | |
364 } | |
365 | |
366 if (connected) | |
367 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID())); | |
368 else | |
369 OnPipeError(); | |
370 } | 312 } |
371 | 313 |
372 void ChannelMojo::OnPipeError() { | 314 void ChannelMojo::OnPipeError() { |
373 DCHECK(task_runner_); | 315 DCHECK(task_runner_); |
374 if (task_runner_->RunsTasksOnCurrentThread()) { | 316 if (task_runner_->RunsTasksOnCurrentThread()) { |
375 listener_->OnChannelError(); | 317 listener_->OnChannelError(); |
376 } else { | 318 } else { |
377 task_runner_->PostTask( | 319 task_runner_->PostTask( |
378 FROM_HERE, | 320 FROM_HERE, |
379 base::Bind(&ChannelMojo::OnPipeError, weak_factory_.GetWeakPtr())); | 321 base::Bind(&ChannelMojo::OnPipeError, weak_factory_.GetWeakPtr())); |
380 } | 322 } |
381 } | 323 } |
382 | 324 |
| 325 void ChannelMojo::OnAssociatedInterfaceRequest( |
| 326 const std::string& name, |
| 327 mojo::ScopedInterfaceEndpointHandle handle) { |
| 328 GenericAssociatedInterfaceFactory factory; |
| 329 { |
| 330 base::AutoLock locker(associated_interface_lock_); |
| 331 auto iter = associated_interfaces_.find(name); |
| 332 if (iter != associated_interfaces_.end()) |
| 333 factory = iter->second; |
| 334 } |
| 335 |
| 336 if (!factory.is_null()) |
| 337 factory.Run(std::move(handle)); |
| 338 } |
| 339 |
383 bool ChannelMojo::Send(Message* message) { | 340 bool ChannelMojo::Send(Message* message) { |
384 base::AutoLock lock(lock_); | 341 std::unique_ptr<Message> scoped_message = base::WrapUnique(message); |
385 if (!message_reader_) { | 342 if (!message_reader_) |
386 pending_messages_.push_back(base::WrapUnique(message)); | 343 return false; |
387 // Counts as OK before the connection is established, but it's an | |
388 // error otherwise. | |
389 return waiting_connect_; | |
390 } | |
391 | 344 |
392 // Comment copied from ipc_channel_posix.cc: | 345 // Comment copied from ipc_channel_posix.cc: |
393 // We can't close the pipe here, because calling OnChannelError may destroy | 346 // We can't close the pipe here, because calling OnChannelError may destroy |
394 // this object, and that would be bad if we are called from Send(). Instead, | 347 // this object, and that would be bad if we are called from Send(). Instead, |
395 // we return false and hope the caller will close the pipe. If they do not, | 348 // we return false and hope the caller will close the pipe. If they do not, |
396 // the pipe will still be closed next time OnFileCanReadWithoutBlocking is | 349 // the pipe will still be closed next time OnFileCanReadWithoutBlocking is |
397 // called. | 350 // called. |
398 // | 351 // |
399 // With Mojo, there's no OnFileCanReadWithoutBlocking, but we expect the | 352 // With Mojo, there's no OnFileCanReadWithoutBlocking, but we expect the |
400 // pipe's connection error handler will be invoked in its place. | 353 // pipe's connection error handler will be invoked in its place. |
401 return message_reader_->Send(base::WrapUnique(message)); | 354 return message_reader_->Send(std::move(scoped_message)); |
402 } | 355 } |
403 | 356 |
404 bool ChannelMojo::IsSendThreadSafe() const { | 357 bool ChannelMojo::IsSendThreadSafe() const { |
405 return false; | 358 return false; |
406 } | 359 } |
407 | 360 |
408 base::ProcessId ChannelMojo::GetPeerPID() const { | 361 base::ProcessId ChannelMojo::GetPeerPID() const { |
409 base::AutoLock lock(lock_); | |
410 if (!message_reader_) | 362 if (!message_reader_) |
411 return base::kNullProcessId; | 363 return base::kNullProcessId; |
412 | |
413 return message_reader_->GetPeerPid(); | 364 return message_reader_->GetPeerPid(); |
414 } | 365 } |
415 | 366 |
416 base::ProcessId ChannelMojo::GetSelfPID() const { | 367 base::ProcessId ChannelMojo::GetSelfPID() const { |
417 return bootstrap_->GetSelfPID(); | 368 #if defined(OS_LINUX) |
| 369 if (int global_pid = GetGlobalPid()) |
| 370 return global_pid; |
| 371 #endif // OS_LINUX |
| 372 #if defined(OS_NACL) |
| 373 return -1; |
| 374 #else |
| 375 return base::GetCurrentProcId(); |
| 376 #endif // defined(OS_NACL) |
418 } | 377 } |
419 | 378 |
420 Channel::AssociatedInterfaceSupport* | 379 Channel::AssociatedInterfaceSupport* |
421 ChannelMojo::GetAssociatedInterfaceSupport() { return this; } | 380 ChannelMojo::GetAssociatedInterfaceSupport() { return this; } |
422 | 381 |
| 382 void ChannelMojo::OnPeerPidReceived() { |
| 383 listener_->OnChannelConnected(static_cast<int32_t>(GetPeerPID())); |
| 384 } |
| 385 |
423 void ChannelMojo::OnMessageReceived(const Message& message) { | 386 void ChannelMojo::OnMessageReceived(const Message& message) { |
424 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived", | 387 TRACE_EVENT2("ipc,toplevel", "ChannelMojo::OnMessageReceived", |
425 "class", IPC_MESSAGE_ID_CLASS(message.type()), | 388 "class", IPC_MESSAGE_ID_CLASS(message.type()), |
426 "line", IPC_MESSAGE_ID_LINE(message.type())); | 389 "line", IPC_MESSAGE_ID_LINE(message.type())); |
427 if (AttachmentBroker* broker = AttachmentBroker::GetGlobal()) { | 390 if (AttachmentBroker* broker = AttachmentBroker::GetGlobal()) { |
428 if (broker->OnMessageReceived(message)) | 391 if (broker->OnMessageReceived(message)) |
429 return; | 392 return; |
430 } | 393 } |
431 listener_->OnMessageReceived(message); | 394 listener_->OnMessageReceived(message); |
432 if (message.dispatch_error()) | 395 if (message.dispatch_error()) |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 } | 460 } |
498 | 461 |
499 mojo::AssociatedGroup* ChannelMojo::GetAssociatedGroup() { | 462 mojo::AssociatedGroup* ChannelMojo::GetAssociatedGroup() { |
500 DCHECK(bootstrap_); | 463 DCHECK(bootstrap_); |
501 return bootstrap_->GetAssociatedGroup(); | 464 return bootstrap_->GetAssociatedGroup(); |
502 } | 465 } |
503 | 466 |
504 void ChannelMojo::AddGenericAssociatedInterface( | 467 void ChannelMojo::AddGenericAssociatedInterface( |
505 const std::string& name, | 468 const std::string& name, |
506 const GenericAssociatedInterfaceFactory& factory) { | 469 const GenericAssociatedInterfaceFactory& factory) { |
| 470 base::AutoLock locker(associated_interface_lock_); |
507 auto result = associated_interfaces_.insert({ name, factory }); | 471 auto result = associated_interfaces_.insert({ name, factory }); |
508 DCHECK(result.second); | 472 DCHECK(result.second); |
509 } | 473 } |
510 | 474 |
511 void ChannelMojo::GetGenericRemoteAssociatedInterface( | 475 void ChannelMojo::GetGenericRemoteAssociatedInterface( |
512 const std::string& name, | 476 const std::string& name, |
513 mojo::ScopedInterfaceEndpointHandle handle) { | 477 mojo::ScopedInterfaceEndpointHandle handle) { |
514 DCHECK(message_reader_); | 478 if (message_reader_) |
515 message_reader_->GetRemoteInterface(name, std::move(handle)); | 479 message_reader_->GetRemoteInterface(name, std::move(handle)); |
516 } | |
517 | |
518 void ChannelMojo::SetProxyTaskRunner( | |
519 scoped_refptr<base::SingleThreadTaskRunner> task_runner) { | |
520 DCHECK(bootstrap_); | |
521 bootstrap_->SetProxyTaskRunner(task_runner); | |
522 } | 480 } |
523 | 481 |
524 } // namespace IPC | 482 } // namespace IPC |
OLD | NEW |