For Developers‎ > ‎Design Documents‎ > ‎Mojo‎ > ‎

Chrome IPC To Mojo IPC Cheat Sheet

 

Overview

This document is intended to provide an overview of how legacy IPC concepts map to Mojo constructs. Documentation for legacy IPC can be found in Inter-process Communication (IPC) and Security Tips for IPC.

Threading Model

IPC

IPCs can be sent and recieved from any threads. If the sending/receiving thread is not the IO thread, there is always a hop and memory copy to/from the IO thread. Related IPCs are grouped in the same _messages.h file only for convenience, so different messages within the same file can be sent from different threads or received on different threads.

Mojo

A binding or interface pointer can only be used on one thread at a time since they're not thread-safe. However the message pipe can be unbound using either Binding::Unbind or InterfacePtr::PassInterface and then it can be bound again on a different thread. Making a method call doesn't involve a thread hop, but receiving it on a thread other than the IO thread does involve a thread hop.
 
Ordering between legacy IPC and Mojo IPC is guaranteed only to the IO thread at this time.
 
SECURITY FOLLOWUPS:
 TODO: are there any examples of type converters between mojo enums? Is this something we want to encourage? Maybe not? Also, should chrome-security do a periodic audit of things marked [Extensible]? A quick search shows that there are some things marked [Extensible] that probably don't need to be.
 

Declaring Messages

IPC

Messages are declared with macros like IPC_MESSAGE_ROUTED1 and IPC_MESSAGE_CONTROL2, which differentiate between control and routed messages. Messages are generally grouped together by message classes, which are defined in //ipc/ipc_message_start.h.

IPC_SYNC_MESSAGE_CONTROL0_1(ClipboardHostMsg_ReadText,
                            std::string /* result */)
 
IPC_MESSAGE_CONTROL1(ClipboardHostMsg_WriteText,
                     std::string /* text */)
 

Mojo

There is no differentiation between control and routed messages in Mojo since there are no routing IDs. Instead messages flow between two endpoints of a message pipe. Mojo messages are declared as interfaces with methods, with related methods grouped together in the same interface. A hypothetical clipboard.mojom might look like this:

 
 
interface ClipboardHost {
  ReadText() => (string text);
  WriteText(string text);
};

Receiving / Sending Messages

IPC

Messages are received via the IPC::Listener interface. Message dispatch is typically handled using helper macros:

bool ClipboardMessageFilter::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(ClipboardMessageFilter, message)
    IPC_MESSAGE_HANDLER(ClipboardHostMsg_ReadText, OnReadText)
    IPC_MESSAGE_HANDLER(ClipboardHostMsg_WriteText, OnWriteText)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void ClipboardMessageFilter::OnReadText(base::string16* result) {
  // Do stuff.
}

void ClipboardMessageFilter::OnWriteText(const base::string16& result) {
  // Do other stuff.
}

 
 

Messages are sent via IPC::Sender::Send(). Typically, code will construct a message, fill out the message params, and then call the IPC sender with the message:

 
std::string WebClipboardImpl::ReadText() {
  std::string result;
  sender_->Send(new ClipboardHostMsg_ReadText(&result));
  return result;
}

Mojo

The Mojo IDL compiler processes the .mojom files to generate corresponding C++ bindings (as well as bindings for other languages). The C++ bindings have generated stub interfaces that a C++ implementation should override:
 
 
#include "services/clipboard/clipboard.mojom.h"

class ClipboardImpl : public Clipboard {
 public:
  void ReadText(const ReadTextCallback& callback) {
    // Do stuff.
  }
  void WriteText(const mojo::String& s) {
    // Do other stuff.
  }
};
 
Sending messages in Mojo is simply a matter of calling the corresponding method on the proxy:
 
 
ClipboardPtr clipboard;
render_frame->GetRemoteInterfaces()->GetInterface(
    mojo::GetProxy(&clipboard));
clipboard->WriteText("Hello World!");

Pickling Values

In IPC, messages are simply a base::Picklebase::Pickle has some methods for reading/writing primitive types, such as uint32_tfloat, and base::StringPiece. Serializing/deserializing a type that doesn't have a corresponding base::Pickle::WriteT method requires specializing the IPC::ParamTraits template. If a message parameter fails deserialization in the browser process, the child process is killed. Currently with Mojo the message pipe is closed, but we don't kill the process (http://crbug.com/607293 tracks doing that).
 
Mojo also has a set of primitives types that it understands how to serialize/deserialize by default, such as stringarrayintenum, etc.
 
TODO(dcheng): Make sure we still emphasize that we want to preserve type-safety as much as possible. If that means defining a type mapping and writing custom validators, then so be it. Doing that is much better than, say, serializing a mojo::Array of bytes and then memcpying it into a struct.

Enums (e.g. IPC_ENUM_TRAITS and friends)

IPC

IPC has several different macros for creating a boilerplate IPC::ParamTraits specialization for enums:
 
 
// Serialization/deserialization of an enum with no validation: typically
// used for enums that are actually bitfields.
IPC_ENUM_TRAITS(blink::WebDragOperation)
 
// Serialization/deserialization of an enum. Validates that the deserialized
// enum value isn't less than 0 and isn't greater than the last declared
// value.
IPC_ENUM_TRAITS_MAX_VALUE(ui::DragDropTypes::DragEventSource,
                          ui::DragDropTypes::DRAG_EVENT_SOURCE_LAST)
 
// Like the previous macro, but validates that the enum value isn't less
// than a custom minimum.
IPC_ENUM_TRAITS_MIN_MAX_VALUE(content::PageZoom,
                              content::PageZoom::PAGE_ZOOM_OUT,
                              content::PageZoom::PAGE_ZOOM_IN)

Mojo

Just declare an enum in the .mojom file.

 
 
// Mojo automatically validates that the received enum has a legal value!
enum PageZoom {
  OUT,
  RESET,
  IN
};

// The Extensible attribute tells Mojo to skip validation. For bitfields,
// there can be many combinations of possible values. Extensible should only be
// used for these sorts of situations.
[Extensible]
enum DragOperation {
  None = 0,
  Copy = 1,
  Link = 2,
  Generic = 4,
  Private = 8,
  Move = 16,
  Delete = 32,
};

Transport-only structs (e.g. IPC_STRUCT_BEGIN, IPC_STRUCT_MEMBER, and IPC_STRUCT_END)

IPC provides IPC_STRUCT_BEGINIPC_STRUCT_MEMBER, and IPC_STRUCT_END macros as a way to define simple structs that are only used as IPC message parameters.

IPC

 

Defining a struct with these macros looks like this today:

 
IPC_STRUCT_BEGIN(ViewMsg_New_Params)
  IPC_STRUCT_MEMBER(int32_t, view_id, MSG_ROUTING_NONE)
  IPC_STRUCT_MEMBER(int32_t, main_frame_routing_id, MSG_ROUTING_NONE)
  IPC_STRUCT_MEMBER(int32_t, main_frame_widget_routing_id, MSG_ROUTING_NONE)
  IPC_STRUCT_MEMBER(int64_t, session_storage_namespace_id)
  IPC_STRUCT_MEMBER(int, opener_frame_route_id, MSG_ROUTING_NONE)
IPC_STRUCT_END()

And the resulting struct can be used like this:

bool RenderViewHostImpl::CreateRenderView(int opener_frame_route_id, ...) {
  /* do stuff */

  ViewMsg_New_Params params;
  params.view_id = GetRoutingID();
  /* …fill in rest of the fieldsu2026 */
  params.opener_frame_route_id = opener_frame_route_id;

  Send(new ViewMsg_New(params));

  /* do the rest of the stuff */
}

Mojo

Structs are defined in .mojom files:

struct CompositionSegment {
  uint32 start_offset;
  uint32 end_offset;
  bool emphasized;
};

The struct can be used as a parameter type:

 
 
interface ImeInstance {
  SetCompositionText(string text, array<CompositionSegment> segments);
}
 
Important: while this example uses the generated mojo structs directly, this is highly discouraged: typemapping to native C++ types usually makes the code more readable, and more importantly, makes sure that the mojo structs go through data validation (e.g. the renderer is not sending the browser invalid GURLs, etc)
 
And using it in C++ looks like this:
 
 
static mojo::Array<arc::mojom::CompositionSegmentPtr> ConvertSegments(
    const ui::CompositionText& composition) {
  mojo::Array<arc::mojom::CompositionSegmentPtr> segments =
      mojo::Array<arc::mojom::CompositionSegmentPtr>::New(0);
  for (const ui::CompositionUnderline& underline : composition.underlines) {
    arc::mojom::CompositionSegmentPtr segment =
        arc::mojom::CompositionSegment::New();
    segment->start_offset = underline.start_offset;
    segment->end_offset = underline.end_offset;
    segment->emphasized = (underline.thick ||
        (composition.selection.start() == underline.start_offset &&
         composition.selection.end() == underline.end_offset));
    segments.push_back(std::move(segment));
  }
  return segments;
}
 
void ArcImeBridgeImpl::SendSetCompositionText(
    const ui::CompositionText& composition) {
  ime_instance_->SetCompositionText(base::UTF16ToUTF8(composition.text),
                                    ConvertSegments(composition));
}

Pre-defined structs (e.g. IPC_STRUCT_TRAITS_BEGIN, IPC_STRUCT_TRAITS_MEMBER, and IPC_STRUCT_TRAITS_END)

IPC

Sometimes, IPC messages need to include structs that are already defined elsewhere. To help serialize simple structs for this case, IPC provides IPC_STRUCT_TRAITS_BEGINIPC_STRUCT_TRAITS_MEMBER, and IPC_STRUCTS_TRAITS_END. For example, given:
 
namespace ui {
struct FileInfo {
  base::FilePath path;
  base::FilePath display_name; // Optional.
};
} // namespace ui

IPC_STRUCT_TRAITS_BEGIN(ui::FileInfo)
  IPC_STRUCT_TRAITS_MEMBER(path)
  IPC_STRUCT_TRAITS_MEMBER(display_name)
IPC_STRUCT_TRAITS_END()

 

C++ code can pass a ui::FileInfo as an IPC parameter and it Just Works™:

Mojo

There isn't really a Mojo equivalent for this. Structs that need to be sent over Mojo need to have a corresponding Mojo struct. See the custom serialization section below for more information.

Custom serialization (e.g. custom IPC::ParamTraits)

IPC

There are some C++ types that can't be serialized with existing IPC::ParamTraits specializations. Those types specialize IPC::ParamTraits directly, rather than using the macros, and use the underlying base::Pickle methods to serialize/deserialize. A simple custom IPC::ParamTraits might look like this:
 
 
template <>
struct ParamTraits<std::string> {
  typedef std::string param_type;
  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    sizer->AddString(p);
  }
  static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); }
  static bool Read(const base::Pickle* m,
                   base::PickleIterator* iter,
                   param_type* r) {
    return iter->ReadString(r);
  }
  IPC_EXPORT static void Log(const param_type& p, std::string* l);
};

Mojo

Mojo uses StructTraits specializations in conjunction with type maps to transparently map between the native type and the Mojo structs at the binding layer. It's a bit too complicated to provide a simple example here, so please see Type Mapping in C++ for how to use this feature.
 
Note that Mojo also has a legacy TypeConverter mechanism for going to/from Mojo types. The use of type converters is discouraged in new code. Using StructTraits simplifies client code (e.g. code can use GURL instead of url::mojom::Url) and it allows validation of the data that needs custom serialization/deserialization. The latter point is quite important, since Mojo IPCs often go from the unprivileged renderer process to the privileged browser process.

Sync messages

In general, just like with legacy IPCs it's best to avoid synchronous messages if possible. If something really must be synchronous for legacy reasons, the [Sync] IDL attribute can be used. See the documentation on Synchronous Calls for more information.

[Chromium文档转载,第006章]Chrome IPC To Mojo IPC Cheat Sheet的更多相关文章

  1. [Chromium文档转载,第001章] Mojo Migration Guide

        For Developers‎ > ‎Design Documents‎ > ‎Mojo‎ > ‎ Mojo Migration Guide 目录 1 Summary 2 H ...

  2. [Chromium文档转载,第002章]Mojo C++ Bindings API

    Mojo C++ Bindings API This document is a subset of the Mojo documentation. Contents Overview Getting ...

  3. [Chromium文档转载,第003章]Proposal: Mojo Synchronous Methods

    Proposal: Mojo Synchronous Methods yzshen@chromium.org 02/02/2016 Overview Currently there are quite ...

  4. [Chromium文档转载,第007章]JNI on Chromium for Android

    Overview JNI (Java Native Interface) is the mechanism that enables Java code to call native function ...

  5. [Chromium文档转载,第005章]Calling Mojo from Blink

    For Developers‎ > ‎Design Documents‎ > ‎Mojo‎ > ‎ Calling Mojo from Blink Variants Let's as ...

  6. [Chromium文档转载,第004章]Mojo Synchronous Calls

    For Developers‎ > ‎Design Documents‎ > ‎Mojo‎ > ‎ Synchronous Calls Think carefully before ...

  7. 用R创建Word和PowerPoint文档--转载

    https://www.jianshu.com/p/7df62865c3ed Rapp --简书 Microsoft的Office软件在办公软件领域占有绝对的主导地位,几乎每个职场人士都必须掌握Wor ...

  8. java实现支付宝接口--文档..转载

    //实现java支付宝很简单,只要从支付宝官方下载   http://help.alipay.com/support/index_sh.htm下载程序,配置一下参数就OK了:   1.先到http:/ ...

  9. iOS开发主要参考文档(转载)

    Objective-C,语言的系统详细资料.这是做iOS开发的前题与基础.https://developer.apple.com/library/ios/#documentation/Cocoa/Co ...

随机推荐

  1. C#串口调试工具 (WPF/MVVM结构完整示例版)

    前文 由于经常用到串口调试, 尽管有现成的软件, 因为前端时间涉及一个二次开发, 就因为一个RtsEnable设置, 折腾半天,  网上各种版本的也很多, 功能扩展的很开也多.所以现在自己做了一个够用 ...

  2. ScrollView反弹效果的实现

    发现非常多APP的界面都能够滑动,QQ.微信等等,自己琢磨了下.效果例如以下: 代码:ScrollView package com.wsj.wsjdemo; import android.conten ...

  3. hdu5282 最长公共子序列的变形

    pid=5282">http://acm.hdu.edu.cn/showproblem.php?pid=5282 Problem Description Xuejiejie loves ...

  4. 木马——本质就是cs socket远程控制,反弹木马是作为c端向外发起网络请求

    摘自:http://kczxsp.hnu.edu.cn/upload/20150504165623705.pdf 里面对于木马的实验过程写得非常清楚,值得一看.   木马是隐藏在正常程序中的具有特殊功 ...

  5. 44.AngularJS Bootstrap

    转自:https://www.cnblogs.com/best/tag/Angular/ Bootstrap 你可以在你的 AngularJS 应用中加入 Twitter Bootstrap,你可以在 ...

  6. [NOI2013模拟] BZOJ4705 棋盘游戏 解题报告(组合计数)

    莫名打不开这道题的链接,请读者自行搜索 Description 有一个N*M的棋盘,初始每个格子都是白色的.行操作是指选定某一行,将这行所有格子的颜色取反(黑白互换).列操作是指选定某一列,将这列所有 ...

  7. WIFI 概览

      概览 Android 提供默认 Android 框架实现,其中包括对各种 WLAN 协议和模式的支持,这些协议和模式包括: WLAN 基础架构 (STA) 网络共享模式或仅限本地模式下的 WLAN ...

  8. jQuery的一些选择器

    一.基本选择器 1. id选择器(指定id元素) 将id="one"的元素背景色设置为黑色.(id选择器返单个元素) $(document).ready(function () { ...

  9. NodeJS学习笔记 进阶 (2)Nodejs进阶:MD5加密算法(ok)

    个人总结:这篇文章讲解了Nodejs中自带模块的MD5加密算法的使用,读完这篇文章需要15分钟,其实还有一个叫utility的包在npm上,也非常好用. 摘选自网络 简介 MD5(Message-Di ...

  10. Linux Network配置

    /etc/sysconfig/network [root@mytest ~]# cat /etc/sysconfig/network NETWORKING=yes HOSTNAME=mytest /e ...