CEF3開發者系列之單進程模式應用


本文基於cef_binary_3.2623.1401.gb90a3be_windows32 ,即Chromium 49。主要利用CEF3在Windows動態鏈接庫dll中做一些輔助性界面開發。

需要解決的問題:

1、 使用單進程。由於項目是給第三方程序調用的SDK,所以不能使用多進程模式,否則增加對接成本和進程控制成本。

2、 JS與Native互調。某些界面中有前端JS與客戶端Native互相調用的接口。

在CEF3中使用單進程比較簡單,在初始化CEF3的時候,通過CefSettings配置進程模式。

CefSettings settings;
settings.single_process = true;        //采用單進程模式
settings.single_process = false;        //采用多進程模式

先來簡單的帶一筆CEF3的進程模式介紹:

CEF3是多進程架構的。Browser被定義為主進程,負責窗口管理,界面繪制和網絡交互。Blink的渲染和Js的執行被放在一個獨立的Render 進程中;除此之外,Render進程還負責Js Binding和對Dom節點的訪問。 默認的進程模型中,會為每個標簽頁創建一個新的Render進程。其他進程按需創建,例如管理插件的進程以及處理合成加速的進程等都是按需創建。

默認情況下,主應用程序會被多次啟動運行各自獨立的進程。這是通過傳遞不同的命令行參數給CefExecuteProcess函數做到的。

  int exit_code = CefExecuteProcess(main_args, NULL, sandbox_info);
  if (exit_code >= 0) {
    // The sub-process has completed so return here.
    return exit_code;
  }

Browser和Render進程可以通過發送異步消息進行雙向通信。甚至在Render進程可以注冊在Browser進程響應的異步JavaScript API。

single_process 設置為true時,Browser和Renderer使用一個進程。此項也可以通過命令行參數“single-process”配置。

回到我們需要解決的問題:單進程模式的時候,Browser和Renderer使用一個進程,不僅滿足界面的繪制,同時滿足JS的執行,與Native進行互相調用。正好滿足的我們的需求,幸好我們暫時不需要加載插件。

解決了方案和技術原理性問題,剩下的基本上就是編寫代碼了。

基於CEF3框架實現一個頁面加載,需要在初始化中實現CefBrowserProcessHandlerCefRenderProcessHandler類以及瀏覽器顯示、加載、生命周期等回調類。

初始化如下:

// Structure for passing command-line arguments.
  // The definition of this structure is platform-specific.
  CefMainArgs main_args(argc, argv);

  // Optional implementation of the CefApp interface.
  CefRefPtr<MyClentApp> app(new MyClentApp);

  // Execute the sub-process logic, if any. This will either return immediately for the browser
  // process or block until the sub-process should exit.
  int exit_code = CefExecuteProcess(main_args, app.get());
  if (exit_code >= 0) {
    // The sub-process terminated, exit now.
    return exit_code;
  }
  scoped_ptr<MainContextImpl>  mainContext.reset(new MainContextImpl(command_line, NULL));
  // Populate this structure to customize CEF behavior.
  CefSettings settings;
  mainContext->PopulateSettings(&settings);
  settings.single_process = true;
  // Initialize CEF in the main process.
  CefInitialize(main_args, settings, app.get());

  // Run the CEF message loop. This will block until CefQuitMessageLoop() is called.
  CefRunMessageLoop();

  // Shut down CEF.
  CefShutdown();

 

MyClientApp主要集成CefBrowserProcessHandler和CefRequestContextHandler 實現頁面加載、渲染和JS執行等

下邊代碼是頭文件代碼,具體的實現方式,參照CEF3的實例cefclient中ClientAppBrowser和 ClientAppRenderer。另外JS橋接口的調用,通過自定義實現CefV8Handler。在Renderer中的OnWebKitInitialized中注冊橋方法。詳見文章《CEF3開發者系列之JS與C++交互之二》

// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#ifndef CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_APP_RENDERER_H_
#define CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_APP_RENDERER_H_
#pragma once

#include <set>

#include "client_app.h"

namespace client {

// Client app implementation for the renderer process.
class ClientAppRenderer : public ClientApp,
                          public CefRenderProcessHandler {
 public:
  // Interface for renderer delegates. All Delegates must be returned via
  // CreateDelegates. Do not perform work in the Delegate
  // constructor. See CefRenderProcessHandler for documentation.
  class Delegate : public virtual CefBase {
   public:
    virtual void OnRenderThreadCreated(CefRefPtr<ClientAppRenderer> app,
                                       CefRefPtr<CefListValue> extra_info) {}

    virtual void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) {}

    virtual void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
                                  CefRefPtr<CefBrowser> browser) {}

    virtual void OnBrowserDestroyed(CefRefPtr<ClientAppRenderer> app,
                                    CefRefPtr<CefBrowser> browser) {}

    virtual CefRefPtr<CefLoadHandler> GetLoadHandler(
        CefRefPtr<ClientAppRenderer> app) {
      return NULL;
    }

    virtual bool OnBeforeNavigation(CefRefPtr<ClientAppRenderer> app,
                                    CefRefPtr<CefBrowser> browser,
                                    CefRefPtr<CefFrame> frame,
                                    CefRefPtr<CefRequest> request,
                                    cef_navigation_type_t navigation_type,
                                    bool is_redirect) {
      return false;
    }

    virtual void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
                                  CefRefPtr<CefBrowser> browser,
                                  CefRefPtr<CefFrame> frame,
                                  CefRefPtr<CefV8Context> context) {}

    virtual void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
                                   CefRefPtr<CefBrowser> browser,
                                   CefRefPtr<CefFrame> frame,
                                   CefRefPtr<CefV8Context> context) {}

    virtual void OnUncaughtException(CefRefPtr<ClientAppRenderer> app,
                                     CefRefPtr<CefBrowser> browser,
                                     CefRefPtr<CefFrame> frame,
                                     CefRefPtr<CefV8Context> context,
                                     CefRefPtr<CefV8Exception> exception,
                                     CefRefPtr<CefV8StackTrace> stackTrace) {}

    virtual void OnFocusedNodeChanged(CefRefPtr<ClientAppRenderer> app,
                                      CefRefPtr<CefBrowser> browser,
                                      CefRefPtr<CefFrame> frame,
                                      CefRefPtr<CefDOMNode> node) {}

    // Called when a process message is received. Return true if the message was
    // handled and should not be passed on to other handlers. Delegates
    // should check for unique message names to avoid interfering with each
    // other.
    virtual bool OnProcessMessageReceived(
        CefRefPtr<ClientAppRenderer> app,
        CefRefPtr<CefBrowser> browser,
        CefProcessId source_process,
        CefRefPtr<CefProcessMessage> message) {
      return false;
    }
  };

  typedef std::set<CefRefPtr<Delegate> > DelegateSet;

  ClientAppRenderer();

 private:
  // Creates all of the Delegate objects. Implemented by cefclient in
  // client_app_delegates_renderer.cc
  static void CreateDelegates(DelegateSet& delegates);

  // CefApp methods.
  CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE {
    return this;
  }

  // CefRenderProcessHandler methods.
  void OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info) OVERRIDE;
  void OnWebKitInitialized() OVERRIDE;
  void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
  void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) OVERRIDE;
  CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE;
  bool OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
                          CefRefPtr<CefRequest> request,
                          NavigationType navigation_type,
                          bool is_redirect) OVERRIDE;
  void OnContextCreated(CefRefPtr<CefBrowser> browser,
                        CefRefPtr<CefFrame> frame,
                        CefRefPtr<CefV8Context> context) OVERRIDE;
  void OnContextReleased(CefRefPtr<CefBrowser> browser,
                         CefRefPtr<CefFrame> frame,
                         CefRefPtr<CefV8Context> context) OVERRIDE;
  void OnUncaughtException(CefRefPtr<CefBrowser> browser,
                           CefRefPtr<CefFrame> frame,
                           CefRefPtr<CefV8Context> context,
                           CefRefPtr<CefV8Exception> exception,
                           CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE;
  void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
                            CefRefPtr<CefFrame> frame,
                            CefRefPtr<CefDOMNode> node) OVERRIDE;
  bool OnProcessMessageReceived(
      CefRefPtr<CefBrowser> browser,
      CefProcessId source_process,
      CefRefPtr<CefProcessMessage> message) OVERRIDE;

 private:
  // Set of supported Delegates.
  DelegateSet delegates_;

  IMPLEMENT_REFCOUNTING(ClientAppRenderer);
  DISALLOW_COPY_AND_ASSIGN(ClientAppRenderer);
};

}  // namespace client

#endif  // CEF_TESTS_CEFCLIENT_RENDERER_CLIENT_APP_RENDERER_H_

 

至此完結。單進程適用於一些常規需求,比如通過前端的方式來實現界面。實現起來也不復雜,主要是通過本篇文章,再次熟悉下基本的進程模式及其作用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM