OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "mojo/public/cpp/bindings/lib/multiplex_router.h" | 5 #include "mojo/public/cpp/bindings/lib/multiplex_router.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 } | 104 } |
105 | 105 |
106 // --------------------------------------------------------------------------- | 106 // --------------------------------------------------------------------------- |
107 // The following public methods (i.e., InterfaceEndpointController | 107 // The following public methods (i.e., InterfaceEndpointController |
108 // implementation) are called by the client on the same thread as the | 108 // implementation) are called by the client on the same thread as the |
109 // AttachClient() call. They are called outside of the router's lock. | 109 // AttachClient() call. They are called outside of the router's lock. |
110 | 110 |
111 bool SendMessage(Message* message) override { | 111 bool SendMessage(Message* message) override { |
112 DCHECK(task_runner_->BelongsToCurrentThread()); | 112 DCHECK(task_runner_->BelongsToCurrentThread()); |
113 message->set_interface_id(id_); | 113 message->set_interface_id(id_); |
114 return router_->connector_.Accept(message); | 114 |
| 115 Error send_error; |
| 116 return router_->connector_.Accept(message, &send_error); |
115 } | 117 } |
116 | 118 |
117 void AllowWokenUpBySyncWatchOnSameThread() override { | 119 void AllowWokenUpBySyncWatchOnSameThread() override { |
118 DCHECK(task_runner_->BelongsToCurrentThread()); | 120 DCHECK(task_runner_->BelongsToCurrentThread()); |
119 | 121 |
120 EnsureSyncWatcherExists(); | 122 EnsureSyncWatcherExists(); |
121 sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); | 123 sync_watcher_->AllowWokenUpBySyncWatchOnSameThread(); |
122 } | 124 } |
123 | 125 |
124 bool SyncWatch(const bool* should_stop) override { | 126 bool SyncWatch(const bool* should_stop) override { |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 | 425 |
424 DCHECK(IsValidInterfaceId(id)); | 426 DCHECK(IsValidInterfaceId(id)); |
425 | 427 |
426 base::AutoLock locker(lock_); | 428 base::AutoLock locker(lock_); |
427 DCHECK(ContainsKey(endpoints_, id)); | 429 DCHECK(ContainsKey(endpoints_, id)); |
428 | 430 |
429 InterfaceEndpoint* endpoint = endpoints_[id].get(); | 431 InterfaceEndpoint* endpoint = endpoints_[id].get(); |
430 endpoint->DetachClient(); | 432 endpoint->DetachClient(); |
431 } | 433 } |
432 | 434 |
433 void MultiplexRouter::RaiseError() { | 435 void MultiplexRouter::RaiseError(Error error) { |
434 if (task_runner_->BelongsToCurrentThread()) { | 436 if (task_runner_->BelongsToCurrentThread()) { |
435 connector_.RaiseError(); | 437 connector_.RaiseError(std::move(error)); |
436 } else { | 438 } else { |
437 task_runner_->PostTask(FROM_HERE, | 439 task_runner_->PostTask(FROM_HERE, |
438 base::Bind(&MultiplexRouter::RaiseError, this)); | 440 base::Bind(&MultiplexRouter::RaiseError, this, |
| 441 base::Passed(&error))); |
439 } | 442 } |
440 } | 443 } |
441 | 444 |
442 std::unique_ptr<AssociatedGroup> MultiplexRouter::CreateAssociatedGroup() { | 445 std::unique_ptr<AssociatedGroup> MultiplexRouter::CreateAssociatedGroup() { |
443 std::unique_ptr<AssociatedGroup> group(new AssociatedGroup); | 446 std::unique_ptr<AssociatedGroup> group(new AssociatedGroup); |
444 group->router_ = this; | 447 group->router_ = this; |
445 return group; | 448 return group; |
446 } | 449 } |
447 | 450 |
448 // static | 451 // static |
(...skipping 15 matching lines...) Expand all Loading... |
464 base::AutoLock locker(lock_); | 467 base::AutoLock locker(lock_); |
465 | 468 |
466 if (endpoints_.size() > 1) | 469 if (endpoints_.size() > 1) |
467 return true; | 470 return true; |
468 if (endpoints_.size() == 0) | 471 if (endpoints_.size() == 0) |
469 return false; | 472 return false; |
470 | 473 |
471 return !ContainsKey(endpoints_, kMasterInterfaceId); | 474 return !ContainsKey(endpoints_, kMasterInterfaceId); |
472 } | 475 } |
473 | 476 |
| 477 void MultiplexRouter::SetMasterInterfaceName(const std::string& name) { |
| 478 DCHECK(thread_checker_.CalledOnValidThread()); |
| 479 master_interface_name_ = name; |
| 480 header_validator_.set_debug_info(name + " master interface header validator"); |
| 481 } |
| 482 |
474 void MultiplexRouter::EnableTestingMode() { | 483 void MultiplexRouter::EnableTestingMode() { |
475 DCHECK(thread_checker_.CalledOnValidThread()); | 484 DCHECK(thread_checker_.CalledOnValidThread()); |
476 base::AutoLock locker(lock_); | 485 base::AutoLock locker(lock_); |
477 | 486 |
478 testing_mode_ = true; | 487 testing_mode_ = true; |
479 connector_.set_enforce_errors_from_incoming_receiver(false); | 488 connector_.set_enforce_errors_from_incoming_receiver(false); |
480 } | 489 } |
481 | 490 |
482 bool MultiplexRouter::Accept(Message* message) { | 491 bool MultiplexRouter::Accept(Message* message, Error* error) { |
483 DCHECK(thread_checker_.CalledOnValidThread()); | 492 DCHECK(thread_checker_.CalledOnValidThread()); |
484 | 493 |
485 scoped_refptr<MultiplexRouter> protector(this); | 494 scoped_refptr<MultiplexRouter> protector(this); |
486 base::AutoLock locker(lock_); | 495 base::AutoLock locker(lock_); |
487 | 496 |
488 ClientCallBehavior client_call_behavior = | 497 ClientCallBehavior client_call_behavior = |
489 connector_.during_sync_handle_watcher_callback() | 498 connector_.during_sync_handle_watcher_callback() |
490 ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES | 499 ? ALLOW_DIRECT_CLIENT_CALLS_FOR_SYNC_MESSAGES |
491 : ALLOW_DIRECT_CLIENT_CALLS; | 500 : ALLOW_DIRECT_CLIENT_CALLS; |
492 | 501 |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
699 DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); | 708 DCHECK(!current_task_runner || current_task_runner->BelongsToCurrentThread()); |
700 lock_.AssertAcquired(); | 709 lock_.AssertAcquired(); |
701 | 710 |
702 if (!message) { | 711 if (!message) { |
703 // This is a sync message and has been processed during sync handle | 712 // This is a sync message and has been processed during sync handle |
704 // watching. | 713 // watching. |
705 return true; | 714 return true; |
706 } | 715 } |
707 | 716 |
708 if (PipeControlMessageHandler::IsPipeControlMessage(message)) { | 717 if (PipeControlMessageHandler::IsPipeControlMessage(message)) { |
709 if (!control_message_handler_.Accept(message)) | 718 Error error; |
710 RaiseErrorInNonTestingMode(); | 719 if (!control_message_handler_.Accept(message, &error)) |
| 720 RaiseErrorInNonTestingMode(std::move(error)); |
711 return true; | 721 return true; |
712 } | 722 } |
713 | 723 |
714 InterfaceId id = message->interface_id(); | 724 InterfaceId id = message->interface_id(); |
715 DCHECK(IsValidInterfaceId(id)); | 725 DCHECK(IsValidInterfaceId(id)); |
716 | 726 |
717 bool inserted = false; | 727 bool inserted = false; |
718 InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); | 728 InterfaceEndpoint* endpoint = FindOrInsertEndpoint(id, &inserted); |
719 if (inserted) { | 729 if (inserted) { |
720 // Currently, it is legitimate to receive messages for an endpoint | 730 // Currently, it is legitimate to receive messages for an endpoint |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 } | 766 } |
757 | 767 |
758 if (!can_direct_call) { | 768 if (!can_direct_call) { |
759 MaybePostToProcessTasks(endpoint->task_runner()); | 769 MaybePostToProcessTasks(endpoint->task_runner()); |
760 return false; | 770 return false; |
761 } | 771 } |
762 | 772 |
763 DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); | 773 DCHECK(endpoint->task_runner()->BelongsToCurrentThread()); |
764 | 774 |
765 InterfaceEndpointClient* client = endpoint->client(); | 775 InterfaceEndpointClient* client = endpoint->client(); |
| 776 Error error(Error::Type::NONE); |
766 bool result = false; | 777 bool result = false; |
767 { | 778 { |
768 // We must unlock before calling into |client| because it may call this | 779 // We must unlock before calling into |client| because it may call this |
769 // object within HandleIncomingMessage(). Holding the lock will lead to | 780 // object within HandleIncomingMessage(). Holding the lock will lead to |
770 // deadlock. | 781 // deadlock. |
771 // | 782 // |
772 // It is safe to call into |client| without the lock. Because |client| is | 783 // It is safe to call into |client| without the lock. Because |client| is |
773 // always accessed on the same thread, including DetachEndpointClient(). | 784 // always accessed on the same thread, including DetachEndpointClient(). |
774 base::AutoUnlock unlocker(lock_); | 785 base::AutoUnlock unlocker(lock_); |
775 result = client->HandleIncomingMessage(message); | 786 result = client->HandleIncomingMessage(message, &error); |
776 } | 787 } |
777 if (!result) | 788 if (!result) |
778 RaiseErrorInNonTestingMode(); | 789 RaiseErrorInNonTestingMode(std::move(error)); |
779 | 790 |
780 return true; | 791 return true; |
781 } | 792 } |
782 | 793 |
783 void MultiplexRouter::MaybePostToProcessTasks( | 794 void MultiplexRouter::MaybePostToProcessTasks( |
784 base::SingleThreadTaskRunner* task_runner) { | 795 base::SingleThreadTaskRunner* task_runner) { |
785 lock_.AssertAcquired(); | 796 lock_.AssertAcquired(); |
786 if (posted_to_process_tasks_) | 797 if (posted_to_process_tasks_) |
787 return; | 798 return; |
788 | 799 |
(...skipping 24 matching lines...) Expand all Loading... |
813 endpoint->set_peer_closed(); | 824 endpoint->set_peer_closed(); |
814 // If the interface endpoint is performing a sync watch, this makes sure | 825 // If the interface endpoint is performing a sync watch, this makes sure |
815 // it is notified and eventually exits the sync watch. | 826 // it is notified and eventually exits the sync watch. |
816 endpoint->SignalSyncMessageEvent(); | 827 endpoint->SignalSyncMessageEvent(); |
817 break; | 828 break; |
818 } | 829 } |
819 if (endpoint->closed() && endpoint->peer_closed()) | 830 if (endpoint->closed() && endpoint->peer_closed()) |
820 endpoints_.erase(endpoint->id()); | 831 endpoints_.erase(endpoint->id()); |
821 } | 832 } |
822 | 833 |
823 void MultiplexRouter::RaiseErrorInNonTestingMode() { | 834 void MultiplexRouter::RaiseErrorInNonTestingMode(Error error) { |
824 lock_.AssertAcquired(); | 835 lock_.AssertAcquired(); |
825 if (!testing_mode_) | 836 if (!testing_mode_) |
826 RaiseError(); | 837 RaiseError(std::move(error)); |
827 } | 838 } |
828 | 839 |
829 MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindOrInsertEndpoint( | 840 MultiplexRouter::InterfaceEndpoint* MultiplexRouter::FindOrInsertEndpoint( |
830 InterfaceId id, | 841 InterfaceId id, |
831 bool* inserted) { | 842 bool* inserted) { |
832 lock_.AssertAcquired(); | 843 lock_.AssertAcquired(); |
833 // Either |inserted| is nullptr or it points to a boolean initialized as | 844 // Either |inserted| is nullptr or it points to a boolean initialized as |
834 // false. | 845 // false. |
835 DCHECK(!inserted || !*inserted); | 846 DCHECK(!inserted || !*inserted); |
836 | 847 |
837 auto iter = endpoints_.find(id); | 848 auto iter = endpoints_.find(id); |
838 InterfaceEndpoint* endpoint; | 849 InterfaceEndpoint* endpoint; |
839 if (iter == endpoints_.end()) { | 850 if (iter == endpoints_.end()) { |
840 endpoint = new InterfaceEndpoint(this, id); | 851 endpoint = new InterfaceEndpoint(this, id); |
841 endpoints_[id] = endpoint; | 852 endpoints_[id] = endpoint; |
842 if (inserted) | 853 if (inserted) |
843 *inserted = true; | 854 *inserted = true; |
844 } else { | 855 } else { |
845 endpoint = iter->second.get(); | 856 endpoint = iter->second.get(); |
846 } | 857 } |
847 | 858 |
848 return endpoint; | 859 return endpoint; |
849 } | 860 } |
850 | 861 |
851 } // namespace internal | 862 } // namespace internal |
852 } // namespace mojo | 863 } // namespace mojo |
OLD | NEW |