Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(214)

Side by Side Diff: mojo/edk/system/node_controller.cc

Issue 1712143002: [mojo-edk] Add support for transferring mach ports. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix build Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/edk/system/node_controller.h ('k') | mojo/edk/test/mojo_test_base.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/edk/system/node_controller.h" 5 #include "mojo/edk/system/node_controller.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/message_loop/message_loop.h" 14 #include "base/message_loop/message_loop.h"
15 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
16 #include "base/process/process_handle.h" 16 #include "base/process/process_handle.h"
17 #include "crypto/random.h" 17 #include "crypto/random.h"
18 #include "mojo/edk/embedder/embedder_internal.h" 18 #include "mojo/edk/embedder/embedder_internal.h"
19 #include "mojo/edk/embedder/platform_channel_pair.h" 19 #include "mojo/edk/embedder/platform_channel_pair.h"
20 #include "mojo/edk/system/broker.h" 20 #include "mojo/edk/system/broker.h"
21 #include "mojo/edk/system/broker_host.h" 21 #include "mojo/edk/system/broker_host.h"
22 #include "mojo/edk/system/core.h" 22 #include "mojo/edk/system/core.h"
23 #include "mojo/edk/system/ports_message.h" 23 #include "mojo/edk/system/ports_message.h"
24 24
25 #if defined(OS_MACOSX) && !defined(OS_IOS)
26 #include "mojo/edk/system/mach_port_relay.h"
27 #endif
28
25 namespace mojo { 29 namespace mojo {
26 namespace edk { 30 namespace edk {
27 31
28 namespace { 32 namespace {
29 33
30 template <typename T> 34 template <typename T>
31 void GenerateRandomName(T* out) { crypto::RandBytes(out, sizeof(T)); } 35 void GenerateRandomName(T* out) { crypto::RandBytes(out, sizeof(T)); }
32 36
33 ports::NodeName GetRandomNodeName() { 37 ports::NodeName GetRandomNodeName() {
34 ports::NodeName name; 38 ports::NodeName name;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 104
101 NodeController::~NodeController() {} 105 NodeController::~NodeController() {}
102 106
103 NodeController::NodeController(Core* core) 107 NodeController::NodeController(Core* core)
104 : core_(core), 108 : core_(core),
105 name_(GetRandomNodeName()), 109 name_(GetRandomNodeName()),
106 node_(new ports::Node(name_, this)) { 110 node_(new ports::Node(name_, this)) {
107 DVLOG(1) << "Initializing node " << name_; 111 DVLOG(1) << "Initializing node " << name_;
108 } 112 }
109 113
114 #if defined(OS_MACOSX) && !defined(OS_IOS)
115 void NodeController::CreateMachPortRelay(
116 base::PortProvider* port_provider) {
117 base::AutoLock lock(mach_port_relay_lock_);
118 DCHECK(!mach_port_relay_);
119 mach_port_relay_.reset(new MachPortRelay(port_provider));
120 }
121 #endif
122
110 void NodeController::SetIOTaskRunner( 123 void NodeController::SetIOTaskRunner(
111 scoped_refptr<base::TaskRunner> task_runner) { 124 scoped_refptr<base::TaskRunner> task_runner) {
112 io_task_runner_ = task_runner; 125 io_task_runner_ = task_runner;
113 ThreadDestructionObserver::Create( 126 ThreadDestructionObserver::Create(
114 io_task_runner_, 127 io_task_runner_,
115 base::Bind(&NodeController::DropAllPeers, base::Unretained(this))); 128 base::Bind(&NodeController::DropAllPeers, base::Unretained(this)));
116 } 129 }
117 130
118 void NodeController::ConnectToChild(base::ProcessHandle process_handle, 131 void NodeController::ConnectToChild(base::ProcessHandle process_handle,
119 ScopedPlatformHandle platform_handle) { 132 ScopedPlatformHandle platform_handle) {
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 channel->SetRemoteProcessHandle(process_handle); 284 channel->SetRemoteProcessHandle(process_handle);
272 channel->Start(); 285 channel->Start();
273 286
274 channel->AcceptChild(name_, token); 287 channel->AcceptChild(name_, token);
275 } 288 }
276 289
277 void NodeController::ConnectToParentOnIOThread( 290 void NodeController::ConnectToParentOnIOThread(
278 ScopedPlatformHandle platform_handle) { 291 ScopedPlatformHandle platform_handle) {
279 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); 292 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
280 293
281 base::AutoLock lock(parent_lock_); 294 {
282 DCHECK(parent_name_ == ports::kInvalidNodeName); 295 base::AutoLock lock(parent_lock_);
296 DCHECK(parent_name_ == ports::kInvalidNodeName);
283 297
284 // At this point we don't know the parent's name, so we can't yet insert it 298 // At this point we don't know the parent's name, so we can't yet insert it
285 // into our |peers_| map. That will happen as soon as we receive an 299 // into our |peers_| map. That will happen as soon as we receive an
286 // AcceptChild message from them. 300 // AcceptChild message from them.
287 bootstrap_parent_channel_ = 301 bootstrap_parent_channel_ =
288 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); 302 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_);
303 }
289 bootstrap_parent_channel_->Start(); 304 bootstrap_parent_channel_->Start();
290 } 305 }
291 306
292 scoped_refptr<NodeChannel> NodeController::GetPeerChannel( 307 scoped_refptr<NodeChannel> NodeController::GetPeerChannel(
293 const ports::NodeName& name) { 308 const ports::NodeName& name) {
294 base::AutoLock lock(peers_lock_); 309 base::AutoLock lock(peers_lock_);
295 auto it = peers_.find(name); 310 auto it = peers_.find(name);
296 if (it == peers_.end()) 311 if (it == peers_.end())
297 return nullptr; 312 return nullptr;
298 return it->second; 313 return it->second;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 if (!peer || !peer->HasRemoteProcessHandle()) { 414 if (!peer || !peer->HasRemoteProcessHandle()) {
400 if (broker) { 415 if (broker) {
401 broker->RelayPortsMessage(name, std::move(channel_message)); 416 broker->RelayPortsMessage(name, std::move(channel_message));
402 } else { 417 } else {
403 base::AutoLock lock(broker_lock_); 418 base::AutoLock lock(broker_lock_);
404 pending_relay_messages_[name].emplace(std::move(channel_message)); 419 pending_relay_messages_[name].emplace(std::move(channel_message));
405 } 420 }
406 return; 421 return;
407 } 422 }
408 } 423 }
409 #endif 424 #elif defined(OS_MACOSX) && !defined(OS_IOS)
425 if (channel_message->has_mach_ports()) {
426 // Messages containing Mach ports are always routed through the broker, even
427 // if the broker process is the intended recipient.
428 bool use_broker = false;
429 {
430 base::AutoLock lock(parent_lock_);
431 use_broker = (bootstrap_parent_channel_ ||
432 parent_name_ != ports::kInvalidNodeName);
433 }
434 if (use_broker) {
435 scoped_refptr<NodeChannel> broker = GetBrokerChannel();
436 if (broker) {
437 broker->RelayPortsMessage(name, std::move(channel_message));
438 } else {
439 base::AutoLock lock(broker_lock_);
440 pending_relay_messages_[name].emplace(std::move(channel_message));
441 }
442 return;
443 }
444 }
445 #endif // defined(OS_WIN)
410 446
411 if (peer) { 447 if (peer) {
412 peer->PortsMessage(std::move(channel_message)); 448 peer->PortsMessage(std::move(channel_message));
413 return; 449 return;
414 } 450 }
415 451
416 // If we don't know who the peer is, queue the message for delivery. If this 452 // If we don't know who the peer is, queue the message for delivery. If this
417 // is the first message queued for the peer, we also ask the broker to 453 // is the first message queued for the peer, we also ask the broker to
418 // introduce us to them. 454 // introduce us to them.
419 455
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 void NodeController::OnBrokerClientAdded(const ports::NodeName& from_node, 688 void NodeController::OnBrokerClientAdded(const ports::NodeName& from_node,
653 const ports::NodeName& client_name, 689 const ports::NodeName& client_name,
654 ScopedPlatformHandle broker_channel) { 690 ScopedPlatformHandle broker_channel) {
655 scoped_refptr<NodeChannel> client = GetPeerChannel(client_name); 691 scoped_refptr<NodeChannel> client = GetPeerChannel(client_name);
656 if (!client) { 692 if (!client) {
657 DLOG(ERROR) << "BrokerClientAdded for unknown child " << client_name; 693 DLOG(ERROR) << "BrokerClientAdded for unknown child " << client_name;
658 return; 694 return;
659 } 695 }
660 696
661 // This should have come from our own broker. 697 // This should have come from our own broker.
662 if(GetBrokerChannel() != GetPeerChannel(from_node)) { 698 if (GetBrokerChannel() != GetPeerChannel(from_node)) {
663 DLOG(ERROR) << "BrokerClientAdded from non-broker node " << from_node; 699 DLOG(ERROR) << "BrokerClientAdded from non-broker node " << from_node;
664 return; 700 return;
665 } 701 }
666 702
667 DVLOG(1) << "Child " << client_name << " accepted by broker " << from_node; 703 DVLOG(1) << "Child " << client_name << " accepted by broker " << from_node;
668 704
669 client->AcceptBrokerClient(from_node, std::move(broker_channel)); 705 client->AcceptBrokerClient(from_node, std::move(broker_channel));
670 } 706 }
671 707
672 void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node, 708 void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 756
721 // Feed the broker any pending children of our own. 757 // Feed the broker any pending children of our own.
722 while (!pending_broker_clients.empty()) { 758 while (!pending_broker_clients.empty()) {
723 const ports::NodeName& child_name = pending_broker_clients.front(); 759 const ports::NodeName& child_name = pending_broker_clients.front();
724 auto it = pending_children_.find(child_name); 760 auto it = pending_children_.find(child_name);
725 DCHECK(it != pending_children_.end()); 761 DCHECK(it != pending_children_.end());
726 broker->AddBrokerClient(child_name, it->second->CopyRemoteProcessHandle()); 762 broker->AddBrokerClient(child_name, it->second->CopyRemoteProcessHandle());
727 pending_broker_clients.pop(); 763 pending_broker_clients.pop();
728 } 764 }
729 765
730 #if defined(OS_WIN) 766 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
731 // Have the broker relay any messages we have waiting. 767 // Have the broker relay any messages we have waiting.
732 for (auto& entry : pending_relay_messages) { 768 for (auto& entry : pending_relay_messages) {
733 const ports::NodeName& destination = entry.first; 769 const ports::NodeName& destination = entry.first;
734 auto& message_queue = entry.second; 770 auto& message_queue = entry.second;
735 while (!message_queue.empty()) { 771 while (!message_queue.empty()) {
736 broker->RelayPortsMessage(destination, std::move(message_queue.front())); 772 broker->RelayPortsMessage(destination, std::move(message_queue.front()));
737 message_queue.pop(); 773 message_queue.pop();
738 } 774 }
739 } 775 }
740 #endif 776 #endif
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
829 return; 865 return;
830 } 866 }
831 867
832 scoped_refptr<NodeChannel> channel = 868 scoped_refptr<NodeChannel> channel =
833 NodeChannel::Create(this, std::move(channel_handle), io_task_runner_); 869 NodeChannel::Create(this, std::move(channel_handle), io_task_runner_);
834 870
835 DVLOG(1) << "Adding new peer " << name << " via parent introduction."; 871 DVLOG(1) << "Adding new peer " << name << " via parent introduction.";
836 AddPeer(name, channel, true /* start_channel */); 872 AddPeer(name, channel, true /* start_channel */);
837 } 873 }
838 874
839 #if defined(OS_WIN) 875 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
840 void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, 876 void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node,
841 base::ProcessHandle from_process, 877 base::ProcessHandle from_process,
842 const ports::NodeName& destination, 878 const ports::NodeName& destination,
843 Channel::MessagePtr message) { 879 Channel::MessagePtr message) {
880 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
881
844 if (GetBrokerChannel()) { 882 if (GetBrokerChannel()) {
845 // Only the broker should be asked to relay a message. 883 // Only the broker should be asked to relay a message.
846 LOG(ERROR) << "Non-broker refusing to relay message."; 884 LOG(ERROR) << "Non-broker refusing to relay message.";
847 DropPeer(from_node); 885 DropPeer(from_node);
848 return; 886 return;
849 } 887 }
850 888
851 // The parent should always know which process this came from. 889 // The parent should always know which process this came from.
852 DCHECK(from_process != base::kNullProcessHandle); 890 DCHECK(from_process != base::kNullProcessHandle);
853 891
892 #if defined(OS_WIN)
854 // Rewrite the handles to this (the parent) process. If the message is 893 // Rewrite the handles to this (the parent) process. If the message is
855 // destined for another child process, the handles will be rewritten to that 894 // destined for another child process, the handles will be rewritten to that
856 // process before going out (see NodeChannel::WriteChannelMessage). 895 // process before going out (see NodeChannel::WriteChannelMessage).
857 // 896 //
858 // TODO: We could avoid double-duplication. 897 // TODO: We could avoid double-duplication.
859 if (!Channel::Message::RewriteHandles(from_process, 898 if (!Channel::Message::RewriteHandles(from_process,
860 base::GetCurrentProcessHandle(), 899 base::GetCurrentProcessHandle(),
861 message->handles(), 900 message->handles(),
862 message->num_handles())) { 901 message->num_handles())) {
863 DLOG(ERROR) << "Failed to relay one or more handles."; 902 DLOG(ERROR) << "Failed to relay one or more handles.";
864 } 903 }
904 #else
905 MachPortRelay* relay = GetMachPortRelay();
906 if (!relay) {
907 LOG(ERROR) << "Receiving Mach ports without a port relay from "
908 << from_node << ". Dropping message.";
909 return;
910 }
911 if (!relay->ExtractPortRights(message.get(), from_process)) {
912 // NodeChannel should ensure that MachPortRelay is ready for the remote
913 // process. At this point, if the port extraction failed, either something
914 // went wrong in the mach stuff, or the remote process died.
915 LOG(ERROR) << "Error on receiving Mach ports " << from_node
916 << ". Dropping message.";
917 return;
918 }
919 #endif // defined(OS_WIN)
865 920
866 if (destination == name_) { 921 if (destination == name_) {
867 // Great, we can deliver this message locally. 922 // Great, we can deliver this message locally.
868 OnPortsMessage(std::move(message)); 923 OnPortsMessage(std::move(message));
869 return; 924 return;
870 } 925 }
871 926
872 scoped_refptr<NodeChannel> peer = GetPeerChannel(destination); 927 scoped_refptr<NodeChannel> peer = GetPeerChannel(destination);
873 if (peer) 928 if (peer)
874 peer->PortsMessage(std::move(message)); 929 peer->PortsMessage(std::move(message));
875 else 930 else
876 DLOG(ERROR) << "Dropping relay message for unknown node " << destination; 931 DLOG(ERROR) << "Dropping relay message for unknown node " << destination;
877 } 932 }
878 #endif 933 #endif
879 934
880 void NodeController::OnChannelError(const ports::NodeName& from_node) { 935 void NodeController::OnChannelError(const ports::NodeName& from_node) {
881 if (io_task_runner_->RunsTasksOnCurrentThread()) { 936 if (io_task_runner_->RunsTasksOnCurrentThread()) {
882 DropPeer(from_node); 937 DropPeer(from_node);
883 } else { 938 } else {
884 io_task_runner_->PostTask( 939 io_task_runner_->PostTask(
885 FROM_HERE, 940 FROM_HERE,
886 base::Bind(&NodeController::DropPeer, base::Unretained(this), 941 base::Bind(&NodeController::DropPeer, base::Unretained(this),
887 from_node)); 942 from_node));
888 } 943 }
889 } 944 }
890 945
946 #if defined(OS_MACOSX) && !defined(OS_IOS)
947 MachPortRelay* NodeController::GetMachPortRelay() {
948 {
949 base::AutoLock lock(parent_lock_);
950 // Return null if we're not the root.
951 if (bootstrap_parent_channel_ || parent_name_ != ports::kInvalidNodeName)
952 return nullptr;
953 }
954
955 base::AutoLock lock(mach_port_relay_lock_);
956 return mach_port_relay_.get();
957 }
958 #endif
959
891 void NodeController::DestroyOnIOThreadShutdown() { 960 void NodeController::DestroyOnIOThreadShutdown() {
892 destroy_on_io_thread_shutdown_ = true; 961 destroy_on_io_thread_shutdown_ = true;
893 } 962 }
894 963
895 void NodeController::AttemptShutdownIfRequested() { 964 void NodeController::AttemptShutdownIfRequested() {
896 base::Closure callback; 965 base::Closure callback;
897 { 966 {
898 base::AutoLock lock(shutdown_lock_); 967 base::AutoLock lock(shutdown_lock_);
899 if (shutdown_callback_.is_null()) 968 if (shutdown_callback_.is_null())
900 return; 969 return;
901 if (!node_->CanShutdownCleanly(true /* allow_local_ports */)) { 970 if (!node_->CanShutdownCleanly(true /* allow_local_ports */)) {
902 DVLOG(2) << "Unable to cleanly shut down node " << name_ << "."; 971 DVLOG(2) << "Unable to cleanly shut down node " << name_ << ".";
903 return; 972 return;
904 } 973 }
905 callback = shutdown_callback_; 974 callback = shutdown_callback_;
906 shutdown_callback_.Reset(); 975 shutdown_callback_.Reset();
907 } 976 }
908 977
909 DCHECK(!callback.is_null()); 978 DCHECK(!callback.is_null());
910 979
911 callback.Run(); 980 callback.Run();
912 } 981 }
913 982
914 } // namespace edk 983 } // namespace edk
915 } // namespace mojo 984 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/node_controller.h ('k') | mojo/edk/test/mojo_test_base.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698