blob: 55a366c45fcaefd41cf4d411cab72ce90e4e0f37 [file] [log] [blame] [view]
Ken Rockot686e4132017-04-26 00:03:311# Mojo C++ Bindings API
Ken Rockot929282c2018-05-02 17:07:292This document is a subset of the [Mojo documentation](/mojo/README.md).
rockotf59d2d62017-04-01 02:49:083
4[TOC]
5
6## Overview
7The Mojo C++ Bindings API leverages the
Ken Rockot929282c2018-05-02 17:07:298[C++ System API](/mojo/public/cpp/system/README.md) to provide a more natural
9set of primitives for communicating over Mojo message pipes. Combined with
10generated code from the
11[Mojom IDL and bindings generator](/mojo/public/tools/bindings/README.md), users
12can easily connect interface clients and implementations across arbitrary intra-
13and inter-process bounaries.
rockotf59d2d62017-04-01 02:49:0814
15This document provides a detailed guide to bindings API usage with example code
16snippets. For a detailed API references please consult the headers in
Ken Rockot929282c2018-05-02 17:07:2917[//mojo/public/cpp/bindings](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/README.md).
rockotf59d2d62017-04-01 02:49:0818
Oksana Zhuravlova70c47af2018-07-06 22:48:2419For a simplified guide targeted at Chromium developers, see [this
Ken Rockotab035122019-02-06 00:35:2420link](/docs/mojo_and_services.md).
Erik Chen3fdc02bc2018-06-28 03:13:4821
rockotf59d2d62017-04-01 02:49:0822## Getting Started
23
24When a Mojom IDL file is processed by the bindings generator, C++ code is
25emitted in a series of `.h` and `.cc` files with names based on the input
26`.mojom` file. Suppose we create the following Mojom file at
Oksana Zhuravlovad5fea16d2018-08-15 00:02:1727`//services/db/public/mojom/db.mojom`:
rockotf59d2d62017-04-01 02:49:0828
29```
30module db.mojom;
31
32interface Table {
33 AddRow(int32 key, string data);
34};
35
36interface Database {
37 CreateTable(Table& table);
38};
39```
40
41And a GN target to generate the bindings in
Oksana Zhuravlovad5fea16d2018-08-15 00:02:1742`//services/db/public/mojom/BUILD.gn`:
rockotf59d2d62017-04-01 02:49:0843
44```
45import("//mojo/public/tools/bindings/mojom.gni")
46
Oksana Zhuravlovad5fea16d2018-08-15 00:02:1747mojom("mojom") {
rockotf59d2d62017-04-01 02:49:0848 sources = [
49 "db.mojom",
50 ]
51}
52```
53
David 'Digit' Turner743836f82017-10-27 13:04:1554Ensure that any target that needs this interface depends on it, e.g. with a line like:
55
56```
Oksana Zhuravlovad5fea16d2018-08-15 00:02:1757 deps += [ '//services/db/public/mojom' ]
David 'Digit' Turner743836f82017-10-27 13:04:1558```
59
rockotf59d2d62017-04-01 02:49:0860If we then build this target:
61
62```
Oksana Zhuravlovad5fea16d2018-08-15 00:02:1763ninja -C out/r services/db/public/mojom
rockotf59d2d62017-04-01 02:49:0864```
65
66This will produce several generated source files, some of which are relevant to
67C++ bindings. Two of these files are:
68
69```
Oksana Zhuravlovad5fea16d2018-08-15 00:02:1770out/gen/services/db/public/mojom/db.mojom.cc
71out/gen/services/db/public/mojom/db.mojom.h
rockotf59d2d62017-04-01 02:49:0872```
73
74You can include the above generated header in your sources in order to use the
75definitions therein:
76
77``` cpp
Oksana Zhuravlovad5fea16d2018-08-15 00:02:1778#include "services/business/public/mojom/factory.mojom.h"
rockotf59d2d62017-04-01 02:49:0879
80class TableImpl : public db::mojom::Table {
81 // ...
82};
83```
84
85This document covers the different kinds of definitions generated by Mojom IDL
86for C++ consumers and how they can effectively be used to communicate across
87message pipes.
88
89*** note
90**NOTE:** Using C++ bindings from within Blink code is typically subject to
91special constraints which require the use of a different generated header.
92For details, see [Blink Type Mapping](#Blink-Type-Mapping).
93***
94
95## Interfaces
96
97Mojom IDL interfaces are translated to corresponding C++ (pure virtual) class
98interface definitions in the generated header, consisting of a single generated
99method signature for each request message on the interface. Internally there is
100also generated code for serialization and deserialization of messages, but this
101detail is hidden from bindings consumers.
102
103### Basic Usage
104
105Let's consider a new `//sample/logger.mojom` to define a simple logging
106interface which clients can use to log simple string messages:
107
108``` cpp
109module sample.mojom;
110
111interface Logger {
112 Log(string message);
113};
114```
115
116Running this through the bindings generator will produce a `logging.mojom.h`
117with the following definitions (modulo unimportant details):
118
119``` cpp
120namespace sample {
121namespace mojom {
122
123class Logger {
124 virtual ~Logger() {}
125
126 virtual void Log(const std::string& message) = 0;
127};
128
129using LoggerPtr = mojo::InterfacePtr<Logger>;
130using LoggerRequest = mojo::InterfaceRequest<Logger>;
131
132} // namespace mojom
133} // namespace sample
134```
135
136Makes sense. Let's take a closer look at those type aliases at the end.
137
138### InterfacePtr and InterfaceRequest
139
140You will notice the type aliases for `LoggerPtr` and
141`LoggerRequest` are using two of the most fundamental template types in the C++
142bindings library: **`InterfacePtr<T>`** and **`InterfaceRequest<T>`**.
143
144In the world of Mojo bindings libraries these are effectively strongly-typed
145message pipe endpoints. If an `InterfacePtr<T>` is bound to a message pipe
146endpoint, it can be dereferenced to make calls on an opaque `T` interface. These
147calls immediately serialize their arguments (using generated code) and write a
148corresponding message to the pipe.
149
150An `InterfaceRequest<T>` is essentially just a typed container to hold the other
151end of an `InterfacePtr<T>`'s pipe -- the receiving end -- until it can be
152routed to some implementation which will **bind** it. The `InterfaceRequest<T>`
153doesn't actually *do* anything other than hold onto a pipe endpoint and carry
154useful compile-time type information.
155
Ken Rockotab035122019-02-06 00:35:24156![Diagram illustrating InterfacePtr and InterfaceRequest on either end of a message pipe](/docs/images/mojo_pipe.png)
rockotf59d2d62017-04-01 02:49:08157
158So how do we create a strongly-typed message pipe?
159
160### Creating Interface Pipes
161
Ken Rockotf4d8a942017-05-13 00:10:37162One way to do this is by manually creating a pipe and wrapping each end with a
163strongly-typed object:
rockotf59d2d62017-04-01 02:49:08164
165``` cpp
166#include "sample/logger.mojom.h"
167
168mojo::MessagePipe pipe;
Ken Rockotf4d8a942017-05-13 00:10:37169sample::mojom::LoggerPtr logger(
170 sample::mojom::LoggerPtrInfo(std::move(pipe.handle0), 0));
171sample::mojom::LoggerRequest request(std::move(pipe.handle1));
rockotf59d2d62017-04-01 02:49:08172```
173
Ken Rockotf4d8a942017-05-13 00:10:37174That's pretty verbose, but the C++ Bindings library provides a more convenient
175way to accomplish the same thing. [interface_request.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/interface_request.h)
rockotf59d2d62017-04-01 02:49:08176defines a `MakeRequest` function:
177
178``` cpp
179sample::mojom::LoggerPtr logger;
Ken Rockotf4d8a942017-05-13 00:10:37180auto request = mojo::MakeRequest(&logger);
rockotf59d2d62017-04-01 02:49:08181```
182
Ken Rockotf4d8a942017-05-13 00:10:37183This second snippet is equivalent to the first one.
rockotf59d2d62017-04-01 02:49:08184
185*** note
186**NOTE:** In the first example above you may notice usage of the `LoggerPtrInfo`
187type, which is a generated alias for `mojo::InterfacePtrInfo<Logger>`. This is
188similar to an `InterfaceRequest<T>` in that it merely holds onto a pipe handle
189and cannot actually read or write messages on the pipe. Both this type and
Sam McNallyd482b4b2017-07-17 03:45:03190`InterfaceRequest<T>` are safe to move freely from sequence to sequence, whereas
191a bound `InterfacePtr<T>` is bound to a single sequence.
rockotf59d2d62017-04-01 02:49:08192
193An `InterfacePtr<T>` may be unbound by calling its `PassInterface()` method,
194which returns a new `InterfacePtrInfo<T>`. Conversely, an `InterfacePtr<T>` may
195bind (and thus take ownership of) an `InterfacePtrInfo<T>` so that interface
196calls can be made on the pipe.
197
Sam McNallyd482b4b2017-07-17 03:45:03198The sequence-bound nature of `InterfacePtr<T>` is necessary to support safe
rockotf59d2d62017-04-01 02:49:08199dispatch of its [message responses](#Receiving-Responses) and
200[connection error notifications](#Connection-Errors).
201***
202
203Once the `LoggerPtr` is bound we can immediately begin calling `Logger`
204interface methods on it, which will immediately write messages into the pipe.
205These messages will stay queued on the receiving end of the pipe until someone
206binds to it and starts reading them.
207
208``` cpp
209logger->Log("Hello!");
210```
211
212This actually writes a `Log` message to the pipe.
213
Ken Rockotab035122019-02-06 00:35:24214![Diagram illustrating a message traveling on a pipe from LoggerPtr to LoggerRequest](/docs/images/mojo_message.png)
rockotf59d2d62017-04-01 02:49:08215
216But as mentioned above, `InterfaceRequest` *doesn't actually do anything*, so
217that message will just sit on the pipe forever. We need a way to read messages
218off the other end of the pipe and dispatch them. We have to
219**bind the interface request**.
220
221### Binding an Interface Request
222
223There are many different helper classes in the bindings library for binding the
224receiving end of a message pipe. The most primitive among them is the aptly
225named `mojo::Binding<T>`. A `mojo::Binding<T>` bridges an implementation of `T`
226with a single bound message pipe endpoint (via a `mojo::InterfaceRequest<T>`),
227which it continuously watches for readability.
228
229Any time the bound pipe becomes readable, the `Binding` will schedule a task to
230read, deserialize (using generated code), and dispatch all available messages to
231the bound `T` implementation. Below is a sample implementation of the `Logger`
232interface. Notice that the implementation itself owns a `mojo::Binding`. This is
233a common pattern, since a bound implementation must outlive any `mojo::Binding`
234which binds it.
235
236``` cpp
237#include "base/logging.h"
238#include "base/macros.h"
239#include "sample/logger.mojom.h"
240
241class LoggerImpl : public sample::mojom::Logger {
242 public:
243 // NOTE: A common pattern for interface implementations which have one
244 // instance per client is to take an InterfaceRequest in the constructor.
245
246 explicit LoggerImpl(sample::mojom::LoggerRequest request)
247 : binding_(this, std::move(request)) {}
248 ~Logger() override {}
249
250 // sample::mojom::Logger:
251 void Log(const std::string& message) override {
252 LOG(ERROR) << "[Logger] " << message;
253 }
254
255 private:
256 mojo::Binding<sample::mojom::Logger> binding_;
257
258 DISALLOW_COPY_AND_ASSIGN(LoggerImpl);
259};
260```
261
262Now we can construct a `LoggerImpl` over our pending `LoggerRequest`, and the
263previously queued `Log` message will be dispatched ASAP on the `LoggerImpl`'s
Sam McNallyd482b4b2017-07-17 03:45:03264sequence:
rockotf59d2d62017-04-01 02:49:08265
266``` cpp
267LoggerImpl impl(std::move(request));
268```
269
270The diagram below illustrates the following sequence of events, all set in
271motion by the above line of code:
272
2731. The `LoggerImpl` constructor is called, passing the `LoggerRequest` along
274 to the `Binding`.
2752. The `Binding` takes ownership of the `LoggerRequest`'s pipe endpoint and
276 begins watching it for readability. The pipe is readable immediately, so a
277 task is scheduled to read the pending `Log` message from the pipe ASAP.
2783. The `Log` message is read and deserialized, causing the `Binding` to invoke
279 the `Logger::Log` implementation on its bound `LoggerImpl`.
280
Ken Rockotab035122019-02-06 00:35:24281![Diagram illustrating the progression of binding a request, reading a pending message, and dispatching it](/docs/images/mojo_binding_and_dispatch.png)
rockotf59d2d62017-04-01 02:49:08282
283As a result, our implementation will eventually log the client's `"Hello!"`
284message via `LOG(ERROR)`.
285
286*** note
287**NOTE:** Messages will only be read and dispatched from a pipe as long as the
288object which binds it (*i.e.* the `mojo::Binding` in the above example) remains
289alive.
290***
291
292### Receiving Responses
293
294Some Mojom interface methods expect a response. Suppose we modify our `Logger`
295interface so that the last logged line can be queried like so:
296
297``` cpp
298module sample.mojom;
299
300interface Logger {
301 Log(string message);
302 GetTail() => (string message);
303};
304```
305
306The generated C++ interface will now look like:
307
308``` cpp
309namespace sample {
310namespace mojom {
311
312class Logger {
313 public:
314 virtual ~Logger() {}
315
316 virtual void Log(const std::string& message) = 0;
317
David 'Digit' Turner743836f82017-10-27 13:04:15318 using GetTailCallback = base::OnceCallback<void(const std::string& message)>;
rockotf59d2d62017-04-01 02:49:08319
David 'Digit' Turner743836f82017-10-27 13:04:15320 virtual void GetTail(GetTailCallback callback) = 0;
rockotf59d2d62017-04-01 02:49:08321}
322
323} // namespace mojom
324} // namespace sample
325```
326
327As before, both clients and implementations of this interface use the same
328signature for the `GetTail` method: implementations use the `callback` argument
329to *respond* to the request, while clients pass a `callback` argument to
Andrew Moylan9216d3772018-12-19 04:52:29330asynchronously `receive` the response. A client's `callback` runs on the same
331sequence on which they invoked `GetTail` (the sequence to which their `logger`
332is bound). Here's an updated implementation:
rockotf59d2d62017-04-01 02:49:08333
334```cpp
335class LoggerImpl : public sample::mojom::Logger {
336 public:
337 // NOTE: A common pattern for interface implementations which have one
338 // instance per client is to take an InterfaceRequest in the constructor.
339
340 explicit LoggerImpl(sample::mojom::LoggerRequest request)
341 : binding_(this, std::move(request)) {}
342 ~Logger() override {}
343
344 // sample::mojom::Logger:
345 void Log(const std::string& message) override {
346 LOG(ERROR) << "[Logger] " << message;
347 lines_.push_back(message);
348 }
349
David 'Digit' Turner743836f82017-10-27 13:04:15350 void GetTail(GetTailCallback callback) override {
351 std::move(callback).Run(lines_.back());
rockotf59d2d62017-04-01 02:49:08352 }
353
354 private:
355 mojo::Binding<sample::mojom::Logger> binding_;
356 std::vector<std::string> lines_;
357
358 DISALLOW_COPY_AND_ASSIGN(LoggerImpl);
359};
360```
361
362And an updated client call:
363
364``` cpp
365void OnGetTail(const std::string& message) {
366 LOG(ERROR) << "Tail was: " << message;
367}
368
David 'Digit' Turner743836f82017-10-27 13:04:15369logger->GetTail(base::BindOnce(&OnGetTail));
rockotf59d2d62017-04-01 02:49:08370```
371
372Behind the scenes, the implementation-side callback is actually serializing the
373response arguments and writing them onto the pipe for delivery back to the
374client. Meanwhile the client-side callback is invoked by some internal logic
375which watches the pipe for an incoming response message, reads and deserializes
376it once it arrives, and then invokes the callback with the deserialized
377parameters.
378
379### Connection Errors
380
Yuzhu Shen92e791aa2017-06-20 20:39:31381If a pipe is disconnected, both endpoints will be able to observe the connection
382error (unless the disconnection is caused by closing/destroying an endpoint, in
383which case that endpoint won't get such a notification). If there are remaining
384incoming messages for an endpoint on disconnection, the connection error won't
385be triggered until the messages are drained.
386
387Pipe disconnecition may be caused by:
388* Mojo system-level causes: process terminated, resource exhausted, etc.
389* The bindings close the pipe due to a validation error when processing a
390 received message.
391* The peer endpoint is closed. For example, the remote side is a bound
392 `mojo::InterfacePtr<T>` and it is destroyed.
rockotf59d2d62017-04-01 02:49:08393
394Regardless of the underlying cause, when a connection error is encountered on
395a binding endpoint, that endpoint's **connection error handler** (if set) is
396invoked. This handler is a simple `base::Closure` and may only be invoked
397*once* as long as the endpoint is bound to the same pipe. Typically clients and
398implementations use this handler to do some kind of cleanup or -- particuarly if
399the error was unexpected -- create a new pipe and attempt to establish a new
400connection with it.
401
402All message pipe-binding C++ objects (*e.g.*, `mojo::Binding<T>`,
403`mojo::InterfacePtr<T>`, *etc.*) support setting their connection error handler
404via a `set_connection_error_handler` method.
405
406We can set up another end-to-end `Logger` example to demonstrate error handler
407invocation:
408
409``` cpp
410sample::mojom::LoggerPtr logger;
411LoggerImpl impl(mojo::MakeRequest(&logger));
jameswest14ae0132017-06-12 22:52:00412impl.set_connection_error_handler(base::BindOnce([] { LOG(ERROR) << "Bye."; }));
rockotf59d2d62017-04-01 02:49:08413logger->Log("OK cool");
414logger.reset(); // Closes the client end.
415```
416
417As long as `impl` stays alive here, it will eventually receive the `Log` message
418followed immediately by an invocation of the bound callback which outputs
419`"Bye."`. Like all other bindings callbacks, a connection error handler will
420**never** be invoked once its corresponding binding object has been destroyed.
421
422In fact, suppose instead that `LoggerImpl` had set up the following error
423handler within its constructor:
424
425``` cpp
426LoggerImpl::LoggerImpl(sample::mojom::LoggerRequest request)
427 : binding_(this, std::move(request)) {
428 binding_.set_connection_error_handler(
jameswest14ae0132017-06-12 22:52:00429 base::BindOnce(&LoggerImpl::OnError, base::Unretained(this)));
rockotf59d2d62017-04-01 02:49:08430}
431
432void LoggerImpl::OnError() {
433 LOG(ERROR) << "Client disconnected! Purging log lines.";
434 lines_.clear();
435}
436```
437
438The use of `base::Unretained` is *safe* because the error handler will never be
439invoked beyond the lifetime of `binding_`, and `this` owns `binding_`.
440
Yuzhu Shen7afd7262017-11-16 22:30:26441### A Note About Endpoint Lifetime and Callbacks
442Once a `mojo::InterfacePtr<T>` is destroyed, it is guaranteed that pending
443callbacks as well as the connection error handler (if registered) won't be
444called.
445
446Once a `mojo::Binding<T>` is destroyed, it is guaranteed that no more method
447calls are dispatched to the implementation and the connection error handler (if
448registered) won't be called.
449
John Abd-El-Maleka9154852017-12-21 23:39:48450### Best practices for dealing with process crashes and callbacks
451A common situation when calling mojo interface methods that take a callback is
452that the caller wants to know if the other endpoint is torn down (e.g. because
453of a crash). In that case, the consumer usually wants to know if the response
454callback won't be run. There are different solutions for this problem, depending
455on how the `InterfacePtr<T>` is held:
4561. The consumer owns the `InterfacePtr<T>`: `set_connection_error_handler`
457 should be used.
4582. The consumer doesn't own the `InterfacePtr<T>`: there are two helpers
459 depending on the behavior that the caller wants. If the caller wants to
460 ensure that an error handler is run, then
461 [**`mojo::WrapCallbackWithDropHandler`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/callback_helpers.h?l=46)
462 should be used. If the caller wants the callback to always be run, then
463 [**`mojo::WrapCallbackWithDefaultInvokeIfNotRun`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/callback_helpers.h?l=40)
464 helper should be used. With both of these helpers, usual callback care should
465 be followed to ensure that the callbacks don't run after the consumer is
466 destructed (e.g. because the owner of the `InterfacePtr<T>` outlives the
467 consumer). This includes using
468 [**`base::WeakPtr`**](https://cs.chromium.org/chromium/src/base/memory/weak_ptr.h?l=5)
469 or
470 [**`base::RefCounted`**](https://cs.chromium.org/chromium/src/base/memory/ref_counted.h?l=246).
471 It should also be noted that with these helpers, the callbacks could be run
472 synchronously while the InterfacePtr<T> is reset or destroyed.
473
rockotf59d2d62017-04-01 02:49:08474### A Note About Ordering
475
476As mentioned in the previous section, closing one end of a pipe will eventually
477trigger a connection error on the other end. However it's important to note that
478this event is itself ordered with respect to any other event (*e.g.* writing a
479message) on the pipe.
480
481This means that it's safe to write something contrived like:
482
483``` cpp
484void GoBindALogger(sample::mojom::LoggerRequest request) {
485 LoggerImpl impl(std::move(request));
486 base::RunLoop loop;
487 impl.set_connection_error_handler(loop.QuitClosure());
488 loop.Run();
489}
490
491void LogSomething() {
492 sample::mojom::LoggerPtr logger;
493 bg_thread->task_runner()->PostTask(
494 FROM_HERE, base::BindOnce(&GoBindALogger, mojo::MakeRequest(&logger)));
495 logger->Log("OK Computer");
496}
497```
498
499When `logger` goes out of scope it immediately closes its end of the message
500pipe, but the impl-side won't notice this until it receives the sent `Log`
501message. Thus the `impl` above will first log our message and *then* see a
502connection error and break out of the run loop.
503
Sasha Bermeister995adc62017-12-07 02:36:43504## Types
505
Ken Rockot686e4132017-04-26 00:03:31506### Enums
507
Ken Rockot929282c2018-05-02 17:07:29508[Mojom enums](/mojo/public/tools/bindings/README.md#Enumeration-Types) translate
509directly to equivalent strongly-typed C++11 enum classes with `int32_t` as the
510underlying type. The typename and value names are identical between Mojom and
511C++. Mojo also always defines a special enumerator `kMaxValue` that shares the
512value of the highest enumerator: this makes it easy to record Mojo enums in
513histograms and interoperate with legacy IPC.
Ken Rockot686e4132017-04-26 00:03:31514
515For example, consider the following Mojom definition:
516
517```cpp
518module business.mojom;
519
520enum Department {
521 kEngineering,
Andrew Moylan341cece72017-06-22 22:03:02522 kMarketing,
Ken Rockot686e4132017-04-26 00:03:31523 kSales,
524};
525```
526
527This translates to the following C++ definition:
528
529```cpp
530namespace business {
531namespace mojom {
532
533enum class Department : int32_t {
534 kEngineering,
535 kMarketing,
536 kSales,
Daniel Chengcda1df5b2018-03-30 21:30:16537 kMaxValue = kSales,
Ken Rockot686e4132017-04-26 00:03:31538};
539
540} // namespace mojom
541} // namespace business
542```
543
544### Structs
545
Ken Rockot929282c2018-05-02 17:07:29546[Mojom structs](mojo/public/tools/bindings/README.md#Structs) can be used to
547define logical groupings of fields into a new composite type. Every Mojom struct
Ken Rockot686e4132017-04-26 00:03:31548elicits the generation of an identically named, representative C++ class, with
549identically named public fields of corresponding C++ types, and several helpful
550public methods.
551
552For example, consider the following Mojom struct:
553
554```cpp
555module business.mojom;
556
557struct Employee {
558 int64 id;
559 string username;
560 Department department;
561};
562```
563
564This would generate a C++ class like so:
565
566```cpp
567namespace business {
568namespace mojom {
569
570class Employee;
571
572using EmployeePtr = mojo::StructPtr<Employee>;
573
574class Employee {
575 public:
576 // Default constructor - applies default values, potentially ones specified
577 // explicitly within the Mojom.
578 Employee();
579
580 // Value constructor - an explicit argument for every field in the struct, in
581 // lexical Mojom definition order.
582 Employee(int64_t id, const std::string& username, Department department);
583
584 // Creates a new copy of this struct value
585 EmployeePtr Clone();
586
587 // Tests for equality with another struct value of the same type.
588 bool Equals(const Employee& other);
589
590 // Equivalent public fields with names identical to the Mojom.
591 int64_t id;
592 std::string username;
593 Department department;
594};
595
596} // namespace mojom
597} // namespace business
598```
599
600Note when used as a message parameter or as a field within another Mojom struct,
601a `struct` type is wrapped by the move-only `mojo::StructPtr` helper, which is
602roughly equivalent to a `std::unique_ptr` with some additional utility methods.
603This allows struct values to be nullable and struct types to be potentially
604self-referential.
605
606Every genereated struct class has a static `New()` method which returns a new
607`mojo::StructPtr<T>` wrapping a new instance of the class constructed by
608forwarding the arguments from `New`. For example:
609
610```cpp
611mojom::EmployeePtr e1 = mojom::Employee::New();
612e1->id = 42;
613e1->username = "mojo";
614e1->department = mojom::Department::kEngineering;
615```
616
617is equivalent to
618
619```cpp
620auto e1 = mojom::Employee::New(42, "mojo", mojom::Department::kEngineering);
621```
622
623Now if we define an interface like:
624
625```cpp
626interface EmployeeManager {
627 AddEmployee(Employee e);
628};
629```
630
631We'll get this C++ interface to implement:
632
633```cpp
634class EmployeeManager {
635 public:
636 virtual ~EmployeManager() {}
637
638 virtual void AddEmployee(EmployeePtr e) = 0;
639};
640```
641
642And we can send this message from C++ code as follows:
643
644```cpp
645mojom::EmployeManagerPtr manager = ...;
646manager->AddEmployee(
647 Employee::New(42, "mojo", mojom::Department::kEngineering));
648
649// or
650auto e = Employee::New(42, "mojo", mojom::Department::kEngineering);
651manager->AddEmployee(std::move(e));
652```
653
654### Unions
655
656Similarly to [structs](#Structs), tagged unions generate an identically named,
657representative C++ class which is typically wrapped in a `mojo::StructPtr<T>`.
658
659Unlike structs, all generated union fields are private and must be retrieved and
Oksana Zhuravlovaa4da21f2019-03-20 20:41:58660manipulated using accessors. A field `foo` is accessible by `get_foo()` and
Ken Rockot686e4132017-04-26 00:03:31661settable by `set_foo()`. There is also a boolean `is_foo()` for each field which
662indicates whether the union is currently taking on the value of field `foo` in
663exclusion to all other union fields.
664
665Finally, every generated union class also has a nested `Tag` enum class which
666enumerates all of the named union fields. A Mojom union value's current type can
667be determined by calling the `which()` method which returns a `Tag`.
668
669For example, consider the following Mojom definitions:
670
671```cpp
672union Value {
673 int64 int_value;
Tom McKee1a5032f2018-08-02 17:14:55674 float float_value;
Ken Rockot686e4132017-04-26 00:03:31675 string string_value;
676};
677
678interface Dictionary {
679 AddValue(string key, Value value);
680};
681```
682
Tom McKee1a5032f2018-08-02 17:14:55683This generates the following C++ interface:
Ken Rockot686e4132017-04-26 00:03:31684
685```cpp
686class Value {
687 public:
Tom McKee1a5032f2018-08-02 17:14:55688 ~Value() {}
689};
690
691class Dictionary {
692 public:
693 virtual ~Dictionary() {}
Ken Rockot686e4132017-04-26 00:03:31694
695 virtual void AddValue(const std::string& key, ValuePtr value) = 0;
696};
697```
698
699And we can use it like so:
700
701```cpp
702ValuePtr value = Value::New();
703value->set_int_value(42);
704CHECK(value->is_int_value());
705CHECK_EQ(value->which(), Value::Tag::INT_VALUE);
706
707value->set_float_value(42);
708CHECK(value->is_float_value());
709CHECK_EQ(value->which(), Value::Tag::FLOAT_VALUE);
710
711value->set_string_value("bananas");
712CHECK(value->is_string_value());
713CHECK_EQ(value->which(), Value::Tag::STRING_VALUE);
714```
715
716Finally, note that if a union value is not currently occupied by a given field,
717attempts to access that field will DCHECK:
718
719```cpp
720ValuePtr value = Value::New();
721value->set_int_value(42);
722LOG(INFO) << "Value is " << value->string_value(); // DCHECK!
723```
724
rockotf59d2d62017-04-01 02:49:08725### Sending Interfaces Over Interfaces
726
Ken Rockot686e4132017-04-26 00:03:31727We know how to create interface pipes and use their Ptr and Request endpoints
728in some interesting ways. This still doesn't add up to interesting IPC! The
729bread and butter of Mojo IPC is the ability to transfer interface endpoints
730across other interfaces, so let's take a look at how to accomplish that.
rockotf59d2d62017-04-01 02:49:08731
732#### Sending Interface Requests
733
734Consider a new example Mojom in `//sample/db.mojom`:
735
736``` cpp
737module db.mojom;
738
739interface Table {
740 void AddRow(int32 key, string data);
741};
742
743interface Database {
744 AddTable(Table& table);
745};
746```
747
748As noted in the
Ken Rockot929282c2018-05-02 17:07:29749[Mojom IDL documentation](/mojo/public/tools/bindings/README.md#Primitive-Types),
rockotf59d2d62017-04-01 02:49:08750the `Table&` syntax denotes a `Table` interface request. This corresponds
751precisely to the `InterfaceRequest<T>` type discussed in the sections above, and
752in fact the generated code for these interfaces is approximately:
753
754``` cpp
755namespace db {
756namespace mojom {
757
758class Table {
759 public:
760 virtual ~Table() {}
761
762 virtual void AddRow(int32_t key, const std::string& data) = 0;
763}
764
765using TablePtr = mojo::InterfacePtr<Table>;
766using TableRequest = mojo::InterfaceRequest<Table>;
767
768class Database {
769 public:
770 virtual ~Database() {}
771
772 virtual void AddTable(TableRequest table);
773};
774
775using DatabasePtr = mojo::InterfacePtr<Database>;
776using DatabaseRequest = mojo::InterfaceRequest<Database>;
777
778} // namespace mojom
779} // namespace db
780```
781
782We can put this all together now with an implementation of `Table` and
783`Database`:
784
785``` cpp
786#include "sample/db.mojom.h"
787
788class TableImpl : public db::mojom:Table {
789 public:
790 explicit TableImpl(db::mojom::TableRequest request)
791 : binding_(this, std::move(request)) {}
792 ~TableImpl() override {}
793
794 // db::mojom::Table:
795 void AddRow(int32_t key, const std::string& data) override {
796 rows_.insert({key, data});
797 }
798
799 private:
800 mojo::Binding<db::mojom::Table> binding_;
801 std::map<int32_t, std::string> rows_;
802};
803
804class DatabaseImpl : public db::mojom::Database {
805 public:
806 explicit DatabaseImpl(db::mojom::DatabaseRequest request)
807 : binding_(this, std::move(request)) {}
808 ~DatabaseImpl() override {}
809
810 // db::mojom::Database:
811 void AddTable(db::mojom::TableRequest table) {
Jeremy Romancf9ae2f2017-08-24 17:06:37812 tables_.emplace_back(std::make_unique<TableImpl>(std::move(table)));
rockotf59d2d62017-04-01 02:49:08813 }
814
815 private:
816 mojo::Binding<db::mojom::Database> binding_;
817 std::vector<std::unique_ptr<TableImpl>> tables_;
818};
819```
820
821Pretty straightforward. The `Table&` Mojom paramter to `AddTable` translates to
822a C++ `db::mojom::TableRequest`, aliased from
823`mojo::InterfaceRequest<db::mojom::Table>`, which we know is just a
824strongly-typed message pipe handle. When `DatabaseImpl` gets an `AddTable` call,
825it constructs a new `TableImpl` and binds it to the received `TableRequest`.
826
827Let's see how this can be used.
828
829``` cpp
830db::mojom::DatabasePtr database;
831DatabaseImpl db_impl(mojo::MakeRequest(&database));
832
833db::mojom::TablePtr table1, table2;
834database->AddTable(mojo::MakeRequest(&table1));
835database->AddTable(mojo::MakeRequest(&table2));
836
837table1->AddRow(1, "hiiiiiiii");
838table2->AddRow(2, "heyyyyyy");
839```
840
841Notice that we can again start using the new `Table` pipes immediately, even
842while their `TableRequest` endpoints are still in transit.
843
844#### Sending InterfacePtrs
845
846Of course we can also send `InterfacePtr`s:
847
848``` cpp
849interface TableListener {
850 OnRowAdded(int32 key, string data);
851};
852
853interface Table {
854 AddRow(int32 key, string data);
855
856 AddListener(TableListener listener);
857};
858```
859
860This would generate a `Table::AddListener` signature like so:
861
862``` cpp
863 virtual void AddListener(TableListenerPtr listener) = 0;
864```
865
866and this could be used like so:
867
868``` cpp
869db::mojom::TableListenerPtr listener;
870TableListenerImpl impl(mojo::MakeRequest(&listener));
871table->AddListener(std::move(listener));
872```
873
874## Other Interface Binding Types
875
876The [Interfaces](#Interfaces) section above covers basic usage of the most
877common bindings object types: `InterfacePtr`, `InterfaceRequest`, and `Binding`.
878While these types are probably the most commonly used in practice, there are
879several other ways of binding both client- and implementation-side interface
880pipes.
881
882### Strong Bindings
883
884A **strong binding** exists as a standalone object which owns its interface
885implementation and automatically cleans itself up when its bound interface
886endpoint detects an error. The
Austin Tankiang670438aa2018-02-05 00:18:36887[**`MakeStrongBinding`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/strong_binding.h)
rockotf59d2d62017-04-01 02:49:08888function is used to create such a binding.
889.
890
891``` cpp
892class LoggerImpl : public sample::mojom::Logger {
893 public:
894 LoggerImpl() {}
895 ~LoggerImpl() override {}
896
897 // sample::mojom::Logger:
898 void Log(const std::string& message) override {
899 LOG(ERROR) << "[Logger] " << message;
900 }
901
902 private:
903 // NOTE: This doesn't own any Binding object!
904};
905
906db::mojom::LoggerPtr logger;
Jeremy Romancf9ae2f2017-08-24 17:06:37907mojo::MakeStrongBinding(std::make_unique<LoggerImpl>(),
rockotf59d2d62017-04-01 02:49:08908 mojo::MakeRequest(&logger));
909
910logger->Log("NOM NOM NOM MESSAGES");
911```
912
913Now as long as `logger` remains open somewhere in the system, the bound
scottmg66139202017-05-04 18:56:35914`LoggerImpl` on the other end will remain alive.
rockotf59d2d62017-04-01 02:49:08915
916### Binding Sets
917
918Sometimes it's useful to share a single implementation instance with multiple
919clients. [**`BindingSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/binding_set.h)
920makes this easy. Consider the Mojom:
921
922``` cpp
923module system.mojom;
924
925interface Logger {
926 Log(string message);
927};
928
929interface LoggerProvider {
930 GetLogger(Logger& logger);
931};
932```
933
934We can use `BindingSet` to bind multiple `Logger` requests to a single
935implementation instance:
936
937``` cpp
938class LogManager : public system::mojom::LoggerProvider,
939 public system::mojom::Logger {
940 public:
941 explicit LogManager(system::mojom::LoggerProviderRequest request)
942 : provider_binding_(this, std::move(request)) {}
943 ~LogManager() {}
944
945 // system::mojom::LoggerProvider:
946 void GetLogger(LoggerRequest request) override {
947 logger_bindings_.AddBinding(this, std::move(request));
948 }
949
950 // system::mojom::Logger:
951 void Log(const std::string& message) override {
952 LOG(ERROR) << "[Logger] " << message;
953 }
954
955 private:
956 mojo::Binding<system::mojom::LoggerProvider> provider_binding_;
957 mojo::BindingSet<system::mojom::Logger> logger_bindings_;
958};
959
960```
961
962
963### InterfacePtr Sets
964
965Similar to the `BindingSet` above, sometimes it's useful to maintain a set of
966`InterfacePtr`s for *e.g.* a set of clients observing some event.
967[**`InterfacePtrSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/interface_ptr_set.h)
968is here to help. Take the Mojom:
969
970``` cpp
971module db.mojom;
972
973interface TableListener {
974 OnRowAdded(int32 key, string data);
975};
976
977interface Table {
978 AddRow(int32 key, string data);
979 AddListener(TableListener listener);
980};
981```
982
983An implementation of `Table` might look something like like this:
984
985``` cpp
986class TableImpl : public db::mojom::Table {
987 public:
988 TableImpl() {}
989 ~TableImpl() override {}
990
991 // db::mojom::Table:
992 void AddRow(int32_t key, const std::string& data) override {
993 rows_.insert({key, data});
994 listeners_.ForEach([key, &data](db::mojom::TableListener* listener) {
995 listener->OnRowAdded(key, data);
996 });
997 }
998
999 void AddListener(db::mojom::TableListenerPtr listener) {
1000 listeners_.AddPtr(std::move(listener));
1001 }
1002
1003 private:
1004 mojo::InterfacePtrSet<db::mojom::Table> listeners_;
1005 std::map<int32_t, std::string> rows_;
1006};
1007```
1008
1009## Associated Interfaces
1010
Chase Phillips3f76e152018-07-18 20:45:261011Associated interfaces are interfaces which:
rockotf59d2d62017-04-01 02:49:081012
Chase Phillips3f76e152018-07-18 20:45:261013* enable running multiple interfaces over a single message pipe while
1014 preserving message ordering.
1015* make it possible for the bindings to access a single message pipe from
1016 multiple sequences.
1017
1018### Mojom
1019
1020A new keyword `associated` is introduced for interface pointer/request
1021fields. For example:
1022
1023``` cpp
1024interface Bar {};
1025
1026struct Qux {
1027 associated Bar bar3;
1028};
1029
1030interface Foo {
1031 // Uses associated interface pointer.
1032 SetBar(associated Bar bar1);
1033 // Uses associated interface request.
1034 GetBar(associated Bar& bar2);
1035 // Passes a struct with associated interface pointer.
1036 PassQux(Qux qux);
1037 // Uses associated interface pointer in callback.
1038 AsyncGetBar() => (associated Bar bar4);
1039};
1040```
1041
1042It means the interface impl/client will communicate using the same
1043message pipe over which the associated interface pointer/request is
1044passed.
1045
1046### Using associated interfaces in C++
1047
1048When generating C++ bindings, the associated interface pointer of `Bar` is
1049mapped to `BarAssociatedPtrInfo` (which is an alias of
1050`mojo::AssociatedInterfacePtrInfo<Bar>`); associated interface request to
1051`BarAssociatedRequest` (which is an alias of
1052`mojo::AssociatedInterfaceRequest<Bar>`).
1053
1054``` cpp
1055// In mojom:
1056interface Foo {
1057 ...
1058 SetBar(associated Bar bar1);
1059 GetBar(associated Bar& bar2);
1060 ...
1061};
1062
1063// In C++:
1064class Foo {
1065 ...
1066 virtual void SetBar(BarAssociatedPtrInfo bar1) = 0;
1067 virtual void GetBar(BarAssociatedRequest bar2) = 0;
1068 ...
1069};
1070```
1071
1072#### Passing associated interface requests
1073
1074Assume you have already got an `InterfacePtr<Foo> foo_ptr`, and you would like
1075to call `GetBar()` on it. You can do:
1076
1077``` cpp
1078BarAssociatedPtrInfo bar_ptr_info;
1079BarAssociatedRequest bar_request = MakeRequest(&bar_ptr_info);
1080foo_ptr->GetBar(std::move(bar_request));
1081
1082// BarAssociatedPtr is an alias of AssociatedInterfacePtr<Bar>.
1083BarAssociatedPtr bar_ptr;
1084bar_ptr.Bind(std::move(bar_ptr_info));
1085bar_ptr->DoSomething();
1086```
1087
1088First, the code creates an associated interface of type `Bar`. It looks very
1089similar to what you would do to setup a non-associated interface. An
1090important difference is that one of the two associated endpoints (either
1091`bar_request` or `bar_ptr_info`) must be sent over another interface. That is
1092how the interface is associated with an existing message pipe.
1093
1094It should be noted that you cannot call `bar_ptr->DoSomething()` before passing
1095`bar_request`. This is required by the FIFO-ness guarantee: at the receiver
1096side, when the message of `DoSomething` call arrives, we want to dispatch it to
1097the corresponding `AssociatedBinding<Bar>` before processing any subsequent
1098messages. If `bar_request` is in a subsequent message, message dispatching gets
1099into a deadlock. On the other hand, as soon as `bar_request` is sent, `bar_ptr`
1100is usable. There is no need to wait until `bar_request` is bound to an
1101implementation at the remote side.
1102
1103A `MakeRequest` overload which takes an `AssociatedInterfacePtr` pointer
1104(instead of an `AssociatedInterfacePtrInfo` pointer) is provided to make the
1105code a little shorter. The following code achieves the same purpose:
1106
1107``` cpp
1108BarAssociatedPtr bar_ptr;
1109foo_ptr->GetBar(MakeRequest(&bar_ptr));
1110bar_ptr->DoSomething();
1111```
1112
1113The implementation of `Foo` looks like this:
1114
1115``` cpp
1116class FooImpl : public Foo {
1117 ...
1118 void GetBar(BarAssociatedRequest bar2) override {
1119 bar_binding_.Bind(std::move(bar2));
1120 ...
1121 }
1122 ...
1123
1124 Binding<Foo> foo_binding_;
1125 AssociatedBinding<Bar> bar_binding_;
1126};
1127```
1128
1129In this example, `bar_binding_`'s lifespan is tied to that of `FooImpl`. But you
1130don't have to do that. You can, for example, pass `bar2` to another sequence to
1131bind to an `AssociatedBinding<Bar>` there.
1132
1133When the underlying message pipe is disconnected (e.g., `foo_ptr` or
1134`foo_binding_` is destroyed), all associated interface endpoints (e.g.,
1135`bar_ptr` and `bar_binding_`) will receive a connection error.
1136
1137#### Passing associated interface pointers
1138
1139Similarly, assume you have already got an `InterfacePtr<Foo> foo_ptr`, and you
1140would like to call `SetBar()` on it. You can do:
1141
1142``` cpp
Kenichi Ishibashi89e8bc92018-08-07 00:37:481143AssociatedBinding<Bar> bar_binding(some_bar_impl);
Chase Phillips3f76e152018-07-18 20:45:261144BarAssociatedPtrInfo bar_ptr_info;
1145BarAssociatedRequest bar_request = MakeRequest(&bar_ptr_info);
1146foo_ptr->SetBar(std::move(bar_ptr_info));
1147bar_binding.Bind(std::move(bar_request));
1148```
1149
1150The following code achieves the same purpose:
1151
1152``` cpp
Kenichi Ishibashi89e8bc92018-08-07 00:37:481153AssociatedBinding<Bar> bar_binding(some_bar_impl);
Chase Phillips3f76e152018-07-18 20:45:261154BarAssociatedPtrInfo bar_ptr_info;
1155bar_binding.Bind(&bar_ptr_info);
1156foo_ptr->SetBar(std::move(bar_ptr_info));
1157```
1158
1159### Performance considerations
1160
1161When using associated interfaces on different sequences than the master sequence
1162(where the master interface lives):
1163
1164* Sending messages: send happens directly on the calling sequence. So there
1165 isn't sequence hopping.
1166* Receiving messages: associated interfaces bound on a different sequence from
1167 the master interface incur an extra sequence hop during dispatch.
1168
1169Therefore, performance-wise associated interfaces are better suited for
1170scenarios where message receiving happens on the master sequence.
1171
1172### Testing
1173
1174Associated interfaces need to be associated with a master interface before
1175they can be used. This means one end of the associated interface must be sent
1176over one end of the master interface, or over one end of another associated
1177interface which itself already has a master interface.
1178
1179If you want to test an associated interface endpoint without first
Adithya Srinivasan4b6c6082018-11-14 16:56:461180associating it, you can use `mojo::MakeRequestAssociatedWithDedicatedPipe`. This
1181will create working associated interface endpoints which are not actually
1182associated with anything else.
Chase Phillips3f76e152018-07-18 20:45:261183
1184### Read more
1185
1186* [Design: Mojo Associated Interfaces](https://docs.google.com/document/d/1nq3J_HbS-gvVfIoEhcVyxm1uY-9G_7lhD-4Kyxb1WIY/edit)
rockotf59d2d62017-04-01 02:49:081187
1188## Synchronous Calls
1189
Oksana Zhuravlova50bac902019-01-15 00:17:591190### Think carefully before you decide to use sync calls
rockotf59d2d62017-04-01 02:49:081191
Oksana Zhuravlova50bac902019-01-15 00:17:591192Although sync calls are convenient, you should avoid them whenever they
1193are not absolutely necessary:
1194
1195* Sync calls hurt parallelism and therefore hurt performance.
1196* Re-entrancy changes message order and produces call stacks that you
1197probably never think about while you are coding. It has always been a
1198huge pain.
1199* Sync calls may lead to deadlocks.
1200
1201### Mojom changes
1202
1203A new attribute `[Sync]` (or `[Sync=true]`) is introduced for methods.
1204For example:
1205
1206``` cpp
1207interface Foo {
1208 [Sync]
1209 SomeSyncCall() => (Bar result);
1210};
1211```
1212
1213It indicates that when `SomeSyncCall()` is called, the control flow of
1214the calling thread is blocked until the response is received.
1215
1216It is not allowed to use this attribute with functions that don’t have
1217responses. If you just need to wait until the service side finishes
1218processing the call, you can use an empty response parameter list:
1219
1220``` cpp
1221[Sync]
1222SomeSyncCallWithNoResult() => ();
1223```
1224
1225### Generated bindings (C++)
1226
1227The generated C++ interface of the Foo interface above is:
1228
1229``` cpp
1230class Foo {
1231 public:
1232 // The service side implements this signature. The client side can
1233 // also use this signature if it wants to call the method asynchronously.
1234 virtual void SomeSyncCall(SomeSyncCallCallback callback) = 0;
1235
1236 // The client side uses this signature to call the method synchronously.
1237 virtual bool SomeSyncCall(BarPtr* result);
1238};
1239```
1240
1241As you can see, the client side and the service side use different
1242signatures. At the client side, response is mapped to output parameters
1243and the boolean return value indicates whether the operation is
1244successful. (Returning false usually means a connection error has
1245occurred.)
1246
1247At the service side, a signature with callback is used. The reason is
1248that in some cases the implementation may need to do some asynchronous
1249work which the sync method’s result depends on.
1250
1251*** note
1252**NOTE:** you can also use the signature with callback at the client side to
1253call the method asynchronously.
1254***
1255
1256### Re-entrancy
1257
1258What happens on the calling thread while waiting for the response of a
1259sync method call? It continues to process incoming sync request messages
1260(i.e., sync method calls); block other messages, including async
1261messages and sync response messages that don’t match the ongoing sync
1262call.
1263
Ken Rockotab035122019-02-06 00:35:241264![Diagram illustrating sync call flow](/docs/images/mojo_sync_call_flow.png)
Oksana Zhuravlova50bac902019-01-15 00:17:591265
1266Please note that sync response messages that don’t match the ongoing
1267sync call cannot re-enter. That is because they correspond to sync calls
1268down in the call stack. Therefore, they need to be queued and processed
1269while the stack unwinds.
1270
1271### Avoid deadlocks
1272
1273Please note that the re-entrancy behavior doesn’t prevent deadlocks
1274involving async calls. You need to avoid call sequences such as:
1275
Ken Rockotab035122019-02-06 00:35:241276![Diagram illustrating a sync call deadlock](/docs/images/mojo_sync_call_deadlock.png)
Oksana Zhuravlova50bac902019-01-15 00:17:591277
1278### Read more
1279
1280* [Design Proposal: Mojo Sync Methods](
1281https://docs.google.com/document/d/1dixzFzZQW8e3ldjdM8Adbo8klXDDE4pVekwo5aLgUsE)
rockotf59d2d62017-04-01 02:49:081282
1283## Type Mapping
1284
1285In many instances you might prefer that your generated C++ bindings use a more
1286natural type to represent certain Mojom types in your interface methods. For one
1287example consider a Mojom struct such as the `Rect` below:
1288
1289``` cpp
1290module gfx.mojom;
1291
1292struct Rect {
1293 int32 x;
1294 int32 y;
1295 int32 width;
1296 int32 height;
1297};
1298
1299interface Canvas {
1300 void FillRect(Rect rect);
1301};
1302```
1303
1304The `Canvas` Mojom interface would normally generate a C++ interface like:
1305
1306``` cpp
1307class Canvas {
1308 public:
1309 virtual void FillRect(RectPtr rect) = 0;
1310};
1311```
1312
1313However, the Chromium tree already defines a native
1314[`gfx::Rect`](https://cs.chromium.org/chromium/src/ui/gfx/geometry/rect.h) which
1315is equivalent in meaning but which also has useful helper methods. Instead of
1316manually converting between a `gfx::Rect` and the Mojom-generated `RectPtr` at
1317every message boundary, wouldn't it be nice if the Mojom bindings generator
1318could instead generate:
1319
1320``` cpp
1321class Canvas {
1322 public:
1323 virtual void FillRect(const gfx::Rect& rect) = 0;
1324}
1325```
1326
1327The correct answer is, "Yes! That would be nice!" And fortunately, it can!
1328
1329### Global Configuration
1330
1331While this feature is quite powerful, it introduces some unavoidable complexity
1332into build system. This stems from the fact that type-mapping is an inherently
1333viral concept: if `gfx::mojom::Rect` is mapped to `gfx::Rect` anywhere, the
1334mapping needs to apply *everywhere*.
1335
1336For this reason we have a few global typemap configurations defined in
sky0b887ae2017-05-18 03:26:031337[chromium_bindings_configuration.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/chromium_bindings_configuration.gni)
rockotf59d2d62017-04-01 02:49:081338and
sky0b887ae2017-05-18 03:26:031339[blink_bindings_configuration.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/blink_bindings_configuration.gni). These configure the two supported [variants](#Variants) of Mojom generated
rockotf59d2d62017-04-01 02:49:081340bindings in the repository. Read more on this in the sections that follow.
1341
1342For now, let's take a look at how to express the mapping from `gfx::mojom::Rect`
1343to `gfx::Rect`.
1344
1345### Defining `StructTraits`
1346
1347In order to teach generated bindings code how to serialize an arbitrary native
1348type `T` as an arbitrary Mojom type `mojom::U`, we need to define an appropriate
1349specialization of the
1350[`mojo::StructTraits`](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/struct_traits.h)
1351template.
1352
1353A valid specialization of `StructTraits` MUST define the following static
1354methods:
1355
1356* A single static accessor for every field of the Mojom struct, with the exact
1357 same name as the struct field. These accessors must all take a const ref to
1358 an object of the native type, and must return a value compatible with the
1359 Mojom struct field's type. This is used to safely and consistently extract
1360 data from the native type during message serialization without incurring extra
1361 copying costs.
1362
1363* A single static `Read` method which initializes an instance of the the native
1364 type given a serialized representation of the Mojom struct. The `Read` method
1365 must return a `bool` to indicate whether the incoming data is accepted
1366 (`true`) or rejected (`false`).
1367
1368There are other methods a `StructTraits` specialization may define to satisfy
1369some less common requirements. See
1370[Advanced StructTraits Usage](#Advanced-StructTraits-Usage) for details.
1371
1372In order to define the mapping for `gfx::Rect`, we want the following
1373`StructTraits` specialization, which we'll define in
Stephen Nusko0ea37f3d2019-02-17 01:45:191374`//ui/gfx/geometry/mojo/geometry_mojom_traits.h`:
rockotf59d2d62017-04-01 02:49:081375
1376``` cpp
Stephen Nusko0ea37f3d2019-02-17 01:45:191377#include "mojo/public/cpp/bindings/mojom_traits.h"
rockotf59d2d62017-04-01 02:49:081378#include "ui/gfx/geometry/rect.h"
1379#include "ui/gfx/geometry/mojo/geometry.mojom.h"
1380
1381namespace mojo {
1382
1383template <>
1384class StructTraits<gfx::mojom::RectDataView, gfx::Rect> {
1385 public:
1386 static int32_t x(const gfx::Rect& r) { return r.x(); }
1387 static int32_t y(const gfx::Rect& r) { return r.y(); }
1388 static int32_t width(const gfx::Rect& r) { return r.width(); }
1389 static int32_t height(const gfx::Rect& r) { return r.height(); }
1390
1391 static bool Read(gfx::mojom::RectDataView data, gfx::Rect* out_rect);
1392};
1393
1394} // namespace mojo
1395```
1396
Stephen Nusko0ea37f3d2019-02-17 01:45:191397And in `//ui/gfx/geometry/mojo/geometry_mojom_traits.cc`:
rockotf59d2d62017-04-01 02:49:081398
1399``` cpp
Stephen Nusko0ea37f3d2019-02-17 01:45:191400#include "ui/gfx/geometry/mojo/geometry_mojom_traits.h"
rockotf59d2d62017-04-01 02:49:081401
1402namespace mojo {
1403
1404// static
1405template <>
1406bool StructTraits<gfx::mojom::RectDataView, gfx::Rect>::Read(
1407 gfx::mojom::RectDataView data,
1408 gfx::Rect* out_rect) {
1409 if (data.width() < 0 || data.height() < 0)
1410 return false;
1411
1412 out_rect->SetRect(data.x(), data.y(), data.width(), data.height());
1413 return true;
1414};
1415
1416} // namespace mojo
1417```
1418
1419Note that the `Read()` method returns `false` if either the incoming `width` or
1420`height` fields are negative. This acts as a validation step during
1421deserialization: if a client sends a `gfx::Rect` with a negative width or
1422height, its message will be rejected and the pipe will be closed. In this way,
1423type mapping can serve to enable custom validation logic in addition to making
1424callsites and interface implemention more convenient.
1425
Oksana Zhuravlova4b594672018-11-06 21:58:251426When the struct fields have non-primitive types, e.g. string or array,
1427returning a read-only view of the data in the accessor is recommended to
1428avoid copying. It is safe because the input object is guaranteed to
1429outlive the usage of the result returned by the accessor method.
1430
1431The following example uses `StringPiece` to return a view of the GURL's
1432data (`//url/mojom/url_gurl_mojom_traits.h`):
1433
1434``` cpp
1435#include "base/strings/string_piece.h"
1436#include "url/gurl.h"
1437#include "url/mojom/url.mojom.h"
1438#include "url/url_constants.h"
1439
1440namespace mojo {
1441
1442template <>
1443struct StructTraits<url::mojom::UrlDataView, GURL> {
1444 static base::StringPiece url(const GURL& r) {
1445 if (r.possibly_invalid_spec().length() > url::kMaxURLChars ||
1446 !r.is_valid()) {
1447 return base::StringPiece();
1448 }
1449 return base::StringPiece(r.possibly_invalid_spec().c_str(),
1450 r.possibly_invalid_spec().length());
1451 }
1452} // namespace mojo
1453```
1454
rockotf59d2d62017-04-01 02:49:081455### Enabling a New Type Mapping
1456
1457We've defined the `StructTraits` necessary, but we still need to teach the
1458bindings generator (and hence the build system) about the mapping. To do this we
1459must create a **typemap** file, which uses familiar GN syntax to describe the
1460new type mapping.
1461
1462Let's place this `geometry.typemap` file alongside our Mojom file:
1463
1464```
1465mojom = "//ui/gfx/geometry/mojo/geometry.mojom"
Oksana Zhuravlova7e09e662018-11-29 21:11:251466os_whitelist = [ "android" ]
rockotf59d2d62017-04-01 02:49:081467public_headers = [ "//ui/gfx/geometry/rect.h" ]
Stephen Nusko0ea37f3d2019-02-17 01:45:191468traits_headers = [ "//ui/gfx/geometry/mojo/geometry_mojom_traits.h" ]
Ken Rockotdb79117e2018-01-17 20:36:081469sources = [
Stephen Nusko0ea37f3d2019-02-17 01:45:191470 "//ui/gfx/geometry/mojo/geometry_mojom_traits.cc",
1471 "//ui/gfx/geometry/mojo/geometry_mojom_traits.h",
Ken Rockotdb79117e2018-01-17 20:36:081472]
rockotf59d2d62017-04-01 02:49:081473public_deps = [ "//ui/gfx/geometry" ]
1474type_mappings = [
1475 "gfx.mojom.Rect=gfx::Rect",
1476]
1477```
1478
1479Let's look at each of the variables above:
1480
1481* `mojom`: Specifies the `mojom` file to which the typemap applies. Many
1482 typemaps may apply to the same `mojom` file, but any given typemap may only
1483 apply to a single `mojom` file.
Oksana Zhuravlova7e09e662018-11-29 21:11:251484* `os_whitelist`: Optional list of specific platforms this typemap
1485 should be constrained to.
rockotf59d2d62017-04-01 02:49:081486* `public_headers`: Additional headers required by any code which would depend
1487 on the Mojom definition of `gfx.mojom.Rect` now that the typemap is applied.
1488 Any headers required for the native target type definition should be listed
1489 here.
1490* `traits_headers`: Headers which contain the relevant `StructTraits`
1491 specialization(s) for any type mappings described by this file.
Stephen Nusko0ea37f3d2019-02-17 01:45:191492* `sources`: Any implementation sources needed for the `StructTraits`
1493 definition. These sources are compiled directly into the generated C++
1494 bindings target for a `mojom` file applying this typemap.
rockotf59d2d62017-04-01 02:49:081495* `public_deps`: Target dependencies exposed by the `public_headers` and
1496 `traits_headers`.
1497* `deps`: Target dependencies exposed by `sources` but not already covered by
1498 `public_deps`.
1499* `type_mappings`: A list of type mappings to be applied for this typemap. The
1500 strings in this list are of the format `"MojomType=CppType"`, where
1501 `MojomType` must be a fully qualified Mojom typename and `CppType` must be a
1502 fully qualified C++ typename. Additional attributes may be specified in square
1503 brackets following the `CppType`:
1504 * `move_only`: The `CppType` is move-only and should be passed by value
1505 in any generated method signatures. Note that `move_only` is transitive,
1506 so containers of `MojomType` will translate to containers of `CppType`
1507 also passed by value.
1508 * `copyable_pass_by_value`: Forces values of type `CppType` to be passed by
1509 value without moving them. Unlike `move_only`, this is not transitive.
1510 * `nullable_is_same_type`: By default a non-nullable `MojomType` will be
1511 mapped to `CppType` while a nullable `MojomType?` will be mapped to
1512 `base::Optional<CppType>`. If this attribute is set, the `base::Optional`
1513 wrapper is omitted for nullable `MojomType?` values, but the
1514 `StructTraits` definition for this type mapping must define additional
1515 `IsNull` and `SetToNull` methods. See
1516 [Specializing Nullability](#Specializing-Nullability) below.
Ken Rockotc9c268a92018-01-31 21:04:401517 * `force_serialize`: The typemap is incompatible with lazy serialization
1518 (e.g. consider a typemap to a `base::StringPiece`, where retaining a
1519 copy is unsafe). Any messages carrying the type will be forced down the
1520 eager serailization path.
rockotf59d2d62017-04-01 02:49:081521
1522
1523Now that we have the typemap file we need to add it to a local list of typemaps
1524that can be added to the global configuration. We create a new
1525`//ui/gfx/typemaps.gni` file with the following contents:
1526
1527```
1528typemaps = [
1529 "//ui/gfx/geometry/mojo/geometry.typemap",
1530]
1531```
1532
1533And finally we can reference this file in the global default (Chromium) bindings
1534configuration by adding it to `_typemap_imports` in
sky0b887ae2017-05-18 03:26:031535[chromium_bindings_configuration.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/chromium_bindings_configuration.gni):
rockotf59d2d62017-04-01 02:49:081536
1537```
1538_typemap_imports = [
1539 ...,
1540 "//ui/gfx/typemaps.gni",
1541 ...,
1542]
1543```
1544
1545### StructTraits Reference
1546
1547Each of a `StructTraits` specialization's static getter methods -- one per
1548struct field -- must return a type which can be used as a data source for the
1549field during serialization. This is a quick reference mapping Mojom field type
1550to valid getter return types:
1551
1552| Mojom Field Type | C++ Getter Return Type |
1553|------------------------------|------------------------|
1554| `bool` | `bool`
1555| `int8` | `int8_t`
1556| `uint8` | `uint8_t`
1557| `int16` | `int16_t`
1558| `uint16` | `uint16_t`
1559| `int32` | `int32_t`
1560| `uint32` | `uint32_t`
1561| `int64` | `int64_t`
1562| `uint64` | `uint64_t`
1563| `float` | `float`
1564| `double` | `double`
1565| `handle` | `mojo::ScopedHandle`
1566| `handle<message_pipe>` | `mojo::ScopedMessagePipeHandle`
1567| `handle<data_pipe_consumer>` | `mojo::ScopedDataPipeConsumerHandle`
1568| `handle<data_pipe_producer>` | `mojo::ScopedDataPipeProducerHandle`
1569| `handle<shared_buffer>` | `mojo::ScopedSharedBufferHandle`
1570| `FooInterface` | `FooInterfacePtr`
1571| `FooInterface&` | `FooInterfaceRequest`
1572| `associated FooInterface` | `FooAssociatedInterfacePtr`
1573| `associated FooInterface&` | `FooAssociatedInterfaceRequest`
1574| `string` | Value or reference to any type `T` that has a `mojo::StringTraits` specialization defined. By default this includes `std::string`, `base::StringPiece`, and `WTF::String` (Blink).
1575| `array<T>` | Value or reference to any type `T` that has a `mojo::ArrayTraits` specialization defined. By default this includes `std::vector<T>`, `mojo::CArray<T>`, and `WTF::Vector<T>` (Blink).
1576| `map<K, V>` | Value or reference to any type `T` that has a `mojo::MapTraits` specialization defined. By default this includes `std::map<T>`, `mojo::unordered_map<T>`, and `WTF::HashMap<T>` (Blink).
1577| `FooEnum` | Value of any type that has an appropriate `EnumTraits` specialization defined. By default this inlcudes only the generated `FooEnum` type.
1578| `FooStruct` | Value or reference to any type that has an appropriate `StructTraits` specialization defined. By default this includes only the generated `FooStructPtr` type.
1579| `FooUnion` | Value of reference to any type that has an appropriate `UnionTraits` specialization defined. By default this includes only the generated `FooUnionPtr` type.
1580
1581### Using Generated DataView Types
1582
1583Static `Read` methods on `StructTraits` specializations get a generated
1584`FooDataView` argument (such as the `RectDataView` in the example above) which
1585exposes a direct view of the serialized Mojom structure within an incoming
1586message's contents. In order to make this as easy to work with as possible, the
1587generated `FooDataView` types have a generated method corresponding to every
1588struct field:
1589
1590* For POD field types (*e.g.* bools, floats, integers) these are simple accessor
1591 methods with names identical to the field name. Hence in the `Rect` example we
1592 can access things like `data.x()` and `data.width()`. The return types
1593 correspond exactly to the mappings listed in the table above, under
1594 [StructTraits Reference](#StructTraits-Reference).
1595
1596* For handle and interface types (*e.g* `handle` or `FooInterface&`) these
1597 are named `TakeFieldName` (for a field named `field_name`) and they return an
1598 appropriate move-only handle type by value. The return types correspond
1599 exactly to the mappings listed in the table above, under
1600 [StructTraits Reference](#StructTraits-Reference).
1601
1602* For all other field types (*e.g.*, enums, strings, arrays, maps, structs)
1603 these are named `ReadFieldName` (for a field named `field_name`) and they
1604 return a `bool` (to indicate success or failure in reading). On success they
1605 fill their output argument with the deserialized field value. The output
1606 argument may be a pointer to any type with an appropriate `StructTraits`
1607 specialization defined, as mentioned in the table above, under
1608 [StructTraits Reference](#StructTraits-Reference).
1609
1610An example would be useful here. Suppose we introduced a new Mojom struct:
1611
1612``` cpp
1613struct RectPair {
1614 Rect left;
1615 Rect right;
1616};
1617```
1618
1619and a corresponding C++ type:
1620
1621``` cpp
1622class RectPair {
1623 public:
1624 RectPair() {}
1625
1626 const gfx::Rect& left() const { return left_; }
1627 const gfx::Rect& right() const { return right_; }
1628
1629 void Set(const gfx::Rect& left, const gfx::Rect& right) {
1630 left_ = left;
1631 right_ = right;
1632 }
1633
1634 // ... some other stuff
1635
1636 private:
1637 gfx::Rect left_;
1638 gfx::Rect right_;
1639};
1640```
1641
1642Our traits to map `gfx::mojom::RectPair` to `gfx::RectPair` might look like
1643this:
1644
1645``` cpp
1646namespace mojo {
1647
1648template <>
1649class StructTraits
1650 public:
1651 static const gfx::Rect& left(const gfx::RectPair& pair) {
1652 return pair.left();
1653 }
1654
1655 static const gfx::Rect& right(const gfx::RectPair& pair) {
1656 return pair.right();
1657 }
1658
1659 static bool Read(gfx::mojom::RectPairDataView data, gfx::RectPair* out_pair) {
1660 gfx::Rect left, right;
1661 if (!data.ReadLeft(&left) || !data.ReadRight(&right))
1662 return false;
1663 out_pair->Set(left, right);
1664 return true;
1665 }
1666} // namespace mojo
1667```
1668
1669Generated `ReadFoo` methods always convert `multi_word_field_name` fields to
1670`ReadMultiWordFieldName` methods.
1671
Andrew Moylan341cece72017-06-22 22:03:021672<a name="Blink-Type-Mapping"></a>
rockotf59d2d62017-04-01 02:49:081673### Variants
1674
1675By now you may have noticed that additional C++ sources are generated when a
1676Mojom is processed. These exist due to type mapping, and the source files we
1677refer to throughout this docuemnt (namely `foo.mojom.cc` and `foo.mojom.h`) are
1678really only one **variant** (the *default* or *chromium* variant) of the C++
1679bindings for a given Mojom file.
1680
1681The only other variant currently defined in the tree is the *blink* variant,
1682which produces a few additional files:
1683
1684```
1685out/gen/sample/db.mojom-blink.cc
1686out/gen/sample/db.mojom-blink.h
1687```
1688
1689These files mirror the definitions in the default variant but with different
1690C++ types in place of certain builtin field and parameter types. For example,
1691Mojom strings are represented by `WTF::String` instead of `std::string`. To
1692avoid symbol collisions, the variant's symbols are nested in an extra inner
1693namespace, so Blink consumer of the interface might write something like:
1694
1695```
1696#include "sample/db.mojom-blink.h"
1697
1698class TableImpl : public db::mojom::blink::Table {
1699 public:
1700 void AddRow(int32_t key, const WTF::String& data) override {
1701 // ...
1702 }
1703};
1704```
1705
1706In addition to using different C++ types for builtin strings, arrays, and maps,
1707the global typemap configuration for default and "blink" variants are completely
1708separate. To add a typemap for the Blink configuration, you can modify
1709[blink_bindings_configuration.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/blink_bindings_configuration.gni).
1710
1711All variants share some definitions which are unaffected by differences in the
1712type mapping configuration (enums, for example). These definitions are generated
1713in *shared* sources:
1714
1715```
1716out/gen/sample/db.mojom-shared.cc
1717out/gen/sample/db.mojom-shared.h
1718out/gen/sample/db.mojom-shared-internal.h
1719```
1720
1721Including either variant's header (`db.mojom.h` or `db.mojom-blink.h`)
Andrew Moylan341cece72017-06-22 22:03:021722implicitly includes the shared header, but may wish to include *only* the shared
1723header in some instances.
rockotf59d2d62017-04-01 02:49:081724
1725Finally, note that for `mojom` GN targets, there is implicitly a corresponding
1726`mojom_{variant}` target defined for any supported bindings configuration. So
1727for example if you've defined in `//sample/BUILD.gn`:
1728
1729```
1730import("mojo/public/tools/bindings/mojom.gni")
1731
Oksana Zhuravlovad5fea16d2018-08-15 00:02:171732mojom("mojom") {
rockotf59d2d62017-04-01 02:49:081733 sources = [
1734 "db.mojom",
1735 ]
1736}
1737```
1738
1739Code in Blink which wishes to use the generated Blink-variant definitions must
Oksana Zhuravlovad5fea16d2018-08-15 00:02:171740depend on `"//sample:mojom_blink"`.
rockotf59d2d62017-04-01 02:49:081741
1742## Versioning Considerations
1743
1744For general documentation of versioning in the Mojom IDL see
Ken Rockot929282c2018-05-02 17:07:291745[Versioning](/mojo/public/tools/bindings/README.md#Versiwoning).
rockotf59d2d62017-04-01 02:49:081746
1747This section briefly discusses some C++-specific considerations relevant to
1748versioned Mojom types.
1749
1750### Querying Interface Versions
1751
1752`InterfacePtr` defines the following methods to query or assert remote interface
1753version:
1754
1755```cpp
1756void QueryVersion(const base::Callback<void(uint32_t)>& callback);
1757```
1758
1759This queries the remote endpoint for the version number of its binding. When a
1760response is received `callback` is invoked with the remote version number. Note
1761that this value is cached by the `InterfacePtr` instance to avoid redundant
1762queries.
1763
1764```cpp
1765void RequireVersion(uint32_t version);
1766```
1767
1768Informs the remote endpoint that a minimum version of `version` is required by
1769the client. If the remote endpoint cannot support that version, it will close
1770its end of the pipe immediately, preventing any other requests from being
1771received.
1772
1773### Versioned Enums
1774
1775For convenience, every extensible enum has a generated helper function to
1776determine whether a received enum value is known by the implementation's current
1777version of the enum definition. For example:
1778
1779```cpp
1780[Extensible]
1781enum Department {
1782 SALES,
1783 DEV,
1784 RESEARCH,
1785};
1786```
1787
1788generates the function in the same namespace as the generated C++ enum type:
1789
1790```cpp
1791inline bool IsKnownEnumValue(Department value);
1792```
1793
Sasha Bermeister995adc62017-12-07 02:36:431794### Using Mojo Bindings in Chrome
1795
Oksana Zhuravlova87b225a2019-03-07 01:08:031796See [Converting Legacy Chrome IPC To Mojo](/docs/mojo_ipc_conversion.md).
Sasha Bermeister995adc62017-12-07 02:36:431797
rockotf59d2d62017-04-01 02:49:081798### Additional Documentation
1799
1800[Calling Mojo From Blink](https://www.chromium.org/developers/design-documents/mojo/calling-mojo-from-blink)
1801: A brief overview of what it looks like to use Mojom C++ bindings from
1802 within Blink code.