OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "services/service_manager/service_manager.h" | 5 #include "services/service_manager/service_manager.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/guid.h" | 13 #include "base/guid.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
17 #include "base/process/process.h" | 17 #include "base/process/process.h" |
18 #include "base/process/process_handle.h" | 18 #include "base/process/process_handle.h" |
19 #include "base/stl_util.h" | 19 #include "base/stl_util.h" |
20 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
21 #include "base/trace_event/trace_event.h" | 21 #include "base/trace_event/trace_event.h" |
22 #include "mojo/public/cpp/bindings/associated_binding.h" | 22 #include "mojo/public/cpp/bindings/associated_binding.h" |
23 #include "mojo/public/cpp/bindings/binding.h" | 23 #include "mojo/public/cpp/bindings/binding.h" |
24 #include "mojo/public/cpp/bindings/binding_set.h" | 24 #include "mojo/public/cpp/bindings/binding_set.h" |
25 #include "mojo/public/cpp/bindings/strong_binding.h" | |
25 #include "services/catalog/public/interfaces/constants.mojom.h" | 26 #include "services/catalog/public/interfaces/constants.mojom.h" |
26 #include "services/service_manager/connect_util.h" | 27 #include "services/service_manager/connect_util.h" |
27 #include "services/service_manager/public/cpp/connector.h" | 28 #include "services/service_manager/public/cpp/connector.h" |
28 #include "services/service_manager/public/cpp/interface_registry.h" | 29 #include "services/service_manager/public/cpp/interface_registry.h" |
29 #include "services/service_manager/public/cpp/service.h" | 30 #include "services/service_manager/public/cpp/service.h" |
30 #include "services/service_manager/public/cpp/service_context.h" | 31 #include "services/service_manager/public/cpp/service_context.h" |
31 #include "services/service_manager/public/interfaces/connector.mojom.h" | 32 #include "services/service_manager/public/interfaces/connector.mojom.h" |
32 #include "services/service_manager/public/interfaces/constants.mojom.h" | 33 #include "services/service_manager/public/interfaces/constants.mojom.h" |
33 #include "services/service_manager/public/interfaces/service.mojom.h" | 34 #include "services/service_manager/public/interfaces/service.mojom.h" |
34 #include "services/service_manager/public/interfaces/service_control.mojom.h" | 35 #include "services/service_manager/public/interfaces/service_control.mojom.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
70 } | 71 } |
71 | 72 |
72 bool HasCapability(const InterfaceProviderSpec& spec, | 73 bool HasCapability(const InterfaceProviderSpec& spec, |
73 const std::string& capability) { | 74 const std::string& capability) { |
74 auto it = spec.requires.find(service_manager::mojom::kServiceName); | 75 auto it = spec.requires.find(service_manager::mojom::kServiceName); |
75 if (it == spec.requires.end()) | 76 if (it == spec.requires.end()) |
76 return false; | 77 return false; |
77 return it->second.find(capability) != it->second.end(); | 78 return it->second.find(capability) != it->second.end(); |
78 } | 79 } |
79 | 80 |
81 bool AllowsInterface(const Identity& source, | |
82 const InterfaceProviderSpec& source_spec, | |
83 const Identity& target, | |
84 const InterfaceProviderSpec& target_spec, | |
85 const std::string& interface_name) { | |
86 InterfaceSet exposed = | |
87 GetInterfacesToExpose(source_spec, target, target_spec); | |
88 bool allowed = (exposed.size() == 1 && exposed.count("*") == 1) || | |
89 exposed.count(interface_name) > 0; | |
90 if (!allowed) { | |
91 std::stringstream ss; | |
92 ss << "Connection InterfaceProviderSpec prevented service: " | |
93 << source.name() << " from binding interface: " << interface_name | |
94 << " exposed by: " << target.name(); | |
95 LOG(ERROR) << ss.str(); | |
96 } | |
97 return allowed; | |
98 } | |
99 | |
80 // Encapsulates a connection to an instance of a service, tracked by the | 100 // Encapsulates a connection to an instance of a service, tracked by the |
81 // Service Manager. | 101 // Service Manager. |
82 class ServiceManager::Instance | 102 class ServiceManager::Instance |
83 : public mojom::Connector, | 103 : public mojom::Connector, |
84 public mojom::PIDReceiver, | 104 public mojom::PIDReceiver, |
85 public Service, | 105 public Service, |
86 public mojom::ServiceManager, | 106 public mojom::ServiceManager, |
87 public mojom::ServiceControl { | 107 public mojom::ServiceControl { |
88 public: | 108 public: |
89 Instance(service_manager::ServiceManager* service_manager, | 109 Instance(service_manager::ServiceManager* service_manager, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 std::unique_ptr<ConnectParams> params(std::move(*in_params)); | 158 std::unique_ptr<ConnectParams> params(std::move(*in_params)); |
139 InterfaceProviderSpecMap source_specs; | 159 InterfaceProviderSpecMap source_specs; |
140 InterfaceProviderSpec source_connection_spec; | 160 InterfaceProviderSpec source_connection_spec; |
141 Instance* source = | 161 Instance* source = |
142 service_manager_->GetExistingInstance(params->source()); | 162 service_manager_->GetExistingInstance(params->source()); |
143 if (source) { | 163 if (source) { |
144 source_specs = source->interface_provider_specs_; | 164 source_specs = source->interface_provider_specs_; |
145 source_connection_spec = source->GetConnectionSpec(); | 165 source_connection_spec = source->GetConnectionSpec(); |
146 } | 166 } |
147 | 167 |
148 InterfaceSet exposed = GetInterfacesToExpose(source_connection_spec, | 168 if (!AllowsInterface(params->source(), source_connection_spec, identity_, |
149 identity_, | 169 GetConnectionSpec(), params->interface_name())) { |
150 GetConnectionSpec()); | |
151 bool allowed = (exposed.size() == 1 && exposed.count("*") == 1) || | |
152 exposed.count(params->interface_name()) > 0; | |
153 if (!allowed) { | |
154 std::stringstream ss; | |
155 ss << "Connection InterfaceProviderSpec prevented service: " | |
156 << params->source().name() << " from binding interface: " | |
157 << params->interface_name() << " exposed by: " << identity_.name(); | |
158 LOG(ERROR) << ss.str(); | |
159 params->set_response_data(mojom::ConnectResult::ACCESS_DENIED, identity_); | 170 params->set_response_data(mojom::ConnectResult::ACCESS_DENIED, identity_); |
160 return false; | 171 return false; |
161 } | 172 } |
162 | 173 |
163 params->set_response_data(mojom::ConnectResult::SUCCEEDED, identity_); | 174 params->set_response_data(mojom::ConnectResult::SUCCEEDED, identity_); |
164 | 175 |
165 pending_service_connections_++; | 176 pending_service_connections_++; |
166 service_->OnBindInterface( | 177 service_->OnBindInterface( |
167 ServiceInfo(params->source(), source_specs), | 178 ServiceInfo(params->source(), source_specs), |
168 params->interface_name(), | 179 params->interface_name(), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 | 219 |
209 mojom::RunningServiceInfoPtr CreateRunningServiceInfo() const { | 220 mojom::RunningServiceInfoPtr CreateRunningServiceInfo() const { |
210 mojom::RunningServiceInfoPtr info(mojom::RunningServiceInfo::New()); | 221 mojom::RunningServiceInfoPtr info(mojom::RunningServiceInfo::New()); |
211 info->id = id_; | 222 info->id = id_; |
212 info->identity = identity_; | 223 info->identity = identity_; |
213 info->pid = pid_; | 224 info->pid = pid_; |
214 return info; | 225 return info; |
215 } | 226 } |
216 | 227 |
217 const InterfaceProviderSpec& GetConnectionSpec() const { | 228 const InterfaceProviderSpec& GetConnectionSpec() const { |
218 auto it = interface_provider_specs_.find( | 229 return GetSpecNamed(mojom::kServiceManager_ConnectorSpec); |
219 mojom::kServiceManager_ConnectorSpec); | 230 } |
231 bool HasSpecNamed(const std::string& spec) const { | |
Ken Rockot(use gerrit already)
2017/04/26 04:32:48
nits: GetSpec and HasSpec? And vertical whitespace
| |
232 auto it = interface_provider_specs_.find(spec); | |
233 return it != interface_provider_specs_.end(); | |
234 } | |
235 const InterfaceProviderSpec& GetSpecNamed(const std::string& spec) const { | |
236 auto it = interface_provider_specs_.find(spec); | |
220 return it != interface_provider_specs_.end() ? it->second : empty_spec_; | 237 return it != interface_provider_specs_.end() ? it->second : empty_spec_; |
221 } | 238 } |
239 | |
222 const Identity& identity() const { return identity_; } | 240 const Identity& identity() const { return identity_; } |
223 void set_identity(const Identity& identity) { identity_ = identity; } | 241 void set_identity(const Identity& identity) { identity_ = identity; } |
224 uint32_t id() const { return id_; } | 242 uint32_t id() const { return id_; } |
225 | 243 |
226 // Service: | 244 // Service: |
227 void OnBindInterface(const ServiceInfo& source_info, | 245 void OnBindInterface(const ServiceInfo& source_info, |
228 const std::string& interface_name, | 246 const std::string& interface_name, |
229 mojo::ScopedMessagePipeHandle interface_pipe) override { | 247 mojo::ScopedMessagePipeHandle interface_pipe) override { |
230 Instance* source = | 248 Instance* source = |
231 service_manager_->GetExistingInstance(source_info.identity); | 249 service_manager_->GetExistingInstance(source_info.identity); |
232 DCHECK(source); | 250 DCHECK(source); |
233 if (interface_name == mojom::ServiceManager::Name_ && | 251 if (interface_name == mojom::ServiceManager::Name_ && |
234 HasCapability(source->GetConnectionSpec(), | 252 HasCapability(source->GetConnectionSpec(), |
235 kCapability_ServiceManager)) { | 253 kCapability_ServiceManager)) { |
236 mojom::ServiceManagerRequest request = | 254 mojom::ServiceManagerRequest request = |
237 mojo::MakeRequest<mojom::ServiceManager>(std::move(interface_pipe)); | 255 mojo::MakeRequest<mojom::ServiceManager>(std::move(interface_pipe)); |
238 service_manager_bindings_.AddBinding(this, std::move(request)); | 256 service_manager_bindings_.AddBinding(this, std::move(request)); |
239 } | 257 } |
240 } | 258 } |
241 | 259 |
242 private: | 260 private: |
243 enum class State { | 261 enum class State { |
244 // The service was not started yet. | 262 // The service was not started yet. |
245 IDLE, | 263 IDLE, |
246 | 264 |
247 // The service was started but the service manager hasn't received the | 265 // The service was started but the service manager hasn't received the |
248 // initial response from it yet. | 266 // initial response from it yet. |
249 STARTING, | 267 STARTING, |
250 | 268 |
251 // The service was started successfully. | 269 // The service was started successfully. |
252 STARTED | 270 STARTED |
253 }; | 271 }; |
254 | 272 |
273 class InterfaceProviderImpl : public mojom::InterfaceProvider { | |
274 public: | |
275 InterfaceProviderImpl(const std::string& spec, | |
276 const Identity& source_identity, | |
277 const Identity& target_identity, | |
278 service_manager::ServiceManager* service_manager, | |
279 mojom::InterfaceProviderPtr target) | |
280 : spec_(spec), | |
281 source_identity_(source_identity), | |
282 target_identity_(target_identity), | |
283 service_manager_(service_manager), | |
284 target_(std::move(target)) {} | |
285 ~InterfaceProviderImpl() override {} | |
286 | |
287 private: | |
288 // mojom::InterfaceProvider: | |
289 void GetInterface(const std::string& interface_name, | |
290 mojo::ScopedMessagePipeHandle interface_pipe) override { | |
291 Instance* source = | |
292 service_manager_->GetExistingInstance(source_identity_); | |
293 Instance* target = | |
294 service_manager_->GetExistingInstance(target_identity_); | |
295 if (!source || !target) | |
296 return; | |
297 if (!ValidateSpec(source) || !ValidateSpec(target)) | |
298 return; | |
299 | |
300 if (AllowsInterface(source_identity_, source->GetSpecNamed(spec_), | |
301 target_identity_, target->GetSpecNamed(spec_), | |
302 interface_name)) { | |
303 target_->GetInterface(interface_name, std::move(interface_pipe)); | |
304 } | |
305 } | |
306 | |
307 bool ValidateSpec(Instance* instance) const { | |
308 if (!instance->HasSpecNamed(spec_)) { | |
309 LOG(ERROR) << "Instance for: " << instance->identity().name() | |
310 << " did not have spec named: " << spec_; | |
311 return false; | |
312 } | |
313 return true; | |
314 } | |
315 | |
316 const std::string spec_; | |
317 const Identity source_identity_; | |
318 const Identity target_identity_; | |
319 service_manager::ServiceManager* service_manager_; | |
Ken Rockot(use gerrit already)
2017/04/26 04:32:48
nit: this could be const too (service_manager::Ser
| |
320 | |
321 mojom::InterfaceProviderPtr target_; | |
322 | |
323 DISALLOW_COPY_AND_ASSIGN(InterfaceProviderImpl); | |
324 }; | |
325 | |
255 // mojom::Connector implementation: | 326 // mojom::Connector implementation: |
256 void BindInterface(const service_manager::Identity& in_target, | 327 void BindInterface(const service_manager::Identity& in_target, |
257 const std::string& interface_name, | 328 const std::string& interface_name, |
258 mojo::ScopedMessagePipeHandle interface_pipe, | 329 mojo::ScopedMessagePipeHandle interface_pipe, |
259 const BindInterfaceCallback& callback) override { | 330 const BindInterfaceCallback& callback) override { |
260 Identity target = in_target; | 331 Identity target = in_target; |
261 mojom::ConnectResult result = | 332 mojom::ConnectResult result = |
262 ValidateConnectParams(&target, nullptr, nullptr); | 333 ValidateConnectParams(&target, nullptr, nullptr); |
263 if (!Succeeded(result)) { | 334 if (!Succeeded(result)) { |
264 callback.Run(result, Identity()); | 335 callback.Run(result, Identity()); |
265 return; | 336 return; |
266 } | 337 } |
267 | 338 |
268 std::unique_ptr<ConnectParams> params(new ConnectParams); | 339 std::unique_ptr<ConnectParams> params(new ConnectParams); |
269 params->set_source(identity_); | 340 params->set_source(identity_); |
270 params->set_target(target); | 341 params->set_target(target); |
271 params->set_interface_request_info(interface_name, | 342 params->set_interface_request_info(interface_name, |
272 std::move(interface_pipe)); | 343 std::move(interface_pipe)); |
273 params->set_start_service_callback(callback); | 344 params->set_start_service_callback(callback); |
274 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); | 345 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
275 } | 346 } |
276 | 347 |
277 void StartService(const Identity& in_target, | 348 void StartService(const Identity& in_target, |
278 const StartServiceCallback& callback) override { | 349 const StartServiceCallback& callback) override { |
279 Identity target = in_target; | 350 Identity target = in_target; |
280 mojom::ConnectResult result = | 351 mojom::ConnectResult result = |
281 ValidateConnectParams(&target, nullptr, nullptr); | 352 ValidateConnectParams(&target, nullptr, nullptr); |
282 if (!Succeeded(result)) { | 353 if (!Succeeded(result)) { |
283 callback.Run(result, Identity()); | 354 callback.Run(result, Identity()); |
284 return; | 355 return; |
285 } | 356 } |
286 | 357 |
287 std::unique_ptr<ConnectParams> params(new ConnectParams); | 358 std::unique_ptr<ConnectParams> params(new ConnectParams); |
288 params->set_source(identity_); | 359 params->set_source(identity_); |
289 params->set_target(target); | 360 params->set_target(target); |
290 params->set_start_service_callback(callback); | 361 params->set_start_service_callback(callback); |
291 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); | 362 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
292 } | 363 } |
293 | 364 |
294 void StartServiceWithProcess( | 365 void StartServiceWithProcess( |
295 const Identity& in_target, | 366 const Identity& in_target, |
296 mojo::ScopedMessagePipeHandle service_handle, | 367 mojo::ScopedMessagePipeHandle service_handle, |
297 mojom::PIDReceiverRequest pid_receiver_request, | 368 mojom::PIDReceiverRequest pid_receiver_request, |
298 const StartServiceWithProcessCallback& callback) override { | 369 const StartServiceWithProcessCallback& callback) override { |
299 Identity target = in_target; | 370 Identity target = in_target; |
300 mojom::ConnectResult result = | 371 mojom::ConnectResult result = |
301 ValidateConnectParams(&target, nullptr, nullptr); | 372 ValidateConnectParams(&target, nullptr, nullptr); |
302 if (!Succeeded(result)) { | 373 if (!Succeeded(result)) { |
303 callback.Run(result, Identity()); | 374 callback.Run(result, Identity()); |
304 return; | 375 return; |
305 } | 376 } |
306 | 377 |
307 std::unique_ptr<ConnectParams> params(new ConnectParams); | 378 std::unique_ptr<ConnectParams> params(new ConnectParams); |
308 params->set_source(identity_); | 379 params->set_source(identity_); |
309 params->set_target(target); | 380 params->set_target(target); |
310 | 381 |
311 mojom::ServicePtr service; | 382 mojom::ServicePtr service; |
312 service.Bind(mojom::ServicePtrInfo(std::move(service_handle), 0)); | 383 service.Bind(mojom::ServicePtrInfo(std::move(service_handle), 0)); |
313 params->set_client_process_info(std::move(service), | 384 params->set_client_process_info(std::move(service), |
314 std::move(pid_receiver_request)); | 385 std::move(pid_receiver_request)); |
315 params->set_start_service_callback(callback); | 386 params->set_start_service_callback(callback); |
316 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); | 387 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
317 } | 388 } |
318 | 389 |
319 void Clone(mojom::ConnectorRequest request) override { | 390 void Clone(mojom::ConnectorRequest request) override { |
320 connectors_.AddBinding(this, std::move(request)); | 391 connectors_.AddBinding(this, std::move(request)); |
321 } | 392 } |
322 | 393 |
394 void ApplySpec(const std::string& spec, | |
395 const Identity& source, | |
396 mojom::InterfaceProviderRequest source_request, | |
397 mojom::InterfaceProviderPtr target) override { | |
398 mojo::MakeStrongBinding( | |
Ken Rockot(use gerrit already)
2017/04/26 04:32:48
It's not safe to use StrongBinding here if you're
| |
399 base::MakeUnique<InterfaceProviderImpl>( | |
400 spec, source, identity_, service_manager_, std::move(target)), | |
401 std::move(source_request)); | |
402 } | |
403 | |
323 // mojom::PIDReceiver: | 404 // mojom::PIDReceiver: |
324 void SetPID(uint32_t pid) override { | 405 void SetPID(uint32_t pid) override { |
325 PIDAvailable(pid); | 406 PIDAvailable(pid); |
326 } | 407 } |
327 | 408 |
328 // mojom::ServiceManager implementation: | 409 // mojom::ServiceManager implementation: |
329 void AddListener(mojom::ServiceManagerListenerPtr listener) override { | 410 void AddListener(mojom::ServiceManagerListenerPtr listener) override { |
330 // TODO(beng): this should only track the instances matching this user, and | 411 // TODO(beng): this should only track the instances matching this user, and |
331 // root. | 412 // root. |
332 service_manager_->AddListener(std::move(listener)); | 413 service_manager_->AddListener(std::move(listener)); |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1000 instance->identity()); | 1081 instance->identity()); |
1001 if (params->HasInterfaceRequestInfo()) | 1082 if (params->HasInterfaceRequestInfo()) |
1002 instance->CallOnBindInterface(¶ms); | 1083 instance->CallOnBindInterface(¶ms); |
1003 } | 1084 } |
1004 | 1085 |
1005 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { | 1086 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { |
1006 return weak_ptr_factory_.GetWeakPtr(); | 1087 return weak_ptr_factory_.GetWeakPtr(); |
1007 } | 1088 } |
1008 | 1089 |
1009 } // namespace service_manager | 1090 } // namespace service_manager |
OLD | NEW |