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