| # Mojo "Style" Guide | 
 |  | 
 | Mojo is Chrome's new IPC system and provides lots of useful abstractions. These | 
 | abstractions can make it easier to write code that makes interprocess calls, | 
 | but can also add significant complexity. Below are some recommendation from | 
 | Mojo and IPC reviewers for best practices. | 
 |  | 
 | For questions, concerns, or suggestions, reach out to <mojo@chromium.org>. | 
 |  | 
 | > For legacy IPC, please see [security tips for IPC][security-tips-for-ipc]. | 
 |  | 
 | [TOC] | 
 |  | 
 |  | 
 | ## Simplicity | 
 |  | 
 | Strive to write simple interfaces. Minimize the amount of cross-process state | 
 | that needs to be maintained in sync. | 
 |  | 
 | **_Good_** | 
 |  | 
 | ```c++ | 
 | interface TeleporterFactory { | 
 |   Create(Location start, Location end) => (Teleporter); | 
 | }; | 
 |  | 
 | interface Teleporter { | 
 |   TeleportGoat(Goat) = (); | 
 | }; | 
 | ``` | 
 |  | 
 | **_Bad_** | 
 |  | 
 | ```c++ | 
 | interface Teleporter { | 
 |   // Bad: comments will need to explicitly call out that both locations need to | 
 |   // be bound before calling TeleportGoat()! | 
 |   // | 
 |   // In addition, if untrustworthy processes can talk to trustworthy processes, | 
 |   // the Teleporter implementation will need to also handle the case where the | 
 |   // Location objects are not yet bound. | 
 |   SetStart(Location); | 
 |   SetEnd(Location); | 
 |   TeleportGoat(Goat) = (); | 
 | }; | 
 | ``` | 
 |  | 
 | Similarly, strive to make methods focused. Do not overuse optional types. | 
 |  | 
 | **_Good_** | 
 |  | 
 | ```c++ | 
 | struct TeleporterStats { | 
 |   AnimalStats animal_stats; | 
 |   FungiStats fungi_stats; | 
 |   GoatStats goat_stats; | 
 |   PlantStats plant_stats; | 
 | }; | 
 |  | 
 | interface Teleporter { | 
 |   TeleportAnimal(Animal) => (); | 
 |   TeleportFungi(Fungi) => (); | 
 |   TeleportGoat(Goat) = (); | 
 |   TeleportPlant(Plant) => (); | 
 |  | 
 |   // TeleportStats is only non-null if success is true. | 
 |   GetStats() => (bool success, TeleporterStats?); | 
 | }; | 
 | ``` | 
 |  | 
 | **_Bad_** | 
 |  | 
 | ```c++ | 
 | interface Teleporter { | 
 |   // The intent of four optional arguments is unclear: can this call teleport | 
 |   // multiple objects of different types at once, or is the caller only | 
 |   // supposed to only pass one non-null argument per call? | 
 |   Teleport(Animal?, Fungi?, Goat?, Plant?) => (); | 
 |  | 
 |   // Does this return all stats if sucess is true? Or just the categories that | 
 |   // the teleporter already has stats for? The intent is uncertain, so wrapping | 
 |   // the disparate values into a result struct would be cleaner. | 
 |   GetStats() => | 
 |       (bool success, AnimalStats?, FungiStats?, PlantStats?, FungiStats?); | 
 | }; | 
 | ``` | 
 |  | 
 |  | 
 | ## Documentation | 
 |  | 
 | Mojo structs, interfaces, and methods should all have comments. Make sure the | 
 | comments cover the "how" and the "why" of using an interface and its methods, | 
 | and not just the "what". Document preconditions, postconditions, and trust: if | 
 | an interface is implemented in the browser process and handles requests from | 
 | the renderer process, this should be mentioned in the comments. Complex features | 
 | should also have an external `README.md` that covers the high-level flow of | 
 | information through interfaces and how they interact to implement the feature. | 
 |  | 
 | **_Good_** | 
 |  | 
 | ```c++ | 
 | // Interface for controlling a teleporter. Lives in the browser process, and | 
 | // used to implement the Teleportation over Mojo IPC RFC. | 
 | interface Teleporter { | 
 |   // Teleportation helpers for different taxonomic kingdoms. Teleportation is | 
 |   // not complete until the reply callback is invoked. The caller must NOT | 
 |   // release the sender side resources until the reply callback runs; releasing | 
 |   // the resources early will cause splinching. | 
 |   TeleportAnimal(Animal) => (); | 
 |   TeleportFungi(Fungi) => (); | 
 |   // Goats require a specialized teleportation channel distinct from | 
 |   // TeleportAnimal to ensure goatiness isolation. | 
 |   TeleportGoat(Goat) => (); | 
 |   TeleportPlant(Plant) => (); | 
 |  | 
 |   // Returns current teleportation stats. On failure (e.g. a teleportation | 
 |   // operation is currently in progress) success will be false and a null stats | 
 |   // object will be returned. | 
 |   GetStats() => | 
 |       (bool success, TeleportationStats?); | 
 | }; | 
 | ``` | 
 |  | 
 |  | 
 | ## Security | 
 |  | 
 | Policy should be controlled solely by the browser process. "Policy" can mean | 
 | any number of things, such as sizes, addresses, permissions, URLs, origins, | 
 | etc. In an ideal world: | 
 |  | 
 | 1.  Unprivileged process asks for a capability from the privileged process that | 
 |     owns the resource. | 
 | 1.  Privileged process applies policy to find an implementation for the | 
 |     capability. | 
 | 1.  Unprivileged process performs operations on the capability, constrained in | 
 |     scope. | 
 |  | 
 | The privileged process must own the capability lifecycle. | 
 |  | 
 |  | 
 | ### Do not trust less privileged processes | 
 |  | 
 | This is the overriding principle for all guidelines in this section. When | 
 | receiving data from a less trusted process, treat the data as if it were | 
 | generated by a malicious adversary. Message handlers cannot assume that offsets | 
 | are valid, calculations won't overflow, et cetera. | 
 |  | 
 | In general: | 
 |  | 
 | *   the browser process is the most privileged process type and therefore, must | 
 |     be maximally suspicious of its IPC inputs | 
 | *   the renderer and the ARC++ processes are the least privileged and least | 
 |     trustworthy process types | 
 | *   other process types, such as GPU and plugin, fall in between | 
 |  | 
 | When passing objects up a privilege gradient (from less → more privileged), the | 
 | callee must validate the inputs before acting on them. When passing objects | 
 | down a privilege gradient, such as from browser → renderer, it is OK for the | 
 | callee to trust the caller. | 
 |  | 
 | > See also: [Do not Handle Impossible Situations](#Do-not-handle-impossible-situations) | 
 |  | 
 |  | 
 | ### Do not send unnecessary or privilege-presuming data | 
 |  | 
 | > Note: there is currently work in progress to associate origins with the | 
 | > `InterfaceProvider`s for frames and workers: <https://crbug.com/734210> and | 
 | > <https://crbug.com/775792/>. | 
 |  | 
 | For example, the browser process must not (fully) trust the renderer's claims | 
 | about origins. The browser process should already know what origin the renderer | 
 | is evaluating, and thus should already have this data (for example, see | 
 | `RenderFrameHost::GetLastCommittedOrigin()`). Thus, a method that requires | 
 | passing an origin from the renderer to the browser process has a conceptual | 
 | error, and quite possibly, a vulnerability. | 
 |  | 
 | > Note: there are currently subtle races when using `GetLastCommittedOrigin()` | 
 | > that will be resolved by fixing <https://crbug.com/729021>. | 
 |  | 
 | Similarly, the browser process must not trust the renderer's claims about file | 
 | pathnames. It would be unsafe for the browser process to save a downloaded file | 
 | to `~/.bashrc` just because the renderer asked. Instead, it would be better for | 
 | the browser process to: | 
 |  | 
 | 1.  Kill the renderer if `basename(pathname) != pathname`, since the renderer is | 
 |     obviously compromised if it makes this mistake. | 
 | 1.  Defang the basename, by removing leading dots, et cetera. Note that the | 
 |     definition of proper defanging varies per platform. | 
 | 1.  Prepend its own parent directory to the basename, e.g. ~/Downloads. | 
 |  | 
 | > TODO(https://crbug.com/779196): Even better would be to implement a C++ type | 
 | > performs the appropriate sanitizations and recommend its usage directly here. | 
 |  | 
 |  | 
 | ### Do not define unused or unimplemented things | 
 |  | 
 | Mojo interfaces often cross privilege boundaries. Having well-defined interfaces | 
 | that don't contain stubbed out methods or unused parameters makes it easier to | 
 | understand and evaluate the implications of crossing these boundaries. Several | 
 | common areas to watch out for: | 
 |  | 
 |  | 
 | #### Do use EnableIf to guard platform-specific constructs | 
 |  | 
 | Platform-specific functionality should only be defined on the platforms where | 
 | it is implemented. Use the Mojo `EnableIf` annotation to guard definitions that | 
 | should only be visible in certain build configurations. | 
 |  | 
 | **_Good_** | 
 | ```c++ | 
 | // GN file: | 
 | mojom("view_bindings") { | 
 |   // ... | 
 |  | 
 |   enabled_features = [] | 
 |   if (is_android) { | 
 |     enabled_features += [ "is_android" ]; | 
 |   } | 
 | } | 
 |  | 
 | // mojom definition: | 
 | interface View { | 
 |   // ... | 
 |  | 
 |   [EnableIf=is_android] | 
 |   UpdateBrowserControlsState(bool enable_hiding, bool enable_showing, | 
 |                              bool animate); | 
 | }; | 
 |  | 
 | // C++ implementation: | 
 | class View : public mojom::View { | 
 |  public: | 
 |   // ... | 
 |  | 
 | #if defined(OS_ANDROID) | 
 |   void UpdateBrowserControlsState(bool enable_hiding, bool enable_showing, | 
 |                                   bool animate); | 
 | #endif | 
 | }; | 
 | ``` | 
 |  | 
 | **_Bad_** | 
 | ```c++ | 
 | // mojom definition: | 
 | interface View { | 
 |   // ... | 
 |  | 
 |   UpdateBrowserControlsState(bool enable_hiding, bool enable_showing, | 
 |                              bool animate); | 
 | }; | 
 |  | 
 | // C++ implementation: | 
 | class View : public mojom::View { | 
 |  public: | 
 |   // ... | 
 |  | 
 | #if defined(OS_ANDROID) | 
 |   void UpdateBrowserControlsState(bool enable_hiding, bool enable_showing, | 
 |                                   bool animate) override; | 
 | #else | 
 |   void UpdateBrowserControlsState(bool enable_hiding, bool enable_showing, | 
 |                                   bool animate) override { | 
 |     NOTREACHED(); | 
 |   } | 
 | #endif | 
 | }; | 
 | ``` | 
 |  | 
 | The `EnableIf` annotation can be applied to almost anything: imports, | 
 | interfaces, methods, arguments, constants, structs, struct members, enums, | 
 | enumerator values, et cetera. | 
 |  | 
 |  | 
 | #### Do not define unimplemented methods | 
 |  | 
 | Reviewing IPC requires reviewing a concrete implementation of the Mojo | 
 | interface, to evaluate how the (possibly untrustworthy) inputs are used, what | 
 | outputs are produced, et cetera. If a method is not yet implemented, do not | 
 | define it in the interface. | 
 |  | 
 | **_Bad_** | 
 | ```c++ | 
 | // mojom definition: | 
 | interface Spaceship { | 
 |   EnterHyperspace(); | 
 |   ExitHyperspace(); | 
 | }; | 
 |  | 
 | // C++ implementation: | 
 | class SpaceshipPrototype : public mojom::Spaceship { | 
 |   void EnterHyperspace() { /* TODO(dcheng): Implement. */ } | 
 |   void ExitHyperspace() { /* TODO(dcheng): Implement. */ } | 
 | }; | 
 | ``` | 
 |  | 
 |  | 
 | #### Do not define placeholder enumerator values | 
 |  | 
 | Do not define placeholder enumerator values like `kLast`, `kMax`, `kCount`, et | 
 | cetera. Instead, rely on the autogenerated `kMaxValue` enumerator emitted for | 
 | Mojo C++ bindings. | 
 |  | 
 | For UMA histograms, logging a Mojo enum is simple: simply use the two argument | 
 | version of `UMA_HISTOGRAM_ENUMERATION`: | 
 |  | 
 | **_Good_** | 
 | ```c++ | 
 | // mojom definition: | 
 | enum GoatStatus { | 
 |   kHappy, | 
 |   kSad, | 
 |   kHungry, | 
 |   kGoaty, | 
 | }; | 
 |  | 
 | // C++: | 
 | UMA_HISTOGRAM_ENUMERATION("Goat.Status", status); | 
 | ``` | 
 |  | 
 | Using a `kCount` sentinel complicates `switch` statements and makes it harder to | 
 | enforce invariants: code needs to actively enforce that the otherwise invalid | 
 | `kCount` sentinel value is not incorrectly passed around. | 
 |  | 
 | **_Bad_** | 
 | ```c++ | 
 | // mojom definition: | 
 | enum CatStatus { | 
 |   kAloof, | 
 |   kCount, | 
 | }; | 
 |  | 
 | // C++ | 
 | switch (cat_status) { | 
 |   case CatStatus::kAloof: | 
 |     IgnoreHuman(); | 
 |     break; | 
 |   case CatStatus::kCount: | 
 |     // this should never happen | 
 | } | 
 | ``` | 
 |  | 
 | Defining `kLast` manually results in ugly casts to perform arithmetic: | 
 |  | 
 | **_Bad_** | 
 | ```c++ | 
 | // mojom definition: | 
 | enum WhaleStatus { | 
 |   kFail, | 
 |   kNotFail, | 
 |   kLast = kNotFail, | 
 | }; | 
 |  | 
 | // C++: | 
 | UMA_HISTOGRAM_ENUMERATION("Whale.Status", status, | 
 |                           static_cast<int>(WhaleStatus::kLast) + 1); | 
 | ``` | 
 |  | 
 | For interoperation with legacy IPC, also use `kMaxValue` rather than defining a | 
 | custom `kLast`: | 
 |  | 
 | **_Good_** | 
 | ```c++ | 
 | IPC_ENUM_TRAITS_MAX_VALUE(GoatStatus, GoatStatus::kMaxValue); | 
 | ``` | 
 |  | 
 |  | 
 | ### Use structured types | 
 |  | 
 | Where possible, use structured types: this allows the type system to help | 
 | enforce that the input data is valid. Common ones to watch out for: | 
 |  | 
 | *   Files: use `mojo_base.mojom.File`, not raw descriptor types like `HANDLE` | 
 |     and `int`. | 
 | *   File paths: use `mojo_base.mojom.FilePath`, not `string`. | 
 | *   JSON: use `mojo_base.mojom.Value`, not `string`. | 
 | *   Mojo interfaces: use `Interface` or `Interface&`, not `handle` or | 
 |     `handle<message_pipe>`. | 
 | *   Nonces: use `mojo_base.mojom.UnguessableToken`, not `string`. | 
 | *   Origins: use `url.mojom.Origin`, not `url.mojom.Url` and certainly not | 
 |     `string`. | 
 | *   Time types: use `mojo_base.mojom.TimeDelta` / | 
 |     `mojo_base.mojom.TimeTicks` / `mojo_base.mojom.Time`, not `int64` / | 
 |     `uint64` / `double` / et cetera. | 
 | *   URLs: use `url.mojom.Url`, not `string`. | 
 |  | 
 | **_Good_** | 
 |  | 
 | ```c++ | 
 | interface ReportingService { | 
 |   ReportDeprecation(mojo_base.mojom.TimeTicks time, | 
 |                     url.mojom.Url resource, | 
 |                     uint32 line_number); | 
 | }; | 
 | ``` | 
 |  | 
 | **_Bad_** | 
 |  | 
 | ```c++ | 
 | interface ReportingService { | 
 |   // Bad: unclear what units |time| is or what |data| contains. | 
 |   ReportDeprecation(double time, mojo_base.mojom.Value data); | 
 | }; | 
 | ``` | 
 |  | 
 | Another anti-pattern to avoid is parallel arrays of data: this requires the | 
 | receiver to validate that all the arrays have the same length. Instead, prefer | 
 | to pass the data so that it is impossible to have a mismatch. | 
 |  | 
 | **_Good_** | 
 |  | 
 | ```c++ | 
 | struct Pixel { | 
 |   int8 reds; | 
 |   int8 greens; | 
 |   int8 blues; | 
 |   int8 alphas; | 
 | }; | 
 |  | 
 | struct Bitmap { | 
 |   // Good: it is impossible for there to be mismatched data. | 
 |   array<Pixel> pixels; | 
 | }; | 
 | ``` | 
 |  | 
 | **_Bad_** | 
 |  | 
 | ```c++ | 
 | // Bad: code using this struct will need to validate that all the arrays have | 
 | // matching sizes. | 
 | struct Bitmap { | 
 |   array<int8> reds; | 
 |   array<int8> greens; | 
 |   array<int8> blues; | 
 |   array<int8> alphas; | 
 | }; | 
 | ``` | 
 |  | 
 |  | 
 | ### Beware of arithmetic overflow | 
 |  | 
 | > TODO(dcheng): Import the guidance from the legacy IPC doc. | 
 |  | 
 | Signed overflow is undefined in C++. If unsure about whether or not something | 
 | will overflow, use the safe numeric helpers from `//base/numerics`! | 
 |  | 
 | **_Good_** | 
 |  | 
 | ```c++ | 
 | base::CheckedNumeric<int32_t> size = mojo_rect->width(); | 
 | size *= mojo_rect.height(); | 
 | if (!size.IsValid()) { | 
 |   mojo::ReportBadMessage("Bad size from renderer!"); | 
 | } | 
 | ``` | 
 |  | 
 | **_Bad_** | 
 |  | 
 | ```c++ | 
 | // Bad: Signed overflow is undefined in C++! | 
 | int32_t size = mojo_rect->width() * mojo_rect.height(); | 
 | ``` | 
 |  | 
 | Note that even if the types have defined overflow semantics, it is almost always | 
 | a good idea to check for overflow. | 
 |  | 
 | **_Good_** | 
 |  | 
 | ```c++ | 
 | uint32_t alloc_size; | 
 | if (!CheckMul(request->elements(), request->element_size()) | 
 |          .AssignIfValid(&alloc_size)) { | 
 |   // Safe: avoids allocating with a bogus size that overflowed to a smaller than | 
 |   // expected value. | 
 |   mojo::ReportBadMessge("Invalid allocation size"); | 
 | } | 
 |  | 
 | Element* array = CreateArray(alloc_size); | 
 | for (size_t i = 0; i < request->element_size(); ++i) { | 
 |   array[i] = PopulateArray(i); | 
 | } | 
 | ``` | 
 |  | 
 | **_Bad_** | 
 |  | 
 | ```c++ | 
 | uint32_t alloc_size = request->elements() * request->element_size(); | 
 |  | 
 | // Dangerous: alloc_size can overflow so that CreateArray allocates too little | 
 | // memory. Subsequent assignments will turn into an out-of-bound write! | 
 | Element* array = CreateArray(alloc_size); | 
 | for (size_t i = 0; i < request->element_size(); ++i) { | 
 |   array[i] = PopulateArray(i); | 
 | } | 
 | ``` | 
 |  | 
 |  | 
 | ## C++ Best Practices | 
 |  | 
 |  | 
 | ### Use mojo::WrapCallbackWithDefaultInvokeIfNotRun And mojo::WrapCallbackWithDropHandler sparingly | 
 |  | 
 | Mojo provides several convenience helpers to automatically invoke a callback if | 
 | the callback has not already been invoked in some other way when the callback is | 
 | destroyed, e.g.: | 
 |  | 
 | ```c++ | 
 |   { | 
 |     base::Callback<int> cb = mojo::WrapCallbackWithDefaultInvokeIfNotRun( | 
 |         base::Bind([](int) { ... }), -1); | 
 |   }  // |cb| is automatically invoked with an argument of -1. | 
 | ``` | 
 |  | 
 | This can be useful for detecting interface errors: | 
 |  | 
 | ```c++ | 
 |   process->GetMemoryStatistics( | 
 |       mojo::WrapCallbackWithDefaultInvokeIfNotRun( | 
 |           base::Bind(&MemoryProfiler::OnReplyFromRenderer), <failure args>)); | 
 |   // If the remote process dies, &MemoryProfiler::OnReplyFromRenderer will be | 
 |   // invoked with <failure args> when Mojo drops outstanding callbacks due to | 
 |   // a connection error on |process|. | 
 | ``` | 
 |  | 
 | However, due to limitations of the current implementation, it's difficult to | 
 | tell if a callback object has invoke-on-destroy behavior. In general: | 
 |  | 
 | 1.  Prefer error connection handlers where possible. | 
 | 1.  Only use the callback helpers for detecting interface errors. These | 
 |     callbacks may be invoked during destruction and must carefully consider | 
 |     receiver object lifetime. For more information, please see the | 
 |     [Mojo documentation][mojo-doc-process-crashes]. | 
 |  | 
 | > Note that using the callback wrappers in the renderer is often unnecessary. | 
 | > Message pipes are typically closed as part of a Document shutting down; since | 
 | > many Blink objects already inherit `blink::ContextLifecycleObserver`, it is | 
 | > usually more idiomatic to use this signal to perform any needed cleanup work. | 
 |  | 
 | ### Use StructTraits | 
 |  | 
 | Creating a typemap and defining a `StructTraits` specialization moves the | 
 | complexity of serialization, deserialization, and validation into a central | 
 | location. We universally recommend this over defining `TypeConverter` | 
 | specializations: when a value fails deserialization, the receiver method will | 
 | never even be invoked. As a bonus, it also reduces the number of copies during | 
 | serialization and deserialization. 😄 | 
 |  | 
 | **_Good_** | 
 |  | 
 | ```c++ | 
 | // In url_gurl_mojom_traits.h: | 
 | template <> | 
 | struct StructTraits<url::mojom::UrlDataView, GURL> { | 
 |   static base::StringPiece url(const GURL& r); | 
 |  | 
 |   // If Read() returns false, Mojo will discard the message. | 
 |   static bool Read(url::mojom::UrlDataView data, GURL* out); | 
 | }; | 
 |  | 
 | // In url_gurl_mojom_traits.cc: | 
 | // Note that methods that aren't simple getters should be defined | 
 | // out-of-line to avoid code bloat. | 
 | base::StringPiece StructTraits<url::mojom::UrlDataView, GURL>::url( | 
 |     const GURL& r) { | 
 |   if (r.possibly_invalid_spec().length() > url::kMaxURLChars || | 
 |       !r.is_valid()) { | 
 |     return base::StringPiece(); | 
 |   } | 
 |   return base::StringPiece(r.possibly_invalid_spec().c_str(), | 
 |                            r.possibly_invalid_spec().length()); | 
 | } | 
 |  | 
 | bool StructTraits<url::mojom::UrlDataView, GURL>::Read( | 
 |     url::mojom::UrlDataView data, GURL* out) { | 
 |   base::StringPiece url_string; | 
 |   if (!data.ReadUrl(&url_string)) | 
 |     return false; | 
 |   if (url_string.length() > url::kMaxURLChars) | 
 |     return false; | 
 |   *out = GURL(url_string); | 
 |   return !url_string.empty() && out->is_valid(); | 
 | } | 
 | ``` | 
 |  | 
 | **_Bad_** | 
 |  | 
 | ```c++ | 
 | template <> | 
 | struct TypeConverter<url::mojom::UrlPtr, GURL> { | 
 |   // Inefficient: this copies data once off the wire to create a | 
 |   // url.mojom.Url object, then copies it again to create a GURL. | 
 |   static GURL Convert(const url::mojom::UrlPtr url) { | 
 |     if (url.url.is_empty()) return GURL(); | 
 |     // Not good: no way to signal errors, so any code that converts the | 
 |     // Mojo struct to a GURL will somehow need to check for errors… | 
 |     // but it can't even be distinguished from the empty URL case! | 
 |     if (url.url.size() > url::kMaxURLChars) return GURL(); | 
 |     return GURL(url.url); | 
 |   } | 
 | }; | 
 | ``` | 
 |  | 
 | There are also corresponding `EnumTraits` and `UnionTraits` specializations for | 
 | mojo enums and unions respectively. | 
 |  | 
 |  | 
 | ### StructTraits getters should be simple | 
 |  | 
 | Where possible, `StructTraits` should be returning const references or simple | 
 | read-only views of the data. Having to create temporary data structures during | 
 | serialization should be rare, and it should be even rarer to mutate the input | 
 | argument. | 
 |  | 
 |  | 
 | ### Out-of-line complex serialization/deserialization logic | 
 |  | 
 | A `StructTraits` specialization is almost always fully specialized. Only define | 
 | `StructTraits` methods inline in the header if the method is a simple getter | 
 | that returns a reference, pointer, or other simple POD. Define all other | 
 | methods out-of-line to avoid code bloat. | 
 |  | 
 |  | 
 | ### Do not write one-off functions to convert to/from Mojo types | 
 |  | 
 | There are some instances where it is simply not possible to define a | 
 | `StructTraits` for type mapping: this commonly occurs with Blink IDL and Oilpan | 
 | types. In these instances, add a `TypeConverter` specialization rather than | 
 | defining a one-off conversion function. This makes it easier to search for and | 
 | audit code that does potentially risky type conversions. | 
 |  | 
 | > The use of `TypeConverter` should be limited as much as possible: ideally, | 
 | > only use it in renderers. | 
 |  | 
 | **_Good_** | 
 |  | 
 | ```c++ | 
 | template <> | 
 | struct TypeConverter<IDLDictionary, mojom::blink::DictionaryPtr> { | 
 |   static IDLDictionary* Convert(const mojom::blink::DictionaryPtr& in) { | 
 |     // Note that unlike StructTraits, there is no out-of-band way to signal | 
 |     // failure. | 
 |     IDLDictionary* out = new IDLDictionary; | 
 |     out->int_value = in->int_value; | 
 |     out->str_value = in->str_value; | 
 |     return out; | 
 |   } | 
 | }; | 
 | ``` | 
 |  | 
 | **_Bad_** | 
 |  | 
 | ```c++ | 
 | // Using a custom one-off function makes this hard to discover in security | 
 | // audits. | 
 | IDLDictionary* FromMojo(const mojom::blink::DictionaryPtr& in) { | 
 |   IDLDictionary* out = new IDLDictionary; | 
 |   out->int_value = in->int_value; | 
 |   out->str_value = in->str_value; | 
 |   return out; | 
 | } | 
 | ``` | 
 |  | 
 |  | 
 | ### Use the proper abstractions | 
 |  | 
 | `mojo::BindingSet` implies multiple clients may connect. If this actually isn't | 
 | the case, please do not use it. For example, if an interface can be rebound, | 
 | then use the singular `mojo::Binding` and simply `Close()` the existing binding | 
 | before reusing it. | 
 |  | 
 |  | 
 | ### Explicitly reject bad input | 
 |  | 
 | While validation should be done inside `StructTraits` specializations when | 
 | possible, there are situations where additional checks, e.g. overflow checks, | 
 | are needed outside of `StructTraits` specializations. Use | 
 | `mojo::ReportBadMessage()` or `mojo::GetBadMessageCallback()` to reject bad | 
 | input in these situations. Under the hood, this may record UMAs, kill the | 
 | process sending bad input, et cetera. | 
 |  | 
 | *   `mojo::ReportBadMessage()`: use to report bad IPC input while a message is | 
 |     being dispatched on the stack. | 
 | *   `mojo::GetBadMessageCallback()`: use to generate a callback to report bad | 
 |     IPC input. The callback must be generated while a message is being | 
 |     dispatched on the stack; however, the returned callback may be invoked be | 
 |     freely invoked in asynchronously posted callbacks. | 
 |  | 
 |  | 
 | ## Java Best Practices | 
 |  | 
 | Unfortunately, there are no strongly established conventions here. Most code | 
 | tends to write manual conversion helpers and throw an exception on conversion | 
 | failure. See [NfcTypeConverter.java] as one example of how to write conversion | 
 | code. | 
 |  | 
 |  | 
 | ## General Code Health | 
 |  | 
 |  | 
 | ### Naming Conventions | 
 |  | 
 | Place mojo types in `<top-level namespace>.mojom`. Directories for Mojo traits | 
 | should be named `mojom` (preferable) or `ipc`. Legacy names that are also | 
 | encountered are `public/interfaces`, `interfaces`, or just `mojo`. | 
 |  | 
 | `mojom` is preferred for consistency between the directory name and the nested | 
 | namespace name. | 
 |  | 
 |  | 
 | ### Do not handle impossible situations | 
 |  | 
 | Do not clutter the code by handling impossible situations. Omitting it makes | 
 | the invariants clear. This takes two different forms: | 
 |  | 
 | *   A less trustworthy process can be compromised by an adversary and send | 
 |     arbitrary data. When processing data from a less trustworthy process, do | 
 |     not attempt to handle this invalid data: just call | 
 |     `mojo::ReportBadMessage()`. When invoked in the context of processing an | 
 |     IPC from the renderer, this will kill the renderer process. | 
 | *   A more trustworthy process must be trusted, by definition. Do not write | 
 |     code to handle impossible situations "just in case" there's a bug. For | 
 |     example, the renderer class `content::RenderFrameImpl` must always be | 
 |     connected to certain control interfaces in the browser. It does not makes | 
 |     sense to handle a Mojo connection error and try to reconnect: a connection | 
 |     error signals that the browser process is in the process of deleting the | 
 |     frame, and any attempt at reconnecting will never succeed. | 
 |  | 
 |  | 
 | ### Using mojo enums directly when possible | 
 |  | 
 | `EnumTraits` generally do not add much value: incoming Mojo enum values are | 
 | already validated before typemapping, so it is guaranteed that the input value | 
 | to `EnumTraits<T>::FromMojom()` is already a valid enum value, so the method | 
 | itself is just a bunch of boilerplate to map between two very similarly named, | 
 | yet slightly different, enums. | 
 |  | 
 | To avoid this, prefer to use the Mojo enum directly when possible. | 
 |  | 
 |  | 
 | ### Consider the cost of setting up message pipes | 
 |  | 
 | Message pipes are fairly inexpensive, but they are not free either: it takes 6 | 
 | control messages to establish a message pipe. Keep this in mind: if the | 
 | interface is used relatively frequently, connecting once and reusing the | 
 | interface pointer is probably a good idea. | 
 |  | 
 |  | 
 | ## Ensure An Explicit Grant For WebUI Bindings | 
 |  | 
 | WebUI renderers sometimes need to call special, powerful IPC endpoints in a | 
 | privileged process. It is important to enforce the constraint that the | 
 | privileged callee previously created and blessed the calling process as a WebUI | 
 | process, and not as a (potentially compromised) web renderer or other | 
 | low-privilege process. | 
 |  | 
 | * Use the standard pattern for instantiating `MojoWebUIController`. WebUI | 
 | Mojo interfaces must only be exposed through a `MojoWebUIController` subclass. | 
 | * If there is external functionality that the WebUI needs, make sure to route | 
 | it through the Mojo interfaces implemented by the `MojoWebUIController`, to | 
 | avoid circumventing access checks. | 
 |  | 
 |  | 
 | ## Not-Yet-Shipped Features Should Be Feature-Checked On The Privileged Side | 
 |  | 
 | Sometimes, there will be powerful new features that are not yet turned on by | 
 | default, such as behind a flag, Finch trial, or [origin | 
 | trial](https://www.chromium.org/blink/origin-trials). It is not safe to check | 
 | for the feature's availability on the renderer side (or in another low-privilege | 
 | process type). Instead, ensure that the check is done in the process that has | 
 | power to actually enact the feature. Otherwise, a compromised renderer could opt | 
 | itself in to the feature! If the feature might not yet be fully developed and | 
 | safe, vulnerabilities could arise. | 
 |  | 
 |  | 
 | [security-tips-for-ipc]: https://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc | 
 | [NfcTypeConverter.java]: https://chromium.googlesource.com/chromium/src/+/e97442ee6e8c4cf6bcf7f5623c6fb2cc8cce92ac/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcTypeConverter.java | 
 | [mojo-doc-process-crashes]: https://chromium.googlesource.com/chromium/src/+/master/mojo/public/cpp/bindings#Best-practices-for-dealing-with-process-crashes-and-callbacks |