blob: 96e23a764435ec4af7a4b0b0da3534dedfaba639 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_SERVICE_MANAGER_PUBLIC_CPP_INTERFACE_REGISTRY_H_
#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_INTERFACE_REGISTRY_H_
#include <list>
#include <memory>
#include <queue>
#include <set>
#include <utility>
#include "base/callback.h"
#include "base/memory/ptr_util.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/cpp/interface_provider_spec.h"
#include "services/service_manager/public/cpp/lib/callback_binder.h"
#include "services/service_manager/public/cpp/lib/interface_factory_binder.h"
#include "services/service_manager/public/interfaces/interface_provider.mojom.h"
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.
//
// To use, define a class that implements your specific interface. Then
// implement an InterfaceFactory<Foo> that binds instances of FooImpl to
// InterfaceRequest<Foo>s and register that on the registry like this:
//
// registry.AddInterface(&factory);
//
// Or, if you have multiple factories implemented by the same type, explicitly
// specify the interface to register the factory for:
//
// registry.AddInterface<Foo>(&my_foo_and_bar_factory_);
// registry.AddInterface<Bar>(&my_foo_and_bar_factory_);
//
// The InterfaceFactory must outlive the InterfaceRegistry.
//
// Additionally you may specify a default InterfaceBinder to handle requests for
// interfaces unhandled by any registered InterfaceFactory. Just as with
// InterfaceFactory, the default InterfaceBinder supplied must outlive
// InterfaceRegistry.
//
class InterfaceRegistry : public mojom::InterfaceProvider {
public:
using Binder = base::Callback<void(const std::string&,
mojo::ScopedMessagePipeHandle)>;
class TestApi {
public:
explicit TestApi(InterfaceRegistry* registry) : registry_(registry) {}
~TestApi() {}
void SetInterfaceBinderForName(InterfaceBinder* binder,
const std::string& interface_name) {
registry_->SetInterfaceBinderForName(
base::WrapUnique(binder), interface_name);
}
template <typename Interface>
void GetLocalInterface(mojo::InterfaceRequest<Interface> request) {
GetLocalInterface(Interface::Name_, request.PassMessagePipe());
}
void GetLocalInterface(const std::string& name,
mojo::ScopedMessagePipeHandle handle) {
registry_->GetInterface(name, std::move(handle));
}
private:
InterfaceRegistry* registry_;
DISALLOW_COPY_AND_ASSIGN(TestApi);
};
// Construct an unbound InterfaceRegistry. This object will not bind requests
// for interfaces until Bind() is called. |name| is used for error reporting
// and should reflect the name of the InterfaceProviderSpec pair that controls
// which interfaces can be bound via this InterfaceRegistry.
explicit InterfaceRegistry(const std::string& name);
~InterfaceRegistry() override;
// Sets a default handler for incoming interface requests which are allowed by
// capability filters but have no registered handler in this registry.
void set_default_binder(const Binder& binder) { default_binder_ = binder; }
// Binds a request for an InterfaceProvider from a remote source.
// |remote_info| contains the the identity of the remote, and the remote's
// InterfaceProviderSpec, which will be intersected with the local's exports
// to determine what interfaces may be bound.
void Bind(mojom::InterfaceProviderRequest request,
const Identity& local_identity,
const InterfaceProviderSpec& local_interface_provider_spec,
const Identity& remote_identity,
const InterfaceProviderSpec& remote_interface_provider_spec);
// Serializes the contents of the registry (including the local and remote
// specs) to a stringstream.
void Serialize(std::stringstream* stream);
base::WeakPtr<InterfaceRegistry> GetWeakPtr();
// Allows |Interface| to be exposed via this registry. Requests to bind will
// be handled by |factory|. Returns true if the interface was exposed, false
// if Connection policy prevented exposure.
template <typename Interface>
bool AddInterface(InterfaceFactory<Interface>* factory) {
return SetInterfaceBinderForName(
base::MakeUnique<internal::InterfaceFactoryBinder<Interface>>(factory),
Interface::Name_);
}
// Like AddInterface above, except supplies a callback to bind the MP instead
// of an InterfaceFactory, and optionally provides a task runner where the
// callback will be run.
template <typename Interface>
bool AddInterface(
const base::Callback<void(mojo::InterfaceRequest<Interface>)>& callback,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner =
nullptr) {
return SetInterfaceBinderForName(
base::MakeUnique<internal::CallbackBinder<Interface>>(callback,
task_runner),
Interface::Name_);
}
bool AddInterface(
const std::string& name,
const base::Callback<void(mojo::ScopedMessagePipeHandle)>& callback,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner =
nullptr);
template <typename Interface>
void RemoveInterface() {
RemoveInterface(Interface::Name_);
}
void RemoveInterface(const std::string& name);
// Temporarily prevent incoming interface requests from being bound. Incoming
// requests will be queued internally and dispatched once ResumeBinding() is
// called.
void PauseBinding();
// Resumes incoming interface request binding.
void ResumeBinding();
// Populates a set with the interface names this registry can bind.
void GetInterfaceNames(std::set<std::string>* interface_names);
// Sets a closure to be run when the InterfaceProvider pipe is closed. Note
// that by the time any added closure is invoked, the InterfaceRegistry may
// have been deleted.
void AddConnectionLostClosure(const base::Closure& connection_lost_closure);
// Binds a local interface request.
void BindInterface(const std::string& name,
mojo::ScopedMessagePipeHandle handle);
private:
using InterfaceNameToBinderMap =
std::map<std::string, std::unique_ptr<InterfaceBinder>>;
// mojom::InterfaceProvider:
void GetInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle handle) override;
// Returns true if the binder was set, false if it was not set (e.g. by
// some filtering policy preventing this interface from being exposed).
bool SetInterfaceBinderForName(std::unique_ptr<InterfaceBinder> binder,
const std::string& name);
// Returns true if |remote_identity_| is allowed to bind |interface_name|,
// according to capability policy.
bool CanBindRequestForInterface(const std::string& interface_name) const;
// Called whenever |remote_interface_provider_spec_| changes to rebuild the
// contents of |exposed_interfaces_| and |expose_all_interfaces_|.
void RebuildExposedInterfaces();
void OnConnectionError();
mojom::InterfaceProviderRequest pending_request_;
mojo::Binding<mojom::InterfaceProvider> binding_;
std::string name_;
// Initialized from static metadata in the host service's manifest.
Identity local_identity_;
InterfaceProviderSpec local_interface_provider_spec_;
// Initialized from static metadata in the remote service's manifest.
Identity remote_identity_;
// Initialized from static metadata in the remote service's manifest. May be
// mutated after the fact when a capability is dynamically granted via a call
// to GrantCapability().
InterfaceProviderSpec remote_interface_provider_spec_;
// Metadata computed whenever |remote_interface_provider_spec_| changes.
InterfaceSet exposed_interfaces_;
bool expose_all_interfaces_ = false;
// Contains every interface binder that has been registered with this
// InterfaceRegistry. Not all binders may be reachable depending on the
// capabilities requested by the remote. Only interfaces in
// exposed_interfaces_ may be bound. When |expose_all_interfaces_| is true,
// any interface may be bound.
InterfaceNameToBinderMap name_to_binder_;
Binder default_binder_;
bool is_paused_ = false;
// Pending interface requests which can accumulate if GetInterface() is called
// while binding is paused.
std::queue<std::pair<std::string, mojo::ScopedMessagePipeHandle>>
pending_interface_requests_;
std::list<base::Closure> connection_lost_closures_;
base::WeakPtrFactory<InterfaceRegistry> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(InterfaceRegistry);
};
} // namespace service_manager
#endif // SERVICES_SERVICE_MANAGER_PUBLIC_CPP_INTERFACE_REGISTRY_H_