| Index: services/service_manager/public/cpp/lib/interface_registry.cc
|
| diff --git a/services/service_manager/public/cpp/lib/interface_registry.cc b/services/service_manager/public/cpp/lib/interface_registry.cc
|
| index 71640d06f93a93bfb67ea4917957600c6ea0a02f..25e537c876ce93264b7084f66f30b260df8a5f92 100644
|
| --- a/services/service_manager/public/cpp/lib/interface_registry.cc
|
| +++ b/services/service_manager/public/cpp/lib/interface_registry.cc
|
| @@ -10,27 +10,83 @@
|
| #include "services/service_manager/public/cpp/connection.h"
|
|
|
| namespace service_manager {
|
| +namespace {
|
| +
|
| +// Returns the set of capabilities required from the target.
|
| +CapabilitySet GetRequestedCapabilities(const InterfaceProviderSpec& source_spec,
|
| + const Identity& target) {
|
| + CapabilitySet capabilities;
|
| +
|
| + // Start by looking for specs specific to the supplied identity.
|
| + auto it = source_spec.requires.find(target.name());
|
| + if (it != source_spec.requires.end()) {
|
| + std::copy(it->second.begin(), it->second.end(),
|
| + std::inserter(capabilities, capabilities.begin()));
|
| + }
|
| +
|
| + // Apply wild card rules too.
|
| + it = source_spec.requires.find("*");
|
| + if (it != source_spec.requires.end()) {
|
| + std::copy(it->second.begin(), it->second.end(),
|
| + std::inserter(capabilities, capabilities.begin()));
|
| + }
|
| + return capabilities;
|
| +}
|
|
|
| -InterfaceRegistry::InterfaceRegistry()
|
| - : binding_(this), allow_all_interfaces_(true), weak_factory_(this) {}
|
| +// Generates a single set of interfaces that is the union of all interfaces
|
| +// exposed by the target for the capabilities requested by the source.
|
| +InterfaceSet GetAllowedInterfaces(
|
| + const InterfaceProviderSpec& source_spec,
|
| + const Identity& target,
|
| + const InterfaceProviderSpec& target_spec) {
|
| + InterfaceSet allowed_interfaces;
|
| + // TODO(beng): remove this once we can assert that an InterfaceRegistry must
|
| + // always be constructed with a valid identity.
|
| + if (!target.IsValid()) {
|
| + allowed_interfaces.insert("*");
|
| + return allowed_interfaces;
|
| + }
|
| + CapabilitySet capabilities = GetRequestedCapabilities(source_spec, target);
|
| + for (const auto& capability : capabilities) {
|
| + auto it = target_spec.provides.find(capability);
|
| + if (it != target_spec.provides.end()) {
|
| + for (const auto& interface_name : it->second)
|
| + allowed_interfaces.insert(interface_name);
|
| + }
|
| + }
|
| + return allowed_interfaces;
|
| +}
|
| +
|
| +
|
| +} // namespace
|
|
|
| InterfaceRegistry::InterfaceRegistry(
|
| - const Identity& local_identity,
|
| - const Identity& remote_identity,
|
| - const InterfaceSet& allowed_interfaces)
|
| + const Identity& identity,
|
| + const InterfaceProviderSpec& interface_provider_spec)
|
| : binding_(this),
|
| - local_identity_(local_identity),
|
| - remote_identity_(remote_identity),
|
| - allowed_interfaces_(allowed_interfaces),
|
| - allow_all_interfaces_(allowed_interfaces_.size() == 1 &&
|
| - allowed_interfaces_.count("*") == 1),
|
| + identity_(identity),
|
| + interface_provider_spec_(interface_provider_spec),
|
| weak_factory_(this) {}
|
|
|
| InterfaceRegistry::~InterfaceRegistry() {}
|
|
|
| void InterfaceRegistry::Bind(
|
| - mojom::InterfaceProviderRequest local_interfaces_request) {
|
| + mojom::InterfaceProviderRequest local_interfaces_request,
|
| + const Identity& remote_identity,
|
| + const InterfaceProviderSpec& remote_interface_provider_spec) {
|
| DCHECK(!binding_.is_bound());
|
| + remote_identity_ = remote_identity;
|
| + allowed_interfaces_ = GetAllowedInterfaces(remote_interface_provider_spec,
|
| + identity_,
|
| + interface_provider_spec_);
|
| + allow_all_interfaces_ =
|
| + allowed_interfaces_.size() == 1 && allowed_interfaces_.count("*") == 1;
|
| + if (!allow_all_interfaces_) {
|
| + for (auto it = name_to_binder_.begin(); it != name_to_binder_.end(); ++it) {
|
| + if (allowed_interfaces_.count(it->first) == 0)
|
| + name_to_binder_.erase(it);
|
| + }
|
| + }
|
| binding_.Bind(std::move(local_interfaces_request));
|
| }
|
|
|
| @@ -98,7 +154,7 @@ void InterfaceRegistry::GetInterface(const std::string& interface_name,
|
| std::stringstream ss;
|
| ss << "Capability spec prevented service " << remote_identity_.name()
|
| << " from binding interface: " << interface_name
|
| - << " exposed by: " << local_identity_.name();
|
| + << " exposed by: " << identity_.name();
|
| LOG(ERROR) << ss.str();
|
| mojo::ReportBadMessage(ss.str());
|
| } else if (!default_binder_.is_null()) {
|
| @@ -106,7 +162,7 @@ void InterfaceRegistry::GetInterface(const std::string& interface_name,
|
| } else {
|
| LOG(ERROR) << "Failed to locate a binder for interface: " << interface_name
|
| << " requested by: " << remote_identity_.name()
|
| - << " exposed by: " << local_identity_.name();
|
| + << " exposed by: " << identity_.name();
|
| }
|
| }
|
|
|
| @@ -123,6 +179,11 @@ bool InterfaceRegistry::SetInterfaceBinderForName(
|
|
|
| bool InterfaceRegistry::CanBindRequestForInterface(
|
| const std::string& interface_name) const {
|
| + // Any interface may be registered before the registry is bound to a pipe. At
|
| + // bind time, the interfaces exposed will be intersected with the requirements
|
| + // of the source.
|
| + if (!binding_.is_bound())
|
| + return true;
|
| return allow_all_interfaces_ || allowed_interfaces_.count(interface_name);
|
| }
|
|
|
|
|