OLD | NEW |
1 # Mojo in Chromium | 1 # Mojo in Chromium |
2 | 2 |
3 **THIS DOCUIMENT IS A WORK IN PROGRESS.** As long as this notice exists, you | 3 **THIS DOCUIMENT IS A WORK IN PROGRESS.** As long as this notice exists, you |
4 should probably ignore everything below it. | 4 should probably ignore everything below it. |
5 | 5 |
6 This document is intended to serve as a Mojo primer for Chromium developers. No | 6 This document is intended to serve as a Mojo primer for Chromium developers. No |
7 prior knowledge of Mojo is assumed, but you should have a decent grasp of C++ | 7 prior knowledge of Mojo is assumed, but you should have a decent grasp of C++ |
8 and be familiar with Chromium's multi-process architecture as well as common | 8 and be familiar with Chromium's multi-process architecture as well as common |
9 concepts used throughout Chromium such as smart pointers, message loops, | 9 concepts used throughout Chromium such as smart pointers, message loops, |
10 callback binding, and so on. | 10 callback binding, and so on. |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 and as for the `mojo::ServiceProvider` interface: | 329 and as for the `mojo::ServiceProvider` interface: |
330 | 330 |
331 ``` | 331 ``` |
332 module mojo; | 332 module mojo; |
333 interface ServiceProvider { | 333 interface ServiceProvider { |
334 ConnectToService(string interface_name, handle<message_pipe> pipe); | 334 ConnectToService(string interface_name, handle<message_pipe> pipe); |
335 }; | 335 }; |
336 ``` | 336 ``` |
337 | 337 |
338 Definitions for these interfaces can be found in | 338 Definitions for these interfaces can be found in |
339 `/mojo/application/public/interfaces`. Also note that `mojo::URLRequest` is a | 339 `/mojo/shell/public/interfaces`. Also note that `mojo::URLRequest` is a |
340 Mojo struct defined in | 340 Mojo struct defined in |
341 `/mojo/services/network/public/interfaces/url_loader.mojom`. | 341 `/mojo/services/network/public/interfaces/url_loader.mojom`. |
342 | 342 |
343 Note that there's some new syntax in the mojom for `ConnectToApplication` above. | 343 Note that there's some new syntax in the mojom for `ConnectToApplication` above. |
344 The '?' signifies a nullable value and the '&' signifies an interface request | 344 The '?' signifies a nullable value and the '&' signifies an interface request |
345 rather than an interface proxy. | 345 rather than an interface proxy. |
346 | 346 |
347 The argument `ServiceProvider&? services` indicates that the caller should pass | 347 The argument `ServiceProvider&? services` indicates that the caller should pass |
348 an `InterfaceRequest<ServiceProvider>` as the second argument, but that it need | 348 an `InterfaceRequest<ServiceProvider>` as the second argument, but that it need |
349 not be bound to a pipe (i.e., it can be "null" in which case it's ignored.) | 349 not be bound to a pipe (i.e., it can be "null" in which case it's ignored.) |
(...skipping 26 matching lines...) Expand all Loading... |
376 ServiceProvider&? services, | 376 ServiceProvider&? services, |
377 ServiceProvider? exposed_services, | 377 ServiceProvider? exposed_services, |
378 string resolved_url); | 378 string resolved_url); |
379 OnQuitRequested() => (bool can_quit); | 379 OnQuitRequested() => (bool can_quit); |
380 }; | 380 }; |
381 ``` | 381 ``` |
382 | 382 |
383 Of course, in Chromium and Mandoline environments this interface is obscured | 383 Of course, in Chromium and Mandoline environments this interface is obscured |
384 from application code and applications should generally just implement | 384 from application code and applications should generally just implement |
385 `mojo::ApplicationDelegate` (defined in | 385 `mojo::ApplicationDelegate` (defined in |
386 `/mojo/application/public/cpp/application_delegate.h`.) We'll see a concrete | 386 `/mojo/shell/public/cpp/application_delegate.h`.) We'll see a concrete |
387 example of this in the next section, | 387 example of this in the next section, |
388 [Your First Mojo Application](#Your-First-Mojo-Application). | 388 [Your First Mojo Application](#Your-First-Mojo-Application). |
389 | 389 |
390 The takeaway here is that an application can be anything. It's not necessarily a | 390 The takeaway here is that an application can be anything. It's not necessarily a |
391 new process (though at the moment, it's at least a new thread). Applications can | 391 new process (though at the moment, it's at least a new thread). Applications can |
392 connect to each other, and these connections are the mechanism through which | 392 connect to each other, and these connections are the mechanism through which |
393 separate components expose services to each other. | 393 separate components expose services to each other. |
394 | 394 |
395 **NOTE##: This is not true in Chromium today, but it should be eventually. For | 395 **NOTE##: This is not true in Chromium today, but it should be eventually. For |
396 some components (like render frames, or arbitrary browser process code) we | 396 some components (like render frames, or arbitrary browser process code) we |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 An app that prints `"Hello, world!"` isn't terribly interesting. At a bare | 482 An app that prints `"Hello, world!"` isn't terribly interesting. At a bare |
483 minimum your app should implement `mojo::ApplicationDelegate` and expose at | 483 minimum your app should implement `mojo::ApplicationDelegate` and expose at |
484 least one service to connecting applications. | 484 least one service to connecting applications. |
485 | 485 |
486 Let's update `main.cc` with the following contents: | 486 Let's update `main.cc` with the following contents: |
487 | 487 |
488 **components/hello/main.cc** | 488 **components/hello/main.cc** |
489 | 489 |
490 ```cpp | 490 ```cpp |
491 #include "components/hello/hello_app.h" | 491 #include "components/hello/hello_app.h" |
492 #include "mojo/application/public/cpp/application_runner.h" | 492 #include "mojo/shell/public/cpp/application_runner.h" |
493 #include "third_party/mojo/src/mojo/public/c/system/main.h" | 493 #include "third_party/mojo/src/mojo/public/c/system/main.h" |
494 | 494 |
495 MojoResult MojoMain(MojoHandle shell_handle) { | 495 MojoResult MojoMain(MojoHandle shell_handle) { |
496 mojo::ApplicationRunner runner(new hello::HelloApp); | 496 mojo::ApplicationRunner runner(new hello::HelloApp); |
497 return runner.Run(shell_handle); | 497 return runner.Run(shell_handle); |
498 }; | 498 }; |
499 ``` | 499 ``` |
500 | 500 |
501 This is a pretty typical looking `MojoMain`. Most of the time this is all you | 501 This is a pretty typical looking `MojoMain`. Most of the time this is all you |
502 want -- a `mojo::ApplicationRunner` constructed over a | 502 want -- a `mojo::ApplicationRunner` constructed over a |
(...skipping 25 matching lines...) Expand all Loading... |
528 ``` | 528 ``` |
529 | 529 |
530 **components/hello/hello_app.h** | 530 **components/hello/hello_app.h** |
531 | 531 |
532 ```cpp | 532 ```cpp |
533 #ifndef COMPONENTS_HELLO_HELLO_APP_H_ | 533 #ifndef COMPONENTS_HELLO_HELLO_APP_H_ |
534 #define COMPONENTS_HELLO_HELLO_APP_H_ | 534 #define COMPONENTS_HELLO_HELLO_APP_H_ |
535 | 535 |
536 #include "base/macros.h" | 536 #include "base/macros.h" |
537 #include "components/hello/public/interfaces/greeter.mojom.h" | 537 #include "components/hello/public/interfaces/greeter.mojom.h" |
538 #include "mojo/application/public/cpp/application_delegate.h" | 538 #include "mojo/shell/public/cpp/application_delegate.h" |
539 #include "mojo/application/public/cpp/interface_factory.h" | 539 #include "mojo/shell/public/cpp/interface_factory.h" |
540 | 540 |
541 namespace hello { | 541 namespace hello { |
542 | 542 |
543 class HelloApp : public mojo::ApplicationDelegate, | 543 class HelloApp : public mojo::ApplicationDelegate, |
544 public mojo::InterfaceFactory<Greeter> { | 544 public mojo::InterfaceFactory<Greeter> { |
545 public: | 545 public: |
546 HelloApp(); | 546 HelloApp(); |
547 ~HelloApp() override; | 547 ~HelloApp() override; |
548 | 548 |
549 private: | 549 private: |
(...skipping 12 matching lines...) Expand all Loading... |
562 | 562 |
563 #endif // COMPONENTS_HELLO_HELLO_APP_H_ | 563 #endif // COMPONENTS_HELLO_HELLO_APP_H_ |
564 ``` | 564 ``` |
565 | 565 |
566 | 566 |
567 **components/hello/hello_app.cc** | 567 **components/hello/hello_app.cc** |
568 | 568 |
569 ```cpp | 569 ```cpp |
570 #include "base/macros.h" | 570 #include "base/macros.h" |
571 #include "components/hello/hello_app.h" | 571 #include "components/hello/hello_app.h" |
572 #include "mojo/application/public/cpp/application_connection.h" | 572 #include "mojo/shell/public/cpp/application_connection.h" |
573 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" | 573 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" |
574 #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" | 574 #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" |
575 | 575 |
576 namespace hello { | 576 namespace hello { |
577 | 577 |
578 namespace { | 578 namespace { |
579 | 579 |
580 class GreeterImpl : public Greeter { | 580 class GreeterImpl : public Greeter { |
581 public: | 581 public: |
582 GreeterImpl(mojo::InterfaceRequest<Greeter> request) | 582 GreeterImpl(mojo::InterfaceRequest<Greeter> request) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 import("//mojo/public/mojo_application.gni") | 628 import("//mojo/public/mojo_application.gni") |
629 | 629 |
630 source_set("lib") { | 630 source_set("lib") { |
631 sources = [ | 631 sources = [ |
632 "hello_app.cc", | 632 "hello_app.cc", |
633 "hello_app.h", | 633 "hello_app.h", |
634 ] | 634 ] |
635 deps = [ | 635 deps = [ |
636 "//base", | 636 "//base", |
637 "//components/hello/public/interfaces", | 637 "//components/hello/public/interfaces", |
638 "//mojo/application/public/cpp", | |
639 "//mojo/environment:chromium", | 638 "//mojo/environment:chromium", |
| 639 "//mojo/shell/public/cpp", |
640 ] | 640 ] |
641 } | 641 } |
642 | 642 |
643 mojo_native_application("hello") { | 643 mojo_native_application("hello") { |
644 sources = [ | 644 sources = [ |
645 "main.cc", | 645 "main.cc", |
646 ], | 646 ], |
647 deps = [ ":lib" ] | 647 deps = [ ":lib" ] |
648 } | 648 } |
649 ``` | 649 ``` |
(...skipping 23 matching lines...) Expand all Loading... |
673 | 673 |
674 **components/hello/hello_apptest.cc** | 674 **components/hello/hello_apptest.cc** |
675 | 675 |
676 ```cpp | 676 ```cpp |
677 #include "base/bind.h" | 677 #include "base/bind.h" |
678 #include "base/callback.h" | 678 #include "base/callback.h" |
679 #include "base/logging.h" | 679 #include "base/logging.h" |
680 #include "base/macros.h" | 680 #include "base/macros.h" |
681 #include "base/run_loop.h" | 681 #include "base/run_loop.h" |
682 #include "components/hello/public/interfaces/greeter.mojom.h" | 682 #include "components/hello/public/interfaces/greeter.mojom.h" |
683 #include "mojo/application/public/cpp/application_impl.h" | 683 #include "mojo/shell/public/cpp/application_impl.h" |
684 #include "mojo/application/public/cpp/application_test_base.h" | 684 #include "mojo/shell/public/cpp/application_test_base.h" |
685 | 685 |
686 namespace hello { | 686 namespace hello { |
687 namespace { | 687 namespace { |
688 | 688 |
689 class HelloAppTest : public mojo::test::ApplicationTestBase { | 689 class HelloAppTest : public mojo::test::ApplicationTestBase { |
690 public: | 690 public: |
691 HelloAppTest() {} | 691 HelloAppTest() {} |
692 ~HelloAppTest() override {} | 692 ~HelloAppTest() override {} |
693 | 693 |
694 void SetUp() override { | 694 void SetUp() override { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
728 | 728 |
729 ``` | 729 ``` |
730 mojo_native_application("apptests") { | 730 mojo_native_application("apptests") { |
731 output_name = "hello_apptests" | 731 output_name = "hello_apptests" |
732 testonly = true | 732 testonly = true |
733 sources = [ | 733 sources = [ |
734 "hello_apptest.cc", | 734 "hello_apptest.cc", |
735 ] | 735 ] |
736 deps = [ | 736 deps = [ |
737 "//base", | 737 "//base", |
738 "//mojo/application/public/cpp:test_support", | 738 "//mojo/shell/public/cpp:test_support", |
739 ] | 739 ] |
740 public_deps = [ | 740 public_deps = [ |
741 "//components/hello/public/interfaces", | 741 "//components/hello/public/interfaces", |
742 ] | 742 ] |
743 data_deps = [ ":hello" ] | 743 data_deps = [ ":hello" ] |
744 } | 744 } |
745 ``` | 745 ``` |
746 | 746 |
747 Note that the `//components/hello:apptests` target does **not** have a binary | 747 Note that the `//components/hello:apptests` target does **not** have a binary |
748 dependency on either `HelloApp` or `GreeterImpl` implementations; instead it | 748 dependency on either `HelloApp` or `GreeterImpl` implementations; instead it |
(...skipping 28 matching lines...) Expand all Loading... |
777 Note that generated interface bindings include a constant string to identify | 777 Note that generated interface bindings include a constant string to identify |
778 each interface by name; so for example the generated `hello::Greeter` type | 778 each interface by name; so for example the generated `hello::Greeter` type |
779 defines a static C string: | 779 defines a static C string: |
780 | 780 |
781 const char hello::Greeter::Name_[] = "hello::Greeter"; | 781 const char hello::Greeter::Name_[] = "hello::Greeter"; |
782 | 782 |
783 This is exploited by the definition of | 783 This is exploited by the definition of |
784 `mojo::ApplicationConnection::ConnectToService<T>`, which uses `T::Name_` as the | 784 `mojo::ApplicationConnection::ConnectToService<T>`, which uses `T::Name_` as the |
785 name of the service to connect to. The type `T` in this context is inferred from | 785 name of the service to connect to. The type `T` in this context is inferred from |
786 the `InterfacePtr<T>*` argument. You can inspect the definition of | 786 the `InterfacePtr<T>*` argument. You can inspect the definition of |
787 `ConnectToService` in `/mojo/application/public/cpp/application_connection.h` | 787 `ConnectToService` in `/mojo/shell/public/cpp/application_connection.h` |
788 for additional clarity. | 788 for additional clarity. |
789 | 789 |
790 We could have instead written this code as: | 790 We could have instead written this code as: |
791 | 791 |
792 ```cpp | 792 ```cpp |
793 mojo::URLRequestPtr app_url = mojo::URLRequest::New(); | 793 mojo::URLRequestPtr app_url = mojo::URLRequest::New(); |
794 app_url->url = "mojo::hello"; | 794 app_url->url = "mojo::hello"; |
795 | 795 |
796 mojo::ServiceProviderPtr services; | 796 mojo::ServiceProviderPtr services; |
797 application_impl()->shell()->ConnectToApplication( | 797 application_impl()->shell()->ConnectToApplication( |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
977 | 977 |
978 This is still a work in progress and might not really take shape until the | 978 This is still a work in progress and might not really take shape until the |
979 Blink+Chromium merge. In the meantime there are some end-to-end WebUI examples | 979 Blink+Chromium merge. In the meantime there are some end-to-end WebUI examples |
980 in `/content/browser/webui/web_ui_mojo_browsertest.cc`. In particular, | 980 in `/content/browser/webui/web_ui_mojo_browsertest.cc`. In particular, |
981 `WebUIMojoTest.ConnectToApplication` connects from a WebUI frame to a test app | 981 `WebUIMojoTest.ConnectToApplication` connects from a WebUI frame to a test app |
982 running in a new utility process. | 982 running in a new utility process. |
983 | 983 |
984 ## FAQ | 984 ## FAQ |
985 | 985 |
986 Nothing here yet! | 986 Nothing here yet! |
OLD | NEW |