0

Update Mojo and services documentation

This is a large update to all Mojo and services documentation in the
tree. Here are the changes in a nutshell:

- Images for Mojo docs are upstreamed instead of being pulled from
  docs.google.com
- Various minor updates, corrections, clarifications in core Mojo
  docs
- Consolidation of documents in the tree.
- Refresh of all service and Service Manager related documentation,
  removing lots of outdated information, adding clarifying definitions
  and examples of core concepts

As of this CL, the relevant documentation in the tree is pared down
to:

- The mojo/ subtree itself
- services/README.md - service guidelines
- services/service_manager/README.md - general service manager
  and service API documentation, examples, etc
- docs/mojo_and_services.md - intro to mojo & services for
  chromium developers
- docs/mojo_ipc_conversion.md - advice for converting legacy IPCs
  to mojo interfaces
- docs/servicification.md - advice for servicifying chromium
  features specifically

Specifically this wipes out content/public/common/services.md,
ipc/README.md, services/service_manager/service_manifests.md, and
services/api_standards.md. Any still-relevant content that was in
these docs has been merged into one of the docs listed above.

Finally, the presence in docs/README.md has been cleaned up a bit.
A new section for "Mojo & Services" is added with links to the above
list of documents.

Change-Id: I294a32025afdca62441d3605da51d714f3aebd00
TBR: jam@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/c/1441640
Commit-Queue: Ken Rockot <rockot@google.com>
Reviewed-by: Oksana Zhuravlova <oksamyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#629384}
This commit is contained in:
Ken Rockot
2019-02-06 00:35:24 +00:00
committed by Commit Bot
parent bb00c14c88
commit ab035127bf
21 changed files with 2627 additions and 2244 deletions

@ -1,65 +0,0 @@
# Services in Content
The //content layer implements the core process model for Chrome, including
major process types: `browser`, `renderer`, `gpu`, `utility`, `plugin`. From the
perspective of the service manager, each process type is a service, and each
process instance is an instantiation of that service. For a renderer process,
its `service_manager::Identity` is constructed as follows:
```
name: content_renderer
userid: <guid, from BrowserContext that spawned this renderer>
instance: <string, generated from the RenderProcesHost's ID>
```
These services express the set of capabilities they expose to one another using
service manifests (see [Service Manager README](https://chromium.googlesource.com/chromium/src/+/master/services/service_manager/README.md)). For //content, the service manifests live in
`//content/public/app/mojo`.
Every `content::BrowserContext` has an instance group ID generated for it upon
construction, and the services run with that BrowserContext use that instance
group as part of their instance identity. Where there are multiple instances of
the same service within the same instance group, the Identity's instance ID
field is used for disambiguation.
Launching code for each process type is currently ad-hoc & specific per type,
and lives in `//content/browser`. In the medium-long term, we'll work to
generalize this and move it all into the service manager.
Each content process type is launched by host code in `//content/browser`,
though eventually all process launching will be moved to the service manager.
The canonical service for each process type is represented by an implementation
of the `service_manager::Service` interface which lives on the IO thread. This
implementation is shared, and is a detail of `content::ServiceManagerConnection`
which you will find in `//content/public/common`. This implementation receives
the `OnStart()` and `OnBindInterface()` calls from the service manager.
The rest of this document talks about things you might like to do and how to
accomplish them.
### Expose Mojo interfaces from one of the existing content-provided services.
To expose interfaces at the service-level from one of the existing content-
provided services, you will need to add a `content::ConnectionFilter` to the
`content::ServiceManagerConnection` in the relevant process. See
`//content/public/common/connection_filter.h`. You implement this interface to
handle `OnBindInterface()` requests on the IO thread. You can construct a
`service_manager::BinderRegistry` on any other thread and move it to the IO
thread using `//content/public/common/connection_filter_impl.h`. When you add
bind callbacks to the binder registry you can specify what task runner you
would like incoming interface requests to be bound on.
### Expose Mojo interfaces at the frame level between browser & renderer.
You can add bind callbacks to the `service_manager::InterfaceRegistry` owned by
the `RenderFrame` and the `RenderFrameHost`. See the various content client
interfaces also for signals to embedders allowing them to add additional
interfaces.
### Expose a named service from an existing process.
If you want to expose a named service (i.e. a service other than the ones
provided by content) from a process provided by content, you can "embed" a
service in one of the content-provided services. You do this by calling
`AddEmbeddedService()` on `ServiceManagerConnection`.

@ -340,7 +340,20 @@ used when committed.
install Chromium OS on VMWare.
* [User Data Directory](user_data_dir.md) - How the user data and cache
directories are determined on all platforms.
* [Mojo](../mojo/README.md) - IPC mechanism used by services.
### Mojo &amp; Services
* [Intro to Mojo &amp; Services](mojo_and_services.md) - Quick introduction
to Mojo and services in Chromium, with examples
* [Mojo API Reference](/mojo/README.md) - Detailed reference documentation for
all things Mojo
* [The Service Manager &amp; Services](/services/service_manager/README.md) -
Services system overview, API references, example services
* [Service Development Guidelines](/services/README.md) - Guidelines for
service development in the Chromium tree
* [Servicifying Chromium Features](servicification.md) - General advice for
integrating new and existing subsystems into Chromium as services
* [Converting Legacy IPC to Mojo](mojo_ipc_conversion.md) - Tips and common
patterns for practical IPC conversion work
### Probably Obsolete
* [TPM Quick Reference](tpm_quick_ref.md) - Trusted Platform Module notes.

Binary file not shown.

After

(image error) Size: 21 KiB

Binary file not shown.

After

(image error) Size: 4.9 KiB

BIN
docs/images/mojo_pipe.png Normal file

Binary file not shown.

After

(image error) Size: 4.7 KiB

BIN
docs/images/mojo_stack.png Normal file

Binary file not shown.

After

(image error) Size: 18 KiB

Binary file not shown.

After

(image error) Size: 23 KiB

Binary file not shown.

After

(image error) Size: 28 KiB

855
docs/mojo_and_services.md Normal file

@ -0,0 +1,855 @@
# Intro to Mojo &amp; Services
[TOC]
## Overview
This document contains the minimum amount of information needed for a developer
to start using Mojo effectively in Chromium, with example Mojo interface usage,
service definition and hookup, and a brief overview of the Content layer's core
services.
See other [Mojo &amp; Services](/docs/README.md#Mojo-Services) documentation
for introductory guides, API references, and more.
## Mojo Terminology
A **message pipe** is a pair of **endpoints**. Each endpoint has a queue of
incoming messages, and writing a message at one endpoint effectively enqueues
that message on the other (**peer**) endpoint. Message pipes are thus
bidirectional.
A **mojom** file describes **interfaces**, which are strongly-typed collections
of **messages**. Each interface message is roughly analogous to a single proto
message, for developers who are familiar with Google protobufs.
Given a mojom interface and a message pipe, one of the endpoints
can be designated as an **InterfacePtr** and is used to *send* messages described by
the interface. The other endpoint can be designated as a **Binding** and is used
to *receive* interface messages.
*** aside
NOTE: The above generalization is a bit oversimplified. Remember that the
message pipe is still bidirectional, and it's possible for a mojom message to
expect a reply. Replies are sent from the Binding endpoint and received by the
InterfacePtr endpoint.
***
The Binding endpoint must be associated with (*i.e.* **bound** to) an
**implementation** of its mojom interface in order to process received messages.
A received message is dispatched as a scheduled task invoking the corresponding
interface method on the implementation object.
Another way to think about all this is simply that **an InterfacePtr makes
calls on a remote implementation of its interface associated with a
corresponding remote Binding.**
## Example: Defining a New Frame Interface
Let's apply this to Chrome. Suppose we want to send a "Ping" message from a
render frame to its corresponding `RenderFrameHostImpl` instance in the browser
process. We need to define a nice mojom interface for this purpose, create a
pipe to use that interface, and then plumb one end of the pipe to the right
place so the sent messages can be received and processed there. This section
goes through that process in detail.
### Defining the Interface
The first step involves creating a new `.mojom` file with an interface
definition, like so:
``` cpp
// src/example/public/mojom/ping_responder.mojom
module example.mojom;
interface PingResponder {
// Receives a "Ping" and responds with a random integer.
Ping() => (int random);
};
```
This should have a corresponding build rule to generate C++ bindings for the
definition here:
``` python
# src/example/public/mojom/BUILD.gn
import "mojo/public/tools/bindings/mojom.gni"
mojom("mojom") {
sources = [ "ping_responder.mojom" ]
}
```
### Creating the Pipe
Now let's create a message pipe to use this interface.
*** aside
As a general rule and as a matter of convenience when
using Mojo, the *client* of an interface (*i.e.* the InterfacePtr side) is
typically the party who creates a new pipe. This is convenient because the
InterfacePtr may be used to start sending messages immediately without waiting
for the InterfaceRequest endpoint to be transferred or bound anywhere.
***
This code would be placed somewhere in the renderer:
```cpp
example::mojom::PingResponderPtr ping_responder;
example::mojom::PingResponderRequest request =
mojo::MakeRequest(&ping_responder);
```
In this example, ```ping_responder``` is the InterfacePtr, and ```request```
is an InterfaceRequest, which is a Binding precursor that will eventually
be turned into a Binding. `mojo::MakeRequest` is the most common way to create
a message pipe: it yields both endpoints as strongly-typed objects, with the
`InterfacePtr` as an output argument and the `InterfaceRequest` as the return
value.
*** aside
NOTE: Every mojom interface `T` generates corresponding C++ type aliases
`TPtr = InterfacePtr<T>` and `TRequest = InterfaceRequest<T>`. Chromium code
almost exclusively uses these aliases instead of writing out the more verbose
templated name.
Also note that an InterfaceRequest doesn't actually **do** anything. It is an
inert holder of a single message pipe endpoint. It exists only to make its
endpoint more strongly-typed at compile-time, indicating that the endpoint
expects to be bound by a Binding of the same interface type.
***
### Sending a Message
Finally, we can call the `Ping()` method on our InterfacePtr to send a message:
```cpp
ping_responder->Ping(base::BindOnce(&OnPong));
```
*** aside
**IMPORTANT:** If we want to receive the the response, we must keep the
`ping_responder` object alive until `OnPong` is invoked. After all,
`ping_responder` *owns* its message pipe endpoint. If it's destroyed then so is
the endpoint, and there will be nothing to receive the response message.
***
We're almost done! Of course, if everything were this easy, this document
wouldn't need to exist. We've taken the hard problem of sending a message from
a renderer process to the browser process, and transformed it into a problem
where we just need to take the `request` object from above and pass it to the
browser process somehow where it can be turned into a Binding that dispatches
its received messages.
### Sending an InterfaceRequest to the Browser
It's worth noting that InterfaceRequests (and message pipe endpoints in general)
are just another type of object that can be freely sent over mojom messages.
The most common way to get an InterfaceRequest somewhere is to pass it as a
method argument on some other already-connected interface.
One such interface which we always have connected between a renderer's
`RenderFrameImpl` and its corresponding `RenderFrameHostImpl` in the browser
is
[`DocumentInterfaceBroker`](https://cs.chromium.org/chromium/src/third_party/blink/public/mojom/frame/document_interface_broker.mojom).
We can update this definition to add support for our new PingResponder
interface:
``` cpp
interface DocumentInterfaceBroker {
...
GetPingResponder(PingResponder& responder);
}
```
The `&` syntax is not a reference! In mojom it denotes an InterfaceRequest.
Specifically in this case, the `GetPingResponder` takes a single
`PingResponderRequest` argument. If the `&` were omitted, this would instead
take a `PingResponderPtr`.
Now the renderer can call this method with the `request` object it created
earlier via `mojo::MakeRequest`:
``` cpp
RenderFrame* my_frame = GetMyFrame();
my_frame->GetDocumentInterfaceBroker()->GetPingResponder(std::move(request));
```
This will transfer the PingResponderRequest endpoint to the browser process
where it will be received by the corresponding `DocumentInterfaceBroker`
implementation. More on that below.
### Implementing the Interface
Finally, we need a browser-side implementation of our `PingResponder` interface
as well as an implementation of the new
`DocumentInterfaceBroker.GetPingResponder` message. Let's implement
`PingResponder` first:
```cpp
#include "example/public/mojom/ping_responder.mojom.h"
class PingResponderImpl : example::mojom::PingResponder {
public:
explicit PingResponderImpl(example::mojom::PingResponderRequest request)
: binding_(this, std::move(request)) {}
// example::mojom::PingResponder:
void Ping(PingCallback callback) override {
// Respond with a random 4, chosen by fair dice roll.
std::move(callback).Run(4);
}
private:
mojo::Binding<example::mojom::PingResponder> binding_;
DISALLOW_COPY_AND_ASSIGN(PingResponderImpl);
};
```
And conveniently `RenderFrameHostImpl` implements `DocumentInterfaceBroker`, and
any calls made on the object returned by
`RenderFrameImpl::GetDocumentInterfaceBroker()' will be routed directly to the
`RenderFrameHostImpl`. So the only thing left to do is update
`RenderFrameHostImpl` to implement `GetPingResponder`. If you forget to do this
the compiler will complain anyway, because generated mojom interface methods are
pure virtual methods in C++.
``` cpp
// render_frame_host_impl.h
class RenderFrameHostImpl
...
void GetPingResponder(example::mojom::PingResponderRequest request) override;
...
private:
...
std::unique_ptr<PingResponderImpl> ping_responder_;
...
};
// render_frame_host_impl.cc
void RenderFrameHostImpl::GetPingResponder(
example::mojom::PingResponderRequest request) {
ping_responder_ = std::make_unique<PingResponderImpl>(std::move(request));
}
```
And we're done. This setup is sufficient to plumb a new interface connection
between a renderer frame and its browser-side host object!
Assuming we kept our `ping_responder` object alive in the renderer long enough,
we would eventually see its `OnPong` callback invoked with the totally random
value of `4`, as defined by the browser-side implementation above.
## Services Overview &amp; Terminology
The previous section only scratches the surface of how Mojo IPC is used in
Chromium. While renderer-to-browser messaging is simple and possibly the most
prevalent usage by sheer code volume, we are incrementally decomposing the
codebase into a set of services with a bit more granularity than the traditional
Content browser/renderer/gpu/utility process split.
A **service** is a self-contained library of code which implements one or more
related features or behaviors and whose interaction with outside code is done
*exclusively* through Mojo interface connections facilitated by the **Service
Manager.**
The **Service Manager** is a component which can run in a dedicated process
or embedded within another process. Only one Service Manager exists globally
across the system, and in Chromium the browser process runs an embedded Service
Manager instance immediately on startup. The Service Manager spawns
**service instances** on-demand, and it routes each interface request from a
service instance to some destination instance of the Service Manager's choosing.
Each service instance implements the
[**`Service`**](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/service.h)
interface to receive incoming interface requests brokered by the Service
Manager, and each service instance has a
[**`Connector`**](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/connector.h)
it can use to issue interface requests to other services via the
Service Manager.
Every service has a **manifest** which declares some static metadata about the
service. This metadata is used by the Service Manager for various purposes,
including as a declaration of what interfaces are exposed to other services in
the system. This eases the security review process.
Inside its manifest every service declares its **service name**, used to
identify instances of the service in the most general sense. Names are free-form
and usually short strings which must be globally unique. Some services defined
in Chromium today include `"device"`, `"identity"`, and `"network"` services.
For more complete and in-depth coverage of the concepts covered here and other
related APIs, see the
[Service Manager documentation](/services/service_manager/README.md).
## Example: Building a Simple Out-of-Process Service
There are multiple steps required to get a new service up and running in
Chromium. You must:
- Define the `Service` implementation
- Define the service's manifest
- Tell Chromium's Service Manager about the manifest
- Tell Chromium how to instantiate the `Service` implementation when it's needed
This section walks through these steps with some brief explanations. For more
thorough documentation of the concepts and APIs used herein, see the
[Service Manager](/services/service_manager/README.md) and
[Mojo](/mojo/README.md) documentation.
### Defining the Service
Typically service definitions are placed in a `services` directory, either at
the top level of the tree or within some subdirectory. In this example, we'll
define a new service for use by Chrome specifically, so we'll define it within
`//chrome/services`.
We can create the following files. First some mojoms:
``` cpp
// src/chrome/services/math/public/mojom/constants.mojom
module math.mojom;
// These are not used by the implementation directly, but will be used in
// following sections.
const string kServiceName = "math";
const string kArithmeticCapability = "arithmetic";
```
``` cpp
// src/chrome/services/math/public/mojom/divider.mojom
module math.mojom;
interface Divider {
Divide(int32 dividend, int32 divisor) => (int32 quotient);
};
```
``` python
# src/chrome/services/math/public/mojom/BUILD.gn
import "mojo/public/tools/bindings/mojom.gni"
mojom("mojom") {
sources = [
"constants.mojom",
"divider.mojom",
]
}
```
Then the actual `Service` implementation:
``` cpp
// src/chrome/services/math/math_service.h
#include "services/service_manager/public/cpp/service.h"
#include "base/macros.h"
#include "chrome/services/math/public/mojom/divider.mojom.h"
namespace math {
class MathService : public service_manager::Service,
public mojom::Divider {
public:
explicit MathService(service_manager::mojom::ServiceRequest request);
~MathService() override;
private:
// service_manager::Service:
void OnBindInterface(const service_manager::BindSourceInfo& source,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) override;
// mojom::Divider:
void Divide(int32_t dividend,
int32_t divisor,
DivideCallback callback) override;
service_manager::ServiceBinding service_binding_;
// You could also use a Binding. We use BindingSet to conveniently allow
// multiple clients to bind to the same instance of this class. See Mojo
// C++ Bindings documentation for more information.
mojo::BindingSet<mojom::Divider> divider_bindings_;
DISALLOW_COPY_AND_ASSIGN(MathService);
};
} // namespace math
```
``` cpp
// src/chrome/services/math/math_service.cc
#include "chrome/services/math/math_service.h"
namespace math {
MathService::MathService(service_manager::ServiceRequest request)
: service_binding_(this, std::move(request)) {}
MathService::~MathService() = default;
void MathService::OnBindInterface(
const service_manager::BindSourceInfo& source,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
// Note that services typically use a service_manager::BinderRegistry if they
// plan on handling many different interface request types.
if (interface_name == mojom::Divider::Name_) {
divider_bindings_.AddBinding(
this, mojom::DividerRequest(std::move(interface_pipe)));
}
}
void MathService::Divide(int32_t dividend,
int32_t divisor,
DivideCallback callback) {
// Respond with the quotient!
callback.Run(dividend / divisor);
}
} // namespace math
```
``` python
# src/chrome/services/math/BUILD.gn
source_set("math") {
sources = [
"math.cc",
"math.h",
]
deps = [
"//base",
"//chrome/services/math/public/mojom",
"//services/service_manager/public/cpp",
]
}
```
Now we have a fully defined `math` service implementation, including a nice
little `Divider` interface for clients to play with. Next we need to define the
service's manifest to declare how the service can be used.
### Defining the Manifest
Manifests are defined as
[`Manifest`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/manifest.h)
objects, typically built using a
[`ManifestBuilder`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/manifest_builder.h). As a general rule, services should define their manifest
in a dedicated `source_set` or `component` target under their `public/cpp`
subdirectory (typically referred to as the service's **C++ client library**).
We can create the following files for this purpose:
``` cpp
// src/chrome/services/math/public/cpp/manifest.h
#include "services/service_manager/public/cpp/manifest.h"
namespace math {
const service_manager::Manifest& GetManifest();
} // namespace math
```
``` cpp
// src/chrome/services/math/public/cpp/manifest.cc
#include "chrome/services/math/public/cpp/manifest.h"
#include "base/no_destructor.h"
#include "chrome/services/math/public/mojom/constants.mojom.h"
#include "chrome/services/math/public/mojom/divider.mojom.h"
#include "services/service_manager/public/cpp/manifest_builder.h"
namespace math {
const service_manager::Manifest& GetManifest() {
static base::NoDestructor<service_manager::Manifest> manifest{
service_manager::ManifestBuilder()
.WithServiceName(mojom::kServiceName)
.ExposeCapability(
mojom::kArithmeticCapability,
service_manager::Manifest::InterfaceList<mojom::Divider>())
.Build()};
return *manifest
}
} // namespace math
```
We also need to define a build target for our manifest sources:
``` python
# src/chrome/services/math/public/cpp/BUILD.gn
source_set("manifest") {
sources = [
"manifest.cc",
"manifest.h",
]
deps = [
"//base",
"//chrome/services/math/public/mojom",
"//services/service_manager/public/cpp",
]
}
```
The above `Manifest` definition declares that the service is named `math` and
that it **exposes** a single **capability** named `arithmetic` which allows
access to the `Divider` interface.
Another service may **require** this capability from its own manifest in order
for the Service Manager to grant it access to a `Divider`. We'll see this a
few sections below. First, let's get the manifest and service implementation
registered with Chromium's Service Manager.
### Registering the Manifest
For the most common out-of-process service cases, we register service manifests
by **packaging** them in Chrome. This can be done by augmenting the value
returned by
[`GetChromePackagedServiceManifests`](https://cs.chromium.org/chromium/src/chrome/app/chrome_packaged_service_manifests.cc?rcl=af43cabf3c01e28be437becb972a7eae44fd54e8&l=133).
We can add our manifest there:
``` cpp
// Deep within src/chrome/app/chrome_packaged_service_manifests.cc...
const std::vector<service_manager::Manifest>
GetChromePackagedServiceManifests() {
...
math::GetManifest(),
...
```
And don't forget to add a GN dependency from
`//chrome/app:packaged_service_manifests` onto
`//chrome/services/math/public/cpp:manifest`!
We're almost done with service setup. The last step is to teach Chromium (and
thus the Service Manager) how to launch an instance of our beautiful `math`
service.
### Hooking Up the Service Implementation
There are two parts to this for an out-of-process Chrome service.
First, we need
to inform the embedded Service Manager that this service is an out-of-process
service. The goofiness of this part is a product of some legacy issues and it
should be eliminated soon, but for now it just means teaching the Service
Manager how to *label* the process it creates for this service (e.g. how the process will
appear in the system task manager). We modify
[`ChromeContentBrowserClient::RegisterOutOfProcessServices`](https://cs.chromium.org/chromium/src/chrome/browser/chrome_content_browser_client.cc?rcl=960886a7febcc2acccea7f797d3d5e03a344a12c&l=3766)
for this:
``` cpp
void ChromeContentBrowserClient::RegisterOutOfProcessServices(
OutOfProcessServicesMap* services) {
...
(*services)[math::mojom::kServiceName] =
base::BindRepeating([]() -> base::string16 {
return "Math Service";
});
...
}
```
And finally, since nearly all out-of-process services run in a "utility" process
today, we need to add a dependency on our actual `Service` implementation to
Chrome's service spawning code within the utility process.
For this step we just modify
[`ChromeContentUtilityClient::MaybeCreateMainThreadService`](https://cs.chromium.org/chromium/src/chrome/utility/chrome_content_utility_client.cc?rcl=7226adebd6e8d077d673a82acf1aab0790627178&l=261)
by adding a block of code as follows:
``` cpp
void ChromeContentUtilityClient::MaybeCreateMainThreadService(
const std::string& service_name,
service_manager::mojom::ServiceRequest request) {
...
if (service_name == math::mojom::kServiceName)
return std::make_unique<math::MathService>(std::move(request));
...
}
```
And we're done!
As one nice follow-up step, let's use our math service from the browser.
### Using the Service
We can grant the browser process access to our `Divider` interface by
**requiring** the `math` service's `arithmetic` capability within the
`content_browser` service manifest.
*** aside
NOTE: See the following section for an elaboration on what `content_browser` is.
For the sake of this example, it's magic.
***
For Chrome-specific features such as our glorious new `math` service, we can
amend the `content_browser` manifest by modifying
[GetChromeContentBrowserOverlayManifest](https://cs.chromium.org/chromium/src/chrome/app/chrome_content_browser_overlay_manifest.cc?rcl=38db90321e8e3627b2f3165cdb051fa8d668af48&l=100)
as follows:
``` cpp
// src/chrome/app/chrome_content_browser_overlay_manifest.cc
...
const service_manager::Manifest& GetChromeContentBrowserOverlayManifest() {
...
.RequireCapability(math::mojom::kServiceName,
math::mojom::kArithmeticCapability)
...
}
```
Finally, we can use the global `content_browser` instance's `Connector` to send
an interface request to our service. This is accessible from the main thread of
the browser process. Somewhere in `src/chrome/browser`, we can write:
``` cpp
// This gives us the global content_browser's Connector
service_manager::Connector* connector =
content::ServiceManagerConnection::GetForProcess()->GetConnector();
// Recall from the earlier Mojo section that mojo::MakeRequest creates a new
// message pipe for our interface. Connector passes the request endpoint to
// the Service Manager along with the name of our target service, "math".
math::mojom::DividerPtr divider;
connector->BindInterface(math::mojom::kServiceName,
mojo::MakeRequest(&divider));
// As a client, we do not have to wait for any acknowledgement or confirmation
// of a connection. We can start queueing messages immediately and they will be
// delivered as soon as the service is up and running.
divider->Divide(
42, 6, base::BindOnce([](int32_t quotient) { LOG(INFO) << quotient; }));
```
This should successfully spawn a new process to run the `math` service if it's
not already running, then ask it to do a division, and ultimately log the result
after it's sent back to the browser process.
Finally it's worth reiterating that every service instance in the system has
its own `Connector` and there's no reason we have to limit ourselves to
`content_browser` as the client, as long as the appropriate manifest declares
that it requires our `arithmetic` capability.
If we did not update the `content_browser` manifest overlay as we did in this
example, the `Divide` call would never reach the `math` service (in fact the
service wouldn't even be started) and instead we'd get an error message (or in
developer builds, an assertion failure) informing us that the Service Manager
blocked the `BindInterface` call.
## Content-Layer Services Overview
Apart from very early initialization steps in the browser process, every bit of
logic in Chromium today is effectively running as part of one service instance
or another.
Although we continue to migrate parts of the browser's privileged
functionality to more granular services defined below the Content layer, the
main services defined in Chromium today continue to model the Content layer's
classical multiprocess architecture which defines a handful of
**process types**: browser, renderer, gpu, utility, and plugin processes. For
each of these process types, we now define corresponding services.
Manifest definitions for all of the following services can be found in
`//content/public/app`.
### The Browser Service
`content_browser` is defined to encapsulate general-purpose browser process
code. There are multiple instances of this service, all running within the
singular browser process. There is one shared global instance as well an
additional instance for each `BrowserContext` (*i.e.* per Chrome profile).
The global instance exists primarily so that arbitrary browser process code can
reach various system services conveniently via a global `Connector` instance
on the main thread.
Each instance associated with a `BrowserContext` is placed in an isolated
instance group specific to that `BrowserContext`. This limits the service
instances with which its `Connector` can make contact. These instances are
used primarily to facilitate the spawning of other isolated per-profile service
instances, such as renderers and plugins.
### The Renderer Service
A `content_renderer` instance is spawned in its own sandboxed process for every
site-isolated instance of Blink we require. Instances are placed in the same
instance group as the renderer's corresponding `BrowserContext`, *i.e.* the
profile which navigated to the site being rendered.
Most interfaces used by `content_renderer` are not brokered through the Service
Manager but instead are brokered through dedicated interfaces implemented by
`content_browser`, with which each renderer maintains persistent connections.
### The GPU Service
Only a single instance of `content_gpu` exists at a time and it always runs in
its own isolated, sandboxed process. This service hosts the code in content/gpu
and whatever else Content's embedder adds to that for GPU support.
### The Plugin Service
`content_plugin` hosts a plugin in an isolated process. Similarly to
`content_renderer` instances, each instance of `content_plugin` belongs to
an instance group associated with a specific `BrowserContext`, and in general
plugins get most of their functionality by talking directly to `content_browser`
rather than brokering interface requests through the Service Manager.
### The Utility Service
`content_utility` exists only nominally today, as there is no remaining API
surface within Content which would allow a caller to explicitly create an
instance of it. Instead, this service is used exclusively to bootstrap new
isolated processes in which other services will run.
## Exposing Interfaces Between Content Processes
Apart from the standard Service Manager APIs, the Content layer defines a number
of additional concepts for Content and its embedder to expose interfaces
specifically between Content processes in various contexts.
### Exposing Browser Interfaces to Renderer Documents and Workers
Documents and workers are somewhat of a special case since interface access
decisions often require browser-centric state that the Service Manager cannot
know about, such as details of the current `BrowserContext`, the origin of the
renderered content, installed extensions in the renderer, *etc.* For this
reason, interface brokering decisions are increasingly being made by the
browser.
There are two ways this is done: the Deprecated way and the New way.
#### The Deprecated Way: InterfaceProvider
This is built on the concept of **interface filters** and the
**`InterfaceProvider`** interface. It is **deprecated** and new features should
use [The New Way](#The-New-Way_Interface-Brokers) instead. This section only
briefly covers practical usage in Chromium.
The `content_browser` manifest exposes capabilities on a few named interface
filters, the main one being `"navigation:frame"`. There are others scoped to
different worker contexts, *e.g.* `"navigation:service_worker"`.
`RenderProcessHostImpl` or `RenderFrameHostImpl` sets up an `InterfaceProvider`
for each known execution context in the corresponding renderer, filtered through
the Service Manager according to one of the named filters.
The practical result of all this means the interface must be listed in the
`content_browser` manifest under the
`ExposeInterfaceFilterCapability_Deprecated("navigation:frame", "renderer", ...)`
entry, and a corresponding interface request handler must be registered with the
host's `registry_` in
[`RenderFrameHostImpl::RegisterMojoInterfaces`](https://cs.chromium.org/chromium/src/content/browser/frame_host/render_frame_host_impl.cc?rcl=0a23c78c57ecb2405837155aa0a0def7b5ba9c22&l=3971)
Similarly for worker contexts, an interface must be exposed by the `"renderer"`
capability on the corresponding interface filter
(*e.g.*, `"navigation:shared_worker"`) and a request handler must be registered
within
[`RendererInterfaceBinders::InitializeParameterizedBinderRegistry`](https://cs.chromium.org/chromium/src/content/browser/renderer_interface_binders.cc?rcl=0a23c78c57ecb2405837155aa0a0def7b5ba9c22&l=116).
The best way to understand all of this after reading this section is to look at
the linked code above and examine a few examples. They are fairly repetitive.
For additional convenience, here is also a link to the `content_browser`
[manifest](https://cs.chromium.org/chromium/src/content/public/app/content_browser_manifest.cc).
#### The New Way: Interface Brokers
*** aside
In classic Google tradition, the New Way is not entirely ready yet. As of this
writing, worker-scoped interfaces must still use the Old Way described above.
***
Rather than the confusing spaghetti of interface filter logic, we now define an
explicit mojom interface with a persistent connection between a renderer's
frame object and the corresponding `RenderFrameHostImpl` in the browser process.
This interface is called
[`DocumentInterfaceBroker`](https://cs.chromium.org/chromium/src/third_party/blink/public/mojom/frame/document_interface_broker.mojom?rcl=ea6921f717f21e9a72d321a15c4bf50d47d10310&l=11)
and is fairly easy to work with: you simply add a new factory method to the
interface definition:
``` cpp
interface DocumentInterfaceBroker {
...
GetGoatTeleporter(magic.mojom.GoatTeleporter& request);
};
```
and implement this new method on `RenderFrameHostImpl`, which is an
implementation (**the** production implementation) of
`DocumentInterfaceBroker`:
``` cpp
void RenderFrameHostImpl::GetGoatTeleporter(
magic::mojom::GoatTeleporterRequest request) {
goat_teleporter_binding_.Bind(std::move(request));
}
```
### Exposing Browser Interfaces to Render Processes
Sometimes (albeit rarely) it's useful to expose a browser interface directly to
a renderer process. This can be done as for any other interface exposed between
two services. In this specific instance, the `content_browser` manifest exposes
a capability named `"renderer"` which `content_renderer` requires. Any interface
listed as part of that capability can be accessed by a `content_renderer`
instance by using its own `Connector`. See below.
### Exposing Browser Interfaces to Content Child Processes
All Content child process types (renderer, GPU, and plugin) share a common API
to interface with the Service Manager. Their Service Manager connection is
initialized and maintained by `ChildThreadImpl` on process startup, and from
the main thread, you can access the process's `Connector` as follows:
``` cpp
auto* connector = content::ChildThread::Get()->GetConnector();
// For example...
connector->BindInterface(content::mojom::kBrowserServiceName,
std::move(some_request));
```
### Exposing Content Child Process Interfaces to the Browser
Content child processes may also expose interfaces to the browser, though this
is much less common and requires a fair bit of caution since the browser must be
careful to only call `Connector.BindInterface` in these cases with an exact
`service_manager::Identity` to avoid unexpected behavior.
Every child process provides a subclass of ChildThreadImpl, and this can be used
to install a new `ConnectionFilter` on the process's Service Manager connection
before starting to accept requests.
This behavior should really be considered deprecated, but for posterity, here is
how the GPU process does it:
1. [Disable Service Manager connection auto-start](https://cs.chromium.org/chromium/src/content/gpu/gpu_child_thread.cc?rcl=6b85a56334c0cd64b0e657934060de716714ca64&l=62)
2. [Register a new ConnectionFilter impl to handle certain interface requests](https://cs.chromium.org/chromium/src/content/gpu/gpu_child_thread.cc?rcl=6b85a56334c0cd64b0e657934060de716714ca64&l=255)
3. [Start the Service Manager connection manually](https://cs.chromium.org/chromium/src/content/gpu/gpu_child_thread.cc?rcl=6b85a56334c0cd64b0e657934060de716714ca64&l=257)
It's much more common instead for there to be some primordial interface
connection established by the child process which can then be used to facilitate
push communications from the browser, so please consider not duplicating this
behavior.
## Additional Support
If this document was not helpful in some way, please post a message to your
friendly
[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
or
[services-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev)
mailing list.

@ -1,157 +0,0 @@
# Mojo For Chromium Developers
## Overview
This document contains the minimum amount of information needed for a developer
to start using Mojo in Chromium. For more detailed documentation on the C++
bindings, see [this link](/mojo/public/cpp/bindings/README.md).
## Terminology
A **message pipe** is a pair of **endpoints**. Each endpoint has a queue of
incoming messages, and writing a message to one endpoint effectively enqueues
that message on the other endpoint. Message pipes are thus bidirectional.
A **mojom** file describes **interfaces** which describe strongly typed message
structures, similar to proto files.
Given a **mojom interface** and a **message pipe**, the two **endpoints**
can be given the labels **InterfacePtr** and **Binding**. This now describes a
strongly typed **message pipe** which transports messages described by the
**mojom interface**. The **InterfacePtr** is the **endpoint** which "sends"
messages, and the **Binding** "receives" messages. Note that the **message
pipe** itself is still bidirectional, and it's possible for a message to have a
response callback, which the **InterfacePtr** would receive.
Another way to think of this is that an **InterfacePtr** is capable of making
remote calls on an implementation of the mojom interface associated with the
**Binding**.
The **Binding** itself is just glue that wires the endpoint's message queue up
to some implementation of the interface provided by the developer.
## Example
Let's apply this to Chrome. Let's say we want to send a "Ping" message from a
Browser to a Renderer. First we need to define the mojom interface.
```
module example.mojom;
interface PingResponder {
// Receives a "Ping" and responds with a random integer.
Ping() => (int random);
};
```
Now let's make a MessagePipe.
```cpp
example::mojom::PingResponderPtr ping_responder;
example::mojom::PingResponderRequest request = mojo::MakeRequest(&ping_responder);
```
In this example, ```ping_responder``` is the **InterfacePtr**, and ```request```
is an **InterfaceRequest**, which is a **Binding** precursor that will shortly
be turned into a **Binding**. Now we can send our Ping message.
```cpp
auto callback = base::Bind(&OnPong);
ping_responder->Ping(callback);
```
Important aside: If we want to receive the the response, we must keep the object
```ping_responder``` alive. After all, it's just a wrapper around a **Message
Pipe endpoint**, if it were to go away, there'd be nothing left to receive the
response.
We're done! Of course, if everything were this easy, this document wouldn't need
to exist. We've taken the hard problem of sending a message from the Browser to
a Renderer, and transformed it into a problem where we just need to take the
```request``` object, pass it to the Renderer, turn it into a **Binding**, and
implement the interface.
In Chrome, processes host services, and the services themselves are connected to
a Service Manager via **message pipes**. It's easy to pass ```request``` to the
appropriate Renderer using the Service Manager, but this requires explicitly
declaring our intentions via manifest files. For this example, we'll use the
content_browser service [manifest
file](https://cs.chromium.org/chromium/src/content/public/app/mojo/content_browser_manifest.json)
and the content_renderer service [manifest
file](https://cs.chromium.org/chromium/src/content/public/app/mojo/content_renderer_manifest.json).
```js
content_renderer_manifest.json:
...
"interface_provider_specs": {
"service_manager:connector": {
"provides": {
"cool_ping_feature": [
"example::mojom::PingResponder"
]
},
},
...
```
```js
content_browser_manifest.json:
...
"interface_provider_specs": {
"service_manager:connector": {
"requires": {
"content_renderer": [ "cool_ping_feature" ],
},
},
},
...
```
These changes indicate that the content_renderer service provides the interface
PingResponder, under the **capability** named "cool_ping_feature". And the
content_browser services intends to use this feature.
```content::BindInterface``` is a helper function that takes ```request``` and
sends it to the renderer process via the Service Manager.
```cpp
content::RenderProcessHost* host = GetRenderProcessHost();
content::BindInterface(host, std::move(request));
```
Putting this all together for the browser process:
```cpp
example::mojom::PingResponderPtr ping_responder; // Make sure to keep this alive! Otherwise the response will never be received.
example::mojom::PingResponderRequest request = mojo::MakeRequest(&ping_responder);
ping_responder->Ping(base::BindOnce(&OnPong));
content::RenderProcessHost* host = GetRenderProcessHost();
content::BindInterface(host, std::move(request));
```
In the Renderer process, we need to write an implementation for PingResponder,
and ensure that a **Binding** is created using the transported ```request```. In a
standalone Mojo service, this would require us to implement
```service_manager::Service::OnBindInterface()```. In Chrome, this is abstracted
behind ```content::ConnectionFilters``` and
```service_manager::BinderRegistry```. This is typically done in
```RenderThreadImpl::Init```.
```cpp
class PingResponderImpl : mojom::PingResponder {
void BindToInterface(example::mojom::PingResponderRequest request) {
binding_.reset(
new mojo::Binding<mojom::MemlogClient>(this, std::move(request)));
}
void Ping(PingCallback callback) { std::move(callback).Run(4); }
std::unique_ptr<mojo::Binding<mojom::PingResponder>> binding_;
};
RenderThreadImpl::Init() {
...
this->ping_responder = std::make_unique<PingResponderImpl>();
auto registry = base::MakeUnique<service_manager::BinderRegistry>();
// This makes the assumption that |this->ping_responder| will outlive |registry|.
registry->AddInterface(base::Bind(&PingResponderImpl::BindToInterface), base::Unretained(this->ping_responder.get()));
GetServiceManagerConnection()->AddConnectionFilter(
base::MakeUnique<SimpleConnectionFilter>(std::move(registry)));
...
```

374
docs/mojo_ipc_conversion.md Normal file

@ -0,0 +1,374 @@
# Converting Legacy IPC to Mojo
[TOC]
## Overview
A number of IPC messages sent (primarily between the browser and renderer
processes) are still defined using Chrome's old IPC system in `//ipc`. This
system uses
[`base::Pickle`](https://cs.chromium.org/chromium/src/base/pickle.h?rcl=8b7842262ee1239b1f3ae20b9c851748ef0b9a8b&l=128)
as the basis for message serialization and is supported by a number if `IPC_*`
preprocessor macros defined in `//ipc` and used around the source tree.
There is an ongoing, distributed effort to get these messages converted to Mojo
interface messages. Messages that still need to be converted are tracked in two
spreadsheets:
- [Chrome IPC to Mojo migration](https://docs.google.com/spreadsheets/d/1pGWX_wxGdjAVtQOmlDDfhuIc3Pbwg9FtvFXAXYu7b7c/edit#gid=0) for non-web platform messages
- [Mojoifying Platform Features](https://docs.google.com/spreadsheets/d/1VIINt17Dg2cJjPpoJ_HY3HI0uLpidql-1u8pBJtpbGk/edit#gid=1603373208) for web platform messages
This document is concerned primarily with rote conversion of legacy IPC messages
to Mojo interface messages. If you are considering more holistic refactoring and
better isolation of an entire subsystem of the browser, you may consider
[servicifying](servicification.md) the feature instead of merely converting its
IPCs.
See other [Mojo &amp; Services](/docs/README.md#Mojo-Services) documentation
for introductory guides, API references, and more.
## Legacy IPC Concepts
Each Content child process has a single **`IPC::Channel`** implementation going
between it and the browser process, and this is used as the sole two-way FIFO
to send legacy IPC messages between the processes.
There are two fundamental types of legacy IPC messages: **control** messages,
defined via `IPC_MESSAGE_CONTROLn` macros (where `n` is some small integer) and
**routed** messages defined via `IPC_MESSAGE_ROUTEDn` macros.
Control messages generally go between a browser-side process host (*e.g.*,
`RenderProcessHost` or `GpuProcessHost`) and the child-side `ChildThreadImpl`
subclass. All of these classes implement `IPC::Sender` and thus have a `Send`
method for sending a control message to their remote counterpart, and they
implement `IPC::Listener` to receive incoming control messages via
`OnMessageReceived`.
Routed messages are relegated to **routes** which have arbitrary meaning
determined by their use within a given process. For example, renderers use
routes to isolate messages scoped to individual render frames, and so such
routed messages will travel between a `RenderFrameHostImpl` and its
corresponding `RenderFrameImpl`, both of which also implement `IPC::Sender` and
`IPC::Listener`.
## Mojo Interfaces as Routes
Routed messages in the old IPC system always carry a **routing ID** to identify
to the receiving endpoint which routed object (*e.g.* which `RenderFrameImpl`
or `RenderViewImpl` or whatever) the message is targeting. Each endpoint is thus
required to do some additional book-keeping to track what each routing ID means.
Mojo interfaces obviate the need for routing IDs, as new "routes" can be
established by simply creating a new interface pipe and passing one endpoint to
something which knows how to bind it.
When thinking about an IPC message conversion to Mojo, it's important to
consider whether the message is a control message or a routed message, as this
determines where you might find an existing Mojo interface to carry your
message, or where you will want to add a new end-to-end Mojo interface for that
purpose. This can mean the difference between a single per-process interface
going between each `RenderProcessHostImpl` and its corresponding
`RenderThreadImpl`, vs a per-frame interface going between each
`RenderFrameHostImpl` and its corresponding `RenderFrameImpl`.
## Ordering Considerations
One **very important** consideration when doing IPC conversions is the relative
ordering of IPC-driven operations. With the old IPC system, because every
message between two processes is globally ordered, it is quite easy for parts
of the system to (intentionally or often unintentionally) rely on strict
ordering guarantees.
For example, imagine a `WebContentsObserver` in the browser processes observes
a frame navigation and immediately sends an IPC message to the frame to
configure some new behavior. The implementation may be inadvertently relying on
this message arriving *before* some other tangentially related message sent to
the same frame shortly after the same navigation event.
Mojo does not (and in fact cannot) make any strict ordering guarantees between
separate message pipes, as message pipes may be freely moved across process
boundaries and thus cannot necessarily share a common FIFO at all times.
If the two messages described above were moved to separate Mojo interfaces on
separate message pipes, renderer behavior could break as the first message may
arrive after the second message.
The best solution to this problem is to rethink the IPC surface and/or
implementation on either side to eliminate ordering dependencies between two
interfaces that otherwise seem to be logically distinct. Failing that, Mojo's
solution to this problem is to support
[**associated interfaces**](/mojo/public/tools/bindings/README.md#Associated-Interfaces).
In a nutshell, these allow multiple distinct interfaces to be multiplexed over
a shared message pipe.
## Channel-Associated Interfaces
The previous section mentions **associated interfaces** as a general-purpose
solution for establishing a mutual FIFO between multiple logical Mojo interfaces
by having them share a single message pipe.
In Chrome, the `IPC::Channel` which carries all legacy IPC messages between
two processes is itself a Mojo message pipe. We provide a mechanism for
associating arbitrary Mojo interfaces with this pipe, which means messages can
be converted to Mojo while preserving strict FIFO with respect to other legacy
IPC messages. Such interfaces are designated in Chrome parlance as
**Channel-associated interfaces**.
*** aside
**NOTE:** Channel-associated interface acquisition is not constrained by the
Service Manager in any way, so security reviewers need to be careful to inspect
new additions and uses of such interfaces.
***
Usage of Channel-associated interfaces should be rare but is considered a
reasonable intermediate solution for incremental IPC conversions where it would
be too risky or noisy to convert a large IPC surface all at once, but it would
also be impossible to split the IPC surface between legacy IPC and a dedicated
Mojo interface pipe without introducing timing bugs.
At this point in Chrome's development, practical usage of Channel-associated
interfaces is restricted to the `IPC::Channel` between the browser process and
a renderer process, as this is the most complex IPC surface with the most
implicit ordering dependencies. A few simple APIs exist to support this.
`RenderProcessHostImpl` owns an `IPC::Channel` to its corresponding
`RenderThreadImpl` in the render process. This object has a
`GetRemoteAssociatedInterfaces` method which can be used to pass arbitrary
associated interface requests:
``` cpp
magic::mojom::GoatTeleporterAssociatedPtr teleporter;
channel_->GetRemoteAssociatedInterfaces()->GetInterface(&teleporter);
// These messages are all guaranteed to arrive in the same order they were sent.
channel_->Send(new FooMsg_SomeLegacyIPC);
teleporter->TeleportAllGoats();
channel_->Send(new FooMsg_AnotherLegacyIPC);
```
Likewise, `ChildThreadImpl` has an `IPC::Channel` that can be used in the same
way to send such messages back to the browser.
To receive and bind incoming Channel-associated interface requests, the above
objects also implement `IPC::Listener::OnAssociatedInterfaceRequest`.
For supplementation of routed messages, both `RenderFrameHostImpl` and
`RenderFrameImpl` define a `GetRemoteAssociatedInterfaces` method which works
like the one on `IPC::Channel`, and both objects also implement
`IPC::Listener::OnAssociatedInterfaceRequest` for processing incoming associated
interface requests specific to their own frame.
There are some example conversion CLs which use Channel-associated interfaces
[here](https://codereview.chromium.org/2381493003) and
[here](https://codereview.chromium.org/2400313002).
## Deciding How to Approach a Conversion
There are a few questions you should ask before embarking upon any IPC message
conversion journey, and there are many potential approaches to consider. The
right one depends on context.
Note that this section assumes the message is traveling between the browser
process and a renderer process. Other cases are rare and developers may wish to
consult
[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
before proceeding with them. Otherwise, apply the following basic algorithm to
decide how to proceed:
- General note: If the message is a reply to some other message (typically these
take a "request ID" argument), see the note about message replies at the
bottom of this section.
- Consider whether or not the message makes sense as part of the IPC surface of
a new or existing service somewhere in `//services` or `//chrome/services`,
*etc.* This is less and less likely to be the case as time goes on, as many
remaining IPC conversions are quite narrowly dealing with specific
browser/renderer details rather than the browser's supporting subsystems. If
defining a new service, you may wish to consult some of the other
[Mojo &amp; Services documentation](/docs/README.md#Mojo-Services) first.
- If the message is an `IPC_MESSAGE_CONTROL` message:
- If there are likely to be strict ordering requirements between this
message and other legacy IPC or Channel-associated interface messages,
consider using a new or existing
[Channel-associated interface](#Channel-Associated-Interfaces) between
`RenderProcessHostImpl` and `RenderThreadImpl`.
- If the message is sent from a renderer to the browser:
- If an existing interface is bound by `RenderProcessHostImpl` and
requested through `RenderThread`'s Connector and seems to be a good
fit for the message, add the equivalent Mojo message to that
interface.
- If no such interface exists, consider adding one for this message and
any related messages.
- If the message is sent from the browser to a renderer:
- If an existing interface is bound by `RenderThreadImpl` and requested
through a `BrowserContext` Connector referencing a specific
`RenderProcessHost` [identity](https://cs.chromium.org/chromium/src/content/public/browser/render_process_host.h?rcl=1497b88b7d6400a2a5cced258df03d53800d7848&l=327),
and the interface seems to be a good fit for the message, add the
equivalent Mojo message to that interface.
- If no such interface exists, consider adding one for this message and
any related messages.
- If the message is an `IPC_MESSAGE_ROUTED` message:
- Determine what the routing endpoints are. If they are
`RenderFrameHostImpl` and `RenderFrameImpl`:
- If there are likely to be strict ordering requirements between this
message and other legacy IPC or Channel-associated interface messages,
consider using a new or existing
[Channel-associated interface](#Channel-Associated-Interfaces) between
`RenderFrameHostImpl` and `RenderFrameImpl`.
- If the message is sent from a renderer to the browser:
- If an existing interface is bound by `RenderFrameHostImpl` and
acquired either via `RenderFrame::GetRemoteInterfaces` or
`RenderFrame::GetDocumentInterfaceBroker` and the interface seems
to be a good fit for this message, add the equivalent Mojo message
to that interface.
- If no such interface exists, consider adding one and exposing it
via a new getter method on `DocumentInterfaceBroker`. See the
[simple example](/docs/mojo_and_services.md#Example_Defining-a-New-Frame-Interface)
earlier in this document.
- If the message is sent from the browser to a renderer, consider
adding a Mojo equivalent to the `content.mojom.Frame` interface
defined
[here](https://cs.chromium.org/chromium/src/content/common/frame.mojom?rcl=138b66744ee9ee853cbb0ae8437b71eaa1fafaa9&l=42).
- If the routing endpoints are **not** frame objects (for example, they may
be `RenderView`/`RenderViewHost` objects), this is a special case which
does not yet have an easy conversion approach readily available. Contact
[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum#!forum/chromium-mojo)
to propose or discuss options.
### Dealing With Replies
If the message is a **reply**, meaning it has a "request ID" which correlates it
to a prior message in the opposite direction, consider converting the
**request** message following the algorithm above. Unlike with legacy IPC, Mojo
messages support replies as a first-class concept. So for example if you have:
``` cpp
IPC_CONTROL_MESSAGE2(FooHostMsg_DoTheThing,
int /* request_id */,
std::string /* name */);
IPC_CONTROL_MESSAGE2(FooMsg_DidTheThing,
int /* request_id */,
bool /* success */);
```
You should consider defining an interface `Foo` which is bound in
`RenderProcessHostImpl` and acquired from `RenderThreadImpl`, with the following
mojom definition:
``` cpp
interface Foo {
DoTheThing(string name) => (bool success);
};
```
## Repurposing `IPC::ParamTraits` and `IPC_STRUCT*` Invocations
Occasionally it is useful to do partial IPC conversions, where you want to
convert a message to a Mojo interface method but you don't want to necessarily
convert every structure passed by the message. In this case, you can leverage
Mojo's
[type-mapping](https://chromium.googlesource.com/chromium/src/+/master/mojo/public/cpp/bindings/README.md#Type-Mapping)
system to repurpose existing `IPC::ParamTraits`.
*** aside
**NOTE**: Although in some cases `IPC::ParamTraits<T>` specializations are
defined manually in library code, the `IPC_STRUCT*` macro helpers also define
`IPC::ParamTraits<T>` specializations under the hood. All advice in this section
pertains to both kinds of definitions.
***
If a mojom struct is declared without a struct body and is tagged with
`[Native]`, and a corresponding typemap is provided for the struct, the emitted
C++ bindings will -- as if by magic -- replace the mojom type with the
typemapped C++ type and will internally use the existing `IPC::ParamTraits<T>`
specialization for that type in order to serialize and deserialize the struct.
For example, given the
[`resource_messages.h`](https://cs.chromium.org/chromium/src/content/common/resource_messages.h?rcl=2e7a430d8d88222c04ab3ffb0a143fa85b3cec5b&l=215) header
which defines an IPC mapping for `content::ResourceRequest`:
``` cpp
IPC_STRUCT_TRAITS_BEGIN(content::ResourceRequest)
IPC_STRUCT_TRAITS_MEMBER(method)
IPC_STRUCT_TRAITS_MEMBER(url)
// ...
IPC_STRUCT_TRAITS_END()
```
and the
[`resource_request.h`](https://cs.chromium.org/chromium/src/content/common/resource_request.h?rcl=dce9e476a525e4ff0304787935dc1a8c38392ac8&l=32) header
which actually defines the `content::ResourceRequest` type:
``` cpp
namespace content {
struct CONTENT_EXPORT ResourceRequest {
// ...
};
} // namespace content
```
we can declare a corresponding "native" mojom struct:
``` cpp
module content.mojom;
[Native]
struct URLRequest;
```
and add a typemap like
[`url_request.typemap`](https://cs.chromium.org/chromium/src/content/common/url_request.typemap?rcl=4b5963fa744a706398f8f06a4cbbf70d7fa3213d)
to define how to map between them:
``` python
mojom = "//content/public/common/url_loader.mojom"
public_headers = [ "//content/common/resource_request.h" ]
traits_headers = [ "//content/common/resource_messages.h" ]
...
type_mappings = [ "content.mojom.URLRequest=content::ResourceRequest" ]
```
Note specifically that public_headers includes the definition of the native C++
type, and traits_headers includes the definition of the legacy IPC traits.
As a result of all this, other mojom files can now reference
`content.mojom.URLRequest` as a type for method parameters and other struct
fields, and the generated C++ bindings will represent those values exclusively
as `content::ResourceRequest` objects.
This same basic approach can be used to leverage existing `IPC_ENUM_TRAITS` for
invocations for `[Native]` mojom enum aliases.
*** aside
**NOTE:** Use of `[Native]` mojom definitions is strictly limited to C++
bindings. If a mojom message depends on such definitions, it cannot be sent or
received by other language bindings. This feature also depends on continued
support for legacy IPC serialization and all uses of it should therefore be
treated as technical debt.
***
## Typemaps For Content and Blink Types
Using typemapping for messages that go between Blink and content browser code
can sometimes be tricky due to things like dependency cycles or confusion over
the correct place for some definition
to live. There are some example CLs provided here, but feel free to also contact
[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
with specific details if you encounter trouble.
[This CL](https://codereview.chromium.org/2363533002) introduces a Mojom
definition and typemap for `ui::WindowOpenDisposition` as a precursor to the
IPC conversion below.
The [follow-up CL](https://codereview.chromium.org/2363573002) uses that
definition along with several other new typemaps (including native typemaps as
described above) to convert the relatively large `ViewHostMsg_CreateWindow`
message to Mojo.
## Additional Support
If this document was not helpful in some way, please post a message to your
friendly
[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
mailing list.

@ -1,102 +1,197 @@
# Servicification Strategies
This document captures strategies, hints, and best practices for solving typical
challenges enountered when converting existing Chromium
code to services. It is assumed that you have already read the high-level
documentation on [what a service is](/services).
If you're looking for Mojo documentation, please see the [general
Mojo documentation](/mojo) and/or the [documentation on converting Chrome IPC to
Mojo](/ipc).
Note that throughout the below document we link to CLs to illustrate the
strategies being made. Over the course of time code tends to shift, so it is
likely that the code on trunk does not exactly match what it was at the time of
the CLs. When necessary, use the CLs as a starting point for examining the
current state of the codebase with respect to these issues (e.g., exactly where
a service is embedded within the content layer).
# Servicifying Chromium Features
[TOC]
## Questions to Answer When Getting Started
## Overview
For the basic nuts and bolts of how to create a new service, see [the
documentation on adding a new service](/services#Adding-a-new-service). This
section gives questions that you should answer in order to shape the design of
your service, as well as hints as to which answers make sense given your
situation.
Much to the dismay of Chromium developers, practicing linguists, and keyboard
operators everywhere, the term **servicificificification** [sic] has been
egregiously smuggled into the Chromium parlance.
### Is your service global or per-BrowserContext?
The Service Manager can either:
Lots of Chromium code is contained in reasonably well-isolated component
libraries with some occasionally fuzzy boundaries and often a surprising number
of gnarly runtime interdependencies among a complex graph of components. Y
implements one of Z's delegate interfaces, while X implements one of Y's
delegate interfaces, and now it's possible for some ridiculous bug to creep in
where W calls into Z at the wrong time and causes a crash in X. Yikes.
- create one service instance per instance group or
- field all connection requests for a given service via the same instance
Servicification embodies the ongoing process of **servicifying** Chromium
features and subsystems, or refactoring these collections of library code into
services with well-defined public API boundaries and very strong runtime
isolation via Mojo interfaces.
Which of these policies the Service Manager employs is determined by the
contents of your service manifest: the former is the default, while the latter
is selected by informing the Service Manager that your service has the
"instance_sharing" option value set to "shared_across_instance_groups"
([example](https://cs.chromium.org/chromium/src/services/device/manifest.json)).
The primary goals are to improve maintainability and extensibility of the system
over time, while also allowing for more flexible runtime configuration. For
example, with the Network Service in place we can now run the entire network
stack either inside or outside of the browser process with the flip of a
command-line switch. Client code using the Network Service stays the same,
independent of that switch.
Service manifests are described in more detail in this
[document](https://chromium.googlesource.com/chromium/src/+/master/services/service_manager/service_manifests.md).
This document focuses on helpful guidelines and patterns for servicifying parts
of Chromium, taking into account some nuances in how Chromium models its core
services as well as how it embeds and configures the Service Manager. Readers
are strongly encouraged to first read some basic
[Service Manager documentation](/services/service_manager/README.md), as it will
likely make the contents of this document easier to digest.
In practice, there is one instance group per-BrowserContext, so the question
becomes: Is your Service a global or keyed by BrowserContext? In considering
this question, there is one obvious hint: If you are converting per-Profile
classes (e.g., KeyedServices), then your service is almost certainly going to
want an instance per BrowserContext. More generally, if you envision needing to
use *any* state related to the profile (e.g., you need to store files in the
user's home directory), then your service should have an instance
per-BrowserContext.
Also see general [Mojo &amp; Services](/docs/README.md#Mojo-Services)
documentation for other introductory guides, API references, *etc.*
Conversely, your service could be a good fit for being global if it is a utility
that is unconcerned with the identity of the requesting client (e.g., the [data
decoder service](/services/data_decoder), which simply decodes untrusted data in
a separate process.
## Setting Up The Service
### Will you embed your service in //content, //chrome, or neither?
There are three big things you must decide when building and hooking up a shiny
new service:
At the start (and potentially even long-term), your service will likely not
actually run in its own process but will rather be embedded in the browser
process. This is especially true in the common case where you are converting
existing browser-process code.
- Where should the service live in the tree?
- Do you need an instance of your service per BrowserContext?
- Can Content depend on your service, or must Content embedders like Chrome do
so independently?
You then have a question: Where should it be embedded? The answer to this
question hinges on the nature and location of the code that you are converting:
This section aims to help you understand and answer those questions.
- //content is the obvious choice if you are converting existing //content code
(e.g., the Device Service). Global services
are embedded by [content::ServiceManagerContext](https://cs.chromium.org/chromium/src/content/browser/service_manager/service_manager_context.cc?type=cs&q=CreateDeviceService),
while per-BrowserContext services are naturally embedded by [content::BrowserContext](https://cs.chromium.org/chromium/src/content/browser/browser_context.cc?type=cs&q=CreateFileService).
### Where in the Tree?
- If your service is converting existing //chrome code, then you will need
to embed your service in //chrome rather than //content. Global services
are embedded by [ChromeContentBrowserClient](https://cs.chromium.org/chromium/src/chrome/browser/chrome_content_browser_client.cc?type=cs&q=CreateMediaService),
while per-Profile services are embedded by [ProfileImpl](https://cs.chromium.org/chromium/src/chrome/browser/profiles/profile_impl.cc?type=cs&q=CreateIdentityService).
Based on the
[service development guidelines](/services/README.md), any service which could
be reasonably justified as a core system service in a hypothetical,
well-designed operating system may belong in the top-level `//services`
directory. If that sounds super hand-wavy and unclear, that's because it is!
There isn't really a great universal policy here, so when in doubt, contact your
favorite local
[services-dev@chromium.org](https://groups.google.com/a/chromium.org/forum#!forum/services-dev)
mailing list and start a friendly discussion.
- If you are looking to convert all or part of a component (i.e., a feature in
//components) into a service, the question arises of whether your new service
is worthy of being in //services (i.e., is it a foundational service?). If
not, then it can be placed in //components/services. See this
[document](https://docs.google.com/document/d/1Zati5ZohwjUM0vz5qj6sWg5r-_I0iisUoSoAMNdd7C8/edit#) for discussion of this point.
Other common places where developers place services, and why:
### If your service is embedded in the browser process, what is its threading model?
- `//components/services` for services which haven't yet made the cut for
`//services` but which are either used by Content directly or by multiple
Content embedders.
- `//chrome/services` for services which are used exclusively within Chrome and
not shared with other Content embedders.
- `//chromeos/services` for services which are used on Chrome OS by more than
just Chrome itself (for example, if the `ash` service must also connect to
them for use in system UI).
If your service is embedded in the browser process, it will run on the IO thread
by default. You can change that by specifying a task runner as part of the
information for constructing your service. In particular, if the code that you
are converting is UI-thread code, then you likely want your service running on
the UI thread. Look at the changes to profile_impl.cc in [this
CL](https://codereview.chromium.org/2753753007) to see an example of setting the
task runner that a service should be run on as part of the factory for creating
the service.
### Inside Content or Not?
### What is your approach for incremental conversion?
The next decision you need to make is whether or not Content will wire in your
service directly -- that is, whether or not your service is necessary to support
some subsystem Content makes available to either the web platform or to Content
embedders like Chrome, Android WebView, Cast Shell, and various third-party
applications.
For example, Content cannot function at all without the Network Service being
available, because Content depends heavily on the Network Service to issue and
process all of its network requests (imagine that, right?). As such, the
Network Service is wired up to the Service Manager from within Content directly.
In general, services which will be wired up in Content must live either in
`//services` or `//components/services` but ideally the former.
Conversely there are a large number of services used only by Chrome today,
such as the `unzip` service which safely performs sandboxed unpacking of
compressed archive files on behalf of clients in the browser process. These
can always be placed in `//chrome/services`.
### Per-BrowserContext or Not?
Now that you've decided on a source location for your service and you know
whether it will be wired into Content or hooked up by Content embedder code, all
that's left left is to decide whether or not you want an instance of your service
per BrowserContext (*i.e.* per user profile in Chrome).
The alternative is for you to manage your own instance arity, either as a
singleton service (quite common) or as a service which supports multiple
instances that are *not* each intrinsically tied to a BrowserContext. Most
services choose this path because BrowserContext coupling is typically
unnecessary.
As a general rule, if you're porting a subsystem which today relies heavily
on `BrowserContextKeyedService`, it's likely that you want your service
instances to have a 1:1 correspondence with BrowserContext instances.
### Putting It All Together
Let's get down to brass tacks. You're a developer of action. You've made all the
important choices you need to make and you've even built a small and extremely
well-tested prototype service with the help of
[this glorious guide](/services/service_manager/README.md#Services). Now you
want to get it working in Chromium while suffering as little pain as possible.
You're not going to believe it, but this section was written *just for YOU*.
For services which are **are not** isolated per BrowserContext and which **can**
be wired directly into Content:
- Include your service's manifest in the `content_packaged_services` manifest
directly, similar to
[these ones](https://cs.chromium.org/chromium/src/content/public/app/content_packaged_services_manifest.cc?rcl=0e8ac57eec2acfaa6f44b06eaa2fa667fe84a293&l=63).
- If you want to run your service embedded in the browser process, follow the
examples using `RegisterInProcessService`
[here](https://cs.chromium.org/chromium/src/content/browser/service_manager/service_manager_context.cc?rcl=0e8ac57eec2acfaa6f44b06eaa2fa667fe84a293&l=589).
- If you want to run your service out-of-process, update
`out_of_process_services`
[like so](https://cs.chromium.org/chromium/src/content/browser/service_manager/service_manager_context.cc?rcl=0e8ac57eec2acfaa6f44b06eaa2fa667fe84a293&l=642)
and hook up your actual private `Service` implementation exactly like the
many examples
[here](https://cs.chromium.org/chromium/src/content/utility/utility_service_factory.cc?rcl=2bdcc80a55c72a26ffe9778681f98dc4b6a565c0&l=114).
For services which are **are** isolated per BrowserContext and which **can**
be wired directly into Content:
- Include your service's manifest in the `content_browser` manifest directly,
similar to
[these ones](https://cs.chromium.org/chromium/src/content/public/app/content_browser_manifest.cc?rcl=a651619623a7b56d0c21083463ef8e61bf0a6058&l=277).
- If you want to run your service embedded in the browser process, follow the
example
[here](https://cs.chromium.org/chromium/src/content/browser/browser_context.cc?rcl=a651619623a7b56d0c21083463ef8e61bf0a6058&l=250)
- If you want to run your service out-of-process, you are doing something that
hasn't been done yet and you will need to build a new thing.
For services which **are not** isolated per BrowserContext but which **can not**
be wired directly into Content:
- Include your service's manifest in Chrome's `content_packaged_services`
manifest overlay similar to
[these ones](https://cs.chromium.org/chromium/src/chrome/app/chrome_packaged_service_manifests.cc?rcl=a651619623a7b56d0c21083463ef8e61bf0a6058&l=135)
- If you want to run your service embedded in the browser process, follow the
examples in `ChromeContentBrowserClient::HandleServiceRequest`
[here](https://cs.chromium.org/chromium/src/chrome/browser/chrome_content_browser_client.cc?rcl=a651619623a7b56d0c21083463ef8e61bf0a6058&l=3891)
- If you want to run your service out-of-process, modify
`ChromeContentBrowserClient::RegisterOutOfProcessServices` like the examples
[here](https://cs.chromium.org/chromium/src/chrome/browser/chrome_content_browser_client.cc?rcl=a651619623a7b56d0c21083463ef8e61bf0a6058&l=3785)
and hook up your `Service` implementation in
`ChromeContentUtilityClient::HandleServiceRequest` like the ones
[here](https://cs.chromium.org/chromium/src/chrome/utility/chrome_content_utility_client.cc?rcl=a651619623a7b56d0c21083463ef8e61bf0a6058&l=237).
For services which **are** isolated per BrowserContext but which **can not** be
wired directly into Content:
- Include your service's manifest in Chrome's `content_browser` manifest overlay
similar to
[these ones](https://cs.chromium.org/chromium/src/chrome/app/chrome_content_browser_overlay_manifest.cc?rcl=a651619623a7b56d0c21083463ef8e61bf0a6058&l=247)
- If you want to run your service embedded in the browser process, follow the
examples in `ProfileImpl::HandleServiceRequest`
[here](https://cs.chromium.org/chromium/src/chrome/browser/profiles/profile_impl.cc?rcl=350aea1a0242c2ea8610c9f755acee085c74ea7d&l=1263)
- If you want to run your service out-of-process, you are doing something that
hasn't been done yet and you will need to build a new thing.
*** aside
The non-Content examples above are obviously specific to Chrome as the embedder,
but Chrome's additions to supported services are all facilitated through the
common `ContentBrowserClient` and `ContentUtilityClient` APIs that all embedders
can implement. Mimicking what Chrome does should be sufficient for any embedder.
***
## Incremental Servicification
For large Chromium features it is not feasible to convert an entire subsystem
to a service all at once. As a result, it may be necessary for the subsystem
to spend a considerable amount of time (weeks or months) split between the old
implementation and your beautiful, sparkling new service implementation.
In creating your service, you likely have two goals:
- Making the service available to other services
- Making the service available to its consumers
- Making the service self-contained
Those two goals are not the same, and to some extent are at tension:
@ -111,7 +206,7 @@ Those two goals are not the same, and to some extent are at tension:
Whatever your goals, you will need to proceed incrementally if your project is
at all non-trivial (as they basically all are given the nature of the effort).
You should explicitly decide what your approach to incremental bringup and
conversion will be. Here some approaches that have been taken for various
conversion will be. Here are some approaches that have been taken for various
services:
- Build out your service depending directly on existing code,
@ -139,11 +234,11 @@ service available for new use cases sooner at the cost of leaving legacy code in
place longer, while the last is most suitable when you want to be very exacting
about doing the servicification cleanly as you go.
## Platform-Specific Issues
## Platform-Specific Issues: Android
### Android
As you servicify code running on Android, you might find that you need to port
interfaces that are served in Java. Here is an [example CL](https://codereview.chromium.org/2643713002) that gives a basic
interfaces that are served in Java. Here is an
[example CL](https://codereview.chromium.org/2643713002) that gives a basic
pattern to follow in doing this.
You also might need to register JNI in your service. That is simple to set
@ -156,50 +251,60 @@ Finally, it is possible that your feature will have coupling to UI process state
(e.g., the Activity) via Android system APIs. To handle this challenging
issue, see the section on [Coupling to UI](#Coupling-to-UI).
### iOS
## Platform-Specific Issues: iOS
*** aside
**WARNING:** Some of this content is obsolete and needs to be updated. When in
doubt, look approximately near the recommended bits of code and try to find
relevant prior art.
***
Services are supported on iOS, with the usage model in //ios/web being very
close to the usage model in //content. More specifically:
* To embed a global service in the browser service, override
[WebClient::RegisterServices](https://cs.chromium.org/chromium/src/ios/web/public/web_client.h?q=WebClient::Register&sq=package:chromium&l=136). For an
example usage, see
[WebClient::RegisterServices](https://cs.chromium.org/chromium/src/ios/web/public/web_client.h?q=WebClient::Register&sq=package:chromium&l=136). For an example usage, see
[ShellWebClient](https://cs.chromium.org/chromium/src/ios/web/shell/shell_web_client.mm?q=ShellWebClient::RegisterS&sq=package:chromium&l=91)
and the related integration test that [connects to the embedded service](https://cs.chromium.org/chromium/src/ios/web/shell/test/service_manager_egtest.mm?q=service_manager_eg&sq=package:chromium&l=89).
and the related integration test that
[connects to the embedded service](https://cs.chromium.org/chromium/src/ios/web/shell/test/service_manager_egtest.mm?q=service_manager_eg&sq=package:chromium&l=89).
* To embed a per-BrowserState service, override
[BrowserState::RegisterServices](https://cs.chromium.org/chromium/src/ios/web/public/browser_state.h?q=BrowserState::RegisterServices&sq=package:chromium&l=89). For an
example usage, see
[ShellBrowserState](https://cs.chromium.org/chromium/src/ios/web/shell/shell_browser_state.mm?q=ShellBrowserState::RegisterServices&sq=package:chromium&l=48)
and the related integration test that [connects to the embedded service](https://cs.chromium.org/chromium/src/ios/web/shell/test/service_manager_egtest.mm?q=service_manager_eg&sq=package:chromium&l=110).
and the related integration test that
[connects to the embedded service](https://cs.chromium.org/chromium/src/ios/web/shell/test/service_manager_egtest.mm?q=service_manager_eg&sq=package:chromium&l=110).
* To register a per-frame Mojo interface, override
[WebClient::BindInterfaceRequestFromMainFrame](https://cs.chromium.org/chromium/src/ios/web/public/web_client.h?q=WebClient::BindInterfaceRequestFromMainFrame&sq=package:chromium&l=148). For an
example usage, see
[WebClient::BindInterfaceRequestFromMainFrame](https://cs.chromium.org/chromium/src/ios/web/public/web_client.h?q=WebClient::BindInterfaceRequestFromMainFrame&sq=package:chromium&l=148).
For an example usage, see
[ShellWebClient](https://cs.chromium.org/chromium/src/ios/web/shell/shell_web_client.mm?type=cs&q=ShellWebClient::BindInterfaceRequestFromMainFrame&sq=package:chromium&l=115)
and the related integration test that [connects to the interface](https://cs.chromium.org/chromium/src/ios/web/shell/test/service_manager_egtest.mm?q=service_manager_eg&sq=package:chromium&l=130). Note that this is the
equivalent of [ContentBrowserClient::BindInterfaceRequestFromFrame()](https://cs.chromium.org/chromium/src/content/public/browser/content_browser_client.h?type=cs&q=ContentBrowserClient::BindInterfaceRequestFromFrame&sq=package:chromium&l=667), as on iOS all operation "in the content area" is implicitly
operating in the context of the page's main frame.
and the related integration test that
[connects to the interface](https://cs.chromium.org/chromium/src/ios/web/shell/test/service_manager_egtest.mm?q=service_manager_eg&sq=package:chromium&l=130).
Note that this is the equivalent of
[ContentBrowserClient::BindInterfaceRequestFromFrame()](https://cs.chromium.org/chromium/src/content/public/browser/content_browser_client.h?type=cs&q=ContentBrowserClient::BindInterfaceRequestFromFrame&sq=package:chromium&l=667),
as on iOS all operation "in the content area" is implicitly operating in the
context of the page's main frame.
If you have a use case or need for services on iOS, contact
blundell@chromium.org. For general information on the motivations and vision for supporting services on iOS, see the high-level [servicification design doc](https://docs.google.com/document/d/15I7sQyQo6zsqXVNAlVd520tdGaS8FCicZHrN0yRu-oU/edit) (in particular, search for the mentions
of iOS within the doc).
blundell@chromium.org. For general information on the motivations and vision for
supporting services on iOS, see the high-level
[servicification design doc](https://docs.google.com/document/d/15I7sQyQo6zsqXVNAlVd520tdGaS8FCicZHrN0yRu-oU/edit).
In particular, search for the mentions of iOS within the doc.
## Client-Specific Issues
### Services and Blink
Connecting to services directly from Blink is fully supported. [This
CL](https://codereview.chromium.org/2698083007) gives a basic example of
connecting to an arbitrary service by name from Blink (look at the change to
SensorProviderProxy.cpp as a starting point).
Below, we go through strategies for some common challenges encountered when
servicifying features that have Blink as a client.
#### Mocking Interface Impls in JS
It is a common pattern in Blink's web tests to mock a remote Mojo interface
in JS. [This CL](https://codereview.chromium.org/2643713002) illustrates the
basic pattern for porting such mocking of an interface hosted by
//content/browser to an interface hosted by an arbitrary service (see the
changes to mock-battery-monitor.js).
in JS so that native Blink code requests interfaces from the test JS rather
than whatever would normally service them in the browser process.
The current way to set up that sort of thing looks like
[this](https://cs.chromium.org/chromium/src/third_party/blink/web_tests/battery-status/resources/mock-battery-monitor.js?rcl=be6e0001855f7f1cfc26205d0ff5a2b5b324fcbd&l=19).
*** aside
**NOTE:** The above approach to mocking in JS no longer applies when using
the new recommended `DocumentInterfaceBroker` approach to exposing interfaces
to documents. New JS mocking support is in development for this.
***
#### Feature Impls That Depend on Blink Headers
In the course of servicifying a feature that has Blink as a client, you might
@ -215,7 +320,9 @@ To meet this challenge, you have two options:
1. Move the code in question from C++ to mojom (e.g., if it is simple structs).
2. Move the code into the service's C++ client library, being very explicit
about its usage by Blink. See [this CL](https://codereview.chromium.org/2415083002) for a basic pattern to follow.
about its usage by Blink. See
[this CL](https://codereview.chromium.org/2415083002) for a basic pattern to
follow.
#### Frame-Scoped Connections
You must think carefully about the scoping of the connection being made
@ -226,8 +333,8 @@ Blink has no frame-scoped connection to arbitrary services (by design, as
arbitrary services have no knowledge of frames or even a notion of what a frame
is).
After a [long
discussion](https://groups.google.com/a/chromium.org/forum/#!topic/services-dev/CSnDUjthAuw),
After a
[long discussion](https://groups.google.com/a/chromium.org/forum/#!topic/services-dev/CSnDUjthAuw),
the policy that we have adopted for this challenge is the following:
CURRENT
@ -246,9 +353,6 @@ AFTER SERVICIFYING THE FEATURE IN QUESTION
Notably, from the renderer's POV essentially nothing changes here.
In the longer term, this will still be the basic model, only with "the browser"
replaced by "the Navigation Service" or "the web permissions broker".
## Strategies for Challenges to Decoupling from //content
### Coupling to UI
@ -268,16 +372,17 @@ what requires the coupling and to avoid the coupling creeping in scope.
The basic strategy to support this coupling while still servicifying the feature
in question is to inject a mechanism of mapping from an opaque "context ID" to
the required context. The embedder (e.g., //content) maintains this map, and the
service makes use of it. The embedder also serves as an intermediary: It
service makes use of it. The embedder also serves as an intermediary: it
provides a connection that is appropriately context-scoped to clients. When
clients request the feature in question, the embedder forwards the request on
along with the appropriate context ID. The service impl can then map that
context ID back to the needed context on-demand using the mapping functionality
injected into the service impl.
To make this more concrete, see [this CL](https://codereview.chromium.org/2734943003).
To make this more concrete, see
[this CL](https://codereview.chromium.org/2734943003).
### Shutdown of singletons
### Shutdown of Singletons
You might find that your feature includes singletons that are shut down as part
of //content's shutdown process. As part of decoupling the feature
@ -293,29 +398,15 @@ either ported into your service or eliminated:
to when the previous code was executing, and ensure that any differences
introduced do not impact correctness.
See [this thread](https://groups.google.com/a/chromium.org/forum/#!topic/services-dev/Y9FKZf9n1ls) for more discussion of this issue.
See
[this thread](https://groups.google.com/a/chromium.org/forum/#!topic/services-dev/Y9FKZf9n1ls)
for more discussion of this issue.
### Tests that muck with service internals
It is often the case that browsertests reach directly into what will become part
of the internal service implementation to either inject mock/fake state or to
monitor private state.
## Additional Support
This poses a challenge: As part of servicification, *no* code outside the
service impl should depend on the service impl. Thus, these dependencies need to
be removed. The question is how to do so while preserving testing coverage.
To answer this question, there are several different strategies. These
strategies are not mutually-exclusive; they can and should be combined to
preserve the full breadth of coverage.
- Blink client-side behavior can be tested via [web tests](https://codereview.chromium.org/2731953003)
- To test service impl behavior, create [service tests](https://codereview.chromium.org/2774783003).
- To preserve tests of end-to-end behavior (e.g., that when Blink makes a
request via a Web API in JS, the relevant feature impl receives a connection
request), we are planning on introducing the ability to register mock
implementations with the Service Manager.
To emphasize one very important point: it is in general necessary to leave
*some* test of end-to-end functionality, as otherwise it is too easy for bustage
to slip in via e.g. changes to how services are registered. See [this thread](https://groups.google.com/a/chromium.org/forum/#!topic/services-dev/lJCKAElWz-E)
for further discussion of this point.
If this document was not helpful in some way, please post a message to your
friendly local
[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
or
[services-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev)
mailing list.

@ -1,860 +0,0 @@
# Converting Legacy Chrome IPC To Mojo
Looking for [Mojo Documentation](/mojo)?
[TOC]
## Overview
The `//ipc` directory contains interfaces and implementation for Chrome's
legacy IPC system, including `IPC::Channel` and various macros for defining
messages and type serialization. For details on using this system please see the
original
[documentation](https://www.chromium.org/developers/design-documents/inter-process-communication).
Legacy IPC is **deprecated**, and Chrome developers are strongly discouraged
from introducing new messages using this system. [Mojo](/mojo) is the correct
IPC system to use moving forward. This document introduces developers to the
various tools available to help with conversion of legacy IPC messages to Mojo.
It assumes familiarity with [Mojom](/mojo/public/tools/bindings) syntax and
general use of Mojo [C++ bindings](/mojo/public/cpp/bindings).
The existing messages that still need to be converted are tracked in two
spreadsheets:
[Chrome IPC to Mojo migration](
https://docs.google.com/spreadsheets/d/1pGWX_wxGdjAVtQOmlDDfhuIc3Pbwg9FtvFXAXYu7b7c/edit#gid=0) -
for non-web platform messages
[Mojoifying Platform Features](
https://docs.google.com/spreadsheets/d/1VIINt17Dg2cJjPpoJ_HY3HI0uLpidql-1u8pBJtpbGk/edit#gid=1603373208) -
for web platform messages
Ownership of items is claimed by specifying a username in the 'Owner' field to
prevent duplication of effort. If you are not very familiar with the messages
you plan to convert, it might be worth asking the owner first.
In traditional Chrome IPC, we have One Big Pipe (the `IPC::Channel`) between
each connected process. Sending an IPC from one process to another means knowing
how to get a handle to the Channel interface (*e.g.,*
[RenderProcessHost::GetChannel](
https://cs.chromium.org/chromium/src/content/public/browser/render_process_host.h?rcl=722be98f7e4d7551710fb9cf30674750cdd0d857&l=196)
when sending from the browser to a renderer process), and then having either an
`IPC::MessageFilter` or some other appropriate `IPC::Listener` implementation
installed in the right place on the other side of the channel.
Because of this arrangement, any message sent on a channel is sent in FIFO order
with respect to all other messages on the channel. While this may be easier to
reason about in general, it carries with it the unfortunate consequence that
many unrelated messages in the system have an implicit, often unintended
ordering dependency.
It's primarily for this reason that conversion to Mojo IPC can be more
challenging than would otherwise be necessary, and that is why we have a number
of different tools available to facilitate such conversions.
## Deciding What to Do
There are few questions you should ask yourself before embarking upon any IPC
message conversion journey. Should this be part of a service? Does message
ordering matter with respect to other parts of the system? What is the meaning
of life?
### Moving Messages to Services
We have a small but growing number of services defined in
[`//services`](https://cs.chromium.org/chromium/src/services/), each of which has
some set of public interfaces defined in their `public/interfaces` subdirectory.
In the limit, this is the preferred destination for any message conversions
pertaining to foundational system services (more info at
[https://www.chromium.org/servicification](https://www.chromium.org/servicification).)
For other code it may make sense to introduce services elsewhere (*e.g.*, in
`//chrome/services` or `//components/services`), or to simply
avoid using services altogether for now and instead define some one-off Mojom
interface alongside the old messages file.
If you need help deciding where a message should live, or if you feel it would
be appropriate to introduce a new service to implement some feature or large set
of messages, please post to
[`services-dev@chromium.org`](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev)
with questions, concerns, and/or a brief proposal or design doc describing
the augmentation of an existing service or introduction of a new service.
See the [Using Services](#Using-Services) section below for details.
When converting messages that still require tight coupling to content or Chrome
code or which require unchanged ordering with respect to one or more remaining
legacy IPC messages, it is often not immediately feasible to move a message
definition or handler implementation into a service.
### Moving Messages to Not-Services
While this isn't strictly possible because everything is a service now, we model
all existing content processes as service instances and provide helpers to make
interface exposure and consumption between them relatively easy.
See [Using Content's Connectors](#Using-Content_s-Connectors) for details on
the recommended way to accomplish this.
See
[Using Content's Interface Registries](#Using-Content_s-Interface-Registries)
for details on the **deprecated** way to accomplish this.
Note that when converting messages to standalone Mojo interfaces, every
interface connection operates 100% independently of each other. This means that
ordering is only guaranteed over a single interface (ignoring
[associated interfaces](/mojo/public/tools/bindings#Associated-Interfaces).)
Consider this example:
``` cpp
mojom::FrobinatorPtr frob1;
RenderThread::Get()->GetConnector()->BindInterface(
foo_service::mojom::kServiceName, &frob1);
mojom::FrobinatorPtr frob2;
RenderThread::Get()->GetConnector()->BindInterface(
foo_service::mojom::kServiceName, &frob2);
// These are ordered on |frob1|.
frob1->Frobinate(1);
frob1->Frobinate(2);
// These are ordered on |frob2|.
frob2->Frobinate(1);
frob2->Frobinate(2);
// It is entirely possible, however, that the renderer receives:
//
// [frob1]Frobinate(1)
// [frob2]Frobinate(1)
// [frob1]Frobinate(2)
// [frob2]Frobinate(2)
//
// Because |frob1| and |frob2| guarantee no mutual ordering.
```
Also note that neither interface is ordered with respect to legacy
`IPC::Channel` messages. This can present significant problems when converting a
single message or group of messages which must retain ordering with respect to
others still on the Channel.
### When Ordering Matters
If ordering really matters with respect to other legacy messages in the system,
as is often the case for *e.g.* frame and navigation-related messages, you
almost certainly want to take advantage of
[Channel-associated interfaces](#Using-Channel_associated-Interfaces) to
eliminate any risk of introducing subtle behavioral changes.
Even if ordering only matters among a small set of messages which you intend to
move entirely to Mojom, you may wish to move them one-by-one in separate CLs.
In that case, it may make sense to use a Channel-associated interface during the
transitional period. Once all relevant messages are fully relocated into a
single Mojom interface, it's trivial to lift the interface away from Channel
association and into a proper independent service connection.
## Using Services
Suppose you have some IPC messages for safely decoding a PNG image:
``` cpp
IPC_MESSAGE_CONTROL2(UtilityMsg_DecodePNG,
int32_t request_id,
std::string /* png_data */);
IPC_MESSAGE_CONTROL2(UtilityHostMsg_PNGDecoded,
int32_t request_id,
int32_t width, int32_t height,
std::string /* rgba_data */);
```
This seems like a perfect fit for an addition to the sandboxed `data_decoder`
service. Your first order of business is to translate this into a suitable
public interface definition within that service:
``` cpp
// src/services/data_decoder/public/mojom/png_decoder.mojom
module data_decoder.mojom;
interface PngDecoder {
Decode(array<uint8> png_data)
=> (int32 width, int32 height, array<uint32> rbga_data);
};
```
You will need to update the relevant BUILD.gn target with the newly added mojom
file. See [this section](
https://chromium.googlesource.com/chromium/src/+/master/mojo/public/cpp/bindings/README.md#getting-started)
for details.
You'll also want to define the implementation within
`//services/data_decoder`, plugging in some appropriate binder so the service
knows how to bind incoming interface requests to your implementation:
``` cpp
// src/services/data_decoder/png_decoder_impl.h
class PngDecoderImpl : public mojom::PngDecoder {
public:
static void BindRequest(mojom::PngDecoderRequest request) { /* ... */ }
// mojom::PngDecoder:
void Decode(const std::vector<uint8_t>& png_data,
const DecodeCallback& callback) override { /* ... */ }
// ...
};
// src/services/data_decoder/data_decoder_service.cc
// Not quite legitimate pseudocode...
DataDecoderService::DataDecoderService() {
// ...
registry_.AddInterface(base::Bind(&PngDecoderImpl::BindRequest));
}
```
and finally you need to update the usage of the old IPC by probably deleting
lots of ugly code which sets up a `UtilityProcessHost` and replacing it with
something like:
``` cpp
#include "services/data_decoder/public/mojom/png_decoder.mojom.h"
...
void OnDecodedPng(const std::vector<uint8_t>& rgba_data) { /* ... */ }
data_decoder::mojom::PngDecoderPtr png_decoder;
connector->BindInterface(data_decoder::mojom::kServiceName,
mojo::MakeRequest(&png_decoder));
png_decoder->Decode(untrusted_png_data, base::Bind(&OnDecodedPng));
```
Where to get a [`Connector`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/connector.h)
is an interesting question, and the answer ultimately depends on where your code
is written. All service instances get a primordial `Connector` which can be
cloned arbitrarily many times and passed around to different threads.
If you're writing service code the answer is trivial since each `Service`
instance has direct access to a `Connector`. If you're writing code at or above
the content layer, the answer is slightly more interesting and is explained in
the [Using Content's Connectors](#Using-Content_s-Connectors) section below.
## Using Content's Connectors
As explained earlier in this document, all content processes are modeled as
service instances today. This means that all content processes have at least
one [`Connector`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/connector.h)
instance which can be used to bind interfaces exposed by other services.
We define [`content::ServiceManagerConnection`](https://cs.chromium.org/chromium/src/content/public/common/service_manager_connection.h?rcl=dd92156efac57169b45aeb0094111b8d94302b12&l=38)
as a helper which fully encapsulates the service instance state within a given
Content process. The main thread of the browser process can access the global
instance by calling
[`content::ServiceManager::GetForProcess()`](https://cs.chromium.org/chromium/src/content/public/common/service_manager_connection.h?rcl=dd92156efac57169b45aeb0094111b8d94302b12&l=56),
and this object has a `GetConnector()` method which exposes the `Connector` for
that process.
The main thread of any Content child process can use
`content::ChildThread::GetServiceManagerConnection` or
`content::ChildThread::GetConnector` directly.
For example, any interfaces registered in
[`RenderProcessHostImpl::RegisterMojoInterfaces()`](https://cs.chromium.org/chromium/src/content/browser/renderer_host/render_process_host_impl.cc?rcl=dd92156efac57169b45aeb0094111b8d94302b12&l=1203)
can be acquired by a renderer as follows:
``` cpp
mojom::LoggerPtr logger;
content::RenderThread::Get()->GetConnector()->BindInterface(
content::mojom::kBrowserServiceName, &logger);
logger->Log("Message to log here");
```
Usually `logger` will be saved in a field at construction time, so the
connection is only created once. There may be situations where you want to
create one connection per request, e.g. a new instance of the Mojo
implementation is created with some information about the request, and any
responses for this request go straight to that instance.
### On Other Threads
`Connector` instances can be created and asynchronously associated with each
other to maximize flexibility in when and how outgoing interface requests are
initiated.
For example if a background (*e.g.,* worker) thread in a renderer process wants
to make an outgoing service request, it can construct its own `Connector` --
which may be used immediately and retained on that thread -- and asynchronously
associate it with the main-thread `Connector` like so:
``` cpp
class Logger {
public:
explicit Logger(scoped_refptr<base::TaskRunner> main_thread_task_runner) {
service_manager::mojom::ConnectorRequest request;
// Of course we could also retain |connector| if we intend to use it again.
auto connector = service_manager::Connector::Create(&request);
// Replace service_name with the name of the service to bind on, e.g.
// content::mojom::kBrowserServiceName.
connector->BindInterface("service_name", &logger_);
logger_->Log("Test Message.");
// Doesn't matter when this happens, as long as it happens eventually.
main_thread_task_runner->PostTask(
FROM_HERE, base::BindOnce(&Logger::BindConnectorOnMainThread,
std::move(request)));
}
private:
static void BindConnectorOnMainThread(
service_manager::mojom::ConnectorRequest request) {
DCHECK(RenderThreadImpl::Get());
RenderThreadImpl::Get()->GetConnector()->BindConnectorRequest(
std::move(request));
}
mojom::LoggerPtr logger_;
DISALLOW_COPY_AND_ASSIGN(Logger);
};
```
## Using Content's Interface Registries
**NOTE:** This section is here mainly for posterity and documentation of
existing usage. Please use `Connector` instead of using an `InterfaceProvider`
directly.
For convenience the Service Manager's
[client library](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/)
exposes two useful types: `BinderRegistry` and `InterfaceProvider`. These
objects generally exist as an intertwined pair with a `BinderRegistry` in
one process and a corresponding `InterfaceProvider` in another process.
The `BinderRegistry` is essentially just a mapping from interface name
to binder function:
``` cpp
void BindFrobinator(mojom::FrobinatorRequest request) {
mojo::MakeStrongBinding(std::make_unique<FrobinatorImpl>, std::move(request));
}
// |registry| will hereby handle all incoming requests for "mojom::Frobinator"
// using the above function, which binds the request pipe handle to a new
// instance of |FrobinatorImpl|.
registry->AddInterface(base::Bind(&BindFrobinator));
```
while an `InterfaceProvider` exposes a means of requesting interfaces from a
remote `BinderRegistry`:
``` cpp
mojom::FrobinatorPtr frob;
// MakeRequest creates a new pipe, and GetInterface sends one end of it to
// the remote InterfaceRegistry along with the "mojom::Frobinator" name. The
// other end of the pipe is bound to |frob| which may immediately begin sending
// messages.
provider->GetInterface(mojo::MakeRequest(&frob));
frob->DoTheFrobinator();
```
`RenderFrameHostImpl`'s binder registry corresponds to the `InterfaceProvider`
returned by `RenderFrameImpl::GetRemoteInterfaces()`, and `RenderFrameImpl`'s
binder registry corresponds to the `InterfaceProvider` returned by
`RenderFrameHostImpl::GetRemoteInterfaces()`.
**NOTE:** this mechanism is being replaced with explicit interface factory
approach described in [this document](
https://docs.google.com/document/d/1e0qqv3ZGQYskE4XhtuGrYJeThjYXu8xozl7zIlwjSD0).
As noted above, use of these registries is generally discouraged.
### Deciding Which Interface Registry to Use
Once you have an implementation of a Mojo interface, the next thing to decide is
which registry and service to register it on.
For browser/renderer communication, you can register your Mojo interface
implementation in either the Browser or Renderer process (whichever side the
interface was implemented on). Usually, this involves calling `AddInterface()`
on the correct registry, passing a method that takes the Mojo Request object
(e.g. `sample::mojom::LoggerRequest`) and binding it (e.g.
`mojo::MakeStrongBinding()`, `bindings_.AddBinding()`, etc). Then the class that
needs this API can call `BindInterface()` on the connector for that process,
e.g.
`ChildThreadImpl::current()->GetConnector()->BindInterface(mojom::kBrowserServiceName, std::move(&mojo_interface_))`.
**NOTE:** `content::ServiceManagerConnection::GetForProcess()` must be called in
the browser process on the main thread, and its connector can only be used on
the main thread; but you can clone connectors and move the clones around to
other threads. A `Connector` is only bound to the thread which first calls into
it.
Depending on what resources you need access to, the main classes are:
| Renderer Class | Corresponding Browser Class | Explanation |
|-----------------|-----------------------------|--------------------------------------------------------------------------------------------------------------------|
| `RenderFrame` | `RenderFrameHost` | A single frame. Use this for frame-to-frame messages. |
| `RenderView` | `RenderViewHost` | A view (conceptually a 'tab'). You cannot send Mojo messages to a `RenderView` directly, since frames in a tab can be in multiple processes (and the classes are deprecated). Migrate these to `RenderFrame` instead, or see section [Migrating IPC calls to `RenderView` or `RenderViewHost`](#other-routed-messages-to-the-browser). |
| `RenderProcess` | `RenderProcessHost` | A process, containing multiple frames (probably from the same origin, but not always). |
**NOTE:** Previously, classes that ended with `Host` were implemented on the
browser side; the equivalent classes on the renderer side had the same name
without the `Host` suffix. We have since deviated from this convention since
Mojo interfaces are not intended to prescribe where their endpoints live, so
future classes should omit such suffixes and just describe the interface they
are providing.
Of course, any combination of the above is possible, e.g. `RenderProcessHost`
can register a Mojo interface that can be called by a `RenderFrame` (this would
be a way of the browser communicating with multiple frames at once).
Once you know which class you want the implementation to be registered in, find
the corresponding `Impl` class (e.g. `RenderProcessImpl`). There should be a
`RegisterMojoInterfaces()` method where you can add calls to `AddInterface`,
e.g. For a strong binding:
```cpp
registry->AddInterface(base::Bind(&Logger::Create, GetID()));
```
Then in `Logger` we add a static `Create()` method that takes the
`LoggerRequest` object:
```cpp
// static
void Logger::Create(int render_process_id,
mojom::LoggerRequest request) {
mojo::MakeStrongBinding(std::make_unique<Logger>(render_process_id),
std::move(request));
}
```
For a `BindingSet`, we can store a `std::unique_ptr<Logger>` on the
`RenderProcessHost` instead, e.g.:
```cpp
// render_process_host_impl.h:
std::unique_ptr<Logger> logger_;
// render_process_host_impl.cc:
logger_ = std::make_unique<Logger>(GetID());
registry->AddInterface(base::Bind(&Logger::BindRequest,
base::Unretained(logger_.get())));
```
Then in `Logger` we define the `BindRequest` method:
```h
class Logger : public sample::mojom::Logger {
public:
explicit Logger(int render_process_id);
~Logger() override;
void BindRequest(mojom::LoggerRequest request);
// sample::mojom::Logger:
void Log(const std::string& message) override;
void GetTail(GetTailCallback callback) override;
private:
mojo::BindingSet<sample::mojom::Logger> bindings_;
DISALLOW_COPY_AND_ASSIGN(Logger);
};
```
```cpp
void Logger::BindRequest(mojom::LoggerRequest request) {
bindings_.AddBinding(this, std::move(request));
}
```
As you can see above, `MakeStrongBinding()` is used to lazily create an
interface implementation when a connection is created. The lifetime of this
implementation spans the lifetime of the connection. This is done to not
unnecessarily create instances that might not be used.
Because strong binding lifetime is not tracked or easily observable, any
implementation bound with a strong binding must be very careful to avoid
dependencies on things which it might outlive. As a general rule, if your
implementation depends on any state outside of itself, please consider avoiding
strong bindings in favor of explicit object ownership.
Alternatively, the relevant registry owner class can own the implementation
instance and dispatch the connection requests that the implementation will
bind.
#### Setting up Capabilities
Once you've registered your interface, you need to add capabilities (resolved at
runtime) to the corresponding capabilities manifest json file.
The service manifest files (which contain the capability spec) are located in
[/content/public/app/mojo/](/content/public/app/mojo/). As a general rule, the
file you want to edit is the service which *provides* the interface (the side
which instantiates the implementation), and the part of the file you want to add
the name of the interface to is the service which *calls* the interface (i.e.
the side containing `LoggerPtr`).
You can usually just run your Mojo code and look at the error messages. The
errors look like:
```sh
[ERROR:service_manager.cc(158)] Connection InterfaceProviderSpec prevented
service: content_renderer from binding interface: content.mojom.Logger
exposed by: content_browser
```
This means something in the renderer process (called "content_renderer") was
trying to bind to `content.mojom.Logger` in the browser process (called
"content_browser"). To add a capability for this, we need to find the json file
with the capabilities for "content_browser", and add our new interface with name
`content.mojom.Logger` to the "renderer" section.
In this example, the capabilities for "content_browser" are implemented in
[content_browser_manifest.json](/content/public/app/mojo/content_browser_manifest.json).
It should look like:
```json
{
"name": "content_browser",
"display_name": "Content (browser process)",
"interface_provider_specs": {
"service_manager:connector": {
"provides": {
// ...
"renderer": [
//...
```
To add permission for `content.mojom.Logger`, add the string
`"content.mojom.Logger"` to the "renderer" list.
Similarly, if the error was:
```sh
[ERROR:service_manager.cc(158)] Connection InterfaceProviderSpec prevented
service: content_browser from binding interface: content.mojom.Logger exposed
by: content_renderer
```
We would want the
`interface_provider_specs.service_manager:connector.provides.browser` section in
[content_renderer_manifest.json](/content/public/app/mojo/content_renderer_manifest.json)
(which defines the capabilities for `content_renderer`).
TODO: Add more details on permission manifests here
## Using Channel-associated Interfaces
**NOTE**: Channel-associated interfaces are an interim solution to make the
transition to Mojo IPC easier in Chrome. You should not design new features
which rely on this system. The ballpark date of deletion for `IPC::Channel` is
projected to be somewhere around mid-2019, and obviously Channel-associated
interfaces can't live beyond that point.
Mojo has support for the concept of
[associated interfaces](/mojo/public/tools/bindings#Associated-Interfaces).
One interface is "associated" with another when it's a logically separate
interface but it shares an underlying message pipe, causing both interfaces to
maintain mutual FIFO message ordering. For example:
``` cpp
// db.mojom
module db.mojom;
interface Table {
void AddRow(string data);
};
interface Database {
QuerySize() => (uint64 size);
AddTable(associated Table& table)
};
// db_client.cc
db::mojom::DatabasePtr db = /* ... get it from somewhere... */
db::mojom::TableAssociatedPtr new_table;
db->AddTable(mojo::MakeRequest(&new_table));
new_table->AddRow("my hovercraft is full of eels");
db->QuerySize(base::Bind([](uint64_t size) { /* ... */ }));
```
In the above code, the `AddTable` message will always arrive before the `AddRow`
message, which itself will always arrive before the `QuerySize` message. If the
`Table` interface were not associated with the `Database` pipe, it would be
possible for the `QuerySize` message to be received before `AddRow`,
potentially leading to unintended behavior.
The legacy `IPC::Channel` used everywhere today is in fact just another Mojo
interface, and developers have the ability to associate other arbitrary Mojo
interfaces with any given Channel. This means that you can define a set of Mojo
messages to convert old IPC messages, and implement them in a way which
perfectly preserves current message ordering.
There are many different facilities in place for taking advantage of
Channel-associated interfaces, and the right one for your use case depends on
how the legacy IPC message is used today. The subsections below cover various
interesting scenarios.
### Basic Usage
The most primitive way to use Channel-associated interfaces is by working
directly with `IPC::Channel` (IO thread) or more commonly `IPC::ChannelProxy`
(main thread). There are a handful of interesting interface methods here.
**On the IO thread** (*e.g.,* typically when working with process hosts that
aren't for render processes), the interesting methods are as follows:
[`IPC::Channel::GetAssociatedInterfaceSupport`](https://cs.chromium.org/chromium/src/ipc/ipc_channel.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=235)
returns an object for working with interfaces associated with the `Channel`.
This is never null.
[`IPC::Channel::AssociatedInterfaceSupport::AddAssociatedInterface<T>`](
https://cs.chromium.org/chromium/src/ipc/ipc_channel.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=115)
allows you to add a binding function to handle all incoming requests for a
specific type of associated interface. Callbacks added here are called on the IO
thread any time a corresponding interface request arrives on the `Channel.` If
no callback is registered for an incoming interface request, the request falls
through to the Channel's `Listener` via
[`IPC::Listener::OnAssociatedInterfaceRequest`](https://cs.chromium.org/chromium/src/ipc/ipc_listener.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=40).
[`IPC::Channel::AssociatedInterfaceSupport::GetRemoteAssociatedInterface<T>`](
https://cs.chromium.org/chromium/src/ipc/ipc_channel.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=124)
requests a Channel-associated interface from the remote endpoint of the channel.
**On the main thread**, typically when working with `RenderProcessHost`, basic
usage involves calls to
[`IPC::ChannelProxy::GetRemoteAssociatedInterface<T>`](
https://cs.chromium.org/chromium/src/ipc/ipc_channel_proxy.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=196)
when making outgoing interface requests, or some implementation of
[`IPC::Listener::OnAssociatedInterfaceRequest`](https://cs.chromium.org/chromium/src/ipc/ipc_listener.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=40)
when handling incoming ones.
TODO - Add docs for using AssociatedInterfaceRegistry where possible.
### BrowserMessageFilter
[BrowserMessageFilter](https://cs.chromium.org/chromium/src/content/public/browser/browser_message_filter.h?rcl=805f2ca5aa0902f56885ea3c8c0a42cb80d84522&l=37)
is a popular helper for listening to incoming legacy IPC messages on the browser
process IO thread and (typically) handling them there.
A common and totally reasonable tactic for converting a group of messages on an
existing `BrowserMessageFilter` is to define a similiarly named Mojom interface
in an inner `mojom` namespace (*e.g.,* a `content::FooMessageFilter` would have
a corresponding `content::mojom::FooMessageFilter` interface), and have the
`BrowserMessageFilter` implementation also implement
`BrowserAssociatedInterface<T>` (optionally overriding methods such as
`BrowserMessageFilter::OnDestruct()` if it needs to be deleted on a certain
thread).
Real code is probably the most useful explanation, so here are some example
conversion CLs which demonstrate practical `BrowserAssociatedInterface` usage.
[FrameHostMsg_SetCookie](https://codereview.chromium.org/2167513003) - This
CL introduces a `content::mojom::RenderFrameMessageFilter` interface
corresponding to the existing `content::RenderFrameMessageFilter` implementation
of `BrowserMessageFilter`. Of particular interest is the fact that it only
converts **one** of the messages on that filter. This is fine because ordering
among the messages -- Mojom or otherwise -- is unchanged.
[FrameHostMsg_GetCookie](https://codereview.chromium.org/2202723005) - A small
follow-up to the above CL, this converts another message on the same filter. It
is common to convert a large group of messages one-by-one in separate CLs. Also
note that this message, unlike the one above on the same interface, is
synchronous.
[ViewHostMsg_GenerateRoutingID](https://codereview.chromium.org/2351333002) -
Another small CL to introduce a new `BrowserAssociatedInterface`.
### Routed Per-Frame Messages To the Browser
Many legacy IPC messages are "routed" -- they carry a routing ID parameter which
is interpreted by the channel endpoint and used to pass a received message on to
some other more specific handler.
Messages received by the browser with a frame routing ID for example are routed
to the RenderFrameHost's owning [`WebContents`](https://cs.chromium.org/chromium/src/content/browser/web_contents/web_contents_impl.h?rcl=a12e52d81346dd23d8284763d44c4ee657f11cea&l=447)
with the corresponding `RenderFrameHostImpl` as additional context.
[This CL](https://codereview.chromium.org/2310583002) introduces usage of
[`WebContentsFrameBindingSet<T>`](https://cs.chromium.org/chromium/src/content/public/browser/web_contents_binding_set.h?rcl=d364139fee76154a1d9fa8875ad0cbb5ccb523c3&l=112), which helps establish
per-frame bindings for Channel-associated interfaces. Some hidden magic is done
to make it so that interface requests from a remote
[`RenderFrame AssociatedInterfaceProvider`](https://cs.chromium.org/chromium/src/content/public/renderer/render_frame.h?rcl=d364139fee76154a1d9fa8875ad0cbb5ccb523c3&l=170)
are routed to the appropriate `WebContentsFrameBindingSet`, typically installed
(as in this CL) by a `WebContentsObserver`.
When a message is received by an interface implementation using a
`WebContentsFrameBindingSet`, that object's `dispatch_context()` can be used
to retrieve the `RenderFrameHostImpl` targeted by the message. See the above CL
for additional clarity.
**NOTE:** When the ordering of messages doesn't matter, the `InterfaceProvider`
of the relevant `RenderFrameHost` should be used to replace the routing ID. It
can be obtained by calling `RenderFrame::GetRemoteInterfaces()`.
### Other Routed Messages To the Browser
Other routing IDs are used when targeting either specific `RenderViewHost` or
`RenderWidgetHost` instances. We don't currently have any facilities in place
to assist with these conversions. Because render views are essentially a
deprecated concept, messages targeting "view" routes should not be converted
as-is, but should instead be moved to target either widgets or frames
accordingly.
Facilities to assist in conversion of widget-routed messages may be added in the
future. Who knows, maybe you'll be the brave developer to add them (and to then
update this documentation, of course!) If you decide this is exactly what you
need but are nervous about the prospect of writing it yourself, please send a
friendly message to [chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
explaining the use case so we can help you get things done.
### Messages to a Renderer
[This CL](https://codereview.chromium.org/2381493003) converts `ViewMsg_New`
to a Mojo interface, by virtue of the fact that
`IPC::ChannelProxy::GetRemoteAssociatedInterface` from the browser process
results in an associated interface request arriving at
`ChildThreadImpl::OnAssociatedInterfaceRequest` in the corresponding child
process.
Similar message conversions are done by [this CL](https://codereview.chromium.org/2400313002).
Note that we do not currently have any helpers for converting routed messages
from browser to renderer. Please confer with
[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
if such a use case is blocking your work.
## Miscellany
### Using Legacy IPC Traits
In some circumstances there may be a C++ enum, struct, or class that you want
to use in a Mojom via [type mapping](/mojo/public/cpp/bindings#Type-Mapping),
and that type may already have `IPC::ParamTraits` defined (possibly via
`IPC_STRUCT_TRAITS*` macros) for legacy IPC.
If this is the case and the Mojom which uses the type will definitely only be
called from and implemented in C++ code, *and* you have sufficient reason to
avoid moving or duplicating the type definition in Mojom, you can take advantage
of the existing `ParamTraits`.
#### The [Native] Attribute
In order to do this you must declare a placeholder type in Mojom somewhere, like
so:
```
module foo.mojom;
[Native]
enum WindowType;
[Native]
struct MyGiganticStructure;
```
The rest of your Mojom will use this typename when referring to the type, but
the wire format used is defined entirely by `IPC::ParamTraits<T>` for whatever
`T` to which you typemap the Mojom type. For example if you typemap
`foo::mojom::MyGiganticStructure` to `foo::MyGiganticStructure`, your typemap
must point to some header which defines
`IPC::ParamTraits<foo::MyGiganticStructure>`.
There are several examples of this traits implementation in common IPC traits
defined [here](https://code.google.com/p/chromium/codesearch#chromium/src/ipc/ipc_message_utils.h).
#### A Practical Example
Given the [`resource_messages.h`](https://cs.chromium.org/chromium/src/content/common/resource_messages.h?rcl=2e7a430d8d88222c04ab3ffb0a143fa85b3cec5b&l=215)
header with the following definition:
``` cpp
IPC_STRUCT_TRAITS_BEGIN(content::ResourceRequest)
IPC_STRUCT_TRAITS_MEMBER(method)
IPC_STRUCT_TRAITS_MEMBER(url)
// ...
IPC_STRUCT_TRAITS_END()
```
and the [`resource_request.h`](https://cs.chromium.org/chromium/src/content/common/resource_request.h?rcl=dce9e476a525e4ff0304787935dc1a8c38392ac8&l=32)
header with the definition for `content::ResourceRequest`:
``` cpp
namespace content {
struct CONTENT_EXPORT ResourceRequest {
// ...
};
} // namespace content
```
we can declare a corresponding Mojom type:
```
module content.mojom;
[Native]
struct URLRequest;
```
and add a typemap like [url_request.typemap](https://cs.chromium.org/chromium/src/content/common/url_request.typemap)
to define the mapping:
```
mojom = "//content/public/common/url_loader.mojom"
public_headers = [ "//content/common/resource_request.h" ]
traits_headers = [ "//content/common/resource_messages.h" ]
...
type_mappings = [ "content.mojom.URLRequest=content::ResourceRequest" ]
```
Note specifically that `public_headers` includes the definition of the native
C++ type, and `traits_headers` includes the definition of the legacy IPC traits.
Finally, note that this same approach can be used to leverage existing
`IPC_ENUM_TRAITS` for `[Native]` Mojom enum aliases.
### Typemaps With Content and Blink Types
Using typemapping for messages that go between Blink and content browser code
can sometimes be tricky due to things like dependency cycles or confusion over
the correct place for some definition to live. There are some example
CLs provided here, but feel free to also contact
[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
with specific details if you encounter trouble.
[This CL](https://codereview.chromium.org/2363533002) introduces a Mojom
definition and typemap for
`ui::WindowOpenDisposition` as a precursor to the IPC conversion below.
The [follow-up CL](https://codereview.chromium.org/2363573002) uses that
definition along with several other new typemaps (including native typemaps as
described above in [Using Legacy IPC Traits](#Using-Legacy-IPC-Traits)) to
convert the relatively large `ViewHostMsg_CreateWindow` message to Mojo.
### Utility Process Messages
Given that there are no interesting ordering dependencies among disparate IPC
messages to and from utility processes, and because the utility process is
already sort of a mixed bag of unrelated IPCs, the correct way to convert
utility process IPCs to Mojo is to move them into services.
We already have support for running services out-of-process (with or without a
sandbox), and many utility process operations already have a suitable service
home they could be moved to. For example, the `data_decoder` service in
[`//services/data_decoder`](https://cs.chromium.org/chromium/src/services/data_decoder/)
is a good place to stick utility process IPCs that do decoding of relatively
complex and untrusted data, of which (at the time of this writing) there are
quite a few.
When in doubt, contact
[`services-dev@chromium.org`](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev)
with ideas, questions, suggestions, etc.
### Additional Documentation
[Chrome IPC to Mojo IPC Cheat Sheet](https://www.chromium.org/developers/design-documents/mojo/chrome-ipc-to-mojo-ipc-cheat-sheet)
: A slightly dated but still valuable document covering some details
regarding the conceptual mapping between legacy IPC and Mojo.
[Additional example CLs](https://docs.google.com/document/d/1GCi08AVMV96cD-tI8kW3xfRir3aNMb5U2yJFU3iAFSU)

@ -4,18 +4,21 @@
## Getting Started With Mojo
To get started using Mojo in applications which already support it (such as
Chrome), the fastest path forward will be to look at the bindings documentation
for your language of choice ([**C++**](#C_Bindings),
[**JavaScript**](#JavaScript-Bindings), or [**Java**](#Java-Bindings)) as well
as the documentation for the
[**Mojom IDL and bindings generator**](/mojo/public/tools/bindings/README.md).
To get started using Mojo in Chromium, the fastest path forward will likely be
to read the Mojo sections of the
[Intro to Mojo &amp; Services](/docs/mojo_and_services.md) guide.
If you're looking for information on creating and/or connecting to services, see
the top-level [Services documentation](/services/README.md).
For more detailed reference material on the most commonly used features of Mojo,
head directly to the [bindings](#Bindings-APIs) documentation for your language
of choice or the more general
[mojom Interface Definition Language (IDL)](/mojo/public/tools/bindings/README.md)
documentation.
For specific details regarding the conversion of old things to new things, check
out [Converting Legacy Chrome IPC To Mojo](/ipc/README.md).
If you're looking for information on creating and/or connecting to services,
you're in the wrong place! Mojo does not deal with services, it only facilitates
interface definition, message passing, and other lower-level IPC primitives.
Instead, you should take a look at some of the other available
[Mojo &amp; Services](/docs/README.md#Mojo-Services) documentation.
## System Overview
@ -25,9 +28,10 @@ library with code generation for multiple target languages to facilitate
convenient message passing across arbitrary inter- and intra-process boundaries.
The documentation here is segmented according to the different libraries
comprising Mojo. The basic hierarchy of features is as follows:
comprising Mojo. Mojo is divided into cleanly-separated layers with the basic
hierarchy of subcomponents as follows:
![Mojo Library Layering: Core on bottom, language bindings on top, public system support APIs in the middle](https://docs.google.com/drawings/d/1RwhzKblXUZw-zhy_KDVobAYprYSqxZzopXTUsbwzDPw/pub?w=570&h=324)
![Mojo Library Layering: Core on bottom, language bindings on top, public system support APIs in the middle](/docs/images/mojo_stack.png)
## Mojo Core
In order to use any of the more interesting high-level support libraries like
@ -44,6 +48,9 @@ Mojo support within each process by calling `mojo::core::Init()`. See
This is a reasonable option when you can guarantee that all interconnected
process binaries are linking against precisely the same revision of Mojo Core.
This includes Chromium itself as well as any developer tools and test
executables built within the tree.
To support other scenarios, use dynamic linking.
### Dynamic Linking
@ -51,7 +58,7 @@ On some platforms, it's also possible for applications to rely on a
dynamically-linked Mojo Core library (`libmojo_core.so` or `mojo_core.dll`)
instead of statically linking against Mojo Core.
In order to take advantage of this mechanism, the corresponding library must be
In order to take advantage of this mechanism, the library's binary must be
present in either:
- The working directory of the application
@ -60,84 +67,65 @@ present in either:
Instead of calling `mojo::core::Init()` as embedders do, an application using
dynamic Mojo Core instead calls `MojoInitialize()` from the C System API. This
call will attempt to locate (see above) and load a Mojo Core library to support
subsequent Mojo API usage within the process.
call will attempt to locate (see above) and load the Mojo Core library to
support subsequent Mojo API usage within the process.
Note that the Mojo Core shared library presents a stable, forward-compatible C
ABI which can support all current and future versions of the higher-level,
public (and not binary-stable) System and Bindings APIs.
Note that the Mojo Core shared library presents a **stable C ABI** designed with
both forward- and backward-compatibility in mind. Thus old applications will
work with new versions of the shared library, and new applications can work
with old versions of the shared library (modulo any dependency on newer
features, whose absence can be gracefully detected at runtime).
## C System API
Once Mojo is initialized within a process, the public
[**C System API**](/mojo/public/c/system/README.md) is usable on any thread for
the remainder of the process's lifetime. This is a lightweight API with a
relatively small, stable, forward-compatible ABI, comprising the total public
API surface of the Mojo Core library.
the remainder of the process's lifetime. This encapsulates Mojo Core's stable
ABI and comprises the total public API surface of the Mojo Core library.
This API is rarely used directly, but it is the foundation upon which all
higher-level Mojo APIs are built. It exposes the fundamental capabilities to
create and interact Mojo primitives like **message pipes**, **data pipes**, and
**shared buffers**, as well as APIs to help bootstrap connections among
processes.
The C System library's only dependency (apart from the system libc and e.g.
pthreads) is Mojo Core itself. As such, it's possible build a fully-featured
multiprocess system using only Mojo Core and its exposed C API. It exposes the
fundamental cross-platform capabilities to create and manipulate Mojo primitives
like **message pipes**, **data pipes**, and **shared buffers**, as well as APIs
to help bootstrap connections among processes.
Despite this, it's rare for applications to use the C API directly. Instead this
API acts as a stable foundation upon which several higher-level and more
ergonomic Mojo libraries are built.
## Platform Support API
Mojo provides a small collection of abstractions around platform-specific IPC
primitives to facilitate bootstrapping Mojo IPC between two processes. See the
[Platform API](/mojo/public/cpp/platform/README.md) documentation for details.
## High-Level System APIs
## Higher-Level System APIs
There is a relatively small, higher-level system API for each supported
language, built upon the low-level C API. Like the C API, direct usage of these
system APIs is rare compared to the bindings APIs, but it is sometimes desirable
or necessary.
### C++
The [**C++ System API**](/mojo/public/cpp/system/README.md) provides a layer of
C++ helper classes and functions to make safe System API usage easier:
strongly-typed handle scopers, synchronous waiting operations, system handle
wrapping and unwrapping helpers, common handle operations, and utilities for
more easily watching handle state changes.
These APIs provide wrappers around low-level [system API](#C-System-API)
concepts, presenting interfaces that are more idiomatic for the target language:
### JavaScript
The [**JavaScript System API**](/third_party/blink/renderer/core/mojo/README.md)
exposes the Mojo primitives to JavaScript, covering all basic functionality of the
low-level C API.
- [**C++ System API**](/mojo/public/cpp/system/README.md)
- [**JavaScript System API**](/third_party/blink/renderer/core/mojo/README.md)
- [**Java System API**](/mojo/public/java/system/README.md)
### Java
The [**Java System API**](/mojo/public/java/system/README.md) provides helper
classes for working with Mojo primitives, covering all basic functionality of
the low-level C API.
## Bindings APIs
The [**mojom Interface Definition Language (IDL)**](/mojo/public/tools/bindings/README.md)
is used to generate interface bindings for various languages to send and receive
mojom interface messages using Mojo message pipes. The generated code is
supported by a language-specific bindings API:
## High-Level Bindings APIs
Typically developers do not use raw message pipe I/O directly, but instead
define some set of interfaces which are used to generate code that resembles
an idiomatic method-calling interface in the target language of choice. This is
the bindings layer.
- [**C++ Bindings API**](/mojo/public/cpp/bindings/README.md)
- [**JavaScript Bindings API**](/mojo/public/js/README.md)
- [**Java Bindings API**](/mojo/public/java/bindings/README.md)
### Mojom IDL and Bindings Generator
Interfaces are defined using the
[**Mojom IDL**](/mojo/public/tools/bindings/README.md), which can be fed to the
[**bindings generator**](/mojo/public/tools/bindings/README.md) to generate code
in various supported languages. Generated code manages serialization and
deserialization of messages between interface clients and implementations,
simplifying the code -- and ultimately hiding the message pipe -- on either side
of an interface connection.
### C++ Bindings
By far the most commonly used API defined by Mojo, the
[**C++ Bindings API**](/mojo/public/cpp/bindings/README.md) exposes a robust set
of features for interacting with message pipes via generated C++ bindings code,
including support for sets of related bindings endpoints, associated interfaces,
nested sync IPC, versioning, bad-message reporting, arbitrary message filter
injection, and convenient test facilities.
### JavaScript Bindings
The [**JavaScript Bindings API**](/mojo/public/js/README.md) provides helper
classes for working with JavaScript code emitted by the bindings generator.
### Java Bindings
The [**Java Bindings API**](/mojo/public/java/bindings/README.md) provides
helper classes for working with Java code emitted by the bindings generator.
Note that the C++ bindings see the broadest usage in Chromium and are thus
naturally the most feature-rich, including support for things like
[associated interfaces](/mojo/public/cpp/bindings/README.md#Associated-Interfaces),
[synchronous calls](/mojo/public/cpp/bindings/README.md#Synchronous-Calls), and
[type-mapping](/mojo/public/cpp/bindings/README.md#Type-Mapping).
## FAQ
@ -162,7 +150,9 @@ Compared to the old IPC in Chrome, making a Mojo call is about 1/3 faster and us
### Can I use in-process message pipes?
Yes, and message pipe usage is identical regardless of whether the pipe actually
crosses a process boundary -- in fact this detail is intentionally obscured.
crosses a process boundary -- in fact the location of the other end of a pipe is
intentionally obscured, in part for the sake of efficiency, and in part to
discourage tight coupling of application logic to such details.
Message pipes which don't cross a process boundary are efficient: sent messages
are never copied, and a write on one end will synchronously modify the message

@ -43,8 +43,8 @@ user-provided notification handlers may be invoked at any time on arbitrary
threads in the process. It is entirely up to the API user to take appropriate
measures to synchronize operations against other application state.
The higher level [system](/mojo/README.md#High-Level-System-APIs) and
[bindings](/mojo/README.md#High-Level-Bindings-APIs) APIs provide helpers to
The higher-level [system](/mojo/README.md#Higher_Level-System-APIs) and
[bindings](/mojo/README.md#Bindings-APIs) APIs provide helpers to
simplify Mojo usage in this regard, at the expense of some flexibility.
## Result Codes

@ -17,7 +17,7 @@ snippets. For a detailed API references please consult the headers in
[//mojo/public/cpp/bindings](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/README.md).
For a simplified guide targeted at Chromium developers, see [this
link](/docs/mojo_guide.md).
link](/docs/mojo_and_services.md).
## Getting Started
@ -153,7 +153,7 @@ routed to some implementation which will **bind** it. The `InterfaceRequest<T>`
doesn't actually *do* anything other than hold onto a pipe endpoint and carry
useful compile-time type information.
![Diagram illustrating InterfacePtr and InterfaceRequest on either end of a message pipe](https://docs.google.com/drawings/d/1_Ocprq7EGgTKcSE_WlOn_RBfXcr5C3FJyIbWhwzwNX8/pub?w=608&h=100)
![Diagram illustrating InterfacePtr and InterfaceRequest on either end of a message pipe](/docs/images/mojo_pipe.png)
So how do we create a strongly-typed message pipe?
@ -211,7 +211,7 @@ logger->Log("Hello!");
This actually writes a `Log` message to the pipe.
![Diagram illustrating a message traveling on a pipe from LoggerPtr to LoggerRequest](https://docs.google.com/drawings/d/11vnOpNP3UBLlWg4KplQuIU3r_e1XqwDFETD-O_bV-2w/pub?w=635&h=112)
![Diagram illustrating a message traveling on a pipe from LoggerPtr to LoggerRequest](/docs/images/mojo_message.png)
But as mentioned above, `InterfaceRequest` *doesn't actually do anything*, so
that message will just sit on the pipe forever. We need a way to read messages
@ -278,7 +278,7 @@ motion by the above line of code:
3. The `Log` message is read and deserialized, causing the `Binding` to invoke
the `Logger::Log` implementation on its bound `LoggerImpl`.
![Diagram illustrating the progression of binding a request, reading a pending message, and dispatching it](https://docs.google.com/drawings/d/1F2VvfoOINGuNibomqeEU8KekYCtxYVFC00146CFGGQY/pub?w=550&h=500)
![Diagram illustrating the progression of binding a request, reading a pending message, and dispatching it](/docs/images/mojo_binding_and_dispatch.png)
As a result, our implementation will eventually log the client's `"Hello!"`
message via `LOG(ERROR)`.
@ -1261,8 +1261,7 @@ sync method call? It continues to process incoming sync request messages
messages and sync response messages that dont match the ongoing sync
call.
![Diagram illustrating sync call flow](
https://docs.google.com/a/google.com/drawings/d/e/2PACX-1vRvsmrmZBszFl_OX9AhCn2Cqwx63K0GC7cYrDNPoRYRuHzxS30OZ4ygMBpeU_cThuQY2lYZkYpvSCdM/pub?w=960&h=560)
![Diagram illustrating sync call flow](/docs/images/mojo_sync_call_flow.png)
Please note that sync response messages that dont match the ongoing
sync call cannot re-enter. That is because they correspond to sync calls
@ -1274,8 +1273,7 @@ while the stack unwinds.
Please note that the re-entrancy behavior doesnt prevent deadlocks
involving async calls. You need to avoid call sequences such as:
![Diagram illustrating a sync call deadlock](
https://docs.google.com/a/google.com/drawings/d/e/2PACX-1vTBl5XPA8K-kVPt0oByMNSSoxpCKh1p2_atIDR9Me4xGfa6nf0fNAKkJ-Hg5utllY5ghXtoS1haHL6d/pub?w=960&h=480)
![Diagram illustrating a sync call deadlock](/docs/images/mojo_sync_call_deadlock.png)
### Read more

@ -1,18 +1,18 @@
# Mojom IDL and Bindings Generator
# Mojom Interface Definition Language (IDL)
This document is a subset of the [Mojo documentation](/mojo/README.md).
[TOC]
## Overview
Mojom is the IDL for Mojo bindings interfaces. Given a `.mojom` file, the
Mojom is the IDL for Mojo interfaces. Given a `.mojom` file, the
[bindings
generator](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/)
outputs bindings for all supported languages: **C++**, **JavaScript**, and
generator](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/) can
output bindings for any supported language: **C++**, **JavaScript**, or
**Java**.
For a trivial example consider the following hypothetical Mojom file we write to
`//services/widget/public/interfaces/frobinator.mojom`:
`//services/widget/public/mojom/frobinator.mojom`:
```
module widget.mojom;
@ -25,15 +25,15 @@ interface Frobinator {
This defines a single [interface](#Interfaces) named `Frobinator` in a
[module](#Modules) named `widget.mojom` (and thus fully qualified in Mojom as
`widget.mojom.Frobinator`.) Note that many interfaces and/or other types of
definitions may be included in a single Mojom file.
definitions (structs, enums, *etc.*) may be included in a single Mojom file.
If we add a corresponding GN target to
`//services/widget/public/interfaces/BUILD.gn`:
`//services/widget/public/mojom/BUILD.gn`:
```
import("mojo/public/tools/bindings/mojom.gni")
mojom("interfaces") {
mojom("mojom") {
sources = [
"frobinator.mojom",
]
@ -43,22 +43,32 @@ mojom("interfaces") {
and then build this target:
```
ninja -C out/r services/widget/public/interfaces
ninja -C out/r services/widget/public/mojom
```
we'll find several generated sources in our output directory:
```
out/r/gen/services/widget/public/interfaces/frobinator.mojom.cc
out/r/gen/services/widget/public/interfaces/frobinator.mojom.h
out/r/gen/services/widget/public/interfaces/frobinator.mojom.js
out/r/gen/services/widget/public/interfaces/frobinator.mojom.srcjar
...
out/r/gen/services/widget/public/mojom/frobinator.mojom.cc
out/r/gen/services/widget/public/mojom/frobinator.mojom.h
out/r/gen/services/widget/public/mojom/frobinator.mojom-shared.h
etc...
```
Each of these generated source modules includes a set of definitions
representing the Mojom contents within the target language. For more details
regarding the generated outputs please see
representing the Mojom contents in C++. You can also build or depend on suffixed
target names to get bindings for other languages. For example,
```
ninja -C out/r services/widget/public/mojom:mojom_js
ninja -C out/r services/widget/public/mojom:mojom_java
```
would generate JavaScript and Java bindings respectively, in the same generated
output directory.
For more details regarding the generated
outputs please see
[documentation for individual target languages](#Generated-Code-For-Target-Languages).
## Mojom Syntax
@ -136,7 +146,7 @@ If your Mojom references definitions from other Mojom files, you must **import**
those files. Import syntax is as follows:
```
import "services/widget/public/interfaces/frobinator.mojom";
import "services/widget/public/mojom/frobinator.mojom";
```
Import paths are always relative to the top-level directory.
@ -493,7 +503,7 @@ relative ordering guarantees among them. Associated interfaces are useful when
one interface needs to guarantee strict FIFO ordering with respect to one or
more other interfaces, as they allow interfaces to share a single pipe.
Currenly associated interfaces are only supported in generated C++ bindings.
Currently associated interfaces are only supported in generated C++ bindings.
See the documentation for
[C++ Associated Interfaces](/mojo/public/cpp/bindings/README.md#Associated-Interfaces).

@ -1,84 +1,256 @@
# Chrome Foundation Services
# Service Development Guidelines
[TOC]
## Overview
This directory contains Chrome Foundation Services. If you think of Chrome as a
"portable OS," Chrome Foundation Services can be thought of as that OS'
foundational "system services" layer.
If you're looking for general documentation on the Service Manager, what a
"service" is, and how to build one, see the
[Service Manager &amp; Services](/services/service_manager/README.md)
documentation instead of this document.
Roughly each subdirectory here corresponds to a service that:
The top-level `//services` directory contains the sources, public Mojo interface
definitions, and public client libraries for a number of essential services,
designated as **Chrome Foundation Services**. If you think of Chrome as a
"portable OS," Chrome Foundation Services can be thought of as the core system
services of that OS.
* is a client of `//services/service_manager` with its own unique Identity.
* could logically run a standalone process for security/performance isolation
benefits depending on the constraints of the host OS.
Each subdirectory here corresponds to a service that:
## API Standards
- implements
[`Service`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/service.h?rcl=ebec02bcca6e327b2e01855ce43ab1bec0aeef27&l=21)
and is thus a client of the Service Manager
- generally focuses on a subset of functionality or features which are
thematically or functionally related in a way that makes sense given the name
of the service
- could logically run in an isolated process for security or performance
isolation, depending on the constraints of the host OS
As illustrated above, the individual services in //services are intended for
graceful reusability across a broad variety of use cases. To enable this goal,
we have rigorous [standards](/services/api_standards.md) on services'
public APIs. Before doing significant work in //services (and especially before
becoming an owner of a service), please internalize these standards -- you are
responsible for upholding them.
*** aside
Note that there are other parts of the tree which aggregate
slightly-less-than-foundational service definitions, such as services specific
to the Chrome browser, defined in `//chrome/services`. The motivations, advice,
and standards discussed in this document apply to all service definitions in the
Chromium tree.
***
## Service Directory Structure
The `//services/service_manager` directory contains the implementation and
public APIs of the Service Manager itself, including an embedder API with which
software applications (such as Chrome) can embed the Service Manager to manage
their own multiprocess service architecture.
Individual services are structured like so:
One of the main motivations for expressing Chromium as a collection of services
is long-term maintainability and code health. Because service API boundaries are
strictly limited to Mojo interfaces, state owned and managed by each service is
strongly isolated from other components in the system.
```
//services/foo/ <-- Implementation code, may have subdirs.
/public/
/cpp/ <-- C++ client libraries (optional)
/mojom/ <-- Mojom interfaces
Another key motivation is general modularity and reusability: in the past there
have been a number of missed opportunities for potential new features or
Chromium-based products due to the browser's generally monolothic and inflexible
system design. With the Service Manager &amp; services providing scaffolding for
system components, it becomes progressively easier to build out newer use cases
with *e.g.* a smaller resource footprint, or a different process model, or even
a more granular binary distribution.
## Service Standards
As outlined above, individual services are intended for graceful reusability
across a broad variety of use cases. To enable this goal, we have rigorous
standards on services' structure and public API design. Before doing significant
work in `//services` (or other places where services are defined), please
internalize these standards. All Chromium developers are responsible for
upholding them!
### Public Service APIs
In creating and maintaining a service's public API, please respect the following
principles:
- The purpose of a service should be readily apparent.
- The supported client use cases of the service should be easy for a new
consumer to understand.
- The service should use idioms and design patterns consistent with other
services.
- From the service's public API documentation and tests, it should be feasible
to develop a new implementation of the service which satisfies existing
clients and doesn't require mimicking internal implementation details of the
existing service.
- Perhaps most important of all, a service's public API should be designed with
multiple hypothetical clients in mind, *not* focused on supporting only a
single narrow use known at development time. **Always be thinking about the
future!**
If you're working on a new service and have concerns or doubts about API design,
please post to
[services-dev@chromium.org](https://groups.google.com/a/chromium.org/forum#!forum/services-dev)
and ask for help. The list is generally quite responsive, and it's loaded with
people who have done a lot of work on services.
### Service API Design Tips
#### Using Interface Factories to Establish Context
One common pitfall when designing service APIs is to write something like:
``` cpp
interface GoatTeleporter {
// Sets the client interface pipe for this teleporter. Must be called before
// other interface methods.
SetClient(GoatTeleporterClient client);
TeleportGoat(string name);
};
interface GoatTeleporterClient {
TeleporterReady();
};
```
## Dependencies
The problem with this approach is that a client may easily fail to call
`SetClient` before calling `TeleportGoat`. When such ordering requirements are
necessary, the service can benefit clients by designing an API that is harder
to fail at. For example:
Code within `//services` may only depend on each other via each other's
`/public/` directories, *i.e.* implementation code may not be shared directly.
``` cpp
interface GoatTeleporterFactory {
GetGoatTeleporter(GoatTeleporter& request, GoatTeleporterClient client);
};
Service code should also take care to tightly limit the dependencies on static
libraries from outside of `//services`. Dependencies to large platform
layers like `//content`, `//chrome` or `//third_party/WebKit` must be avoided.
interface GoatTeleporter {
TeleportGoat(string name);
};
```
## Physical Packaging
Instead of exposing `GoatTeleporter` directly to other services, the service can
expose `GoatTeleporterFactory` instead. Now it's impossible for a client to
acquire a functioning `GoatTeleporter` pipe without also providing a
corresponding client pipe to complement it.
Note that while it may be possible to build a discrete physical package (DSO)
for each service, products consuming these services may package them
differently, e.g. by combining them into a single package.
### Service &amp; Interface Naming
## Additional Documentation
Just some basic tips for service and interface naming:
[High-level Design Doc](https://docs.google.com/document/d/15I7sQyQo6zsqXVNAlVd520tdGaS8FCicZHrN0yRu-oU)
- Strive to give your service a name that makes it immediately obvious what the
service is for (*e.g.*, `"network"`, `"metrics"`) rather than a meaningless
codename like `"cromulator_3000"`.
- Avoid the usage of `"Service"` in interface names. While the term "service"
is overloaded in Chromium and certainly has plenty of valid interpretations,
in the context of Service Manager services it has a very specific meaning
and should not be overloaded further if possible. An interface which exposes a
control API for a goat teleporter can just be called `GoatTeleporter`, not
`GoatTeleporterService`.
[Servicification Homepage](https://sites.google.com/a/chromium.org/dev/servicification)
- Strive to avoid conceptual layering violations in naming and documentation --
*e.g.*, avoid referencing Blink or Content concepts like "renderers" or
"frame hosts".
[Servicification Strategies](/docs/servicification.md)
- Use the names `FooClient` and `FooObserver` consistently in interfaces. If
there is an expected 1:1 correspondence between a Foo and its client interface
counterpart, that counterpart should most likely be called `FooClient`. If
there is expected to be 1-to-many correspondence between a Foo and its
counterpart clients, the client interface may be better named `FooObserver`.
## Relationship To Other Top-Level Directories
### Service Directory &amp; Dependency Structure
Services can be thought of as integrators of library code from across the
Chromium repository, most commonly `//base` and `//mojo` (obviously) but for
each service also `//components`, `//ui`, *etc.* in accordance with the
functionality they provide.
Services typically follow a canonical directory structure:
Not everything in `//components` is automatically a service in its own right.
Think of `//components` as sort of like a `//lib`. Individual `//components` can
define, implement and use Mojom interfaces, but only `//services` have unique
identities with the Service Manager and so only `//services` make it possible
for Mojom interfaces to be acquired.
```
//services/service_name/ # Private implementation
public/
mojom/ # Mojom interfaces
cpp/ # C++ client libraries (optional)
java/ # Java client libararies (optional, rare)
js/ # JS client libraries (optional, rare)
```
## Adding a new service
As a general rule, **nothing below `/public` can depend on the private service
implementation** (*i.e.* things above `/public`). Enforcing this principle makes
it much easier to keep the service's state well-isolated from the rest of the
system.
See the [Service Manager documentation](/services/service_manager) for more
details regarding how to define a service and expose or consume interfaces to
and from other services.
Generally the language-specific client libraries are built against only the
public mojom API of the service (and usually few other common dependencies like
`//base` and `//mojo`), and they bootstrap connections to those interfaces by
using public Service Manager APIs like
[`Connector`](/services/service_manager/README.md#Connectors).
Please start a thread on [services-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev)
if you want to introduce a new service.
Even in the private service implementation, services should not depend on very
large components like Content, Chrome, or Blink.
If you are servicifying existing Chromium code: Please first read the
[servicification strategies documentation](/docs/servicification.md), which
contains information that will hopefully make your task easier.
*** aside
NOTE: Exceptions to the above rule are made in rare cases where Blink or V8 is
actually required as part of the service implementation. For example
`"data_decoder"` uses Blink implementation to decode common image formats, and
`"proxy_resolver"` uses V8 to execute proxy autoconfig scripts.
***
### Service Documentation
- Every service should have a top-level `README.md` that explains the purpose and
supported usage models of the service.
- Every public interface should be documented within its Mojom file at both the
interface level and indivudal message level.
- Interface documentation should be complete enough to serve as test
specifications. If the method returns information of a user's accounts, what
should happen if the user is not signed in? If the method makes a request for
an access token, what happens if a client makes a second method call before
the first one has completed? If the method returns a nullable object, under
which conditions will it be null?
- Avoid writing interface documentation which is unnecessarily prescriptive
about implementation details. Keep in mind that these are **interface**
definitions, not implementations thereof.
- Avoid writing documentation which is tailored to a specific client.
### Service Testing
- Try to cover service implementation details with unit tests tied as closely
as possible to the private implementation object or method being tested,
rather than exercising implementation details through public API surface.
- For integration tests, try to have tests cover as much of the public API
surface as possible while mocking out as little of the underlying service as
possible.
- Treat the public API tests as "conformance tests" which clearly demonstrate
what expectations and guarantees are supposed to be upheld by *any*
implementation of the service's APIs.
- Take advantage of the
[test support library](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/test/)
provided by the Service Manager. In particular, `TestConnectorFactory` is
useful for driving public API tests with the service running inside the test
process, and `TestServiceManager` makes it possible to easily cover
out-of-process testing scenarios while faking out as little of the system as
possible.
## Adding a New Service
See the [Service Manager documentation](/services/service_manager/README.md) for
more details regarding how to define a service and expose or consume interfaces
to and from it, as well as how to make the service available to an application's
runtime environment.
Please start a thread on
[services-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev)
if you want to propose the introduction of a new service.
If you are servicifying an existing Chromium feature, please check out
[Servicifying Chromium Features](/docs/servicification.md).
## Other Docs
Here are some other external documents that aren't quite fully captured by any
documents in the Chromium tree. Beware of obsolete information:
- [High-level Design Doc](https://docs.google.com/document/d/15I7sQyQo6zsqXVNAlVd520tdGaS8FCicZHrN0yRu-oU)
- [Servicification Homepage](https://sites.google.com/a/chromium.org/dev/servicification)
## Additional Support
You can always post to
[services-dev@chromium.org](https://groups.google.com/a/chromium.org/forum#!forum/services-dev)
with questions or concerns about anything related to service development.

@ -1,116 +0,0 @@
# API Standards for Foundation Services
In creating and maintaining the public-facing structure of a foundation service,
you should hold yourself to several first-order goals:
* The purpose of the service should be readily apparent.
* The supported usage models of the service should be easy for a new
consumer to understand.
* The service should be consistent with other foundation services.
* From the API documentation and tests, it should be feasible
to develop a distinct implementation of the service (i.e., without having to
delve into the internals of the current implementation).
Below we outline concrete standards that aid in achieving the above goals.
## Naming
* Strive to give your service a name that makes it immediately obvious what the
service is for ("network", "metrics").
* Avoid the usage of "Service" in interface names. While the term "Service" is
overloaded in Chromium, in the context of //services it has a very specific
meaning and should not be overloaded.
* Strive to avoid conceptual layering violations in naming -- e.g., references
to Blink or //content.
* Use the names "FooClient" and "FooObserver" consistently in interfaces. If
there is an expected 1:1 correspondence between Foo and its counterpart, that
counterpart should be called FooClient. If there is an expected 1:many
correspondence between Foo and its counterparts, those counterparts should be
called FooObservers.
## Documentation
* Every service should have a top-level README.md that explains the purpose and
supported usage models of the service.
* Every public interface should be documented at the interface (class) level and
at the method level.
* Interface documentation should be complete enough to serve as test
specifications. If the method returns information of a user's accounts, what
happens if the user is not signed in? If the method makes a request for an
access token, what happens if a client makes a second method call before a
first one has completed? If the method returns a nullable object, under which
conditions will it be null?
* Strive to avoid your documentation being too specific to a given client.
## API Shape
* Strive to avoid molding your API shape too specifically to the needs of a
given client. Most foundational services should make sense even in a
Chrome-less system environment. A good test is: Would your service's APIs seem
sensible to users who don't have knowledge of Chrome's specific needs?
* If a given interface Foo requires "construction parameters" (e.g., the client
must give it a FooClient before calling any methods), provide a FooProvider
interface with a GetFoo() method that takes in the relevant construction
parameters. This approach eliminates the possibility of a badly-written (or
malevolent) client calling methods on a partially-constructed Foo. To be
concrete:
````
// NO: Client will have access to partially-constructed Foo.
interface Foo {
SetClient(FooClient client);
...
};
// YES: Foo will be completely constructed before client has access.
interface FooProvider {
GetFoo(Foo& request, FooClient client);
};
interface Foo { ... };
````
* In the absence of specific guidance, strive for consistency with surrounding
interfaces and with interfaces in other services.
## Testing
* Use service tests to test the public interfaces exposed by your service.
* Every public method should be covered by at least one service test. Strive
to have your tests enforce your documentation (corollary: if you can enforce
your documentation without any tests, improve your documentation :).
* Think of these tests as a form of "compliance tests": They should be written
in such a way that engineers with a distinct implementation of your
APIs should trivially be able to run your tests against their implementation.
Notably, try to avoid relying on implementation details of the service in its
tests.
* Related to the above, aim for a high degree of coverage with these tests. If a
reimplementation passes your tests, you should have a high degree of
confidence that it will be usable by your consumers.
## Appendix: Responsibility for Upholding These Standards
The responsibility for holding these standards is shared across
//services/OWNERS, individual service OWNERS, and services developers:
* //services/OWNERS own the standards themselves and are responsible for
ensuring that quality and consistency are maintained across //services.
* Individual service OWNERS are responsible for ensuring that their service
adheres to these standards.
* Service developers are responsible for ensuring that their CLs adhere to
these standards (and thus making life easier for the OWNERS that must review
these CLs :).
We expect that these standards will evolve over time. If you encounter a tricky
situation not covered here, please send an email to services-dev@. Similarly, if
you see inconsistency or violations of the standards, please file a bug and CC
relevant OWNERS (i.e., of the service in question and/or //services/OWNERS).

File diff suppressed because it is too large Load Diff

@ -1,315 +0,0 @@
# Service Manifests
[TOC]
## Overview
Manifest files are used to configure security properties and
permissions for services, such as listing allowed sets of interfaces or
specifying a sandbox type. The files use JSON format and are usually
placed in the same directory as the service source files, but the path
is configurable in the BUILD.gn file for the service
(see [README.md](README.md#build-targets) for an example).
## Terminology
The Service Manager is responsible for starting new service instances on-demand,
and a given service may have any number of concurrently running instances.
The Service Manager disambiguates service instances by their unique identity.
A service's **identity** is represented by the 4-tuple of its service name,
instance group, instance ID, and a globally unique ID:
### Service name
A free-form -- typically short -- string identifying the the specific service
being run in the instance.
### Instance Group
Service instances started by the Service Manager are organized into
*instance groups*. Typically a service instance can only connect to other
service instances in its own group. Exceptions are made for targeted services
which are designed to be accessible cross-group (such as singleton services), as
well as for connecting services which are sufficiently privileged to connect to
any service instance in the system.
Instance group is represented by a `base::Token` in `service_manager::Identity`.
When instance group is omitted from an Identity passed with an interface request
to the Service Manager, the Service Manager assumes that the request should be
routed to a service instance in the requestor's same instance group.
In Chrome, every `BrowserContext` has a randomly generated instance group ID
associated with it, and this is used to isolate the service instances which run
on behalf of specific profiles, including renderers.
### Instance ID
Another `base::Token` in `service_manager::Identity`, used to disambiguate
multiple instances of a service for the same user. Every instance has an
instance ID, but it typically takes on the default value of a zero-token.
### Globally Unique ID
Every service instance started by the Service Manager is assigned a randomly
generated `base::Token` value designated as the instance's
**globally unique ID**. This value is always unique to a single instance across
time and space.
### Connections
Every service instance has a Connector API it can use to issue requests to the
Service Manager. One such request is `BindInterface`, which allows the service
to bind an interface within another service instance.
When binding an interface, the **source identity** refers to the service
initiating the bind request, and the **target identity** refers to the
destination service instance. Based on both the source and target identities,
the Service Manager may choose to start a new service instance, reuse an
existing instance as the destination for the bind request or deny the request.
### Interface provider
InterfaceProvider is a Mojo
[interface](https://cs.chromium.org/chromium/src/services/service_manager/public/mojom/interface_provider.mojom)
for providing an implementation of an interface by name. It is implemented by
different hosts (for frames and workers) in the browser, and the manifest
allows to specify different sets of capabilities exposed by these hosts.
## File structure
### name (string)
A unique identifier that is used to refer to the service.
### display\_name (string)
A human-readable name which can have any descriptive value. Not user-visible.
### sandbox\_type (string)
An optional field that provides access to several types of sandboxes.
Inside a sandbox, by default the service is essentially restricted to CPU and
memory access only. Common values are:
* `utility` (default) - also allows full access to one configurable directory;
* `none` - no sandboxing is applied;
* `none_and_elevated` - under Windows, no sandboxing is applied and privileges
are elevated.
If the service cannot run with a sandbox type of utility, elevated, or none,
please reach out to the security team.
### options (dictionary)
This field can be used to specify values for any of the following options:
#### instance\_sharing (string)
Determines which parameters result in the creation of a new service
instance on an incoming service start/interface bind request.
Possible values:
##### none (default)
When one service is connecting to another, checks are performed to either find
an existing instance that matches the target identity or create a new one if
no match is found.
By default, all four identity components (service name, instance group, instance
ID, and globally unique ID) are used to find a match.
See
[advice](https://chromium.googlesource.com/chromium/src/+/master/docs/servicification.md#is-your-service-global-or-per_browsercontext)
on using this option.
Example:
[identity](https://cs.chromium.org/chromium/src/services/identity/manifest.json)
##### shared\_across\_instance\_groups
In this case, the instance group parameter is ignored when looking for a
matching target instance, so an existing instance can be reused regardless of
which instance group the connecting service belongs to.
Example:
[data_decoder](https://cs.chromium.org/chromium/src/services/data_decoder/manifest.json)
##### singleton
In this case, both instance group and instance ID parameters are ignored when
an interface request is targeting the service. Only one service instance is
created, and all interface requests targeting the service will be routed to that
instance.
Example:
[download_manager](https://cs.chromium.org/chromium/src/chrome/browser/android/download/manifest.json)
#### can\_connect\_to\_instances\_in\_any\_group (bool)
This option allows a service to make outgoing requests with a target instance
group other than its own.
**Note:** this privilege must only be granted to services that are trusted
at the same level as the browser process itself.
Example:
[content_browser](https://cs.chromium.org/chromium/src/content/public/app/mojo/content_browser_manifest.json)
The browser process manages all `BrowserContexts`, so it needs this privilege
to act on behalf of different users.
#### can\_connect\_to\_other\_services\_with\_any\_instance\_name (bool)
This option allows a service to specify an instance ID that is
different from the service name when connecting.
**Note:** this privilege must only be granted to services that are trusted
at the same level as the browser process itself.
Example:
[chrome_browser](https://cs.chromium.org/chromium/src/chrome/app/chrome_manifest.json)
Code in chrome_browser calls an XML parsing library function, which generates a
random instance ID to
[isolate unrelated decode operations](https://cs.chromium.org/chromium/src/services/data_decoder/public/cpp/safe_xml_parser.cc?l=50).
#### can\_create\_other\_service\_instances (bool)
This option allows a service to register arbitrary new service instances it
creates on its own.
**Note:** this privilege must only be granted to services that are trusted
at least at the same level as the Service Manager itself.
Example:
[content_browser](https://cs.chromium.org/chromium/src/content/public/app/mojo/content_browser_manifest.json)
The browser manages render processes, and thus needs this privilege to manage
the content_renderer instances on behalf of the service manager.
### interface\_provider\_specs (dictionary)
The interface provider spec is a dictionary keyed by interface provider
name, with each value representing the capability spec for that
provider.
Each capability spec defines an optional "provides" key and an optional
"requires" key.
Every interface provider spec (often exclusively) contains one standard
capability spec named “service_manager:connector”. This is the
capability spec enforced when inter-service connections are made from a
service's `Connector` interface.
Some other examples of capability specs are things like "navigation:frame",
which enforces capability specs for interfaces retrieved through a
frame's `InterfaceProvider`.
See [README.md](README.md#service-manifests) for some examples.
**Note:** Since multiple interface provider support makes the manifest files
harder to understand, there is a plan to simplify this section
(see https://crbug.com/718652 for more details).
#### provides (dictionary)
This optional section specifies a set of capabilities provided by the service.
A capability is a set of accessible interfaces.
For example, suppose we have the following capabilities:
* useful_capability
* useful\_interface\_1
* useful\_interface\_2
* better\_capability
* better\_interface
The `provides` section would be:
``` json
"provides": {
"useful_capability": [
"useful_interface_1",
"useful_interface_2" ],
"better_capability": [
"better_interface" ],
}
```
#### requires (dictionary)
This optional section is also a dictionary, keyed by remote service
names (the service name must match the "name" value in the remote service's
manifest). Each value is a list of capabilities required by this service
from the listed remote service. This section does not name interfaces,
only capabilities.
For example, if our capability requires service "some_capability" from
service "another_service", the "requires" section will look like this:
``` json
"requires": {
"another_service": [ "some_capability" ]
```
An asterisk is a wildcard which means that any listed capabilities are
required of any service that provides them. For example:
``` json
"requires": {
"*": [ "some_capability" ]
```
In the above example, this service can access any interface provided as part
of a capability named "some_capability" in any service on the system.
While generally discouraged, there are use cases for wildcards.
Consider building something like a UI shell with a launcher that wants to
tell any service "please launch with some default UI". The services providing
a "launch" capability would be expected to include access to an
"`app_launcher.mojom.Launcher`" interface as part of that capability, with an
implementation that does something useful like open some default UI for the
service:
``` json
"provides": {
"launch": [ "app_launcher.mojom.Launcher" ]
}
```
Then our app launcher service would expect to be able to bind
`app_launcher.mojom.Launcher` in any service that provides that capability:
``` json
"requires": {
"*" : [ "launch" ]
}
```
### required\_files (dictionary)
Allows the (sandboxed) service to specify a list of platform-specific files it
needs to access from disk while running. Each file is keyed by an arbitrary
name chosen by the service, and references a file path relative to the Service
Manager embedder (e.g. the Chrome binary) at runtime.
Files specified here will be opened by the Service Manager before launching a
new instance of this service, and their opened file descriptors will be passed
to the new sandboxed process. The file descriptors may be accessed via
`base::FileDescriptorStore` using the corresponding key string from the
manifest.
**Note:** This is currently only supported on Android and Linux-based desktop
builds.
#### path (string)
Path to the file relative to the executable location at runtime.
#### platform (string)
The platform this file is required on.
Possible values:
* `linux`
* `android`