blob: e27d13fc7e1d4432a2de2e2da895e977b33b9e74 [file] [log] [blame] [view]
Ken Rockot686e4132017-04-26 00:03:311# Mojo C++ Bindings API
rockotf59d2d62017-04-01 02:49:082This document is a subset of the [Mojo documentation](/mojo).
3
4[TOC]
5
6## Overview
7The Mojo C++ Bindings API leverages the
8[C++ System API](/mojo/public/cpp/system) to provide a more natural set of
9primitives for communicating over Mojo message pipes. Combined with generated
10code from the [Mojom IDL and bindings generator](/mojo/public/tools/bindings),
11users can easily connect interface clients and implementations across arbitrary
12intra- and inter-process bounaries.
13
14This document provides a detailed guide to bindings API usage with example code
15snippets. For a detailed API references please consult the headers in
16[//mojo/public/cpp/bindings](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/).
17
18## Getting Started
19
20When a Mojom IDL file is processed by the bindings generator, C++ code is
21emitted in a series of `.h` and `.cc` files with names based on the input
22`.mojom` file. Suppose we create the following Mojom file at
23`//services/db/public/interfaces/db.mojom`:
24
25```
26module db.mojom;
27
28interface Table {
29 AddRow(int32 key, string data);
30};
31
32interface Database {
33 CreateTable(Table& table);
34};
35```
36
37And a GN target to generate the bindings in
38`//services/db/public/interfaces/BUILD.gn`:
39
40```
41import("//mojo/public/tools/bindings/mojom.gni")
42
43mojom("interfaces") {
44 sources = [
45 "db.mojom",
46 ]
47}
48```
49
50If we then build this target:
51
52```
53ninja -C out/r services/db/public/interfaces
54```
55
56This will produce several generated source files, some of which are relevant to
57C++ bindings. Two of these files are:
58
59```
Yuzhu Shene70d1972017-06-02 16:35:1560out/gen/services/db/public/interfaces/db.mojom.cc
61out/gen/services/db/public/interfaces/db.mojom.h
rockotf59d2d62017-04-01 02:49:0862```
63
64You can include the above generated header in your sources in order to use the
65definitions therein:
66
67``` cpp
68#include "services/business/public/interfaces/factory.mojom.h"
69
70class TableImpl : public db::mojom::Table {
71 // ...
72};
73```
74
75This document covers the different kinds of definitions generated by Mojom IDL
76for C++ consumers and how they can effectively be used to communicate across
77message pipes.
78
79*** note
80**NOTE:** Using C++ bindings from within Blink code is typically subject to
81special constraints which require the use of a different generated header.
82For details, see [Blink Type Mapping](#Blink-Type-Mapping).
83***
84
85## Interfaces
86
87Mojom IDL interfaces are translated to corresponding C++ (pure virtual) class
88interface definitions in the generated header, consisting of a single generated
89method signature for each request message on the interface. Internally there is
90also generated code for serialization and deserialization of messages, but this
91detail is hidden from bindings consumers.
92
93### Basic Usage
94
95Let's consider a new `//sample/logger.mojom` to define a simple logging
96interface which clients can use to log simple string messages:
97
98``` cpp
99module sample.mojom;
100
101interface Logger {
102 Log(string message);
103};
104```
105
106Running this through the bindings generator will produce a `logging.mojom.h`
107with the following definitions (modulo unimportant details):
108
109``` cpp
110namespace sample {
111namespace mojom {
112
113class Logger {
114 virtual ~Logger() {}
115
116 virtual void Log(const std::string& message) = 0;
117};
118
119using LoggerPtr = mojo::InterfacePtr<Logger>;
120using LoggerRequest = mojo::InterfaceRequest<Logger>;
121
122} // namespace mojom
123} // namespace sample
124```
125
126Makes sense. Let's take a closer look at those type aliases at the end.
127
128### InterfacePtr and InterfaceRequest
129
130You will notice the type aliases for `LoggerPtr` and
131`LoggerRequest` are using two of the most fundamental template types in the C++
132bindings library: **`InterfacePtr<T>`** and **`InterfaceRequest<T>`**.
133
134In the world of Mojo bindings libraries these are effectively strongly-typed
135message pipe endpoints. If an `InterfacePtr<T>` is bound to a message pipe
136endpoint, it can be dereferenced to make calls on an opaque `T` interface. These
137calls immediately serialize their arguments (using generated code) and write a
138corresponding message to the pipe.
139
140An `InterfaceRequest<T>` is essentially just a typed container to hold the other
141end of an `InterfacePtr<T>`'s pipe -- the receiving end -- until it can be
142routed to some implementation which will **bind** it. The `InterfaceRequest<T>`
143doesn't actually *do* anything other than hold onto a pipe endpoint and carry
144useful compile-time type information.
145
Ken Rockot856f9772017-04-11 19:41:39146![Diagram illustrating InterfacePtr and InterfaceRequest on either end of a message pipe](https://docs.google.com/drawings/d/1_Ocprq7EGgTKcSE_WlOn_RBfXcr5C3FJyIbWhwzwNX8/pub?w=608&h=100)
rockotf59d2d62017-04-01 02:49:08147
148So how do we create a strongly-typed message pipe?
149
150### Creating Interface Pipes
151
Ken Rockotf4d8a942017-05-13 00:10:37152One way to do this is by manually creating a pipe and wrapping each end with a
153strongly-typed object:
rockotf59d2d62017-04-01 02:49:08154
155``` cpp
156#include "sample/logger.mojom.h"
157
158mojo::MessagePipe pipe;
Ken Rockotf4d8a942017-05-13 00:10:37159sample::mojom::LoggerPtr logger(
160 sample::mojom::LoggerPtrInfo(std::move(pipe.handle0), 0));
161sample::mojom::LoggerRequest request(std::move(pipe.handle1));
rockotf59d2d62017-04-01 02:49:08162```
163
Ken Rockotf4d8a942017-05-13 00:10:37164That's pretty verbose, but the C++ Bindings library provides a more convenient
165way 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:08166defines a `MakeRequest` function:
167
168``` cpp
169sample::mojom::LoggerPtr logger;
Ken Rockotf4d8a942017-05-13 00:10:37170auto request = mojo::MakeRequest(&logger);
rockotf59d2d62017-04-01 02:49:08171```
172
Ken Rockotf4d8a942017-05-13 00:10:37173This second snippet is equivalent to the first one.
rockotf59d2d62017-04-01 02:49:08174
175*** note
176**NOTE:** In the first example above you may notice usage of the `LoggerPtrInfo`
177type, which is a generated alias for `mojo::InterfacePtrInfo<Logger>`. This is
178similar to an `InterfaceRequest<T>` in that it merely holds onto a pipe handle
179and cannot actually read or write messages on the pipe. Both this type and
Sam McNallyd482b4b2017-07-17 03:45:03180`InterfaceRequest<T>` are safe to move freely from sequence to sequence, whereas
181a bound `InterfacePtr<T>` is bound to a single sequence.
rockotf59d2d62017-04-01 02:49:08182
183An `InterfacePtr<T>` may be unbound by calling its `PassInterface()` method,
184which returns a new `InterfacePtrInfo<T>`. Conversely, an `InterfacePtr<T>` may
185bind (and thus take ownership of) an `InterfacePtrInfo<T>` so that interface
186calls can be made on the pipe.
187
Sam McNallyd482b4b2017-07-17 03:45:03188The sequence-bound nature of `InterfacePtr<T>` is necessary to support safe
rockotf59d2d62017-04-01 02:49:08189dispatch of its [message responses](#Receiving-Responses) and
190[connection error notifications](#Connection-Errors).
191***
192
193Once the `LoggerPtr` is bound we can immediately begin calling `Logger`
194interface methods on it, which will immediately write messages into the pipe.
195These messages will stay queued on the receiving end of the pipe until someone
196binds to it and starts reading them.
197
198``` cpp
199logger->Log("Hello!");
200```
201
202This actually writes a `Log` message to the pipe.
203
Ken Rockot856f9772017-04-11 19:41:39204![Diagram illustrating a message traveling on a pipe from LoggerPtr to LoggerRequest](https://docs.google.com/drawings/d/11vnOpNP3UBLlWg4KplQuIU3r_e1XqwDFETD-O_bV-2w/pub?w=635&h=112)
rockotf59d2d62017-04-01 02:49:08205
206But as mentioned above, `InterfaceRequest` *doesn't actually do anything*, so
207that message will just sit on the pipe forever. We need a way to read messages
208off the other end of the pipe and dispatch them. We have to
209**bind the interface request**.
210
211### Binding an Interface Request
212
213There are many different helper classes in the bindings library for binding the
214receiving end of a message pipe. The most primitive among them is the aptly
215named `mojo::Binding<T>`. A `mojo::Binding<T>` bridges an implementation of `T`
216with a single bound message pipe endpoint (via a `mojo::InterfaceRequest<T>`),
217which it continuously watches for readability.
218
219Any time the bound pipe becomes readable, the `Binding` will schedule a task to
220read, deserialize (using generated code), and dispatch all available messages to
221the bound `T` implementation. Below is a sample implementation of the `Logger`
222interface. Notice that the implementation itself owns a `mojo::Binding`. This is
223a common pattern, since a bound implementation must outlive any `mojo::Binding`
224which binds it.
225
226``` cpp
227#include "base/logging.h"
228#include "base/macros.h"
229#include "sample/logger.mojom.h"
230
231class LoggerImpl : public sample::mojom::Logger {
232 public:
233 // NOTE: A common pattern for interface implementations which have one
234 // instance per client is to take an InterfaceRequest in the constructor.
235
236 explicit LoggerImpl(sample::mojom::LoggerRequest request)
237 : binding_(this, std::move(request)) {}
238 ~Logger() override {}
239
240 // sample::mojom::Logger:
241 void Log(const std::string& message) override {
242 LOG(ERROR) << "[Logger] " << message;
243 }
244
245 private:
246 mojo::Binding<sample::mojom::Logger> binding_;
247
248 DISALLOW_COPY_AND_ASSIGN(LoggerImpl);
249};
250```
251
252Now we can construct a `LoggerImpl` over our pending `LoggerRequest`, and the
253previously queued `Log` message will be dispatched ASAP on the `LoggerImpl`'s
Sam McNallyd482b4b2017-07-17 03:45:03254sequence:
rockotf59d2d62017-04-01 02:49:08255
256``` cpp
257LoggerImpl impl(std::move(request));
258```
259
260The diagram below illustrates the following sequence of events, all set in
261motion by the above line of code:
262
2631. The `LoggerImpl` constructor is called, passing the `LoggerRequest` along
264 to the `Binding`.
2652. The `Binding` takes ownership of the `LoggerRequest`'s pipe endpoint and
266 begins watching it for readability. The pipe is readable immediately, so a
267 task is scheduled to read the pending `Log` message from the pipe ASAP.
2683. The `Log` message is read and deserialized, causing the `Binding` to invoke
269 the `Logger::Log` implementation on its bound `LoggerImpl`.
270
Ken Rockot856f9772017-04-11 19:41:39271![Diagram illustrating the progression of binding a request, reading a pending message, and dispatching it](https://docs.google.com/drawings/d/1F2VvfoOINGuNibomqeEU8KekYCtxYVFC00146CFGGQY/pub?w=550&h=500)
rockotf59d2d62017-04-01 02:49:08272
273As a result, our implementation will eventually log the client's `"Hello!"`
274message via `LOG(ERROR)`.
275
276*** note
277**NOTE:** Messages will only be read and dispatched from a pipe as long as the
278object which binds it (*i.e.* the `mojo::Binding` in the above example) remains
279alive.
280***
281
282### Receiving Responses
283
284Some Mojom interface methods expect a response. Suppose we modify our `Logger`
285interface so that the last logged line can be queried like so:
286
287``` cpp
288module sample.mojom;
289
290interface Logger {
291 Log(string message);
292 GetTail() => (string message);
293};
294```
295
296The generated C++ interface will now look like:
297
298``` cpp
299namespace sample {
300namespace mojom {
301
302class Logger {
303 public:
304 virtual ~Logger() {}
305
306 virtual void Log(const std::string& message) = 0;
307
308 using GetTailCallback = base::Callback<void(const std::string& message)>;
309
310 virtual void GetTail(const GetTailCallback& callback) = 0;
311}
312
313} // namespace mojom
314} // namespace sample
315```
316
317As before, both clients and implementations of this interface use the same
318signature for the `GetTail` method: implementations use the `callback` argument
319to *respond* to the request, while clients pass a `callback` argument to
320asynchronously `receive` the response. Here's an updated implementation:
321
322```cpp
323class LoggerImpl : public sample::mojom::Logger {
324 public:
325 // NOTE: A common pattern for interface implementations which have one
326 // instance per client is to take an InterfaceRequest in the constructor.
327
328 explicit LoggerImpl(sample::mojom::LoggerRequest request)
329 : binding_(this, std::move(request)) {}
330 ~Logger() override {}
331
332 // sample::mojom::Logger:
333 void Log(const std::string& message) override {
334 LOG(ERROR) << "[Logger] " << message;
335 lines_.push_back(message);
336 }
337
338 void GetTail(const GetTailCallback& callback) override {
339 callback.Run(lines_.back());
340 }
341
342 private:
343 mojo::Binding<sample::mojom::Logger> binding_;
344 std::vector<std::string> lines_;
345
346 DISALLOW_COPY_AND_ASSIGN(LoggerImpl);
347};
348```
349
350And an updated client call:
351
352``` cpp
353void OnGetTail(const std::string& message) {
354 LOG(ERROR) << "Tail was: " << message;
355}
356
357logger->GetTail(base::Bind(&OnGetTail));
358```
359
360Behind the scenes, the implementation-side callback is actually serializing the
361response arguments and writing them onto the pipe for delivery back to the
362client. Meanwhile the client-side callback is invoked by some internal logic
363which watches the pipe for an incoming response message, reads and deserializes
364it once it arrives, and then invokes the callback with the deserialized
365parameters.
366
367### Connection Errors
368
Yuzhu Shen92e791aa2017-06-20 20:39:31369If a pipe is disconnected, both endpoints will be able to observe the connection
370error (unless the disconnection is caused by closing/destroying an endpoint, in
371which case that endpoint won't get such a notification). If there are remaining
372incoming messages for an endpoint on disconnection, the connection error won't
373be triggered until the messages are drained.
374
375Pipe disconnecition may be caused by:
376* Mojo system-level causes: process terminated, resource exhausted, etc.
377* The bindings close the pipe due to a validation error when processing a
378 received message.
379* The peer endpoint is closed. For example, the remote side is a bound
380 `mojo::InterfacePtr<T>` and it is destroyed.
rockotf59d2d62017-04-01 02:49:08381
382Regardless of the underlying cause, when a connection error is encountered on
383a binding endpoint, that endpoint's **connection error handler** (if set) is
384invoked. This handler is a simple `base::Closure` and may only be invoked
385*once* as long as the endpoint is bound to the same pipe. Typically clients and
386implementations use this handler to do some kind of cleanup or -- particuarly if
387the error was unexpected -- create a new pipe and attempt to establish a new
388connection with it.
389
390All message pipe-binding C++ objects (*e.g.*, `mojo::Binding<T>`,
391`mojo::InterfacePtr<T>`, *etc.*) support setting their connection error handler
392via a `set_connection_error_handler` method.
393
394We can set up another end-to-end `Logger` example to demonstrate error handler
395invocation:
396
397``` cpp
398sample::mojom::LoggerPtr logger;
399LoggerImpl impl(mojo::MakeRequest(&logger));
jameswest14ae0132017-06-12 22:52:00400impl.set_connection_error_handler(base::BindOnce([] { LOG(ERROR) << "Bye."; }));
rockotf59d2d62017-04-01 02:49:08401logger->Log("OK cool");
402logger.reset(); // Closes the client end.
403```
404
405As long as `impl` stays alive here, it will eventually receive the `Log` message
406followed immediately by an invocation of the bound callback which outputs
407`"Bye."`. Like all other bindings callbacks, a connection error handler will
408**never** be invoked once its corresponding binding object has been destroyed.
409
410In fact, suppose instead that `LoggerImpl` had set up the following error
411handler within its constructor:
412
413``` cpp
414LoggerImpl::LoggerImpl(sample::mojom::LoggerRequest request)
415 : binding_(this, std::move(request)) {
416 binding_.set_connection_error_handler(
jameswest14ae0132017-06-12 22:52:00417 base::BindOnce(&LoggerImpl::OnError, base::Unretained(this)));
rockotf59d2d62017-04-01 02:49:08418}
419
420void LoggerImpl::OnError() {
421 LOG(ERROR) << "Client disconnected! Purging log lines.";
422 lines_.clear();
423}
424```
425
426The use of `base::Unretained` is *safe* because the error handler will never be
427invoked beyond the lifetime of `binding_`, and `this` owns `binding_`.
428
429### A Note About Ordering
430
431As mentioned in the previous section, closing one end of a pipe will eventually
432trigger a connection error on the other end. However it's important to note that
433this event is itself ordered with respect to any other event (*e.g.* writing a
434message) on the pipe.
435
436This means that it's safe to write something contrived like:
437
438``` cpp
439void GoBindALogger(sample::mojom::LoggerRequest request) {
440 LoggerImpl impl(std::move(request));
441 base::RunLoop loop;
442 impl.set_connection_error_handler(loop.QuitClosure());
443 loop.Run();
444}
445
446void LogSomething() {
447 sample::mojom::LoggerPtr logger;
448 bg_thread->task_runner()->PostTask(
449 FROM_HERE, base::BindOnce(&GoBindALogger, mojo::MakeRequest(&logger)));
450 logger->Log("OK Computer");
451}
452```
453
454When `logger` goes out of scope it immediately closes its end of the message
455pipe, but the impl-side won't notice this until it receives the sent `Log`
456message. Thus the `impl` above will first log our message and *then* see a
457connection error and break out of the run loop.
458
Ken Rockot686e4132017-04-26 00:03:31459### Enums
460
461[Mojom enums](/mojo/public/tools/bindings#Enumeration-Types) translate directly
462to equivalent strongly-typed C++11 enum classes with `int32_t` as the underlying
463type. The typename and value names are identical between Mojom and C++.
464
465For example, consider the following Mojom definition:
466
467```cpp
468module business.mojom;
469
470enum Department {
471 kEngineering,
Andrew Moylan341cece72017-06-22 22:03:02472 kMarketing,
Ken Rockot686e4132017-04-26 00:03:31473 kSales,
474};
475```
476
477This translates to the following C++ definition:
478
479```cpp
480namespace business {
481namespace mojom {
482
483enum class Department : int32_t {
484 kEngineering,
485 kMarketing,
486 kSales,
487};
488
489} // namespace mojom
490} // namespace business
491```
492
493### Structs
494
495[Mojom structs](mojo/public/tools/bindings#Structs) can be used to define
496logical groupings of fields into a new composite type. Every Mojom struct
497elicits the generation of an identically named, representative C++ class, with
498identically named public fields of corresponding C++ types, and several helpful
499public methods.
500
501For example, consider the following Mojom struct:
502
503```cpp
504module business.mojom;
505
506struct Employee {
507 int64 id;
508 string username;
509 Department department;
510};
511```
512
513This would generate a C++ class like so:
514
515```cpp
516namespace business {
517namespace mojom {
518
519class Employee;
520
521using EmployeePtr = mojo::StructPtr<Employee>;
522
523class Employee {
524 public:
525 // Default constructor - applies default values, potentially ones specified
526 // explicitly within the Mojom.
527 Employee();
528
529 // Value constructor - an explicit argument for every field in the struct, in
530 // lexical Mojom definition order.
531 Employee(int64_t id, const std::string& username, Department department);
532
533 // Creates a new copy of this struct value
534 EmployeePtr Clone();
535
536 // Tests for equality with another struct value of the same type.
537 bool Equals(const Employee& other);
538
539 // Equivalent public fields with names identical to the Mojom.
540 int64_t id;
541 std::string username;
542 Department department;
543};
544
545} // namespace mojom
546} // namespace business
547```
548
549Note when used as a message parameter or as a field within another Mojom struct,
550a `struct` type is wrapped by the move-only `mojo::StructPtr` helper, which is
551roughly equivalent to a `std::unique_ptr` with some additional utility methods.
552This allows struct values to be nullable and struct types to be potentially
553self-referential.
554
555Every genereated struct class has a static `New()` method which returns a new
556`mojo::StructPtr<T>` wrapping a new instance of the class constructed by
557forwarding the arguments from `New`. For example:
558
559```cpp
560mojom::EmployeePtr e1 = mojom::Employee::New();
561e1->id = 42;
562e1->username = "mojo";
563e1->department = mojom::Department::kEngineering;
564```
565
566is equivalent to
567
568```cpp
569auto e1 = mojom::Employee::New(42, "mojo", mojom::Department::kEngineering);
570```
571
572Now if we define an interface like:
573
574```cpp
575interface EmployeeManager {
576 AddEmployee(Employee e);
577};
578```
579
580We'll get this C++ interface to implement:
581
582```cpp
583class EmployeeManager {
584 public:
585 virtual ~EmployeManager() {}
586
587 virtual void AddEmployee(EmployeePtr e) = 0;
588};
589```
590
591And we can send this message from C++ code as follows:
592
593```cpp
594mojom::EmployeManagerPtr manager = ...;
595manager->AddEmployee(
596 Employee::New(42, "mojo", mojom::Department::kEngineering));
597
598// or
599auto e = Employee::New(42, "mojo", mojom::Department::kEngineering);
600manager->AddEmployee(std::move(e));
601```
602
603### Unions
604
605Similarly to [structs](#Structs), tagged unions generate an identically named,
606representative C++ class which is typically wrapped in a `mojo::StructPtr<T>`.
607
608Unlike structs, all generated union fields are private and must be retrieved and
609manipulated using accessors. A field `foo` is accessible by `foo()` and
610settable by `set_foo()`. There is also a boolean `is_foo()` for each field which
611indicates whether the union is currently taking on the value of field `foo` in
612exclusion to all other union fields.
613
614Finally, every generated union class also has a nested `Tag` enum class which
615enumerates all of the named union fields. A Mojom union value's current type can
616be determined by calling the `which()` method which returns a `Tag`.
617
618For example, consider the following Mojom definitions:
619
620```cpp
621union Value {
622 int64 int_value;
Gary Klassence3ed942017-08-28 19:57:24623 float32 float_value;
Ken Rockot686e4132017-04-26 00:03:31624 string string_value;
625};
626
627interface Dictionary {
628 AddValue(string key, Value value);
629};
630```
631
632This generates a the following C++ interface:
633
634```cpp
635class Value {
636 public:
637 virtual ~Value() {}
638
639 virtual void AddValue(const std::string& key, ValuePtr value) = 0;
640};
641```
642
643And we can use it like so:
644
645```cpp
646ValuePtr value = Value::New();
647value->set_int_value(42);
648CHECK(value->is_int_value());
649CHECK_EQ(value->which(), Value::Tag::INT_VALUE);
650
651value->set_float_value(42);
652CHECK(value->is_float_value());
653CHECK_EQ(value->which(), Value::Tag::FLOAT_VALUE);
654
655value->set_string_value("bananas");
656CHECK(value->is_string_value());
657CHECK_EQ(value->which(), Value::Tag::STRING_VALUE);
658```
659
660Finally, note that if a union value is not currently occupied by a given field,
661attempts to access that field will DCHECK:
662
663```cpp
664ValuePtr value = Value::New();
665value->set_int_value(42);
666LOG(INFO) << "Value is " << value->string_value(); // DCHECK!
667```
668
rockotf59d2d62017-04-01 02:49:08669### Sending Interfaces Over Interfaces
670
Ken Rockot686e4132017-04-26 00:03:31671We know how to create interface pipes and use their Ptr and Request endpoints
672in some interesting ways. This still doesn't add up to interesting IPC! The
673bread and butter of Mojo IPC is the ability to transfer interface endpoints
674across other interfaces, so let's take a look at how to accomplish that.
rockotf59d2d62017-04-01 02:49:08675
676#### Sending Interface Requests
677
678Consider a new example Mojom in `//sample/db.mojom`:
679
680``` cpp
681module db.mojom;
682
683interface Table {
684 void AddRow(int32 key, string data);
685};
686
687interface Database {
688 AddTable(Table& table);
689};
690```
691
692As noted in the
693[Mojom IDL documentation](/mojo/public/tools/bindings#Primitive-Types),
694the `Table&` syntax denotes a `Table` interface request. This corresponds
695precisely to the `InterfaceRequest<T>` type discussed in the sections above, and
696in fact the generated code for these interfaces is approximately:
697
698``` cpp
699namespace db {
700namespace mojom {
701
702class Table {
703 public:
704 virtual ~Table() {}
705
706 virtual void AddRow(int32_t key, const std::string& data) = 0;
707}
708
709using TablePtr = mojo::InterfacePtr<Table>;
710using TableRequest = mojo::InterfaceRequest<Table>;
711
712class Database {
713 public:
714 virtual ~Database() {}
715
716 virtual void AddTable(TableRequest table);
717};
718
719using DatabasePtr = mojo::InterfacePtr<Database>;
720using DatabaseRequest = mojo::InterfaceRequest<Database>;
721
722} // namespace mojom
723} // namespace db
724```
725
726We can put this all together now with an implementation of `Table` and
727`Database`:
728
729``` cpp
730#include "sample/db.mojom.h"
731
732class TableImpl : public db::mojom:Table {
733 public:
734 explicit TableImpl(db::mojom::TableRequest request)
735 : binding_(this, std::move(request)) {}
736 ~TableImpl() override {}
737
738 // db::mojom::Table:
739 void AddRow(int32_t key, const std::string& data) override {
740 rows_.insert({key, data});
741 }
742
743 private:
744 mojo::Binding<db::mojom::Table> binding_;
745 std::map<int32_t, std::string> rows_;
746};
747
748class DatabaseImpl : public db::mojom::Database {
749 public:
750 explicit DatabaseImpl(db::mojom::DatabaseRequest request)
751 : binding_(this, std::move(request)) {}
752 ~DatabaseImpl() override {}
753
754 // db::mojom::Database:
755 void AddTable(db::mojom::TableRequest table) {
Jeremy Romancf9ae2f2017-08-24 17:06:37756 tables_.emplace_back(std::make_unique<TableImpl>(std::move(table)));
rockotf59d2d62017-04-01 02:49:08757 }
758
759 private:
760 mojo::Binding<db::mojom::Database> binding_;
761 std::vector<std::unique_ptr<TableImpl>> tables_;
762};
763```
764
765Pretty straightforward. The `Table&` Mojom paramter to `AddTable` translates to
766a C++ `db::mojom::TableRequest`, aliased from
767`mojo::InterfaceRequest<db::mojom::Table>`, which we know is just a
768strongly-typed message pipe handle. When `DatabaseImpl` gets an `AddTable` call,
769it constructs a new `TableImpl` and binds it to the received `TableRequest`.
770
771Let's see how this can be used.
772
773``` cpp
774db::mojom::DatabasePtr database;
775DatabaseImpl db_impl(mojo::MakeRequest(&database));
776
777db::mojom::TablePtr table1, table2;
778database->AddTable(mojo::MakeRequest(&table1));
779database->AddTable(mojo::MakeRequest(&table2));
780
781table1->AddRow(1, "hiiiiiiii");
782table2->AddRow(2, "heyyyyyy");
783```
784
785Notice that we can again start using the new `Table` pipes immediately, even
786while their `TableRequest` endpoints are still in transit.
787
788#### Sending InterfacePtrs
789
790Of course we can also send `InterfacePtr`s:
791
792``` cpp
793interface TableListener {
794 OnRowAdded(int32 key, string data);
795};
796
797interface Table {
798 AddRow(int32 key, string data);
799
800 AddListener(TableListener listener);
801};
802```
803
804This would generate a `Table::AddListener` signature like so:
805
806``` cpp
807 virtual void AddListener(TableListenerPtr listener) = 0;
808```
809
810and this could be used like so:
811
812``` cpp
813db::mojom::TableListenerPtr listener;
814TableListenerImpl impl(mojo::MakeRequest(&listener));
815table->AddListener(std::move(listener));
816```
817
818## Other Interface Binding Types
819
820The [Interfaces](#Interfaces) section above covers basic usage of the most
821common bindings object types: `InterfacePtr`, `InterfaceRequest`, and `Binding`.
822While these types are probably the most commonly used in practice, there are
823several other ways of binding both client- and implementation-side interface
824pipes.
825
826### Strong Bindings
827
828A **strong binding** exists as a standalone object which owns its interface
829implementation and automatically cleans itself up when its bound interface
830endpoint detects an error. The
831[**`MakeStrongBinding`**](https://cs.chromim.org/chromium/src//mojo/public/cpp/bindings/strong_binding.h)
832function is used to create such a binding.
833.
834
835``` cpp
836class LoggerImpl : public sample::mojom::Logger {
837 public:
838 LoggerImpl() {}
839 ~LoggerImpl() override {}
840
841 // sample::mojom::Logger:
842 void Log(const std::string& message) override {
843 LOG(ERROR) << "[Logger] " << message;
844 }
845
846 private:
847 // NOTE: This doesn't own any Binding object!
848};
849
850db::mojom::LoggerPtr logger;
Jeremy Romancf9ae2f2017-08-24 17:06:37851mojo::MakeStrongBinding(std::make_unique<LoggerImpl>(),
rockotf59d2d62017-04-01 02:49:08852 mojo::MakeRequest(&logger));
853
854logger->Log("NOM NOM NOM MESSAGES");
855```
856
857Now as long as `logger` remains open somewhere in the system, the bound
scottmg66139202017-05-04 18:56:35858`LoggerImpl` on the other end will remain alive.
rockotf59d2d62017-04-01 02:49:08859
860### Binding Sets
861
862Sometimes it's useful to share a single implementation instance with multiple
863clients. [**`BindingSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/binding_set.h)
864makes this easy. Consider the Mojom:
865
866``` cpp
867module system.mojom;
868
869interface Logger {
870 Log(string message);
871};
872
873interface LoggerProvider {
874 GetLogger(Logger& logger);
875};
876```
877
878We can use `BindingSet` to bind multiple `Logger` requests to a single
879implementation instance:
880
881``` cpp
882class LogManager : public system::mojom::LoggerProvider,
883 public system::mojom::Logger {
884 public:
885 explicit LogManager(system::mojom::LoggerProviderRequest request)
886 : provider_binding_(this, std::move(request)) {}
887 ~LogManager() {}
888
889 // system::mojom::LoggerProvider:
890 void GetLogger(LoggerRequest request) override {
891 logger_bindings_.AddBinding(this, std::move(request));
892 }
893
894 // system::mojom::Logger:
895 void Log(const std::string& message) override {
896 LOG(ERROR) << "[Logger] " << message;
897 }
898
899 private:
900 mojo::Binding<system::mojom::LoggerProvider> provider_binding_;
901 mojo::BindingSet<system::mojom::Logger> logger_bindings_;
902};
903
904```
905
906
907### InterfacePtr Sets
908
909Similar to the `BindingSet` above, sometimes it's useful to maintain a set of
910`InterfacePtr`s for *e.g.* a set of clients observing some event.
911[**`InterfacePtrSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/interface_ptr_set.h)
912is here to help. Take the Mojom:
913
914``` cpp
915module db.mojom;
916
917interface TableListener {
918 OnRowAdded(int32 key, string data);
919};
920
921interface Table {
922 AddRow(int32 key, string data);
923 AddListener(TableListener listener);
924};
925```
926
927An implementation of `Table` might look something like like this:
928
929``` cpp
930class TableImpl : public db::mojom::Table {
931 public:
932 TableImpl() {}
933 ~TableImpl() override {}
934
935 // db::mojom::Table:
936 void AddRow(int32_t key, const std::string& data) override {
937 rows_.insert({key, data});
938 listeners_.ForEach([key, &data](db::mojom::TableListener* listener) {
939 listener->OnRowAdded(key, data);
940 });
941 }
942
943 void AddListener(db::mojom::TableListenerPtr listener) {
944 listeners_.AddPtr(std::move(listener));
945 }
946
947 private:
948 mojo::InterfacePtrSet<db::mojom::Table> listeners_;
949 std::map<int32_t, std::string> rows_;
950};
951```
952
953## Associated Interfaces
954
955See [this document](https://www.chromium.org/developers/design-documents/mojo/associated-interfaces).
956
957TODO: Move the above doc into the repository markdown docs.
958
959## Synchronous Calls
960
961See [this document](https://www.chromium.org/developers/design-documents/mojo/synchronous-calls)
962
963TODO: Move the above doc into the repository markdown docs.
964
965## Type Mapping
966
967In many instances you might prefer that your generated C++ bindings use a more
968natural type to represent certain Mojom types in your interface methods. For one
969example consider a Mojom struct such as the `Rect` below:
970
971``` cpp
972module gfx.mojom;
973
974struct Rect {
975 int32 x;
976 int32 y;
977 int32 width;
978 int32 height;
979};
980
981interface Canvas {
982 void FillRect(Rect rect);
983};
984```
985
986The `Canvas` Mojom interface would normally generate a C++ interface like:
987
988``` cpp
989class Canvas {
990 public:
991 virtual void FillRect(RectPtr rect) = 0;
992};
993```
994
995However, the Chromium tree already defines a native
996[`gfx::Rect`](https://cs.chromium.org/chromium/src/ui/gfx/geometry/rect.h) which
997is equivalent in meaning but which also has useful helper methods. Instead of
998manually converting between a `gfx::Rect` and the Mojom-generated `RectPtr` at
999every message boundary, wouldn't it be nice if the Mojom bindings generator
1000could instead generate:
1001
1002``` cpp
1003class Canvas {
1004 public:
1005 virtual void FillRect(const gfx::Rect& rect) = 0;
1006}
1007```
1008
1009The correct answer is, "Yes! That would be nice!" And fortunately, it can!
1010
1011### Global Configuration
1012
1013While this feature is quite powerful, it introduces some unavoidable complexity
1014into build system. This stems from the fact that type-mapping is an inherently
1015viral concept: if `gfx::mojom::Rect` is mapped to `gfx::Rect` anywhere, the
1016mapping needs to apply *everywhere*.
1017
1018For this reason we have a few global typemap configurations defined in
sky0b887ae2017-05-18 03:26:031019[chromium_bindings_configuration.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/chromium_bindings_configuration.gni)
rockotf59d2d62017-04-01 02:49:081020and
sky0b887ae2017-05-18 03:26:031021[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:081022bindings in the repository. Read more on this in the sections that follow.
1023
1024For now, let's take a look at how to express the mapping from `gfx::mojom::Rect`
1025to `gfx::Rect`.
1026
1027### Defining `StructTraits`
1028
1029In order to teach generated bindings code how to serialize an arbitrary native
1030type `T` as an arbitrary Mojom type `mojom::U`, we need to define an appropriate
1031specialization of the
1032[`mojo::StructTraits`](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/struct_traits.h)
1033template.
1034
1035A valid specialization of `StructTraits` MUST define the following static
1036methods:
1037
1038* A single static accessor for every field of the Mojom struct, with the exact
1039 same name as the struct field. These accessors must all take a const ref to
1040 an object of the native type, and must return a value compatible with the
1041 Mojom struct field's type. This is used to safely and consistently extract
1042 data from the native type during message serialization without incurring extra
1043 copying costs.
1044
1045* A single static `Read` method which initializes an instance of the the native
1046 type given a serialized representation of the Mojom struct. The `Read` method
1047 must return a `bool` to indicate whether the incoming data is accepted
1048 (`true`) or rejected (`false`).
1049
1050There are other methods a `StructTraits` specialization may define to satisfy
1051some less common requirements. See
1052[Advanced StructTraits Usage](#Advanced-StructTraits-Usage) for details.
1053
1054In order to define the mapping for `gfx::Rect`, we want the following
1055`StructTraits` specialization, which we'll define in
1056`//ui/gfx/geometry/mojo/geometry_struct_traits.h`:
1057
1058``` cpp
1059#include "mojo/public/cpp/bindings/struct_traits.h"
1060#include "ui/gfx/geometry/rect.h"
1061#include "ui/gfx/geometry/mojo/geometry.mojom.h"
1062
1063namespace mojo {
1064
1065template <>
1066class StructTraits<gfx::mojom::RectDataView, gfx::Rect> {
1067 public:
1068 static int32_t x(const gfx::Rect& r) { return r.x(); }
1069 static int32_t y(const gfx::Rect& r) { return r.y(); }
1070 static int32_t width(const gfx::Rect& r) { return r.width(); }
1071 static int32_t height(const gfx::Rect& r) { return r.height(); }
1072
1073 static bool Read(gfx::mojom::RectDataView data, gfx::Rect* out_rect);
1074};
1075
1076} // namespace mojo
1077```
1078
1079And in `//ui/gfx/geometry/mojo/geometry_struct_traits.cc`:
1080
1081``` cpp
1082#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
1083
1084namespace mojo {
1085
1086// static
1087template <>
1088bool StructTraits<gfx::mojom::RectDataView, gfx::Rect>::Read(
1089 gfx::mojom::RectDataView data,
1090 gfx::Rect* out_rect) {
1091 if (data.width() < 0 || data.height() < 0)
1092 return false;
1093
1094 out_rect->SetRect(data.x(), data.y(), data.width(), data.height());
1095 return true;
1096};
1097
1098} // namespace mojo
1099```
1100
1101Note that the `Read()` method returns `false` if either the incoming `width` or
1102`height` fields are negative. This acts as a validation step during
1103deserialization: if a client sends a `gfx::Rect` with a negative width or
1104height, its message will be rejected and the pipe will be closed. In this way,
1105type mapping can serve to enable custom validation logic in addition to making
1106callsites and interface implemention more convenient.
1107
1108### Enabling a New Type Mapping
1109
1110We've defined the `StructTraits` necessary, but we still need to teach the
1111bindings generator (and hence the build system) about the mapping. To do this we
1112must create a **typemap** file, which uses familiar GN syntax to describe the
1113new type mapping.
1114
1115Let's place this `geometry.typemap` file alongside our Mojom file:
1116
1117```
1118mojom = "//ui/gfx/geometry/mojo/geometry.mojom"
1119public_headers = [ "//ui/gfx/geometry/rect.h" ]
1120traits_headers = [ "//ui/gfx/geometry/mojo/geometry_struct_traits.h" ]
1121sources = [ "//ui/gfx/geometry/mojo/geometry_struct_traits.cc" ]
1122public_deps = [ "//ui/gfx/geometry" ]
1123type_mappings = [
1124 "gfx.mojom.Rect=gfx::Rect",
1125]
1126```
1127
1128Let's look at each of the variables above:
1129
1130* `mojom`: Specifies the `mojom` file to which the typemap applies. Many
1131 typemaps may apply to the same `mojom` file, but any given typemap may only
1132 apply to a single `mojom` file.
1133* `public_headers`: Additional headers required by any code which would depend
1134 on the Mojom definition of `gfx.mojom.Rect` now that the typemap is applied.
1135 Any headers required for the native target type definition should be listed
1136 here.
1137* `traits_headers`: Headers which contain the relevant `StructTraits`
1138 specialization(s) for any type mappings described by this file.
1139* `sources`: Any private implementation sources needed for the `StructTraits`
1140 definition.
1141* `public_deps`: Target dependencies exposed by the `public_headers` and
1142 `traits_headers`.
1143* `deps`: Target dependencies exposed by `sources` but not already covered by
1144 `public_deps`.
1145* `type_mappings`: A list of type mappings to be applied for this typemap. The
1146 strings in this list are of the format `"MojomType=CppType"`, where
1147 `MojomType` must be a fully qualified Mojom typename and `CppType` must be a
1148 fully qualified C++ typename. Additional attributes may be specified in square
1149 brackets following the `CppType`:
1150 * `move_only`: The `CppType` is move-only and should be passed by value
1151 in any generated method signatures. Note that `move_only` is transitive,
1152 so containers of `MojomType` will translate to containers of `CppType`
1153 also passed by value.
1154 * `copyable_pass_by_value`: Forces values of type `CppType` to be passed by
1155 value without moving them. Unlike `move_only`, this is not transitive.
1156 * `nullable_is_same_type`: By default a non-nullable `MojomType` will be
1157 mapped to `CppType` while a nullable `MojomType?` will be mapped to
1158 `base::Optional<CppType>`. If this attribute is set, the `base::Optional`
1159 wrapper is omitted for nullable `MojomType?` values, but the
1160 `StructTraits` definition for this type mapping must define additional
1161 `IsNull` and `SetToNull` methods. See
1162 [Specializing Nullability](#Specializing-Nullability) below.
1163
1164
1165Now that we have the typemap file we need to add it to a local list of typemaps
1166that can be added to the global configuration. We create a new
1167`//ui/gfx/typemaps.gni` file with the following contents:
1168
1169```
1170typemaps = [
1171 "//ui/gfx/geometry/mojo/geometry.typemap",
1172]
1173```
1174
1175And finally we can reference this file in the global default (Chromium) bindings
1176configuration by adding it to `_typemap_imports` in
sky0b887ae2017-05-18 03:26:031177[chromium_bindings_configuration.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/chromium_bindings_configuration.gni):
rockotf59d2d62017-04-01 02:49:081178
1179```
1180_typemap_imports = [
1181 ...,
1182 "//ui/gfx/typemaps.gni",
1183 ...,
1184]
1185```
1186
1187### StructTraits Reference
1188
1189Each of a `StructTraits` specialization's static getter methods -- one per
1190struct field -- must return a type which can be used as a data source for the
1191field during serialization. This is a quick reference mapping Mojom field type
1192to valid getter return types:
1193
1194| Mojom Field Type | C++ Getter Return Type |
1195|------------------------------|------------------------|
1196| `bool` | `bool`
1197| `int8` | `int8_t`
1198| `uint8` | `uint8_t`
1199| `int16` | `int16_t`
1200| `uint16` | `uint16_t`
1201| `int32` | `int32_t`
1202| `uint32` | `uint32_t`
1203| `int64` | `int64_t`
1204| `uint64` | `uint64_t`
1205| `float` | `float`
1206| `double` | `double`
1207| `handle` | `mojo::ScopedHandle`
1208| `handle<message_pipe>` | `mojo::ScopedMessagePipeHandle`
1209| `handle<data_pipe_consumer>` | `mojo::ScopedDataPipeConsumerHandle`
1210| `handle<data_pipe_producer>` | `mojo::ScopedDataPipeProducerHandle`
1211| `handle<shared_buffer>` | `mojo::ScopedSharedBufferHandle`
1212| `FooInterface` | `FooInterfacePtr`
1213| `FooInterface&` | `FooInterfaceRequest`
1214| `associated FooInterface` | `FooAssociatedInterfacePtr`
1215| `associated FooInterface&` | `FooAssociatedInterfaceRequest`
1216| `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).
1217| `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).
1218| `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).
1219| `FooEnum` | Value of any type that has an appropriate `EnumTraits` specialization defined. By default this inlcudes only the generated `FooEnum` type.
1220| `FooStruct` | Value or reference to any type that has an appropriate `StructTraits` specialization defined. By default this includes only the generated `FooStructPtr` type.
1221| `FooUnion` | Value of reference to any type that has an appropriate `UnionTraits` specialization defined. By default this includes only the generated `FooUnionPtr` type.
1222
1223### Using Generated DataView Types
1224
1225Static `Read` methods on `StructTraits` specializations get a generated
1226`FooDataView` argument (such as the `RectDataView` in the example above) which
1227exposes a direct view of the serialized Mojom structure within an incoming
1228message's contents. In order to make this as easy to work with as possible, the
1229generated `FooDataView` types have a generated method corresponding to every
1230struct field:
1231
1232* For POD field types (*e.g.* bools, floats, integers) these are simple accessor
1233 methods with names identical to the field name. Hence in the `Rect` example we
1234 can access things like `data.x()` and `data.width()`. The return types
1235 correspond exactly to the mappings listed in the table above, under
1236 [StructTraits Reference](#StructTraits-Reference).
1237
1238* For handle and interface types (*e.g* `handle` or `FooInterface&`) these
1239 are named `TakeFieldName` (for a field named `field_name`) and they return an
1240 appropriate move-only handle type by value. The return types correspond
1241 exactly to the mappings listed in the table above, under
1242 [StructTraits Reference](#StructTraits-Reference).
1243
1244* For all other field types (*e.g.*, enums, strings, arrays, maps, structs)
1245 these are named `ReadFieldName` (for a field named `field_name`) and they
1246 return a `bool` (to indicate success or failure in reading). On success they
1247 fill their output argument with the deserialized field value. The output
1248 argument may be a pointer to any type with an appropriate `StructTraits`
1249 specialization defined, as mentioned in the table above, under
1250 [StructTraits Reference](#StructTraits-Reference).
1251
1252An example would be useful here. Suppose we introduced a new Mojom struct:
1253
1254``` cpp
1255struct RectPair {
1256 Rect left;
1257 Rect right;
1258};
1259```
1260
1261and a corresponding C++ type:
1262
1263``` cpp
1264class RectPair {
1265 public:
1266 RectPair() {}
1267
1268 const gfx::Rect& left() const { return left_; }
1269 const gfx::Rect& right() const { return right_; }
1270
1271 void Set(const gfx::Rect& left, const gfx::Rect& right) {
1272 left_ = left;
1273 right_ = right;
1274 }
1275
1276 // ... some other stuff
1277
1278 private:
1279 gfx::Rect left_;
1280 gfx::Rect right_;
1281};
1282```
1283
1284Our traits to map `gfx::mojom::RectPair` to `gfx::RectPair` might look like
1285this:
1286
1287``` cpp
1288namespace mojo {
1289
1290template <>
1291class StructTraits
1292 public:
1293 static const gfx::Rect& left(const gfx::RectPair& pair) {
1294 return pair.left();
1295 }
1296
1297 static const gfx::Rect& right(const gfx::RectPair& pair) {
1298 return pair.right();
1299 }
1300
1301 static bool Read(gfx::mojom::RectPairDataView data, gfx::RectPair* out_pair) {
1302 gfx::Rect left, right;
1303 if (!data.ReadLeft(&left) || !data.ReadRight(&right))
1304 return false;
1305 out_pair->Set(left, right);
1306 return true;
1307 }
1308} // namespace mojo
1309```
1310
1311Generated `ReadFoo` methods always convert `multi_word_field_name` fields to
1312`ReadMultiWordFieldName` methods.
1313
Andrew Moylan341cece72017-06-22 22:03:021314<a name="Blink-Type-Mapping"></a>
rockotf59d2d62017-04-01 02:49:081315### Variants
1316
1317By now you may have noticed that additional C++ sources are generated when a
1318Mojom is processed. These exist due to type mapping, and the source files we
1319refer to throughout this docuemnt (namely `foo.mojom.cc` and `foo.mojom.h`) are
1320really only one **variant** (the *default* or *chromium* variant) of the C++
1321bindings for a given Mojom file.
1322
1323The only other variant currently defined in the tree is the *blink* variant,
1324which produces a few additional files:
1325
1326```
1327out/gen/sample/db.mojom-blink.cc
1328out/gen/sample/db.mojom-blink.h
1329```
1330
1331These files mirror the definitions in the default variant but with different
1332C++ types in place of certain builtin field and parameter types. For example,
1333Mojom strings are represented by `WTF::String` instead of `std::string`. To
1334avoid symbol collisions, the variant's symbols are nested in an extra inner
1335namespace, so Blink consumer of the interface might write something like:
1336
1337```
1338#include "sample/db.mojom-blink.h"
1339
1340class TableImpl : public db::mojom::blink::Table {
1341 public:
1342 void AddRow(int32_t key, const WTF::String& data) override {
1343 // ...
1344 }
1345};
1346```
1347
1348In addition to using different C++ types for builtin strings, arrays, and maps,
1349the global typemap configuration for default and "blink" variants are completely
1350separate. To add a typemap for the Blink configuration, you can modify
1351[blink_bindings_configuration.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/blink_bindings_configuration.gni).
1352
1353All variants share some definitions which are unaffected by differences in the
1354type mapping configuration (enums, for example). These definitions are generated
1355in *shared* sources:
1356
1357```
1358out/gen/sample/db.mojom-shared.cc
1359out/gen/sample/db.mojom-shared.h
1360out/gen/sample/db.mojom-shared-internal.h
1361```
1362
1363Including either variant's header (`db.mojom.h` or `db.mojom-blink.h`)
Andrew Moylan341cece72017-06-22 22:03:021364implicitly includes the shared header, but may wish to include *only* the shared
1365header in some instances.
rockotf59d2d62017-04-01 02:49:081366
1367Finally, note that for `mojom` GN targets, there is implicitly a corresponding
1368`mojom_{variant}` target defined for any supported bindings configuration. So
1369for example if you've defined in `//sample/BUILD.gn`:
1370
1371```
1372import("mojo/public/tools/bindings/mojom.gni")
1373
1374mojom("interfaces") {
1375 sources = [
1376 "db.mojom",
1377 ]
1378}
1379```
1380
1381Code in Blink which wishes to use the generated Blink-variant definitions must
1382depend on `"//sample:interfaces_blink"`.
1383
1384## Versioning Considerations
1385
1386For general documentation of versioning in the Mojom IDL see
1387[Versioning](/mojo/public/tools/bindings#Versioning).
1388
1389This section briefly discusses some C++-specific considerations relevant to
1390versioned Mojom types.
1391
1392### Querying Interface Versions
1393
1394`InterfacePtr` defines the following methods to query or assert remote interface
1395version:
1396
1397```cpp
1398void QueryVersion(const base::Callback<void(uint32_t)>& callback);
1399```
1400
1401This queries the remote endpoint for the version number of its binding. When a
1402response is received `callback` is invoked with the remote version number. Note
1403that this value is cached by the `InterfacePtr` instance to avoid redundant
1404queries.
1405
1406```cpp
1407void RequireVersion(uint32_t version);
1408```
1409
1410Informs the remote endpoint that a minimum version of `version` is required by
1411the client. If the remote endpoint cannot support that version, it will close
1412its end of the pipe immediately, preventing any other requests from being
1413received.
1414
1415### Versioned Enums
1416
1417For convenience, every extensible enum has a generated helper function to
1418determine whether a received enum value is known by the implementation's current
1419version of the enum definition. For example:
1420
1421```cpp
1422[Extensible]
1423enum Department {
1424 SALES,
1425 DEV,
1426 RESEARCH,
1427};
1428```
1429
1430generates the function in the same namespace as the generated C++ enum type:
1431
1432```cpp
1433inline bool IsKnownEnumValue(Department value);
1434```
1435
1436### Additional Documentation
1437
1438[Calling Mojo From Blink](https://www.chromium.org/developers/design-documents/mojo/calling-mojo-from-blink)
1439: A brief overview of what it looks like to use Mojom C++ bindings from
1440 within Blink code.