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 |