1# Mojo C++ Bindings API 2This document is a subset of the [Mojo documentation](/mojo/README.md). 3 4[TOC] 5 6## Overview 7The Mojo C++ Bindings API leverages the 8[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 boundaries. 14 15This document provides a detailed guide to bindings API usage with example code 16snippets. For a detailed API references please consult the headers in 17[//mojo/public/cpp/bindings](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/README.md). 18 19For a simplified guide targeted at Chromium developers, see [this 20link](/docs/mojo_and_services.md). 21 22## 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 27`//services/db/public/mojom/db.mojom`: 28 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 42`//services/db/public/mojom/BUILD.gn`: 43 44``` 45import("//mojo/public/tools/bindings/mojom.gni") 46 47mojom("mojom") { 48 sources = [ 49 "db.mojom", 50 ] 51} 52``` 53 54Ensure that any target that needs this interface depends on it, e.g. with a line like: 55 56``` 57 deps += [ '//services/db/public/mojom' ] 58``` 59 60If we then build this target: 61 62``` 63ninja -C out/r services/db/public/mojom 64``` 65 66This will produce several generated source files, some of which are relevant to 67C++ bindings. Two of these files are: 68 69``` 70out/gen/services/db/public/mojom/db.mojom.cc 71out/gen/services/db/public/mojom/db.mojom.h 72``` 73 74You can include the above generated header in your sources in order to use the 75definitions therein: 76 77``` cpp 78#include "services/business/public/mojom/factory.mojom.h" 79 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 `logger.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 129} // namespace mojom 130} // namespace sample 131``` 132 133### Remote and PendingReceiver 134 135In the world of Mojo bindings libraries these are effectively strongly-typed 136message pipe endpoints. If a `Remote<T>` is bound to a message pipe 137endpoint, it can be dereferenced to make calls on an opaque `T` interface. These 138calls immediately serialize their arguments (using generated code) and write a 139corresponding message to the pipe. 140 141A `PendingReceiver<T>` is essentially just a typed container to hold the other 142end of a `Remote<T>`'s pipe -- the receiving end -- until it can be 143routed to some implementation which will **bind** it. The `PendingReceiver<T>` 144doesn't actually *do* anything other than hold onto a pipe endpoint and carry 145useful compile-time type information. 146 147![Diagram illustrating Remote and PendingReceiver on either end of a message pipe](/docs/images/mojo_pipe.png) 148 149So how do we create a strongly-typed message pipe? 150 151### Creating Interface Pipes 152 153One way to do this is by manually creating a pipe and wrapping each end with a 154strongly-typed object: 155 156``` cpp 157#include "sample/logger.mojom.h" 158 159mojo::MessagePipe pipe; 160mojo::Remote<sample::mojom::Logger> logger( 161 mojo::PendingRemote<sample::mojom::Logger>(std::move(pipe.handle0), 0)); 162mojo::PendingReceiver<sample::mojom::Logger> receiver(std::move(pipe.handle1)); 163``` 164 165That's pretty verbose, but the C++ Bindings library provides a more convenient 166way to accomplish the same thing. [remote.h](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/remote.h) 167defines a `BindNewPipeAndPassReceiver` method: 168 169``` cpp 170mojo::Remote<sample::mojom::Logger> logger; 171auto receiver = logger.BindNewPipeAndPassReceiver()); 172``` 173 174This second snippet is equivalent to the first one. 175 176*** note 177**NOTE:** In the first example above you may notice usage of the 178`mojo::PendingRemote<Logger>`. This is similar to a `PendingReceiver<T>` 179in that it merely holds onto a pipe handle and cannot actually read or 180write messages on the pipe. Both this type and `PendingReceiver<T>` are safe 181to move freely from sequence to sequence, whereas a bound `Remote<T>` is bound 182to a single sequence. 183 184A `Remote<T>` may be unbound by calling its `Unbind()` method, 185which returns a new `PendingRemote<T>`. Conversely, an `Remote<T>` may 186bind (and thus take ownership of) an `PendingRemote<T>` so that interface 187calls can be made on the pipe. 188 189The sequence-bound nature of `Remote<T>` is necessary to support safe 190dispatch of its [message responses](#Receiving-Responses) and 191[connection error notifications](#Connection-Errors). 192*** 193 194Once the `PendingRemote<Logger>` is bound we can immediately begin calling `Logger` 195interface methods on it, which will immediately write messages into the pipe. 196These messages will stay queued on the receiving end of the pipe until someone 197binds to it and starts reading them. 198 199``` cpp 200logger->Log("Hello!"); 201``` 202 203This actually writes a `Log` message to the pipe. 204 205![Diagram illustrating a message traveling on a pipe from Remote<Logger> to PendingReceiver<Logger>](/docs/images/mojo_message.png) 206 207But as mentioned above, `PendingReceiver` *doesn't actually do anything*, so 208that message will just sit on the pipe forever. We need a way to read messages 209off the other end of the pipe and dispatch them. We have to 210**bind the pending receiver**. 211 212### Binding a Pending Receiver 213 214There are many different helper classes in the bindings library for binding the 215receiving end of a message pipe. The most primitive among them is `mojo::Receiver<T>`. 216A `mojo::Receiver<T>` bridges an implementation of `T` 217with a single bound message pipe endpoint (via a `mojo::PendingReceiver<T>`), 218which it continuously watches for readability. 219 220Any time the bound pipe becomes readable, the `Receiver` will schedule a task to 221read, deserialize (using generated code), and dispatch all available messages to 222the bound `T` implementation. Below is a sample implementation of the `Logger` 223interface. Notice that the implementation itself owns a `mojo::Receiver`. This is 224a common pattern, since a bound implementation must outlive any `mojo::Receiver` 225which binds it. 226 227``` cpp 228#include "base/logging.h" 229#include "base/macros.h" 230#include "sample/logger.mojom.h" 231 232class LoggerImpl : public sample::mojom::Logger { 233 public: 234 // NOTE: A common pattern for interface implementations which have one 235 // instance per client is to take a PendingReceiver in the constructor. 236 237 explicit LoggerImpl(mojo::PendingReceiver<sample::mojom::Logger> receiver) 238 : receiver_(this, std::move(receiver)) {} 239 ~Logger() override {} 240 241 // sample::mojom::Logger: 242 void Log(const std::string& message) override { 243 LOG(ERROR) << "[Logger] " << message; 244 } 245 246 private: 247 mojo::Receiver<sample::mojom::Logger> receiver_; 248 249 DISALLOW_COPY_AND_ASSIGN(LoggerImpl); 250}; 251``` 252 253Now we can construct a `LoggerImpl` over our `PendingReceiver<Logger>`, and the 254previously queued `Log` message will be dispatched ASAP on the `LoggerImpl`'s 255sequence: 256 257``` cpp 258LoggerImpl impl(std::move(receiver)); 259``` 260 261The diagram below illustrates the following sequence of events, all set in 262motion by the above line of code: 263 2641. The `LoggerImpl` constructor is called, passing the `PendingReceiver<Logger>` along 265 to the `Receiver`. 2662. The `Receiver` takes ownership of the `PendingReceiver<Logger>`'s pipe endpoint and 267 begins watching it for readability. The pipe is readable immediately, so a 268 task is scheduled to read the pending `Log` message from the pipe ASAP. 2693. The `Log` message is read and deserialized, causing the `Receiver` to invoke 270 the `Logger::Log` implementation on its bound `LoggerImpl`. 271 272![Diagram illustrating the progression of binding a pending receiver, reading a pending message, and dispatching it](/docs/images/mojo_receiver_and_dispatch.png) 273 274As a result, our implementation will eventually log the client's `"Hello!"` 275message via `LOG(ERROR)`. 276 277*** note 278**NOTE:** Messages will only be read and dispatched from a pipe as long as the 279object which binds it (*i.e.* the `mojo::Receiver` in the above example) remains 280alive. 281*** 282 283### Receiving Responses 284 285Some Mojom interface methods expect a response. Suppose we modify our `Logger` 286interface so that the last logged line can be queried like so: 287 288``` cpp 289module sample.mojom; 290 291interface Logger { 292 Log(string message); 293 GetTail() => (string message); 294}; 295``` 296 297The generated C++ interface will now look like: 298 299``` cpp 300namespace sample { 301namespace mojom { 302 303class Logger { 304 public: 305 virtual ~Logger() {} 306 307 virtual void Log(const std::string& message) = 0; 308 309 using GetTailCallback = base::OnceCallback<void(const std::string& message)>; 310 311 virtual void GetTail(GetTailCallback callback) = 0; 312} 313 314} // namespace mojom 315} // namespace sample 316``` 317 318As before, both clients and implementations of this interface use the same 319signature for the `GetTail` method: implementations use the `callback` argument 320to *respond* to the request, while clients pass a `callback` argument to 321asynchronously `receive` the response. A client's `callback` runs on the same 322sequence on which they invoked `GetTail` (the sequence to which their `logger` 323is bound). Here's an updated implementation: 324 325```cpp 326class LoggerImpl : public sample::mojom::Logger { 327 public: 328 // NOTE: A common pattern for interface implementations which have one 329 // instance per client is to take a PendingReceiver in the constructor. 330 331 explicit LoggerImpl(mojo::PendingReceiver<sample::mojom::Logger> receiver) 332 : receiver_(this, std::move(receiver)) {} 333 ~Logger() override {} 334 335 // sample::mojom::Logger: 336 void Log(const std::string& message) override { 337 LOG(ERROR) << "[Logger] " << message; 338 lines_.push_back(message); 339 } 340 341 void GetTail(GetTailCallback callback) override { 342 std::move(callback).Run(lines_.back()); 343 } 344 345 private: 346 mojo::Receiver<sample::mojom::Logger> receiver_; 347 std::vector<std::string> lines_; 348 349 DISALLOW_COPY_AND_ASSIGN(LoggerImpl); 350}; 351``` 352 353And an updated client call: 354 355``` cpp 356void OnGetTail(const std::string& message) { 357 LOG(ERROR) << "Tail was: " << message; 358} 359 360logger->GetTail(base::BindOnce(&OnGetTail)); 361``` 362 363Behind the scenes, the implementation-side callback is actually serializing the 364response arguments and writing them onto the pipe for delivery back to the 365client. Meanwhile the client-side callback is invoked by some internal logic 366which watches the pipe for an incoming response message, reads and deserializes 367it once it arrives, and then invokes the callback with the deserialized 368parameters. 369 370### Connection Errors 371 372If a pipe is disconnected, both endpoints will be able to observe the connection 373error (unless the disconnection is caused by closing/destroying an endpoint, in 374which case that endpoint won't get such a notification). If there are remaining 375incoming messages for an endpoint on disconnection, the connection error won't 376be triggered until the messages are drained. 377 378Pipe disconnection may be caused by: 379* Mojo system-level causes: process terminated, resource exhausted, etc. 380* The bindings close the pipe due to a validation error when processing a 381 received message. 382* The peer endpoint is closed. For example, the remote side is a bound 383 `mojo::Remote<T>` and it is destroyed. 384 385Regardless of the underlying cause, when a connection error is encountered on 386a receiver endpoint, that endpoint's **disconnect handler** (if set) is 387invoked. This handler is a simple `base::OnceClosure` and may only be invoked 388*once* as long as the endpoint is bound to the same pipe. Typically clients and 389implementations use this handler to do some kind of cleanup or -- particuarly if 390the error was unexpected -- create a new pipe and attempt to establish a new 391connection with it. 392 393All message pipe-binding C++ objects (*e.g.*, `mojo::Receiver<T>`, 394`mojo::Remote<T>`, *etc.*) support setting their disconnect handler 395via a `set_disconnect_handler` method. 396 397We can set up another end-to-end `Logger` example to demonstrate disconnect handler 398invocation. Suppose that `LoggerImpl` had set up the following disconnect 399handler within its constructor: 400 401``` cpp 402LoggerImpl::LoggerImpl(mojo::PendingReceiver<sample::mojom::Logger> receiver) 403 : receiver_(this, std::move(receiver)) { 404 receiver_.set_disconnect_handler( 405 base::BindOnce(&LoggerImpl::OnError, base::Unretained(this))); 406} 407 408void LoggerImpl::OnError() { 409 LOG(ERROR) << "Client disconnected! Purging log lines."; 410 lines_.clear(); 411} 412 413mojo::Remote<sample::mojom::Logger> logger; 414LoggerImpl impl(logger.BindNewPipeAndPassReceiver()); 415logger->Log("OK cool"); 416logger.reset(); // Closes the client end. 417 418``` 419 420As long as `impl` stays alive here, it will eventually receive the `Log` message 421followed immediately by an invocation of the bound callback which outputs 422`"Client disconnected! Purging log lines."`. Like all other receiver callbacks, a disconnect handler will 423**never** be invoked once its corresponding receiver object has been destroyed. 424 425The use of `base::Unretained` is *safe* because the error handler will never be 426invoked beyond the lifetime of `receiver_`, and `this` owns `receiver_`. 427 428### A Note About Endpoint Lifetime and Callbacks 429Once a `mojo::Remote<T>` is destroyed, it is guaranteed that pending 430callbacks as well as the connection error handler (if registered) won't be 431called. 432 433Once a `mojo::Receiver<T>` is destroyed, it is guaranteed that no more method 434calls are dispatched to the implementation and the connection error handler (if 435registered) won't be called. 436 437### Best practices for dealing with process crashes and callbacks 438A common situation when calling mojo interface methods that take a callback is 439that the caller wants to know if the other endpoint is torn down (e.g. because 440of a crash). In that case, the consumer usually wants to know if the response 441callback won't be run. There are different solutions for this problem, depending 442on how the `Remote<T>` is held: 4431. The consumer owns the `Remote<T>`: `set_disconnect_handler` 444 should be used. 4452. The consumer doesn't own the `Remote<T>`: there are two helpers 446 depending on the behavior that the caller wants. If the caller wants to 447 ensure that an error handler is run, then 448 [**`mojo::WrapCallbackWithDropHandler`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/callback_helpers.h?l=46) 449 should be used. If the caller wants the callback to always be run, then 450 [**`mojo::WrapCallbackWithDefaultInvokeIfNotRun`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/callback_helpers.h?l=40) 451 helper should be used. With both of these helpers, usual callback care should 452 be followed to ensure that the callbacks don't run after the consumer is 453 destructed (e.g. because the owner of the `Remote<T>` outlives the 454 consumer). This includes using 455 [**`base::WeakPtr`**](https://cs.chromium.org/chromium/src/base/memory/weak_ptr.h?l=5) 456 or 457 [**`base::RefCounted`**](https://cs.chromium.org/chromium/src/base/memory/ref_counted.h?l=246). 458 It should also be noted that with these helpers, the callbacks could be run 459 synchronously while the Remote<T> is reset or destroyed. 460 461### A Note About Ordering 462 463As mentioned in the previous section, closing one end of a pipe will eventually 464trigger a connection error on the other end. However it's important to note that 465this event is itself ordered with respect to any other event (*e.g.* writing a 466message) on the pipe. 467 468This means that it's safe to write something contrived like: 469 470``` cpp 471LoggerImpl::LoggerImpl(mojo::PendingReceiver<sample::mojom::Logger> receiver, 472 base::OnceClosure disconnect_handler) 473 : receiver_(this, std::move(receiver)) { 474 receiver_.set_disconnect_handler(std::move(disconnect_handler)); 475} 476 477void GoBindALogger(mojo::PendingReceiver<sample::mojom::Logger> receiver) { 478 base::RunLoop loop; 479 LoggerImpl impl(std::move(receiver), loop.QuitClosure()); 480 loop.Run(); 481} 482 483void LogSomething() { 484 mojo::Remote<sample::mojom::Logger> logger; 485 bg_thread->task_runner()->PostTask( 486 FROM_HERE, base::BindOnce(&GoBindALogger, logger.BindNewPipeAndPassReceiver())); 487 logger->Log("OK Computer"); 488} 489``` 490 491When `logger` goes out of scope it immediately closes its end of the message 492pipe, but the impl-side won't notice this until it receives the sent `Log` 493message. Thus the `impl` above will first log our message and *then* see a 494connection error and break out of the run loop. 495 496## Types 497 498### Enums 499 500[Mojom enums](/mojo/public/tools/bindings/README.md#Enumeration-Types) translate 501directly to equivalent strongly-typed C++11 enum classes with `int32_t` as the 502underlying type. The typename and value names are identical between Mojom and 503C++. Mojo also always defines a special enumerator `kMaxValue` that shares the 504value of the highest enumerator: this makes it easy to record Mojo enums in 505histograms and interoperate with legacy IPC. 506 507For example, consider the following Mojom definition: 508 509```cpp 510module business.mojom; 511 512enum Department { 513 kEngineering, 514 kMarketing, 515 kSales, 516}; 517``` 518 519This translates to the following C++ definition: 520 521```cpp 522namespace business { 523namespace mojom { 524 525enum class Department : int32_t { 526 kEngineering, 527 kMarketing, 528 kSales, 529 kMaxValue = kSales, 530}; 531 532} // namespace mojom 533} // namespace business 534``` 535 536### Structs 537 538[Mojom structs](mojo/public/tools/bindings/README.md#Structs) can be used to 539define logical groupings of fields into a new composite type. Every Mojom struct 540elicits the generation of an identically named, representative C++ class, with 541identically named public fields of corresponding C++ types, and several helpful 542public methods. 543 544For example, consider the following Mojom struct: 545 546```cpp 547module business.mojom; 548 549struct Employee { 550 int64 id; 551 string username; 552 Department department; 553}; 554``` 555 556This would generate a C++ class like so: 557 558```cpp 559namespace business { 560namespace mojom { 561 562class Employee; 563 564using EmployeePtr = mojo::StructPtr<Employee>; 565 566class Employee { 567 public: 568 // Default constructor - applies default values, potentially ones specified 569 // explicitly within the Mojom. 570 Employee(); 571 572 // Value constructor - an explicit argument for every field in the struct, in 573 // lexical Mojom definition order. 574 Employee(int64_t id, const std::string& username, Department department); 575 576 // Creates a new copy of this struct value 577 EmployeePtr Clone(); 578 579 // Tests for equality with another struct value of the same type. 580 bool Equals(const Employee& other); 581 582 // Equivalent public fields with names identical to the Mojom. 583 int64_t id; 584 std::string username; 585 Department department; 586}; 587 588} // namespace mojom 589} // namespace business 590``` 591 592Note when used as a message parameter or as a field within another Mojom struct, 593a `struct` type is wrapped by the move-only `mojo::StructPtr` helper, which is 594roughly equivalent to a `std::unique_ptr` with some additional utility methods. 595This allows struct values to be nullable and struct types to be potentially 596self-referential. 597 598Every generated struct class has a static `New()` method which returns a new 599`mojo::StructPtr<T>` wrapping a new instance of the class constructed by 600forwarding the arguments from `New`. For example: 601 602```cpp 603mojom::EmployeePtr e1 = mojom::Employee::New(); 604e1->id = 42; 605e1->username = "mojo"; 606e1->department = mojom::Department::kEngineering; 607``` 608 609is equivalent to 610 611```cpp 612auto e1 = mojom::Employee::New(42, "mojo", mojom::Department::kEngineering); 613``` 614 615Now if we define an interface like: 616 617```cpp 618interface EmployeeManager { 619 AddEmployee(Employee e); 620}; 621``` 622 623We'll get this C++ interface to implement: 624 625```cpp 626class EmployeeManager { 627 public: 628 virtual ~EmployeManager() {} 629 630 virtual void AddEmployee(EmployeePtr e) = 0; 631}; 632``` 633 634And we can send this message from C++ code as follows: 635 636```cpp 637mojom::EmployeManagerPtr manager = ...; 638manager->AddEmployee( 639 Employee::New(42, "mojo", mojom::Department::kEngineering)); 640 641// or 642auto e = Employee::New(42, "mojo", mojom::Department::kEngineering); 643manager->AddEmployee(std::move(e)); 644``` 645 646### Unions 647 648Similarly to [structs](#Structs), tagged unions generate an identically named, 649representative C++ class which is typically wrapped in a `mojo::StructPtr<T>`. 650 651Unlike structs, all generated union fields are private and must be retrieved and 652manipulated using accessors. A field `foo` is accessible by `get_foo()` and 653settable by `set_foo()`. There is also a boolean `is_foo()` for each field which 654indicates whether the union is currently taking on the value of field `foo` in 655exclusion to all other union fields. 656 657Finally, every generated union class also has a nested `Tag` enum class which 658enumerates all of the named union fields. A Mojom union value's current type can 659be determined by calling the `which()` method which returns a `Tag`. 660 661For example, consider the following Mojom definitions: 662 663```cpp 664union Value { 665 int64 int_value; 666 float float_value; 667 string string_value; 668}; 669 670interface Dictionary { 671 AddValue(string key, Value value); 672}; 673``` 674 675This generates the following C++ interface: 676 677```cpp 678class Value { 679 public: 680 ~Value() {} 681}; 682 683class Dictionary { 684 public: 685 virtual ~Dictionary() {} 686 687 virtual void AddValue(const std::string& key, ValuePtr value) = 0; 688}; 689``` 690 691And we can use it like so: 692 693```cpp 694ValuePtr value = Value::New(); 695value->set_int_value(42); 696CHECK(value->is_int_value()); 697CHECK_EQ(value->which(), Value::Tag::INT_VALUE); 698 699value->set_float_value(42); 700CHECK(value->is_float_value()); 701CHECK_EQ(value->which(), Value::Tag::FLOAT_VALUE); 702 703value->set_string_value("bananas"); 704CHECK(value->is_string_value()); 705CHECK_EQ(value->which(), Value::Tag::STRING_VALUE); 706``` 707 708Finally, note that if a union value is not currently occupied by a given field, 709attempts to access that field will DCHECK: 710 711```cpp 712ValuePtr value = Value::New(); 713value->set_int_value(42); 714LOG(INFO) << "Value is " << value->string_value(); // DCHECK! 715``` 716 717### Sending Interfaces Over Interfaces 718 719We know how to create interface pipes and use their Remote and PendingReceiver endpoints 720in some interesting ways. This still doesn't add up to interesting IPC! The 721bread and butter of Mojo IPC is the ability to transfer interface endpoints 722across other interfaces, so let's take a look at how to accomplish that. 723 724#### Sending Pending Receivers 725 726Consider a new example Mojom in `//sample/db.mojom`: 727 728``` cpp 729module db.mojom; 730 731interface Table { 732 void AddRow(int32 key, string data); 733}; 734 735interface Database { 736 AddTable(pending_receiver<Table> table); 737}; 738``` 739 740As noted in the 741[Mojom IDL documentation](/mojo/public/tools/bindings/README.md#Primitive-Types), // need to update this page too! 742the `pending_receiver<Table>` syntax corresponds 743precisely to the `PendingReceiver<T>` type discussed in the sections above, and 744in fact the generated code for these interfaces is approximately: 745 746``` cpp 747namespace db { 748namespace mojom { 749 750class Table { 751 public: 752 virtual ~Table() {} 753 754 virtual void AddRow(int32_t key, const std::string& data) = 0; 755} 756 757class Database { 758 public: 759 virtual ~Database() {} 760 761 virtual void AddTable(mojo::PendingReceiver<Table> table); 762}; 763 764} // namespace mojom 765} // namespace db 766``` 767 768We can put this all together now with an implementation of `Table` and 769`Database`: 770 771``` cpp 772#include "sample/db.mojom.h" 773 774class TableImpl : public db::mojom:Table { 775 public: 776 explicit TableImpl(mojo::PendingReceiver<db::mojom::Table> receiver) 777 : receiver_(this, std::move(receiver)) {} 778 ~TableImpl() override {} 779 780 // db::mojom::Table: 781 void AddRow(int32_t key, const std::string& data) override { 782 rows_.insert({key, data}); 783 } 784 785 private: 786 mojo::Receiver<db::mojom::Table> receiver_; 787 std::map<int32_t, std::string> rows_; 788}; 789 790class DatabaseImpl : public db::mojom::Database { 791 public: 792 explicit DatabaseImpl(mojo::PendingReceiver<db::mojom::Database> receiver) 793 : receiver_(this, std::move(receiver)) {} 794 ~DatabaseImpl() override {} 795 796 // db::mojom::Database: 797 void AddTable(mojo::PendingReceiver<db::mojom::Table> table) { 798 tables_.emplace_back(std::make_unique<TableImpl>(std::move(table))); 799 } 800 801 private: 802 mojo::Receiver<db::mojom::Database> receiver_; 803 std::vector<std::unique_ptr<TableImpl>> tables_; 804}; 805``` 806 807Pretty straightforward. The `pending_receiver<Table>` Mojom parameter to `AddTable` translates to 808a C++ `mojo::PendingReceiver<db::mojom::Table>`, which we know is just a 809strongly-typed message pipe handle. When `DatabaseImpl` gets an `AddTable` call, 810it constructs a new `TableImpl` and binds it to the received `mojo::PendingReceiver<db::mojom::Table>`. 811 812Let's see how this can be used. 813 814``` cpp 815mojo::Remote<db::mojom::Database> database; 816DatabaseImpl db_impl(database.BindNewPipeAndPassReceiver()); 817 818mojo::Remote<db::mojom::Table> table1, table2; 819database->AddTable(table1.BindNewPipeAndPassReceiver()); 820database->AddTable(table2.BindNewPipeAndPassReceiver()); 821 822table1->AddRow(1, "hiiiiiiii"); 823table2->AddRow(2, "heyyyyyy"); 824``` 825 826Notice that we can again start using the new `Table` pipes immediately, even 827while their `mojo::PendingReceiver<db::mojom::Table>` endpoints are still in transit. 828 829#### Sending Remotes 830 831Of course we can also send `Remote`s: 832 833``` cpp 834interface TableListener { 835 OnRowAdded(int32 key, string data); 836}; 837 838interface Table { 839 AddRow(int32 key, string data); 840 841 AddListener(pending_remote<TableListener> listener); 842}; 843``` 844 845This would generate a `Table::AddListener` signature like so: 846 847``` cpp 848 virtual void AddListener(mojo::PendingRemote<TableListener> listener) = 0; 849``` 850 851and this could be used like so: 852 853``` cpp 854mojo::PendingRemote<db::mojom::TableListener> listener; 855TableListenerImpl impl(listener.InitWithNewPipeAndPassReceiver()); 856table->AddListener(std::move(listener)); 857``` 858 859## Other Interface Binding Types 860 861The [Interfaces](#Interfaces) section above covers basic usage of the most 862common bindings object types: `Remote`, `PendingReceiver`, and `Receiver`. 863While these types are probably the most commonly used in practice, there are 864several other ways of binding both client- and implementation-side interface 865pipes. 866 867### Self-owned Receivers 868 869A **self-owned receiver** exists as a standalone object which owns its interface 870implementation and automatically cleans itself up when its bound interface 871endpoint detects an error. The 872[**`MakeSelfOwnedReceiver`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/self_owned_receiver.h) 873function is used to create such a receiver. 874. 875 876``` cpp 877class LoggerImpl : public sample::mojom::Logger { 878 public: 879 LoggerImpl() {} 880 ~LoggerImpl() override {} 881 882 // sample::mojom::Logger: 883 void Log(const std::string& message) override { 884 LOG(ERROR) << "[Logger] " << message; 885 } 886 887 private: 888 // NOTE: This doesn't own any Receiver object! 889}; 890 891mojo::Remote<db::mojom::Logger> logger; 892mojo::MakeSelfOwnedReceiver(std::make_unique<LoggerImpl>(), 893 logger.BindNewPipeAndPassReceiver()); 894 895logger->Log("NOM NOM NOM MESSAGES"); 896``` 897 898Now as long as `logger` remains open somewhere in the system, the bound 899`LoggerImpl` on the other end will remain alive. 900 901### Receiver Sets 902 903Sometimes it's useful to share a single implementation instance with multiple 904clients. [**`ReceiverSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/receiver_set.h) 905makes this easy. Consider the Mojom: 906 907``` cpp 908module system.mojom; 909 910interface Logger { 911 Log(string message); 912}; 913 914interface LoggerProvider { 915 GetLogger(Logger& logger); 916}; 917``` 918 919We can use `ReceiverSet` to bind multiple `Logger` pending receivers to a single 920implementation instance: 921 922``` cpp 923class LogManager : public system::mojom::LoggerProvider, 924 public system::mojom::Logger { 925 public: 926 explicit LogManager(mojo::PendingReceiver<system::mojom::LoggerProvider> receiver) 927 : provider_receiver_(this, std::move(receiver)) {} 928 ~LogManager() {} 929 930 // system::mojom::LoggerProvider: 931 void GetLogger(mojo::PendingReceiver<Logger> receiver) override { 932 logger_receivers_.Add(this, std::move(receiver)); 933 } 934 935 // system::mojom::Logger: 936 void Log(const std::string& message) override { 937 LOG(ERROR) << "[Logger] " << message; 938 } 939 940 private: 941 mojo::Receiver<system::mojom::LoggerProvider> provider_receiver_; 942 mojo::ReceiverSet<system::mojom::Logger> logger_receivers_; 943}; 944 945``` 946 947 948### Remote Sets 949 950Similar to the `ReceiverSet` above, sometimes it's useful to maintain a set of 951`Remote`s for *e.g.* a set of clients observing some event. 952[**`RemoteSet`**](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/remote_set.h) 953is here to help. Take the Mojom: 954 955``` cpp 956module db.mojom; 957 958interface TableListener { 959 OnRowAdded(int32 key, string data); 960}; 961 962interface Table { 963 AddRow(int32 key, string data); 964 AddListener(pending_remote<TableListener> listener); 965}; 966``` 967 968An implementation of `Table` might look something like like this: 969 970``` cpp 971class TableImpl : public db::mojom::Table { 972 public: 973 TableImpl() {} 974 ~TableImpl() override {} 975 976 // db::mojom::Table: 977 void AddRow(int32_t key, const std::string& data) override { 978 rows_.insert({key, data}); 979 listeners_.ForEach([key, &data](db::mojom::TableListener* listener) { 980 listener->OnRowAdded(key, data); 981 }); 982 } 983 984 void AddListener(mojo::PendingRemote<db::mojom::TableListener> listener) { 985 listeners_.Add(std::move(listener)); 986 } 987 988 private: 989 mojo::RemoteSet<db::mojom::Table> listeners_; 990 std::map<int32_t, std::string> rows_; 991}; 992``` 993 994## Associated Interfaces 995 996Associated interfaces are interfaces which: 997 998* enable running multiple interfaces over a single message pipe while 999 preserving message ordering. 1000* make it possible for the receiver to access a single message pipe from 1001 multiple sequences. 1002 1003### Mojom 1004 1005A new keyword `associated` is introduced for remote/receiver 1006fields. For example: 1007 1008``` cpp 1009interface Bar {}; 1010 1011struct Qux { 1012 pending_associated_remote<Bar> bar3; 1013}; 1014 1015interface Foo { 1016 // Uses associated remote. 1017 SetBar(pending_associated_remote<Bar> bar1); 1018 // Uses associated receiver. 1019 GetBar(pending_associated_receiver<Bar> bar2); 1020 // Passes a struct with associated interface pointer. 1021 PassQux(Qux qux); 1022 // Uses associated interface pointer in callback. 1023 AsyncGetBar() => (pending_associated_remote<Bar> bar4); 1024}; 1025``` 1026 1027It means the interface impl/client will communicate using the same 1028message pipe over which the associated remote/receiver is 1029passed. 1030 1031### Using associated interfaces in C++ 1032 1033When generating C++ bindings, the pending_associated_remote of `Bar` is 1034mapped to `mojo::PendingAssociatedRemote<Bar>`; pending_associated_receiver to 1035`mojo::PendingAssociatedReceiver<Bar>`. 1036 1037``` cpp 1038// In mojom: 1039interface Foo { 1040 ... 1041 SetBar(pending_associated_remote<Bar> bar1); 1042 GetBar(pending_associated_receiver<Bar> bar2); 1043 ... 1044}; 1045 1046// In C++: 1047class Foo { 1048 ... 1049 virtual void SetBar(mojo::PendingAssociatedRemote<Bar> bar1) = 0; 1050 virtual void GetBar(mojo::PendingAssociatedReceiver<Bar> bar2) = 0; 1051 ... 1052}; 1053``` 1054 1055#### Passing pending associated receivers 1056 1057Assume you have already got an `Remote<Foo> foo`, and you would like 1058to call `GetBar()` on it. You can do: 1059 1060``` cpp 1061mojo::PendingAssociatedRemote<Bar> pending_bar; 1062mojo::PendingAssociatedReceiver<Bar> bar_receiver = pending_bar.InitWithNewEndpointAndPassReceiver(); 1063foo->GetBar(std::move(bar_receiver)); 1064 1065mojo::AssociatedRemote<Bar> bar; 1066bar.Bind(std::move(pending_bar)); 1067bar->DoSomething(); 1068``` 1069 1070First, the code creates an associated interface of type `Bar`. It looks very 1071similar to what you would do to setup a non-associated interface. An 1072important difference is that one of the two associated endpoints (either 1073`bar_receiver` or `pending_bar`) must be sent over another interface. That is 1074how the interface is associated with an existing message pipe. 1075 1076It should be noted that you cannot call `bar->DoSomething()` before passing 1077`bar_receiver`. This is required by the FIFO-ness guarantee: at the receiver 1078side, when the message of `DoSomething` call arrives, we want to dispatch it to 1079the corresponding `AssociatedReceiver<Bar>` before processing any subsequent 1080messages. If `bar_receiver` is in a subsequent message, message dispatching gets 1081into a deadlock. On the other hand, as soon as `bar_receiver` is sent, `bar` 1082is usable. There is no need to wait until `bar_receiver` is bound to an 1083implementation at the remote side. 1084 1085`AssociatedRemote` provides a `BindNewEndpointAndPassReceiver` method 1086to make the code a little shorter. The following code achieves the same purpose: 1087 1088``` cpp 1089mojo::AssociatedRemote<Bar> bar; 1090foo->GetBar(bar.BindNewEndpointAndPassReceiver()); 1091bar->DoSomething(); 1092``` 1093 1094The implementation of `Foo` looks like this: 1095 1096``` cpp 1097class FooImpl : public Foo { 1098 ... 1099 void GetBar(mojo::AssociatedReceiver<Bar> bar2) override { 1100 bar_receiver_.Bind(std::move(bar2)); 1101 ... 1102 } 1103 ... 1104 1105 Receiver<Foo> foo_receiver_; 1106 AssociatedReceiver<Bar> bar_receiver_; 1107}; 1108``` 1109 1110In this example, `bar_receiver_`'s lifespan is tied to that of `FooImpl`. But you 1111don't have to do that. You can, for example, pass `bar2` to another sequence to 1112bind to an `AssociatedReceiver<Bar>` there. 1113 1114When the underlying message pipe is disconnected (e.g., `foo` or 1115`foo_receiver_` is destroyed), all associated interface endpoints (e.g., 1116`bar` and `bar_receiver_`) will receive a disconnect error. 1117 1118#### Passing associated remotes 1119 1120Similarly, assume you have already got an `Remote<Foo> foo`, and you 1121would like to call `SetBar()` on it. You can do: 1122 1123``` cpp 1124mojo::AssociatedReceiver<Bar> bar_receiver(some_bar_impl); 1125mojo::PendingAssociatedRemote<Bar> bar; 1126mojo::PendingAssociatedReceiver<Bar> bar_pending_receiver = bar.InitWithNewEndpointAndPassReceiver(); 1127foo->SetBar(std::move(bar)); 1128bar_receiver.Bind(std::move(bar_pending_receiver)); 1129``` 1130 1131The following code achieves the same purpose: 1132 1133``` cpp 1134mojo::AssociatedReceiver<Bar> bar_receiver(some_bar_impl); 1135mojo::PendingAssociatedRemote<Bar> bar; 1136bar_receiver.Bind(bar.InitWithNewPipeAndPassReceiver()); 1137foo->SetBar(std::move(bar)); 1138``` 1139 1140### Performance considerations 1141 1142When using associated interfaces on different sequences than the master sequence 1143(where the master interface lives): 1144 1145* Sending messages: send happens directly on the calling sequence. So there 1146 isn't sequence hopping. 1147* Receiving messages: associated interfaces bound on a different sequence from 1148 the master interface incur an extra sequence hop during dispatch. 1149 1150Therefore, performance-wise associated interfaces are better suited for 1151scenarios where message receiving happens on the master sequence. 1152 1153### Testing 1154 1155Associated interfaces need to be associated with a master interface before 1156they can be used. This means one end of the associated interface must be sent 1157over one end of the master interface, or over one end of another associated 1158interface which itself already has a master interface. 1159 1160If you want to test an associated interface endpoint without first 1161associating it, you can use `AssociatedRemote::BindNewEndpointAndPassDedicatedReceiverForTesting`. 1162This will create working associated interface endpoints which are not actually 1163associated with anything else. 1164 1165### Read more 1166 1167* [Design: Mojo Associated Interfaces](https://docs.google.com/document/d/1nq3J_HbS-gvVfIoEhcVyxm1uY-9G_7lhD-4Kyxb1WIY/edit) 1168 1169## Synchronous Calls 1170 1171### Think carefully before you decide to use sync calls 1172 1173Although sync calls are convenient, you should avoid them whenever they 1174are not absolutely necessary: 1175 1176* Sync calls hurt parallelism and therefore hurt performance. 1177* Re-entrancy changes message order and produces call stacks that you 1178probably never think about while you are coding. It has always been a 1179huge pain. 1180* Sync calls may lead to deadlocks. 1181 1182### Mojom changes 1183 1184A new attribute `[Sync]` (or `[Sync=true]`) is introduced for methods. 1185For example: 1186 1187``` cpp 1188interface Foo { 1189 [Sync] 1190 SomeSyncCall() => (Bar result); 1191}; 1192``` 1193 1194It indicates that when `SomeSyncCall()` is called, the control flow of 1195the calling thread is blocked until the response is received. 1196 1197It is not allowed to use this attribute with functions that don’t have 1198responses. If you just need to wait until the service side finishes 1199processing the call, you can use an empty response parameter list: 1200 1201``` cpp 1202[Sync] 1203SomeSyncCallWithNoResult() => (); 1204``` 1205 1206### Generated bindings (C++) 1207 1208The generated C++ interface of the Foo interface above is: 1209 1210``` cpp 1211class Foo { 1212 public: 1213 // The service side implements this signature. The client side can 1214 // also use this signature if it wants to call the method asynchronously. 1215 virtual void SomeSyncCall(SomeSyncCallCallback callback) = 0; 1216 1217 // The client side uses this signature to call the method synchronously. 1218 virtual bool SomeSyncCall(BarPtr* result); 1219}; 1220``` 1221 1222As you can see, the client side and the service side use different 1223signatures. At the client side, response is mapped to output parameters 1224and the boolean return value indicates whether the operation is 1225successful. (Returning false usually means a connection error has 1226occurred.) 1227 1228At the service side, a signature with callback is used. The reason is 1229that in some cases the implementation may need to do some asynchronous 1230work which the sync method’s result depends on. 1231 1232*** note 1233**NOTE:** you can also use the signature with callback at the client side to 1234call the method asynchronously. 1235*** 1236 1237### Re-entrancy 1238 1239What happens on the calling thread while waiting for the response of a 1240sync method call? It continues to process incoming sync request messages 1241(i.e., sync method calls); block other messages, including async 1242messages and sync response messages that don’t match the ongoing sync 1243call. 1244 1245![Diagram illustrating sync call flow](/docs/images/mojo_sync_call_flow.png) 1246 1247Please note that sync response messages that don’t match the ongoing 1248sync call cannot re-enter. That is because they correspond to sync calls 1249down in the call stack. Therefore, they need to be queued and processed 1250while the stack unwinds. 1251 1252### Avoid deadlocks 1253 1254Please note that the re-entrancy behavior doesn’t prevent deadlocks 1255involving async calls. You need to avoid call sequences such as: 1256 1257![Diagram illustrating a sync call deadlock](/docs/images/mojo_sync_call_deadlock.png) 1258 1259### Read more 1260 1261* [Design Proposal: Mojo Sync Methods]( 1262https://docs.google.com/document/d/1dixzFzZQW8e3ldjdM8Adbo8klXDDE4pVekwo5aLgUsE) 1263 1264## Type Mapping 1265 1266In many instances you might prefer that your generated C++ bindings use a more 1267natural type to represent certain Mojom types in your interface methods. For one 1268example consider a Mojom struct such as the `Rect` below: 1269 1270``` cpp 1271module gfx.mojom; 1272 1273struct Rect { 1274 int32 x; 1275 int32 y; 1276 int32 width; 1277 int32 height; 1278}; 1279 1280interface Canvas { 1281 void FillRect(Rect rect); 1282}; 1283``` 1284 1285The `Canvas` Mojom interface would normally generate a C++ interface like: 1286 1287``` cpp 1288class Canvas { 1289 public: 1290 virtual void FillRect(RectPtr rect) = 0; 1291}; 1292``` 1293 1294However, the Chromium tree already defines a native 1295[`gfx::Rect`](https://cs.chromium.org/chromium/src/ui/gfx/geometry/rect.h) which 1296is equivalent in meaning but which also has useful helper methods. Instead of 1297manually converting between a `gfx::Rect` and the Mojom-generated `RectPtr` at 1298every message boundary, wouldn't it be nice if the Mojom bindings generator 1299could instead generate: 1300 1301``` cpp 1302class Canvas { 1303 public: 1304 virtual void FillRect(const gfx::Rect& rect) = 0; 1305} 1306``` 1307 1308The correct answer is, "Yes! That would be nice!" And fortunately, it can! 1309 1310### Defining `StructTraits` 1311 1312In order to teach generated bindings code how to serialize an arbitrary native 1313type `T` as an arbitrary Mojom type `mojom::U`, we need to define an appropriate 1314specialization of the 1315[`mojo::StructTraits`](https://cs.chromium.org/chromium/src/mojo/public/cpp/bindings/struct_traits.h) 1316template. 1317 1318A valid specialization of `StructTraits` MUST define the following static 1319methods: 1320 1321* A single static accessor for every field of the Mojom struct, with the exact 1322 same name as the struct field. These accessors must all take a (preferably 1323 const) ref to an object of the native type, and must return a value compatible 1324 with the Mojom struct field's type. This is used to safely and consistently 1325 extract data from the native type during message serialization without 1326 incurring extra copying costs. 1327 1328* A single static `Read` method which initializes an instance of the the native 1329 type given a serialized representation of the Mojom struct. The `Read` method 1330 must return a `bool` to indicate whether the incoming data is accepted 1331 (`true`) or rejected (`false`). 1332 1333There are other methods a `StructTraits` specialization may define to satisfy 1334some less common requirements. See 1335[Advanced StructTraits Usage](#Advanced-StructTraits-Usage) for details. 1336 1337In order to define the mapping for `gfx::Rect`, we want the following 1338`StructTraits` specialization, which we'll define in 1339`//ui/gfx/geometry/mojo/geometry_mojom_traits.h`: 1340 1341``` cpp 1342#include "mojo/public/cpp/bindings/mojom_traits.h" 1343#include "ui/gfx/geometry/rect.h" 1344#include "ui/gfx/geometry/mojo/geometry.mojom.h" 1345 1346namespace mojo { 1347 1348template <> 1349class StructTraits<gfx::mojom::RectDataView, gfx::Rect> { 1350 public: 1351 static int32_t x(const gfx::Rect& r) { return r.x(); } 1352 static int32_t y(const gfx::Rect& r) { return r.y(); } 1353 static int32_t width(const gfx::Rect& r) { return r.width(); } 1354 static int32_t height(const gfx::Rect& r) { return r.height(); } 1355 1356 static bool Read(gfx::mojom::RectDataView data, gfx::Rect* out_rect); 1357}; 1358 1359} // namespace mojo 1360``` 1361 1362And in `//ui/gfx/geometry/mojo/geometry_mojom_traits.cc`: 1363 1364``` cpp 1365#include "ui/gfx/geometry/mojo/geometry_mojom_traits.h" 1366 1367namespace mojo { 1368 1369// static 1370bool StructTraits<gfx::mojom::RectDataView, gfx::Rect>::Read( 1371 gfx::mojom::RectDataView data, 1372 gfx::Rect* out_rect) { 1373 if (data.width() < 0 || data.height() < 0) 1374 return false; 1375 1376 out_rect->SetRect(data.x(), data.y(), data.width(), data.height()); 1377 return true; 1378}; 1379 1380} // namespace mojo 1381``` 1382 1383Note that the `Read()` method returns `false` if either the incoming `width` or 1384`height` fields are negative. This acts as a validation step during 1385deserialization: if a client sends a `gfx::Rect` with a negative width or 1386height, its message will be rejected and the pipe will be closed. In this way, 1387type mapping can serve to enable custom validation logic in addition to making 1388callsites and interface implemention more convenient. 1389 1390When the struct fields have non-primitive types, e.g. string or array, 1391returning a read-only view of the data in the accessor is recommended to 1392avoid copying. It is safe because the input object is guaranteed to 1393outlive the usage of the result returned by the accessor method. 1394 1395The following example uses `StringPiece` to return a view of the GURL's 1396data (`//url/mojom/url_gurl_mojom_traits.h`): 1397 1398``` cpp 1399#include "base/strings/string_piece.h" 1400#include "url/gurl.h" 1401#include "url/mojom/url.mojom.h" 1402#include "url/url_constants.h" 1403 1404namespace mojo { 1405 1406template <> 1407struct StructTraits<url::mojom::UrlDataView, GURL> { 1408 static base::StringPiece url(const GURL& r) { 1409 if (r.possibly_invalid_spec().length() > url::kMaxURLChars || 1410 !r.is_valid()) { 1411 return base::StringPiece(); 1412 } 1413 return base::StringPiece(r.possibly_invalid_spec().c_str(), 1414 r.possibly_invalid_spec().length()); 1415 } 1416} // namespace mojo 1417``` 1418 1419### Enabling a New Type Mapping 1420 1421We've defined the `StructTraits` necessary, but we still need to teach the 1422bindings generator (and hence the build system) about the mapping. To do this we 1423must add some more information to our `mojom` target in GN: 1424 1425``` 1426# Without a typemap 1427mojom("mojom") { 1428 sources = [ 1429 "rect.mojom", 1430 ] 1431} 1432 1433# With a typemap. 1434mojom("mojom") { 1435 sources = [ 1436 "rect.mojom", 1437 ] 1438 1439 cpp_typemaps = [ 1440 { 1441 # NOTE: A single typemap entry can list multiple individual type mappings. 1442 # Each mapping assumes the same values for |traits_headers| etc below. 1443 # 1444 # To typemap a type with separate |traits_headers| etc, add a separate 1445 # entry to |cpp_typemaps|. 1446 types = [ 1447 { 1448 mojom = "gfx.mojom.Rect" 1449 cpp = "::gfx::Rect" 1450 }, 1451 ] 1452 traits_headers = [ "//ui/gfx/geometry/mojo/geometry_mojom_traits.h" ] 1453 traits_sources = [ "//ui/gfx/geometry/mojo/geometry_mojom_traits.cc" ] 1454 traits_public_deps = [ "//ui/gfx/geometry" ] 1455 }, 1456 ] 1457} 1458``` 1459 1460See typemap documentation in 1461[mojom.gni](https://cs.chromium.org/chromium/src/mojo/public/tools/bindings/mojom.gni) 1462for details on the above definition and other supported parameters. 1463 1464With this extra configuration present, any mojom references to `gfx.mojom.Rect` 1465(e.g. for method parameters or struct fields) will be `gfx::Rect` references in 1466generated C++ code. 1467``` 1468 1469For the Blink variant of bindings, add to the `blink_cpp_typemaps` list instead. 1470 1471### Type Mapping Without `traits_sources` 1472 1473Using `traits_sources` in a typemap configuration means that the listed sources 1474will be baked directly into the corresponding `mojom` target's own sources. This 1475can be problematic if you want to use the same typemap for both Blink and 1476non-Blink bindings. 1477 1478For such cases, it is recommended that you define a separate `component` target 1479for your typemap traits, and reference this in the `traits_public_deps` of the 1480typemap: 1481 1482``` 1483mojom("mojom") { 1484 sources = [ 1485 "rect.mojom", 1486 ] 1487 1488 cpp_typemaps = [ 1489 { 1490 types = [ 1491 { 1492 mojom = "gfx.mojom.Rect" 1493 cpp = "::gfx::Rect" 1494 }, 1495 ] 1496 traits_headers = [ "//ui/gfx/geometry/mojo/geometry_mojom_traits.h" ] 1497 traits_public_deps = [ ":geometry_mojom_traits" ] 1498 }, 1499 ] 1500} 1501 1502component("geometry_mojom_traits") { 1503 sources = [ 1504 "//ui/gfx/geometry/mojo/geometry_mojom_traits.cc", 1505 "//ui/gfx/geometry/mojo/geometry_mojom_traits.h", 1506 ] 1507 1508 # The header of course needs corresponding COMPONENT_EXPORT() tags. 1509 defines = [ "IS_GEOMETRY_MOJOM_TRAITS_IMPL" ] 1510} 1511``` 1512 1513### StructTraits Reference 1514 1515Each of a `StructTraits` specialization's static getter methods -- one per 1516struct field -- must return a type which can be used as a data source for the 1517field during serialization. This is a quick reference mapping Mojom field type 1518to valid getter return types: 1519 1520| Mojom Field Type | C++ Getter Return Type | 1521|------------------------------|------------------------| 1522| `bool` | `bool` 1523| `int8` | `int8_t` 1524| `uint8` | `uint8_t` 1525| `int16` | `int16_t` 1526| `uint16` | `uint16_t` 1527| `int32` | `int32_t` 1528| `uint32` | `uint32_t` 1529| `int64` | `int64_t` 1530| `uint64` | `uint64_t` 1531| `float` | `float` 1532| `double` | `double` 1533| `handle` | `mojo::ScopedHandle` 1534| `handle<message_pipe>` | `mojo::ScopedMessagePipeHandle` 1535| `handle<data_pipe_consumer>` | `mojo::ScopedDataPipeConsumerHandle` 1536| `handle<data_pipe_producer>` | `mojo::ScopedDataPipeProducerHandle` 1537| `handle<shared_buffer>` | `mojo::ScopedSharedBufferHandle` 1538| `pending_remote<Foo>` | `mojo::PendingRemote<Foo>` 1539| `pending_receiver<Foo>` | `mojo::PendingReceiver<Foo>` 1540| `pending_associated_remote<Foo>` | `mojo::PendingAssociatedRemote<Foo>` 1541| `pending_associated_receiver<Foo>` | `mojo::PendingAssociatedReceiver<Foo>` 1542| `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). 1543| `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). 1544| `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). 1545| `FooEnum` | Value of any type that has an appropriate `EnumTraits` specialization defined. By default this inlcudes only the generated `FooEnum` type. 1546| `FooStruct` | Value or reference to any type that has an appropriate `StructTraits` specialization defined. By default this includes only the generated `FooStructPtr` type. 1547| `FooUnion` | Value of reference to any type that has an appropriate `UnionTraits` specialization defined. By default this includes only the generated `FooUnionPtr` type. 1548| `Foo?` | `base::Optional<CppType>`, where `CppType` is the value type defined by the appropriate traits class specialization (e.g. `StructTraits`, `mojo::MapTraits`, etc.). This may be customized by the [typemapping](#Enabling-a-New-Type-Mapping). 1549 1550### Using Generated DataView Types 1551 1552Static `Read` methods on `StructTraits` specializations get a generated 1553`FooDataView` argument (such as the `RectDataView` in the example above) which 1554exposes a direct view of the serialized Mojom structure within an incoming 1555message's contents. In order to make this as easy to work with as possible, the 1556generated `FooDataView` types have a generated method corresponding to every 1557struct field: 1558 1559* For POD field types (*e.g.* bools, floats, integers) these are simple accessor 1560 methods with names identical to the field name. Hence in the `Rect` example we 1561 can access things like `data.x()` and `data.width()`. The return types 1562 correspond exactly to the mappings listed in the table above, under 1563 [StructTraits Reference](#StructTraits-Reference). 1564 1565* For handle and interface types (*e.g* `handle` or `pending_remote<Foo>`) these 1566 are named `TakeFieldName` (for a field named `field_name`) and they return an 1567 appropriate move-only handle type by value. The return types correspond 1568 exactly to the mappings listed in the table above, under 1569 [StructTraits Reference](#StructTraits-Reference). 1570 1571* For all other field types (*e.g.*, enums, strings, arrays, maps, structs) 1572 these are named `ReadFieldName` (for a field named `field_name`) and they 1573 return a `bool` (to indicate success or failure in reading). On success they 1574 fill their output argument with the deserialized field value. The output 1575 argument may be a pointer to any type with an appropriate `StructTraits` 1576 specialization defined, as mentioned in the table above, under 1577 [StructTraits Reference](#StructTraits-Reference). 1578 1579An example would be useful here. Suppose we introduced a new Mojom struct: 1580 1581``` cpp 1582struct RectPair { 1583 Rect left; 1584 Rect right; 1585}; 1586``` 1587 1588and a corresponding C++ type: 1589 1590``` cpp 1591class RectPair { 1592 public: 1593 RectPair() {} 1594 1595 const gfx::Rect& left() const { return left_; } 1596 const gfx::Rect& right() const { return right_; } 1597 1598 void Set(const gfx::Rect& left, const gfx::Rect& right) { 1599 left_ = left; 1600 right_ = right; 1601 } 1602 1603 // ... some other stuff 1604 1605 private: 1606 gfx::Rect left_; 1607 gfx::Rect right_; 1608}; 1609``` 1610 1611Our traits to map `gfx::mojom::RectPair` to `gfx::RectPair` might look like 1612this: 1613 1614``` cpp 1615namespace mojo { 1616 1617template <> 1618class StructTraits 1619 public: 1620 static const gfx::Rect& left(const gfx::RectPair& pair) { 1621 return pair.left(); 1622 } 1623 1624 static const gfx::Rect& right(const gfx::RectPair& pair) { 1625 return pair.right(); 1626 } 1627 1628 static bool Read(gfx::mojom::RectPairDataView data, gfx::RectPair* out_pair) { 1629 gfx::Rect left, right; 1630 if (!data.ReadLeft(&left) || !data.ReadRight(&right)) 1631 return false; 1632 out_pair->Set(left, right); 1633 return true; 1634 } 1635} // namespace mojo 1636``` 1637 1638Generated `ReadFoo` methods always convert `multi_word_field_name` fields to 1639`ReadMultiWordFieldName` methods. 1640 1641<a name="Blink-Type-Mapping"></a> 1642### Variants 1643 1644By now you may have noticed that additional C++ sources are generated when a 1645Mojom is processed. These exist due to type mapping, and the source files we 1646refer to throughout this docuemnt (namely `foo.mojom.cc` and `foo.mojom.h`) are 1647really only one **variant** (the *default* or *chromium* variant) of the C++ 1648bindings for a given Mojom file. 1649 1650The only other variant currently defined in the tree is the *blink* variant, 1651which produces a few additional files: 1652 1653``` 1654out/gen/sample/db.mojom-blink.cc 1655out/gen/sample/db.mojom-blink.h 1656``` 1657 1658These files mirror the definitions in the default variant but with different 1659C++ types in place of certain builtin field and parameter types. For example, 1660Mojom strings are represented by `WTF::String` instead of `std::string`. To 1661avoid symbol collisions, the variant's symbols are nested in an extra inner 1662namespace, so Blink consumer of the interface might write something like: 1663 1664``` 1665#include "sample/db.mojom-blink.h" 1666 1667class TableImpl : public db::mojom::blink::Table { 1668 public: 1669 void AddRow(int32_t key, const WTF::String& data) override { 1670 // ... 1671 } 1672}; 1673``` 1674 1675In addition to using different C++ types for builtin strings, arrays, and maps, 1676the custom typemaps applied to Blink bindings are managed separately from 1677regular bindings. 1678 1679`mojom` targets support a `blink_cpp_typemaps` parameter in addition to the 1680regular `cpp_typemaps`. This lists the typemaps to apply to Blink bindings. 1681 1682To depend specifically on generated Blink bindings, reference 1683`${target_name}_blink`. So for example, with the definition: 1684 1685``` 1686# In //foo/mojom 1687mojom("mojom") { 1688 sources = [ 1689 "db.mojom", 1690 ] 1691} 1692``` 1693 1694C++ sources can depend on the Blink bindings by depending on 1695`"//foo/mojom:mojom_blink"`. 1696 1697Finally note that both bindings variants share some common definitions which are 1698unaffected by differences in the type-mapping configuration (like enums, and 1699structures describing serialized object formats). These definitions are 1700generated in *shared* sources: 1701 1702``` 1703out/gen/sample/db.mojom-shared.cc 1704out/gen/sample/db.mojom-shared.h 1705out/gen/sample/db.mojom-shared-internal.h 1706``` 1707 1708Including either variant's header (`db.mojom.h` or `db.mojom-blink.h`) 1709implicitly includes the shared header, but may wish to include *only* the shared 1710header in some instances. 1711 1712C++ sources can depend on shared sources only, by referencing the 1713`"${target_name}_shared"` target, e.g. `"//foo/mojom:mojom_shared"` in the 1714example above. 1715 1716## Versioning Considerations 1717 1718For general documentation of versioning in the Mojom IDL see 1719[Versioning](/mojo/public/tools/bindings/README.md#Versioning). 1720 1721This section briefly discusses some C++-specific considerations relevant to 1722versioned Mojom types. 1723 1724### Querying Interface Versions 1725 1726`Remote` defines the following methods to query or assert remote interface 1727version: 1728 1729```cpp 1730void QueryVersion(base::OnceCallback<void(uint32_t)> callback); 1731``` 1732 1733This queries the remote endpoint for the version number of its binding. When a 1734response is received `callback` is invoked with the remote version number. Note 1735that this value is cached by the `Remote` instance to avoid redundant 1736queries. 1737 1738```cpp 1739void RequireVersion(uint32_t version); 1740``` 1741 1742Informs the remote endpoint that a minimum version of `version` is required by 1743the client. If the remote endpoint cannot support that version, it will close 1744its end of the pipe immediately, preventing any other requests from being 1745received. 1746 1747### Versioned Enums 1748 1749For convenience, every extensible enum has a generated helper function to 1750determine whether a received enum value is known by the implementation's current 1751version of the enum definition. For example: 1752 1753```cpp 1754[Extensible] 1755enum Department { 1756 SALES, 1757 DEV, 1758 RESEARCH, 1759}; 1760``` 1761 1762generates the function in the same namespace as the generated C++ enum type: 1763 1764```cpp 1765inline bool IsKnownEnumValue(Department value); 1766``` 1767 1768### Using Mojo Bindings in Chrome 1769 1770See [Converting Legacy Chrome IPC To Mojo](/docs/mojo_ipc_conversion.md). 1771 1772### Additional Documentation 1773 1774[Calling Mojo From Blink](/docs/mojo_ipc_conversion.md#Blink_Specific-Advice): 1775A brief overview of what it looks like to use Mojom C++ bindings from 1776within Blink code. 1777