过程
来自:Intro to Mojo & Services
实现:将消息从render 发送到browser 进程的RenderFrameHostImpl
实例处,这个实例和render frame 相关联。
定义接口。
创建一个 mojom
Ping() 返回值会对应到C++中的回调方法 :返回值对应回调方法的 参数。
// src/example/public/mojom/ping_responder.mojom
module example.mojom;
interface PingResponder {
// Receives a "Ping" and responds with a random integer.
Ping() => (int32 random);
};
# src/example/public/mojom/BUILD.gn
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [ "ping_responder.mojom" ]
}
添加一个pipe 、Remote
。
添加一个 message pipe 以使用这个接口。
通常 Remote
端 为创建管道一方,因为其通常先发送消息。 将下面代码放在renderer 中
创建一个Remote
、PendingReceiver
,后者只是为了编译期强类型,表明端点希望被Receiver
端同接口类型 绑定。
mojo:: Remote< example:: mojom:: PingResponder> ping_responder;
mojo:: PendingReceiver< example:: mojom:: PingResponder> receiver = ping_responder. BindNewPipeAndPassReceiver ( ) ;
这里的Remote
通过BindNewPipeAndPassReceiver
实现了创建pipe、绑定端口。
Remote
可以在构造的时候传入PendingRemote
以实现绑定, 或者后续使用 Bind
绑定PendingRemote
。(PendingRemote
包含了message pipe 的端点)
Remote
端通过调用Ping
来发送消息。
实现回调、发送消息。
回调通过 mojom接口 -> 底层通道 -> mojom 接口实例 -> browser 侧。
void OnPong ( int32_t num) { }
ping_responder- > Ping ( base:: BindOnce ( & OnPong) ) ;
将PendingReceiver
发送到 browser 进程。
可以使用 invitation
传递,原文采用了BrowserInterfaceBroker
传递。
在 browser 侧实现 PingResponder
接口 的实现。
其中Receiver
作为私有成员,在构造时传入了 this 和PendingReceiver
(PendingReceiver 存储了message pipe 的另一个端点)。
#include "example/public/mojom/ping_responder.mojom.h"
class PingResponderImpl : example:: mojom:: PingResponder {
public :
explicit PingResponderImpl ( mojo:: PendingReceiver< example:: mojom:: PingResponder> receiver)
: receiver_ ( this , std:: move ( receiver) ) { }
PingResponderImpl ( const PingResponderImpl& ) = delete ;
PingResponderImpl& operator = ( const PingResponderImpl& ) = delete ;
void Ping ( PingCallback callback) override {
std:: move ( callback) . Run ( 4 ) ;
}
private :
mojo:: Receiver< example:: mojom:: PingResponder> receiver_;
} ;
class RenderFrameHostImpl
. . .
void GetPingResponder ( mojo:: PendingReceiver< example:: mojom:: PingResponder> receiver) ;
. . .
private :
. . .
std:: unique_ptr< PingResponderImpl> ping_responder_;
. . .
} ;
void RenderFrameHostImpl:: GetPingResponder (
mojo:: PendingReceiver< example:: mojom:: PingResponder> receiver) {
ping_responder_ = std:: make_unique< PingResponderImpl> ( std:: move ( receiver) ) ;
}
void PopulateFrameBinders ( RenderFrameHostImpl* host,
mojo:: BinderMap* map) {
. . .
map- > Add< example:: mojom:: PingResponder> ( base:: BindRepeating (
& RenderFrameHostImpl:: GetPingResponder, base:: Unretained ( host) ) ) ;
}
只要 ping_responder
对象在render 端存在的够久,OnPong
回调会被正确调用。
理解
过程: (A、B 进程需要通信)
A进程:创建mojom 文件、修改构建规则 BUILD.gn、创建message pipe、创建Remote
(绑定message pipe 的一个端点)、将另一个端点发送给进程B。
随后A进程就可以使用 mojom 接口的方法, 用于传递消息。最终B进程实现的实例中的方法会被调用。 B进程:实现mojom 接口的实例类 并创建其对象、根据传递来的message pipe 端点和 实例对象 创建Receiver
。即形成了通路。
render 端的 Remote
通过 mojom 接口 发送消息。
mojo::Remote<example::mojom::PingResponder> ping_responder;
将其绑定到message pipe 的一端,再调用PingResponder
接口即可。
browser端 对mojom 接口实现类: PingResponderImpl
,其实例和message pipe端点一起绑定到Receiver
上。mojo::Receiver<example::mojom::PingResponder> receiver_;
将其绑定到底层message pipe的另一个 端点上。消息最终传递到实现类对应的方法中。
图来自:Chromium-Mojo&IPC
需要保证 Remote
、Receiver
的生命周期,否则消息无法传递或收取。
参考