1. CEF中一个页面的框架

如下图所示:

 CEF筆記

 

CefBrowser:一个普通的浏览器页面(HTML)

CefFrame:每一个页面都由至少一个frame组成,最顶层的为mainframe

context:JS执行环境,每个frame都有自己独立的context,CEF中使用V8JavaScriptEngine解析和执行JS代码

 

2..C++ call JS:
由框架图可以知道,后端执行JS的实质是:在特定的frame上执行JS代码片段

CefRefPtr<CefBrowser> browser = ...;  
CefRefPtr<CefFrame> frame = browser->GetMainFrame();  
frame->ExecuteJavaScript("alert('ExecuteJavaScript works!');",  
    frame->GetURL(), 0);  

3.JS call C++
C++和JS对象的映射关系:

 CEF筆記

CefValue表示JS环境中的一个对象,其可以表示JS中所有变量,切其自身可以嵌套。特别重要的一点,前端的window对象在后端也是一个CefV8Value,并且可以通过CefV8Context取到它。

 

JS调用C++的实质是:以CefV8Value的形式包装C++对象,并将其绑定到特定frame的JS执行环境的window对象上,如此JS代码就可以直接对其读写(属性)或者调用(函数)。

 

4.Browser和Render进程

CEF筆記

现在我们清楚了,Browser进程,需要CefApp(SimpleApp实现了这个接口)和CefClient(SimpleHandler实现了这个接口)。而Renderer进程只要CefApp。

另外,CEF还定义了CefBrowserProcessHandler和CefRenderProcessHandler两个接口,分别来处理Browser进程和Render进程的个性化的通知。因此,Browser进程的App一般还需要实现CefBrowserProcessHandler接口,Renderer进程的App一般还需要实现CefRenderProcessHandler接口。
 

如果要实现JS与Native代码交互,最好分开实现Browser进程需要的CefApp和Render进程需要的CefApp。像下面这样:

class ClientAppRenderer : public CefApp,
    public CefRenderProcessHandler 
{
    ...
}

class ClientAppBrowser : public CefApp, 
    public CefBrowserProcessHandler
{
    ...
}

当我们实现了CefRenderProcessHandler接口,就可以在其OnContextCreated()方法中获取到CefFrame对应的window对象,在它上面绑定一些JS函数或对象,然后JS代码里就可以通过window对象访问,如果是函数,就会调用到我们实现的CefV8Handler接口的Execute方法。

 

JS和Native代码的交互发生在Render进程,App需要继承CefRenderProcessHandler来整合JS相关功能。

这个示例演示了三种JS交互方式(参见https://bitbucket.org/chromiumembedded/cef/wiki/JavaScriptIntegration.md): 
- 在native代码中通过CefFrame::ExecuteJavaScript()来执行JavaScript代码 
- 将函数或对象绑定到CefFrame对应的window对象上,JS代码通过window对象访问native代码导出的函数或对象 
- 使用CefRegisterExtension()注册JS扩展,JS直接访问注册到JS Context中的对象
 

相关文章: