| 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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 | 147 |
| 148 `mojo::InterfacePtr<T>` is a typed proxy for a service of type `T`, which can be | 148 `mojo::InterfacePtr<T>` is a typed proxy for a service of type `T`, which can be |
| 149 bound to a message pipe endpoint. This class implements every interface method | 149 bound to a message pipe endpoint. This class implements every interface method |
| 150 on `T` by serializing a message (encoding the method call and its arguments) and | 150 on `T` by serializing a message (encoding the method call and its arguments) and |
| 151 writing it to the pipe (if bound.) This is the standard way for C++ code to talk | 151 writing it to the pipe (if bound.) This is the standard way for C++ code to talk |
| 152 to any Mojo service. | 152 to any Mojo service. |
| 153 | 153 |
| 154 For illustrative purposes only, we can create a message pipe and bind an | 154 For illustrative purposes only, we can create a message pipe and bind an |
| 155 `InterfacePtr` to one end as follows: | 155 `InterfacePtr` to one end as follows: |
| 156 | 156 |
| 157 ``` | 157 ```cpp |
| 158 mojo::MessagePipe pipe; | 158 mojo::MessagePipe pipe; |
| 159 mojo::InterfacePtr<frob::Frobinator> frobinator; | 159 mojo::InterfacePtr<frob::Frobinator> frobinator; |
| 160 frobinator.Bind( | 160 frobinator.Bind( |
| 161 mojo::InterfacePtrInfo<frob::Frobinator>(pipe.handle0.Pass(), 0u)); | 161 mojo::InterfacePtrInfo<frob::Frobinator>(pipe.handle0.Pass(), 0u)); |
| 162 ``` | 162 ``` |
| 163 | 163 |
| 164 You could then call `frobinator->Frobinate()` and read the encoded `Frobinate` | 164 You could then call `frobinator->Frobinate()` and read the encoded `Frobinate` |
| 165 message from the other side of the pipe (`handle1`.) You most likely don't want | 165 message from the other side of the pipe (`handle1`.) You most likely don't want |
| 166 to do this though, because as you'll soon see there's a nicer way to establish | 166 to do this though, because as you'll soon see there's a nicer way to establish |
| 167 service pipes. | 167 service pipes. |
| 168 | 168 |
| 169 #### `mojo::InterfaceRequest<T>` | 169 #### `mojo::InterfaceRequest<T>` |
| 170 | 170 |
| 171 Defined in `/third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h`. | 171 Defined in `/third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h`. |
| 172 | 172 |
| 173 `mojo::InterfaceRequest<T>` is a typed container for a message pipe endpoint | 173 `mojo::InterfaceRequest<T>` is a typed container for a message pipe endpoint |
| 174 that should _eventually_ be bound to a service implementation. An | 174 that should _eventually_ be bound to a service implementation. An |
| 175 `InterfaceRequest` doesn't actually _do_ anything, it's just a way of holding | 175 `InterfaceRequest` doesn't actually _do_ anything, it's just a way of holding |
| 176 onto an endpoint without losing interface type information. | 176 onto an endpoint without losing interface type information. |
| 177 | 177 |
| 178 A common usage pattern is to create a pipe, bind one end to an | 178 A common usage pattern is to create a pipe, bind one end to an |
| 179 `InterfacePtr<T>`, and pass the other end off to someone else (say, over some | 179 `InterfacePtr<T>`, and pass the other end off to someone else (say, over some |
| 180 other message pipe) who is expected to eventually bind it to a concrete service | 180 other message pipe) who is expected to eventually bind it to a concrete service |
| 181 implementation. `InterfaceRequest<T>` is here for that purpose and is, as we'll | 181 implementation. `InterfaceRequest<T>` is here for that purpose and is, as we'll |
| 182 see later, a first-class concept in Mojom interface definitions. | 182 see later, a first-class concept in Mojom interface definitions. |
| 183 | 183 |
| 184 As with `InterfacePtr<T>`, we can manually bind an `InterfaceRequest<T>` to a | 184 As with `InterfacePtr<T>`, we can manually bind an `InterfaceRequest<T>` to a |
| 185 pipe endpoint: | 185 pipe endpoint: |
| 186 | 186 |
| 187 ``` | 187 ```cpp |
| 188 mojo::MessagePipe pipe; | 188 mojo::MessagePipe pipe; |
| 189 | 189 |
| 190 mojo::InterfacePtr<frob::Frobinator> frobinator; | 190 mojo::InterfacePtr<frob::Frobinator> frobinator; |
| 191 frobinator.Bind( | 191 frobinator.Bind( |
| 192 mojo::InterfacePtrInfo<frob::Frobinator>(pipe.handle0.Pass(), 0u)); | 192 mojo::InterfacePtrInfo<frob::Frobinator>(pipe.handle0.Pass(), 0u)); |
| 193 | 193 |
| 194 mojo::InterfaceRequest<frob::Frobinator> frobinator_request; | 194 mojo::InterfaceRequest<frob::Frobinator> frobinator_request; |
| 195 frobinator_request.Bind(pipe.handle1.Pass()); | 195 frobinator_request.Bind(pipe.handle1.Pass()); |
| 196 ``` | 196 ``` |
| 197 | 197 |
| 198 At this point we could start making calls to `frobinator->Frobinate()` as | 198 At this point we could start making calls to `frobinator->Frobinate()` as |
| 199 before, but they'll just sit in queue waiting for the request side to be bound. | 199 before, but they'll just sit in queue waiting for the request side to be bound. |
| 200 Note that the basic logic in the snippet above is such a common pattern that | 200 Note that the basic logic in the snippet above is such a common pattern that |
| 201 there's a convenient API function which does it for us. | 201 there's a convenient API function which does it for us. |
| 202 | 202 |
| 203 #### `mojo::GetProxy<T>` | 203 #### `mojo::GetProxy<T>` |
| 204 | 204 |
| 205 Defined in | 205 Defined in |
| 206 `/third_party/mojo/src/mojo/public/cpp/bindings/interface`_request.h`. | 206 `/third_party/mojo/src/mojo/public/cpp/bindings/interface`_request.h`. |
| 207 | 207 |
| 208 `mojo::GetProxy<T>` is the function you will most commonly use to create a new | 208 `mojo::GetProxy<T>` is the function you will most commonly use to create a new |
| 209 message pipe. Its signature is as follows: | 209 message pipe. Its signature is as follows: |
| 210 | 210 |
| 211 ``` | 211 ```cpp |
| 212 template <typename T> | 212 template <typename T> |
| 213 mojo::InterfaceRequest<T> GetProxy(mojo::InterfacePtr<T>* ptr); | 213 mojo::InterfaceRequest<T> GetProxy(mojo::InterfacePtr<T>* ptr); |
| 214 ``` | 214 ``` |
| 215 | 215 |
| 216 This function creates a new message pipe, binds one end to the given | 216 This function creates a new message pipe, binds one end to the given |
| 217 `InterfacePtr` argument, and binds the other end to a new `InterfaceRequest` | 217 `InterfacePtr` argument, and binds the other end to a new `InterfaceRequest` |
| 218 which it then returns. Equivalent to the sample code just above is the following | 218 which it then returns. Equivalent to the sample code just above is the following |
| 219 snippet: | 219 snippet: |
| 220 | 220 |
| 221 ``` | 221 ```cpp |
| 222 mojo::InterfacePtr<frob::Frobinator> frobinator; | 222 mojo::InterfacePtr<frob::Frobinator> frobinator; |
| 223 mojo::InterfaceRequest<frob::Frobinator> frobinator_request = | 223 mojo::InterfaceRequest<frob::Frobinator> frobinator_request = |
| 224 mojo::GetProxy(&frobinator); | 224 mojo::GetProxy(&frobinator); |
| 225 ``` | 225 ``` |
| 226 | 226 |
| 227 #### `mojo::Binding<T>` | 227 #### `mojo::Binding<T>` |
| 228 | 228 |
| 229 Defined in `/third_party/mojo/src/mojo/public/cpp/bindings/binding.h`. | 229 Defined in `/third_party/mojo/src/mojo/public/cpp/bindings/binding.h`. |
| 230 | 230 |
| 231 Binds one end of a message pipe to an implementation of service `T`. A message | 231 Binds one end of a message pipe to an implementation of service `T`. A message |
| 232 sent from the other end of the pipe will be read and, if successfully decoded as | 232 sent from the other end of the pipe will be read and, if successfully decoded as |
| 233 a `T` message, will invoke the corresponding call on the bound `T` | 233 a `T` message, will invoke the corresponding call on the bound `T` |
| 234 implementation. A `Binding<T>` must be constructed over an instance of `T` | 234 implementation. A `Binding<T>` must be constructed over an instance of `T` |
| 235 (which itself usually owns said `Binding` object), and its bound pipe is usually | 235 (which itself usually owns said `Binding` object), and its bound pipe is usually |
| 236 taken from a passed `InterfaceRequest<T>`. | 236 taken from a passed `InterfaceRequest<T>`. |
| 237 | 237 |
| 238 A common usage pattern looks something like this: | 238 A common usage pattern looks something like this: |
| 239 | 239 |
| 240 ``` | 240 ```cpp |
| 241 #include "components/frob/public/interfaces/frobinator.mojom.h" | 241 #include "components/frob/public/interfaces/frobinator.mojom.h" |
| 242 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" | 242 #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" |
| 243 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" | 243 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" |
| 244 | 244 |
| 245 class FrobinatorImpl : public frob::Frobinator { | 245 class FrobinatorImpl : public frob::Frobinator { |
| 246 public: | 246 public: |
| 247 FrobinatorImpl(mojo::InterfaceRequest<frob::Frobinator> request) | 247 FrobinatorImpl(mojo::InterfaceRequest<frob::Frobinator> request) |
| 248 : binding_(this, request.Pass()) {} | 248 : binding_(this, request.Pass()) {} |
| 249 ~FrobinatorImpl() override {} | 249 ~FrobinatorImpl() override {} |
| 250 | 250 |
| 251 private: | 251 private: |
| 252 // frob::Frobinator: | 252 // frob::Frobinator: |
| 253 void Frobinate() override { /* ... */ } | 253 void Frobinate() override { /* ... */ } |
| 254 | 254 |
| 255 mojo::Binding<frob::Frobinator> binding_; | 255 mojo::Binding<frob::Frobinator> binding_; |
| 256 }; | 256 }; |
| 257 ``` | 257 ``` |
| 258 | 258 |
| 259 And then we could write some code to test this: | 259 And then we could write some code to test this: |
| 260 | 260 |
| 261 ``` | 261 ```cpp |
| 262 // Fun fact: The bindings generator emits a type alias like this for every | 262 // Fun fact: The bindings generator emits a type alias like this for every |
| 263 // interface type. frob::FrobinatorPtr is an InterfacePtr<frob::Frobinator>. | 263 // interface type. frob::FrobinatorPtr is an InterfacePtr<frob::Frobinator>. |
| 264 frob::FrobinatorPtr frobinator; | 264 frob::FrobinatorPtr frobinator; |
| 265 scoped_ptr<FrobinatorImpl> impl( | 265 scoped_ptr<FrobinatorImpl> impl( |
| 266 new FrobinatorImpl(mojo::GetProxy(&frobinator))); | 266 new FrobinatorImpl(mojo::GetProxy(&frobinator))); |
| 267 frobinator->Frobinate(); | 267 frobinator->Frobinate(); |
| 268 ``` | 268 ``` |
| 269 | 269 |
| 270 This will _eventually_ call `FrobinatorImpl::Frobinate()`. "Eventually," because | 270 This will _eventually_ call `FrobinatorImpl::Frobinate()`. "Eventually," because |
| 271 the sequence of events when `frobinator->Frobinate()` is called is roughly as | 271 the sequence of events when `frobinator->Frobinate()` is called is roughly as |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 foreseeable future we'll likely be treating `//components` as a sort of | 418 foreseeable future we'll likely be treating `//components` as a sort of |
| 419 top-level home for new Mojo apps in the Chromium tree. Any component application | 419 top-level home for new Mojo apps in the Chromium tree. Any component application |
| 420 you build should probably go there. Let's create some basic files to kick things | 420 you build should probably go there. Let's create some basic files to kick things |
| 421 off. You may want to start a new local Git branch to isolate any changes you | 421 off. You may want to start a new local Git branch to isolate any changes you |
| 422 make while working through this. | 422 make while working through this. |
| 423 | 423 |
| 424 First create a new `//components/hello` directory. Inside this directory we're | 424 First create a new `//components/hello` directory. Inside this directory we're |
| 425 going to add the following files: | 425 going to add the following files: |
| 426 | 426 |
| 427 **components/hello/main.cc** | 427 **components/hello/main.cc** |
| 428 ``` | 428 |
| 429 ```cpp |
| 429 #include "base/logging.h" | 430 #include "base/logging.h" |
| 430 #include "third_party/mojo/src/mojo/public/c/system/main.h" | 431 #include "third_party/mojo/src/mojo/public/c/system/main.h" |
| 431 | 432 |
| 432 MojoResult MojoMain(MojoHandle shell_handle) { | 433 MojoResult MojoMain(MojoHandle shell_handle) { |
| 433 LOG(ERROR) << "Hello, world!"; | 434 LOG(ERROR) << "Hello, world!"; |
| 434 return MOJO_RESULT_OK; | 435 return MOJO_RESULT_OK; |
| 435 }; | 436 }; |
| 436 ``` | 437 ``` |
| 437 | 438 |
| 438 **components/hello/BUILD.gn** | 439 **components/hello/BUILD.gn** |
| 440 |
| 439 ``` | 441 ``` |
| 440 import("//mojo/public/mojo_application.gni") | 442 import("//mojo/public/mojo_application.gni") |
| 441 | 443 |
| 442 mojo_native_application("hello") { | 444 mojo_native_application("hello") { |
| 443 sources = [ | 445 sources = [ |
| 444 "main.cc", | 446 "main.cc", |
| 445 ] | 447 ] |
| 446 deps = [ | 448 deps = [ |
| 447 "//base", | 449 "//base", |
| 448 "//mojo/environment:chromium", | 450 "//mojo/environment:chromium", |
| (...skipping 28 matching lines...) Expand all Loading... |
| 477 | 479 |
| 478 ### Exposing Services | 480 ### Exposing Services |
| 479 | 481 |
| 480 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 |
| 481 minimum your app should implement `mojo::ApplicationDelegate` and expose at | 483 minimum your app should implement `mojo::ApplicationDelegate` and expose at |
| 482 least one service to connecting applications. | 484 least one service to connecting applications. |
| 483 | 485 |
| 484 Let's update `main.cc` with the following contents: | 486 Let's update `main.cc` with the following contents: |
| 485 | 487 |
| 486 **components/hello/main.cc** | 488 **components/hello/main.cc** |
| 487 ``` | 489 |
| 490 ```cpp |
| 488 #include "components/hello/hello_app.h" | 491 #include "components/hello/hello_app.h" |
| 489 #include "mojo/application/public/cpp/application_runner.h" | 492 #include "mojo/application/public/cpp/application_runner.h" |
| 490 #include "third_party/mojo/src/mojo/public/c/system/main.h" | 493 #include "third_party/mojo/src/mojo/public/c/system/main.h" |
| 491 | 494 |
| 492 MojoResult MojoMain(MojoHandle shell_handle) { | 495 MojoResult MojoMain(MojoHandle shell_handle) { |
| 493 mojo::ApplicationRunner runner(new hello::HelloApp); | 496 mojo::ApplicationRunner runner(new hello::HelloApp); |
| 494 return runner.Run(shell_handle); | 497 return runner.Run(shell_handle); |
| 495 }; | 498 }; |
| 496 ``` | 499 ``` |
| 497 | 500 |
| 498 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 |
| 499 want -- a `mojo::ApplicationRunner` constructed over a | 502 want -- a `mojo::ApplicationRunner` constructed over a |
| 500 `mojo::ApplicationDelegate` instance, `Run()` with the pipe handle received from | 503 `mojo::ApplicationDelegate` instance, `Run()` with the pipe handle received from |
| 501 the shell. We'll add some new files to the app as well: | 504 the shell. We'll add some new files to the app as well: |
| 502 | 505 |
| 503 **components/hello/public/interfaces/greeter.mojom** | 506 **components/hello/public/interfaces/greeter.mojom** |
| 507 |
| 504 ``` | 508 ``` |
| 505 module hello; | 509 module hello; |
| 506 interface Greeter { | 510 interface Greeter { |
| 507 Greet(string name) => (string greeting); | 511 Greet(string name) => (string greeting); |
| 508 }; | 512 }; |
| 509 ``` | 513 ``` |
| 510 | 514 |
| 511 Note the new arrow syntax on the `Greet` method. This indicates that the caller | 515 Note the new arrow syntax on the `Greet` method. This indicates that the caller |
| 512 expects a response from the service. | 516 expects a response from the service. |
| 513 | 517 |
| 514 **components/hello/public/interfaces/BUILD.gn** | 518 **components/hello/public/interfaces/BUILD.gn** |
| 519 |
| 515 ``` | 520 ``` |
| 516 import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") | 521 import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") |
| 517 | 522 |
| 518 mojom("interfaces") { | 523 mojom("interfaces") { |
| 519 sources = [ | 524 sources = [ |
| 520 "greeter.mojom", | 525 "greeter.mojom", |
| 521 ] | 526 ] |
| 522 } | 527 } |
| 523 ``` | 528 ``` |
| 524 | 529 |
| 525 **components/hello/hello_app.h** | 530 **components/hello/hello_app.h** |
| 526 ``` | 531 |
| 532 ```cpp |
| 527 #ifndef COMPONENTS_HELLO_HELLO_APP_H_ | 533 #ifndef COMPONENTS_HELLO_HELLO_APP_H_ |
| 528 #define COMPONENTS_HELLO_HELLO_APP_H_ | 534 #define COMPONENTS_HELLO_HELLO_APP_H_ |
| 529 | 535 |
| 530 #include "base/macros.h" | 536 #include "base/macros.h" |
| 531 #include "components/hello/public/interfaces/greeter.mojom.h" | 537 #include "components/hello/public/interfaces/greeter.mojom.h" |
| 532 #include "mojo/application/public/cpp/application_delegate.h" | 538 #include "mojo/application/public/cpp/application_delegate.h" |
| 533 #include "mojo/application/public/cpp/interface_factory.h" | 539 #include "mojo/application/public/cpp/interface_factory.h" |
| 534 | 540 |
| 535 namespace hello { | 541 namespace hello { |
| 536 | 542 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 552 DISALLOW_COPY_AND_ASSIGN(HelloApp); | 558 DISALLOW_COPY_AND_ASSIGN(HelloApp); |
| 553 }; | 559 }; |
| 554 | 560 |
| 555 } // namespace hello | 561 } // namespace hello |
| 556 | 562 |
| 557 #endif // COMPONENTS_HELLO_HELLO_APP_H_ | 563 #endif // COMPONENTS_HELLO_HELLO_APP_H_ |
| 558 ``` | 564 ``` |
| 559 | 565 |
| 560 | 566 |
| 561 **components/hello/hello_app.cc** | 567 **components/hello/hello_app.cc** |
| 562 ``` | 568 |
| 569 ```cpp |
| 563 #include "base/macros.h" | 570 #include "base/macros.h" |
| 564 #include "components/hello/hello_app.h" | 571 #include "components/hello/hello_app.h" |
| 565 #include "mojo/application/public/cpp/application_connection.h" | 572 #include "mojo/application/public/cpp/application_connection.h" |
| 566 #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" |
| 567 #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" |
| 568 | 575 |
| 569 namespace hello { | 576 namespace hello { |
| 570 | 577 |
| 571 namespace { | 578 namespace { |
| 572 | 579 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 new GreeterImpl(request.Pass()); | 616 new GreeterImpl(request.Pass()); |
| 610 } | 617 } |
| 611 | 618 |
| 612 } // namespace hello | 619 } // namespace hello |
| 613 ``` | 620 ``` |
| 614 | 621 |
| 615 And finally we need to update our app's `BUILD.gn` to add some new sources and | 622 And finally we need to update our app's `BUILD.gn` to add some new sources and |
| 616 dependencies: | 623 dependencies: |
| 617 | 624 |
| 618 **components/hello/BUILD.gn** | 625 **components/hello/BUILD.gn** |
| 626 |
| 619 ``` | 627 ``` |
| 620 import("//mojo/public/mojo_application.gni") | 628 import("//mojo/public/mojo_application.gni") |
| 621 | 629 |
| 622 source_set("lib") { | 630 source_set("lib") { |
| 623 sources = [ | 631 sources = [ |
| 624 "hello_app.cc", | 632 "hello_app.cc", |
| 625 "hello_app.h", | 633 "hello_app.h", |
| 626 ] | 634 ] |
| 627 deps = [ | 635 deps = [ |
| 628 "//base", | 636 "//base", |
| (...skipping 28 matching lines...) Expand all Loading... |
| 657 test! | 665 test! |
| 658 | 666 |
| 659 ### App Tests | 667 ### App Tests |
| 660 | 668 |
| 661 App tests run inside a test application, giving test code access to a shell | 669 App tests run inside a test application, giving test code access to a shell |
| 662 which can connect to one or more applications-under-test. | 670 which can connect to one or more applications-under-test. |
| 663 | 671 |
| 664 First let's introduce some test code: | 672 First let's introduce some test code: |
| 665 | 673 |
| 666 **components/hello/hello_apptest.cc** | 674 **components/hello/hello_apptest.cc** |
| 667 ``` | 675 |
| 676 ```cpp |
| 668 #include "base/bind.h" | 677 #include "base/bind.h" |
| 669 #include "base/callback.h" | 678 #include "base/callback.h" |
| 670 #include "base/logging.h" | 679 #include "base/logging.h" |
| 671 #include "base/macros.h" | 680 #include "base/macros.h" |
| 672 #include "base/run_loop.h" | 681 #include "base/run_loop.h" |
| 673 #include "components/hello/public/interfaces/greeter.mojom.h" | 682 #include "components/hello/public/interfaces/greeter.mojom.h" |
| 674 #include "mojo/application/public/cpp/application_impl.h" | 683 #include "mojo/application/public/cpp/application_impl.h" |
| 675 #include "mojo/application/public/cpp/application_test_base.h" | 684 #include "mojo/application/public/cpp/application_test_base.h" |
| 676 | 685 |
| 677 namespace hello { | 686 namespace hello { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 773 | 782 |
| 774 This is exploited by the definition of | 783 This is exploited by the definition of |
| 775 `mojo::ApplicationConnection::ConnectToService<T>`, which uses `T::Name_` as the | 784 `mojo::ApplicationConnection::ConnectToService<T>`, which uses `T::Name_` as the |
| 776 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 |
| 777 the `InterfacePtr<T>*` argument. You can inspect the definition of | 786 the `InterfacePtr<T>*` argument. You can inspect the definition of |
| 778 `ConnectToService` in `/mojo/application/public/cpp/application_connection.h` | 787 `ConnectToService` in `/mojo/application/public/cpp/application_connection.h` |
| 779 for additional clarity. | 788 for additional clarity. |
| 780 | 789 |
| 781 We could have instead written this code as: | 790 We could have instead written this code as: |
| 782 | 791 |
| 783 ``` | 792 ```cpp |
| 784 mojo::URLRequestPtr app_url = mojo::URLRequest::New(); | 793 mojo::URLRequestPtr app_url = mojo::URLRequest::New(); |
| 785 app_url->url = "mojo::hello"; | 794 app_url->url = "mojo::hello"; |
| 786 | 795 |
| 787 mojo::ServiceProviderPtr services; | 796 mojo::ServiceProviderPtr services; |
| 788 application_impl()->shell()->ConnectToApplication( | 797 application_impl()->shell()->ConnectToApplication( |
| 789 app_url.Pass(), mojo::GetProxy(&services), | 798 app_url.Pass(), mojo::GetProxy(&services), |
| 790 // We pass a null provider since we aren't exposing any of our own | 799 // We pass a null provider since we aren't exposing any of our own |
| 791 // services to the target app. | 800 // services to the target app. |
| 792 mojo::ServiceProviderPtr()); | 801 mojo::ServiceProviderPtr()); |
| 793 | 802 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 828 Applications can be set up to run within the browser process via | 837 Applications can be set up to run within the browser process via |
| 829 `ContentBrowserClient::RegisterInProcessMojoApplications`. This method populates | 838 `ContentBrowserClient::RegisterInProcessMojoApplications`. This method populates |
| 830 a mapping from URL to `base::Callback<scoped_ptr<mojo::ApplicationDelegate>()>` | 839 a mapping from URL to `base::Callback<scoped_ptr<mojo::ApplicationDelegate>()>` |
| 831 (_i.e._, a factory function which creates a new `mojo::ApplicationDelegate` | 840 (_i.e._, a factory function which creates a new `mojo::ApplicationDelegate` |
| 832 instance), so registering a new app means adding an entry to this map. | 841 instance), so registering a new app means adding an entry to this map. |
| 833 | 842 |
| 834 Let's modify `ChromeContentBrowserClient::RegisterInProcessMojoApplications` | 843 Let's modify `ChromeContentBrowserClient::RegisterInProcessMojoApplications` |
| 835 (in `//chrome/browser/chrome_content_browser_client.cc`) by adding the following | 844 (in `//chrome/browser/chrome_content_browser_client.cc`) by adding the following |
| 836 code: | 845 code: |
| 837 | 846 |
| 838 apps->insert(std::make_pair(GURL("mojo:hello"), | 847 ```cpp |
| 839 base::Bind(&HelloApp::CreateApp))); | 848 apps->insert(std::make_pair(GURL("mojo:hello"), |
| 849 base::Bind(&HelloApp::CreateApp))); |
| 850 ``` |
| 840 | 851 |
| 841 you'll also want to add the following convenience method to your `HelloApp` | 852 you'll also want to add the following convenience method to your `HelloApp` |
| 842 definition in `//components/hello/hello_app.h`: | 853 definition in `//components/hello/hello_app.h`: |
| 843 | 854 |
| 844 static scoped_ptr<mojo::ApplicationDelegate> HelloApp::CreateApp() { | 855 ```cpp |
| 845 return scoped_ptr<mojo::ApplicationDelegate>(new HelloApp); | 856 static scoped_ptr<mojo::ApplicationDelegate> HelloApp::CreateApp() { |
| 846 } | 857 return scoped_ptr<mojo::ApplicationDelegate>(new HelloApp); |
| 858 } |
| 859 ``` |
| 847 | 860 |
| 848 This introduces a dependency from `//chrome/browser` on to | 861 This introduces a dependency from `//chrome/browser` on to |
| 849 `//components/hello:lib`, which you can add to the `"browser"` target's deps in | 862 `//components/hello:lib`, which you can add to the `"browser"` target's deps in |
| 850 `//chrome/browser/BUILD.gn`. You'll of course also need to include | 863 `//chrome/browser/BUILD.gn`. You'll of course also need to include |
| 851 `"components/hello/hello_app.h"` in `chrome_content_browser_client.cc`. | 864 `"components/hello/hello_app.h"` in `chrome_content_browser_client.cc`. |
| 852 | 865 |
| 853 That's it! Now if an app comes to the shell asking to connect to `"mojo:hello"` | 866 That's it! Now if an app comes to the shell asking to connect to `"mojo:hello"` |
| 854 and app is already running, it'll get connected to our `HelloApp` and have | 867 and app is already running, it'll get connected to our `HelloApp` and have |
| 855 access to the `Greeter` service. If the app wasn't already running, it will | 868 access to the `Greeter` service. If the app wasn't already running, it will |
| 856 first be launched on a new thread. | 869 first be launched on a new thread. |
| 857 | 870 |
| 858 ### Connecting From the Browser | 871 ### Connecting From the Browser |
| 859 | 872 |
| 860 We've already seen how apps can connect to each other using their own private | 873 We've already seen how apps can connect to each other using their own private |
| 861 shell proxy, but the vast majority of Chromium code doesn't yet belong to a Mojo | 874 shell proxy, but the vast majority of Chromium code doesn't yet belong to a Mojo |
| 862 application. So how do we use an app's services from arbitrary browser code? We | 875 application. So how do we use an app's services from arbitrary browser code? We |
| 863 use `content::MojoAppConnection`, like this: | 876 use `content::MojoAppConnection`, like this: |
| 864 | 877 |
| 865 ``` | 878 ```cpp |
| 866 #include "base/bind.h" | 879 #include "base/bind.h" |
| 867 #include "base/logging.h" | 880 #include "base/logging.h" |
| 868 #include "components/hello/public/interfaces/greeter.mojom.h" | 881 #include "components/hello/public/interfaces/greeter.mojom.h" |
| 869 #include "content/public/browser/mojo_app_connection.h" | 882 #include "content/public/browser/mojo_app_connection.h" |
| 870 | 883 |
| 871 void LogGreeting(const mojo::String& greeting) { | 884 void LogGreeting(const mojo::String& greeting) { |
| 872 LOG(INFO) << greeting; | 885 LOG(INFO) << greeting; |
| 873 } | 886 } |
| 874 | 887 |
| 875 void GreetTheWorld() { | 888 void GreetTheWorld() { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 923 run out-of-process and unsandboxed (which you **probably do not**), you can | 936 run out-of-process and unsandboxed (which you **probably do not**), you can |
| 924 register its URL via | 937 register its URL via |
| 925 `ContentBrowserClient::RegisterUnsandboxedOutOfProcessMojoApplications`. | 938 `ContentBrowserClient::RegisterUnsandboxedOutOfProcessMojoApplications`. |
| 926 | 939 |
| 927 ## Connecting From `RenderFrame` | 940 ## Connecting From `RenderFrame` |
| 928 | 941 |
| 929 We can also connect to Mojo apps from a `RenderFrame`. This is made possible by | 942 We can also connect to Mojo apps from a `RenderFrame`. This is made possible by |
| 930 `RenderFrame`'s `GetServiceRegistry()` interface. The `ServiceRegistry` can be | 943 `RenderFrame`'s `GetServiceRegistry()` interface. The `ServiceRegistry` can be |
| 931 used to acquire a shell proxy and in turn connect to an app like so: | 944 used to acquire a shell proxy and in turn connect to an app like so: |
| 932 | 945 |
| 933 ``` | 946 ```cpp |
| 934 void GreetWorld(content::RenderFrame* frame) { | 947 void GreetWorld(content::RenderFrame* frame) { |
| 935 mojo::ShellPtr shell; | 948 mojo::ShellPtr shell; |
| 936 frame->GetServiceRegistry()->ConnectToRemoteService( | 949 frame->GetServiceRegistry()->ConnectToRemoteService( |
| 937 mojo::GetProxy(&shell)); | 950 mojo::GetProxy(&shell)); |
| 938 | 951 |
| 939 mojo::URLRequestPtr request = mojo::URLRequest::New(); | 952 mojo::URLRequestPtr request = mojo::URLRequest::New(); |
| 940 request->url = "mojo:hello"; | 953 request->url = "mojo:hello"; |
| 941 | 954 |
| 942 mojo::ServiceProviderPtr hello_services; | 955 mojo::ServiceProviderPtr hello_services; |
| 943 shell->ConnectToApplication( | 956 shell->ConnectToApplication( |
| (...skipping 20 matching lines...) Expand all Loading... |
| 964 | 977 |
| 965 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 |
| 966 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 |
| 967 in `/content/browser/webui/web_ui_mojo_browsertest.cc`. In particular, | 980 in `/content/browser/webui/web_ui_mojo_browsertest.cc`. In particular, |
| 968 `WebUIMojoTest.ConnectToApplication` connects from a WebUI frame to a test app | 981 `WebUIMojoTest.ConnectToApplication` connects from a WebUI frame to a test app |
| 969 running in a new utility process. | 982 running in a new utility process. |
| 970 | 983 |
| 971 ## FAQ | 984 ## FAQ |
| 972 | 985 |
| 973 Nothing here yet! | 986 Nothing here yet! |
| OLD | NEW |