blob: c1827b01e21dc59668b111dd62bc82c8e44cebd2 [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
Darwin Huangb4bd2452019-10-08 22:56:0427can be designated as a **`Remote`** and is used to *send* messages described by
28the interface. The other endpoint can be designated as a **`Receiver`** and is used
Ken Rockotab035122019-02-06 00:35:2429to *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
Darwin Huangb4bd2452019-10-08 22:56:0434expect a reply. Replies are sent from the `Receiver` endpoint and received by the
35`Remote` endpoint.
Ken Rockotab035122019-02-06 00:35:2436***
37
Darwin Huangb4bd2452019-10-08 22:56:0438The `Receiver` endpoint must be associated with (*i.e.* **bound** to) an
Ken Rockotab035122019-02-06 00:35:2439**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
Darwin Huangb4bd2452019-10-08 22:56:0443Another way to think about all this is simply that **a `Remote` makes
Ken Rockotab035122019-02-06 00:35:2444calls on a remote implementation of its interface associated with a
Darwin Huangb4bd2452019-10-08 22:56:0445corresponding remote `Receiver`.**
Ken Rockotab035122019-02-06 00:35:2446
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.
Ken Rockota0cb6cf92019-03-26 16:40:4267 Ping() => (int32 random);
Ken Rockotab035122019-02-06 00:35:2468};
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
Ken Rockota0cb6cf92019-03-26 16:40:4276import("//mojo/public/tools/bindings/mojom.gni")
Ken Rockotab035122019-02-06 00:35:2477mojom("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
Darwin Huangb4bd2452019-10-08 22:56:0488using Mojo, the *client* of an interface (*i.e.* the `Remote` side) is
Ken Rockotab035122019-02-06 00:35:2489typically the party who creates a new pipe. This is convenient because the
Darwin Huangb4bd2452019-10-08 22:56:0490`Remote` may be used to start sending messages immediately without waiting
Ken Rockotab035122019-02-06 00:35:2491for the InterfaceRequest endpoint to be transferred or bound anywhere.
92***
93
94This code would be placed somewhere in the renderer:
95
96```cpp
Darwin Huangb4bd2452019-10-08 22:56:0497// src/third_party/blink/example/public/ping_responder.h
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:4098mojo::Remote<example::mojom::PingResponder> ping_responder;
99mojo::PendingReceiver<example::mojom::PingResponder> receiver =
100 ping_responder.BindNewPipeAndPassReceiver();
Ken Rockotab035122019-02-06 00:35:24101```
102
Darwin Huangb4bd2452019-10-08 22:56:04103In this example, ```ping_responder``` is the `Remote`, and ```receiver```
104is a `PendingReceiver`, which is a `Receiver` precursor that will eventually
105be turned into a `Receiver`. `BindNewPipeAndPassReceiver` is the most common way to create
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40106a message pipe: it yields the `PendingReceiver` as the return
Ken Rockotab035122019-02-06 00:35:24107value.
108
109*** aside
Darwin Huangb4bd2452019-10-08 22:56:04110NOTE: A `PendingReceiver` doesn't actually **do** anything. It is an
Ken Rockotab035122019-02-06 00:35:24111inert holder of a single message pipe endpoint. It exists only to make its
112endpoint more strongly-typed at compile-time, indicating that the endpoint
Darwin Huangb4bd2452019-10-08 22:56:04113expects to be bound by a `Receiver` of the same interface type.
Ken Rockotab035122019-02-06 00:35:24114***
115
116### Sending a Message
117
Darwin Huangb4bd2452019-10-08 22:56:04118Finally, we can call the `Ping()` method on our `Remote` to send a message:
Ken Rockotab035122019-02-06 00:35:24119
120```cpp
Darwin Huangb4bd2452019-10-08 22:56:04121// src/third_party/blink/example/public/ping_responder.h
Ken Rockotab035122019-02-06 00:35:24122ping_responder->Ping(base::BindOnce(&OnPong));
123```
124
125*** aside
Darwin Huangb4bd2452019-10-08 22:56:04126**IMPORTANT:** If we want to receive the response, we must keep the
Ken Rockotab035122019-02-06 00:35:24127`ping_responder` object alive until `OnPong` is invoked. After all,
128`ping_responder` *owns* its message pipe endpoint. If it's destroyed then so is
129the endpoint, and there will be nothing to receive the response message.
130***
131
132We're almost done! Of course, if everything were this easy, this document
133wouldn't need to exist. We've taken the hard problem of sending a message from
134a renderer process to the browser process, and transformed it into a problem
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40135where we just need to take the `receiver` object from above and pass it to the
Darwin Huangb4bd2452019-10-08 22:56:04136browser process somehow where it can be turned into a `Receiver` that dispatches
Ken Rockotab035122019-02-06 00:35:24137its received messages.
138
Darwin Huangb4bd2452019-10-08 22:56:04139### Sending a `PendingReceiver` to the Browser
Ken Rockotab035122019-02-06 00:35:24140
Darwin Huangb4bd2452019-10-08 22:56:04141It's worth noting that `PendingReceiver`s (and message pipe endpoints in general)
Ken Rockotab035122019-02-06 00:35:24142are just another type of object that can be freely sent over mojom messages.
Darwin Huangb4bd2452019-10-08 22:56:04143The most common way to get a `PendingReceiver` somewhere is to pass it as a
Ken Rockotab035122019-02-06 00:35:24144method argument on some other already-connected interface.
145
146One such interface which we always have connected between a renderer's
147`RenderFrameImpl` and its corresponding `RenderFrameHostImpl` in the browser
148is
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40149[`BrowserInterfaceBroker`](https://cs.chromium.org/chromium/src/third_party/blink/public/mojom/browser_interface_broker.mojom).
150This interface is a factory for acquiring other interfaces. Its `GetInterface`
151method takes a `GenericPendingReceiver`, which allows passing arbitrary
152interface receivers.
Ken Rockotab035122019-02-06 00:35:24153
154``` cpp
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40155interface BrowserInterfaceBroker {
156 GetInterface(mojo_base.mojom.GenericPendingReceiver receiver);
Ken Rockotab035122019-02-06 00:35:24157}
158```
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40159Since `GenericPendingReceiver` can be implicitly constructed from any specific
Darwin Huangb4bd2452019-10-08 22:56:04160`PendingReceiver`, it can call this method with the `receiver` object it created
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40161earlier via `BindNewPipeAndPassReceiver`:
Ken Rockotab035122019-02-06 00:35:24162
163``` cpp
164RenderFrame* my_frame = GetMyFrame();
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40165my_frame->GetBrowserInterfaceBrokerProxy()->GetInterface(std::move(receiver));
Ken Rockotab035122019-02-06 00:35:24166```
167
Darwin Huangb4bd2452019-10-08 22:56:04168This will transfer the `PendingReceiver` endpoint to the browser process
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40169where it will be received by the corresponding `BrowserInterfaceBroker`
Ken Rockotab035122019-02-06 00:35:24170implementation. More on that below.
171
172### Implementing the Interface
173
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40174Finally, we need a browser-side implementation of our `PingResponder` interface.
Ken Rockotab035122019-02-06 00:35:24175
176```cpp
177#include "example/public/mojom/ping_responder.mojom.h"
178
179class PingResponderImpl : example::mojom::PingResponder {
180 public:
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40181 explicit PingResponderImpl(mojo::PendingReceiver<example::mojom::PingResponder> receiver)
182 : receiver_(this, std::move(receiver)) {}
Ken Rockotab035122019-02-06 00:35:24183
184 // example::mojom::PingResponder:
185 void Ping(PingCallback callback) override {
186 // Respond with a random 4, chosen by fair dice roll.
187 std::move(callback).Run(4);
188 }
189
190 private:
Charlie Hud4c0fe82019-10-08 19:48:13191 mojo::Receiver<example::mojom::PingResponder> receiver_;
Ken Rockotab035122019-02-06 00:35:24192
193 DISALLOW_COPY_AND_ASSIGN(PingResponderImpl);
194};
195```
196
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40197`RenderFrameHostImpl` owns an implementation of `BrowserInterfaceBroker`.
198When this implementation receives a `GetInterface` method call, it calls
199the handler previously registered for this specific interface.
Ken Rockotab035122019-02-06 00:35:24200
201``` cpp
202// render_frame_host_impl.h
203class RenderFrameHostImpl
204 ...
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40205 void GetPingResponder(mojo::PendingReceiver<example::mojom::PingResponder> receiver);
Ken Rockotab035122019-02-06 00:35:24206 ...
207 private:
208 ...
209 std::unique_ptr<PingResponderImpl> ping_responder_;
210 ...
211};
212
213// render_frame_host_impl.cc
214void RenderFrameHostImpl::GetPingResponder(
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40215 mojo::PendingReceiver<example::mojom::PingResponder> receiver) {
216 ping_responder_ = std::make_unique<PingResponderImpl>(std::move(receiver));
217}
218
219// browser_interface_binders.cc
220void PopulateFrameBinders(RenderFrameHostImpl* host,
221 service_manager::BinderMap* map) {
222...
223 // Register the handler for PingResponder.
224 map->Add<example::mojom::PingResponder>(base::BindRepeating(
225 &RenderFrameHostImpl::GetPingResponder, base::Unretained(host)));
Ken Rockotab035122019-02-06 00:35:24226}
227```
228
229And we're done. This setup is sufficient to plumb a new interface connection
230between a renderer frame and its browser-side host object!
231
232Assuming we kept our `ping_responder` object alive in the renderer long enough,
233we would eventually see its `OnPong` callback invoked with the totally random
234value of `4`, as defined by the browser-side implementation above.
235
236## Services Overview &amp; Terminology
237The previous section only scratches the surface of how Mojo IPC is used in
238Chromium. While renderer-to-browser messaging is simple and possibly the most
239prevalent usage by sheer code volume, we are incrementally decomposing the
240codebase into a set of services with a bit more granularity than the traditional
241Content browser/renderer/gpu/utility process split.
242
243A **service** is a self-contained library of code which implements one or more
244related features or behaviors and whose interaction with outside code is done
245*exclusively* through Mojo interface connections facilitated by the **Service
246Manager.**
247
248The **Service Manager** is a component which can run in a dedicated process
249or embedded within another process. Only one Service Manager exists globally
250across the system, and in Chromium the browser process runs an embedded Service
251Manager instance immediately on startup. The Service Manager spawns
252**service instances** on-demand, and it routes each interface request from a
253service instance to some destination instance of the Service Manager's choosing.
254
255Each service instance implements the
256[**`Service`**](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/service.h)
257interface to receive incoming interface requests brokered by the Service
258Manager, and each service instance has a
259[**`Connector`**](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/connector.h)
260it can use to issue interface requests to other services via the
261Service Manager.
262
263Every service has a **manifest** which declares some static metadata about the
264service. This metadata is used by the Service Manager for various purposes,
265including as a declaration of what interfaces are exposed to other services in
266the system. This eases the security review process.
267
268Inside its manifest every service declares its **service name**, used to
269identify instances of the service in the most general sense. Names are free-form
270and usually short strings which must be globally unique. Some services defined
271in Chromium today include `"device"`, `"identity"`, and `"network"` services.
272
273For more complete and in-depth coverage of the concepts covered here and other
274related APIs, see the
275[Service Manager documentation](/services/service_manager/README.md).
276
277## Example: Building a Simple Out-of-Process Service
278
279There are multiple steps required to get a new service up and running in
280Chromium. You must:
281
282- Define the `Service` implementation
283- Define the service's manifest
284- Tell Chromium's Service Manager about the manifest
285- Tell Chromium how to instantiate the `Service` implementation when it's needed
286
287This section walks through these steps with some brief explanations. For more
288thorough documentation of the concepts and APIs used herein, see the
289[Service Manager](/services/service_manager/README.md) and
290[Mojo](/mojo/README.md) documentation.
291
292### Defining the Service
293
294Typically service definitions are placed in a `services` directory, either at
295the top level of the tree or within some subdirectory. In this example, we'll
296define a new service for use by Chrome specifically, so we'll define it within
297`//chrome/services`.
298
299We can create the following files. First some mojoms:
300
301``` cpp
302// src/chrome/services/math/public/mojom/constants.mojom
303module math.mojom;
304
305// These are not used by the implementation directly, but will be used in
306// following sections.
307const string kServiceName = "math";
308const string kArithmeticCapability = "arithmetic";
309```
310
311``` cpp
312// src/chrome/services/math/public/mojom/divider.mojom
313module math.mojom;
314
315interface Divider {
316 Divide(int32 dividend, int32 divisor) => (int32 quotient);
317};
318```
319
320``` python
321# src/chrome/services/math/public/mojom/BUILD.gn
Ken Rockota0cb6cf92019-03-26 16:40:42322import("//mojo/public/tools/bindings/mojom.gni")
Ken Rockotab035122019-02-06 00:35:24323
324mojom("mojom") {
325 sources = [
326 "constants.mojom",
327 "divider.mojom",
328 ]
329}
330```
331
332Then the actual `Service` implementation:
333
334``` cpp
335// src/chrome/services/math/math_service.h
336#include "services/service_manager/public/cpp/service.h"
337
338#include "base/macros.h"
339#include "chrome/services/math/public/mojom/divider.mojom.h"
340
341namespace math {
342
343class MathService : public service_manager::Service,
344 public mojom::Divider {
345 public:
346 explicit MathService(service_manager::mojom::ServiceRequest request);
347 ~MathService() override;
348
349 private:
350 // service_manager::Service:
351 void OnBindInterface(const service_manager::BindSourceInfo& source,
352 const std::string& interface_name,
353 mojo::ScopedMessagePipeHandle interface_pipe) override;
354
355 // mojom::Divider:
356 void Divide(int32_t dividend,
357 int32_t divisor,
358 DivideCallback callback) override;
359
360 service_manager::ServiceBinding service_binding_;
361
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40362 // You could also use a Receiver. We use ReceiverSet to conveniently allow
Ken Rockotab035122019-02-06 00:35:24363 // multiple clients to bind to the same instance of this class. See Mojo
364 // C++ Bindings documentation for more information.
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40365 mojo::ReceiverSet<mojom::Divider> divider_receivers_;
Ken Rockotab035122019-02-06 00:35:24366
367 DISALLOW_COPY_AND_ASSIGN(MathService);
368};
369
370} // namespace math
371```
372
373``` cpp
374// src/chrome/services/math/math_service.cc
375#include "chrome/services/math/math_service.h"
376
377namespace math {
378
379MathService::MathService(service_manager::ServiceRequest request)
380 : service_binding_(this, std::move(request)) {}
381
382MathService::~MathService() = default;
383
384void MathService::OnBindInterface(
385 const service_manager::BindSourceInfo& source,
386 const std::string& interface_name,
387 mojo::ScopedMessagePipeHandle interface_pipe) {
388 // Note that services typically use a service_manager::BinderRegistry if they
389 // plan on handling many different interface request types.
390 if (interface_name == mojom::Divider::Name_) {
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40391 divider_receivers_.Add(
392 this, mojo::PendingReceiver<mojom::Divider>(std::move(interface_pipe)));
Ken Rockotab035122019-02-06 00:35:24393 }
394}
395
396void MathService::Divide(int32_t dividend,
397 int32_t divisor,
398 DivideCallback callback) {
399 // Respond with the quotient!
Oksana Zhuravlova0941c08d2019-05-03 20:46:33400 std::move(callback).Run(dividend / divisor);
Ken Rockotab035122019-02-06 00:35:24401}
402
403} // namespace math
404```
405
406``` python
407# src/chrome/services/math/BUILD.gn
408
409source_set("math") {
410 sources = [
411 "math.cc",
412 "math.h",
413 ]
414
415 deps = [
416 "//base",
417 "//chrome/services/math/public/mojom",
418 "//services/service_manager/public/cpp",
419 ]
420}
421```
422
423Now we have a fully defined `math` service implementation, including a nice
424little `Divider` interface for clients to play with. Next we need to define the
425service's manifest to declare how the service can be used.
426
427### Defining the Manifest
428Manifests are defined as
429[`Manifest`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/manifest.h)
430objects, typically built using a
431[`ManifestBuilder`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/manifest_builder.h). As a general rule, services should define their manifest
432in a dedicated `source_set` or `component` target under their `public/cpp`
433subdirectory (typically referred to as the service's **C++ client library**).
434
435We can create the following files for this purpose:
436
437``` cpp
438// src/chrome/services/math/public/cpp/manifest.h
439#include "services/service_manager/public/cpp/manifest.h"
440
441namespace math {
442
443const service_manager::Manifest& GetManifest();
444
445} // namespace math
446```
447
448``` cpp
449// src/chrome/services/math/public/cpp/manifest.cc
450#include "chrome/services/math/public/cpp/manifest.h"
451
452#include "base/no_destructor.h"
453#include "chrome/services/math/public/mojom/constants.mojom.h"
454#include "chrome/services/math/public/mojom/divider.mojom.h"
455#include "services/service_manager/public/cpp/manifest_builder.h"
456
457namespace math {
458
459const service_manager::Manifest& GetManifest() {
460 static base::NoDestructor<service_manager::Manifest> manifest{
461 service_manager::ManifestBuilder()
462 .WithServiceName(mojom::kServiceName)
463 .ExposeCapability(
464 mojom::kArithmeticCapability,
465 service_manager::Manifest::InterfaceList<mojom::Divider>())
466 .Build()};
467 return *manifest
468}
469
470} // namespace math
471```
472
473We also need to define a build target for our manifest sources:
474
475``` python
476# src/chrome/services/math/public/cpp/BUILD.gn
477
478source_set("manifest") {
479 sources = [
480 "manifest.cc",
481 "manifest.h",
482 ]
483
484 deps = [
485 "//base",
486 "//chrome/services/math/public/mojom",
487 "//services/service_manager/public/cpp",
488 ]
489}
490```
491
492The above `Manifest` definition declares that the service is named `math` and
493that it **exposes** a single **capability** named `arithmetic` which allows
494access to the `Divider` interface.
495
496Another service may **require** this capability from its own manifest in order
497for the Service Manager to grant it access to a `Divider`. We'll see this a
498few sections below. First, let's get the manifest and service implementation
499registered with Chromium's Service Manager.
500
501### Registering the Manifest
502
503For the most common out-of-process service cases, we register service manifests
504by **packaging** them in Chrome. This can be done by augmenting the value
505returned by
506[`GetChromePackagedServiceManifests`](https://cs.chromium.org/chromium/src/chrome/app/chrome_packaged_service_manifests.cc?rcl=af43cabf3c01e28be437becb972a7eae44fd54e8&l=133).
507
508We can add our manifest there:
509
510``` cpp
511// Deep within src/chrome/app/chrome_packaged_service_manifests.cc...
512const std::vector<service_manager::Manifest>
513GetChromePackagedServiceManifests() {
514 ...
515 math::GetManifest(),
516 ...
517```
518
519And don't forget to add a GN dependency from
Oksana Zhuravlova0941c08d2019-05-03 20:46:33520[`//chrome/app:chrome_packaged_service_manifests`](https://cs.chromium.org/chromium/src/chrome/app/BUILD.gn?l=564&rcl=a77d5ba9c4621cfe14e7e1cd03bbae16904f269e) onto
Ken Rockotab035122019-02-06 00:35:24521`//chrome/services/math/public/cpp:manifest`!
522
523We're almost done with service setup. The last step is to teach Chromium (and
524thus the Service Manager) how to launch an instance of our beautiful `math`
525service.
526
527### Hooking Up the Service Implementation
528
529There are two parts to this for an out-of-process Chrome service.
530
531First, we need
532to inform the embedded Service Manager that this service is an out-of-process
533service. The goofiness of this part is a product of some legacy issues and it
534should be eliminated soon, but for now it just means teaching the Service
535Manager how to *label* the process it creates for this service (e.g. how the process will
536appear in the system task manager). We modify
537[`ChromeContentBrowserClient::RegisterOutOfProcessServices`](https://cs.chromium.org/chromium/src/chrome/browser/chrome_content_browser_client.cc?rcl=960886a7febcc2acccea7f797d3d5e03a344a12c&l=3766)
538for this:
539
540``` cpp
541void ChromeContentBrowserClient::RegisterOutOfProcessServices(
542 OutOfProcessServicesMap* services) {
543 ...
544
545 (*services)[math::mojom::kServiceName] =
546 base::BindRepeating([]() -> base::string16 {
547 return "Math Service";
548 });
549
550 ...
551}
552```
553
554And finally, since nearly all out-of-process services run in a "utility" process
555today, we need to add a dependency on our actual `Service` implementation to
556Chrome's service spawning code within the utility process.
557
558For this step we just modify
559[`ChromeContentUtilityClient::MaybeCreateMainThreadService`](https://cs.chromium.org/chromium/src/chrome/utility/chrome_content_utility_client.cc?rcl=7226adebd6e8d077d673a82acf1aab0790627178&l=261)
560by adding a block of code as follows:
561
562``` cpp
Mohamed Heikala841c4f02019-06-10 19:50:40563std::unique_ptr<service_manager::Service> ChromeContentUtilityClient::MaybeCreateMainThreadService(
Ken Rockotab035122019-02-06 00:35:24564 const std::string& service_name,
565 service_manager::mojom::ServiceRequest request) {
566 ...
567
568 if (service_name == math::mojom::kServiceName)
569 return std::make_unique<math::MathService>(std::move(request));
570
571 ...
572}
573```
574
575And we're done!
576
577As one nice follow-up step, let's use our math service from the browser.
578
579### Using the Service
580
581We can grant the browser process access to our `Divider` interface by
582**requiring** the `math` service's `arithmetic` capability within the
583`content_browser` service manifest.
584
585*** aside
586NOTE: See the following section for an elaboration on what `content_browser` is.
587For the sake of this example, it's magic.
588***
589
590For Chrome-specific features such as our glorious new `math` service, we can
591amend the `content_browser` manifest by modifying
592[GetChromeContentBrowserOverlayManifest](https://cs.chromium.org/chromium/src/chrome/app/chrome_content_browser_overlay_manifest.cc?rcl=38db90321e8e3627b2f3165cdb051fa8d668af48&l=100)
593as follows:
594
595``` cpp
596// src/chrome/app/chrome_content_browser_overlay_manifest.cc
597
598...
599const service_manager::Manifest& GetChromeContentBrowserOverlayManifest() {
600 ...
601 .RequireCapability(math::mojom::kServiceName,
602 math::mojom::kArithmeticCapability)
603 ...
604}
605```
606
607Finally, we can use the global `content_browser` instance's `Connector` to send
608an interface request to our service. This is accessible from the main thread of
609the browser process. Somewhere in `src/chrome/browser`, we can write:
610
611``` cpp
Ken Rockot70f44082019-06-20 21:47:38612// This gives us the system Connector for the browser process, which has access
613// to most service interfaces.
614service_manager::Connector* connector = content::GetSystemConnector();
Ken Rockotab035122019-02-06 00:35:24615
616// Recall from the earlier Mojo section that mojo::MakeRequest creates a new
617// message pipe for our interface. Connector passes the request endpoint to
618// the Service Manager along with the name of our target service, "math".
619math::mojom::DividerPtr divider;
620connector->BindInterface(math::mojom::kServiceName,
621 mojo::MakeRequest(&divider));
622
623// As a client, we do not have to wait for any acknowledgement or confirmation
624// of a connection. We can start queueing messages immediately and they will be
625// delivered as soon as the service is up and running.
626divider->Divide(
627 42, 6, base::BindOnce([](int32_t quotient) { LOG(INFO) << quotient; }));
628```
Oksana Zhuravlova0941c08d2019-05-03 20:46:33629*** aside
630NOTE: To ensure the execution of the response callback, the DividerPtr
631object must be kept alive (see
632[this section](/mojo/public/cpp/bindings/README.md#A-Note-About-Endpoint-Lifetime-and-Callbacks)
633and [this note from an earlier section](#sending-a-message)).
634***
Ken Rockotab035122019-02-06 00:35:24635
636This should successfully spawn a new process to run the `math` service if it's
637not already running, then ask it to do a division, and ultimately log the result
638after it's sent back to the browser process.
639
640Finally it's worth reiterating that every service instance in the system has
641its own `Connector` and there's no reason we have to limit ourselves to
642`content_browser` as the client, as long as the appropriate manifest declares
643that it requires our `arithmetic` capability.
644
645If we did not update the `content_browser` manifest overlay as we did in this
646example, the `Divide` call would never reach the `math` service (in fact the
647service wouldn't even be started) and instead we'd get an error message (or in
648developer builds, an assertion failure) informing us that the Service Manager
649blocked the `BindInterface` call.
650
651## Content-Layer Services Overview
652
653Apart from very early initialization steps in the browser process, every bit of
654logic in Chromium today is effectively running as part of one service instance
655or another.
656
657Although we continue to migrate parts of the browser's privileged
658functionality to more granular services defined below the Content layer, the
659main services defined in Chromium today continue to model the Content layer's
660classical multiprocess architecture which defines a handful of
661**process types**: browser, renderer, gpu, utility, and plugin processes. For
662each of these process types, we now define corresponding services.
663
664Manifest definitions for all of the following services can be found in
665`//content/public/app`.
666
667### The Browser Service
668
669`content_browser` is defined to encapsulate general-purpose browser process
670code. There are multiple instances of this service, all running within the
671singular browser process. There is one shared global instance as well an
672additional instance for each `BrowserContext` (*i.e.* per Chrome profile).
673
674The global instance exists primarily so that arbitrary browser process code can
675reach various system services conveniently via a global `Connector` instance
676on the main thread.
677
678Each instance associated with a `BrowserContext` is placed in an isolated
679instance group specific to that `BrowserContext`. This limits the service
680instances with which its `Connector` can make contact. These instances are
681used primarily to facilitate the spawning of other isolated per-profile service
682instances, such as renderers and plugins.
683
684### The Renderer Service
685
686A `content_renderer` instance is spawned in its own sandboxed process for every
687site-isolated instance of Blink we require. Instances are placed in the same
688instance group as the renderer's corresponding `BrowserContext`, *i.e.* the
689profile which navigated to the site being rendered.
690
691Most interfaces used by `content_renderer` are not brokered through the Service
692Manager but instead are brokered through dedicated interfaces implemented by
693`content_browser`, with which each renderer maintains persistent connections.
694
695### The GPU Service
696
697Only a single instance of `content_gpu` exists at a time and it always runs in
698its own isolated, sandboxed process. This service hosts the code in content/gpu
699and whatever else Content's embedder adds to that for GPU support.
700
701### The Plugin Service
702
703`content_plugin` hosts a plugin in an isolated process. Similarly to
704`content_renderer` instances, each instance of `content_plugin` belongs to
705an instance group associated with a specific `BrowserContext`, and in general
706plugins get most of their functionality by talking directly to `content_browser`
707rather than brokering interface requests through the Service Manager.
708
709### The Utility Service
710
711`content_utility` exists only nominally today, as there is no remaining API
712surface within Content which would allow a caller to explicitly create an
713instance of it. Instead, this service is used exclusively to bootstrap new
714isolated processes in which other services will run.
715
716## Exposing Interfaces Between Content Processes
717
718Apart from the standard Service Manager APIs, the Content layer defines a number
719of additional concepts for Content and its embedder to expose interfaces
720specifically between Content processes in various contexts.
721
722### Exposing Browser Interfaces to Renderer Documents and Workers
723
724Documents and workers are somewhat of a special case since interface access
725decisions often require browser-centric state that the Service Manager cannot
726know about, such as details of the current `BrowserContext`, the origin of the
727renderered content, installed extensions in the renderer, *etc.* For this
728reason, interface brokering decisions are increasingly being made by the
729browser.
730
731There are two ways this is done: the Deprecated way and the New way.
732
733#### The Deprecated Way: InterfaceProvider
734
735This is built on the concept of **interface filters** and the
736**`InterfaceProvider`** interface. It is **deprecated** and new features should
737use [The New Way](#The-New-Way_Interface-Brokers) instead. This section only
738briefly covers practical usage in Chromium.
739
740The `content_browser` manifest exposes capabilities on a few named interface
741filters, the main one being `"navigation:frame"`. There are others scoped to
742different worker contexts, *e.g.* `"navigation:service_worker"`.
743`RenderProcessHostImpl` or `RenderFrameHostImpl` sets up an `InterfaceProvider`
744for each known execution context in the corresponding renderer, filtered through
745the Service Manager according to one of the named filters.
746
747The practical result of all this means the interface must be listed in the
748`content_browser` manifest under the
749`ExposeInterfaceFilterCapability_Deprecated("navigation:frame", "renderer", ...)`
750entry, and a corresponding interface request handler must be registered with the
751host's `registry_` in
752[`RenderFrameHostImpl::RegisterMojoInterfaces`](https://cs.chromium.org/chromium/src/content/browser/frame_host/render_frame_host_impl.cc?rcl=0a23c78c57ecb2405837155aa0a0def7b5ba9c22&l=3971)
753
754Similarly for worker contexts, an interface must be exposed by the `"renderer"`
755capability on the corresponding interface filter
756(*e.g.*, `"navigation:shared_worker"`) and a request handler must be registered
757within
758[`RendererInterfaceBinders::InitializeParameterizedBinderRegistry`](https://cs.chromium.org/chromium/src/content/browser/renderer_interface_binders.cc?rcl=0a23c78c57ecb2405837155aa0a0def7b5ba9c22&l=116).
759
760The best way to understand all of this after reading this section is to look at
761the linked code above and examine a few examples. They are fairly repetitive.
762For additional convenience, here is also a link to the `content_browser`
763[manifest](https://cs.chromium.org/chromium/src/content/public/app/content_browser_manifest.cc).
764
765#### The New Way: Interface Brokers
766
Ken Rockotab035122019-02-06 00:35:24767Rather than the confusing spaghetti of interface filter logic, we now define an
768explicit mojom interface with a persistent connection between a renderer's
769frame object and the corresponding `RenderFrameHostImpl` in the browser process.
770This interface is called
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40771[`BrowserInterfaceBroker`](https://cs.chromium.org/chromium/src/third_party/blink/public/mojom/browser_interface_broker.mojom?rcl=09aa5ae71649974cae8ad4f889d7cd093637ccdb&l=11)
772and is fairly easy to work with: you add a new method on `RenderFrameHostImpl`:
Ken Rockotab035122019-02-06 00:35:24773
774``` cpp
775void RenderFrameHostImpl::GetGoatTeleporter(
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40776 mojo::PendingReceiver<magic::mojom::GoatTeleporter> receiver) {
777 goat_teleporter_receiver_.Bind(std::move(receiver));
Ken Rockotab035122019-02-06 00:35:24778}
779```
780
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40781and register this method in `PopulateFrameBinders` function in `browser_interface_binders.cc`,
782which maps specific interfaces to their handlers in respective hosts:
783
784``` cpp
785// //content/browser/browser_interface_binders.cc
786void PopulateFrameBinders(RenderFrameHostImpl* host,
787 service_manager::BinderMap* map) {
788...
789 map->Add<magic::mojom::GoatTeleporter>(base::BindRepeating(
790 &RenderFrameHostImpl::GetGoatTeleporter, base::Unretained(host)));
791}
792```
793
794
Ken Rockotab035122019-02-06 00:35:24795### Exposing Browser Interfaces to Render Processes
796
797Sometimes (albeit rarely) it's useful to expose a browser interface directly to
798a renderer process. This can be done as for any other interface exposed between
799two services. In this specific instance, the `content_browser` manifest exposes
800a capability named `"renderer"` which `content_renderer` requires. Any interface
801listed as part of that capability can be accessed by a `content_renderer`
802instance by using its own `Connector`. See below.
803
804### Exposing Browser Interfaces to Content Child Processes
805
806All Content child process types (renderer, GPU, and plugin) share a common API
807to interface with the Service Manager. Their Service Manager connection is
808initialized and maintained by `ChildThreadImpl` on process startup, and from
809the main thread, you can access the process's `Connector` as follows:
810
811``` cpp
812auto* connector = content::ChildThread::Get()->GetConnector();
813
814// For example...
Oksana Zhuravlova9f3b8ef2019-08-26 20:27:40815connector->Connect(content::mojom::kBrowserServiceName,
816 std::move(some_receiver));
Ken Rockotab035122019-02-06 00:35:24817```
818
819### Exposing Content Child Process Interfaces to the Browser
820
821Content child processes may also expose interfaces to the browser, though this
822is much less common and requires a fair bit of caution since the browser must be
823careful to only call `Connector.BindInterface` in these cases with an exact
824`service_manager::Identity` to avoid unexpected behavior.
825
826Every child process provides a subclass of ChildThreadImpl, and this can be used
827to install a new `ConnectionFilter` on the process's Service Manager connection
828before starting to accept requests.
829
830This behavior should really be considered deprecated, but for posterity, here is
831how the GPU process does it:
832
8331. [Disable Service Manager connection auto-start](https://cs.chromium.org/chromium/src/content/gpu/gpu_child_thread.cc?rcl=6b85a56334c0cd64b0e657934060de716714ca64&l=62)
8342. [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)
8353. [Start the Service Manager connection manually](https://cs.chromium.org/chromium/src/content/gpu/gpu_child_thread.cc?rcl=6b85a56334c0cd64b0e657934060de716714ca64&l=257)
836
837It's much more common instead for there to be some primordial interface
838connection established by the child process which can then be used to facilitate
839push communications from the browser, so please consider not duplicating this
840behavior.
841
842## Additional Support
843
844If this document was not helpful in some way, please post a message to your
845friendly
846[[email protected]](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo)
847or
848[[email protected]](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev)
849mailing list.