Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(948)

Side by Side Diff: services/service_manager/README.md

Issue 2420253002: Rename shell namespace to service_manager (Closed)
Patch Set: . Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Service Manager User Guide 1 # Service Manager User Guide
2 2
3 ## What is the Service Manager? 3 ## What is the Service Manager?
4 4
5 The Service Manager is a tool that brokers connections and capabilities between 5 The Service Manager is a tool that brokers connections and capabilities between
6 and manages instances of components, referred to henceforth as “services”. 6 and manages instances of components, referred to henceforth as “services”.
7 7
8 The Service Manager performs the following functions: 8 The Service Manager performs the following functions:
9 9
10 * Brokering connections between services, including communicating policies such 10 * Brokering connections between services, including communicating policies such
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 has its own unique Identity. From the Service Manager’s perspective, a service’s 54 has its own unique Identity. From the Service Manager’s perspective, a service’s
55 Identity is represented by the tuple of the its Name, UserId and Instance Name. 55 Identity is represented by the tuple of the its Name, UserId and Instance Name.
56 The Name is a formatted string that superficially represents a scheme:host pair, 56 The Name is a formatted string that superficially represents a scheme:host pair,
57 but actually isn’t a URL. More on the structure of these names later. The UserId 57 but actually isn’t a URL. More on the structure of these names later. The UserId
58 is a string GUID, representing the user the service is run as. The Instance Name 58 is a string GUID, representing the user the service is run as. The Instance Name
59 is a string, typically (but not necessarily) derived from the Name, which can be 59 is a string, typically (but not necessarily) derived from the Name, which can be
60 used to allow multiple instances of a service to exist for the same Name,UserId 60 used to allow multiple instances of a service to exist for the same Name,UserId
61 pair. In Chrome an example of this would be multiple instances of the renderer 61 pair. In Chrome an example of this would be multiple instances of the renderer
62 or the same profile. 62 or the same profile.
63 63
64 A Service implements the Mojo interface shell.mojom.Service, which is the 64 A Service implements the Mojo interface service_manager.mojom.Service, which is the
65 primary means the Service Manager has of communicating with its service. Service 65 primary means the Service Manager has of communicating with its service. Service
66 has two methods: OnStart(), called once at when the Service Manager first learns 66 has two methods: OnStart(), called once at when the Service Manager first learns
67 about the service, and OnConnect(), which the Service Manager calls every time 67 about the service, and OnConnect(), which the Service Manager calls every time
68 some other service tries to connect to this one. 68 some other service tries to connect to this one.
69 69
70 Services have a link back to the Service Manager too, primarily in the form of 70 Services have a link back to the Service Manager too, primarily in the form of
71 the shell.mojom.Connector interface. The Connector allows services to open 71 the service_manager.mojom.Connector interface. The Connector allows services to open
72 connections to other services. 72 connections to other services.
73 73
74 A unique connection from the Service Manager to a service is called an 74 A unique connection from the Service Manager to a service is called an
75 “instance,” each with its own unique identifier, called an instance id. Every 75 “instance,” each with its own unique identifier, called an instance id. Every
76 instance has a unique Identity. It is possible to locate an existing instance 76 instance has a unique Identity. It is possible to locate an existing instance
77 purely using its Identity. 77 purely using its Identity.
78 78
79 Services define their own lifetimes. Services in processes started by other 79 Services define their own lifetimes. Services in processes started by other
80 services (rather than the Service Manager) may even outlive the connection with 80 services (rather than the Service Manager) may even outlive the connection with
81 the Service Manager. For processes launched by the Service Manager, when a 81 the Service Manager. For processes launched by the Service Manager, when a
82 service wishes to terminate it closes the Service pipe with the Service Manager 82 service wishes to terminate it closes the Service pipe with the Service Manager
83 and the Service Manager destroys its corresponding instance and asks the process 83 and the Service Manager destroys its corresponding instance and asks the process
84 to exit. 84 to exit.
85 85
86 #### A simple Service example 86 #### A simple Service example
87 87
88 Consider this simple application that implements the Service interface: 88 Consider this simple application that implements the Service interface:
89 89
90 **app.cc:** 90 **app.cc:**
91 91
92 #include “"mojo/public/c/system/main.h”" 92 #include “"mojo/public/c/system/main.h”"
93 #include “"services/service_manager/public/cpp/application_runner.h”" 93 #include “"services/service_manager/public/cpp/application_runner.h”"
94 #include “"services/service_manager/public/cpp/connector.h”" 94 #include “"services/service_manager/public/cpp/connector.h”"
95 #include “"services/service_manager/public/cpp/connection.h”" 95 #include “"services/service_manager/public/cpp/connection.h”"
96 #include “"services/service_manager/public/cpp/identity.h”" 96 #include “"services/service_manager/public/cpp/identity.h”"
97 #include “"services/service_manager/public/cpp/service.h”" 97 #include “"services/service_manager/public/cpp/service.h”"
98 98
99 class Service : public shell::Service { 99 class Service : public service_manager::Service {
100 public: 100 public:
101 Service() {} 101 Service() {}
102 ~Service() override {} 102 ~Service() override {}
103 103
104 // Overridden from shell::Service: 104 // Overridden from service_manager::Service:
105 void OnStart(const shell::Identity& identity) override { 105 void OnStart(const service_manager::Identity& identity) override {
106 } 106 }
107 bool OnConnect(shell::Connection* connection) override { 107 bool OnConnect(service_manager::Connection* connection) override {
108 return true; 108 return true;
109 } 109 }
110 }; 110 };
111 111
112 MojoResult ServiceMain(MojoHandle service_request_handle) { 112 MojoResult ServiceMain(MojoHandle service_request_handle) {
113 return shell::ServiceRunner(new Service).Run(service_request_handle); 113 return service_manager::ServiceRunner(new Service).Run(service_request_han dle);
114 } 114 }
115 115
116 app_manifest.json: 116 app_manifest.json:
117 117
118 { 118 {
119 "“manifest_version"”: 1, 119 "“manifest_version"”: 1,
120 "“name"”: "“mojo:app”", 120 "“name"”: "“mojo:app”",
121 "“display_name"”: “"Example App”", 121 "“display_name"”: “"Example App”",
122 "“capabilities"”: {} 122 "“capabilities"”: {}
123 } 123 }
124 124
125 **BUILD.gn:** 125 **BUILD.gn:**
126 126
127 import(“"//mojo/public/mojo_application.gni”") 127 import(“"//mojo/public/mojo_application.gni”")
128 128
129 service(“"app"”) { 129 service(“"app"”) {
130 sources = [ "“app.cc"” ] 130 sources = [ "“app.cc"” ]
131 deps = [ "“//base"”, "“//mojo/shell/public/cpp”" ] 131 deps = [ "“//base"”, "“//services/service_manager/public/cpp”" ]
132 data_deps = [ “":manifest"” ] 132 data_deps = [ “":manifest"” ]
133 } 133 }
134 134
135 service_manifest(“"manifest"”) { 135 service_manifest(“"manifest"”) {
136 name = "“app"” 136 name = "“app"”
137 source = “"app_manifest.json”" 137 source = “"app_manifest.json”"
138 } 138 }
139 139
140 What does all this do? Building the app target produces two files in the output 140 What does all this do? Building the app target produces two files in the output
141 directory: app/app.library and app/manifest.json. app.library is a DSO loaded by 141 directory: app/app.library and app/manifest.json. app.library is a DSO loaded by
142 the Service Manager in its own process when another service connects to the 142 the Service Manager in its own process when another service connects to the
143 “mojo:app” name. This is not the only way (nor even the most likely one) you can 143 “mojo:app” name. This is not the only way (nor even the most likely one) you can
144 implement a Service, but it’s the simplest and easiest to reason about. 144 implement a Service, but it’s the simplest and easiest to reason about.
145 145
146 This service doesn’t do much. Its implementation of OnStart() is empty, and its 146 This service doesn’t do much. Its implementation of OnStart() is empty, and its
147 implementation of OnConnect just returns true to allow the inbound connection to 147 implementation of OnConnect just returns true to allow the inbound connection to
148 complete. Let’s study the parameters to these methods though, since they’ll be 148 complete. Let’s study the parameters to these methods though, since they’ll be
149 important as we begin to do more in our service. 149 important as we begin to do more in our service.
150 150
151 ##### OnStart Parameters 151 ##### OnStart Parameters
152 152
153 ###### const shell::Identity& identity 153 ###### const service_manager::Identity& identity
154 This is the identity this service is known to the Service Manager as. It 154 This is the identity this service is known to the Service Manager as. It
155 includes the service’s Name, User ID and Instance Name. 155 includes the service’s Name, User ID and Instance Name.
156 156
157 ##### OnConnect Parameters 157 ##### OnConnect Parameters
158 158
159 ###### shell::Connection* connection 159 ###### service_manager::Connection* connection
160 This is a pointer to an object that encapsulates the connection with a remote 160 This is a pointer to an object that encapsulates the connection with a remote
161 service. The service uses this object to learn about the service at the remote 161 service. The service uses this object to learn about the service at the remote
162 end, to bind interfaces from it, and to expose interfaces to it. The 162 end, to bind interfaces from it, and to expose interfaces to it. The
163 “Connection” concept is implemented under the hood by a pair of 163 “Connection” concept is implemented under the hood by a pair of
164 shell.mojom.InterfaceProviders - this is the physical link between the service 164 service_manager.mojom.InterfaceProviders - this is the physical link between the service
165 that give the Connection its utility. The Connection object is owned by the 165 that give the Connection its utility. The Connection object is owned by the
166 caller of OnConnect, and will outlive the underlying pipes. 166 caller of OnConnect, and will outlive the underlying pipes.
167 167
168 The service can decide to block the connection outright by returning false from 168 The service can decide to block the connection outright by returning false from
169 this method. In that scenario the underlying pipes will be closed and the remote 169 this method. In that scenario the underlying pipes will be closed and the remote
170 end will see an error and have the chance to recover. 170 end will see an error and have the chance to recover.
171 171
172 Before we add any functionality to our service, such as exposing an interface, 172 Before we add any functionality to our service, such as exposing an interface,
173 we should look at how we connect to another service and bind an interface from 173 we should look at how we connect to another service and bind an interface from
174 it. This will lay the groundwork to understanding how to export an interface. 174 it. This will lay the groundwork to understanding how to export an interface.
175 175
176 ### Connecting 176 ### Connecting
177 177
178 Once we have a Connector, we can connect to other services and bind interfaces 178 Once we have a Connector, we can connect to other services and bind interfaces
179 from them. In the trivial app above we can do this directly in OnStart: 179 from them. In the trivial app above we can do this directly in OnStart:
180 180
181 void OnStart(const shell::Identity& identity) override { 181 void OnStart(const service_manager::Identity& identity) override {
182 scoped_ptr<shell::Connection> connection = 182 scoped_ptr<service_manager::Connection> connection =
183 connector()->Connect(“"mojo:service"”); 183 connector()->Connect(“"mojo:service"”);
184 mojom::SomeInterfacePtr some_interface; 184 mojom::SomeInterfacePtr some_interface;
185 connection->GetInterface(&some_interface); 185 connection->GetInterface(&some_interface);
186 some_interface->Foo(); 186 some_interface->Foo();
187 } 187 }
188 188
189 This assumes an interface called “mojo.SomeInterface” with a method “Foo()” 189 This assumes an interface called “mojo.SomeInterface” with a method “Foo()”
190 exported by another Mojo client identified by the name “mojo:service”. 190 exported by another Mojo client identified by the name “mojo:service”.
191 191
192 What is happening here? Let’s look line-by-line 192 What is happening here? Let’s look line-by-line
193 193
194 194
195 scoped_ptr<shell::Connection> connection = 195 scoped_ptr<service_manager::Connection> connection =
196 connector->Connect("“mojo:service”"); 196 connector->Connect("“mojo:service”");
197 197
198 This asks the Service Manager to open a connection to the service named 198 This asks the Service Manager to open a connection to the service named
199 “mojo:service”. The Connect() method returns a Connection object similar to the 199 “mojo:service”. The Connect() method returns a Connection object similar to the
200 one received by OnConnect() - in fact this Connection object binds the other 200 one received by OnConnect() - in fact this Connection object binds the other
201 ends of the pipes of the Connection object received by OnConnect in the remote 201 ends of the pipes of the Connection object received by OnConnect in the remote
202 service. This time, the caller of Connect() takes ownership of the Connection, 202 service. This time, the caller of Connect() takes ownership of the Connection,
203 and when it is destroyed the connection (and the underlying pipes) is closed. A 203 and when it is destroyed the connection (and the underlying pipes) is closed. A
204 note on this later. 204 note on this later.
205 205
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 `//mojo/public/tools/bindings/mojom.gni`. Once we do that and look at the 247 `//mojo/public/tools/bindings/mojom.gni`. Once we do that and look at the
248 output, we can see that the C++ class mojom::SomeInterface is generated and can 248 output, we can see that the C++ class mojom::SomeInterface is generated and can
249 be #included from the same path as the .mojom file at some_interface.mojom.h. 249 be #included from the same path as the .mojom file at some_interface.mojom.h.
250 In our implementation of the mojo:service client, we’ll need to derive from this 250 In our implementation of the mojo:service client, we’ll need to derive from this
251 class to implement the interface. But that’s not enough. We’ll also have to find 251 class to implement the interface. But that’s not enough. We’ll also have to find
252 a way to bind inbound requests to bind this interface to the object that 252 a way to bind inbound requests to bind this interface to the object that
253 implements it. Let’s look at a snippet of a class that does all of this: 253 implements it. Let’s look at a snippet of a class that does all of this:
254 254
255 **service.cc:** 255 **service.cc:**
256 256
257 class Service : public shell::Service, 257 class Service : public service_manager::Service,
258 public shell::InterfaceFactory<mojom::SomeInterface>, 258 public service_manager::InterfaceFactory<mojom::SomeInterfac e>,
259 public mojom::SomeInterface { 259 public mojom::SomeInterface {
260 public: 260 public:
261 .. 261 ..
262 262
263 // Overridden from shell::Service: 263 // Overridden from service_manager::Service:
264 bool OnConnect(shell::Connection* connection) override { 264 bool OnConnect(service_manager::Connection* connection) override {
265 connection->AddInterface<mojom::SomeInterface>(this); 265 connection->AddInterface<mojom::SomeInterface>(this);
266 return true; 266 return true;
267 } 267 }
268 268
269 // Overridden from shell::InterfaceFactory<mojom::SomeInterface>: 269 // Overridden from service_manager::InterfaceFactory<mojom::SomeInterface> :
270 void Create(shell::Connection* connection, 270 void Create(service_manager::Connection* connection,
271 mojom::SomeInterfaceRequest request) override { 271 mojom::SomeInterfaceRequest request) override {
272 bindings_.AddBinding(this, std::move(request)); 272 bindings_.AddBinding(this, std::move(request));
273 } 273 }
274 274
275 // Overridden from mojom::SomeInterface: 275 // Overridden from mojom::SomeInterface:
276 void Foo() override { /* .. */ } 276 void Foo() override { /* .. */ }
277 277
278 mojo::BindingSet<mojom::SomeInterface> bindings_; 278 mojo::BindingSet<mojom::SomeInterface> bindings_;
279 }; 279 };
280 280
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 403
404 (Note that we didn’t write a manifest for mojo:service. We’d need to do that 404 (Note that we didn’t write a manifest for mojo:service. We’d need to do that
405 too, though for this example we wouldn’t have to describe mojom.SomeInterface in 405 too, though for this example we wouldn’t have to describe mojom.SomeInterface in
406 the provided section of its capability spec, since it wasn’t part of a class. 406 the provided section of its capability spec, since it wasn’t part of a class.
407 Connecting services like mojo:app just need to state that interface.) 407 Connecting services like mojo:app just need to state that interface.)
408 408
409 ### Testing 409 ### Testing
410 410
411 Now that we’ve built a simple application and service, it’s time to write a test 411 Now that we’ve built a simple application and service, it’s time to write a test
412 for them. The Shell client library provides a gtest base class 412 for them. The Shell client library provides a gtest base class
413 **shell::test::ServiceTest** that makes writing integration tests of services 413 **service_manager::test::ServiceTest** that makes writing integration tests of s ervices
414 straightforward. Let’s look at a simple test of our service: 414 straightforward. Let’s look at a simple test of our service:
415 415
416 #include "“base/bind.h”" 416 #include "“base/bind.h”"
417 #include “"base/run_loop.h”" 417 #include “"base/run_loop.h”"
418 #include “"mojo/shell/public/cpp/service_test.h”" 418 #include “"services/service_manager/public/cpp/service_test.h”"
419 #include “"path/to/some_interface.mojom.h”" 419 #include “"path/to/some_interface.mojom.h”"
420 420
421 void QuitLoop(base::RunLoop* loop) { 421 void QuitLoop(base::RunLoop* loop) {
422 loop->Quit(); 422 loop->Quit();
423 } 423 }
424 424
425 class Test : public shell::test::ServiceTest { 425 class Test : public service_manager::test::ServiceTest {
426 public: 426 public:
427 Test() : shell::test::ServiceTest(“exe:service_unittest”) {} 427 Test() : service_manager::test::ServiceTest(“exe:service_unittest”) {}
428 ~Test() override {} 428 ~Test() override {}
429 } 429 }
430 430
431 TEST_F(Test, Basic) { 431 TEST_F(Test, Basic) {
432 mojom::SomeInterface some_interface; 432 mojom::SomeInterface some_interface;
433 connector()->ConnectToInterface(“"mojo:service"”, &some_interface); 433 connector()->ConnectToInterface(“"mojo:service"”, &some_interface);
434 base::RunLoop loop; 434 base::RunLoop loop;
435 some_interface->Foo(base::Bind(&QuitLoop, &loop)); 435 some_interface->Foo(base::Bind(&QuitLoop, &loop));
436 loop.Run(); 436 loop.Run();
437 } 437 }
438 438
439 The BUILD.gn for this test file looks like any other using the test() template. 439 The BUILD.gn for this test file looks like any other using the test() template.
440 It must also depend on //services/service_manager/public/cpp:shell_test_support. 440 It must also depend on
441 //services/service_manager/public/cpp:service_test_support.
441 442
442 ServiceTest does a few things, but most importantly it register the test itself 443 ServiceTest does a few things, but most importantly it register the test itself
443 as a Service, with the name you pass it via its constructor. In the example 444 as a Service, with the name you pass it via its constructor. In the example
444 above, we supplied the name “exe:service_unittest”. This name is has no special 445 above, we supplied the name “exe:service_unittest”. This name is has no special
445 meaning other than that henceforth it will be used to identify the test service. 446 meaning other than that henceforth it will be used to identify the test service.
446 447
447 Behind the scenes, ServiceTest spins up the Service Manager on a background 448 Behind the scenes, ServiceTest spins up the Service Manager on a background
448 thread, and asks it to create an instance for the test service on the main 449 thread, and asks it to create an instance for the test service on the main
449 thread, with the name supplied. ServiceTest blocks the main thread while the 450 thread, with the name supplied. ServiceTest blocks the main thread while the
450 Service Manager thread does this initialization. Once the Service Manager has 451 Service Manager thread does this initialization. Once the Service Manager has
451 created the instance, it calls OnStart() (as for any other service), and the 452 created the instance, it calls OnStart() (as for any other service), and the
452 main thread continues, running the test. At this point accessors defined in 453 main thread continues, running the test. At this point accessors defined in
453 service_test.h like connector() can be used to connect to other services. 454 service_test.h like connector() can be used to connect to other services.
454 455
455 You’ll note in the example above I made Foo() take a callback, this is to give 456 You’ll note in the example above I made Foo() take a callback, this is to give
456 the test something interesting to do. In the mojom for SomeInterface we’d have 457 the test something interesting to do. In the mojom for SomeInterface we’d have
457 the Foo() method return an empty response. In mojo:service, we’d have Foo() take 458 the Foo() method return an empty response. In mojo:service, we’d have Foo() take
458 the callback as a parameter, and run it. In the test, we spin a RunLoop until we 459 the callback as a parameter, and run it. In the test, we spin a RunLoop until we
459 get that response. In real world cases we can pass back state & validate 460 get that response. In real world cases we can pass back state & validate
460 expectations. You can see real examples of this test framework in use in the 461 expectations. You can see real examples of this test framework in use in the
461 Service Manager’s own suite of tests, under //services/service_manager/tests. 462 Service Manager’s own suite of tests, under //services/service_manager/tests.
462 463
463 ### Packaging 464 ### Packaging
464 465
465 By default a .library statically links its dependencies, so having many of them 466 By default a .library statically links its dependencies, so having many of them
466 will yield an installed product many times larger than Chrome today. For this 467 will yield an installed product many times larger than Chrome today. For this
467 reason it’s desirable to package several Services together in a single binary. 468 reason it’s desirable to package several Services together in a single binary.
468 The Service Manager provides an interface **shell.mojom.ServiceFactory**: 469 The Service Manager provides an interface **service_manager.mojom.ServiceFactory **:
469 470
470 interface ServiceFactory { 471 interface ServiceFactory {
471 CreateService(Service& service, string name); 472 CreateService(Service& service, string name);
472 }; 473 };
473 474
474 When implemented by a service, the service becomes a “package” of other 475 When implemented by a service, the service becomes a “package” of other
475 services, which are instantiated by this interface. Imagine we have two services 476 services, which are instantiated by this interface. Imagine we have two services
476 mojo:service1 and mojo:service2, and we wish to package them together in a 477 mojo:service1 and mojo:service2, and we wish to package them together in a
477 single package mojo:services. We write the Service implementations for 478 single package mojo:services. We write the Service implementations for
478 mojo:service1 and mojo:service2, and then a Service implementation for 479 mojo:service1 and mojo:service2, and then a Service implementation for
479 mojo:services - the latter implements ServiceFactory and instantiates the other 480 mojo:services - the latter implements ServiceFactory and instantiates the other
480 two: 481 two:
481 482
482 using shell::mojom::ServiceFactory; 483 using service_manager::mojom::ServiceFactory;
483 using shell::mojom::ServiceRequest; 484 using service_manager::mojom::ServiceRequest;
484 485
485 class Services : public shell::Service, 486 class Services : public service_manager::Service,
486 public shell::InterfaceFactory<ServiceFactory>, 487 public service_manager::InterfaceFactory<ServiceFactory>,
487 public ServiceFactory { 488 public ServiceFactory {
488 489
489 // Expose ServiceFactory to inbound connections and implement 490 // Expose ServiceFactory to inbound connections and implement
490 // InterfaceFactory to bind requests for it to this object. 491 // InterfaceFactory to bind requests for it to this object.
491 void CreateService(ServiceRequest request, 492 void CreateService(ServiceRequest request,
492 const std::string& name) { 493 const std::string& name) {
493 if (name == “mojo:service1”) 494 if (name == “mojo:service1”)
494 new Service1(std::move(request)); 495 new Service1(std::move(request));
495 else if (name == “mojo:service2”) 496 else if (name == “mojo:service2”)
496 new Service2(std::move(request)); 497 new Service2(std::move(request));
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 packaged_services = [ “"service1”", “"service2"” ] 534 packaged_services = [ “"service1”", “"service2"” ]
534 535
535 The deps line lists the service_manifest targets for the packaged services to be 536 The deps line lists the service_manifest targets for the packaged services to be
536 consumed, and the packaged_services line provides the service names, without the 537 consumed, and the packaged_services line provides the service names, without the
537 “mojo:” prefix. The presence of these two lines will cause the Manifest Collator 538 “mojo:” prefix. The presence of these two lines will cause the Manifest Collator
538 script to run, merging the dependent manifests into the package manifest. You 539 script to run, merging the dependent manifests into the package manifest. You
539 can study the resulting manifest to see what gets generated. 540 can study the resulting manifest to see what gets generated.
540 541
541 At startup, the Service Manager will scan the package directory and consume the 542 At startup, the Service Manager will scan the package directory and consume the
542 manifests it finds, so it can learn about how to resolve aliases that it might 543 manifests it finds, so it can learn about how to resolve aliases that it might
543 encounter subsequently. 544 encounter subsequently.
544 545
545 ### Executables 546 ### Executables
546 547
547 Thus far, the examples we’ve covered have packaged Services in .library files. 548 Thus far, the examples we’ve covered have packaged Services in .library files.
548 It’s also possible to have a conventional executable provide a Service. There 549 It’s also possible to have a conventional executable provide a Service. There
549 are two different ways to use executables with the Service Manager, the first is 550 are two different ways to use executables with the Service Manager, the first is
550 to have the Service Manager start the executable itself, the second is to have 551 to have the Service Manager start the executable itself, the second is to have
551 some other executable start the process and then tell the Service Manager about 552 some other executable start the process and then tell the Service Manager about
552 it. In both cases, the target executable has to perform a handshake with the 553 it. In both cases, the target executable has to perform a handshake with the
553 Service Manager early on so it can bind the Service request the Service Manager 554 Service Manager early on so it can bind the Service request the Service Manager
554 sends it. 555 sends it.
555 556
556 Assuming you have an executable that properly initializes the Mojo EDK, you add 557 Assuming you have an executable that properly initializes the Mojo EDK, you add
557 the following lines at some point early in application startup to establish the 558 the following lines at some point early in application startup to establish the
558 connection with the Service Manager: 559 connection with the Service Manager:
559 560
560 #include “"services/service_manager/public/cpp/service.h”" 561 #include “"services/service_manager/public/cpp/service.h”"
561 #include “"services/service_manager/public/cpp/service_context.h”" 562 #include “"services/service_manager/public/cpp/service_context.h”"
562 #include “"services/service_manager/runner/child/runner_connection.h”" 563 #include “"services/service_manager/runner/child/runner_connection.h”"
563 564
564 class MyClient : public shell::Service { 565 class MyClient : public service_manager::Service {
565 .. 566 ..
566 }; 567 };
567 568
568 shell::mojom::ServiceRequest request; 569 service_manager::mojom::ServiceRequest request;
569 scoped_ptr<shell::RunnerConnection> connection( 570 scoped_ptr<service_manager::RunnerConnection> connection(
570 shell::RunnerConnection::ConnectToRunner( 571 service_manager::RunnerConnection::ConnectToRunner(
571 &request, ScopedMessagePipeHandle())); 572 &request, ScopedMessagePipeHandle()));
572 MyService service; 573 MyService service;
573 shell::ServiceContext context(&service, std::move(request)); 574 service_manager::ServiceContext context(&service, std::move(request));
574 575
575 What’s happening here? The Service/ServiceContext usage should be familiar from 576 What’s happening here? The Service/ServiceContext usage should be familiar from
576 our earlier examples. The interesting part here happens in 577 our earlier examples. The interesting part here happens in
577 `RunnerConnection::ConnectToRunner()`. Before we look at what ConnectToRunner 578 `RunnerConnection::ConnectToRunner()`. Before we look at what ConnectToRunner
578 does, it’s important to cover how this process is launched. In this example, 579 does, it’s important to cover how this process is launched. In this example,
579 this process is launched by the Service Manager. This is achieved through the 580 this process is launched by the Service Manager. This is achieved through the
580 use of the “exe” Service Name type. The Service Names we’ve covered thus far 581 use of the “exe” Service Name type. The Service Names we’ve covered thus far
581 have looked like “mojo:foo”. The “mojo” prefix means that the Shell should look 582 have looked like “mojo:foo”. The “mojo” prefix means that the Shell should look
582 for a .library file at “foo/foo.library” alongside the Service Manager 583 for a .library file at “foo/foo.library” alongside the Service Manager
583 executable. If the code above was linked into an executable “app.exe” alongside 584 executable. If the code above was linked into an executable “app.exe” alongside
(...skipping 24 matching lines...) Expand all
608 base::FilePath target_path; 609 base::FilePath target_path;
609 base::PathService::Get(base::DIR_EXE, &target_path); 610 base::PathService::Get(base::DIR_EXE, &target_path);
610 target_path = target_path.Append(FILE_PATH_LITERAL("“target.exe"”)); 611 target_path = target_path.Append(FILE_PATH_LITERAL("“target.exe"”));
611 base::CommandLine target_command_line(target_path); 612 base::CommandLine target_command_line(target_path);
612 613
613 mojo::edk::PlatformChannelPair pair; 614 mojo::edk::PlatformChannelPair pair;
614 mojo::edk::HandlePassingInformation info; 615 mojo::edk::HandlePassingInformation info;
615 pair.PrepareToPassClientHandleToChildProcess(&target_command_line, &info); 616 pair.PrepareToPassClientHandleToChildProcess(&target_command_line, &info);
616 617
617 std::string token = mojo::edk::GenerateRandomToken(); 618 std::string token = mojo::edk::GenerateRandomToken();
618 target_command_line.AppendSwitchASCII(switches::kPrimordialPipeToken, 619 target_command_line.AppendSwitchASCII(switches::kPrimordialPipeToken,
619 token); 620 token);
620 621
621 mojo::ScopedMessagePipeHandle pipe = 622 mojo::ScopedMessagePipeHandle pipe =
622 mojo::edk::CreateParentMessagePipe(token); 623 mojo::edk::CreateParentMessagePipe(token);
623 624
624 shell::mojom::ServiceFactoryPtr factory; 625 service_manager::mojom::ServiceFactoryPtr factory;
625 factory.Bind( 626 factory.Bind(
626 mojo::InterfacePtrInfo<shell::mojom::ServiceFactory>( 627 mojo::InterfacePtrInfo<service_manager::mojom::ServiceFactory>(
627 std::move(pipe), 0u)); 628 std::move(pipe), 0u));
628 shell::mojom::PIDReceiverPtr receiver; 629 service_manager::mojom::PIDReceiverPtr receiver;
629 630
630 shell::Identity target(“"exe:target”",shell::mojom::kInheritUserID); 631 service_manager::Identity target(“"exe:target”",service_manager::mojom::kInh eritUserID);
631 shell::Connector::ConnectParams params(target); 632 service_manager::Connector::ConnectParams params(target);
632 params.set_client_process_connection(std::move(factory), 633 params.set_client_process_connection(std::move(factory),
633 GetProxy(&receiver)); 634 GetProxy(&receiver));
634 scoped_ptr<shell::Connection> connection = connector->Connect(&params); 635 scoped_ptr<service_manager::Connection> connection = connector->Connect(&par ams);
635 636
636 base::LaunchOptions options; 637 base::LaunchOptions options;
637 options.handles_to_inherit = &info; 638 options.handles_to_inherit = &info;
638 base::Process process = base::LaunchProcess(target_command_line, options); 639 base::Process process = base::LaunchProcess(target_command_line, options);
639 mojo::edk::ChildProcessLaunched(process.Handle(), pair.PassServerHandle()); 640 mojo::edk::ChildProcessLaunched(process.Handle(), pair.PassServerHandle());
640 641
641 That’s a lot. But it boils down to these steps: 642 That’s a lot. But it boils down to these steps:
642 1. Creating the message pipe to connect the target process and the Service 643 1. Creating the message pipe to connect the target process and the Service
643 Manager. 644 Manager.
644 2. Putting the server end of the pipe onto the command line to the target 645 2. Putting the server end of the pipe onto the command line to the target
645 process. 646 process.
646 3. Binding the client end to a ServiceFactoryPtr, constructing an Identity for 647 3. Binding the client end to a ServiceFactoryPtr, constructing an Identity for
647 the target process and passing both through Connector::Connect(). 648 the target process and passing both through Connector::Connect().
648 4. Starting the process with the configured command line. 649 4. Starting the process with the configured command line.
649 650
650 In this example the target executable could be the same as the previous example. 651 In this example the target executable could be the same as the previous example.
651 652
652 A word about process lifetimes. Processes created by the shell are managed by 653 A word about process lifetimes. Processes created by the Service Manager are
653 the Service Manager. While a service-launched process may quit itself at any 654 also managed by the Service Manager. While a service-launched process may quit
654 point, when the Service Manager shuts down it will also shut down any process it 655 itself at any point, when the Service Manager shuts down it will also shut down
655 started. Processes created by services themselves are left to those services to 656 any process it started. Processes created by services themselves are left to
656 manage. 657 those services to manage.
657 658
658 *** 659 ***
659 660
660 TBD: 661 TBD:
661 662
662 Instances & Processes 663 Instances & Processes
663 664
664 Client lifetime strategies 665 Client lifetime strategies
665 666
666 Process lifetimes. 667 Process lifetimes.
667 668
668 Writing tests (ShellTest) 669 Writing tests (ShellTest)
669 Under the Hood 670 Under the Hood
670 Four major components: Shell API (Mojom), Shell, Catalog, Shell Client Lib. 671 Four major components: Shell API (Mojom), Shell, Catalog, Shell Client Lib.
671 The connect flow, catalog, etc. 672 The connect flow, catalog, etc.
672 Capability brokering in the shell 673 Capability brokering in the shell
673 Userids 674 Userids
674 675
675 Finer points: 676 Finer points:
676 677
677 Mojo Names: mojo, exe 678 Mojo Names: mojo, exe
678 Exposing services on outbound connections 679 Exposing services on outbound connections
OLDNEW
« no previous file with comments | « services/navigation/view_impl.cc ('k') | services/service_manager/background/background_shell.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698