blob: 18c5d3cf419dcc152341d1fbaa68742670404b74 [file] [log] [blame] [view]
Ken Rockotab035122019-02-06 00:35:241# Intro to Mojo & Services
2
3[TOC]
4
5## Overview
6
7This document contains the minimum amount of information needed for a developer
8to start using Mojo effectively in Chromium, with example Mojo interface usage,
9service definition and hookup, and a brief overview of the Content layer's core
10services.
11
12See other [Mojo & Services](/docs/README.md#Mojo-Services) documentation
13for introductory guides, API references, and more.
14
15## Mojo Terminology
16
17A **message pipe** is a pair of **endpoints**. Each endpoint has a queue of
18incoming messages, and writing a message at one endpoint effectively enqueues
19that message on the other (**peer**) endpoint. Message pipes are thus
20bidirectional.
21
22A **mojom** file describes **interfaces**, which are strongly-typed collections
23of **messages**. Each interface message is roughly analogous to a single proto
24message, for developers who are familiar with Google protobufs.
25
26Given a mojom interface and a message pipe, one of the endpoints
27can be designated as an **InterfacePtr** and is used to *send* messages described by
28the interface. The other endpoint can be designated as a **Binding** and is used
29to *receive* interface messages.
30
31*** aside
32NOTE: The above generalization is a bit oversimplified. Remember that the
33message pipe is still bidirectional, and it's possible for a mojom message to
34expect a reply. Replies are sent from the Binding endpoint and received by the
35InterfacePtr endpoint.
36***
37
38The Binding endpoint must be associated with (*i.e.* **bound** to) an
39**implementation** of its mojom interface in order to process received messages.
40A received message is dispatched as a scheduled task invoking the corresponding
41interface method on the implementation object.
42
43Another way to think about all this is simply that **an InterfacePtr makes
44calls on a remote implementation of its interface associated with a
45corresponding remote Binding.**
46
47## Example: Defining a New Frame Interface
48
49Let's apply this to Chrome. Suppose we want to send a "Ping" message from a
50render frame to its corresponding `RenderFrameHostImpl` instance in the browser
51process. We need to define a nice mojom interface for this purpose, create a
52pipe to use that interface, and then plumb one end of the pipe to the right
53place so the sent messages can be received and processed there. This section
54goes through that process in detail.
55
56### Defining the Interface
57
58The first step involves creating a new `.mojom` file with an interface
59definition, like so:
60
61``` cpp
62// src/example/public/mojom/ping_responder.mojom
63module example.mojom;
64
65interface PingResponder {
66 // Receives a "Ping" and responds with a random integer.
67 Ping() => (int random);
68};
69```
70
71This should have a corresponding build rule to generate C++ bindings for the
72definition here:
73
74``` python
75# src/example/public/mojom/BUILD.gn
76import "mojo/public/tools/bindings/mojom.gni"
77mojom("mojom") {
78 sources = [ "ping_responder.mojom" ]
79}
80```
81
82### Creating the Pipe
83
84Now let's create a message pipe to use this interface.
85
86*** aside
87As a general rule and as a matter of convenience when
88using Mojo, the *client* of an interface (*i.e.* the InterfacePtr side) is
89typically the party who creates a new pipe. This is convenient because the
90InterfacePtr may be used to start sending messages immediately without waiting
91for the InterfaceRequest endpoint to be transferred or bound anywhere.
92***
93
94This code would be placed somewhere in the renderer:
95
96```cpp
97example::mojom::PingResponderPtr ping_responder;
98example::mojom::PingResponderRequest request =
99 mojo::MakeRequest(&ping_responder);
100```
101
102In this example, ```ping_responder``` is the InterfacePtr, and ```request```
103is an InterfaceRequest, which is a Binding precursor that will eventually
104be turned into a Binding. `mojo::MakeRequest` is the most common way to create
105a message pipe: it yields both endpoints as strongly-typed objects, with the
106`InterfacePtr` as an output argument and the `InterfaceRequest` as the return
107value.
108
109*** aside
110NOTE: Every mojom interface `T` generates corresponding C++ type aliases
111`TPtr = InterfacePtr<T>` and `TRequest = InterfaceRequest<T>`. Chromium code
112almost exclusively uses these aliases instead of writing out the more verbose
113templated name.
114
115Also note that an InterfaceRequest doesn't actually **do** anything. It is an
116inert holder of a single message pipe endpoint. It exists only to make its
117endpoint more strongly-typed at compile-time, indicating that the endpoint
118expects to be bound by a Binding of the same interface type.
119***
120
121### Sending a Message
122
123Finally, we can call the `Ping()` method on our InterfacePtr to send a message:
124
125```cpp
126ping_responder->Ping(base::BindOnce(&OnPong));
127```
128
129*** aside
130**IMPORTANT:** If we want to receive the the response, we must keep the
131`ping_responder` object alive until `OnPong` is invoked. After all,
132`ping_responder` *owns* its message pipe endpoint. If it's destroyed then so is
133the endpoint, and there will be nothing to receive the response message.
134***
135
136We're almost done! Of course, if everything were this easy, this document
137wouldn't need to exist. We've taken the hard problem of sending a message from
138a renderer process to the browser process, and transformed it into a problem
139where we just need to take the `request` object from above and pass it to the
140browser process somehow where it can be turned into a Binding that dispatches
141its received messages.
142
143### Sending an InterfaceRequest to the Browser
144
145It's worth noting that InterfaceRequests (and message pipe endpoints in general)
146are just another type of object that can be freely sent over mojom messages.
147The most common way to get an InterfaceRequest somewhere is to pass it as a
148method argument on some other already-connected interface.
149
150One such interface which we always have connected between a renderer's
151`RenderFrameImpl` and its corresponding `RenderFrameHostImpl` in the browser
152is
153[`DocumentInterfaceBroker`](https://cs.chromium.org/chromium/src/third_party/blink/public/mojom/frame/document_interface_broker.mojom).
154We can update this definition to add support for our new PingResponder
155interface:
156
157``` cpp
158interface DocumentInterfaceBroker {
159 ...
160
161 GetPingResponder(PingResponder& responder);
162}
163```
164
165The `&` syntax is not a reference! In mojom it denotes an InterfaceRequest.
166Specifically in this case, the `GetPingResponder` takes a single
167`PingResponderRequest` argument. If the `&` were omitted, this would instead
168take a `PingResponderPtr`.
169
170Now the renderer can call this method with the `request` object it created
171earlier via `mojo::MakeRequest`:
172
173``` cpp
174RenderFrame* my_frame = GetMyFrame();
175my_frame->GetDocumentInterfaceBroker()->GetPingResponder(std::move(request));
176```
177
178This will transfer the PingResponderRequest endpoint to the browser process
179where it will be received by the corresponding `DocumentInterfaceBroker`
180implementation. More on that below.
181
182### Implementing the Interface
183
184Finally, we need a browser-side implementation of our `PingResponder` interface
185as well as an implementation of the new
186`DocumentInterfaceBroker.GetPingResponder` message. Let's implement
187`PingResponder` first:
188
189```cpp
190#include "example/public/mojom/ping_responder.mojom.h"
191
192class PingResponderImpl : example::mojom::PingResponder {
193 public:
194 explicit PingResponderImpl(example::mojom::PingResponderRequest request)
195 : binding_(this, std::move(request)) {}
196
197 // example::mojom::PingResponder:
198 void Ping(PingCallback callback) override {
199 // Respond with a random 4, chosen by fair dice roll.
200 std::move(callback).Run(4);
201 }
202
203 private:
204 mojo::Binding<example::mojom::PingResponder> binding_;
205
206 DISALLOW_COPY_AND_ASSIGN(PingResponderImpl);
207};
208```
209
210And conveniently `RenderFrameHostImpl` implements `DocumentInterfaceBroker`, and
211any calls made on the object returned by
212`RenderFrameImpl::GetDocumentInterfaceBroker()' will be routed directly to the
213`RenderFrameHostImpl`. So the only thing left to do is update
214`RenderFrameHostImpl` to implement `GetPingResponder`. If you forget to do this
215the compiler will complain anyway, because generated mojom interface methods are
216pure virtual methods in C++.
217
218``` cpp
219// render_frame_host_impl.h
220class RenderFrameHostImpl
221 ...
222 void GetPingResponder(example::mojom::PingResponderRequest request) override;
223 ...
224 private:
225 ...
226 std::unique_ptr<PingResponderImpl> ping_responder_;
227 ...
228};
229
230// render_frame_host_impl.cc
231void RenderFrameHostImpl::GetPingResponder(
232 example::mojom::PingResponderRequest request) {
233 ping_responder_ = std::make_unique<PingResponderImpl>(std::move(request));
234}
235```
236
237And we're done. This setup is sufficient to plumb a new interface connection
238between a renderer frame and its browser-side host object!
239
240Assuming we kept our `ping_responder` object alive in the renderer long enough,
241we would eventually see its `OnPong` callback invoked with the totally random
242value of `4`, as defined by the browser-side implementation above.
243
244## Services Overview &amp; Terminology
245The previous section only scratches the surface of how Mojo IPC is used in
246Chromium. While renderer-to-browser messaging is simple and possibly the most
247prevalent usage by sheer code volume, we are incrementally decomposing the
248codebase into a set of services with a bit more granularity than the traditional
249Content browser/renderer/gpu/utility process split.
250
251A **service** is a self-contained library of code which implements one or more
252related features or behaviors and whose interaction with outside code is done
253*exclusively* through Mojo interface connections facilitated by the **Service
254Manager.**
255
256The **Service Manager** is a component which can run in a dedicated process
257or embedded within another process. Only one Service Manager exists globally
258across the system, and in Chromium the browser process runs an embedded Service
259Manager instance immediately on startup. The Service Manager spawns
260**service instances** on-demand, and it routes each interface request from a
261service instance to some destination instance of the Service Manager's choosing.
262
263Each service instance implements the
264[**`Service`**](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/service.h)
265interface to receive incoming interface requests brokered by the Service
266Manager, and each service instance has a
267[**`Connector`**](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/connector.h)
268it can use to issue interface requests to other services via the
269Service Manager.
270
271Every service has a **manifest** which declares some static metadata about the
272service. This metadata is used by the Service Manager for various purposes,
273including as a declaration of what interfaces are exposed to other services in
274the system. This eases the security review process.
275
276Inside its manifest every service declares its **service name**, used to
277identify instances of the service in the most general sense. Names are free-form
278and usually short strings which must be globally unique. Some services defined
279in Chromium today include `"device"`, `"identity"`, and `"network"` services.
280
281For more complete and in-depth coverage of the concepts covered here and other
282related APIs, see the
283[Service Manager documentation](/services/service_manager/README.md).
284
285## Example: Building a Simple Out-of-Process Service
286
287There are multiple steps required to get a new service up and running in
288Chromium. You must:
289
290- Define the `Service` implementation
291- Define the service's manifest
292- Tell Chromium's Service Manager about the manifest
293- Tell Chromium how to instantiate the `Service` implementation when it's needed
294
295This section walks through these steps with some brief explanations. For more
296thorough documentation of the concepts and APIs used herein, see the
297[Service Manager](/services/service_manager/README.md) and
298[Mojo](/mojo/README.md) documentation.
299
300### Defining the Service
301
302Typically service definitions are placed in a `services` directory, either at
303the top level of the tree or within some subdirectory. In this example, we'll
304define a new service for use by Chrome specifically, so we'll define it within
305`//chrome/services`.
306
307We can create the following files. First some mojoms:
308
309``` cpp
310// src/chrome/services/math/public/mojom/constants.mojom
311module math.mojom;
312
313// These are not used by the implementation directly, but will be used in
314// following sections.
315const string kServiceName = "math";
316const string kArithmeticCapability = "arithmetic";
317```
318
319``` cpp
320// src/chrome/services/math/public/mojom/divider.mojom
321module math.mojom;
322
323interface Divider {
324 Divide(int32 dividend, int32 divisor) => (int32 quotient);
325};
326```
327
328``` python
329# src/chrome/services/math/public/mojom/BUILD.gn
330import "mojo/public/tools/bindings/mojom.gni"
331
332mojom("mojom") {
333 sources = [
334 "constants.mojom",
335 "divider.mojom",
336 ]
337}
338```
339
340Then the actual `Service` implementation:
341
342``` cpp
343// src/chrome/services/math/math_service.h
344#include "services/service_manager/public/cpp/service.h"
345
346#include "base/macros.h"
347#include "chrome/services/math/public/mojom/divider.mojom.h"
348
349namespace math {
350
351class MathService : public service_manager::Service,
352 public mojom::Divider {
353 public:
354 explicit MathService(service_manager::mojom::ServiceRequest request);
355 ~MathService() override;
356
357 private:
358 // service_manager::Service:
359 void OnBindInterface(const service_manager::BindSourceInfo& source,
360 const std::string& interface_name,
361 mojo::ScopedMessagePipeHandle interface_pipe) override;
362
363 // mojom::Divider:
364 void Divide(int32_t dividend,
365 int32_t divisor,
366 DivideCallback callback) override;
367
368 service_manager::ServiceBinding service_binding_;
369
370 // You could also use a Binding. We use BindingSet to conveniently allow
371 // multiple clients to bind to the same instance of this class. See Mojo
372 // C++ Bindings documentation for more information.
373 mojo::BindingSet<mojom::Divider> divider_bindings_;
374
375 DISALLOW_COPY_AND_ASSIGN(MathService);
376};
377
378} // namespace math
379```
380
381``` cpp
382// src/chrome/services/math/math_service.cc
383#include "chrome/services/math/math_service.h"
384
385namespace math {
386
387MathService::MathService(service_manager::ServiceRequest request)
388 : service_binding_(this, std::move(request)) {}
389
390MathService::~MathService() = default;
391
392void MathService::OnBindInterface(
393 const service_manager::BindSourceInfo& source,
394 const std::string& interface_name,
395 mojo::ScopedMessagePipeHandle interface_pipe) {
396 // Note that services typically use a service_manager::BinderRegistry if they
397 // plan on handling many different interface request types.
398 if (interface_name == mojom::Divider::Name_) {
399 divider_bindings_.AddBinding(
400 this, mojom::DividerRequest(std::move(interface_pipe)));
401 }
402}
403
404void MathService::Divide(int32_t dividend,
405 int32_t divisor,
406 DivideCallback callback) {
407 // Respond with the quotient!
408 callback.Run(dividend / divisor);
409}
410
411} // namespace math
412```
413
414``` python
415# src/chrome/services/math/BUILD.gn
416
417source_set("math") {
418 sources = [
419 "math.cc",
420 "math.h",
421 ]
422
423 deps = [
424 "//base",
425 "//chrome/services/math/public/mojom",
426 "//services/service_manager/public/cpp",
427 ]
428}
429```
430
431Now we have a fully defined `math` service implementation, including a nice
432little `Divider` interface for clients to play with. Next we need to define the
433service's manifest to declare how the service can be used.
434
435### Defining the Manifest
436Manifests are defined as
437[`Manifest`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/manifest.h)
438objects, typically built using a
439[`ManifestBuilder`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/manifest_builder.h). As a general rule, services should define their manifest
440in a dedicated `source_set` or `component` target under their `public/cpp`
441subdirectory (typically referred to as the service's **C++ client library**).
442
443We can create the following files for this purpose:
444
445``` cpp
446// src/chrome/services/math/public/cpp/manifest.h
447#include "services/service_manager/public/cpp/manifest.h"
448
449namespace math {
450
451const service_manager::Manifest& GetManifest();
452
453} // namespace math
454```
455
456``` cpp
457// src/chrome/services/math/public/cpp/manifest.cc
458#include "chrome/services/math/public/cpp/manifest.h"
459
460#include "base/no_destructor.h"
461#include "chrome/services/math/public/mojom/constants.mojom.h"
462#include "chrome/services/math/public/mojom/divider.mojom.h"
463#include "services/service_manager/public/cpp/manifest_builder.h"
464
465namespace math {
466
467const service_manager::Manifest& GetManifest() {
468 static base::NoDestructor<service_manager::Manifest> manifest{
469 service_manager::ManifestBuilder()
470 .WithServiceName(mojom::kServiceName)
471 .ExposeCapability(
472 mojom::kArithmeticCapability,
473 service_manager::Manifest::InterfaceList<mojom::Divider>())
474 .Build()};
475 return *manifest
476}
477
478} // namespace math
479```
480
481We also need to define a build target for our manifest sources:
482
483``` python
484# src/chrome/services/math/public/cpp/BUILD.gn
485
486source_set("manifest") {
487 sources = [
488 "manifest.cc",
489 "manifest.h",
490 ]
491
492 deps = [
493 "//base",
494 "//chrome/services/math/public/mojom",
495 "//services/service_manager/public/cpp",
496 ]
497}
498```
499
500The above `Manifest` definition declares that the service is named `math` and
501that it **exposes** a single **capability** named `arithmetic` which allows
502access to the `Divider` interface.
503
504Another service may **require** this capability from its own manifest in order
505for the Service Manager to grant it access to a `Divider`. We'll see this a
506few sections below. First, let's get the manifest and service implementation
507registered with Chromium's Service Manager.
508
509### Registering the Manifest
510
511For the most common out-of-process service cases, we register service manifests
512by **packaging** them in Chrome. This can be done by augmenting the value
513returned by
514[`GetChromePackagedServiceManifests`](https://cs.chromium.org/chromium/src/chrome/app/chrome_packaged_service_manifests.cc?rcl=af43cabf3c01e28be437becb972a7eae44fd54e8&l=133).
515
516We can add our manifest there:
517
518``` cpp
519// Deep within src/chrome/app/chrome_packaged_service_manifests.cc...
520const std::vector<service_manager::Manifest>
521GetChromePackagedServiceManifests() {
522 ...
523 math::GetManifest(),
524 ...
525```
526
527And don't forget to add a GN dependency from
528`//chrome/app:packaged_service_manifests` onto
529`//chrome/services/math/public/cpp:manifest`!
530
531We're almost done with service setup. The last step is to teach Chromium (and
532thus the Service Manager) how to launch an instance of our beautiful `math`
533service.
534
535### Hooking Up the Service Implementation
536
537There are two parts to this for an out-of-process Chrome service.
538
539First, we need
540to inform the embedded Service Manager that this service is an out-of-process
541service. The goofiness of this part is a product of some legacy issues and it
542should be eliminated soon, but for now it just means teaching the Service
543Manager how to *label* the process it creates for this service (e.g. how the process will
544appear in the system task manager). We modify
545[`ChromeContentBrowserClient::RegisterOutOfProcessServices`](https://cs.chromium.org/chromium/src/chrome/browser/chrome_content_browser_client.cc?rcl=960886a7febcc2acccea7f797d3d5e03a344a12c&l=3766)
546for this:
547
548``` cpp
549void ChromeContentBrowserClient::RegisterOutOfProcessServices(
550 OutOfProcessServicesMap* services) {
551 ...
552
553 (*services)[math::mojom::kServiceName] =
554 base::BindRepeating([]() -> base::string16 {
555 return "Math Service";
556 });
557
558 ...
559}
560```
561
562And finally, since nearly all out-of-process services run in a "utility" process
563today, we need to add a dependency on our actual `Service` implementation to
564Chrome's service spawning code within the utility process.
565
566For this step we just modify
567[`ChromeContentUtilityClient::MaybeCreateMainThreadService`](https://cs.chromium.org/chromium/src/chrome/utility/chrome_content_utility_client.cc?rcl=7226adebd6e8d077d673a82acf1aab0790627178&l=261)
568by adding a block of code as follows:
569
570``` cpp
571void ChromeContentUtilityClient::MaybeCreateMainThreadService(
572 const std::string& service_name,
573 service_manager::mojom::ServiceRequest request) {
574 ...
575
576 if (service_name == math::mojom::kServiceName)
577 return std::make_unique<math::MathService>(std::move(request));
578
579 ...
580}
581```
582
583And we're done!
584
585As one nice follow-up step, let's use our math service from the browser.
586
587### Using the Service
588
589We can grant the browser process access to our `Divider` interface by
590**requiring** the `math` service's `arithmetic` capability within the
591`content_browser` service manifest.
592
593*** aside
594NOTE: See the following section for an elaboration on what `content_browser` is.
595For the sake of this example, it's magic.
596***
597
598For Chrome-specific features such as our glorious new `math` service, we can
599amend the `content_browser` manifest by modifying
600[GetChromeContentBrowserOverlayManifest](https://cs.chromium.org/chromium/src/chrome/app/chrome_content_browser_overlay_manifest.cc?rcl=38db90321e8e3627b2f3165cdb051fa8d668af48&l=100)
601as follows:
602
603``` cpp
604// src/chrome/app/chrome_content_browser_overlay_manifest.cc
605
606...
607const service_manager::Manifest& GetChromeContentBrowserOverlayManifest() {
608 ...
609 .RequireCapability(math::mojom::kServiceName,
610 math::mojom::kArithmeticCapability)
611 ...
612}
613```
614
615Finally, we can use the global `content_browser` instance's `Connector` to send
616an interface request to our service. This is accessible from the main thread of
617the browser process. Somewhere in `src/chrome/browser`, we can write:
618
619``` cpp
620// This gives us the global content_browser's Connector
621service_manager::Connector* connector =
622 content::ServiceManagerConnection::GetForProcess()->GetConnector();
623
624// Recall from the earlier Mojo section that mojo::MakeRequest creates a new
625// message pipe for our interface. Connector passes the request endpoint to
626// the Service Manager along with the name of our target service, "math".
627math::mojom::DividerPtr divider;
628connector->BindInterface(math::mojom::kServiceName,
629 mojo::MakeRequest(&divider));
630
631// As a client, we do not have to wait for any acknowledgement or confirmation
632// of a connection. We can start queueing messages immediately and they will be
633// delivered as soon as the service is up and running.
634divider->Divide(
635 42, 6, base::BindOnce([](int32_t quotient) { LOG(INFO) << quotient; }));
636```
637
638This should successfully spawn a new process to run the `math` service if it's
639not already running, then ask it to do a division, and ultimately log the result
640after it's sent back to the browser process.
641
642Finally it's worth reiterating that every service instance in the system has
643its own `Connector` and there's no reason we have to limit ourselves to
644`content_browser` as the client, as long as the appropriate manifest declares
645that it requires our `arithmetic` capability.
646
647If we did not update the `content_browser` manifest overlay as we did in this
648example, the `Divide` call would never reach the `math` service (in fact the
649service wouldn't even be started) and instead we'd get an error message (or in
650developer builds, an assertion failure) informing us that the Service Manager
651blocked the `BindInterface` call.
652
653## Content-Layer Services Overview
654
655Apart from very early initialization steps in the browser process, every bit of
656logic in Chromium today is effectively running as part of one service instance
657or another.
658
659Although we continue to migrate parts of the browser's privileged
660functionality to more granular services defined below the Content layer, the
661main services defined in Chromium today continue to model the Content layer's
662classical multiprocess architecture which defines a handful of
663**process types**: browser, renderer, gpu, utility, and plugin processes. For
664each of these process types, we now define corresponding services.
665
666Manifest definitions for all of the following services can be found in
667`//content/public/app`.
668
669### The Browser Service
670
671`content_browser` is defined to encapsulate general-purpose browser process
672code. There are multiple instances of this service, all running within the
673singular browser process. There is one shared global instance as well an
674additional instance for each `BrowserContext` (*i.e.* per Chrome profile).
675
676The global instance exists primarily so that arbitrary browser process code can
677reach various system services conveniently via a global `Connector` instance
678on the main thread.
679
680Each instance associated with a `BrowserContext` is placed in an isolated
681instance group specific to that `BrowserContext`. This limits the service
682instances with which its `Connector` can make contact. These instances are
683used primarily to facilitate the spawning of other isolated per-profile service
684instances, such as renderers and plugins.
685
686### The Renderer Service
687
688A `content_renderer` instance is spawned in its own sandboxed process for every
689site-isolated instance of Blink we require. Instances are placed in the same
690instance group as the renderer's corresponding `BrowserContext`, *i.e.* the
691profile which navigated to the site being rendered.
692
693Most interfaces used by `content_renderer` are not brokered through the Service
694Manager but instead are brokered through dedicated interfaces implemented by
695`content_browser`, with which each renderer maintains persistent connections.
696
697### The GPU Service
698
699Only a single instance of `content_gpu` exists at a time and it always runs in
700its own isolated, sandboxed process. This service hosts the code in content/gpu
701and whatever else Content's embedder adds to that for GPU support.
702
703### The Plugin Service
704
705`content_plugin` hosts a plugin in an isolated process. Similarly to
706`content_renderer` instances, each instance of `content_plugin` belongs to
707an instance group associated with a specific `BrowserContext`, and in general
708plugins get most of their functionality by talking directly to `content_browser`
709rather than brokering interface requests through the Service Manager.
710
711### The Utility Service
712
713`content_utility` exists only nominally today, as there is no remaining API
714surface within Content which would allow a caller to explicitly create an
715instance of it. Instead, this service is used exclusively to bootstrap new
716isolated processes in which other services will run.
717
718## Exposing Interfaces Between Content Processes
719
720Apart from the standard Service Manager APIs, the Content layer defines a number
721of additional concepts for Content and its embedder to expose interfaces
722specifically between Content processes in various contexts.
723
724### Exposing Browser Interfaces to Renderer Documents and Workers
725
726Documents and workers are somewhat of a special case since interface access
727decisions often require browser-centric state that the Service Manager cannot
728know about, such as details of the current `BrowserContext`, the origin of the
729renderered content, installed extensions in the renderer, *etc.* For this
730reason, interface brokering decisions are increasingly being made by the
731browser.
732
733There are two ways this is done: the Deprecated way and the New way.
734
735#### The Deprecated Way: InterfaceProvider
736
737This is built on the concept of **interface filters** and the
738**`InterfaceProvider`** interface. It is **deprecated** and new features should
739use [The New Way](#The-New-Way_Interface-Brokers) instead. This section only
740briefly covers practical usage in Chromium.
741
742The `content_browser` manifest exposes capabilities on a few named interface
743filters, the main one being `"navigation:frame"`. There are others scoped to
744different worker contexts, *e.g.* `"navigation:service_worker"`.
745`RenderProcessHostImpl` or `RenderFrameHostImpl` sets up an `InterfaceProvider`
746for each known execution context in the corresponding renderer, filtered through
747the Service Manager according to one of the named filters.
748
749The practical result of all this means the interface must be listed in the
750`content_browser` manifest under the
751`ExposeInterfaceFilterCapability_Deprecated("navigation:frame", "renderer", ...)`
752entry, and a corresponding interface request handler must be registered with the
753host's `registry_` in
754[`RenderFrameHostImpl::RegisterMojoInterfaces`](https://cs.chromium.org/chromium/src/content/browser/frame_host/render_frame_host_impl.cc?rcl=0a23c78c57ecb2405837155aa0a0def7b5ba9c22&l=3971)
755
756Similarly for worker contexts, an interface must be exposed by the `"renderer"`
757capability on the corresponding interface filter
758(*e.g.*, `"navigation:shared_worker"`) and a request handler must be registered
759within
760[`RendererInterfaceBinders::InitializeParameterizedBinderRegistry`](https://cs.chromium.org/chromium/src/content/browser/renderer_interface_binders.cc?rcl=0a23c78c57ecb2405837155aa0a0def7b5ba9c22&l=116).
761
762The best way to understand all of this after reading this section is to look at
763the linked code above and examine a few examples. They are fairly repetitive.
764For additional convenience, here is also a link to the `content_browser`
765[manifest](https://cs.chromium.org/chromium/src/content/public/app/content_browser_manifest.cc).
766
767#### The New Way: Interface Brokers
768
769*** aside
770In classic Google tradition, the New Way is not entirely ready yet. As of this
771writing, worker-scoped interfaces must still use the Old Way described above.
772***
773
774Rather than the confusing spaghetti of interface filter logic, we now define an
775explicit mojom interface with a persistent connection between a renderer's
776frame object and the corresponding `RenderFrameHostImpl` in the browser process.
777This interface is called
778[`DocumentInterfaceBroker`](https://cs.chromium.org/chromium/src/third_party/blink/public/mojom/frame/document_interface_broker.mojom?rcl=ea6921f717f21e9a72d321a15c4bf50d47d10310&l=11)
779and is fairly easy to work with: you simply add a new factory method to the
780interface definition:
781
782``` cpp
783interface DocumentInterfaceBroker {
784 ...
785
786 GetGoatTeleporter(magic.mojom.GoatTeleporter& request);
787};
788```
789
790and implement this new method on `RenderFrameHostImpl`, which is an
791implementation (**the** production implementation) of
792`DocumentInterfaceBroker`:
793
794``` cpp
795void RenderFrameHostImpl::GetGoatTeleporter(
796 magic::mojom::GoatTeleporterRequest request) {
797 goat_teleporter_binding_.Bind(std::move(request));
798}
799```
800
801### Exposing Browser Interfaces to Render Processes
802
803Sometimes (albeit rarely) it's useful to expose a browser interface directly to
804a renderer process. This can be done as for any other interface exposed between
805two services. In this specific instance, the `content_browser` manifest exposes
806a capability named `"renderer"` which `content_renderer` requires. Any interface
807listed as part of that capability can be accessed by a `content_renderer`
808instance by using its own `Connector`. See below.
809
810### Exposing Browser Interfaces to Content Child Processes
811
812All Content child process types (renderer, GPU, and plugin) share a common API
813to interface with the Service Manager. Their Service Manager connection is
814initialized and maintained by `ChildThreadImpl` on process startup, and from
815the main thread, you can access the process's `Connector` as follows:
816
817``` cpp
818auto* connector = content::ChildThread::Get()->GetConnector();
819
820// For example...
821connector->BindInterface(content::mojom::kBrowserServiceName,
822 std::move(some_request));
823```
824
825### Exposing Content Child Process Interfaces to the Browser
826
827Content child processes may also expose interfaces to the browser, though this
828is much less common and requires a fair bit of caution since the browser must be
829careful to only call `Connector.BindInterface` in these cases with an exact
830`service_manager::Identity` to avoid unexpected behavior.
831
832Every child process provides a subclass of ChildThreadImpl, and this can be used
833to install a new `ConnectionFilter` on the process's Service Manager connection
834before starting to accept requests.
835
836This behavior should really be considered deprecated, but for posterity, here is
837how the GPU process does it:
838
8391. [Disable Service Manager connection auto-start](https://cs.chromium.org/chromium/src/content/gpu/gpu_child_thread.cc?rcl=6b85a56334c0cd64b0e657934060de716714ca64&l=62)
8402. [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)
8413. [Start the Service Manager connection manually](https://cs.chromium.org/chromium/src/content/gpu/gpu_child_thread.cc?rcl=6b85a56334c0cd64b0e657934060de716714ca64&l=257)
842
843It's much more common instead for there to be some primordial interface
844connection established by the child process which can then be used to facilitate
845push communications from the browser, so please consider not duplicating this
846behavior.
847
848## Additional Support
849
850If this document was not helpful in some way, please post a message to your
851friendly
852[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
853or
854[services-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev)
855mailing list.