| 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/shell/service_manager.h" | 5 #include "services/shell/service_manager.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 pid_receiver_binding_(this), | 126 pid_receiver_binding_(this), |
| 127 weak_factory_(this) { | 127 weak_factory_(this) { |
| 128 if (identity_.name() == kServiceManagerName || | 128 if (identity_.name() == kServiceManagerName || |
| 129 identity_.name() == kCatalogName) { | 129 identity_.name() == kCatalogName) { |
| 130 pid_ = base::Process::Current().Pid(); | 130 pid_ = base::Process::Current().Pid(); |
| 131 } | 131 } |
| 132 DCHECK_NE(mojom::kInvalidInstanceID, id_); | 132 DCHECK_NE(mojom::kInvalidInstanceID, id_); |
| 133 } | 133 } |
| 134 | 134 |
| 135 ~Instance() override { | 135 ~Instance() override { |
| 136 if (parent_) | |
| 137 parent_->RemoveChild(this); | |
| 138 // |children_| will be modified during destruction. | |
| 139 std::set<Instance*> children = children_; | |
| 140 for (auto* child : children) | |
| 141 service_manager_->OnInstanceError(child, InstanceErrorType::DESTROY); | |
| 142 | |
| 143 // Shutdown all bindings before we close the runner. This way the process | 136 // Shutdown all bindings before we close the runner. This way the process |
| 144 // should see the pipes closed and exit, as well as waking up any potential | 137 // should see the pipes closed and exit, as well as waking up any potential |
| 145 // sync/WaitForIncomingResponse(). | 138 // sync/WaitForIncomingResponse(). |
| 146 service_.reset(); | 139 service_.reset(); |
| 147 if (pid_receiver_binding_.is_bound()) | 140 if (pid_receiver_binding_.is_bound()) |
| 148 pid_receiver_binding_.Close(); | 141 pid_receiver_binding_.Close(); |
| 149 connectors_.CloseAllBindings(); | 142 connectors_.CloseAllBindings(); |
| 150 service_manager_bindings_.CloseAllBindings(); | 143 service_manager_bindings_.CloseAllBindings(); |
| 144 |
| 145 // Notify the ServiceManager that this Instance is really going away. |
| 146 service_manager_->OnInstanceStopped(identity_); |
| 147 |
| 151 // Release |runner_| so that if we are called back to OnRunnerCompleted() | 148 // Release |runner_| so that if we are called back to OnRunnerCompleted() |
| 152 // we know we're in the destructor. | 149 // we know we're in the destructor. |
| 153 std::unique_ptr<NativeRunner> runner = std::move(runner_); | 150 std::unique_ptr<NativeRunner> runner = std::move(runner_); |
| 154 runner.reset(); | 151 runner.reset(); |
| 155 } | 152 } |
| 156 | 153 |
| 157 Instance* parent() { return parent_; } | 154 Instance* parent() { return parent_; } |
| 158 | 155 |
| 159 void AddChild(Instance* child) { | 156 void AddChild(std::unique_ptr<Instance> child) { |
| 160 children_.insert(child); | |
| 161 child->parent_ = this; | 157 child->parent_ = this; |
| 158 children_.insert(std::make_pair(child.get(), std::move(child))); |
| 162 } | 159 } |
| 163 | 160 |
| 164 void RemoveChild(Instance* child) { | 161 void RemoveChild(Instance* child) { |
| 165 auto it = children_.find(child); | 162 auto it = children_.find(child); |
| 166 DCHECK(it != children_.end()); | 163 DCHECK(it != children_.end()); |
| 164 |
| 165 // Deletes |child|. |
| 167 children_.erase(it); | 166 children_.erase(it); |
| 168 child->parent_ = nullptr; | |
| 169 } | 167 } |
| 170 | 168 |
| 171 bool ConnectToService(std::unique_ptr<ConnectParams>* connect_params) { | 169 bool ConnectToService(std::unique_ptr<ConnectParams>* connect_params) { |
| 172 if (!service_.is_bound()) | 170 if (!service_.is_bound()) |
| 173 return false; | 171 return false; |
| 174 | 172 |
| 175 std::unique_ptr<ConnectParams> params(std::move(*connect_params)); | 173 std::unique_ptr<ConnectParams> params(std::move(*connect_params)); |
| 176 if (!params->connect_callback().is_null()) { | 174 if (!params->connect_callback().is_null()) { |
| 177 params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED, | 175 params->connect_callback().Run(mojom::ConnectResult::SUCCEEDED, |
| 178 identity_.user_id()); | 176 identity_.user_id()); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 395 | 393 |
| 396 uint32_t GenerateUniqueID() const { | 394 uint32_t GenerateUniqueID() const { |
| 397 static uint32_t id = mojom::kInvalidInstanceID; | 395 static uint32_t id = mojom::kInvalidInstanceID; |
| 398 ++id; | 396 ++id; |
| 399 CHECK_NE(mojom::kInvalidInstanceID, id); | 397 CHECK_NE(mojom::kInvalidInstanceID, id); |
| 400 return id; | 398 return id; |
| 401 } | 399 } |
| 402 | 400 |
| 403 void PIDAvailable(base::ProcessId pid) { | 401 void PIDAvailable(base::ProcessId pid) { |
| 404 if (pid == base::kNullProcessId) { | 402 if (pid == base::kNullProcessId) { |
| 405 service_manager_->OnInstanceError(this, InstanceErrorType::DESTROY); | 403 service_manager_->OnInstanceError(this); |
| 406 return; | 404 return; |
| 407 } | 405 } |
| 408 pid_ = pid; | 406 pid_ = pid; |
| 409 service_manager_->NotifyPIDAvailable(identity_, pid_); | 407 service_manager_->NotifyPIDAvailable(identity_, pid_); |
| 410 } | 408 } |
| 411 | 409 |
| 412 void OnServiceLost(base::WeakPtr<shell::ServiceManager> service_manager) { | 410 void OnServiceLost(base::WeakPtr<shell::ServiceManager> service_manager) { |
| 413 service_.reset(); | 411 service_.reset(); |
| 414 OnConnectionLost(service_manager); | 412 OnConnectionLost(service_manager); |
| 415 } | 413 } |
| 416 | 414 |
| 417 void OnConnectionLost(base::WeakPtr<shell::ServiceManager> service_manager) { | 415 void OnConnectionLost(base::WeakPtr<shell::ServiceManager> service_manager) { |
| 418 // Any time a Connector is lost or we lose the Service connection, it | 416 // Any time a Connector is lost or we lose the Service connection, it |
| 419 // may have been the last pipe using this Instance. If so, clean up. | 417 // may have been the last pipe using this Instance. If so, clean up. |
| 420 if (service_manager && !service_) { | 418 if (service_manager && !service_) { |
| 421 InstanceErrorType instance_error_type = | 419 if (connectors_.empty()) |
| 422 connectors_.empty() ? InstanceErrorType::DESTROY | 420 service_manager->OnInstanceError(this); |
| 423 : InstanceErrorType::LOST_SERVICE; | 421 else |
| 424 service_manager->OnInstanceError(this, instance_error_type); | 422 service_manager->OnInstanceUnreachable(this); |
| 425 } | 423 } |
| 426 } | 424 } |
| 427 | 425 |
| 428 void OnInitializeResponse(mojom::ConnectorRequest connector_request) { | 426 void OnInitializeResponse(mojom::ConnectorRequest connector_request) { |
| 429 if (connector_request.is_pending()) { | 427 if (connector_request.is_pending()) { |
| 430 connectors_.AddBinding(this, std::move(connector_request)); | 428 connectors_.AddBinding(this, std::move(connector_request)); |
| 431 connectors_.set_connection_error_handler( | 429 connectors_.set_connection_error_handler( |
| 432 base::Bind(&Instance::OnConnectionLost, base::Unretained(this), | 430 base::Bind(&Instance::OnConnectionLost, base::Unretained(this), |
| 433 service_manager_->GetWeakPtr())); | 431 service_manager_->GetWeakPtr())); |
| 434 } | 432 } |
| 435 } | 433 } |
| 436 | 434 |
| 437 // Callback when NativeRunner completes. | 435 // Callback when NativeRunner completes. |
| 438 void OnRunnerCompleted() { | 436 void OnRunnerCompleted() { |
| 439 if (!runner_.get()) | 437 if (!runner_.get()) |
| 440 return; // We're in the destructor. | 438 return; // We're in the destructor. |
| 441 | 439 |
| 442 service_manager_->OnInstanceError(this, InstanceErrorType::DESTROY); | 440 service_manager_->OnInstanceError(this); |
| 443 } | 441 } |
| 444 | 442 |
| 445 shell::ServiceManager* const service_manager_; | 443 shell::ServiceManager* const service_manager_; |
| 446 | 444 |
| 447 // An id that identifies this instance. Distinct from pid, as a single process | 445 // An id that identifies this instance. Distinct from pid, as a single process |
| 448 // may vend multiple application instances, and this object may exist before a | 446 // may vend multiple application instances, and this object may exist before a |
| 449 // process is launched. | 447 // process is launched. |
| 450 const uint32_t id_; | 448 const uint32_t id_; |
| 451 const Identity identity_; | 449 const Identity identity_; |
| 452 const CapabilitySpec capability_spec_; | 450 const CapabilitySpec capability_spec_; |
| 453 const bool allow_any_application_; | 451 const bool allow_any_application_; |
| 454 std::unique_ptr<NativeRunner> runner_; | 452 std::unique_ptr<NativeRunner> runner_; |
| 455 mojom::ServicePtr service_; | 453 mojom::ServicePtr service_; |
| 456 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; | 454 mojo::Binding<mojom::PIDReceiver> pid_receiver_binding_; |
| 457 mojo::BindingSet<mojom::Connector> connectors_; | 455 mojo::BindingSet<mojom::Connector> connectors_; |
| 458 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_; | 456 mojo::BindingSet<mojom::ServiceManager> service_manager_bindings_; |
| 459 base::ProcessId pid_ = base::kNullProcessId; | 457 base::ProcessId pid_ = base::kNullProcessId; |
| 460 Instance* parent_ = nullptr; | 458 Instance* parent_ = nullptr; |
| 461 std::set<Instance*> children_; | 459 InstanceMap children_; |
| 462 base::WeakPtrFactory<Instance> weak_factory_; | 460 base::WeakPtrFactory<Instance> weak_factory_; |
| 463 | 461 |
| 464 DISALLOW_COPY_AND_ASSIGN(Instance); | 462 DISALLOW_COPY_AND_ASSIGN(Instance); |
| 465 }; | 463 }; |
| 466 | 464 |
| 467 // static | 465 // static |
| 468 ServiceManager::TestAPI::TestAPI(ServiceManager* service_manager) | 466 ServiceManager::TestAPI::TestAPI(ServiceManager* service_manager) |
| 469 : service_manager_(service_manager) {} | 467 : service_manager_(service_manager) {} |
| 470 ServiceManager::TestAPI::~TestAPI() {} | 468 ServiceManager::TestAPI::~TestAPI() {} |
| 471 | 469 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 493 instance->StartWithService(std::move(service)); | 491 instance->StartWithService(std::move(service)); |
| 494 singletons_.insert(kServiceManagerName); | 492 singletons_.insert(kServiceManagerName); |
| 495 service_context_.reset(new ServiceContext(this, std::move(request))); | 493 service_context_.reset(new ServiceContext(this, std::move(request))); |
| 496 | 494 |
| 497 if (catalog) | 495 if (catalog) |
| 498 InitCatalog(std::move(catalog)); | 496 InitCatalog(std::move(catalog)); |
| 499 } | 497 } |
| 500 | 498 |
| 501 ServiceManager::~ServiceManager() { | 499 ServiceManager::~ServiceManager() { |
| 502 TerminateServiceManagerConnections(); | 500 TerminateServiceManagerConnections(); |
| 503 // Terminate any remaining instances. | |
| 504 while (!identity_to_instance_.empty()) { | |
| 505 OnInstanceError(identity_to_instance_.begin()->second, | |
| 506 InstanceErrorType::DESTROY); | |
| 507 } | |
| 508 while (!instances_without_service_.empty()) { | |
| 509 OnInstanceError(*instances_without_service_.begin(), | |
| 510 InstanceErrorType::DESTROY); | |
| 511 } | |
| 512 identity_to_resolver_.clear(); | |
| 513 } | 501 } |
| 514 | 502 |
| 515 void ServiceManager::SetInstanceQuitCallback( | 503 void ServiceManager::SetInstanceQuitCallback( |
| 516 base::Callback<void(const Identity&)> callback) { | 504 base::Callback<void(const Identity&)> callback) { |
| 517 instance_quit_callback_ = callback; | 505 instance_quit_callback_ = callback; |
| 518 } | 506 } |
| 519 | 507 |
| 520 void ServiceManager::Connect(std::unique_ptr<ConnectParams> params) { | 508 void ServiceManager::Connect(std::unique_ptr<ConnectParams> params) { |
| 521 Connect(std::move(params), nullptr, nullptr); | 509 Connect(std::move(params), nullptr, nullptr); |
| 522 } | 510 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 mojom::ResolverPtr resolver_ptr; | 569 mojom::ResolverPtr resolver_ptr; |
| 582 ConnectToInterface(this, identity, CreateCatalogIdentity(), &resolver_ptr); | 570 ConnectToInterface(this, identity, CreateCatalogIdentity(), &resolver_ptr); |
| 583 mojom::Resolver* resolver = resolver_ptr.get(); | 571 mojom::Resolver* resolver = resolver_ptr.get(); |
| 584 identity_to_resolver_[identity] = std::move(resolver_ptr); | 572 identity_to_resolver_[identity] = std::move(resolver_ptr); |
| 585 return resolver; | 573 return resolver; |
| 586 } | 574 } |
| 587 | 575 |
| 588 void ServiceManager::TerminateServiceManagerConnections() { | 576 void ServiceManager::TerminateServiceManagerConnections() { |
| 589 Instance* instance = GetExistingInstance(CreateServiceManagerIdentity()); | 577 Instance* instance = GetExistingInstance(CreateServiceManagerIdentity()); |
| 590 if (instance) | 578 if (instance) |
| 591 OnInstanceError(instance, InstanceErrorType::DESTROY); | 579 OnInstanceError(instance); |
| 592 } | 580 } |
| 593 | 581 |
| 594 void ServiceManager::OnInstanceError(Instance* instance, | 582 void ServiceManager::OnInstanceError(Instance* instance) { |
| 595 InstanceErrorType error_type) { | |
| 596 const Identity identity = instance->identity(); | 583 const Identity identity = instance->identity(); |
| 584 identity_to_instance_.erase(identity); |
| 597 | 585 |
| 598 const bool in_identity_to_instance = | 586 if (instance->parent()) { |
| 599 identity_to_instance_.erase(identity) > 0; | 587 // Deletes |instance|. |
| 600 const bool in_instances_without_services = | 588 instance->parent()->RemoveChild(instance); |
| 601 instances_without_service_.erase(instance) > 0; | 589 } else { |
| 602 DCHECK_NE(in_identity_to_instance, in_instances_without_services); | 590 auto it = root_instances_.find(instance); |
| 591 DCHECK(it != root_instances_.end()); |
| 603 | 592 |
| 604 if (error_type == InstanceErrorType::LOST_SERVICE) { | 593 // Deletes |instance|. |
| 605 // |instance| has lost its service but still has connections to it, we need | 594 root_instances_.erase(it); |
| 606 // to keep it around. The instance is removed from |identity_to_instance_| | |
| 607 // so that if an attempt is made to connect to the same identity a new | |
| 608 // Instance is created. | |
| 609 instances_without_service_.insert(instance); | |
| 610 return; | |
| 611 } | 595 } |
| 596 } |
| 612 | 597 |
| 598 void ServiceManager::OnInstanceUnreachable(Instance* instance) { |
| 599 // If an Instance becomes unreachable, new connection requests for this |
| 600 // identity will elicit a new Instance instantiation. The unreachable instance |
| 601 // remains alive. |
| 602 identity_to_instance_.erase(instance->identity()); |
| 603 } |
| 604 |
| 605 void ServiceManager::OnInstanceStopped(const Identity& identity) { |
| 613 listeners_.ForAllPtrs([identity](mojom::ServiceManagerListener* listener) { | 606 listeners_.ForAllPtrs([identity](mojom::ServiceManagerListener* listener) { |
| 614 listener->OnServiceStopped(identity); | 607 listener->OnServiceStopped(identity); |
| 615 }); | 608 }); |
| 616 delete instance; | |
| 617 if (!instance_quit_callback_.is_null()) | 609 if (!instance_quit_callback_.is_null()) |
| 618 instance_quit_callback_.Run(identity); | 610 instance_quit_callback_.Run(identity); |
| 619 } | 611 } |
| 620 | 612 |
| 621 void ServiceManager::Connect(std::unique_ptr<ConnectParams> params, | 613 void ServiceManager::Connect(std::unique_ptr<ConnectParams> params, |
| 622 mojom::ServicePtr service, | 614 mojom::ServicePtr service, |
| 623 base::WeakPtr<Instance> source_instance) { | 615 base::WeakPtr<Instance> source_instance) { |
| 624 TRACE_EVENT_INSTANT1("mojo_shell", "ServiceManager::Connect", | 616 TRACE_EVENT_INSTANT1("mojo_shell", "ServiceManager::Connect", |
| 625 TRACE_EVENT_SCOPE_THREAD, "original_name", | 617 TRACE_EVENT_SCOPE_THREAD, "original_name", |
| 626 params->target().name()); | 618 params->target().name()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 std::unique_ptr<ConnectParams>* params) { | 670 std::unique_ptr<ConnectParams>* params) { |
| 679 Instance* instance = GetExistingInstance((*params)->target()); | 671 Instance* instance = GetExistingInstance((*params)->target()); |
| 680 return instance && instance->ConnectToService(params); | 672 return instance && instance->ConnectToService(params); |
| 681 } | 673 } |
| 682 | 674 |
| 683 ServiceManager::Instance* ServiceManager::CreateInstance( | 675 ServiceManager::Instance* ServiceManager::CreateInstance( |
| 684 const Identity& source, | 676 const Identity& source, |
| 685 const Identity& target, | 677 const Identity& target, |
| 686 const CapabilitySpec& spec) { | 678 const CapabilitySpec& spec) { |
| 687 CHECK(target.user_id() != mojom::kInheritUserID); | 679 CHECK(target.user_id() != mojom::kInheritUserID); |
| 688 Instance* instance = new Instance(this, target, spec); | 680 |
| 689 DCHECK(identity_to_instance_.find(target) == | 681 std::unique_ptr<Instance> instance(new Instance(this, target, spec)); |
| 690 identity_to_instance_.end()); | 682 Instance* raw_instance = instance.get(); |
| 683 |
| 691 Instance* source_instance = GetExistingInstance(source); | 684 Instance* source_instance = GetExistingInstance(source); |
| 692 if (source_instance) | 685 if (source_instance) |
| 693 source_instance->AddChild(instance); | 686 source_instance->AddChild(std::move(instance)); |
| 694 identity_to_instance_[target] = instance; | 687 else |
| 695 mojom::ServiceInfoPtr info = instance->CreateServiceInfo(); | 688 root_instances_.insert(std::make_pair(raw_instance, std::move(instance))); |
| 689 |
| 690 // NOTE: |instance| has been passed elsewhere. Use |raw_instance| from this |
| 691 // point forward. It's safe for the extent of this method. |
| 692 |
| 693 auto result = |
| 694 identity_to_instance_.insert(std::make_pair(target, raw_instance)); |
| 695 DCHECK(result.second); |
| 696 |
| 697 mojom::ServiceInfoPtr info = raw_instance->CreateServiceInfo(); |
| 696 listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) { | 698 listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) { |
| 697 listener->OnServiceCreated(info.Clone()); | 699 listener->OnServiceCreated(info.Clone()); |
| 698 }); | 700 }); |
| 699 return instance; | 701 |
| 702 return raw_instance; |
| 700 } | 703 } |
| 701 | 704 |
| 702 void ServiceManager::AddListener(mojom::ServiceManagerListenerPtr listener) { | 705 void ServiceManager::AddListener(mojom::ServiceManagerListenerPtr listener) { |
| 703 // TODO(beng): filter instances provided by those visible to this service. | 706 // TODO(beng): filter instances provided by those visible to this service. |
| 704 std::vector<mojom::ServiceInfoPtr> instances; | 707 std::vector<mojom::ServiceInfoPtr> instances; |
| 705 instances.reserve(identity_to_instance_.size()); | 708 instances.reserve(identity_to_instance_.size()); |
| 706 for (auto& instance : identity_to_instance_) | 709 for (auto& instance : identity_to_instance_) |
| 707 instances.push_back(instance.second->CreateServiceInfo()); | 710 instances.push_back(instance.second->CreateServiceInfo()); |
| 708 listener->OnInit(std::move(instances)); | 711 listener->OnInit(std::move(instances)); |
| 709 | 712 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 // Now that the instance has a Service, we can connect to it. | 828 // Now that the instance has a Service, we can connect to it. |
| 826 bool connected = instance->ConnectToService(¶ms); | 829 bool connected = instance->ConnectToService(¶ms); |
| 827 DCHECK(connected); | 830 DCHECK(connected); |
| 828 } | 831 } |
| 829 | 832 |
| 830 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { | 833 base::WeakPtr<ServiceManager> ServiceManager::GetWeakPtr() { |
| 831 return weak_ptr_factory_.GetWeakPtr(); | 834 return weak_ptr_factory_.GetWeakPtr(); |
| 832 } | 835 } |
| 833 | 836 |
| 834 } // namespace shell | 837 } // namespace shell |
| OLD | NEW |