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