1.下载libcef_wrapper工程:
https://cef-builds.spotifycdn.com/index.html#windows32
修改里面的cefsimple工程和js通信
2.文档:
https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration
1.添加html文件:
cefsimple工程的默认url是google.com,把url改为我们的本地的html文件如下:
V8Test
hello v8
2.实现v8 handler:
cef使用v8和js通信,所以我们需要继承CefV8Handler,并且实现Execute函数,因为js调用我们注册的对象或者函数会进入Execute函数,上面js调用了myfunc函数,现在我们需要在Execute处理这个调用:
bool V8Handler::Execute(const CefString& name, CefRefPtr object,
const CefV8ValueList& arguments, CefRefPtr& retval,
CefString& exception)
{
if (name == "myfunc") {
// Return my string value.
retval = CefV8Value::CreateString("My Value!");
return true;
}
// Function does not exist.
return false;
}
直接返回一个字符串的值。
2.实现render handler:
在cefsimple_win.cc文件中,渲染进程是没有handler的,默认传了nullptr,所以我们需要传递一个rendler handler:
// CEF applications have multiple sub-processes (render, plugin, GPU, etc)
// that share the same executable. This function checks the command-line and,
// if this is a sub-process, executes the appropriate logic.
CefRefPtrrenderHandler(new RenderHandler);
int exit_code = CefExecuteProcess(main_args, renderHandler.get(), sandbox_info);
if (exit_code >= 0) {
// The sub-process has completed so return here.
return exit_code;
}
rendler handler主要继承:CefApp、CefRenderProcessHandler、CefLifeSpanHandler这个三个类,然后我们需要override OnContextCreated这个函数,在里面注册对象并且绑定到js:
void RenderHandler::OnContextCreated(CefRefPtr browser,
CefRefPtr frame, CefRefPtr context)
{
CefRefPtr object = context->GetGlobal();
CefRefPtr handler = new V8Handler();
CefRefPtr func = CefV8Value::CreateFunction("myfunc", handler);
object->SetValue("myfunc", func, V8_PROPERTY_ATTRIBUTE_NONE);
}
3.cpp调用调用js:
最直接的方式就是调用CefFrame::ExecuteJavaScript(),在browser创建完成后,可以通过browser获取frame:
void RenderHandler::OnBrowserCreated(CefRefPtr browser,
CefRefPtr extra_info)
{
CefRefPtr frame = browser->GetMainFrame();
frame->ExecuteJavaScript("alert(\"browser created\")", frame->GetURL(), 0);
}
4.效果:
1.wrapper工程实现了message router,可以直接使用,message router默认在js的window对象中添加cefQuery方法,所以在js中直接调用:
V8Test
hello v8
2.渲染进程的router:
在渲染进程中,创建一个CefMessageRouterRendererSide类型的成员变量,用于处理render handler的路由:
RenderHandler::RenderHandler()
{
CefMessageRouterConfig config;
config.js_query_function = "cefQuery"; //可以自由配置函数名字,需要和browser进程的一致
config.js_cancel_function = "cefQueryCancel";
m_renderMsgRouter = CefMessageRouterRendererSide::Create(config);
}
然后把rendler handler中的OnContextCreated、OnContextReleased、OnProcessMessageReceived都交给router:
void RenderHandler::OnContextCreated(CefRefPtr browser,
CefRefPtr frame, CefRefPtr context)
{
m_renderMsgRouter->OnContextCreated(browser, frame, context);
}
void RenderHandler::OnContextReleased(CefRefPtr browser,
CefRefPtr frame, CefRefPtr context)
{
m_renderMsgRouter->OnContextReleased(browser, frame, context);
}
bool RenderHandler::OnProcessMessageReceived(CefRefPtr browser,
CefRefPtr frame, CefProcessId source_process,
CefRefPtr message)
{
return m_renderMsgRouter->OnProcessMessageReceived(browser, frame, source_process, message);
}
如果查看CefMessageRouterRendererSide::OnContextCreated里面的实现,可以看到其实也是用了上面的绑定方式,只是他帮我们实现了v8 handler,并且通过IPC发送到了browser进程:
3.browser进程的router:
browser进程也创建一个CefMessageRouterBrowserSide的成员变量,然后进行处理message:
CefMessageRouterConfig config;
config.js_query_function = "cefQuery"; //和render handler中的名字一致
config.js_cancel_function = "cefQueryCancel";
m_browserMsgRouter = CefMessageRouterBrowserSide::Create(config);
m_browserMsgRouter->AddHandler(this,false);
把handler的OnProcessMessageReceived交给router:
bool SimpleHandler::OnProcessMessageReceived(CefRefPtr browser,
CefRefPtr frame, CefProcessId source_process,
CefRefPtr message)
{
return m_browserMsgRouter->OnProcessMessageReceived(browser, frame, source_process, message);
}
browser handler继承CefMessageRouterBrowserSide::Handler,并且实现OnQuery函数,因为消息会被路由到Handler的OnQuery函数:
bool SimpleHandler::OnQuery(CefRefPtr browser,
CefRefPtr frame, int64 query_id, const CefString& request,
bool persistent, CefRefPtr callback)
{
if (request == "testfromjs")
{
callback->Success("testfromcpp");
return true;
}
return false;
}
CefMessageRouterBrowserSide::OnProcessMessageReceived函数其实就是接收到IPC消息,分发给了AddHandler保存的所有handler的OnQuery函数。
4.效果: