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 ...
随机推荐
- Linux常见后缀缩写含义
ctl: control rc: run control (A run-control file is a file of declarations or commands associated wi ...
- SpringMVC框架入门
简介 SpringMVC采用模型(Model)-视图(View)-控制器(controller)的方法把业务逻辑.数据与界面显示分离.用通俗的话来讲,MVC的理念就是把数据处理.数据展示和程序/用户的 ...
- 记一次html页面传值给另一个html并解码
前言 由于最近写项目用到layui中的table.render,好像是直接由当前html直接与后台controller取数据,由一方(后台)遍历列表给html,而如果当前html需要传值给这个后台co ...
- 小程序做一个能够左右滑动切换的多tab页面
主要原理:使用 <swiper> 和 <scroll-view> 组件 代码片段: https://developers.weixin.qq.com/s/mLx4FWmF757 ...
- Vue-给对象新增属性(使用Vue.$set())
在开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的. 根据官方文档定义 ...
- SQLserver 导入超大CSV(100G以上)方法
1.似乎SQLSERVER2008对UTF8不兼容,采用SQLSERVER20052.采用SQLSERVER2005,还是出现UTF8诸如此类的问题,修改表结构,varchar改成 nvarchar3 ...
- qt quick中qml编程语言
Qt QML 入门 — 使用C++定义QML类型 发表于 2013 年 3 月 11 日 注册C++类 注册可实例化的类型 注册不实例化的QML类型 附带属性 注册C++类 注册可实例化的类型 如 ...
- 原生ajax的请求过程
原生ajax的请求过程 创建全平台兼容的XMLHttpRequest对象: function getXHR(){ var xhr = null; if(window.XMLHttpRequest) { ...
- vuejs 基础总结(one)
vuejs 入门知识点 1.active-class 是哪个组件的属性?嵌套路由怎么定义 (1).active-class 是 vue-router 模块的 router-link 组件的属性 (2) ...
- 【codeforces 794B】Cutting Carrot
[题目链接]:http://codeforces.com/contest/794/problem/B [题意] 给你一个等腰三角形; 它的底边为1; 高为h; 要求你把这个等腰三角形分成n份面积相等的 ...