Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Unified Diff: services/service_manager/public/cpp/lib/interface_registry.cc

Issue 2446313003: Revise InterfaceRegistry API to support filtering interfaces @ Bind() time. (Closed)
Patch Set: . Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
}
« no previous file with comments | « services/service_manager/public/cpp/lib/identity.cc ('k') | services/service_manager/public/cpp/lib/service_context.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698