1.1 renderer进程中的JS给CEF的browserC++进程发送消息
1.1.1 流程原理介绍
renderer进程中暴露一个query函数和cancel函数,在renderer进程运行的JavaScript代码调用window.cefQuery,cefQueryCancel函数将消息发给browser进程的c++代码处理消息,.cefQuery,cefQueryCancel是在C++代码中的CefMessageRouterConfig对象中注册的,如果你希望注册不同名字的函数,需要在CefMessageRouterConfig对象中设置,如果你要 设置两套注册函数,router也要两套。rendder进程和browser进程之间是通两端的消息路由传递消息的,render进程消息路由CefMessageRouterRendererSide,browser进程消息路由CefMessageRouterBrowserSide。在renderer进程的OnProcessMessageRecieved, OnContextCreated OnContextReleased函数中通过router对象调用CefMessageRouterRendererSide中同名的函数(OnContextCreated注册JavaScript的函数;OnContextReleased取消与上下文相关的正在进行中的query,调用OnQueryCanceled会被调用;OnProcessMessageRecieved消被router正确处理返回true),消息路由会将从renderer进程发送给browser进程中的CefMessageRouterBrowserSide路由。renderer进程支持一般的JavaScript回调函数注册和执行,browser进程中的路由router可以对消息采用一个或者多个不同逻辑的处理实例来处理。前端JavaScript调用window.cefQuery函数,renderder通过消息路由将消息发给browser进程,browser进程的一个或者多个queryhander就会接收到消息,每个handler可以选择处理或者忽略消息。如果处理了消息,如果响应有效,需要执行回调函数Callback::Success,如果出错,需要调用Callback::Failure。这两个函数会同步调用renderer进程中JavaScript的回调函数onSuccess和onFailure,返回执行结果。如果query没有被borwser进程的hander处理,则会自动取消,JavaScript的onFaillure回调函数会被执行,错误码-1;qurry可以是持续的或者非持续的
(1)如果是持续的,需要在browser进程中定义map>保存持续的请求queryid和callback对象,在onquery函数中保存进入map,当JavaScript调用window.CefQueryCancel函数,或者C++代码中使用了CallFailure函数,或者上下文context销毁时,需要将query在C++的OnQueryCancel回调函数中从map中删除。
(2)如果query是非持续的,注册会在JavaScript的回调函数执行后自动清除。不用保存到map主要实现在CEF的cef_message_router.h文件中。
1.1.2 query请模式
(1) 一次请求模式,使用非持续query,handle执行请求,返回响应, query销毁。
(2) 广播模式。使用持久性query注册为一个广播接受者,handler一直追踪所有的注册回调,并执行他们来发送广播消息。
(3) 订阅模式。使用持续性query注册为JavaScript的订阅接受者,handler在第一次请求时初始化订阅feed,将响应发送给所有的订阅者。没有一个注册的JavaScript接收者时,handle会取消订阅feed。
render进程中一般只要一个router就可以了,如果需要注册不同的JavaScript函数名字,需要多个router。当browser进程需要多个hadler来处理不同的消息,这样做是非常有用的。
1.1.3 消息通讯具体开发步骤
(1) 在renderer进程的rendererApp类的构造函数中创建CefMessageRouterRendererSide对象。
CefMessageRouterConfig config;
m_messagerouter=CefMessageRouterRendererSide.Create(config);
(2) 在renderer进程的OnProcessMessageRecieved, OnContextReleased OnContextCreated函数中通过router对象调用CefMessageRouterRendererSide中同名的函数,消息就会发送给browser进程中的CefMessageRouterBrowserSide路由。
void RendererApp::OnContextCreated(CefRefPtr browser, CefRefPtr frame, CefRefPtr context)
{
m_messageRouter->OnContextCreated(browser, frame, context);
}
void RendererApp::OnContextReleased(CefRefPtr browser, CefRefPtr frame, CefRefPtr context)
{
m_messageRouter->OnContextReleased(browser, frame, context);
}
bool RendererApp::OnProcessMessageReceived(CefRefPtr browser, CefProcessId source_process, CefRefPtr message)
{
return m_messageRouter->OnProcessMessageReceived(
browser, source_process, message);
}
(3) 定义处理类QueryHand,继承类 CefMessageRouterBrowserSide ::Handler类,实现OnQuery函数。
#pragma once
#include
#include "include/wrapper/cef_message_router.h"
#include "FrameCommunication/CefInterfaceCallback.h"
class CefQueryHandler : public CefBaseRefCounted
, public CefMessageRouterBrowserSide::Handler
{
protected:
virtual bool OnQuery(CefRefPtr browser,
CefRefPtr frame,
int64 query_id,
const CefString& request,
bool persistent,
CefRefPtr callback);
virtual void OnQueryCanceled(CefRefPtr browser,
CefRefPtr frame,
int64 query_id);
void complete(int64 query_id, int error_code, const CefString response);
private:
std::map> m_pendings;
IMPLEMENT_REFCOUNTING(CefQueryHandler);
};
(4)在browser进程中clienthand类中创建对象CefMessageRouterConfig
CefMessageRouterConfig用来定义js调用的函数名称,下面给出的是默认函数名称。
CefMessageRouterConfig config;
// config.js_query_function = "cefQuery";
// config.js_cancel_function = "cefQueryCancel";
(5)在browser进程中根据配置创建CefMessageRouterBrowserSide对象管理QueryHand。创建QueryHand对象,并添加到CefMessageRouterBrowserSide。clienthandler的OnBeforeClose、OnBeforeBrowse、OnProcessMessageReceived函数中执行CefMessageRouterBrowserSide对象中对应名称的函数(在OnBeforeClose、OnBeforeBrowse中调用,这样做的目的是网页刷新或者关闭时,所有正在进行中的query会取消掉,OnQueryCanceled函数会被调用,取消所有正在进