天天看點

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

繼續閱讀