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

Side by Side Diff: ipc/README.md

Issue 2783223004: Adds lots of Mojo documentation (Closed)
Patch Set: Created 3 years, 8 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
« no previous file with comments | « no previous file | mojo/README.md » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Converting Legacy Chrome IPC To Mojo
2
3 Looking for [Mojo Documentation](/mojo)?
4
5 [TOC]
6
7 ## Overview
8
9 The `//ipc` directory contains interfaces and implementation for Chrome's
10 legacy IPC system, including `IPC::Channel` and various macros for defining
11 messages and type serialization. For details on using this system please see the
12 original
13 [documentation](https://www.chromium.org/developers/design-documents/inter-proce ss-communication).
14
15 Legacy IPC is **deprecated**, and Chrome developers are strongly discouraged
16 from introducing new messages using this system. [Mojo](/mojo) is the correct
17 IPC system to use moving forward. This document introduces developers to the
18 various tools available to help with conversion of legacy IPC messages to Mojo.
19 It assumes familiarity with [Mojom](/mojo/public/tools/bindings) syntax and
20 general use of Mojo [C++ bindings](/mojo/public/cpp/bindings).
21
22 In traditional Chrome IPC, we have One Big Pipe (the `IPC::Channel`) between
23 each connected process. Sending an IPC from one process to another means knowing
24 how to get a handle to the Channel interface (*e.g.,*
25 [RenderProcessHost::GetChannel](
26 https://cs.chromium.org/chromium/src/content/public/browser/render_process_host. h?rcl=722be98f7e4d7551710fb9cf30674750cdd0d857&l=196)
27 when sending from the browser to a renderer process), and then having either an
28 `IPC::MessageFilter` or some other appropriate `IPC::Listener` implementation
29 installed in the right place on the other side of the channel.
30
31 Because of this arrangement, any message sent on a channel is sent in FIFO order
32 with respect to all other messages on the channel. While this may be easier to
33 reason about in general, it carries with it the unfortunate consequence that
34 many unrelated messages in the system have an implicit, often unintended
35 ordering dependency.
36
37 It's primarily for this reason that conversion to Mojo IPC can be more
38 challenging than would otherwise be necessary, and that is why we have a number
39 of different tools available to facilitate such conversions.
40
41 ## Deciding What to Do
42
43 There are few questions you should ask yourself before embarking upon any IPC
44 message conversion journey. Should this be part of a service? Does message
45 ordering matter with respect to other parts of the system? What is the meaning
46 of life?
47
48 ### Moving Messages to Services
49
50 We have a small but growing number of services defined in
51 [`//services`](https://cs.chromium.org/chromium/src/services), each of which has
52 some set of public interfaces defined in their `public/interfaces` subdirectory.
53 In the limit we want all IPC interfaces to be defined by some Mojom in these
54 directories, so this is the preferred destination for any new message
55 conversions.
jam 2017/04/04 16:05:55 services/ for the foreseeable future is where foun
56
57 If you need help deciding where a message should live, or if you feel it would
58 be appropriate to introduce a new service to implement some feature or large set
59 of messages, please post to
60 [`services-dev@chromium.org`](https://groups.google.com/a/chromium.org/forum/#!f orum/services-dev)
61 with questions, concerns, and/or a brief proposal or design doc describing
62 the augmentation of an existing service or introduction of a new service.
63
64 See the [Using Services](#Using-Services) section below for details.
65
66 When converting messages that still require tight coupling to content or Chrome
67 code or which require unchanged ordering with respect to one or more remaining
68 legacy IPC messages, it is often not immediately feasible to move a message
69 definition or handler implementation into a service.
70
71 ### Moving Messages to Not-Services
72
73 While this isn't strictly possible because everything is a service now, we model
74 all existing content processes as service instances and provide helpers to make
75 interface exposure and consumption between them relatively easy.
76
77 See [Using Content's Connectors](#Using-Content_s-Connectors) for details on
78 the recommended way to accomplish this.
79
80 See
81 [Using Content's Interface Registries](#Using-Content_s-Interface-Registries)
82 for details on the **deprecated** way to accomplish this.
83
84 Note that when converting messages to standalone Mojo interfaces, every
85 interface connection operates 100% independently of each other. This means that
86 ordering is only guaranteed over a single interface (ignoring
87 [associated interfaces](/mojo/public/tools/bindings#Associated-Interfaces).)
88 Consider this example:
89
90 ``` cpp
91 mojom::FrobinatorPtr frob1;
92 RenderThread::Get()->GetConnector()->BindInterface(
93 foo_service::mojom::kServiceName, &frob1);
94
95 mojom::FrobinatorPtr frob2;
96 RenderThread::Get()->GetConnector()->BindInterface(
97 foo_service::mojom::kServiceName, &frob2);
98
99 // These are ordered on |frob1|.
100 frob1->Frobinate(1);
101 frob1->Frobinate(2);
102
103 // These are ordered on |frob2|.
104 frob2->Frobinate(1);
105 frob2->Frobinate(2);
106
107 // It is entirely possible, however, that the renderer receives:
108 //
109 // [frob1]Frobinate(1)
110 // [frob2]Frobinate(1)
111 // [frob1]Frobinate(2)
112 // [frob2]Frobinate(2)
113 //
114 // Because |frob1| and |frob2| guarantee no mutual ordering.
115 ```
116
117 Also note that neither interface is ordered with respect to legacy
118 `IPC::Channel` messages. This can present significant problems when converting a
119 single message or group of messages which must retain ordering with respect to
120 others still on the Channel.
121
122 ### When Ordering Matters
123
124 If ordering really matters with respect to other legacy messages in the system,
125 as is often the case for *e.g.* frame and navigation-related messages, you
126 almost certainly want to take advantage of
127 [Channel-associated interfaces](#Using-Channel-associated-Interfaces) to
128 eliminate any risk of introducing subtle behavioral changes.
129
130 Even if ordering only matters among a small set of messages which you intend to
131 move entirely to Mojom, you may wish to move them one-by-one in separate CLs.
132 In that case, it may make sense to use a Channel-associated interface during the
133 transitional period. Once all relevant messages are fully relocated into a
134 single Mojom interface, it's trivial to lift the interface away from Channel
135 association and into a proper independent service connection.
136
137 ## Using Services
138
139 Suppose you have some IPC messages for safely decoding a PNG image:
140
141 ``` cpp
142 IPC_MESSAGE_CONTROL2(UtilityMsg_DecodePNG,
143 int32_t request_id,
144 std::string /* png_data */);
145 IPC_MESSAGE_CONTROL2(UtilityHostMsg_PNGDecoded,
146 int32_t request_id,
147 int32_t width, int32_t height,
148 std::string /* rgba_data */);
149 ```
150
151 This seems like a perfect fit for an addition to the sandboxed `data_decoder`
152 service. Your first order of business is to translate this into a suitable
153 public interface definition within that service:
154
155 ``` cpp
156 // src/services/data_decoder/public/interfaces/png_decoder.mojom
157 module data_decoder.mojom;
158
159 interface PngDecoder {
160 Decode(array<uint8> png_data)
161 => (int32 width, int32 height, array<uint32> rbga_data);
162 };
163 ```
164
165 and you'll also want to define the implementation within
166 `//services/data_decoder`, pluging in some appropriate binder so the service
167 knows how to bind incoming interface requests to your implementation:
168
169 ``` cpp
170 // src/services/data_decoder/png_decoder_impl.h
171 class PngDecoderImpl : public mojom::PngDecoder {
172 public:
173 static void BindRequest(mojom::PngDecoderRequest request) { /* ... */ }
174
175 // mojom::PngDecoder:
176 void Decode(const std::vector<uint8_t>& png_data,
177 const DecodeCallback& callback) override { /* ... */ }
178 // ...
179 };
180
181 // src/services/data_decoder/data_decoder_service.cc
182 // Not quite legitimate pseudocode...
183 DataDecoderService::DataDecoderService() {
184 // ...
185 registry_.AddInterface(base::Bind(&PngDecoderImpl::BindRequest));
186 }
187 ```
188
189 and finally you need to update the usage of the old IPC by probably deleting
190 lots of ugly code which sets up a `UtilityProcessHostImpl` and replacing it
191 with something like:
192
193 ``` cpp
194 void OnDecodedPng(const std::vector<uint8_t>& rgba_data) { /* ... */ }
195
196 data_decoder::mojom::PngDecoderPtr png_decoder;
197 connector->BindInterface(data_decoder::mojom::kServiceName,
198 mojo::MakeRequest(&png_decoder));
199 png_decoder->Decode(untrusted_png_data, base::Bind(&OnDecodedPng));
200 ```
201
202 Where to get a [`Connector`](https://cs.chromium.org/chromium/src/services/servi ce_manager/public/cpp/connector.h)
203 is an interesting question, and the answer ultimately depends on where your code
204 is written. All service instances get a primordial `Connector` which can be
205 cloned arbitrarily many times and passed around to different threads.
206
207 If you're writing service code the answer is trivial since each `Service`
208 instance has direct access to a `Connector`. If you're writing code at or above
209 the content layer, the answer is slightly more interesting and is explained in
210 the [Using Content's Connectors](#Using-Content_s-Connectors) section below.
211
212 ## Using Content's Connectors
213
214 As explained earlier in this document, all content processes are modeled as
215 service instances today. This means that all content processes have at least
216 one [`Connector`](https://cs.chromium.org/chromium/src/services/service_manager/ public/cpp/connector.h)
217 instance which can be used to bind interfaces exposed by other services.
218
219 We define [`content::ServiceManagerConnection`](https://cs.chromium.org/chromium /src/content/public/common/service_manager_connection.h?rcl=dd92156efac57169b45a eb0094111b8d94302b12&l=38)
220 as a helper which fully encapsulates the service instance state within a given
221 Content process. The main thread of the browser process can access the global
222 instance by calling
223 [`content::ServiceManager::GetForProcess()`](https://cs.chromium.org/chromium/sr c/content/public/common/service_manager_connection.h?rcl=dd92156efac57169b45aeb0 094111b8d94302b12&l=56),
224 and this object has a `GetConnector()` method which exposes the `Connector` for
225 that process.
226
227 The main thread of any Content child process can use
228 `content::ChildThread::GetServiceManagerConnection` or
229 `content::ChildThread::GetConnector` directly.
230
231 For example, any interfaces registered in
232 [`RenderProcessHostImpl::RegisterMojoInterfaces()`](https://cs.chromium.org/chro mium/src/content/browser/renderer_host/render_process_host_impl.cc?rcl=dd92156ef ac57169b45aeb0094111b8d94302b12&l=1203)
233 can be acquired by a renderer as follows:
234
235 ``` cpp
236 mojom::FooPtr foo;
237 content::RenderThread::Get()->GetConnector()->BindInterface(
238 content::mojom::kBrowserServiceName, &foo);
239 foo->DoSomePrettyCoolIPC();
240 ```
241
242 ### On Other Threads
243
244 `Connector` instances can be created and asynchronously associated with each
245 other to maximize flexibility in when and how outgoing interface requests are
246 initiated.
247
248 For example if a background (*e.g.,* worker) thread in a renderer process wants
249 to make an outgoing service request, it can construct its own `Connector` --
250 which may be used immediately and retained on that thread -- and asynchronously
251 associate it with the main-thread `Connector` like so:
252
253 ``` cpp
254 class Thinger {
255 public:
256 explicit Thinger(scoped_refptr<base::TaskRunner> main_thread_task_runner) {
257 service_manager::mojom::ConnectorRequest request;
258
259 // Of course we could also retain |connector| if we intend to use it again.
260 auto connector = service_manager::Connector::Create(&request);
261 connector->BindInterface("best_service_ever", &thinger_);
262 thinger_->DoTheThing();
263
264 // Doesn't really matter when this happens, as long as it eventually
265 // happens.
266 main_thread_task_runner->PostTask(
267 FROM_HERE, base::BindOnce(&Thinger::BindConnectorOnMainThread,
268 std::move(request)));
269 }
270
271 private:
272 static void BindConnectorOnMainThread(
273 service_manager::mojom::ConnectorRequest request) {
274 DCHECK(RenderThreadImpl::Get());
275 RenderThreadImpl::Get()->GetConnector()->BindConnectorRequest(
276 std::move(request));
277 }
278
279 mojom::ThingerPtr thinger_;
280
281 DISALLOW_COPY_AND_ASSIGN(Thinger);
282 };
283 ```
284
285 ## Using Content's Interface Registries
286
287 **NOTE:** This section is here mainly for posterity and documentation of
288 existing usage. Please use `Connector` instead of using an `InterfaceProvider`
289 directly.
290
291 For convenience the Service Manager's
292 [client library](https://cs.chromium.org/chromium/src/services/service_manager/p ublic/cpp/)
293 exposes two useful types: `InterfaceRegistry` and `InterfaceProvider`. These
294 objects generally exist as an intertwined pair with an `InterfaceRegistry` in
295 one process and a corresponding `InterfaceProvider` in another process.
296
297 The `InterfaceRegistry` is essentially just a mapping from interface name
298 to binder function:
299
300 ``` cpp
301 void BindFrobinator(mojom::FrobinatorRequest request) {
302 mojo::MakeStrongBinding(base::MakeUnique<FrobinatorImpl>, std::move(request));
303 }
304
305 // |registry| will hereby handle all incoming requests for "mojom::Frobinator"
306 // using the above function, which binds the request pipe handle to a new
307 // instance of |FrobinatorImpl|.
308 registry->AddInterface(base::Bind(&BindFrobinator));
309 ```
310
311 while an `InterfaceProvider` exposes a means of requesting interfaces from a
312 remote `InterfaceRegistry`:
313
314 ``` cpp
315 mojom::FrobinatorPtr frob;
316
317 // MakeRequest creates a new pipe, and GetInterface sends one end of it to
318 // the remote InterfaceRegistry along with the "mojom::Frobinator" name. The
319 // other end of the pipe is bound to |frob| which may immediately begin sending
320 // messages.
321 provider->GetInterface(mojo::MakeRequest(&frob));
322 frob->DoTheFrobinator();
323 ```
324
325 For convenience, we stick an `InterfaceRegistry` and corresponding
326 `InterfaceProvider` in several places at the Content layer to facilitate
327 interface connection between browser and renderer processes:
328
329 | `InterfaceRegistry` | `InterfaceProvider` |
330 |---------------------------------------------|--------------------------------- -----------|
331 | `RenderProcessHost::GetInterfaceRegistry()` | `RenderThreadImpl::GetRemoteInte rfaces()` |
332 | `RenderThreadImpl::GetInterfaceRegistry()` | `RenderProcessHost::GetRemoteInt erfaces()` |
333 | `RenderFrameHost::GetInterfaceRegistry()` | `RenderFrame::GetRemoteInterface s()` |
334 | `RenderFrame::GetInterfaceRegistry()` | `RenderFrameHost::GetRemoteInter faces()` |
335
336 As noted above, use of these registries is generally discouraged.
337
338 ## Using Channel-associated Interfaces
339
340 **NOTE**: Channel-associated interfaces are an interim solution to make the
341 transition to Mojo IPC easier in Chrome. You should not design new features
342 which rely on this system. The ballpark date of deletion for `IPC::Channel` is
343 projected to be somewhere around mid-2019, and obviously Channel-associated
344 interfaces can't live beyond that point.
345
346 Mojo has support for the concept of
347 [associated interfaces](/mojo/public/tools/bindings#Associated-Interfaces).
348 One interface is "associated" with another when it's a logically separate
349 interface but it shares an underlying message pipe, causing both interfaces to
350 maintain mutual FIFO message ordering. For example:
351
352 ``` cpp
353 // db.mojom
354 module db.mojom;
355
356 interface Table {
357 void AddRow(string data);
358 };
359
360 interface Database {
361 QuerySize() => (uint64 size);
362 AddTable(associated Table& table)
363 };
364
365 // db_client.cc
366 db::mojom::DatabasePtr db = /* ... get it from somewhere... */
367 db::mojom::TableAssociatedPtr new_table;
368 db->AddTable(mojo::MakeRequest(&new_table));
369 new_table->AddRow("my hovercraft is full of eels");
370 db->QuerySize(base::Bind([](uint64_t size) { /* ... */ }));
371 ```
372
373 In the above code, the `AddTable` message will always arrive before the `AddRow`
374 message, which itself will always arrive before the `QuerySize` message. If the
375 `Table` interface were not associated with the `Database` pipe, it would be
376 possible for the `QuerySize` message to be received before `AddRow`,
377 potentially leading to unintended behavior.
378
379 The legacy `IPC::Channel` used everywhere today is in fact just another Mojo
380 interface, and developers have the ability to associate other arbitrary Mojo
381 interfaces with any given Channel. This means that you can define a set of Mojo
382 messages to convert old IPC messages, and implement them in a way which
383 perfectly preserves current message ordering.
384
385 There are many different facilities in place for taking advantage of
386 Channel-associated interfaces, and the right one for your use case depends on
387 how the legacy IPC message is used today. The subsections below cover various
388 interesting scenarios.
389
390 ### Basic Usage
391
392 The most primitive way to use Channel-associated interfaces is by working
393 directly with `IPC::Channel` (IO thread) or more commonly `IPC::ChannelProxy`
394 (main thread). There are a handful of interesting interface methods here.
395
396 **On the IO thread** (*e.g.,* typically when working with process hosts that
397 aren't for render processes), the interesting methods are as follows:
398
399 [`IPC::Channel::GetAssociatedInterfaceSupport`](https://cs.chromium.org/chromium /src/ipc/ipc_channel.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=235)
400 returns an object for working with interfaces associated with the `Channel`.
401 This is never null.
402
403 [`IPC::Channel::AssociatedInterfaceSupport::AddAssociatedInterface<T>`](
404 https://cs.chromium.org/chromium/src/ipc/ipc_channel.h?rcl=a896ff44a395a50ab18f5 120f20b7eb5a9550247&l=115)
405 allows you to add a binding function to handle all incoming requests for a
406 specific type of associated interface. Callbacks added here are called on the IO
407 thread any time a corresponding interface request arrives on the `Channel.` If
408 no callback is registered for an incoming interface request, the request falls
409 through to the Channel's `Listener` via
410 [`IPC::Listener::OnAssociatedInterfaceRequest`](https://cs.chromium.org/chromium /src/ipc/ipc_listener.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=40).
411
412 [`IPC::Channel::AssociatedInterfaceSupport::GetRemoteAssociatedInterface<T>`](
413 https://cs.chromium.org/chromium/src/ipc/ipc_channel.h?rcl=a896ff44a395a50ab18f5 120f20b7eb5a9550247&l=124)
414 requests a Channel-associated interface from the remote endpoint of the channel.
415
416 **On the main thread**, typically when working with `RenderProcessHost`, basic
417 usage involves calls to
418 [`IPC::ChannelProxy::GetRemoteAssociatedInterface<T>`](
419 https://cs.chromium.org/chromium/src/ipc/ipc_channel_proxy.h?rcl=a896ff44a395a50 ab18f5120f20b7eb5a9550247&l=196)
420 when making outgoing interface requests, or some implementation of
421 [`IPC::Listener::OnAssociatedInterfaceRequest`](https://cs.chromium.org/chromium /src/ipc/ipc_listener.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=40)
422 when handling incoming ones.
423
424 TODO - Add docs for using AssociatedInterfaceRegistry where possible.
425
426 ### BrowserMessageFilter
427
428 [BrowserMessageFilter](https://cs.chromium.org/chromium/src/content/public/brows er/browser_message_filter.h?rcl=805f2ca5aa0902f56885ea3c8c0a42cb80d84522&l=37)
429 is a popular helper for listening to incoming legacy IPC messages on the browser
430 process IO thread and (typically) handling them there.
431
432 A common and totally reasonable tactic for converting a group of messages on an
433 existing `BrowserMessageFilter` is to define a similiarly named Mojom interface
434 in an inner `mojom` namespace (*e.g.,* a `content::FooMessageFilter` would have
435 a corresponding `content::mojom::FooMessageFilter` interface), and have the
436 `BrowserMessageFilter` implementation also implement
437 `BrowserAssociatedInterface<T>`.
438
439 Real code is probably the most useful explanation, so here are some example
440 conversion CLs which demonstrate practical `BrowserAssociatedInterface` usage.
441
442 [FrameHostMsg_SetCookie](https://codereview.chromium.org/2167513003) - This
443 CL introduces a `content::mojom::RenderFrameMessageFilter` interface
444 corresponding to the existing `content::RenderFrameMessageFilter` implementation
445 of `BrowserMessageFilter`. Of particular interest is the fact that it only
446 converts **one** of the messages on that filter. This is fine because ordering
447 among the messages -- Mojom or otherwise -- is unchanged.
448
449 [FrameHostMsg_GetCookie](https://codereview.chromium.org/2202723005) - A small
450 follow-up to the above CL, this converts another message on the same filter. It
451 is common to convert a large group of messages one-by-one in separate CLs. Also
452 note that this message, unlike the one above on the same interface, is
453 synchronous.
454
455 [ViewHostMsg_GenerateRoutingID](https://codereview.chromium.org/2351333002) -
456 Another small CL to introduce a new `BrowserAssociatedInterface`.
457
458 ### Routed Per-Frame Messages To the Browser
459
460 Many legacy IPC messages are "routed" -- they carry a routing ID parameter which
461 is interpreted by the channel endpoint and used to pass a received message on to
462 some other more specific handler.
463
464 Messages received by the browser with a frame routing ID for example are routed
465 to the RenderFrameHost's owning [`WebContents`](https://cs.chromium.org/chromium /src/content/browser/web_contents/web_contents_impl.h?rcl=a12e52d81346dd23d82847 63d44c4ee657f11cea&l=447)
466 with the corresponding `RenderFrameHostImpl` as additional context.
467
468 [This CL](https://codereview.chromium.org/2310583002) introduces usage of
469 [`WebContentsFrameBindingSet<T>`](https://cs.chromium.org/chromium/src/content/p ublic/browser/web_contents_binding_set.h?rcl=d364139fee76154a1d9fa8875ad0cbb5ccb 523c3&l=112), which helps establish
470 per-frame bindings for Channel-associated interfaces. Some hidden magic is done
471 to make it so that interface requests from a remote
472 [`RenderFrame AssociatedInterfaceProvider`](https://cs.chromium.org/chromium/src /content/public/renderer/render_frame.h?rcl=d364139fee76154a1d9fa8875ad0cbb5ccb5 23c3&l=170)
473 are routed to the appropriate `WebContentsFrameBindingSet`, typically installed
474 (as in this CL) by a `WebContentsObserver`.
475
476 When a message is received by an interface implementation using a
477 `WebContentsFrameBindingSet`, that object's `dispatch_context()` can be used
478 to retrieve the `RenderFrameHostImpl` targeted by the message. See the above CL
479 for additional clarity.
480
481 ### Other Routed Messages To the Browser
482
483 Other routing IDs are used when targeting either specific `RenderViewHost` or
484 `RenderWidgetHost` instances. We don't currently have any facilities in place
485 to assist with these conversions. Because render views are essentially a
486 deprecated concept, messages targeting "view" routes should not be converted
487 as-is, but should instead be moved to target either widgets or frames
488 accordingly.
489
490 Facilities to assist in conversion of widget-routed messages may be added in the
491 future. Who knows, maybe you'll be the brave developer to add them (and to then
492 update this documentation, of course!) If you decide this is exactly what you
493 need but are nervous about the prospect of writing it yourself, please send a
494 friendly message to [chromium-mojo@chromium.org](https://groups.google.com/a/chr omium.org/forum/#!forum/chromium-mojo)
495 explaining the use case so we can help you get things done.
496
497 ### Messages to a Renderer
498
499 [This CL](https://codereview.chromium.org/2381493003) converts `ViewMsg_New`
500 to a Mojo interface, by virtue of the fact that
501 `IPC::ChannelProxy::GetRemoteAssociatedInterface` from the browser process
502 results in an associated interface request arriving at
503 `ChildThreadImpl::OnAssociatedInterfaceRequest` in the corresponding child
504 process.
505
506 Similar message conversions are done by [this CL](https://codereview.chromium.or g/2400313002).
507
508 Note that we do not currently have any helpers for converting routed messages
509 from browser to renderer. Please confer with
510 [chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!fo rum/chromium-mojo)
511 if such a use case is blocking your work.
512
513 ## Miscellany
514
515 ### Using Legacy IPC Traits
516
517 InsSome circumstances there may be a C++ enum, struct, or class that you want
518 to use in a Mojom via [type mapping](/mojo/public/cpp/bindings#Type-Mapping),
519 and that type may already have `IPC::ParamTraits` defined (possibly via
520 `IPC_STRUCT_TRAITS*` macros) for legacy IPC.
521
522 If this is the case and the Mojom which uses the type will definitely only be
523 called from and implemented in C++ code, *and* you have sufficient reason to
524 avoid moving or duplicating the type definition in Mojom, you can take advantage
525 of the existing `ParamTraits`.
526
527 #### The [Native] Attribute
528 In order to do this you must declare a placeholder type in Mojom somewhere, like
529 so:
530
531 ```
532 module foo.mojom;
533
534 [Native]
535 enum WindowType;
536
537 [Native]
538 struct MyGiganticStructure;
539 ```
540
541 The rest of your Mojom will use this typename when referring to the type, but
542 the wire format used is defined entirely by `IPC::ParamTraits<T>` for whatever
543 `T` to which you typemap the Mojom type. For example if you typemap
544 `foo::mojom::MyGiganticStructure` to `foo::MyGiganticStructure`, your typemap
545 must point to some header which defines
546 `IPC::ParamTraits<foo::MyGiganticStructure>`.
547
548 Note that if your `ParamTraits` are defined manually (*i.e.* not by invocation
549 of `IPC_STRUCT_TRAITS*` macros) you must also ensure that they define the new
550 `GetSize` method:
551
552 ``` cpp
553 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
554 // ...
555 }
556 ```
557
558 `base::PickleSizer` has an interface analogous to `base::Pickle`, except that it
559 merely accumulates a byte count rather than accumulating serialized data.
560
561 There are several examples of this traits implementation in common IPC traits
562 defined [here](https://code.google.com/p/chromium/codesearch#chromium/src/ipc/ip c_message_utils.h).
563
564 #### A Practical Example
565
566 Given the [`resource_messages.h`](https://cs.chromium.org/chromium/src/content/c ommon/resource_messages.h?rcl=2e7a430d8d88222c04ab3ffb0a143fa85b3cec5b&l=215)
567 header with the following definition:
568
569 ``` cpp
570 IPC_STRUCT_TRAITS_BEGIN(content::ResourceRequest)
571 IPC_STRUCT_TRAITS_MEMBER(method)
572 IPC_STRUCT_TRAITS_MEMBER(url)
573 // ...
574 IPC_STRUCT_TRAITS_END()
575 ```
576
577 and the [`resource_request.h`](https://cs.chromium.org/chromium/src/content/comm on/resource_request.h?rcl=dce9e476a525e4ff0304787935dc1a8c38392ac8&l=32)
578 header with the definition for `content::ResourceRequest`:
579
580 ``` cpp
581 namespace content {
582
583 struct CONTENT_EXPORT ResourceRequest {
584 // ...
585 };
586
587 } // namespace content
588 ```
589
590 we can declare a corresponding Mojom type:
591
592 ```
593 module content.mojom;
594
595 [Native]
596 struct URLRequest;
597 ```
598
599 and add a typemap like [url_request.typemap](https://cs.chromium.org/chromium/sr c/content/common/url_request.typemap)
600 to define the mapping:
601
602 ```
603 mojom = "//content/common/url_loader.mojom"
604 public_headers = [ "//content/common/resource_request.h" ]
605 traits_headers = [ "//content/common/resource_messages.h" ]
606 ...
607 type_mappings = [ "content.mojom.URLRequest=content::ResourceRequest" ]
608 ```
609
610 Note specifically that `public_headers` includes the definition of the native
611 C++ type, and `traits_headers` includes the definition of the legacy IPC traits.
612
613 Finally, note that this same approach can be used to leverage existing
614 `IPC_ENUM_TRAITS` for `[Native]` Mojom enum aliases.
615
616 ### Typemaps With Content and Blink Types
617
618 Using typemapping for messages that go between Blink and content browser code
619 can sometimes be tricky due to things like dependency cycles or confusion over
620 the correct place for some definition to live. There are some example
621 CLs provided here, but feel free to also contact
622 [chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!fo rum/chromium-mojo)
623 with specific details if you encounter trouble.
624
625 [This CL](https://codereview.chromium.org/2363533002) introduces a Mojom
626 definition and typemap for
627 `ui::WindowOpenDisposition` as a precursor to the IPC conversion below.
628
629 The [follow-up CL](https://codereview.chromium.org/2363573002) uses that
630 definition along with several other new typemaps (including native typemaps as
631 described above in [Using Legacy IPC Traits](#Using-Legacy-IPC-Traits)) to
632 convert the relatively large `ViewHostMsg_CreateWindow` message to Mojo.
633
634 ### Utility Process Messages
635
636 Given that there are no interesting ordering dependencies among disparate IPC
637 messages to and from utility processes, and because the utility process is
638 already sort of a mixed bag of unrelated IPCs, the correct way to convert
639 utility process IPCs to Mojo is to move them into services.
640
641 We already have support for running services out-of-process (with or without a
642 sandbox), and many utility process operations already have a suitable service
643 home they could be moved to. For example, the `data_decoder` service in
644 [`//services/data_decoder`](https://cs.chromium.org/chromium/src/services/data_d ecoder/)
645 is a good place to stick utility process IPCs that do decoding of relatively
646 complex and untrusted data, of which (at the time of this writing) there are
647 quite a few.
648
649 When in doubt, contact
650 [`services-dev@chromium.org`](https://groups.google.com/a/chromium.org/forum/#!f orum/services-dev)
651 with ideas, questions, suggestions, etc.
652
653 ### Additional Documentation
654
655 [Chrome IPC to Mojo IPC Cheat Sheet](https://www.chromium.org/developers/design- documents/mojo/chrome-ipc-to-mojo-ipc-cheat-sheet)
656 : A slightly dated but still valuable document covering some details
657 regarding the conceptual mapping between legacy IPC and Mojo.
658
659 [Mojo Migration Guide](https://www.chromium.org/developers/design-documents/mojo /mojo-migration-guide)
660 : Another slightly (more) data document covering the basics of IPC conversion
661 to Mojo.
662
663 TODO: The migration guide above should probably be deleted and the good
664 parts merged into this document.
OLDNEW
« no previous file with comments | « no previous file | mojo/README.md » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698