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

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: Rebase 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
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::CreateMachPortRelayIfNeeded(
116 base::PortProvider* port_provider) {
117 base::AutoLock lock(mach_port_relay_lock_);
118 DCHECK(!mach_port_relay_ ||
119 mach_port_relay_->port_provider() == port_provider);
120 mach_port_relay_.reset(new MachPortRelay(port_provider));
121 }
122 #endif
123
110 void NodeController::SetIOTaskRunner( 124 void NodeController::SetIOTaskRunner(
111 scoped_refptr<base::TaskRunner> task_runner) { 125 scoped_refptr<base::TaskRunner> task_runner) {
112 io_task_runner_ = task_runner; 126 io_task_runner_ = task_runner;
113 ThreadDestructionObserver::Create( 127 ThreadDestructionObserver::Create(
114 io_task_runner_, 128 io_task_runner_,
115 base::Bind(&NodeController::DropAllPeers, base::Unretained(this))); 129 base::Bind(&NodeController::DropAllPeers, base::Unretained(this)));
116 } 130 }
117 131
118 void NodeController::ConnectToChild(base::ProcessHandle process_handle, 132 void NodeController::ConnectToChild(base::ProcessHandle process_handle,
119 ScopedPlatformHandle platform_handle) { 133 ScopedPlatformHandle platform_handle) {
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 channel->SetRemoteProcessHandle(process_handle); 278 channel->SetRemoteProcessHandle(process_handle);
265 channel->Start(); 279 channel->Start();
266 280
267 channel->AcceptChild(name_, token); 281 channel->AcceptChild(name_, token);
268 } 282 }
269 283
270 void NodeController::ConnectToParentOnIOThread( 284 void NodeController::ConnectToParentOnIOThread(
271 ScopedPlatformHandle platform_handle) { 285 ScopedPlatformHandle platform_handle) {
272 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); 286 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
273 287
274 base::AutoLock lock(parent_lock_); 288 {
275 DCHECK(parent_name_ == ports::kInvalidNodeName); 289 base::AutoLock lock(parent_lock_);
290 DCHECK(parent_name_ == ports::kInvalidNodeName);
276 291
277 // At this point we don't know the parent's name, so we can't yet insert it 292 // At this point we don't know the parent's name, so we can't yet insert it
278 // into our |peers_| map. That will happen as soon as we receive an 293 // into our |peers_| map. That will happen as soon as we receive an
279 // AcceptChild message from them. 294 // AcceptChild message from them.
280 bootstrap_parent_channel_ = 295 bootstrap_parent_channel_ =
281 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); 296 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_);
297 }
282 bootstrap_parent_channel_->Start(); 298 bootstrap_parent_channel_->Start();
283 } 299 }
284 300
285 scoped_refptr<NodeChannel> NodeController::GetPeerChannel( 301 scoped_refptr<NodeChannel> NodeController::GetPeerChannel(
286 const ports::NodeName& name) { 302 const ports::NodeName& name) {
287 base::AutoLock lock(peers_lock_); 303 base::AutoLock lock(peers_lock_);
288 auto it = peers_.find(name); 304 auto it = peers_.find(name);
289 if (it == peers_.end()) 305 if (it == peers_.end())
290 return nullptr; 306 return nullptr;
291 return it->second; 307 return it->second;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 if (!peer || !peer->HasRemoteProcessHandle()) { 408 if (!peer || !peer->HasRemoteProcessHandle()) {
393 if (broker) { 409 if (broker) {
394 broker->RelayPortsMessage(name, std::move(channel_message)); 410 broker->RelayPortsMessage(name, std::move(channel_message));
395 } else { 411 } else {
396 base::AutoLock lock(broker_lock_); 412 base::AutoLock lock(broker_lock_);
397 pending_relay_messages_[name].emplace(std::move(channel_message)); 413 pending_relay_messages_[name].emplace(std::move(channel_message));
398 } 414 }
399 return; 415 return;
400 } 416 }
401 } 417 }
402 #endif 418 #elif defined(OS_MACOSX) && !defined(OS_IOS)
419 if (channel_message->has_mach_ports()) {
420 // Messages containing Mach ports are always routed through the broker, even
421 // if the broker process is the intended recipient.
422 bool use_broker = false;
423 {
424 base::AutoLock lock(parent_lock_);
425 use_broker = (bootstrap_parent_channel_ ||
426 parent_name_ != ports::kInvalidNodeName);
427 }
428 if (use_broker) {
429 scoped_refptr<NodeChannel> broker = GetBrokerChannel();
430 if (broker) {
431 broker->RelayPortsMessage(name, std::move(channel_message));
432 } else {
433 base::AutoLock lock(broker_lock_);
434 pending_relay_messages_[name].emplace(std::move(channel_message));
435 }
436 return;
437 }
438 }
439 #endif // defined(OS_WIN)
403 440
404 if (peer) { 441 if (peer) {
405 peer->PortsMessage(std::move(channel_message)); 442 peer->PortsMessage(std::move(channel_message));
406 return; 443 return;
407 } 444 }
408 445
409 // If we don't know who the peer is, queue the message for delivery. If this 446 // If we don't know who the peer is, queue the message for delivery. If this
410 // is the first message queued for the peer, we also ask the broker to 447 // is the first message queued for the peer, we also ask the broker to
411 // introduce us to them. 448 // introduce us to them.
412 449
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 void NodeController::OnBrokerClientAdded(const ports::NodeName& from_node, 679 void NodeController::OnBrokerClientAdded(const ports::NodeName& from_node,
643 const ports::NodeName& client_name, 680 const ports::NodeName& client_name,
644 ScopedPlatformHandle broker_channel) { 681 ScopedPlatformHandle broker_channel) {
645 scoped_refptr<NodeChannel> client = GetPeerChannel(client_name); 682 scoped_refptr<NodeChannel> client = GetPeerChannel(client_name);
646 if (!client) { 683 if (!client) {
647 DLOG(ERROR) << "BrokerClientAdded for unknown child " << client_name; 684 DLOG(ERROR) << "BrokerClientAdded for unknown child " << client_name;
648 return; 685 return;
649 } 686 }
650 687
651 // This should have come from our own broker. 688 // This should have come from our own broker.
652 if(GetBrokerChannel() != GetPeerChannel(from_node)) { 689 if (GetBrokerChannel() != GetPeerChannel(from_node)) {
653 DLOG(ERROR) << "BrokerClientAdded from non-broker node " << from_node; 690 DLOG(ERROR) << "BrokerClientAdded from non-broker node " << from_node;
654 return; 691 return;
655 } 692 }
656 693
657 DVLOG(1) << "Child " << client_name << " accepted by broker " << from_node; 694 DVLOG(1) << "Child " << client_name << " accepted by broker " << from_node;
658 695
659 client->AcceptBrokerClient(from_node, std::move(broker_channel)); 696 client->AcceptBrokerClient(from_node, std::move(broker_channel));
660 } 697 }
661 698
662 void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node, 699 void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 747
711 // Feed the broker any pending children of our own. 748 // Feed the broker any pending children of our own.
712 while (!pending_broker_clients.empty()) { 749 while (!pending_broker_clients.empty()) {
713 const ports::NodeName& child_name = pending_broker_clients.front(); 750 const ports::NodeName& child_name = pending_broker_clients.front();
714 auto it = pending_children_.find(child_name); 751 auto it = pending_children_.find(child_name);
715 DCHECK(it != pending_children_.end()); 752 DCHECK(it != pending_children_.end());
716 broker->AddBrokerClient(child_name, it->second->CopyRemoteProcessHandle()); 753 broker->AddBrokerClient(child_name, it->second->CopyRemoteProcessHandle());
717 pending_broker_clients.pop(); 754 pending_broker_clients.pop();
718 } 755 }
719 756
720 #if defined(OS_WIN) 757 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
721 // Have the broker relay any messages we have waiting. 758 // Have the broker relay any messages we have waiting.
722 for (auto& entry : pending_relay_messages) { 759 for (auto& entry : pending_relay_messages) {
723 const ports::NodeName& destination = entry.first; 760 const ports::NodeName& destination = entry.first;
724 auto& message_queue = entry.second; 761 auto& message_queue = entry.second;
725 while (!message_queue.empty()) { 762 while (!message_queue.empty()) {
726 broker->RelayPortsMessage(destination, std::move(message_queue.front())); 763 broker->RelayPortsMessage(destination, std::move(message_queue.front()));
727 message_queue.pop(); 764 message_queue.pop();
728 } 765 }
729 } 766 }
730 #endif 767 #endif
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 return; 857 return;
821 } 858 }
822 859
823 scoped_refptr<NodeChannel> channel = 860 scoped_refptr<NodeChannel> channel =
824 NodeChannel::Create(this, std::move(channel_handle), io_task_runner_); 861 NodeChannel::Create(this, std::move(channel_handle), io_task_runner_);
825 862
826 DVLOG(1) << "Adding new peer " << name << " via parent introduction."; 863 DVLOG(1) << "Adding new peer " << name << " via parent introduction.";
827 AddPeer(name, channel, true /* start_channel */); 864 AddPeer(name, channel, true /* start_channel */);
828 } 865 }
829 866
830 #if defined(OS_WIN) 867 #if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
831 void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, 868 void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node,
832 base::ProcessHandle from_process, 869 base::ProcessHandle from_process,
833 const ports::NodeName& destination, 870 const ports::NodeName& destination,
834 Channel::MessagePtr message) { 871 Channel::MessagePtr message) {
872 DCHECK(io_task_runner_->RunsTasksOnCurrentThread());
873
835 if (GetBrokerChannel()) { 874 if (GetBrokerChannel()) {
836 // Only the broker should be asked to relay a message. 875 // Only the broker should be asked to relay a message.
837 LOG(ERROR) << "Non-broker refusing to relay message."; 876 LOG(ERROR) << "Non-broker refusing to relay message.";
838 DropPeer(from_node); 877 DropPeer(from_node);
839 return; 878 return;
840 } 879 }
841 880
842 // The parent should always know which process this came from. 881 // The parent should always know which process this came from.
843 DCHECK(from_process != base::kNullProcessHandle); 882 DCHECK(from_process != base::kNullProcessHandle);
844 883
884 #if defined(OS_WIN)
845 // Rewrite the handles to this (the parent) process. If the message is 885 // Rewrite the handles to this (the parent) process. If the message is
846 // destined for another child process, the handles will be rewritten to that 886 // destined for another child process, the handles will be rewritten to that
847 // process before going out (see NodeChannel::WriteChannelMessage). 887 // process before going out (see NodeChannel::WriteChannelMessage).
848 // 888 //
849 // TODO: We could avoid double-duplication. 889 // TODO: We could avoid double-duplication.
850 if (!Channel::Message::RewriteHandles(from_process, 890 if (!Channel::Message::RewriteHandles(from_process,
851 base::GetCurrentProcessHandle(), 891 base::GetCurrentProcessHandle(),
852 message->handles(), 892 message->handles(),
853 message->num_handles())) { 893 message->num_handles())) {
854 DLOG(ERROR) << "Failed to relay one or more handles."; 894 DLOG(ERROR) << "Failed to relay one or more handles.";
855 } 895 }
896 #else
897 MachPortRelay* relay = GetMachPortRelay();
898 if (!relay) {
899 LOG(ERROR) << "Receiving Mach ports without a port relay from "
900 << from_node << ". Dropping message.";
901 return;
902 }
903 if (!relay->ExtractPortRights(message.get(), from_process)) {
904 // NodeChannel should ensure that MachPortRelay is ready for the remote
905 // process. At this point, if the port extraction failed, either something
906 // went wrong in the mach stuff, or the remote process died.
907 LOG(ERROR) << "Error on receiving Mach ports " << from_node
908 << ". Dropping message.";
909 return;
910 }
911 #endif // defined(OS_WIN)
856 912
857 if (destination == name_) { 913 if (destination == name_) {
858 // Great, we can deliver this message locally. 914 // Great, we can deliver this message locally.
859 OnPortsMessage(std::move(message)); 915 OnPortsMessage(std::move(message));
860 return; 916 return;
861 } 917 }
862 918
863 scoped_refptr<NodeChannel> peer = GetPeerChannel(destination); 919 scoped_refptr<NodeChannel> peer = GetPeerChannel(destination);
864 if (peer) 920 if (peer)
865 peer->PortsMessage(std::move(message)); 921 peer->PortsMessage(std::move(message));
866 else 922 else
867 DLOG(ERROR) << "Dropping relay message for unknown node " << destination; 923 DLOG(ERROR) << "Dropping relay message for unknown node " << destination;
868 } 924 }
869 #endif 925 #endif
870 926
871 void NodeController::OnChannelError(const ports::NodeName& from_node) { 927 void NodeController::OnChannelError(const ports::NodeName& from_node) {
872 if (io_task_runner_->RunsTasksOnCurrentThread()) { 928 if (io_task_runner_->RunsTasksOnCurrentThread()) {
873 DropPeer(from_node); 929 DropPeer(from_node);
874 } else { 930 } else {
875 io_task_runner_->PostTask( 931 io_task_runner_->PostTask(
876 FROM_HERE, 932 FROM_HERE,
877 base::Bind(&NodeController::DropPeer, base::Unretained(this), 933 base::Bind(&NodeController::DropPeer, base::Unretained(this),
878 from_node)); 934 from_node));
879 } 935 }
880 } 936 }
881 937
938 #if defined(OS_MACOSX) && !defined(OS_IOS)
939 MachPortRelay* NodeController::GetMachPortRelay() {
940 {
941 base::AutoLock lock(parent_lock_);
942 // Return null if we're not the root.
943 if (bootstrap_parent_channel_ || parent_name_ != ports::kInvalidNodeName)
944 return nullptr;
945 }
946
947 base::AutoLock lock(mach_port_relay_lock_);
948 return mach_port_relay_.get();
949 }
950 #endif
951
882 void NodeController::DestroyOnIOThreadShutdown() { 952 void NodeController::DestroyOnIOThreadShutdown() {
883 destroy_on_io_thread_shutdown_ = true; 953 destroy_on_io_thread_shutdown_ = true;
884 } 954 }
885 955
886 void NodeController::AttemptShutdownIfRequested() { 956 void NodeController::AttemptShutdownIfRequested() {
887 base::Closure callback; 957 base::Closure callback;
888 { 958 {
889 base::AutoLock lock(shutdown_lock_); 959 base::AutoLock lock(shutdown_lock_);
890 if (shutdown_callback_.is_null()) 960 if (shutdown_callback_.is_null())
891 return; 961 return;
892 if (!node_->CanShutdownCleanly(true /* allow_local_ports */)) { 962 if (!node_->CanShutdownCleanly(true /* allow_local_ports */)) {
893 DVLOG(2) << "Unable to cleanly shut down node " << name_ << "."; 963 DVLOG(2) << "Unable to cleanly shut down node " << name_ << ".";
894 return; 964 return;
895 } 965 }
896 callback = shutdown_callback_; 966 callback = shutdown_callback_;
897 shutdown_callback_.Reset(); 967 shutdown_callback_.Reset();
898 } 968 }
899 969
900 DCHECK(!callback.is_null()); 970 DCHECK(!callback.is_null());
901 971
902 callback.Run(); 972 callback.Run();
903 } 973 }
904 974
905 } // namespace edk 975 } // namespace edk
906 } // namespace mojo 976 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698