Index: mojo/edk/system/node_controller.cc |
diff --git a/mojo/edk/system/node_controller.cc b/mojo/edk/system/node_controller.cc |
index 5b2fea82cb9738890071ddddef7808eaf8acaa12..1aac2d5423a2ee3af797ba05739e6459fdb78b76 100644 |
--- a/mojo/edk/system/node_controller.cc |
+++ b/mojo/edk/system/node_controller.cc |
@@ -22,6 +22,10 @@ |
#include "mojo/edk/system/core.h" |
#include "mojo/edk/system/ports_message.h" |
+#if defined(OS_MACOSX) && !defined(OS_IOS) |
+#include "mojo/edk/system/mach_port_relay.h" |
+#endif |
+ |
namespace mojo { |
namespace edk { |
@@ -107,6 +111,18 @@ NodeController::NodeController(Core* core) |
DVLOG(1) << "Initializing node " << name_; |
} |
+#if defined(OS_MACOSX) && !defined(OS_IOS) |
+void NodeController::CreateMachPortRelayIfNeeded( |
+ base::PortProvider* port_provider) { |
+ base::AutoLock lock(mach_port_relay_lock_); |
+#if DCHECK_IS_ON() |
+ DCHECK(!mach_port_relay_ || |
+ mach_port_relay_->port_provider() == port_provider); |
+#endif |
+ mach_port_relay_.reset(new MachPortRelay(port_provider)); |
+} |
+#endif |
+ |
void NodeController::SetIOTaskRunner( |
scoped_refptr<base::TaskRunner> task_runner) { |
io_task_runner_ = task_runner; |
@@ -265,14 +281,16 @@ void NodeController::ConnectToParentOnIOThread( |
ScopedPlatformHandle platform_handle) { |
DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
- base::AutoLock lock(parent_lock_); |
- DCHECK(parent_name_ == ports::kInvalidNodeName); |
+ { |
+ base::AutoLock lock(parent_lock_); |
+ DCHECK(parent_name_ == ports::kInvalidNodeName); |
- // At this point we don't know the parent's name, so we can't yet insert it |
- // into our |peers_| map. That will happen as soon as we receive an |
- // AcceptChild message from them. |
- bootstrap_parent_channel_ = |
- NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); |
+ // At this point we don't know the parent's name, so we can't yet insert it |
+ // into our |peers_| map. That will happen as soon as we receive an |
+ // AcceptChild message from them. |
+ bootstrap_parent_channel_ = |
+ NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); |
+ } |
bootstrap_parent_channel_->Start(); |
} |
@@ -393,7 +411,28 @@ void NodeController::SendPeerMessage(const ports::NodeName& name, |
return; |
} |
} |
-#endif |
+#elif defined(OS_MACOSX) && !defined(OS_IOS) |
+ if (channel_message->has_mach_ports()) { |
+ // Messages containing mach ports are always routed through the broker, even |
+ // if the broker process is the intended recipient. |
+ bool use_broker = false; |
erikchen
2016/03/09 19:13:17
What happens if the message has mach ports but the
Anand Mistry (off Chromium)
2016/03/11 07:44:18
That's covered below. The child startup process is
|
+ { |
+ base::AutoLock lock(parent_lock_); |
+ use_broker = (bootstrap_parent_channel_ || |
+ parent_name_ != ports::kInvalidNodeName); |
+ } |
+ if (use_broker) { |
+ scoped_refptr<NodeChannel> broker = GetBrokerChannel(); |
+ if (broker) { |
+ broker->RelayPortsMessage(name, std::move(channel_message)); |
+ } else { |
+ base::AutoLock lock(broker_lock_); |
+ pending_relay_messages_[name].emplace(std::move(channel_message)); |
+ } |
+ return; |
+ } |
+ } |
+#endif // defined(OS_WIN) |
if (peer) { |
peer->PortsMessage(std::move(channel_message)); |
@@ -643,7 +682,7 @@ void NodeController::OnBrokerClientAdded(const ports::NodeName& from_node, |
} |
// This should have come from our own broker. |
- if(GetBrokerChannel() != GetPeerChannel(from_node)) { |
+ if (GetBrokerChannel() != GetPeerChannel(from_node)) { |
DLOG(ERROR) << "BrokerClientAdded from non-broker node " << from_node; |
return; |
} |
@@ -711,7 +750,7 @@ void NodeController::OnAcceptBrokerClient(const ports::NodeName& from_node, |
pending_broker_clients.pop(); |
} |
-#if defined(OS_WIN) |
+#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
// Have the broker relay any messages we have waiting. |
for (auto& entry : pending_relay_messages) { |
const ports::NodeName& destination = entry.first; |
@@ -821,11 +860,13 @@ void NodeController::OnIntroduce(const ports::NodeName& from_node, |
AddPeer(name, channel, true /* start_channel */); |
} |
-#if defined(OS_WIN) |
+#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS)) |
void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, |
base::ProcessHandle from_process, |
const ports::NodeName& destination, |
Channel::MessagePtr message) { |
+ DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
+ |
if (GetBrokerChannel()) { |
// Only the broker should be asked to relay a message. |
LOG(ERROR) << "Non-broker refusing to relay message."; |
@@ -836,6 +877,7 @@ void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, |
// The parent should always know which process this came from. |
DCHECK(from_process != base::kNullProcessHandle); |
+#if defined(OS_WIN) |
// Rewrite the handles to this (the parent) process. If the message is |
// destined for another child process, the handles will be rewritten to that |
// process before going out (see NodeChannel::WriteChannelMessage). |
@@ -847,6 +889,22 @@ void NodeController::OnRelayPortsMessage(const ports::NodeName& from_node, |
message->num_handles())) { |
DLOG(ERROR) << "Failed to relay one or more handles."; |
} |
+#else |
+ MachPortRelay* relay = GetMachPortRelay(); |
+ if (!relay) { |
+ LOG(ERROR) << "Receiving mach ports without a port relay from " |
+ << from_node << ". Dropping message."; |
+ return; |
+ } |
+ if (!relay->ExtractPortRights(message.get(), from_process)) { |
+ // NodeChannel should ensure that MachPortRelay is ready for the remote |
+ // process. At this point, if the port extraction failed, either something |
+ // went wrong in the mach stuff, or the remote process died. |
+ LOG(ERROR) << "Error on receiving mach ports " << from_node |
+ << ". Dropping message."; |
+ return; |
+ } |
+#endif // defined(OS_WIN) |
if (destination == name_) { |
// Great, we can deliver this message locally. |
@@ -873,6 +931,20 @@ void NodeController::OnChannelError(const ports::NodeName& from_node) { |
} |
} |
+#if defined(OS_MACOSX) && !defined(OS_IOS) |
+MachPortRelay* NodeController::GetMachPortRelay() { |
+ { |
+ base::AutoLock lock(parent_lock_); |
+ // Return null if we're not the root. |
+ if (bootstrap_parent_channel_ || parent_name_ != ports::kInvalidNodeName) |
+ return nullptr; |
+ } |
+ |
+ base::AutoLock lock(mach_port_relay_lock_); |
+ return mach_port_relay_.get(); |
+} |
+#endif |
+ |
void NodeController::DestroyOnIOThreadShutdown() { |
destroy_on_io_thread_shutdown_ = true; |
} |