// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module service_manager.mojom;
import "mojo/public/mojom/base/process_id.mojom";
import "mojo/public/mojom/base/token.mojom";
import "services/service_manager/public/mojom/constants.mojom";
import "services/service_manager/public/mojom/interface_provider.mojom";
import "services/service_manager/public/mojom/service_filter.mojom";
// TODO(beng): Evaluate the utility of this enum. There are some inconsistencies
// in its use with BindInterface/WarmService.
enum ConnectResult {
// The operation was completed successfully.
SUCCEEDED,
// The given service name specified by |name| does not match a known service.
INVALID_ARGUMENT,
// Policy prevented the successful completion of this operation. Either
// requests to bind to |name| are forbidden from the calling service by its
// manifest, or the service attempted to connect to an instance in an instance
// group with which it's not allowed to communicate.
ACCESS_DENIED
};
// Used with BindInterface to indicate how the Service Manager should treat an
// individual interface request.
enum BindInterfacePriority {
// The request is important and the Service Manager should try to keep the
// destination service instance alive until it receives the request. This is
// generally the default mode of operation that clients want.
kImportant,
// Allows the Service Manager to route the request to a service instance which
// may die by the time the request arrives. BindInterface calls which use this
// priority may be inherently flaky, but this behavior can be desirable in
// cases where a service manages its lifetime independent of whether the given
// interface is in use (e.g. for shared client support like tracing).
kBestEffort,
};
// A collection of metadata that disambiguates instances in the service manager.
struct Identity {
// A name identifying a service.
string name;
// Identifies the instance group to which a service instance belongs. Most
// running service instances can only reach (via Connector) other service
// instances running in the same instance group. This facilitates a mode of
// isolation which is useful for modeling, e.g., different users in a multi-
// user system. Must always be non-zero.
mojo_base.mojom.Token instance_group;
// Disambiguates multiple instances of the same service potentially running
// within the same instance group. Used for more granular isolation of
// instances. May be zero.
//
// At any given moment, there can be at most ONE service instance running with
// any given combination of |name|, |instance_group|, and |instance_id|.
mojo_base.mojom.Token instance_id;
// A Token which globally and uniquely identifies a service instance across
// space and time. This value is generated and assigned by the Service Manager
// when starting a new instance, or is given to the Service Manager by a
// privileged client using the |Connector.RegisterServiceInstance()| API.
//
// In either case, this value is always unique to a single service instance.
mojo_base.mojom.Token globally_unique_id;
};
// Static metadata about a service the Service Manager knows about. This is
// information pertaining to the service definition itself (e.g. registered
// manifest contents), not to any particular service instance running in the
// system.
struct ServiceInfo {
// A string describing the kind of sandboxing the service has declared for
// itself in its manifest.
string sandbox_type;
};
// Implemented by an object in the Service Manager associated with a specific
// instance. Used by privileged clients to inform the Service Manager about
// metadata concerning a specific service process controlled by the client. See
// |Connector.RegisterServiceInstance()| and
// |Service.CreatePackagedServiceInstance()|.
interface ProcessMetadata {
SetPID(mojo_base.mojom.ProcessId pid);
};
// An interface that allows the holder to start other services & bind to
// interfaces exposed by them.
interface Connector {
// Asks the Service Manager to route an interface request to another service
// instance. The target instance is selected by |filter|, subject to various
// constraints. With some exceptions and limitations, if no existing service
// instance is found matching the given |filter|, a new instance is started
// which meets the constraints of the filter.
//
// Upon success, |result| will be |SUCCEEDED| and |identity| will contain the
// full identity of the service instance to which the request was successfully
// routed. Upon failure |result| will take on a different value and |identity|
// will be null.
//
// If |filter| filters only by service name, the Service Manager may select
// any running service instance with that service name. If the named service
// is not a singleton or otherwise shared across all instance groups, the
// selection space is limited to the caller's own instance group.
//
// If |filter| includes an instance group ID, either that group ID must match
// the caller's own, or the caller must have set the
// |can_connect_to_instances_in_any_group| option in its own manifest.
//
// If |filter| includes an instance ID, the caller must have set the
// |can_connect_to_other_services_with_any_instance_name| option in its own
// manifest.
//
// If |filter| includes a globally unique ID, it must include a group ID and
// instance ID as well. Requests like this will only ever match a specific
// service instance that is already running. Unlike in other cases, the
// Service Manager will NEVER create a new service instance to fulfill this
// request.
BindInterface(ServiceFilter filter,
string interface_name,
handle<message_pipe> interface_pipe,
BindInterfacePriority priority)
=> (ConnectResult result, Identity? identity);
// Asks the Service Manager for details about the service named
// |service_name|. No processes are started as a result of this request. On
// response, |info| provides information about the service. If the Service
// Manager is not familiar the named service, |info| will be null.
QueryService(string service_name) => (ServiceInfo? info);
// Asks the Service Manager to ensure that a service instance which would
// match |filter| (from the caller's perspective) is running. This is
// essentially equivalent to |BindInterface()| above but no interface request
// is given to bind. This is mainly here as a performance measure, as a client
// may wish to ensure that a service is warmed up by the time the client
// actually needs it.
//
// See comments on |BindInterface()| above for details on filtering
// constraints, instance creation, and response values.
WarmService(ServiceFilter filter)
=> (ConnectResult result, Identity? identity);
// Typically, the Service Manager will start a process for a service the first
// time it receives a |BindInterface()| or |WarmService()| request for a
// filter it can't match to an existing instance.
//
// This call allows new service instances to be explicitly injected into the
// Service Manager's set of running services. As such, this is considered to
// be a highly privileged API. A service calling this API must have the
// |can_create_other_service_instances| option set to |true| in its own
// manifest or the request will be rejected.
//
// |identity| is the full identity of the service instance to introduce. This
// must include a valid instance group and a valid, random, globally unique
// ID.
//
// |service| is a |Service| interface pipe (i.e. a ServicePtr in C++).
//
// |metadata_receiver| is the receiving end of a ProcessMetadata pipe. The
// caller is expected to call |SetPID()| on the other end of this pipe in
// order to inform the Service Manager about which process is actually hosting
// the service instance.
//
// TODO(crbug.com/40601908): We should be able to be more typesafe here
// for the |service| argument, but Service's definition requires Connector's
// definition and we don't yet support circular mojom imports. Hence the raw
// message pipe.
RegisterServiceInstance(Identity identity,
handle<message_pipe> service,
pending_receiver<ProcessMetadata>? metadata_receiver)
=> (ConnectResult result);
// Binds another Connector pipe to this same implementation. This effectively
// allows the client to "clone" its Connector arbitrarily many times, for
// example to mint Connector endpoints for different threads to use.
Clone(pending_receiver<Connector> receiver);
};