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 GetSpec(mojom::kServiceManager_ConnectorSpec); |
219 mojom::kServiceManager_ConnectorSpec); | 230 } |
| 231 bool HasSpec(const std::string& spec) const { |
| 232 auto it = interface_provider_specs_.find(spec); |
| 233 return it != interface_provider_specs_.end(); |
| 234 } |
| 235 const InterfaceProviderSpec& GetSpec(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 mojom::InterfaceProviderRequest source_request) |
| 281 : spec_(spec), |
| 282 source_identity_(source_identity), |
| 283 target_identity_(target_identity), |
| 284 service_manager_(service_manager), |
| 285 target_(std::move(target)), |
| 286 source_binding_(this, std::move(source_request)) {} |
| 287 ~InterfaceProviderImpl() override {} |
| 288 |
| 289 private: |
| 290 // mojom::InterfaceProvider: |
| 291 void GetInterface(const std::string& interface_name, |
| 292 mojo::ScopedMessagePipeHandle interface_pipe) override { |
| 293 Instance* source = |
| 294 service_manager_->GetExistingInstance(source_identity_); |
| 295 Instance* target = |
| 296 service_manager_->GetExistingInstance(target_identity_); |
| 297 if (!source || !target) |
| 298 return; |
| 299 if (!ValidateSpec(source) || !ValidateSpec(target)) |
| 300 return; |
| 301 |
| 302 if (AllowsInterface(source_identity_, source->GetSpec(spec_), |
| 303 target_identity_, target->GetSpec(spec_), |
| 304 interface_name)) { |
| 305 target_->GetInterface(interface_name, std::move(interface_pipe)); |
| 306 } |
| 307 } |
| 308 |
| 309 bool ValidateSpec(Instance* instance) const { |
| 310 if (!instance->HasSpec(spec_)) { |
| 311 LOG(ERROR) << "Instance for: " << instance->identity().name() |
| 312 << " did not have spec named: " << spec_; |
| 313 return false; |
| 314 } |
| 315 return true; |
| 316 } |
| 317 |
| 318 const std::string spec_; |
| 319 const Identity source_identity_; |
| 320 const Identity target_identity_; |
| 321 const service_manager::ServiceManager* service_manager_; |
| 322 |
| 323 mojom::InterfaceProviderPtr target_; |
| 324 mojo::Binding<mojom::InterfaceProvider> source_binding_; |
| 325 |
| 326 DISALLOW_COPY_AND_ASSIGN(InterfaceProviderImpl); |
| 327 }; |
| 328 |
255 // mojom::Connector implementation: | 329 // mojom::Connector implementation: |
256 void BindInterface(const service_manager::Identity& in_target, | 330 void BindInterface(const service_manager::Identity& in_target, |
257 const std::string& interface_name, | 331 const std::string& interface_name, |
258 mojo::ScopedMessagePipeHandle interface_pipe, | 332 mojo::ScopedMessagePipeHandle interface_pipe, |
259 const BindInterfaceCallback& callback) override { | 333 const BindInterfaceCallback& callback) override { |
260 Identity target = in_target; | 334 Identity target = in_target; |
261 mojom::ConnectResult result = | 335 mojom::ConnectResult result = |
262 ValidateConnectParams(&target, nullptr, nullptr); | 336 ValidateConnectParams(&target, nullptr, nullptr); |
263 if (!Succeeded(result)) { | 337 if (!Succeeded(result)) { |
264 callback.Run(result, Identity()); | 338 callback.Run(result, Identity()); |
265 return; | 339 return; |
266 } | 340 } |
267 | 341 |
268 std::unique_ptr<ConnectParams> params(new ConnectParams); | 342 std::unique_ptr<ConnectParams> params(new ConnectParams); |
269 params->set_source(identity_); | 343 params->set_source(identity_); |
270 params->set_target(target); | 344 params->set_target(target); |
271 params->set_interface_request_info(interface_name, | 345 params->set_interface_request_info(interface_name, |
272 std::move(interface_pipe)); | 346 std::move(interface_pipe)); |
273 params->set_start_service_callback(callback); | 347 params->set_start_service_callback(callback); |
274 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); | 348 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
275 } | 349 } |
276 | 350 |
277 void StartService(const Identity& in_target, | 351 void StartService(const Identity& in_target, |
278 const StartServiceCallback& callback) override { | 352 const StartServiceCallback& callback) override { |
279 Identity target = in_target; | 353 Identity target = in_target; |
280 mojom::ConnectResult result = | 354 mojom::ConnectResult result = |
281 ValidateConnectParams(&target, nullptr, nullptr); | 355 ValidateConnectParams(&target, nullptr, nullptr); |
282 if (!Succeeded(result)) { | 356 if (!Succeeded(result)) { |
283 callback.Run(result, Identity()); | 357 callback.Run(result, Identity()); |
284 return; | 358 return; |
285 } | 359 } |
286 | 360 |
287 std::unique_ptr<ConnectParams> params(new ConnectParams); | 361 std::unique_ptr<ConnectParams> params(new ConnectParams); |
288 params->set_source(identity_); | 362 params->set_source(identity_); |
289 params->set_target(target); | 363 params->set_target(target); |
290 params->set_start_service_callback(callback); | 364 params->set_start_service_callback(callback); |
291 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); | 365 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
292 } | 366 } |
293 | 367 |
294 void StartServiceWithProcess( | 368 void StartServiceWithProcess( |
295 const Identity& in_target, | 369 const Identity& in_target, |
296 mojo::ScopedMessagePipeHandle service_handle, | 370 mojo::ScopedMessagePipeHandle service_handle, |
297 mojom::PIDReceiverRequest pid_receiver_request, | 371 mojom::PIDReceiverRequest pid_receiver_request, |
298 const StartServiceWithProcessCallback& callback) override { | 372 const StartServiceWithProcessCallback& callback) override { |
299 Identity target = in_target; | 373 Identity target = in_target; |
300 mojom::ConnectResult result = | 374 mojom::ConnectResult result = |
301 ValidateConnectParams(&target, nullptr, nullptr); | 375 ValidateConnectParams(&target, nullptr, nullptr); |
302 if (!Succeeded(result)) { | 376 if (!Succeeded(result)) { |
303 callback.Run(result, Identity()); | 377 callback.Run(result, Identity()); |
304 return; | 378 return; |
305 } | 379 } |
306 | 380 |
307 std::unique_ptr<ConnectParams> params(new ConnectParams); | 381 std::unique_ptr<ConnectParams> params(new ConnectParams); |
308 params->set_source(identity_); | 382 params->set_source(identity_); |
309 params->set_target(target); | 383 params->set_target(target); |
310 | 384 |
311 mojom::ServicePtr service; | 385 mojom::ServicePtr service; |
312 service.Bind(mojom::ServicePtrInfo(std::move(service_handle), 0)); | 386 service.Bind(mojom::ServicePtrInfo(std::move(service_handle), 0)); |
313 params->set_client_process_info(std::move(service), | 387 params->set_client_process_info(std::move(service), |
314 std::move(pid_receiver_request)); | 388 std::move(pid_receiver_request)); |
315 params->set_start_service_callback(callback); | 389 params->set_start_service_callback(callback); |
316 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); | 390 service_manager_->Connect(std::move(params), weak_factory_.GetWeakPtr()); |
317 } | 391 } |
318 | 392 |
319 void Clone(mojom::ConnectorRequest request) override { | 393 void Clone(mojom::ConnectorRequest request) override { |
320 connectors_.AddBinding(this, std::move(request)); | 394 connectors_.AddBinding(this, std::move(request)); |
321 } | 395 } |
322 | 396 |
| 397 void FilterInterfaces(const std::string& spec, |
| 398 const Identity& source, |
| 399 mojom::InterfaceProviderRequest source_request, |
| 400 mojom::InterfaceProviderPtr target) override { |
| 401 filters_.push_back(base::MakeUnique<InterfaceProviderImpl>( |
| 402 spec, source, identity_, service_manager_, std::move(target), |
| 403 std::move(source_request))); |
| 404 } |
| 405 |
323 // mojom::PIDReceiver: | 406 // mojom::PIDReceiver: |
324 void SetPID(uint32_t pid) override { | 407 void SetPID(uint32_t pid) override { |
325 PIDAvailable(pid); | 408 PIDAvailable(pid); |
326 } | 409 } |
327 | 410 |
328 // mojom::ServiceManager implementation: | 411 // mojom::ServiceManager implementation: |
329 void AddListener(mojom::ServiceManagerListenerPtr listener) override { | 412 void AddListener(mojom::ServiceManagerListenerPtr listener) override { |
330 // TODO(beng): this should only track the instances matching this user, and | 413 // TODO(beng): this should only track the instances matching this user, and |
331 // root. | 414 // root. |
332 service_manager_->AddListener(std::move(listener)); | 415 service_manager_->AddListener(std::move(listener)); |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
493 const bool allow_any_application_; | 576 const bool allow_any_application_; |
494 std::unique_ptr<ServiceProcessLauncher> runner_; | 577 std::unique_ptr<ServiceProcessLauncher> runner_; |
495 mojom::ServicePtr service_; | 578 mojom::ServicePtr service_; |
496 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; | 579 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; |
497 mojo::BindingSet<mojom::Connector> connectors_; | 580 mojo::BindingSet<mojom::Connector> connectors_; |
498 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_; | 581 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_; |
499 mojo::AssociatedBinding<mojom::ServiceControl> control_binding_; | 582 mojo::AssociatedBinding<mojom::ServiceControl> control_binding_; |
500 base::ProcessId pid_ = base::kNullProcessId; | 583 base::ProcessId pid_ = base::kNullProcessId; |
501 State state_; | 584 State state_; |
502 | 585 |
| 586 std::vector<std::unique_ptr<InterfaceProviderImpl>> filters_; |
| 587 |
503 // The number of outstanding OnBindInterface requests which are in flight. | 588 // The number of outstanding OnBindInterface requests which are in flight. |
504 int pending_service_connections_ = 0; | 589 int pending_service_connections_ = 0; |
505 | 590 |
506 base::WeakPtrFactory<Instance> weak_factory_; | 591 base::WeakPtrFactory<Instance> weak_factory_; |
507 | 592 |
508 DISALLOW_COPY_AND_ASSIGN(Instance); | 593 DISALLOW_COPY_AND_ASSIGN(Instance); |
509 }; | 594 }; |
510 | 595 |
511 class ServiceManager::ServiceImpl : public Service { | 596 class ServiceManager::ServiceImpl : public Service { |
512 public: | 597 public: |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1000 instance->identity()); | 1085 instance->identity()); |
1001 if (params->HasInterfaceRequestInfo()) | 1086 if (params->HasInterfaceRequestInfo()) |
1002 instance->CallOnBindInterface(¶ms); | 1087 instance->CallOnBindInterface(¶ms); |
1003 } | 1088 } |
1004 | 1089 |
1005 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { | 1090 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { |
1006 return weak_ptr_factory_.GetWeakPtr(); | 1091 return weak_ptr_factory_.GetWeakPtr(); |
1007 } | 1092 } |
1008 | 1093 |
1009 } // namespace service_manager | 1094 } // namespace service_manager |
OLD | NEW |