Index: services/service_manager/service_manager.cc |
diff --git a/services/service_manager/service_manager.cc b/services/service_manager/service_manager.cc |
index 59ab943054c01b9063faf89e94a788fa706a4e4b..606ff04f2253cce52c600275d03050d183d3535e 100644 |
--- a/services/service_manager/service_manager.cc |
+++ b/services/service_manager/service_manager.cc |
@@ -118,12 +118,12 @@ class ServiceManager::Instance |
public: |
Instance(service_manager::ServiceManager* service_manager, |
const Identity& identity, |
- const InterfaceProviderSpec& connection_spec) |
+ const InterfaceProviderSpecMap& interface_provider_specs) |
: service_manager_(service_manager), |
id_(GenerateUniqueID()), |
identity_(identity), |
- connection_spec_(connection_spec), |
- allow_any_application_(connection_spec.requires.count("*") == 1), |
+ interface_provider_specs_(interface_provider_specs), |
+ allow_any_application_(GetConnectionSpec().requires.count("*") == 1), |
pid_receiver_binding_(this), |
weak_factory_(this) { |
if (identity_.name() == kServiceManagerName || |
@@ -177,12 +177,13 @@ class ServiceManager::Instance |
identity_.user_id()); |
} |
+ InterfaceProviderSpec connection_spec = GetConnectionSpec(); |
CapabilitySet capabilities; |
InterfaceSet interfaces; |
Instance* source = service_manager_->GetExistingInstance(params->source()); |
if (source) { |
- GetCapabilitiesAndInterfacesForConnection(source->connection_spec_, |
- identity_, connection_spec_, |
+ GetCapabilitiesAndInterfacesForConnection(source->GetConnectionSpec(), |
+ identity_, connection_spec, |
&capabilities, &interfaces); |
} else { |
interfaces.insert("*"); |
@@ -190,13 +191,17 @@ class ServiceManager::Instance |
// The target has specified that sources must request one of its provided |
// classes instead of specifying a wild-card for interfaces. |
- if (HasCapability(connection_spec_, kCapability_ExplicitClass) && |
+ if (HasCapability(connection_spec, kCapability_ExplicitClass) && |
(interfaces.count("*") != 0)) { |
interfaces.erase("*"); |
} |
- service_->OnConnect(params->source(), params->TakeRemoteInterfaces(), |
- interfaces, capabilities); |
+ InterfaceProviderSpecMap specs; |
+ if (source) |
+ specs = source->interface_provider_specs_; |
+ service_->OnConnect(ServiceInfo(params->source(), specs), |
+ params->TakeRemoteInterfaces(), interfaces, |
+ capabilities); |
return true; |
} |
@@ -206,7 +211,7 @@ class ServiceManager::Instance |
service_.set_connection_error_handler( |
base::Bind(&Instance::OnServiceLost, base::Unretained(this), |
service_manager_->GetWeakPtr())); |
- service_->OnStart(identity_, |
+ service_->OnStart(ServiceInfo(identity_, interface_provider_specs_), |
base::Bind(&Instance::OnInitializeResponse, |
base::Unretained(this))); |
} |
@@ -232,16 +237,18 @@ class ServiceManager::Instance |
StartWithService(std::move(service)); |
} |
- mojom::ServiceInfoPtr CreateServiceInfo() const { |
- mojom::ServiceInfoPtr info(mojom::ServiceInfo::New()); |
+ mojom::RunningServiceInfoPtr CreateRunningServiceInfo() const { |
+ mojom::RunningServiceInfoPtr info(mojom::RunningServiceInfo::New()); |
info->id = id_; |
info->identity = identity_; |
info->pid = pid_; |
return info; |
} |
- const InterfaceProviderSpec& connection_spec() const { |
- return connection_spec_; |
+ const InterfaceProviderSpec& GetConnectionSpec() const { |
+ auto it = interface_provider_specs_.find( |
+ mojom::kServiceManager_ConnectorSpec); |
+ return it != interface_provider_specs_.end() ? it->second : empty_spec_; |
} |
const Identity& identity() const { return identity_; } |
uint32_t id() const { return id_; } |
@@ -251,7 +258,8 @@ class ServiceManager::Instance |
InterfaceRegistry* registry) override { |
Instance* source = service_manager_->GetExistingInstance(remote_identity); |
DCHECK(source); |
- if (HasCapability(source->connection_spec_, kCapability_ServiceManager)) { |
+ if (HasCapability(source->GetConnectionSpec(), |
+ kCapability_ServiceManager)) { |
registry->AddInterface<mojom::ServiceManager>(this); |
return true; |
} |
@@ -331,7 +339,7 @@ class ServiceManager::Instance |
const Identity& target, |
const ConnectCallback& callback) { |
if (!client_process_connection->is_null()) { |
- if (!HasCapability(connection_spec_, kCapability_ClientProcess)) { |
+ if (!HasCapability(GetConnectionSpec(), kCapability_ClientProcess)) { |
LOG(ERROR) << "Instance: " << identity_.name() << " attempting " |
<< "to register an instance for a process it created for " |
<< "target: " << target.name() << " without the " |
@@ -365,12 +373,13 @@ class ServiceManager::Instance |
bool ValidateConnectionSpec(const Identity& target, |
const ConnectCallback& callback) { |
+ InterfaceProviderSpec connection_spec = GetConnectionSpec(); |
// TODO(beng): Need to do the following additional policy validation of |
// whether this instance is allowed to connect using: |
// - a non-null client_process_connection. |
if (target.user_id() != identity_.user_id() && |
target.user_id() != mojom::kRootUserID && |
- !HasCapability(connection_spec_, kCapability_UserID)) { |
+ !HasCapability(connection_spec, kCapability_UserID)) { |
LOG(ERROR) << "Instance: " << identity_.name() |
<< " running as: " << identity_.user_id() |
<< " attempting to connect to: " << target.name() |
@@ -382,7 +391,7 @@ class ServiceManager::Instance |
} |
if (!target.instance().empty() && |
target.instance() != GetNamePath(target.name()) && |
- !HasCapability(connection_spec_, kCapability_InstanceName)) { |
+ !HasCapability(connection_spec, kCapability_InstanceName)) { |
LOG(ERROR) << "Instance: " << identity_.name() << " attempting to " |
<< "connect to " << target.name() |
<< " using Instance name: " << target.instance() |
@@ -393,8 +402,8 @@ class ServiceManager::Instance |
} |
if (allow_any_application_ || |
- connection_spec_.requires.find(target.name()) != |
- connection_spec_.requires.end()) { |
+ connection_spec.requires.find(target.name()) != |
+ connection_spec.requires.end()) { |
return true; |
} |
LOG(ERROR) << "InterfaceProviderSpec prevented connection from: " |
@@ -461,7 +470,8 @@ class ServiceManager::Instance |
// process is launched. |
const uint32_t id_; |
const Identity identity_; |
- const InterfaceProviderSpec connection_spec_; |
+ const InterfaceProviderSpecMap interface_provider_specs_; |
+ const InterfaceProviderSpec empty_spec_; |
const bool allow_any_application_; |
std::unique_ptr<NativeRunner> runner_; |
mojom::ServicePtr service_; |
@@ -507,9 +517,11 @@ ServiceManager::ServiceManager( |
spec.requires["*"].insert("service_manager:service_factory"); |
spec.requires["service:catalog"].insert("service_manager:resolver"); |
spec.requires["service:tracing"].insert("app"); |
+ InterfaceProviderSpecMap specs; |
+ specs[mojom::kServiceManager_ConnectorSpec] = spec; |
service_manager_instance_ = |
- CreateInstance(Identity(), CreateServiceManagerIdentity(), spec); |
+ CreateInstance(Identity(), CreateServiceManagerIdentity(), specs); |
service_manager_instance_->StartWithService(std::move(service)); |
singletons_.insert(kServiceManagerName); |
service_context_.reset(new ServiceContext(this, std::move(request))); |
@@ -591,8 +603,11 @@ void ServiceManager::InitCatalog(mojom::ServicePtr catalog) { |
spec.provides["service_manager:resolver"].insert( |
"service_manager::mojom::Resolver"); |
spec.provides["control"].insert("catalog::mojom::CatalogControl"); |
+ InterfaceProviderSpecMap specs; |
+ specs[mojom::kServiceManager_ConnectorSpec] = spec; |
+ |
Instance* instance = CreateInstance( |
- CreateServiceManagerIdentity(), CreateCatalogIdentity(), spec); |
+ CreateServiceManagerIdentity(), CreateCatalogIdentity(), specs); |
singletons_.insert(kCatalogName); |
instance->StartWithService(std::move(catalog)); |
} |
@@ -709,11 +724,10 @@ bool ServiceManager::ConnectToExistingInstance( |
ServiceManager::Instance* ServiceManager::CreateInstance( |
const Identity& source, |
const Identity& target, |
- const InterfaceProviderSpec& connection_spec) { |
+ const InterfaceProviderSpecMap& specs) { |
CHECK(target.user_id() != mojom::kInheritUserID); |
- std::unique_ptr<Instance> instance( |
- new Instance(this, target, connection_spec)); |
+ auto instance = base::MakeUnique<Instance>(this, target, specs); |
Instance* raw_instance = instance.get(); |
Instance* source_instance = GetExistingInstance(source); |
@@ -729,7 +743,7 @@ ServiceManager::Instance* ServiceManager::CreateInstance( |
identity_to_instance_.insert(std::make_pair(target, raw_instance)); |
DCHECK(result.second); |
- mojom::ServiceInfoPtr info = raw_instance->CreateServiceInfo(); |
+ mojom::RunningServiceInfoPtr info = raw_instance->CreateRunningServiceInfo(); |
listeners_.ForAllPtrs([&info](mojom::ServiceManagerListener* listener) { |
listener->OnServiceCreated(info.Clone()); |
}); |
@@ -739,10 +753,10 @@ ServiceManager::Instance* ServiceManager::CreateInstance( |
void ServiceManager::AddListener(mojom::ServiceManagerListenerPtr listener) { |
// TODO(beng): filter instances provided by those visible to this service. |
- std::vector<mojom::ServiceInfoPtr> instances; |
+ std::vector<mojom::RunningServiceInfoPtr> instances; |
instances.reserve(identity_to_instance_.size()); |
for (auto& instance : identity_to_instance_) |
- instances.push_back(instance.second->CreateServiceInfo()); |
+ instances.push_back(instance.second->CreateRunningServiceInfo()); |
listener->OnInit(std::move(instances)); |
listeners_.AddPtr(std::move(listener)); |
@@ -795,11 +809,13 @@ void ServiceManager::OnGotResolvedName(std::unique_ptr<ConnectParams> params, |
result->qualifier != GetNamePath(result->resolved_name)) { |
instance_name = result->qualifier; |
} |
- // |result->connection_spec| can be null when there is no manifest, e.g. for |
- // URL types not resolvable by the resolver. |
+ // |result->interface_provider_specs| can be empty when there is no manifest, |
+ // e.g. for URL types not resolvable by the resolver. |
InterfaceProviderSpec connection_spec = GetPermissiveInterfaceProviderSpec(); |
- if (result->connection_spec.has_value()) |
- connection_spec = result->connection_spec.value(); |
+ auto it = result->interface_provider_specs.find( |
+ mojom::kServiceManager_ConnectorSpec); |
+ if (it != result->interface_provider_specs.end()) |
+ connection_spec = it->second; |
const std::string user_id = |
HasCapability(connection_spec, kCapability_AllUsers) |
@@ -832,7 +848,7 @@ void ServiceManager::OnGotResolvedName(std::unique_ptr<ConnectParams> params, |
mojom::ClientProcessConnectionPtr client_process_connection = |
params->TakeClientProcessConnection(); |
Instance* instance = CreateInstance(source_identity_for_creation, |
- target, connection_spec); |
+ target, result->interface_provider_specs); |
// Below are various paths through which a new Instance can be bound to a |
// Service proxy. |
@@ -848,7 +864,17 @@ void ServiceManager::OnGotResolvedName(std::unique_ptr<ConnectParams> params, |
} else { |
// Otherwise we create a new Service pipe. |
mojom::ServiceRequest request = GetProxy(&service); |
- CHECK(!result->package_path.empty() && result->connection_spec.has_value()); |
+ CHECK(!result->package_path.empty()); |
+ |
+ // The catalog was unable to read a manifest for this service. We can't do |
+ // anything more. |
+ // TODO(beng): There may be some cases where it's valid to have an empty |
+ // spec, so we should probably include a return value in |result|. |
+ if (result->interface_provider_specs.empty()) { |
+ if (!params->connect_callback().is_null()) |
+ params->connect_callback().Run(mojom::ConnectResult::ACCESS_DENIED, ""); |
+ return; |
+ } |
if (target.name() != result->resolved_name) { |
instance->StartWithService(std::move(service)); |