Index: ipc/README.md |
diff --git a/ipc/README.md b/ipc/README.md |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ba08e0753059bb2194ffccc6ef9349705ca53ef4 |
--- /dev/null |
+++ b/ipc/README.md |
@@ -0,0 +1,664 @@ |
+# Converting Legacy Chrome IPC To Mojo |
+ |
+Looking for [Mojo Documentation](/mojo)? |
+ |
+[TOC] |
+ |
+## Overview |
+ |
+The `//ipc` directory contains interfaces and implementation for Chrome's |
+legacy IPC system, including `IPC::Channel` and various macros for defining |
+messages and type serialization. For details on using this system please see the |
+original |
+[documentation](https://www.chromium.org/developers/design-documents/inter-process-communication). |
+ |
+Legacy IPC is **deprecated**, and Chrome developers are strongly discouraged |
+from introducing new messages using this system. [Mojo](/mojo) is the correct |
+IPC system to use moving forward. This document introduces developers to the |
+various tools available to help with conversion of legacy IPC messages to Mojo. |
+It assumes familiarity with [Mojom](/mojo/public/tools/bindings) syntax and |
+general use of Mojo [C++ bindings](/mojo/public/cpp/bindings). |
+ |
+In traditional Chrome IPC, we have One Big Pipe (the `IPC::Channel`) between |
+each connected process. Sending an IPC from one process to another means knowing |
+how to get a handle to the Channel interface (*e.g.,* |
+[RenderProcessHost::GetChannel]( |
+https://cs.chromium.org/chromium/src/content/public/browser/render_process_host.h?rcl=722be98f7e4d7551710fb9cf30674750cdd0d857&l=196) |
+when sending from the browser to a renderer process), and then having either an |
+`IPC::MessageFilter` or some other appropriate `IPC::Listener` implementation |
+installed in the right place on the other side of the channel. |
+ |
+Because of this arrangement, any message sent on a channel is sent in FIFO order |
+with respect to all other messages on the channel. While this may be easier to |
+reason about in general, it carries with it the unfortunate consequence that |
+many unrelated messages in the system have an implicit, often unintended |
+ordering dependency. |
+ |
+It's primarily for this reason that conversion to Mojo IPC can be more |
+challenging than would otherwise be necessary, and that is why we have a number |
+of different tools available to facilitate such conversions. |
+ |
+## Deciding What to Do |
+ |
+There are few questions you should ask yourself before embarking upon any IPC |
+message conversion journey. Should this be part of a service? Does message |
+ordering matter with respect to other parts of the system? What is the meaning |
+of life? |
+ |
+### Moving Messages to Services |
+ |
+We have a small but growing number of services defined in |
+[`//services`](https://cs.chromium.org/chromium/src/services), each of which has |
+some set of public interfaces defined in their `public/interfaces` subdirectory. |
+In the limit we want all IPC interfaces to be defined by some Mojom in these |
+directories, so this is the preferred destination for any new message |
+conversions. |
jam
2017/04/04 16:05:55
services/ for the foreseeable future is where foun
|
+ |
+If you need help deciding where a message should live, or if you feel it would |
+be appropriate to introduce a new service to implement some feature or large set |
+of messages, please post to |
+[`services-dev@chromium.org`](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev) |
+with questions, concerns, and/or a brief proposal or design doc describing |
+the augmentation of an existing service or introduction of a new service. |
+ |
+See the [Using Services](#Using-Services) section below for details. |
+ |
+When converting messages that still require tight coupling to content or Chrome |
+code or which require unchanged ordering with respect to one or more remaining |
+legacy IPC messages, it is often not immediately feasible to move a message |
+definition or handler implementation into a service. |
+ |
+### Moving Messages to Not-Services |
+ |
+While this isn't strictly possible because everything is a service now, we model |
+all existing content processes as service instances and provide helpers to make |
+interface exposure and consumption between them relatively easy. |
+ |
+See [Using Content's Connectors](#Using-Content_s-Connectors) for details on |
+the recommended way to accomplish this. |
+ |
+See |
+[Using Content's Interface Registries](#Using-Content_s-Interface-Registries) |
+for details on the **deprecated** way to accomplish this. |
+ |
+Note that when converting messages to standalone Mojo interfaces, every |
+interface connection operates 100% independently of each other. This means that |
+ordering is only guaranteed over a single interface (ignoring |
+[associated interfaces](/mojo/public/tools/bindings#Associated-Interfaces).) |
+Consider this example: |
+ |
+``` cpp |
+mojom::FrobinatorPtr frob1; |
+RenderThread::Get()->GetConnector()->BindInterface( |
+ foo_service::mojom::kServiceName, &frob1); |
+ |
+mojom::FrobinatorPtr frob2; |
+RenderThread::Get()->GetConnector()->BindInterface( |
+ foo_service::mojom::kServiceName, &frob2); |
+ |
+// These are ordered on |frob1|. |
+frob1->Frobinate(1); |
+frob1->Frobinate(2); |
+ |
+// These are ordered on |frob2|. |
+frob2->Frobinate(1); |
+frob2->Frobinate(2); |
+ |
+// It is entirely possible, however, that the renderer receives: |
+// |
+// [frob1]Frobinate(1) |
+// [frob2]Frobinate(1) |
+// [frob1]Frobinate(2) |
+// [frob2]Frobinate(2) |
+// |
+// Because |frob1| and |frob2| guarantee no mutual ordering. |
+``` |
+ |
+Also note that neither interface is ordered with respect to legacy |
+`IPC::Channel` messages. This can present significant problems when converting a |
+single message or group of messages which must retain ordering with respect to |
+others still on the Channel. |
+ |
+### When Ordering Matters |
+ |
+If ordering really matters with respect to other legacy messages in the system, |
+as is often the case for *e.g.* frame and navigation-related messages, you |
+almost certainly want to take advantage of |
+[Channel-associated interfaces](#Using-Channel-associated-Interfaces) to |
+eliminate any risk of introducing subtle behavioral changes. |
+ |
+Even if ordering only matters among a small set of messages which you intend to |
+move entirely to Mojom, you may wish to move them one-by-one in separate CLs. |
+In that case, it may make sense to use a Channel-associated interface during the |
+transitional period. Once all relevant messages are fully relocated into a |
+single Mojom interface, it's trivial to lift the interface away from Channel |
+association and into a proper independent service connection. |
+ |
+## Using Services |
+ |
+Suppose you have some IPC messages for safely decoding a PNG image: |
+ |
+``` cpp |
+IPC_MESSAGE_CONTROL2(UtilityMsg_DecodePNG, |
+ int32_t request_id, |
+ std::string /* png_data */); |
+IPC_MESSAGE_CONTROL2(UtilityHostMsg_PNGDecoded, |
+ int32_t request_id, |
+ int32_t width, int32_t height, |
+ std::string /* rgba_data */); |
+``` |
+ |
+This seems like a perfect fit for an addition to the sandboxed `data_decoder` |
+service. Your first order of business is to translate this into a suitable |
+public interface definition within that service: |
+ |
+``` cpp |
+// src/services/data_decoder/public/interfaces/png_decoder.mojom |
+module data_decoder.mojom; |
+ |
+interface PngDecoder { |
+ Decode(array<uint8> png_data) |
+ => (int32 width, int32 height, array<uint32> rbga_data); |
+}; |
+``` |
+ |
+and you'll also want to define the implementation within |
+`//services/data_decoder`, pluging in some appropriate binder so the service |
+knows how to bind incoming interface requests to your implementation: |
+ |
+``` cpp |
+// src/services/data_decoder/png_decoder_impl.h |
+class PngDecoderImpl : public mojom::PngDecoder { |
+ public: |
+ static void BindRequest(mojom::PngDecoderRequest request) { /* ... */ } |
+ |
+ // mojom::PngDecoder: |
+ void Decode(const std::vector<uint8_t>& png_data, |
+ const DecodeCallback& callback) override { /* ... */ } |
+ // ... |
+}; |
+ |
+// src/services/data_decoder/data_decoder_service.cc |
+// Not quite legitimate pseudocode... |
+DataDecoderService::DataDecoderService() { |
+ // ... |
+ registry_.AddInterface(base::Bind(&PngDecoderImpl::BindRequest)); |
+} |
+``` |
+ |
+and finally you need to update the usage of the old IPC by probably deleting |
+lots of ugly code which sets up a `UtilityProcessHostImpl` and replacing it |
+with something like: |
+ |
+``` cpp |
+void OnDecodedPng(const std::vector<uint8_t>& rgba_data) { /* ... */ } |
+ |
+data_decoder::mojom::PngDecoderPtr png_decoder; |
+connector->BindInterface(data_decoder::mojom::kServiceName, |
+ mojo::MakeRequest(&png_decoder)); |
+png_decoder->Decode(untrusted_png_data, base::Bind(&OnDecodedPng)); |
+``` |
+ |
+Where to get a [`Connector`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/connector.h) |
+is an interesting question, and the answer ultimately depends on where your code |
+is written. All service instances get a primordial `Connector` which can be |
+cloned arbitrarily many times and passed around to different threads. |
+ |
+If you're writing service code the answer is trivial since each `Service` |
+instance has direct access to a `Connector`. If you're writing code at or above |
+the content layer, the answer is slightly more interesting and is explained in |
+the [Using Content's Connectors](#Using-Content_s-Connectors) section below. |
+ |
+## Using Content's Connectors |
+ |
+As explained earlier in this document, all content processes are modeled as |
+service instances today. This means that all content processes have at least |
+one [`Connector`](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/connector.h) |
+instance which can be used to bind interfaces exposed by other services. |
+ |
+We define [`content::ServiceManagerConnection`](https://cs.chromium.org/chromium/src/content/public/common/service_manager_connection.h?rcl=dd92156efac57169b45aeb0094111b8d94302b12&l=38) |
+as a helper which fully encapsulates the service instance state within a given |
+Content process. The main thread of the browser process can access the global |
+instance by calling |
+[`content::ServiceManager::GetForProcess()`](https://cs.chromium.org/chromium/src/content/public/common/service_manager_connection.h?rcl=dd92156efac57169b45aeb0094111b8d94302b12&l=56), |
+and this object has a `GetConnector()` method which exposes the `Connector` for |
+that process. |
+ |
+The main thread of any Content child process can use |
+`content::ChildThread::GetServiceManagerConnection` or |
+`content::ChildThread::GetConnector` directly. |
+ |
+For example, any interfaces registered in |
+[`RenderProcessHostImpl::RegisterMojoInterfaces()`](https://cs.chromium.org/chromium/src/content/browser/renderer_host/render_process_host_impl.cc?rcl=dd92156efac57169b45aeb0094111b8d94302b12&l=1203) |
+can be acquired by a renderer as follows: |
+ |
+``` cpp |
+mojom::FooPtr foo; |
+content::RenderThread::Get()->GetConnector()->BindInterface( |
+ content::mojom::kBrowserServiceName, &foo); |
+foo->DoSomePrettyCoolIPC(); |
+``` |
+ |
+### On Other Threads |
+ |
+`Connector` instances can be created and asynchronously associated with each |
+other to maximize flexibility in when and how outgoing interface requests are |
+initiated. |
+ |
+For example if a background (*e.g.,* worker) thread in a renderer process wants |
+to make an outgoing service request, it can construct its own `Connector` -- |
+which may be used immediately and retained on that thread -- and asynchronously |
+associate it with the main-thread `Connector` like so: |
+ |
+``` cpp |
+class Thinger { |
+ public: |
+ explicit Thinger(scoped_refptr<base::TaskRunner> main_thread_task_runner) { |
+ service_manager::mojom::ConnectorRequest request; |
+ |
+ // Of course we could also retain |connector| if we intend to use it again. |
+ auto connector = service_manager::Connector::Create(&request); |
+ connector->BindInterface("best_service_ever", &thinger_); |
+ thinger_->DoTheThing(); |
+ |
+ // Doesn't really matter when this happens, as long as it eventually |
+ // happens. |
+ main_thread_task_runner->PostTask( |
+ FROM_HERE, base::BindOnce(&Thinger::BindConnectorOnMainThread, |
+ std::move(request))); |
+ } |
+ |
+ private: |
+ static void BindConnectorOnMainThread( |
+ service_manager::mojom::ConnectorRequest request) { |
+ DCHECK(RenderThreadImpl::Get()); |
+ RenderThreadImpl::Get()->GetConnector()->BindConnectorRequest( |
+ std::move(request)); |
+ } |
+ |
+ mojom::ThingerPtr thinger_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Thinger); |
+}; |
+``` |
+ |
+## Using Content's Interface Registries |
+ |
+**NOTE:** This section is here mainly for posterity and documentation of |
+existing usage. Please use `Connector` instead of using an `InterfaceProvider` |
+directly. |
+ |
+For convenience the Service Manager's |
+[client library](https://cs.chromium.org/chromium/src/services/service_manager/public/cpp/) |
+exposes two useful types: `InterfaceRegistry` and `InterfaceProvider`. These |
+objects generally exist as an intertwined pair with an `InterfaceRegistry` in |
+one process and a corresponding `InterfaceProvider` in another process. |
+ |
+The `InterfaceRegistry` is essentially just a mapping from interface name |
+to binder function: |
+ |
+``` cpp |
+void BindFrobinator(mojom::FrobinatorRequest request) { |
+ mojo::MakeStrongBinding(base::MakeUnique<FrobinatorImpl>, std::move(request)); |
+} |
+ |
+// |registry| will hereby handle all incoming requests for "mojom::Frobinator" |
+// using the above function, which binds the request pipe handle to a new |
+// instance of |FrobinatorImpl|. |
+registry->AddInterface(base::Bind(&BindFrobinator)); |
+``` |
+ |
+while an `InterfaceProvider` exposes a means of requesting interfaces from a |
+remote `InterfaceRegistry`: |
+ |
+``` cpp |
+mojom::FrobinatorPtr frob; |
+ |
+// MakeRequest creates a new pipe, and GetInterface sends one end of it to |
+// the remote InterfaceRegistry along with the "mojom::Frobinator" name. The |
+// other end of the pipe is bound to |frob| which may immediately begin sending |
+// messages. |
+provider->GetInterface(mojo::MakeRequest(&frob)); |
+frob->DoTheFrobinator(); |
+``` |
+ |
+For convenience, we stick an `InterfaceRegistry` and corresponding |
+`InterfaceProvider` in several places at the Content layer to facilitate |
+interface connection between browser and renderer processes: |
+ |
+| `InterfaceRegistry` | `InterfaceProvider` | |
+|---------------------------------------------|--------------------------------------------| |
+| `RenderProcessHost::GetInterfaceRegistry()` | `RenderThreadImpl::GetRemoteInterfaces()` | |
+| `RenderThreadImpl::GetInterfaceRegistry()` | `RenderProcessHost::GetRemoteInterfaces()` | |
+| `RenderFrameHost::GetInterfaceRegistry()` | `RenderFrame::GetRemoteInterfaces()` | |
+| `RenderFrame::GetInterfaceRegistry()` | `RenderFrameHost::GetRemoteInterfaces()` | |
+ |
+As noted above, use of these registries is generally discouraged. |
+ |
+## Using Channel-associated Interfaces |
+ |
+**NOTE**: Channel-associated interfaces are an interim solution to make the |
+transition to Mojo IPC easier in Chrome. You should not design new features |
+which rely on this system. The ballpark date of deletion for `IPC::Channel` is |
+projected to be somewhere around mid-2019, and obviously Channel-associated |
+interfaces can't live beyond that point. |
+ |
+Mojo has support for the concept of |
+[associated interfaces](/mojo/public/tools/bindings#Associated-Interfaces). |
+One interface is "associated" with another when it's a logically separate |
+interface but it shares an underlying message pipe, causing both interfaces to |
+maintain mutual FIFO message ordering. For example: |
+ |
+``` cpp |
+// db.mojom |
+module db.mojom; |
+ |
+interface Table { |
+ void AddRow(string data); |
+}; |
+ |
+interface Database { |
+ QuerySize() => (uint64 size); |
+ AddTable(associated Table& table) |
+}; |
+ |
+// db_client.cc |
+db::mojom::DatabasePtr db = /* ... get it from somewhere... */ |
+db::mojom::TableAssociatedPtr new_table; |
+db->AddTable(mojo::MakeRequest(&new_table)); |
+new_table->AddRow("my hovercraft is full of eels"); |
+db->QuerySize(base::Bind([](uint64_t size) { /* ... */ })); |
+``` |
+ |
+In the above code, the `AddTable` message will always arrive before the `AddRow` |
+message, which itself will always arrive before the `QuerySize` message. If the |
+`Table` interface were not associated with the `Database` pipe, it would be |
+possible for the `QuerySize` message to be received before `AddRow`, |
+potentially leading to unintended behavior. |
+ |
+The legacy `IPC::Channel` used everywhere today is in fact just another Mojo |
+interface, and developers have the ability to associate other arbitrary Mojo |
+interfaces with any given Channel. This means that you can define a set of Mojo |
+messages to convert old IPC messages, and implement them in a way which |
+perfectly preserves current message ordering. |
+ |
+There are many different facilities in place for taking advantage of |
+Channel-associated interfaces, and the right one for your use case depends on |
+how the legacy IPC message is used today. The subsections below cover various |
+interesting scenarios. |
+ |
+### Basic Usage |
+ |
+The most primitive way to use Channel-associated interfaces is by working |
+directly with `IPC::Channel` (IO thread) or more commonly `IPC::ChannelProxy` |
+(main thread). There are a handful of interesting interface methods here. |
+ |
+**On the IO thread** (*e.g.,* typically when working with process hosts that |
+aren't for render processes), the interesting methods are as follows: |
+ |
+[`IPC::Channel::GetAssociatedInterfaceSupport`](https://cs.chromium.org/chromium/src/ipc/ipc_channel.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=235) |
+returns an object for working with interfaces associated with the `Channel`. |
+This is never null. |
+ |
+[`IPC::Channel::AssociatedInterfaceSupport::AddAssociatedInterface<T>`]( |
+https://cs.chromium.org/chromium/src/ipc/ipc_channel.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=115) |
+allows you to add a binding function to handle all incoming requests for a |
+specific type of associated interface. Callbacks added here are called on the IO |
+thread any time a corresponding interface request arrives on the `Channel.` If |
+no callback is registered for an incoming interface request, the request falls |
+through to the Channel's `Listener` via |
+[`IPC::Listener::OnAssociatedInterfaceRequest`](https://cs.chromium.org/chromium/src/ipc/ipc_listener.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=40). |
+ |
+[`IPC::Channel::AssociatedInterfaceSupport::GetRemoteAssociatedInterface<T>`]( |
+https://cs.chromium.org/chromium/src/ipc/ipc_channel.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=124) |
+requests a Channel-associated interface from the remote endpoint of the channel. |
+ |
+**On the main thread**, typically when working with `RenderProcessHost`, basic |
+usage involves calls to |
+[`IPC::ChannelProxy::GetRemoteAssociatedInterface<T>`]( |
+https://cs.chromium.org/chromium/src/ipc/ipc_channel_proxy.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=196) |
+when making outgoing interface requests, or some implementation of |
+[`IPC::Listener::OnAssociatedInterfaceRequest`](https://cs.chromium.org/chromium/src/ipc/ipc_listener.h?rcl=a896ff44a395a50ab18f5120f20b7eb5a9550247&l=40) |
+when handling incoming ones. |
+ |
+TODO - Add docs for using AssociatedInterfaceRegistry where possible. |
+ |
+### BrowserMessageFilter |
+ |
+[BrowserMessageFilter](https://cs.chromium.org/chromium/src/content/public/browser/browser_message_filter.h?rcl=805f2ca5aa0902f56885ea3c8c0a42cb80d84522&l=37) |
+is a popular helper for listening to incoming legacy IPC messages on the browser |
+process IO thread and (typically) handling them there. |
+ |
+A common and totally reasonable tactic for converting a group of messages on an |
+existing `BrowserMessageFilter` is to define a similiarly named Mojom interface |
+in an inner `mojom` namespace (*e.g.,* a `content::FooMessageFilter` would have |
+a corresponding `content::mojom::FooMessageFilter` interface), and have the |
+`BrowserMessageFilter` implementation also implement |
+`BrowserAssociatedInterface<T>`. |
+ |
+Real code is probably the most useful explanation, so here are some example |
+conversion CLs which demonstrate practical `BrowserAssociatedInterface` usage. |
+ |
+[FrameHostMsg_SetCookie](https://codereview.chromium.org/2167513003) - This |
+CL introduces a `content::mojom::RenderFrameMessageFilter` interface |
+corresponding to the existing `content::RenderFrameMessageFilter` implementation |
+of `BrowserMessageFilter`. Of particular interest is the fact that it only |
+converts **one** of the messages on that filter. This is fine because ordering |
+among the messages -- Mojom or otherwise -- is unchanged. |
+ |
+[FrameHostMsg_GetCookie](https://codereview.chromium.org/2202723005) - A small |
+follow-up to the above CL, this converts another message on the same filter. It |
+is common to convert a large group of messages one-by-one in separate CLs. Also |
+note that this message, unlike the one above on the same interface, is |
+synchronous. |
+ |
+[ViewHostMsg_GenerateRoutingID](https://codereview.chromium.org/2351333002) - |
+Another small CL to introduce a new `BrowserAssociatedInterface`. |
+ |
+### Routed Per-Frame Messages To the Browser |
+ |
+Many legacy IPC messages are "routed" -- they carry a routing ID parameter which |
+is interpreted by the channel endpoint and used to pass a received message on to |
+some other more specific handler. |
+ |
+Messages received by the browser with a frame routing ID for example are routed |
+to the RenderFrameHost's owning [`WebContents`](https://cs.chromium.org/chromium/src/content/browser/web_contents/web_contents_impl.h?rcl=a12e52d81346dd23d8284763d44c4ee657f11cea&l=447) |
+with the corresponding `RenderFrameHostImpl` as additional context. |
+ |
+[This CL](https://codereview.chromium.org/2310583002) introduces usage of |
+[`WebContentsFrameBindingSet<T>`](https://cs.chromium.org/chromium/src/content/public/browser/web_contents_binding_set.h?rcl=d364139fee76154a1d9fa8875ad0cbb5ccb523c3&l=112), which helps establish |
+per-frame bindings for Channel-associated interfaces. Some hidden magic is done |
+to make it so that interface requests from a remote |
+[`RenderFrame AssociatedInterfaceProvider`](https://cs.chromium.org/chromium/src/content/public/renderer/render_frame.h?rcl=d364139fee76154a1d9fa8875ad0cbb5ccb523c3&l=170) |
+are routed to the appropriate `WebContentsFrameBindingSet`, typically installed |
+(as in this CL) by a `WebContentsObserver`. |
+ |
+When a message is received by an interface implementation using a |
+`WebContentsFrameBindingSet`, that object's `dispatch_context()` can be used |
+to retrieve the `RenderFrameHostImpl` targeted by the message. See the above CL |
+for additional clarity. |
+ |
+### Other Routed Messages To the Browser |
+ |
+Other routing IDs are used when targeting either specific `RenderViewHost` or |
+`RenderWidgetHost` instances. We don't currently have any facilities in place |
+to assist with these conversions. Because render views are essentially a |
+deprecated concept, messages targeting "view" routes should not be converted |
+as-is, but should instead be moved to target either widgets or frames |
+accordingly. |
+ |
+Facilities to assist in conversion of widget-routed messages may be added in the |
+future. Who knows, maybe you'll be the brave developer to add them (and to then |
+update this documentation, of course!) If you decide this is exactly what you |
+need but are nervous about the prospect of writing it yourself, please send a |
+friendly message to [chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo) |
+explaining the use case so we can help you get things done. |
+ |
+### Messages to a Renderer |
+ |
+[This CL](https://codereview.chromium.org/2381493003) converts `ViewMsg_New` |
+to a Mojo interface, by virtue of the fact that |
+`IPC::ChannelProxy::GetRemoteAssociatedInterface` from the browser process |
+results in an associated interface request arriving at |
+`ChildThreadImpl::OnAssociatedInterfaceRequest` in the corresponding child |
+process. |
+ |
+Similar message conversions are done by [this CL](https://codereview.chromium.org/2400313002). |
+ |
+Note that we do not currently have any helpers for converting routed messages |
+from browser to renderer. Please confer with |
+[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo) |
+if such a use case is blocking your work. |
+ |
+## Miscellany |
+ |
+### Using Legacy IPC Traits |
+ |
+InsSome circumstances there may be a C++ enum, struct, or class that you want |
+to use in a Mojom via [type mapping](/mojo/public/cpp/bindings#Type-Mapping), |
+and that type may already have `IPC::ParamTraits` defined (possibly via |
+`IPC_STRUCT_TRAITS*` macros) for legacy IPC. |
+ |
+If this is the case and the Mojom which uses the type will definitely only be |
+called from and implemented in C++ code, *and* you have sufficient reason to |
+avoid moving or duplicating the type definition in Mojom, you can take advantage |
+of the existing `ParamTraits`. |
+ |
+#### The [Native] Attribute |
+In order to do this you must declare a placeholder type in Mojom somewhere, like |
+so: |
+ |
+``` |
+module foo.mojom; |
+ |
+[Native] |
+enum WindowType; |
+ |
+[Native] |
+struct MyGiganticStructure; |
+``` |
+ |
+The rest of your Mojom will use this typename when referring to the type, but |
+the wire format used is defined entirely by `IPC::ParamTraits<T>` for whatever |
+`T` to which you typemap the Mojom type. For example if you typemap |
+`foo::mojom::MyGiganticStructure` to `foo::MyGiganticStructure`, your typemap |
+must point to some header which defines |
+`IPC::ParamTraits<foo::MyGiganticStructure>`. |
+ |
+Note that if your `ParamTraits` are defined manually (*i.e.* not by invocation |
+of `IPC_STRUCT_TRAITS*` macros) you must also ensure that they define the new |
+`GetSize` method: |
+ |
+``` cpp |
+static void GetSize(base::PickleSizer* sizer, const param_type& p) { |
+ // ... |
+} |
+``` |
+ |
+`base::PickleSizer` has an interface analogous to `base::Pickle`, except that it |
+merely accumulates a byte count rather than accumulating serialized data. |
+ |
+There are several examples of this traits implementation in common IPC traits |
+defined [here](https://code.google.com/p/chromium/codesearch#chromium/src/ipc/ipc_message_utils.h). |
+ |
+#### A Practical Example |
+ |
+Given the [`resource_messages.h`](https://cs.chromium.org/chromium/src/content/common/resource_messages.h?rcl=2e7a430d8d88222c04ab3ffb0a143fa85b3cec5b&l=215) |
+header with the following definition: |
+ |
+``` cpp |
+IPC_STRUCT_TRAITS_BEGIN(content::ResourceRequest) |
+ IPC_STRUCT_TRAITS_MEMBER(method) |
+ IPC_STRUCT_TRAITS_MEMBER(url) |
+ // ... |
+IPC_STRUCT_TRAITS_END() |
+``` |
+ |
+and the [`resource_request.h`](https://cs.chromium.org/chromium/src/content/common/resource_request.h?rcl=dce9e476a525e4ff0304787935dc1a8c38392ac8&l=32) |
+header with the definition for `content::ResourceRequest`: |
+ |
+``` cpp |
+namespace content { |
+ |
+struct CONTENT_EXPORT ResourceRequest { |
+ // ... |
+}; |
+ |
+} // namespace content |
+``` |
+ |
+we can declare a corresponding Mojom type: |
+ |
+``` |
+module content.mojom; |
+ |
+[Native] |
+struct URLRequest; |
+``` |
+ |
+and add a typemap like [url_request.typemap](https://cs.chromium.org/chromium/src/content/common/url_request.typemap) |
+to define the mapping: |
+ |
+``` |
+mojom = "//content/common/url_loader.mojom" |
+public_headers = [ "//content/common/resource_request.h" ] |
+traits_headers = [ "//content/common/resource_messages.h" ] |
+... |
+type_mappings = [ "content.mojom.URLRequest=content::ResourceRequest" ] |
+``` |
+ |
+Note specifically that `public_headers` includes the definition of the native |
+C++ type, and `traits_headers` includes the definition of the legacy IPC traits. |
+ |
+Finally, note that this same approach can be used to leverage existing |
+`IPC_ENUM_TRAITS` for `[Native]` Mojom enum aliases. |
+ |
+### Typemaps With Content and Blink Types |
+ |
+Using typemapping for messages that go between Blink and content browser code |
+can sometimes be tricky due to things like dependency cycles or confusion over |
+the correct place for some definition to live. There are some example |
+CLs provided here, but feel free to also contact |
+[chromium-mojo@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-mojo) |
+with specific details if you encounter trouble. |
+ |
+[This CL](https://codereview.chromium.org/2363533002) introduces a Mojom |
+definition and typemap for |
+`ui::WindowOpenDisposition` as a precursor to the IPC conversion below. |
+ |
+The [follow-up CL](https://codereview.chromium.org/2363573002) uses that |
+definition along with several other new typemaps (including native typemaps as |
+described above in [Using Legacy IPC Traits](#Using-Legacy-IPC-Traits)) to |
+convert the relatively large `ViewHostMsg_CreateWindow` message to Mojo. |
+ |
+### Utility Process Messages |
+ |
+Given that there are no interesting ordering dependencies among disparate IPC |
+messages to and from utility processes, and because the utility process is |
+already sort of a mixed bag of unrelated IPCs, the correct way to convert |
+utility process IPCs to Mojo is to move them into services. |
+ |
+We already have support for running services out-of-process (with or without a |
+sandbox), and many utility process operations already have a suitable service |
+home they could be moved to. For example, the `data_decoder` service in |
+[`//services/data_decoder`](https://cs.chromium.org/chromium/src/services/data_decoder/) |
+is a good place to stick utility process IPCs that do decoding of relatively |
+complex and untrusted data, of which (at the time of this writing) there are |
+quite a few. |
+ |
+When in doubt, contact |
+[`services-dev@chromium.org`](https://groups.google.com/a/chromium.org/forum/#!forum/services-dev) |
+with ideas, questions, suggestions, etc. |
+ |
+### Additional Documentation |
+ |
+[Chrome IPC to Mojo IPC Cheat Sheet](https://www.chromium.org/developers/design-documents/mojo/chrome-ipc-to-mojo-ipc-cheat-sheet) |
+: A slightly dated but still valuable document covering some details |
+ regarding the conceptual mapping between legacy IPC and Mojo. |
+ |
+[Mojo Migration Guide](https://www.chromium.org/developers/design-documents/mojo/mojo-migration-guide) |
+: Another slightly (more) data document covering the basics of IPC conversion |
+ to Mojo. |
+ |
+ TODO: The migration guide above should probably be deleted and the good |
+ parts merged into this document. |