libcef和js交互

1.下载libcef_wrapper工程:

        https://cef-builds.spotifycdn.com/index.html#windows32

        修改里面的cefsimple工程和js通信

2.文档:

        https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration

1.实现V8handler进行交互

        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.效果:

libcef和js交互_第1张图片

libcef和js交互_第2张图片

2.使用message router和js交互

        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.效果:

        

libcef和js交互_第3张图片

你可能感兴趣的:(C++,c++,libcef,javascript)