OLD | NEW |
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" |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 | 109 |
110 void NodeController::SetIOTaskRunner( | 110 void NodeController::SetIOTaskRunner( |
111 scoped_refptr<base::TaskRunner> task_runner) { | 111 scoped_refptr<base::TaskRunner> task_runner) { |
112 io_task_runner_ = task_runner; | 112 io_task_runner_ = task_runner; |
113 ThreadDestructionObserver::Create( | 113 ThreadDestructionObserver::Create( |
114 io_task_runner_, | 114 io_task_runner_, |
115 base::Bind(&NodeController::DropAllPeers, base::Unretained(this))); | 115 base::Bind(&NodeController::DropAllPeers, base::Unretained(this))); |
116 } | 116 } |
117 | 117 |
118 void NodeController::ConnectToChild(base::ProcessHandle process_handle, | 118 void NodeController::ConnectToChild(base::ProcessHandle process_handle, |
119 ScopedPlatformHandle platform_handle) { | 119 ScopedPlatformHandle platform_handle, |
| 120 const std::string& secret) { |
| 121 #if !defined(OS_WIN) |
| 122 // We don't require or support secret validation on non-Windows platforms. |
| 123 CHECK(secret.empty()); |
| 124 #endif |
120 io_task_runner_->PostTask( | 125 io_task_runner_->PostTask( |
121 FROM_HERE, | 126 FROM_HERE, |
122 base::Bind(&NodeController::ConnectToChildOnIOThread, | 127 base::Bind(&NodeController::ConnectToChildOnIOThread, |
123 base::Unretained(this), | 128 base::Unretained(this), process_handle, |
124 process_handle, | 129 base::Passed(&platform_handle), secret)); |
125 base::Passed(&platform_handle))); | |
126 } | 130 } |
127 | 131 |
128 void NodeController::ConnectToParent(ScopedPlatformHandle platform_handle) { | 132 void NodeController::ConnectToParent(ScopedPlatformHandle platform_handle, |
| 133 const std::string& secret) { |
| 134 #if !defined(OS_WIN) |
| 135 // We don't require or support secret validation on non-Windows platforms. |
| 136 CHECK(secret.empty()); |
| 137 #endif |
| 138 |
129 // TODO(amistry): Consider the need for a broker on Windows. | 139 // TODO(amistry): Consider the need for a broker on Windows. |
130 #if defined(OS_POSIX) | 140 #if defined(OS_POSIX) |
131 // On posix, use the bootstrap channel for the broker and receive the node's | 141 // On posix, use the bootstrap channel for the broker and receive the node's |
132 // channel synchronously as the first message from the broker. | 142 // channel synchronously as the first message from the broker. |
133 broker_.reset(new Broker(std::move(platform_handle))); | 143 broker_.reset(new Broker(std::move(platform_handle))); |
134 platform_handle = broker_->GetParentPlatformHandle(); | 144 platform_handle = broker_->GetParentPlatformHandle(); |
135 #endif | 145 #endif |
136 | 146 |
137 io_task_runner_->PostTask( | 147 io_task_runner_->PostTask( |
138 FROM_HERE, | 148 FROM_HERE, |
139 base::Bind(&NodeController::ConnectToParentOnIOThread, | 149 base::Bind(&NodeController::ConnectToParentOnIOThread, |
140 base::Unretained(this), | 150 base::Unretained(this), base::Passed(&platform_handle), |
141 base::Passed(&platform_handle))); | 151 secret)); |
142 } | 152 } |
143 | 153 |
144 void NodeController::SetPortObserver( | 154 void NodeController::SetPortObserver( |
145 const ports::PortRef& port, | 155 const ports::PortRef& port, |
146 const scoped_refptr<PortObserver>& observer) { | 156 const scoped_refptr<PortObserver>& observer) { |
147 node_->SetUserData(port, observer); | 157 node_->SetUserData(port, observer); |
148 } | 158 } |
149 | 159 |
150 void NodeController::ClosePort(const ports::PortRef& port) { | 160 void NodeController::ClosePort(const ports::PortRef& port) { |
151 SetPortObserver(port, nullptr); | 161 SetPortObserver(port, nullptr); |
(...skipping 21 matching lines...) Expand all Loading... |
173 DVLOG(2) << "Reserving port " << port.name() << "@" << name_ << " for token " | 183 DVLOG(2) << "Reserving port " << port.name() << "@" << name_ << " for token " |
174 << token; | 184 << token; |
175 | 185 |
176 base::AutoLock lock(reserved_ports_lock_); | 186 base::AutoLock lock(reserved_ports_lock_); |
177 auto result = reserved_ports_.insert(std::make_pair(token, port)); | 187 auto result = reserved_ports_.insert(std::make_pair(token, port)); |
178 DCHECK(result.second); | 188 DCHECK(result.second); |
179 } | 189 } |
180 | 190 |
181 void NodeController::MergePortIntoParent(const std::string& token, | 191 void NodeController::MergePortIntoParent(const std::string& token, |
182 const ports::PortRef& port) { | 192 const ports::PortRef& port) { |
| 193 { |
| 194 // This request may be coming from within the process that reserved the |
| 195 // "parent" side (e.g. for Chrome single-process mode), so if this token is |
| 196 // reserved locally, merge locally instead. |
| 197 base::AutoLock lock(reserved_ports_lock_); |
| 198 auto it = reserved_ports_.find(token); |
| 199 if (it != reserved_ports_.end()) { |
| 200 node_->MergePorts(port, name_, it->second.name()); |
| 201 reserved_ports_.erase(it); |
| 202 return; |
| 203 } |
| 204 } |
| 205 |
183 scoped_refptr<NodeChannel> parent = GetParentChannel(); | 206 scoped_refptr<NodeChannel> parent = GetParentChannel(); |
184 if (parent) { | 207 if (parent) { |
185 parent->RequestPortMerge(port.name(), token); | 208 parent->RequestPortMerge(port.name(), token); |
186 return; | 209 return; |
187 } | 210 } |
188 | 211 |
189 base::AutoLock lock(pending_port_merges_lock_); | 212 base::AutoLock lock(pending_port_merges_lock_); |
190 pending_port_merges_.push_back(std::make_pair(token, port)); | 213 pending_port_merges_.push_back(std::make_pair(token, port)); |
191 } | 214 } |
192 | 215 |
(...skipping 15 matching lines...) Expand all Loading... |
208 { | 231 { |
209 base::AutoLock lock(shutdown_lock_); | 232 base::AutoLock lock(shutdown_lock_); |
210 shutdown_callback_ = callback; | 233 shutdown_callback_ = callback; |
211 } | 234 } |
212 | 235 |
213 AttemptShutdownIfRequested(); | 236 AttemptShutdownIfRequested(); |
214 } | 237 } |
215 | 238 |
216 void NodeController::ConnectToChildOnIOThread( | 239 void NodeController::ConnectToChildOnIOThread( |
217 base::ProcessHandle process_handle, | 240 base::ProcessHandle process_handle, |
218 ScopedPlatformHandle platform_handle) { | 241 ScopedPlatformHandle platform_handle, |
| 242 const std::string& secret) { |
219 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); | 243 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
220 | 244 |
221 #if defined(OS_POSIX) | 245 #if defined(OS_POSIX) |
222 PlatformChannelPair node_channel; | 246 PlatformChannelPair node_channel; |
223 // BrokerHost owns itself. | 247 // BrokerHost owns itself. |
224 BrokerHost* broker_host = new BrokerHost(std::move(platform_handle)); | 248 BrokerHost* broker_host = new BrokerHost(std::move(platform_handle)); |
225 broker_host->SendChannel(node_channel.PassClientHandle()); | 249 broker_host->SendChannel(node_channel.PassClientHandle()); |
226 scoped_refptr<NodeChannel> channel = NodeChannel::Create( | 250 scoped_refptr<NodeChannel> channel = NodeChannel::Create( |
227 this, node_channel.PassServerHandle(), io_task_runner_); | 251 this, node_channel.PassServerHandle(), io_task_runner_); |
228 #else | 252 #else |
229 scoped_refptr<NodeChannel> channel = | 253 scoped_refptr<NodeChannel> channel = |
230 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); | 254 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); |
231 #endif | 255 #endif |
232 | 256 |
233 // We set up the child channel with a temporary name so it can be identified | 257 // We set up the child channel with a temporary name so it can be identified |
234 // as a pending child if it writes any messages to the channel. We may start | 258 // as a pending child if it writes any messages to the channel. We may start |
235 // receiving messages from it (though we shouldn't) as soon as Start() is | 259 // receiving messages from it (though we shouldn't) as soon as Start() is |
236 // called below. | 260 // called below. |
237 ports::NodeName token; | 261 ports::NodeName token; |
238 GenerateRandomName(&token); | 262 GenerateRandomName(&token); |
239 | 263 |
240 pending_children_.insert(std::make_pair(token, channel)); | 264 pending_children_.insert(std::make_pair(token, channel)); |
241 RecordPendingChildCount(pending_children_.size()); | 265 RecordPendingChildCount(pending_children_.size()); |
242 | 266 |
243 channel->SetRemoteNodeName(token); | 267 channel->SetRemoteNodeName(token); |
244 channel->SetRemoteProcessHandle(process_handle); | 268 channel->SetRemoteProcessHandle(process_handle); |
| 269 channel->SetExpectedSecret(secret); |
245 channel->Start(); | 270 channel->Start(); |
246 | 271 |
247 channel->AcceptChild(name_, token); | 272 channel->AcceptChild(name_, token); |
248 } | 273 } |
249 | 274 |
250 void NodeController::ConnectToParentOnIOThread( | 275 void NodeController::ConnectToParentOnIOThread( |
251 ScopedPlatformHandle platform_handle) { | 276 ScopedPlatformHandle platform_handle, |
| 277 const std::string& secret) { |
252 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); | 278 DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); |
253 | 279 |
254 base::AutoLock lock(parent_lock_); | 280 base::AutoLock lock(parent_lock_); |
255 DCHECK(parent_name_ == ports::kInvalidNodeName); | 281 DCHECK(parent_name_ == ports::kInvalidNodeName); |
256 | 282 |
257 // At this point we don't know the parent's name, so we can't yet insert it | 283 // At this point we don't know the parent's name, so we can't yet insert it |
258 // into our |peers_| map. That will happen as soon as we receive an | 284 // into our |peers_| map. That will happen as soon as we receive an |
259 // AcceptChild message from them. | 285 // AcceptChild message from them. |
260 bootstrap_parent_channel_ = | 286 bootstrap_parent_channel_ = |
261 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); | 287 NodeChannel::Create(this, std::move(platform_handle), io_task_runner_); |
262 bootstrap_parent_channel_->Start(); | 288 bootstrap_parent_channel_->Start(); |
| 289 |
| 290 if (!secret.empty()) { |
| 291 // On Windows we start out by sending a secret token to the parent process |
| 292 // which it will use to authenticate our end of the pipe. |
| 293 #if !defined(OS_WIN) |
| 294 // We don't ever want to send a secret on non-Windows. |
| 295 NOTREACHED(); |
| 296 #endif |
| 297 bootstrap_parent_channel_->SendSecret(secret); |
| 298 } |
263 } | 299 } |
264 | 300 |
265 scoped_refptr<NodeChannel> NodeController::GetPeerChannel( | 301 scoped_refptr<NodeChannel> NodeController::GetPeerChannel( |
266 const ports::NodeName& name) { | 302 const ports::NodeName& name) { |
267 base::AutoLock lock(peers_lock_); | 303 base::AutoLock lock(peers_lock_); |
268 auto it = peers_.find(name); | 304 auto it = peers_.find(name); |
269 if (it == peers_.end()) | 305 if (it == peers_.end()) |
270 return nullptr; | 306 return nullptr; |
271 return it->second; | 307 return it->second; |
272 } | 308 } |
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 shutdown_callback_.Reset(); | 906 shutdown_callback_.Reset(); |
871 } | 907 } |
872 | 908 |
873 DCHECK(!callback.is_null()); | 909 DCHECK(!callback.is_null()); |
874 | 910 |
875 callback.Run(); | 911 callback.Run(); |
876 } | 912 } |
877 | 913 |
878 } // namespace edk | 914 } // namespace edk |
879 } // namespace mojo | 915 } // namespace mojo |
OLD | NEW |