Chromium Code Reviews| 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 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 public: | 118 public: |
| 119 Instance(service_manager::ServiceManager* service_manager, | 119 Instance(service_manager::ServiceManager* service_manager, |
| 120 const Identity& identity, | 120 const Identity& identity, |
| 121 const InterfaceProviderSpec& connection_spec) | 121 const InterfaceProviderSpec& connection_spec) |
| 122 : service_manager_(service_manager), | 122 : service_manager_(service_manager), |
| 123 id_(GenerateUniqueID()), | 123 id_(GenerateUniqueID()), |
| 124 identity_(identity), | 124 identity_(identity), |
| 125 connection_spec_(connection_spec), | 125 connection_spec_(connection_spec), |
| 126 allow_any_application_(connection_spec.requires.count("*") == 1), | 126 allow_any_application_(connection_spec.requires.count("*") == 1), |
| 127 pid_receiver_binding_(this), | 127 pid_receiver_binding_(this), |
| 128 state_(State::IDLE), | |
| 128 weak_factory_(this) { | 129 weak_factory_(this) { |
| 129 if (identity_.name() == kServiceManagerName || | 130 if (identity_.name() == kServiceManagerName || |
| 130 identity_.name() == kCatalogName) { | 131 identity_.name() == kCatalogName) { |
| 131 pid_ = base::Process::Current().Pid(); | 132 pid_ = base::Process::Current().Pid(); |
| 132 } | 133 } |
| 133 DCHECK_NE(mojom::kInvalidInstanceID, id_); | 134 DCHECK_NE(mojom::kInvalidInstanceID, id_); |
| 134 } | 135 } |
| 135 | 136 |
| 136 ~Instance() override { | 137 ~Instance() override { |
| 137 // Shutdown all bindings before we close the runner. This way the process | 138 // Shutdown all bindings before we close the runner. This way the process |
| 138 // should see the pipes closed and exit, as well as waking up any potential | 139 // should see the pipes closed and exit, as well as waking up any potential |
| 139 // sync/WaitForIncomingResponse(). | 140 // sync/WaitForIncomingResponse(). |
| 140 service_.reset(); | 141 service_.reset(); |
| 141 if (pid_receiver_binding_.is_bound()) | 142 if (pid_receiver_binding_.is_bound()) |
| 142 pid_receiver_binding_.Close(); | 143 pid_receiver_binding_.Close(); |
| 143 connectors_.CloseAllBindings(); | 144 connectors_.CloseAllBindings(); |
| 144 service_manager_bindings_.CloseAllBindings(); | 145 service_manager_bindings_.CloseAllBindings(); |
| 145 | 146 |
| 146 // Notify the ServiceManager that this Instance is really going away. | 147 if (state_ == State::STARTING) { |
| 147 service_manager_->OnInstanceStopped(identity_); | 148 service_manager_->NotifyServiceFailedToStart(identity_); |
| 149 } else { | |
| 150 // Notify the ServiceManager that this Instance is really going away. | |
| 151 service_manager_->OnInstanceStopped(identity_); | |
| 152 } | |
| 148 | 153 |
| 149 // Release |runner_| so that if we are called back to OnRunnerCompleted() | 154 // Release |runner_| so that if we are called back to OnRunnerCompleted() |
| 150 // we know we're in the destructor. | 155 // we know we're in the destructor. |
| 151 std::unique_ptr<NativeRunner> runner = std::move(runner_); | 156 std::unique_ptr<NativeRunner> runner = std::move(runner_); |
| 152 runner.reset(); | 157 runner.reset(); |
| 153 } | 158 } |
| 154 | 159 |
| 155 Instance* parent() { return parent_; } | 160 Instance* parent() const { return parent_; } |
| 156 | 161 |
| 157 void AddChild(std::unique_ptr<Instance> child) { | 162 void AddChild(std::unique_ptr<Instance> child) { |
| 158 child->parent_ = this; | 163 child->parent_ = this; |
| 159 children_.insert(std::make_pair(child.get(), std::move(child))); | 164 children_.insert(std::make_pair(child.get(), std::move(child))); |
| 160 } | 165 } |
| 161 | 166 |
| 162 void RemoveChild(Instance* child) { | 167 void RemoveChild(Instance* child) { |
| 163 auto it = children_.find(child); | 168 auto it = children_.find(child); |
| 164 DCHECK(it != children_.end()); | 169 DCHECK(it != children_.end()); |
| 165 | 170 |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 195 interfaces.erase("*"); | 200 interfaces.erase("*"); |
| 196 } | 201 } |
| 197 | 202 |
| 198 service_->OnConnect(params->source(), params->TakeRemoteInterfaces(), | 203 service_->OnConnect(params->source(), params->TakeRemoteInterfaces(), |
| 199 interfaces, capabilities); | 204 interfaces, capabilities); |
| 200 return true; | 205 return true; |
| 201 } | 206 } |
| 202 | 207 |
| 203 void StartWithService(mojom::ServicePtr service) { | 208 void StartWithService(mojom::ServicePtr service) { |
| 204 CHECK(!service_); | 209 CHECK(!service_); |
| 210 state_ = State::STARTING; | |
| 205 service_ = std::move(service); | 211 service_ = std::move(service); |
| 206 service_.set_connection_error_handler( | 212 service_.set_connection_error_handler( |
| 207 base::Bind(&Instance::OnServiceLost, base::Unretained(this), | 213 base::Bind(&Instance::OnServiceLost, base::Unretained(this), |
| 208 service_manager_->GetWeakPtr())); | 214 service_manager_->GetWeakPtr())); |
| 209 service_->OnStart(identity_, | 215 service_->OnStart(identity_, |
| 210 base::Bind(&Instance::OnInitializeResponse, | 216 base::Bind(&Instance::OnInitializeResponse, |
| 211 base::Unretained(this))); | 217 base::Unretained(this))); |
| 212 } | 218 } |
| 213 | 219 |
| 214 void StartWithClientProcessConnection( | 220 void StartWithClientProcessConnection( |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 237 info->id = id_; | 243 info->id = id_; |
| 238 info->identity = identity_; | 244 info->identity = identity_; |
| 239 info->pid = pid_; | 245 info->pid = pid_; |
| 240 return info; | 246 return info; |
| 241 } | 247 } |
| 242 | 248 |
| 243 const InterfaceProviderSpec& connection_spec() const { | 249 const InterfaceProviderSpec& connection_spec() const { |
| 244 return connection_spec_; | 250 return connection_spec_; |
| 245 } | 251 } |
| 246 const Identity& identity() const { return identity_; } | 252 const Identity& identity() const { return identity_; } |
| 253 void set_identity(const Identity& identity) { identity_ = identity; } | |
| 247 uint32_t id() const { return id_; } | 254 uint32_t id() const { return id_; } |
| 248 | 255 |
| 249 // Service: | 256 // Service: |
| 250 bool OnConnect(const Identity& remote_identity, | 257 bool OnConnect(const Identity& remote_identity, |
| 251 InterfaceRegistry* registry) override { | 258 InterfaceRegistry* registry) override { |
| 252 Instance* source = service_manager_->GetExistingInstance(remote_identity); | 259 Instance* source = service_manager_->GetExistingInstance(remote_identity); |
| 253 DCHECK(source); | 260 DCHECK(source); |
| 254 if (HasCapability(source->connection_spec_, kCapability_ServiceManager)) { | 261 if (HasCapability(source->connection_spec_, kCapability_ServiceManager)) { |
| 255 registry->AddInterface<mojom::ServiceManager>(this); | 262 registry->AddInterface<mojom::ServiceManager>(this); |
| 256 return true; | 263 return true; |
| 257 } | 264 } |
| 258 return false; | 265 return false; |
| 259 } | 266 } |
| 260 | 267 |
| 261 private: | 268 private: |
| 269 enum class State { | |
| 270 // This connection was not started yet. | |
|
Ken Rockot(use gerrit already)
2016/10/21 19:52:33
nit: in these comments I think s/connection/instan
Jay Civelli
2016/10/21 20:48:33
Done.
| |
| 271 IDLE, | |
| 272 | |
| 273 // The connection was started but no success was reported. | |
| 274 STARTING, | |
| 275 | |
| 276 // The connection was started successfully. | |
| 277 STARTED | |
| 278 }; | |
| 279 | |
| 262 // mojom::Connector implementation: | 280 // mojom::Connector implementation: |
| 263 void Connect(const service_manager::Identity& in_target, | 281 void Connect(const service_manager::Identity& in_target, |
| 264 mojom::InterfaceProviderRequest remote_interfaces, | 282 mojom::InterfaceProviderRequest remote_interfaces, |
| 265 mojom::ClientProcessConnectionPtr client_process_connection, | 283 mojom::ClientProcessConnectionPtr client_process_connection, |
| 266 const ConnectCallback& callback) override { | 284 const ConnectCallback& callback) override { |
| 267 Identity target = in_target; | 285 Identity target = in_target; |
| 268 if (target.user_id() == mojom::kInheritUserID) | 286 if (target.user_id() == mojom::kInheritUserID) |
| 269 target.set_user_id(identity_.user_id()); | 287 target.set_user_id(identity_.user_id()); |
| 270 | 288 |
| 271 if (!ValidateIdentity(target, callback)) | 289 if (!ValidateIdentity(target, callback)) |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 409 CHECK_NE(mojom::kInvalidInstanceID, id); | 427 CHECK_NE(mojom::kInvalidInstanceID, id); |
| 410 return id; | 428 return id; |
| 411 } | 429 } |
| 412 | 430 |
| 413 void PIDAvailable(base::ProcessId pid) { | 431 void PIDAvailable(base::ProcessId pid) { |
| 414 if (pid == base::kNullProcessId) { | 432 if (pid == base::kNullProcessId) { |
| 415 service_manager_->OnInstanceError(this); | 433 service_manager_->OnInstanceError(this); |
| 416 return; | 434 return; |
| 417 } | 435 } |
| 418 pid_ = pid; | 436 pid_ = pid; |
| 419 service_manager_->NotifyPIDAvailable(identity_, pid_); | |
| 420 } | 437 } |
| 421 | 438 |
| 422 void OnServiceLost( | 439 void OnServiceLost( |
| 423 base::WeakPtr<service_manager::ServiceManager> service_manager) { | 440 base::WeakPtr<service_manager::ServiceManager> service_manager) { |
| 424 service_.reset(); | 441 service_.reset(); |
| 425 OnConnectionLost(service_manager); | 442 OnConnectionLost(service_manager); |
| 426 } | 443 } |
| 427 | 444 |
| 428 void OnConnectionLost( | 445 void OnConnectionLost( |
| 429 base::WeakPtr<service_manager::ServiceManager> service_manager) { | 446 base::WeakPtr<service_manager::ServiceManager> service_manager) { |
| 430 // Any time a Connector is lost or we lose the Service connection, it | 447 // Any time a Connector is lost or we lose the Service connection, it |
| 431 // may have been the last pipe using this Instance. If so, clean up. | 448 // may have been the last pipe using this Instance. If so, clean up. |
| 432 if (service_manager && !service_) { | 449 if (service_manager && !service_) { |
| 433 if (connectors_.empty()) | 450 if (connectors_.empty()) |
| 434 service_manager->OnInstanceError(this); | 451 service_manager->OnInstanceError(this); |
| 435 else | 452 else |
| 436 service_manager->OnInstanceUnreachable(this); | 453 service_manager->OnInstanceUnreachable(this); |
| 437 } | 454 } |
| 438 } | 455 } |
| 439 | 456 |
| 440 void OnInitializeResponse(mojom::ConnectorRequest connector_request) { | 457 void OnInitializeResponse(mojom::ConnectorRequest connector_request) { |
| 458 state_ = State::STARTED; | |
| 441 if (connector_request.is_pending()) { | 459 if (connector_request.is_pending()) { |
| 442 connectors_.AddBinding(this, std::move(connector_request)); | 460 connectors_.AddBinding(this, std::move(connector_request)); |
| 443 connectors_.set_connection_error_handler( | 461 connectors_.set_connection_error_handler( |
| 444 base::Bind(&Instance::OnConnectionLost, base::Unretained(this), | 462 base::Bind(&Instance::OnConnectionLost, base::Unretained(this), |
| 445 service_manager_->GetWeakPtr())); | 463 service_manager_->GetWeakPtr())); |
| 446 } | 464 } |
| 465 service_manager_->NotifyServiceStarted(identity_, pid_); | |
| 447 } | 466 } |
| 448 | 467 |
| 449 // Callback when NativeRunner completes. | 468 // Callback when NativeRunner completes. |
| 450 void OnRunnerCompleted() { | 469 void OnRunnerCompleted() { |
| 451 if (!runner_.get()) | 470 if (!runner_.get()) |
| 452 return; // We're in the destructor. | 471 return; // We're in the destructor. |
| 453 | 472 |
| 454 service_manager_->OnInstanceError(this); | 473 service_manager_->OnInstanceError(this); |
| 455 } | 474 } |
| 456 | 475 |
| 457 service_manager::ServiceManager* const service_manager_; | 476 service_manager::ServiceManager* const service_manager_; |
| 458 | 477 |
| 459 // An id that identifies this instance. Distinct from pid, as a single process | 478 // An id that identifies this instance. Distinct from pid, as a single process |
| 460 // may vend multiple application instances, and this object may exist before a | 479 // may vend multiple application instances, and this object may exist before a |
| 461 // process is launched. | 480 // process is launched. |
| 462 const uint32_t id_; | 481 const uint32_t id_; |
| 463 const Identity identity_; | 482 Identity identity_; |
| 464 const InterfaceProviderSpec connection_spec_; | 483 const InterfaceProviderSpec connection_spec_; |
| 465 const bool allow_any_application_; | 484 const bool allow_any_application_; |
| 466 std::unique_ptr<NativeRunner> runner_; | 485 std::unique_ptr<NativeRunner> runner_; |
| 467 mojom::ServicePtr service_; | 486 mojom::ServicePtr service_; |
| 468 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; | 487 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; |
| 469 mojo::BindingSet<mojom::Connector> connectors_; | 488 mojo::BindingSet<mojom::Connector> connectors_; |
| 470 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_; | 489 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_; |
| 471 base::ProcessId pid_ = base::kNullProcessId; | 490 base::ProcessId pid_ = base::kNullProcessId; |
| 472 Instance* parent_ = nullptr; | 491 Instance* parent_ = nullptr; |
| 473 InstanceMap children_; | 492 InstanceMap children_; |
| 493 State state_; | |
| 474 base::WeakPtrFactory<Instance> weak_factory_; | 494 base::WeakPtrFactory<Instance> weak_factory_; |
| 475 | 495 |
| 476 DISALLOW_COPY_AND_ASSIGN(Instance); | 496 DISALLOW_COPY_AND_ASSIGN(Instance); |
| 477 }; | 497 }; |
| 478 | 498 |
| 479 // static | 499 // static |
| 480 ServiceManager::TestAPI::TestAPI(ServiceManager* service_manager) | 500 ServiceManager::TestAPI::TestAPI(ServiceManager* service_manager) |
| 481 : service_manager_(service_manager) {} | 501 : service_manager_(service_manager) {} |
| 482 ServiceManager::TestAPI::~TestAPI() {} | 502 ServiceManager::TestAPI::~TestAPI() {} |
| 483 | 503 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 685 for (auto entry : identity_to_instance_) { | 705 for (auto entry : identity_to_instance_) { |
| 686 if (entry.first.name() == identity.name() && | 706 if (entry.first.name() == identity.name() && |
| 687 entry.first.instance() == identity.instance()) { | 707 entry.first.instance() == identity.instance()) { |
| 688 return entry.second; | 708 return entry.second; |
| 689 } | 709 } |
| 690 } | 710 } |
| 691 } | 711 } |
| 692 return nullptr; | 712 return nullptr; |
| 693 } | 713 } |
| 694 | 714 |
| 695 void ServiceManager::NotifyPIDAvailable(const Identity& identity, | 715 void ServiceManager::NotifyServiceStarted(const Identity& identity, |
| 696 base::ProcessId pid) { | 716 base::ProcessId pid) { |
| 697 listeners_.ForAllPtrs( | 717 listeners_.ForAllPtrs( |
| 698 [identity, pid](mojom::ServiceManagerListener* listener) { | 718 [identity, pid](mojom::ServiceManagerListener* listener) { |
| 699 listener->OnServiceStarted(identity, pid); | 719 listener->OnServiceStarted(identity, pid); |
| 700 }); | 720 }); |
| 701 } | 721 } |
| 702 | 722 |
| 723 void ServiceManager::NotifyServiceFailedToStart(const Identity& identity) { | |
| 724 listeners_.ForAllPtrs( | |
| 725 [identity](mojom::ServiceManagerListener* listener) { | |
| 726 listener->OnServiceFailedToStart(identity); | |
| 727 }); | |
| 728 } | |
| 729 | |
| 703 bool ServiceManager::ConnectToExistingInstance( | 730 bool ServiceManager::ConnectToExistingInstance( |
| 704 std::unique_ptr<ConnectParams>* params) { | 731 std::unique_ptr<ConnectParams>* params) { |
| 705 Instance* instance = GetExistingInstance((*params)->target()); | 732 Instance* instance = GetExistingInstance((*params)->target()); |
| 706 return instance && instance->ConnectToService(params); | 733 return instance && instance->ConnectToService(params); |
| 707 } | 734 } |
| 708 | 735 |
| 709 ServiceManager::Instance* ServiceManager::CreateInstance( | 736 ServiceManager::Instance* ServiceManager::CreateInstance( |
| 710 const Identity& source, | 737 const Identity& source, |
| 711 const Identity& target, | 738 const Identity& target, |
| 712 const InterfaceProviderSpec& connection_spec) { | 739 const InterfaceProviderSpec& connection_spec) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 794 if (instance_name == GetNamePath(params->target().name()) && | 821 if (instance_name == GetNamePath(params->target().name()) && |
| 795 result->qualifier != GetNamePath(result->resolved_name)) { | 822 result->qualifier != GetNamePath(result->resolved_name)) { |
| 796 instance_name = result->qualifier; | 823 instance_name = result->qualifier; |
| 797 } | 824 } |
| 798 // |result->connection_spec| can be null when there is no manifest, e.g. for | 825 // |result->connection_spec| can be null when there is no manifest, e.g. for |
| 799 // URL types not resolvable by the resolver. | 826 // URL types not resolvable by the resolver. |
| 800 InterfaceProviderSpec connection_spec = GetPermissiveInterfaceProviderSpec(); | 827 InterfaceProviderSpec connection_spec = GetPermissiveInterfaceProviderSpec(); |
| 801 if (result->connection_spec.has_value()) | 828 if (result->connection_spec.has_value()) |
| 802 connection_spec = result->connection_spec.value(); | 829 connection_spec = result->connection_spec.value(); |
| 803 | 830 |
| 831 const Identity original_target(params->target()); | |
| 804 const std::string user_id = | 832 const std::string user_id = |
| 805 HasCapability(connection_spec, kCapability_AllUsers) | 833 HasCapability(connection_spec, kCapability_AllUsers) |
| 806 ? base::GenerateGUID() : params->target().user_id(); | 834 ? base::GenerateGUID() : params->target().user_id(); |
| 807 const Identity target(params->target().name(), user_id, instance_name); | 835 const Identity target(params->target().name(), user_id, instance_name); |
| 808 params->set_target(target); | 836 params->set_target(target); |
| 809 | 837 |
| 810 // It's possible that when this manifest request was issued, another one was | 838 // It's possible that when this manifest request was issued, another one was |
| 811 // already in-progress and completed by the time this one did, and so the | 839 // already in-progress and completed by the time this one did, and so the |
| 812 // requested application may already be running. | 840 // requested application may already be running. |
| 813 if (ConnectToExistingInstance(¶ms)) | 841 if (ConnectToExistingInstance(¶ms)) |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 844 // Likewise if a ClientProcessConnection was given via Connect(), it | 872 // Likewise if a ClientProcessConnection was given via Connect(), it |
| 845 // provides the Service proxy to use. | 873 // provides the Service proxy to use. |
| 846 instance->StartWithClientProcessConnection( | 874 instance->StartWithClientProcessConnection( |
| 847 std::move(client_process_connection)); | 875 std::move(client_process_connection)); |
| 848 } else { | 876 } else { |
| 849 // Otherwise we create a new Service pipe. | 877 // Otherwise we create a new Service pipe. |
| 850 mojom::ServiceRequest request = GetProxy(&service); | 878 mojom::ServiceRequest request = GetProxy(&service); |
| 851 CHECK(!result->package_path.empty() && result->connection_spec.has_value()); | 879 CHECK(!result->package_path.empty() && result->connection_spec.has_value()); |
| 852 | 880 |
| 853 if (target.name() != result->resolved_name) { | 881 if (target.name() != result->resolved_name) { |
| 882 // When part of a packaged app, use the original user ID. | |
|
Ken Rockot(use gerrit already)
2016/10/21 19:52:33
nit: s/app/service/
Jay Civelli
2016/10/21 20:48:33
Done.
| |
| 883 Identity packaged_app_target(target); | |
| 884 packaged_app_target.set_user_id(original_target.user_id()); | |
| 885 instance->set_identity(packaged_app_target); | |
| 854 instance->StartWithService(std::move(service)); | 886 instance->StartWithService(std::move(service)); |
| 855 Identity factory(result->resolved_name, target.user_id(), | 887 Identity factory(result->resolved_name, original_target.user_id(), |
| 856 instance_name); | 888 instance_name); |
| 857 CreateServiceWithFactory(factory, target.name(), std::move(request)); | 889 CreateServiceWithFactory(factory, target.name(), std::move(request)); |
| 858 } else { | 890 } else { |
| 859 base::FilePath package_path; | 891 base::FilePath package_path; |
| 860 if (!service_overrides_ || !service_overrides_->GetExecutablePathOverride( | 892 if (!service_overrides_ || !service_overrides_->GetExecutablePathOverride( |
| 861 target.name(), &package_path)) { | 893 target.name(), &package_path)) { |
| 862 package_path = result->package_path; | 894 package_path = result->package_path; |
| 863 } | 895 } |
| 864 | 896 |
| 865 Identity source_instance_identity; | 897 Identity source_instance_identity; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 882 // Now that the instance has a Service, we can connect to it. | 914 // Now that the instance has a Service, we can connect to it. |
| 883 bool connected = instance->ConnectToService(¶ms); | 915 bool connected = instance->ConnectToService(¶ms); |
| 884 DCHECK(connected); | 916 DCHECK(connected); |
| 885 } | 917 } |
| 886 | 918 |
| 887 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { | 919 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { |
| 888 return weak_ptr_factory_.GetWeakPtr(); | 920 return weak_ptr_factory_.GetWeakPtr(); |
| 889 } | 921 } |
| 890 | 922 |
| 891 } // namespace service_manager | 923 } // namespace service_manager |
| OLD | NEW |