Commit e70e635a authored by ben's avatar ben Committed by Commit bot

Perform InterfaceProviderSpec intersection in the ServiceManager.

. Introduces a parallel flow in ServiceManager to Connect called BindInterface which carries (via ConnectParams) interface name and pipe.
. Introduces an OnBindInterface() method to mojom::Service. In ServiceContext, this just calls through to OnConnect still since updating callsites is a pretty large task for a subsequent change.

Note that policy checking is still happening in the client - there was no easy way to avoid this without adding an unsafe mode to InterfaceRegistry that skips the check that I'd be concerned might be misused. And IR should probably just die once this work is complete anyway.

R=rockot@chromium.org,tsepez@chromium.org

Review-Url: https://codereview.chromium.org/2610853013
Cr-Commit-Position: refs/heads/master@{#443119}
parent e62b61b8
......@@ -52,6 +52,22 @@ class ConnectParams {
return std::move(pid_receiver_request_);
}
void set_interface_request_info(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
interface_name_ = interface_name;
interface_pipe_ = std::move(interface_pipe);
}
const std::string& interface_name() const {
return interface_name_;
}
bool HasInterfaceRequestInfo() const {
return !interface_name_.empty() && interface_pipe_.is_valid();
}
mojo::ScopedMessagePipeHandle TakeInterfaceRequestPipe() {
return std::move(interface_pipe_);
}
void set_connect_callback(const mojom::Connector::ConnectCallback& value) {
connect_callback_ = value;
}
......@@ -59,6 +75,15 @@ class ConnectParams {
return connect_callback_;
}
void set_bind_interface_callback(
const mojom::Connector::BindInterfaceCallback& callback) {
bind_interface_callback_ = callback;
}
const mojom::Connector::BindInterfaceCallback&
bind_interface_callback() const {
return bind_interface_callback_;
}
private:
// It may be null (i.e., is_null() returns true) which indicates that there is
// no source (e.g., for the first application or in tests).
......@@ -69,7 +94,10 @@ class ConnectParams {
mojom::InterfaceProviderRequest remote_interfaces_;
mojom::ServicePtr service_;
mojom::PIDReceiverRequest pid_receiver_request_;
std::string interface_name_;
mojo::ScopedMessagePipeHandle interface_pipe_;
mojom::Connector::ConnectCallback connect_callback_;
mojom::Connector::BindInterfaceCallback bind_interface_callback_;
DISALLOW_COPY_AND_ASSIGN(ConnectParams);
};
......
......@@ -24,6 +24,16 @@ namespace service_manager {
class Connection;
class InterfaceBinder;
// Returns the set of capabilities required from the target.
CapabilitySet GetRequestedCapabilities(const InterfaceProviderSpec& source_spec,
const Identity& target);
// 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 GetInterfacesToExpose(const InterfaceProviderSpec& source_spec,
const Identity& target,
const InterfaceProviderSpec& target_spec);
// An implementation of mojom::InterfaceProvider that allows the user to
// register services to be exposed to another application.
//
......
......@@ -13,7 +13,29 @@
namespace service_manager {
namespace {
// Returns the set of capabilities required from the target.
void SerializeIdentity(const Identity& identity, std::stringstream* stream) {
*stream << identity.name() << "@" << identity.instance() << " run as: "
<< identity.user_id();
}
void SerializeSpec(const InterfaceProviderSpec& spec,
std::stringstream* stream) {
*stream << " Providing:\n";
for (const auto& entry : spec.provides) {
*stream << " capability: " << entry.first << " containing interfaces:\n";
for (const auto& interface_name : entry.second)
*stream << " " << interface_name << "\n";
}
*stream << "\n Requiring:\n";
for (const auto& entry : spec.requires) {
*stream << " From: " << entry.first << ":\n";
for (const auto& capability_name : entry.second)
*stream << " " << capability_name << "\n";
}
}
} // namespace
CapabilitySet GetRequestedCapabilities(const InterfaceProviderSpec& source_spec,
const Identity& target) {
CapabilitySet capabilities;
......@@ -34,8 +56,6 @@ CapabilitySet GetRequestedCapabilities(const InterfaceProviderSpec& source_spec,
return capabilities;
}
// 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 GetInterfacesToExpose(
const InterfaceProviderSpec& source_spec,
const Identity& target,
......@@ -58,29 +78,6 @@ InterfaceSet GetInterfacesToExpose(
return exposed_interfaces;
}
void SerializeIdentity(const Identity& identity, std::stringstream* stream) {
*stream << identity.name() << "@" << identity.instance() << " run as: "
<< identity.user_id();
}
void SerializeSpec(const InterfaceProviderSpec& spec,
std::stringstream* stream) {
*stream << " Providing:\n";
for (const auto& entry : spec.provides) {
*stream << " capability: " << entry.first << " containing interfaces:\n";
for (const auto& interface_name : entry.second)
*stream << " " << interface_name << "\n";
}
*stream << "\n Requiring:\n";
for (const auto& entry : spec.requires) {
*stream << " From: " << entry.first << ":\n";
for (const auto& capability_name : entry.second)
*stream << " " << capability_name << "\n";
}
}
} // namespace
InterfaceRegistry::InterfaceRegistry(const std::string& name)
: binding_(this),
name_(name),
......
......@@ -98,14 +98,46 @@ void ServiceContext::OnConnect(
local_info_.interface_provider_specs, &target_spec);
GetInterfaceProviderSpec(mojom::kServiceManager_ConnectorSpec,
source_info.interface_provider_specs, &source_spec);
// Acknowledge the request regardless of whether it's accepted.
callback.Run();
CallOnConnect(source_info, source_spec, target_spec, std::move(interfaces));
}
void ServiceContext::OnBindInterface(
const ServiceInfo& source_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe,
const OnBindInterfaceCallback& callback) {
// Acknowledge the request regardless of whether it's accepted.
callback.Run();
mojom::InterfaceProviderPtr interface_provider;
// TODO(beng): This should be replaced with a call to OnBindInterface() in a
// subsequent change.
InterfaceProviderSpec source_spec, target_spec;
GetInterfaceProviderSpec(mojom::kServiceManager_ConnectorSpec,
local_info_.interface_provider_specs, &target_spec);
GetInterfaceProviderSpec(mojom::kServiceManager_ConnectorSpec,
source_info.interface_provider_specs, &source_spec);
CallOnConnect(source_info, source_spec, target_spec,
MakeRequest(&interface_provider));
interface_provider->GetInterface(interface_name, std::move(interface_pipe));
}
////////////////////////////////////////////////////////////////////////////////
// ServiceContext, private:
void ServiceContext::CallOnConnect(const ServiceInfo& source_info,
const InterfaceProviderSpec& source_spec,
const InterfaceProviderSpec& target_spec,
mojom::InterfaceProviderRequest interfaces) {
auto registry =
base::MakeUnique<InterfaceRegistry>(mojom::kServiceManager_ConnectorSpec);
registry->Bind(std::move(interfaces), local_info_.identity, target_spec,
source_info.identity, source_spec);
// Acknowledge the request regardless of whether it's accepted.
callback.Run();
if (!service_->OnConnect(source_info, registry.get()))
return;
......@@ -117,9 +149,6 @@ void ServiceContext::OnConnect(
std::make_pair(raw_registry, std::move(registry)));
}
////////////////////////////////////////////////////////////////////////////////
// ServiceContext, private:
void ServiceContext::OnConnectionError() {
// Note that the Service doesn't technically have to quit now, it may live
// on to service existing connections. All existing Connectors however are
......
......@@ -112,6 +112,16 @@ class ServiceContext : public mojom::Service {
void OnConnect(const ServiceInfo& source_info,
mojom::InterfaceProviderRequest interfaces,
const OnConnectCallback& callback) override;
void OnBindInterface(
const ServiceInfo& source_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe,
const OnBindInterfaceCallback& callback) override;
void CallOnConnect(const ServiceInfo& source_info,
const InterfaceProviderSpec& source_spec,
const InterfaceProviderSpec& target_spec,
mojom::InterfaceProviderRequest request);
void OnConnectionError();
void OnRegistryConnectionError(InterfaceRegistry* registry);
......
......@@ -67,4 +67,32 @@ interface Service {
// seek to bind interface implementations exported by the target.
//
OnConnect(ServiceInfo source_info, InterfaceProvider&? interfaces) => ();
// Called when a request to bind an interface is received from another
// ("source") service. This is the result of that service calling
// BindInterface() on a Connector. By the time this method is called, the
// service manager has already completed a policy check to determine that this
// interface can be bound.
//
// The Service must respond to acknowledge receipt of the request.
//
// Parameters:
//
// source_info
// Contains the source identity and interface provider specs.
//
// interface_name
// The name of the interface to be bound.
//
// interface_pipe
// The message pipe to bind the interface implementation to.
//
// TODO(beng): It occurs to me that |source_info| leaks all metadata about
// the source's capability requirements to the target. This seems
// undesirable. The metadata supplied here should be germane to
// fulfilling this request and no more.
// TODO(beng): This should replace OnConnect().
OnBindInterface(ServiceInfo source_info,
string interface_name,
handle<message_pipe> interface_pipe) => ();
};
This diff is collapsed.
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