Mojo For Chromium Developers
Overview
This document contains the minimum amount of information needed for a developer to start using Mojo in Chromium. For more detailed documentation on the C++ bindings, see this link.
Terminology
A message pipe is a pair of endpoints. Each endpoint has a queue of incoming messages, and writing a message to one endpoint effectively enqueues that message on the other endpoint. Message pipes are thus bidirectional.
A mojom file describes interfaces which describe strongly typed message structures, similar to proto files.
Given a mojom interface and a message pipe, the two endpoints can be given the labels InterfacePtr and Binding. This now describes a strongly typed message pipe which transports messages described by the mojom interface. The InterfacePtr is the endpoint which “sends” messages, and the Binding “receives” messages. Note that the message pipe itself is still bidirectional, and it's possible for a message to have a response callback, which the InterfacePtr would receive.
Another way to think of this is that an InterfacePtr is capable of making remote calls on an implementation of the mojom interface associated with the Binding.
The Binding itself is just glue that wires the endpoint's message queue up to some implementation of the interface provided by the developer.
Example
Let‘s apply this to Chrome. Let’s say we want to send a “Ping” message from a Browser to a Renderer. First we need to define the mojom interface.
module example.mojom;
interface PingResponder {
// Receives a "Ping" and responds with a random integer.
Ping() => (int random);
};
Now let's make a MessagePipe.
example::mojom::PingResponderPtr ping_responder;
example::mojom::PingResponderRequest request = mojo::MakeRequest(&ping_responder);
In this example, ping_responder is the InterfacePtr, and request is an InterfaceRequest, which is a Binding precursor that will shortly be turned into a Binding. Now we can send our Ping message.
auto callback = base::Bind(&OnPong);
ping_responder->Ping(callback);
Important aside: If we want to receive the the response, we must keep the object ping_responder alive. After all, it‘s just a wrapper around a Message Pipe endpoint, if it were to go away, there’d be nothing left to receive the response.
We‘re done! Of course, if everything were this easy, this document wouldn’t need to exist. We've taken the hard problem of sending a message from the Browser to a Renderer, and transformed it into a problem where we just need to take the request object, pass it to the Renderer, turn it into a Binding, and implement the interface.
In Chrome, processes host services, and the services themselves are connected to a Service Manager via message pipes. It‘s easy to pass request to the appropriate Renderer using the Service Manager, but this requires explicitly declaring our intentions via manifest files. For this example, we’ll use the content_browser service manifest file and the content_renderer service manifest file.
content_renderer_manifest.json:
...
"interface_provider_specs": {
"service_manager:connector": {
"provides": {
"cool_ping_feature": [
"example::mojom::PingResponder"
]
},
},
...
content_browser_manifest.json:
...
"interface_provider_specs": {
"service_manager:connector": {
"requires": {
"content_renderer": [ "cool_ping_feature" ],
},
},
},
...
These changes indicate that the content_renderer service provides the interface PingResponder, under the capability named “cool_ping_feature”. And the content_browser services intends to use this feature. content::BindInterface is a helper function that takes request and sends it to the renderer process via the Service Manager.
content::RenderProcessHost* host = GetRenderProcessHost();
content::BindInterface(host, std::move(request));
Putting this all together for the browser process:
example::mojom::PingResponderPtr ping_responder; // Make sure to keep this alive! Otherwise the response will never be received.
example::mojom::PingResponderRequest request = mojo::MakeRequest(&ping_responder);
ping_responder->Ping(base::BindOnce(&OnPong));
content::RenderProcessHost* host = GetRenderProcessHost();
content::BindInterface(host, std::move(request));
In the Renderer process, we need to write an implementation for PingResponder, and ensure that a Binding is created using the transported request. In a standalone Mojo service, this would require us to implement service_manager::Service::OnBindInterface(). In Chrome, this is abstracted behind content::ConnectionFilters and service_manager::BinderRegistry. This is typically done in RenderThreadImpl::Init.
class PingResponderImpl : mojom::PingResponder {
void BindToInterface(example::mojom::PingResponderRequest request) {
binding_.reset(
new mojo::Binding<mojom::MemlogClient>(this, std::move(request)));
}
void Ping(PingCallback callback) { std::move(callback).Run(4); }
std::unique_ptr<mojo::Binding<mojom::PingResponder>> binding_;
};
RenderThreadImpl::Init() {
...
this->ping_responder = std::make_unique<PingResponderImpl>();
auto registry = base::MakeUnique<service_manager::BinderRegistry>();
// This makes the assumption that |this->ping_responder| will outlive |registry|.
registry->AddInterface(base::Bind(&PingResponderImpl::BindToInterface), base::Unretained(this->ping_responder.get()));
GetServiceManagerConnection()->AddConnectionFilter(
base::MakeUnique<SimpleConnectionFilter>(std::move(registry)));
...
Mojo For Chromium Developers的更多相关文章
- Mojo For Chromium Developers1
Mojo For Chromium Developers Overview This document contains the minimum amount of information neede ...
- [Chromium文档转载,第002章]Mojo C++ Bindings API
Mojo C++ Bindings API This document is a subset of the Mojo documentation. Contents Overview Getting ...
- Converting Legacy Chrome IPC To Mojo
Converting Legacy Chrome IPC To Mojo Looking for Mojo Documentation? Contents Overview Deciding What ...
- Mojo C++ Bindings API
This document is a subset of the Mojo documentation. Contents Overview Getting Started Interfaces Ba ...
- Chromium Embedded Framework 中文文档(简介)
转自:http://www.cnblogs.com/think/archive/2011/10/06/CEF-Introduce.html 简介 Chromium Embedded Framework ...
- How to steal any developer's local database
原文链接: http://bouk.co/blog/hacking-developers/ If you’re reading this and you’re a software developer ...
- Why mobile web apps are slow
http://sealedabstract.com/rants/why-mobile-web-apps-are-slow/ I’ve had an unusual number of interest ...
- Network Stack
Network Stack 目录 1 Overview 2 Code Layout 3 Anatomy of a Network Request (focused on HTTP) 3.1 URLRe ...
- React中autoComplete="off" 失效
Turning Off Autocomplete in Chrome with React tl;dr Add a hidden input with an arbitrary value attri ...
随机推荐
- jar文件配置冲突问题transformResourcesWithMergeJavaResForDebug
先看本人AS报错异常 Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'. > c ...
- Activity全屏沉浸状态
public class MainActivity extends AppCompatActivity { private static final String TAG = "MainAc ...
- [读书笔记] Python数据分析 (四) 数组和矢量计算
Numpy:高性能计算和数学分析的基础包 ndarray, 一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组 用于对数组数据进行快速运算的标准数学函数 用于读写磁盘数据的工具和用于操作内存 ...
- %02x与%2x之间的区别
输出最小宽度用十进制整数来表示输出的最少位数.若实际位数多于定义的宽度,则按实际位数输出,若实际位数少于定义的宽度则补以空格或0(当最小宽度数值以0开头时). X 表示以十六进制形式输出02表示不足两 ...
- vue自定义一个过滤器
vue如何自定义一个过滤器 html代码: <div id="app"> <input type="text" v-model="m ...
- 【codeforces 733E】Sleep in Class
[题目链接]:http://codeforces.com/problemset/problem/733/E [题意] 有n级台阶,每个台阶上都有一个tag; 标记着向上或向下; 你到了某级台阶,就要按 ...
- 【codeforces 749D】Leaving Auction
[题目链接]:http://codeforces.com/problemset/problem/749/D [题意] 有n个人在竞价; 按照时间的顺序给出n次竞价(可能有一些人没有参加竞价); 每次竞 ...
- UVALIVE 4256 Salesmen
Salesmen Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ...
- LeetCode104_MaximumDepthofBinaryTree Java题解
题目: Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the ...
- ZOJ 3688
做出这题,小有成就感 本来已打算要用那个禁位的排列公式,可是,问题在于,每个阶乘前的系数r的求法是一个难点. 随便翻了翻那本美国教材<组合数学>,在容斥原理一章的习题里竟有一道类似,虽然并 ...