Commit 18526eed authored by Ken Rockot's avatar Ken Rockot Committed by Commit Bot

[service-manager] Simplify connection logic

This reduces the complexity of Service Manager's logic for handling
interconnection between service instances. Much of the complexity was
due to connection operations once upon a time being highly
asynchronous within SM, but that hasn't been the case for a while.

Rather than having ServiceManager::Connect do way too much stuff, it's
replaced with a simpler and more straightforward
FindOrCreateMatchingTargetInstance, which does only what the name says.
Previous work done by Connect() in various edge cases has been moved out
to its prior call sites, now replaced with calls to FOCMTI.

Bug: 904240
Change-Id: Ia276f6fa61477ddc141724d30484237498eef070
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1593722Reviewed-by: default avatarOksana Zhuravlova <oksamyt@chromium.org>
Commit-Queue: Ken Rockot <rockot@google.com>
Cr-Commit-Position: refs/heads/master@{#657401}
parent cb0fb84e
...@@ -220,7 +220,7 @@ void ServiceInstance::StartWithRemote( ...@@ -220,7 +220,7 @@ void ServiceInstance::StartWithRemote(
base::BindOnce(&ServiceInstance::OnStartCompleted, base::BindOnce(&ServiceInstance::OnStartCompleted,
base::Unretained(this))); base::Unretained(this)));
service_manager_->NotifyServiceCreated(this); service_manager_->NotifyServiceCreated(*this);
} }
bool ServiceInstance::StartWithExecutablePath(const base::FilePath& path, bool ServiceInstance::StartWithExecutablePath(const base::FilePath& path,
...@@ -246,30 +246,24 @@ bool ServiceInstance::StartWithExecutablePath(const base::FilePath& path, ...@@ -246,30 +246,24 @@ bool ServiceInstance::StartWithExecutablePath(const base::FilePath& path,
#endif #endif
} }
void ServiceInstance::AuthorizeAndForwardConnectionRequestFromOtherService( bool ServiceInstance::MaybeAcceptConnectionRequest(
const Identity& source_identity, const ServiceInstance& source_instance,
const std::string& interface_name, const std::string& interface_name,
mojo::ScopedMessagePipeHandle receiving_pipe, mojo::ScopedMessagePipeHandle receiving_pipe,
mojom::BindInterfacePriority priority, mojom::BindInterfacePriority priority) {
mojom::Connector::BindInterfaceCallback callback) { if (state_ == mojom::InstanceState::kUnreachable)
ServiceInstance* const source = return false;
service_manager_->GetExistingInstance(source_identity);
if (!source || state_ == mojom::InstanceState::kUnreachable) {
std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, identity_);
return;
}
const Manifest& source_manifest = source->manifest(); const Manifest& source_manifest = source_instance.manifest();
const bool bindable_on_any_service = base::ContainsKey( const bool bindable_on_any_service = base::ContainsKey(
source_manifest.interfaces_bindable_on_any_service, interface_name); source_manifest.interfaces_bindable_on_any_service, interface_name);
const bool allowed_by_capabilities = const bool allowed_by_capabilities =
AllowsInterface(source_manifest.required_capabilities, identity_.name(), AllowsInterface(source_manifest.required_capabilities, identity_.name(),
manifest_.exposed_capabilities, interface_name); manifest_.exposed_capabilities, interface_name);
if (!bindable_on_any_service && !allowed_by_capabilities) { if (!bindable_on_any_service && !allowed_by_capabilities) {
ReportBlockedInterface(source_identity.name(), identity_.name(), ReportBlockedInterface(source_instance.identity().name(), identity_.name(),
interface_name); interface_name);
std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, identity_); return false;
return;
} }
base::OnceClosure on_bind_interface_complete; base::OnceClosure on_bind_interface_complete;
...@@ -280,13 +274,14 @@ void ServiceInstance::AuthorizeAndForwardConnectionRequestFromOtherService( ...@@ -280,13 +274,14 @@ void ServiceInstance::AuthorizeAndForwardConnectionRequestFromOtherService(
} }
service_remote_->OnBindInterface( service_remote_->OnBindInterface(
BindSourceInfo(source_identity, GetRequiredCapabilities( BindSourceInfo(
source_manifest.required_capabilities, source_instance.identity(),
identity_.name())), GetRequiredCapabilities(source_manifest.required_capabilities,
identity_.name())),
interface_name, std::move(receiving_pipe), interface_name, std::move(receiving_pipe),
std::move(on_bind_interface_complete)); std::move(on_bind_interface_complete));
std::move(callback).Run(mojom::ConnectResult::SUCCEEDED, identity_); return true;
} }
void ServiceInstance::Stop() { void ServiceInstance::Stop() {
...@@ -379,12 +374,12 @@ void ServiceInstance::HandleServiceOrConnectorDisconnection() { ...@@ -379,12 +374,12 @@ void ServiceInstance::HandleServiceOrConnectorDisconnection() {
} }
} }
mojom::ConnectResult ServiceInstance::ValidateConnectionRequestToOtherService( bool ServiceInstance::CanConnectToOtherInstance(
const ServiceFilter& target_filter, const ServiceFilter& target_filter,
const base::Optional<std::string>& target_interface_name) { const base::Optional<std::string>& target_interface_name) {
if (target_filter.service_name().empty()) { if (target_filter.service_name().empty()) {
DLOG(ERROR) << "ServiceFilter has no service name."; DLOG(ERROR) << "ServiceFilter has no service name.";
return mojom::ConnectResult::INVALID_ARGUMENT; return false;
} }
bool skip_instance_group_check = bool skip_instance_group_check =
...@@ -402,7 +397,7 @@ mojom::ConnectResult ServiceInstance::ValidateConnectionRequestToOtherService( ...@@ -402,7 +397,7 @@ mojom::ConnectResult ServiceInstance::ValidateConnectionRequestToOtherService(
<< "group " << target_filter.instance_group()->ToString() << "group " << target_filter.instance_group()->ToString()
<< " without |can_connect_to_instances_in_any_group| set to " << " without |can_connect_to_instances_in_any_group| set to "
<< "|true|."; << "|true|.";
return mojom::ConnectResult::ACCESS_DENIED; return false;
} }
if (target_filter.instance_id() && !target_filter.instance_id()->is_zero() && if (target_filter.instance_id() && !target_filter.instance_id()->is_zero() &&
!manifest_.options.can_connect_to_instances_with_any_id) { !manifest_.options.can_connect_to_instances_with_any_id) {
...@@ -411,14 +406,14 @@ mojom::ConnectResult ServiceInstance::ValidateConnectionRequestToOtherService( ...@@ -411,14 +406,14 @@ mojom::ConnectResult ServiceInstance::ValidateConnectionRequestToOtherService(
<< " with instance ID " << " with instance ID "
<< target_filter.instance_id()->ToString() << " without " << target_filter.instance_id()->ToString() << " without "
<< "|can_connect_to_instances_with_any_id| set to |true|."; << "|can_connect_to_instances_with_any_id| set to |true|.";
return mojom::ConnectResult::ACCESS_DENIED; return false;
} }
if (can_contact_all_services_ || if (can_contact_all_services_ ||
!manifest_.interfaces_bindable_on_any_service.empty() || !manifest_.interfaces_bindable_on_any_service.empty() ||
manifest_.required_capabilities.find(target_filter.service_name()) != manifest_.required_capabilities.find(target_filter.service_name()) !=
manifest_.required_capabilities.end()) { manifest_.required_capabilities.end()) {
return mojom::ConnectResult::SUCCEEDED; return true;
} }
if (target_interface_name) { if (target_interface_name) {
...@@ -428,7 +423,7 @@ mojom::ConnectResult ServiceInstance::ValidateConnectionRequestToOtherService( ...@@ -428,7 +423,7 @@ mojom::ConnectResult ServiceInstance::ValidateConnectionRequestToOtherService(
ReportBlockedStartService(identity_.name(), target_filter.service_name()); ReportBlockedStartService(identity_.name(), target_filter.service_name());
} }
return mojom::ConnectResult::ACCESS_DENIED; return false;
} }
void ServiceInstance::BindInterface( void ServiceInstance::BindInterface(
...@@ -437,16 +432,25 @@ void ServiceInstance::BindInterface( ...@@ -437,16 +432,25 @@ void ServiceInstance::BindInterface(
mojo::ScopedMessagePipeHandle receiving_pipe, mojo::ScopedMessagePipeHandle receiving_pipe,
mojom::BindInterfacePriority priority, mojom::BindInterfacePriority priority,
BindInterfaceCallback callback) { BindInterfaceCallback callback) {
mojom::ConnectResult result = if (!CanConnectToOtherInstance(target_filter, interface_name)) {
ValidateConnectionRequestToOtherService(target_filter, interface_name); std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, base::nullopt);
if (result != mojom::ConnectResult::SUCCEEDED) { return;
std::move(callback).Run(result, base::nullopt); }
ServiceInstance* target_instance =
service_manager_->FindOrCreateMatchingTargetInstance(*this,
target_filter);
bool allowed =
target_instance &&
target_instance->MaybeAcceptConnectionRequest(
*this, interface_name, std::move(receiving_pipe), priority);
if (!allowed) {
std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, base::nullopt);
return; return;
} }
service_manager_->Connect(target_filter, identity_, interface_name, std::move(callback).Run(mojom::ConnectResult::SUCCEEDED,
std::move(receiving_pipe), priority, target_instance->identity());
std::move(callback));
} }
void ServiceInstance::QueryService(const std::string& service_name, void ServiceInstance::QueryService(const std::string& service_name,
...@@ -462,14 +466,22 @@ void ServiceInstance::QueryService(const std::string& service_name, ...@@ -462,14 +466,22 @@ void ServiceInstance::QueryService(const std::string& service_name,
void ServiceInstance::WarmService(const ServiceFilter& target_filter, void ServiceInstance::WarmService(const ServiceFilter& target_filter,
WarmServiceCallback callback) { WarmServiceCallback callback) {
mojom::ConnectResult result = ValidateConnectionRequestToOtherService( if (!CanConnectToOtherInstance(target_filter,
target_filter, base::nullopt /* interface_name */); base::nullopt /* interface_name */)) {
if (result != mojom::ConnectResult::SUCCEEDED) { std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, base::nullopt);
std::move(callback).Run(result, base::nullopt);
return; return;
} }
service_manager_->Connect(target_filter, identity_, std::move(callback)); ServiceInstance* target_instance =
service_manager_->FindOrCreateMatchingTargetInstance(*this,
target_filter);
if (!target_instance) {
std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED, base::nullopt);
return;
}
std::move(callback).Run(mojom::ConnectResult::SUCCEEDED,
target_instance->identity());
} }
void ServiceInstance::RegisterServiceInstance( void ServiceInstance::RegisterServiceInstance(
...@@ -477,6 +489,13 @@ void ServiceInstance::RegisterServiceInstance( ...@@ -477,6 +489,13 @@ void ServiceInstance::RegisterServiceInstance(
mojo::ScopedMessagePipeHandle service_remote_handle, mojo::ScopedMessagePipeHandle service_remote_handle,
mojom::PIDReceiverRequest pid_receiver_request, mojom::PIDReceiverRequest pid_receiver_request,
RegisterServiceInstanceCallback callback) { RegisterServiceInstanceCallback callback) {
auto target_filter = ServiceFilter::ForExactIdentity(identity);
if (!CanConnectToOtherInstance(target_filter,
base::nullopt /* interface_name */)) {
std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED);
return;
}
mojo::PendingRemote<mojom::Service> service_remote( mojo::PendingRemote<mojom::Service> service_remote(
std::move(service_remote_handle), 0); std::move(service_remote_handle), 0);
...@@ -495,23 +514,13 @@ void ServiceInstance::RegisterServiceInstance( ...@@ -495,23 +514,13 @@ void ServiceInstance::RegisterServiceInstance(
return; return;
} }
auto target_filter = ServiceFilter::ForExactIdentity(identity); mojom::ServicePtr service(std::move(service_remote));
mojom::ConnectResult result = ValidateConnectionRequestToOtherService( if (!service_manager_->RegisterService(identity, std::move(service),
target_filter, base::nullopt /* interface_name */); std::move(pid_receiver_request))) {
if (result != mojom::ConnectResult::SUCCEEDED) { std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED);
std::move(callback).Run(result);
return;
} }
service_manager_->Connect(target_filter, identity_, std::move(service_remote), std::move(callback).Run(mojom::ConnectResult::SUCCEEDED);
std::move(pid_receiver_request),
base::BindOnce(
[](RegisterServiceInstanceCallback callback,
mojom::ConnectResult result,
const base::Optional<Identity>& identity) {
std::move(callback).Run(result);
},
std::move(callback)));
} }
void ServiceInstance::Clone(mojom::ConnectorRequest request) { void ServiceInstance::Clone(mojom::ConnectorRequest request) {
......
...@@ -73,14 +73,14 @@ class ServiceInstance : public mojom::Connector, ...@@ -73,14 +73,14 @@ class ServiceInstance : public mojom::Connector,
bool StartWithExecutablePath(const base::FilePath& path, bool StartWithExecutablePath(const base::FilePath& path,
SandboxType sandbox_type); SandboxType sandbox_type);
// Forwards a BindInterface request to the service instance, iff it should be // Forwards a BindInterface request from |source_instance| to this instance,
// allowed based on manifest constraints. // iff it should be allowed based on manifest constraints. Returns |true| if
void AuthorizeAndForwardConnectionRequestFromOtherService( // the request was allowed, or |false| otherwise.
const Identity& source_identity, bool MaybeAcceptConnectionRequest(
const ServiceInstance& source_instance,
const std::string& interface_name, const std::string& interface_name,
mojo::ScopedMessagePipeHandle receiving_pipe, mojo::ScopedMessagePipeHandle receiving_pipe,
mojom::BindInterfacePriority priority, mojom::BindInterfacePriority priority);
mojom::Connector::BindInterfaceCallback callback);
// Stops receiving any new messages from the service instance and renders the // Stops receiving any new messages from the service instance and renders the
// instance permanently unreachable. Note that this does NOT make any attempt // instance permanently unreachable. Note that this does NOT make any attempt
...@@ -112,10 +112,11 @@ class ServiceInstance : public mojom::Connector, ...@@ -112,10 +112,11 @@ class ServiceInstance : public mojom::Connector,
// Examines an interface connection request coming from this service instance // Examines an interface connection request coming from this service instance
// and determines whether it should be allowed to reach any designated target // and determines whether it should be allowed to reach any designated target
// instance. A return value of |mojom::ConnectResult::SUCCESS| indicates that // instance. Returns |true| if so, or |false| otherwise.
// the request can be processed further. Any other result means the request //
// should be rejected. // If |target_interface_name| is null, it is sufficient for this (the source)
mojom::ConnectResult ValidateConnectionRequestToOtherService( // service to have access to *any* arbitrary interface on the target service.
bool CanConnectToOtherInstance(
const ServiceFilter& target_filter, const ServiceFilter& target_filter,
const base::Optional<std::string>& target_interface_name); const base::Optional<std::string>& target_interface_name);
......
...@@ -115,20 +115,14 @@ void ServiceManager::SetInstanceQuitCallback( ...@@ -115,20 +115,14 @@ void ServiceManager::SetInstanceQuitCallback(
instance_quit_callback_ = std::move(callback); instance_quit_callback_ = std::move(callback);
} }
void ServiceManager::Connect( ServiceInstance* ServiceManager::FindOrCreateMatchingTargetInstance(
const ServiceFilter& partial_target_filter, const ServiceInstance& source_instance,
const Identity& source_identity, const ServiceFilter& partial_target_filter) {
const base::Optional<std::string>& interface_name,
mojo::ScopedMessagePipeHandle receiving_pipe,
mojo::PendingRemote<mojom::Service> service_remote,
mojo::PendingReceiver<mojom::PIDReceiver> pid_receiver,
mojom::BindInterfacePriority priority,
mojom::Connector::BindInterfaceCallback callback) {
TRACE_EVENT_INSTANT1("service_manager", "ServiceManager::Connect", TRACE_EVENT_INSTANT1("service_manager", "ServiceManager::Connect",
TRACE_EVENT_SCOPE_THREAD, "original_name", TRACE_EVENT_SCOPE_THREAD, "original_name",
partial_target_filter.service_name()); partial_target_filter.service_name());
DCHECK(source_identity.IsValid());
const Identity& source_identity = source_instance.identity();
ServiceFilter target_filter = partial_target_filter; ServiceFilter target_filter = partial_target_filter;
// If the target filter does not specify an instance group, we assume the // If the target filter does not specify an instance group, we assume the
...@@ -140,66 +134,29 @@ void ServiceManager::Connect( ...@@ -140,66 +134,29 @@ void ServiceManager::Connect(
if (!target_filter.instance_id()) if (!target_filter.instance_id())
target_filter.set_instance_id(base::Token()); target_filter.set_instance_id(base::Token());
if (!service_remote) { // Use an existing instance if possible.
// Connect to an existing matching instance, if possible. ServiceInstance* target_instance =
ServiceInstance* instance = instance_registry_.FindMatching(target_filter); instance_registry_.FindMatching(target_filter);
if (instance) { if (target_instance)
if (interface_name) { return target_instance;
DCHECK(receiving_pipe.is_valid());
instance->AuthorizeAndForwardConnectionRequestFromOtherService(
source_identity, interface_name.value(), std::move(receiving_pipe),
priority, std::move(callback));
} else {
// This is a StartService request and the instance is already running.
// Make sure the response identity is properly resolved.
std::move(callback).Run(mojom::ConnectResult::SUCCEEDED,
instance->identity());
}
return;
}
// If there was no existing instance but the request specified a specific
// globally unique ID for the target, ignore the request. That instance is
// obviously no longer running.
if (target_filter.globally_unique_id()) {
std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED,
base::nullopt);
return;
}
}
// Beyond this point, in order to fulfill the connection request we need to
// start a new instance of the target service.
const service_manager::Manifest* manifest = const service_manager::Manifest* manifest =
catalog_.GetManifest(target_filter.service_name()); catalog_.GetManifest(target_filter.service_name());
if (!manifest) { if (!manifest) {
LOG(ERROR) << "Failed to resolve service name: " LOG(ERROR) << "Failed to resolve service name: "
<< target_filter.service_name(); << target_filter.service_name();
std::move(callback).Run(mojom::ConnectResult::INVALID_ARGUMENT, return nullptr;
base::nullopt);
return;
} }
// Services that use |kSharedAcrossGroups| sharing policy are allowed to // If there was no existing instance but the caller is requesting a specific
// handle connection requests from instances in any instance group. They also // globally unique ID for the target, ignore the request. That instance is
// run with a synthetic group ID generated below and the group provided by // obviously no longer running, and globally unique IDs are never reused.
// |target_filter| is ignored. if (target_filter.globally_unique_id())
return nullptr;
Identity new_instance_identity; Identity new_instance_identity;
if (service_remote) { if (manifest->options.instance_sharing_policy ==
// This is a service instance registration, so we should use the exact Manifest::InstanceSharingPolicy::kSingleton) {
// Identity given by the caller.
if (!target_filter.globally_unique_id() ||
target_filter.globally_unique_id()->is_zero()) {
std::move(callback).Run(mojom::ConnectResult::INVALID_ARGUMENT,
base::nullopt);
return;
}
new_instance_identity = Identity(
target_filter.service_name(), *target_filter.instance_group(),
*target_filter.instance_id(), *target_filter.globally_unique_id());
} else if (manifest->options.instance_sharing_policy ==
Manifest::InstanceSharingPolicy::kSingleton) {
// For singleton instances, we generate a random group ID along with the // For singleton instances, we generate a random group ID along with the
// random GUID. // random GUID.
new_instance_identity = new_instance_identity =
...@@ -207,9 +164,10 @@ void ServiceManager::Connect( ...@@ -207,9 +164,10 @@ void ServiceManager::Connect(
base::Token{}, base::Token::CreateRandom()); base::Token{}, base::Token::CreateRandom());
} else if (manifest->options.instance_sharing_policy == } else if (manifest->options.instance_sharing_policy ==
Manifest::InstanceSharingPolicy::kSharedAcrossGroups) { Manifest::InstanceSharingPolicy::kSharedAcrossGroups) {
// For services shared across instance groups, we respect the target // Services that use |kSharedAcrossGroups| sharing policy are allowed to
// instance ID but still generate a random group ID along with the random // match ServiceFilters targeting any instance group. They run with a
// GUID. // random group ID generated here, and the group provided by |target_filter|
// is ignored. The instance ID from |target_filter| is still used.
new_instance_identity = new_instance_identity =
Identity(target_filter.service_name(), base::Token::CreateRandom(), Identity(target_filter.service_name(), base::Token::CreateRandom(),
*target_filter.instance_id(), base::Token::CreateRandom()); *target_filter.instance_id(), base::Token::CreateRandom());
...@@ -221,19 +179,8 @@ void ServiceManager::Connect( ...@@ -221,19 +179,8 @@ void ServiceManager::Connect(
*target_filter.instance_id(), base::Token::CreateRandom()); *target_filter.instance_id(), base::Token::CreateRandom());
} }
ServiceInstance* instance = DCHECK(!target_instance);
CreateServiceInstance(new_instance_identity, *manifest); target_instance = CreateServiceInstance(new_instance_identity, *manifest);
if (service_remote) {
// If this is a service registration via |RegisterService()| or
// |Connector.RegisterServiceInstance()|, we'll have a valid
// |service_remote| already and that's enough to be done.
instance->StartWithRemote(std::move(service_remote),
std::move(pid_receiver));
std::move(callback).Run(mojom::ConnectResult::SUCCEEDED,
instance->identity());
return;
}
const service_manager::Manifest* parent_manifest = const service_manager::Manifest* parent_manifest =
catalog_.GetParentManifest(manifest->service_name); catalog_.GetParentManifest(manifest->service_name);
...@@ -249,7 +196,7 @@ void ServiceManager::Connect( ...@@ -249,7 +196,7 @@ void ServiceManager::Connect(
// //
// TODO(https://crbug.com/904240): This is super weird and hard to // TODO(https://crbug.com/904240): This is super weird and hard to
// rationalize. Maybe it's the wrong thing to do. // rationalize. Maybe it's the wrong thing to do.
instance->set_identity( target_instance->set_identity(
Identity(new_instance_identity.name(), *target_filter.instance_group(), Identity(new_instance_identity.name(), *target_filter.instance_group(),
new_instance_identity.instance_id(), new_instance_identity.instance_id(),
new_instance_identity.globally_unique_id())); new_instance_identity.globally_unique_id()));
...@@ -262,72 +209,36 @@ void ServiceManager::Connect( ...@@ -262,72 +209,36 @@ void ServiceManager::Connect(
auto pid_receiver_request = mojo::MakeRequest(&pid_receiver); auto pid_receiver_request = mojo::MakeRequest(&pid_receiver);
mojo::PendingRemote<mojom::Service> remote; mojo::PendingRemote<mojom::Service> remote;
CreateServiceWithFactory(factory_filter, target_filter.service_name(), auto* factory = GetServiceFactory(factory_filter);
remote.InitWithNewPipeAndPassReceiver(), if (!factory) {
std::move(pid_receiver)); DestroyInstance(target_instance);
instance->StartWithRemote(std::move(remote), return nullptr;
std::move(pid_receiver_request)); }
factory->CreateService(remote.InitWithNewPipeAndPassReceiver(),
target_filter.service_name(),
std::move(pid_receiver));
target_instance->StartWithRemote(std::move(remote),
std::move(pid_receiver_request));
} else { } else {
base::FilePath service_exe_root; base::FilePath service_exe_root;
CHECK(base::PathService::Get(base::DIR_ASSETS, &service_exe_root)); CHECK(base::PathService::Get(base::DIR_ASSETS, &service_exe_root));
if (!instance->StartWithExecutablePath( if (!target_instance->StartWithExecutablePath(
service_exe_root.AppendASCII(manifest->service_name + service_exe_root.AppendASCII(manifest->service_name +
kServiceExecutableExtension), kServiceExecutableExtension),
UtilitySandboxTypeFromString(manifest->options.sandbox_type))) { UtilitySandboxTypeFromString(manifest->options.sandbox_type))) {
DestroyInstance(instance); DestroyInstance(target_instance);
std::move(callback).Run(mojom::ConnectResult::INVALID_ARGUMENT, return nullptr;
base::nullopt);
return;
} }
} }
if (interface_name) { return target_instance;
DCHECK(receiving_pipe);
instance->AuthorizeAndForwardConnectionRequestFromOtherService(
source_identity, interface_name.value(), std::move(receiving_pipe),
priority, std::move(callback));
return;
}
std::move(callback).Run(mojom::ConnectResult::SUCCEEDED,
instance->identity());
}
void ServiceManager::Connect(const ServiceFilter& partial_target_filter,
const Identity& source_identity,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle receiving_pipe,
mojom::BindInterfacePriority priority,
mojom::Connector::BindInterfaceCallback callback) {
Connect(partial_target_filter, source_identity, interface_name,
std::move(receiving_pipe), mojo::NullRemote(), mojo::NullReceiver(),
priority, std::move(callback));
}
void ServiceManager::Connect(const ServiceFilter& partial_target_filter,
const Identity& source_identity,
mojom::Connector::BindInterfaceCallback callback) {
Connect(partial_target_filter, source_identity,
base::nullopt /* interface_name */, mojo::ScopedMessagePipeHandle(),
mojo::NullRemote(), mojo::NullReceiver(),
mojom::BindInterfacePriority::kBestEffort, std::move(callback));
}
void ServiceManager::Connect(
const ServiceFilter& partial_target_filter,
const Identity& source_identity,
mojo::PendingRemote<mojom::Service> service_remote,
mojo::PendingReceiver<mojom::PIDReceiver> pid_receiver,
mojom::Connector::BindInterfaceCallback callback) {
Connect(partial_target_filter, source_identity,
base::nullopt /* interface_name */, mojo::ScopedMessagePipeHandle(),
std::move(service_remote), std::move(pid_receiver),
mojom::BindInterfacePriority::kImportant, std::move(callback));
} }
void ServiceManager::StartService(const std::string& service_name) { void ServiceManager::StartService(const std::string& service_name) {
Connect(ServiceFilter::ByNameInGroup(service_name, kSystemInstanceGroup), FindOrCreateMatchingTargetInstance(
GetServiceManagerInstanceIdentity(), base::DoNothing()); *service_manager_instance_,
ServiceFilter::ByNameInGroup(service_name, kSystemInstanceGroup));
} }
bool ServiceManager::QueryCatalog(const std::string& service_name, bool ServiceManager::QueryCatalog(const std::string& service_name,
...@@ -340,20 +251,30 @@ bool ServiceManager::QueryCatalog(const std::string& service_name, ...@@ -340,20 +251,30 @@ bool ServiceManager::QueryCatalog(const std::string& service_name,
return true; return true;
} }
void ServiceManager::RegisterService( bool ServiceManager::RegisterService(
const Identity& identity, const Identity& identity,
mojom::ServicePtr service, mojom::ServicePtr service,
mojom::PIDReceiverRequest pid_receiver_request) { mojom::PIDReceiverRequest pid_receiver_request) {
if (!identity.IsValid())
return false;
const service_manager::Manifest* manifest =
catalog_.GetManifest(identity.name());
if (!manifest) {
LOG(ERROR) << "Failed to resolve service name: " << identity.name();
return false;
}
if (!pid_receiver_request.is_pending()) { if (!pid_receiver_request.is_pending()) {
mojo::Remote<mojom::PIDReceiver> pid_receiver; mojo::Remote<mojom::PIDReceiver> pid_receiver;
pid_receiver_request = pid_receiver.BindNewPipeAndPassReceiver(); pid_receiver_request = pid_receiver.BindNewPipeAndPassReceiver();
pid_receiver->SetPID(GetCurrentPid()); pid_receiver->SetPID(GetCurrentPid());
} }
DCHECK(identity.IsValid()); ServiceInstance* instance = CreateServiceInstance(identity, *manifest);
Connect(ServiceFilter::ForExactIdentity(identity), identity, instance->StartWithRemote(service.PassInterface(),
service.PassInterface(), std::move(pid_receiver_request), std::move(pid_receiver_request));
base::DoNothing()); return true;
} }
void ServiceManager::MakeInstanceUnreachable(ServiceInstance* instance) { void ServiceManager::MakeInstanceUnreachable(ServiceInstance* instance) {
...@@ -387,8 +308,8 @@ ServiceInstance* ServiceManager::GetExistingInstance( ...@@ -387,8 +308,8 @@ ServiceInstance* ServiceManager::GetExistingInstance(
ServiceFilter::ForExactIdentity(identity)); ServiceFilter::ForExactIdentity(identity));
} }
void ServiceManager::NotifyServiceCreated(ServiceInstance* instance) { void ServiceManager::NotifyServiceCreated(const ServiceInstance& instance) {
mojom::RunningServiceInfoPtr info = instance->CreateRunningServiceInfo(); mojom::RunningServiceInfoPtr info = instance.CreateRunningServiceInfo();
listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) { listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) {
listener->OnServiceCreated(info.Clone()); listener->OnServiceCreated(info.Clone());
}); });
...@@ -443,15 +364,6 @@ void ServiceManager::AddListener(mojom::ServiceManagerListenerPtr listener) { ...@@ -443,15 +364,6 @@ void ServiceManager::AddListener(mojom::ServiceManagerListenerPtr listener) {
listeners_.AddPtr(std::move(listener)); listeners_.AddPtr(std::move(listener));
} }
void ServiceManager::CreateServiceWithFactory(
const ServiceFilter& service_factory_filter,
const std::string& name,
mojom::ServiceRequest request,
mojom::PIDReceiverPtr pid_receiver) {
mojom::ServiceFactory* factory = GetServiceFactory(service_factory_filter);
factory->CreateService(std::move(request), name, std::move(pid_receiver));
}
mojom::ServiceFactory* ServiceManager::GetServiceFactory( mojom::ServiceFactory* ServiceManager::GetServiceFactory(
const ServiceFilter& filter) { const ServiceFilter& filter) {
auto it = service_factories_.find(filter); auto it = service_factories_.find(filter);
...@@ -459,10 +371,15 @@ mojom::ServiceFactory* ServiceManager::GetServiceFactory( ...@@ -459,10 +371,15 @@ mojom::ServiceFactory* ServiceManager::GetServiceFactory(
return it->second.get(); return it->second.get();
mojom::ServiceFactoryPtr factory; mojom::ServiceFactoryPtr factory;
Connect(filter, GetServiceManagerInstanceIdentity(), ServiceInstance* factory_instance =
mojom::ServiceFactory::Name_, FindOrCreateMatchingTargetInstance(*service_manager_instance_, filter);
mojo::MakeRequest(&factory).PassMessagePipe(), if (!factory_instance)
mojom::BindInterfacePriority::kImportant, base::DoNothing()); return nullptr;
factory_instance->MaybeAcceptConnectionRequest(
*service_manager_instance_, mojom::ServiceFactory::Name_,
mojo::MakeRequest(&factory).PassMessagePipe(),
mojom::BindInterfacePriority::kImportant);
mojom::ServiceFactory* factory_interface = factory.get(); mojom::ServiceFactory* factory_interface = factory.get();
factory.set_connection_error_handler(base::BindOnce( factory.set_connection_error_handler(base::BindOnce(
......
...@@ -64,7 +64,9 @@ class ServiceManager : public Service { ...@@ -64,7 +64,9 @@ class ServiceManager : public Service {
// //
// |pid_receiver_request| may be null, in which case the service manager // |pid_receiver_request| may be null, in which case the service manager
// assumes the new service is running in this process. // assumes the new service is running in this process.
void RegisterService(const Identity& identity, //
// Returns |true| if registration succeeded, or |false| otherwise.
bool RegisterService(const Identity& identity,
mojom::ServicePtr service, mojom::ServicePtr service,
mojom::PIDReceiverRequest pid_receiver_request); mojom::PIDReceiverRequest pid_receiver_request);
...@@ -74,40 +76,17 @@ class ServiceManager : public Service { ...@@ -74,40 +76,17 @@ class ServiceManager : public Service {
const base::Token& instance_group, const base::Token& instance_group,
std::string* sandbox_type); std::string* sandbox_type);
// Completes a connection between a source and target application as defined // Attempts to locate a ServiceInstance as a target for a connection request
// by |params|. If no existing instance of the target service is running, one // from |source_instance| by matching against |partial_target_filter|. If
// will be loaded. // a suitable instance exists it is returned, otherwise the Service Manager
void Connect(const ServiceFilter& partial_target_filter, // attempts to create a new suitable instance.
const Identity& source_identity, //
const base::Optional<std::string>& interface_name, // Returns null if a matching instance did not exist and could not be created,
mojo::ScopedMessagePipeHandle receiving_pipe, // otherwise returns a valid ServiceInstance which matches
mojo::PendingRemote<mojom::Service> service_remote, // |partial_target_filter| from |source_instance|'s perspective.
mojo::PendingReceiver<mojom::PIDReceiver> pid_receiver, ServiceInstance* FindOrCreateMatchingTargetInstance(
mojom::BindInterfacePriority priority, const ServiceInstance& source_instance,
mojom::Connector::BindInterfaceCallback callback); const ServiceFilter& partial_target_filter);
// Variant of the above when no Service remote or PIDReceiver is provided by
// the caller.
void Connect(const ServiceFilter& partial_target_filter,
const Identity& source_identity,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle receiving_pipe,
mojom::BindInterfacePriority priority,
mojom::Connector::BindInterfaceCallback callback);
// Variant of the above where no interface name, receiving pipe, Service
// remote, or PIDReceiver is provided by the caller.
void Connect(const ServiceFilter& partial_target_filter,
const Identity& source_identity,
mojom::Connector::BindInterfaceCallback callback);
// Variant of the above where no interface name or receiving pipe is provided
// by the caller, but a Service remote and PIDReceiver are provided.
void Connect(const ServiceFilter& partial_target_filter,
const Identity& source_identity,
mojo::PendingRemote<mojom::Service> service_remote,
mojo::PendingReceiver<mojom::PIDReceiver> pid_receiver,
mojom::Connector::BindInterfaceCallback callback);
private: private:
friend class ServiceInstance; friend class ServiceInstance;
...@@ -129,7 +108,7 @@ class ServiceManager : public Service { ...@@ -129,7 +108,7 @@ class ServiceManager : public Service {
// Returns a running instance identified by |identity|. // Returns a running instance identified by |identity|.
ServiceInstance* GetExistingInstance(const Identity& identity) const; ServiceInstance* GetExistingInstance(const Identity& identity) const;
void NotifyServiceCreated(ServiceInstance* instance); void NotifyServiceCreated(const ServiceInstance& instance);
void NotifyServiceStarted(const Identity& identity, base::ProcessId pid); void NotifyServiceStarted(const Identity& identity, base::ProcessId pid);
void NotifyServiceFailedToStart(const Identity& identity); void NotifyServiceFailedToStart(const Identity& identity);
...@@ -141,11 +120,6 @@ class ServiceManager : public Service { ...@@ -141,11 +120,6 @@ class ServiceManager : public Service {
// Called from the instance implementing mojom::ServiceManager. // Called from the instance implementing mojom::ServiceManager.
void AddListener(mojom::ServiceManagerListenerPtr listener); void AddListener(mojom::ServiceManagerListenerPtr listener);
void CreateServiceWithFactory(const ServiceFilter& service_factory_filter,
const std::string& name,
mojom::ServiceRequest request,
mojom::PIDReceiverPtr pid_receiver);
// Returns a running ServiceFactory for |filter|. If there is not one running, // Returns a running ServiceFactory for |filter|. If there is not one running,
// one is started. // one is started.
mojom::ServiceFactory* GetServiceFactory(const ServiceFilter& filter); mojom::ServiceFactory* GetServiceFactory(const ServiceFilter& filter);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment