1. 程式人生 > >CEF3研究(二)

CEF3研究(二)

ade host 之前 不為 void 描述 可執行文件 render linu

  1. 應用程序結構

每個CEF3應用程序都有一個相同的結構:

  • 提供一個入口函數以初始化CEF和運行每個子進程邏輯和CEF消息處理
  • 提供一個CefApp子類處理某個進程的回調
  • 提供一個CefClinet子類處理某個瀏覽進程的回調
  • 調用CefBrowserHost::CreateBrowser()函數創建瀏覽進程實例並使用CefLifeSpanHandler來管理瀏覽生命周期

2. 入口函數

CEF3應用程序都是以多進程方式運行的。這些進程都可以使用相同的可執行文件和獨立的可執行文件被分配在每個子進程上。每個可執行進程都有一個入口函數。
每個CEF3子進程運行時使用運行行來指定配置信息並通過CefMainArgs結構傳遞給CefExecuteProcess函數,CefMainArgs結構是跨平臺的。
如:
CefMainArgs main_args(argc, argv);
CefMainArgs main_args(hInstance);

3.單可執行體-單進程運行方式

當單可執行體時行時,入口函數CefExecuteProcess在不同進程類型之間需要區分。單可執行體結構只支持window和linux,不支持macos

4. 分離的子進程可執行體-多進程運行方式

當使用一個分離的子進程執行體時需要兩個分離的進程和入口函數。

5. 消息循環集成

CEF可集成已經存在的應用程序消息循環來代替它自己的消息循環。有2種方式:

    1. 正常的調用CefDoMessageLoopWork() 函數來代替調用 CefRunMessageLoop()。每調用 CefDoMessageLoopWork()函數會對CEF消息循環執行單一集成。
      應該謹慎使用這種方法。調用的方法也經常會挨餓CEF消息循環湊並且瀏覽器性能產生影響。調用方法過於頻繁地將影響CPU使用率。
    2. 設置 CefSettings.multi_threaded_message_loop = true(僅Windows平臺),這會引起CEF從主應用程序線程以單個線程運行瀏覽器的UI線程。這不會引起 CefDoMessageLoopWork()和 CefRunMessageLoop()的調用。. CefInitialize() 和CefShutdown() 應該在應用程序的主線程調用。 需要自己提供機制與應用程序主線程通信。

6. CefSettings

CefSettings結構允許Cef配置應用程序類型。以下列出通用的成員:

  • single_process 設置為true將為瀏覽器和渲染使用單進程。也可配置使用單個進程的命令行開關。
  • browser_subprocess_path 子進程的單個執行體路徑,
  • multi_threaded_message_loop為true表示瀏覽器進程的消息循環以單線程運行。
  • command_line_args_idsabled為true表示禁用使用標準的CEF和Chrominum命令行參數的瀏覽器進程配置的特性。
  • cache_path緩存數據保存在磁盤上,如果為空,內存緩存會被某些特性使用,臨時磁盤緩存會被其他地方使用。如果不為空,如HTML5本地存儲數據庫會跨域。
  • locale locale字符串會傳遞給blink,默認為en-US
  • log_file為debuglog文件路徑
  • log_severity日誌等級
  • resources_dir_path資料的目錄路徑。即cef.pak或devtools_resources.pak文件的保存路徑
  • locales_dir_path
  • locales_dir_path locales的保存路徑
  • remote_debugging_port遠程調試端口。範圍在1024~65535

7.CefBrowser和CefFrame

CefBrowser和CefFrame對象用於向瀏覽器發送命令和接受回調函數的狀態信息。每個CerBrowser對象有一個主CefFrame對象描述主窗口。有零個和多個描述子窗口。例如:一個瀏覽器加載兩個窗口會有三個CefFrame對象,一個是頂層窗口,兩個子窗口。

在主窗口中加載一個URL:
browser->GetMainFrame()->LoadURL(some_url);

調用瀏覽的返回按鈕:
browser->GoBack();

獲取主窗口的HTML內容

class Visitor : public CefStringVisitor {

public: Visitor() {}

virtual void Visit(const CefString& string) OVERRIDE { // Do something with |string|... }

IMPLEMENT_REFCOUNTING(Visitor);

};

browser->GetMainFrame()->GetSource(new Visitor());

CefBrowser和CefFrame對象分別存在瀏覽進程和渲染進程中。在瀏覽進程中可通過CefBrowser::GetHoset()函數控制主機行為,如獲取窗口句柄:

CefWindowHandle window_handle = browser->GetHost()->GetWindowHandle();

8.CefApp

CefApp接口提供特殊進程回調的訪問。重要的回調包括:
OnBeforeCommandLineProcessing 以編程的方式設置命令行
OnRegisterCustomSchemes 提供一個機會自定義主題
GetBrowserProcessHandler 指定瀏覽進程及包括 OnContextInitialized() 特定功能的處理者
GetRenderProcessHandler 渲染進程的處理者,包括JavaScript關聯的回調和進程消息

9.CefClient

CefClient接口提供了瀏覽器實例的特定回調。一個CefClient實例可以被多個瀏覽器共享。重要的回調包括:
瀏覽器生命周期,上下文菜單,對話框,顯示通知,拖拽事件,焦點事件,鍵盤事件的處理者
OnProcessMessageReceived 從渲染進程中發來的IPC消息的接受。

10.瀏覽器生命周期

Browser Life Space 以調用 CefBrowserHost::CreateBrowser()或CefBrowserHost::CreateBrowserSync()函數開始。 方便執行邏輯,包括CefBrowserProcessHandler::OnContextInitialized()或像WM_CREATE消息處理的調用。

CefLifeSpaceHandler類提供了管理瀏覽器生命周期的回調。

  • OnAfterCreated() 在瀏覽器對象被創建後立即調用,主應用程序通常用這個函數保存瀏覽器對象的引用,如:
    void MyClient::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
      // Must be executed on the UI thread.
      REQUIRE_UI_THREAD();
      // Protect data members from access on multiple threads.
      AutoLock lock_scope(this);  // Deprecated -- see the “Threads” section.
    
      if (!m_Browser.get())   {
        // Keep a reference to the main browser.
        m_Browser = browser;
        m_BrowserId = browser->GetIdentifier();
      }
    
      // Keep track of how many browsers currently exist.
      m_BrowserCount++;
    }
  • CefBrowserHost::CloseBrowser() 銷毀瀏覽進程 如:browser->GetHost()->CloseBrowser(false)
    如果瀏覽器是其他窗口的父窗口,那麽這個關閉事件會引起父窗口的系統函數調用。那父窗口需要調用 CloseBrowser(false) 並等待第二個系統調用的關閉事件來指示瀏覽進程允許關閉。
    如果關閉通過Javascript事件或DoClose()回調函數處理,那第二個系統關閉事件就不會被發送。
    IsClosing()測試是否關閉,如果是第一次的系統關閉事件就返回false,每二次返回true;
    第一個系統關閉事件是在窗口的WndProc函數中處理的
    case WM_CLOSE:

      if (g_handler.get() && !g_handler->IsClosing()) {
        CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
        if (browser.get()) {
          // Notify the browser window that we would like to close it. This will result in a call to 
          // MyHandler::DoClose() if the JavaScript ‘onbeforeunload‘ event handler allows it.
          browser->GetHost()->CloseBrowser(false);
    
          // Cancel the close.
          return 0;
        }
      }
    
      // Allow the close.
      break;
    
    case WM_DESTROY:
      // Quitting CEF is handled in MyHandler::OnBeforeClose().
      return 0;
    }
  • DoClose() 設置m_blsClosing標識並設置第二次系統關閉事件為false

    bool MyClient::DoClose(CefRefPtr<CefBrowser> browser) {
      // Must be executed on the UI thread.
      REQUIRE_UI_THREAD();
      // Protect data members from access on multiple threads.
      AutoLock lock_scope(this);
    
      // Closing the main window requires special handling. See the DoClose()
      // documentation in the CEF header for a detailed description of this
      // process.
      if (m_BrowserId == browser->GetIdentifier()) {
        // Notify the browser that the parent window is about to close.
        browser->GetHost()->ParentWindowWillClose();
    
        // Set a flag to indicate that the window close should be allowed.
        m_bIsClosing = true;
      }
    
      // Allow the close. For windowed browsers this will result in the OS close
      // event being sent.
      return false;
    }
  • OnBeforeClose 在接受第二次OS關閉事件之前需要調用OnBeforeCloseb函數釋放瀏覽器進程的引用。

CEF3研究(二)