天天看点

CEF筆記

1. CEF中一个页面的框架

如下图所示:

CEF筆記

https://svn.hitecloud.com.cn:9800/svn/Bricks/trunk/HHCef

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..加载网页的过程

Chromium加载网页的过程,需要Browser进程和Render进程协作完成。加载网页的过程由Browser进程发起,向服务器请求网页内容的过程也是由Browser进程完成。Render进程负责对下载回来的网页内容进行解析,解析之后得到一个DOM Tree。有了这个DOM Tree之后,Render进程就可以对网页进行渲染了。

5.Browser和Render进程 -- https://blog.csdn.net/foruok/article/details/50573612

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方法。

Browser进程会启动一个Render进程。当我们在Chromium的地址栏输入一个网址,然后进行加载的时候,Browser进程经过判断,发现需要在一个新的Render进程中渲染该网址的内容时,就会创建一个RenderViewHostImpl对象,并且调用它的成员函数CreateRenderView触发启动一个新的Render进程。

6. JS和Native代码的三种JS交互方式

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中的对象

7.Browser进程与Render进程的IPC通信过程

CEF筆記

在Browser进程中,一个RenderProcessHost对象用来描述它所启动的一个Render进程,而一个RenderViewHost对象用来描述运行在一个Render进程中的一个网页,我们可以将它理解为浏览器中的一个TAB。这两个对象在Render进程中都有一个对等体,它们分别是一个RenderProcess对象和一个RenderView对象。这里说的对等体,就是它们是Browser进程和Render进程进行IPC的两个端点,类似于TCP/IP网络堆栈中的层对层通信。例如,RenderViewHost和RenderView之间的IPC通信,就代表了Browser进程请求Render进程加载、更新和渲染一个网页。

我们首先了解什么情况下Browser进程会启动一个Render进程。当我们在Chromium的地址栏输入一个网址,然后进行加载的时候,Browser进程经过判断,发现需要在一个新的Render进程中渲染该网址的内容时,就会创建一个RenderViewHostImpl对象,并且调用它的成员函数CreateRenderView触发启动一个新的Render进程。后面我们分析WebView加载一个URL的时候,就会看到触发创建RenderViewHostImpl对象的流程。

8 CEF_USE_SANDBOX

// When generating projects with CMake the CEF_USE_SANDBOX value will be defined

// automatically if using the required compiler version. Pass -DUSE_SANDBOX=OFF

// to the CMake command-line to disable use of the sandbox.

// Uncomment this line to manually enable sandbox support.

// #define CEF_USE_SANDBOX 1

#if defined(CEF_USE_SANDBOX)

// The cef_sandbox.lib static library is currently built with VS2013. It may not

// link successfully with other VS versions.

#pragma comment(lib, "cef_sandbox.lib")

#endif

9.资源文件都添加的情况下,debug下开始运行还是会出现崩溃

解决方法:把debug下用到的dll文件和libcef.lib文件都替换成release文件,libcef_dll_wrapper.lib文件除外。

10.C++ 封装(C++ Wrapper) - libcef_dll_wrapper

libcef 动态链接库导出 C API 使得使用者不用关心CEF运行库和基础代码。libcef_dll_wrapper 工程把 C API 封装成 C++ API同时包含在客户端应用程序工程中,与cefclient一样,源代码作为CEF二进制发布包的一部分共同发布。C/C++ API的转换层代码是由转换工具自动生成。UsingTheCAPI 页面描述了如何使用C API。

初识CEF - https://www.cnblogs.com/chechen/p/6104943.html

11. 集成消息循环(Message Loop Integration)

CEF可以不用它自己提供的消息循环,而与已经存在的程序中消息环境集成在一起,有两种方式可以做到:

a.周期性执行CefDoMessageLoopWork()函数,替代调用CefRunMessageLoop()。CefDoMessageLoopWork()的每一次调用,都将执行一次CEF消息循环的单次迭代。需要注意的是,此方法调用次数太少时,CEF消息循环会饿死,将极大的影响Browser的性能,调用次数太频繁又将影响CPU使用率。

b.设置CefSettings.multi_threaded_message_loop=true(Windows平台下有效),这个设置项将导致CEF在单独的线程上运行Browser的界面,而不是在主线程上,这种场景下CefDoMessageLoopWork()或者CefRunMessageLoop()都不需要调用,CefInitialze()、CefShutdown()仍然在主线程中调用。你需要提供主程序线程通信的机制(查看cefclient_win.cpp中提供的消息窗口实例)。在Windows平台下,你可以通过命令行参数--multi-threaded-message-loop测试上述消息模型。

https://www.cnblogs.com/chechen/p/6104943.html

继续阅读