CEF框架:各种各样的Handle(一)

2024-01-09 17:01:04


在前面几篇文章中,将CEF初始化的基本框架和流程介绍了一遍。那么当整个CEF框架启动后,程序员可以通过什么样的方式去获得CEF内部的信息,还有就是如何修改CEF的行为呢?在CEF框架中,都是通过各种各样的Handle来实现。

那么什么是Handle呢,我的理解就是和WIN32编程中的HANDLE差不多,就是一个句柄,是某个程序实体,或者内存中的实体对外暴露的一个接口,通过这个接口就可以得到这个实体或者对象的控制权,从而得到这个实体的各种信息,或者控制这个实体的行为。

甚至更简单的一点理解,也可以理解成一个指针。

在CEF框架中有非常多的Handle类,直接罗列容易让人晕菜,我做了一个简单线索图,供各位朋友参考(以CEF的CefSimple为例)。

CefApp类

整个CEF程序可以看成是一个App,所以CEF程序或者称作App,就是最顶层的需要管理操作的实体,而管理和控制这个实体的类就是CefApp类:

类的定义

类的定义在cef_app.h中:

///
// Implement this interface to provide handler implementations. Methods will be
// called by the process and/or thread indicated.
///
/*--cef(source=client,no_debugct_check)--*/
class CefApp : public virtual CefBaseRefCounted {
 public:
  ///
  // Provides an opportunity to view and/or modify command-line arguments before
  // processing by CEF and Chromium. The |process_type| value will be empty for
  // the browser process. Do not keep a reference to the CefCommandLine object
  // passed to this method. The CefSettings.command_line_args_disabled value
  // can be used to start with an empty command-line object. Any values
  // specified in CefSettings that equate to command-line arguments will be set
  // before this method is called. Be cautious when using this method to modify
  // command-line arguments for non-browser processes as this may result in
  // undefined behavior including crashes.
  ///
  /*--cef(optional_param=process_type)--*/
  virtual void OnBeforeCommandLineProcessing(
      const CefString& process_type,
      CefRefPtr<CefCommandLine> command_line) {}

  ///
  // Provides an opportunity to register custom schemes. Do not keep a reference
  // to the |registrar| object. This method is called on the main thread for
  // each process and the registered schemes should be the same across all
  // processes.
  ///
  /*--cef()--*/
  virtual void OnRegisterCustomSchemes(
      CefRawPtr<CefSchemeRegistrar> registrar) {}

  ///
  // Return the handler for resource bundle events. If
  // CefSettings.pack_loading_disabled is true a handler must be returned. If no
  // handler is returned resources will be loaded from pack files. This method
  // is called by the browser and render processes on multiple threads.
  ///
  /*--cef()--*/
  virtual CefRefPtr<CefResourceBundleHandler> GetResourceBundleHandler() {
    return nullptr;
  }

  ///
  // Return the handler for functionality specific to the browser process. This
  // method is called on multiple threads in the browser process.
  ///
  /*--cef()--*/
  virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() {
    return nullptr;
  }

  ///
  // Return the handler for functionality specific to the render process. This
  // method is called on the render process main thread.
  ///
  /*--cef()--*/
  virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() {
    return nullptr;
  }
};

主要包含了下面几个函数:

  • OnBeforeCommandLineProcessing,启动任何一个程序,都会输入一些命令行参数,这个函数提供创建app程序时,修改处理命令行参数的能力。
  • GetBrowserProcessHandler,提供自定义浏览器进程实体控制器的能力。下面会提到。
  • GetRenderProcessHandler,提供自定义renderer进程实体控制器的能力。下面也会提到。
  • 其他的在simple例子里没怎么用,后续再说。

CefApp在simple例子中的使用

  • 在程序的main函数,初始化的时候,就需要new一个CefApp的对象:

     CefRefPtr<CefApp> app = new SimpleApp();
    
  • 在cefsimple的例子里,SimpleApp同时担任了CefApp,GetBrowserProcessHandler和CefRenderProcessHandler的管理类,当然是可以分开的。

    class SimpleApp : public CefApp, public CefBrowserProcessHandler, public CefRenderProcessHandler {...}
    

    在SimpleApp中定义了GetBrowserProcessHandler函数,就是返回自身:

    // CefApp methods:
    virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
        OVERRIDE {
      return this;
    }
    

    在SimpleApp中没有定义了GetRenderProcessHandler。

  • 在初始化的过程函数CefExecuteProcess中传入了app这个对象。在CefExecuteProcess后续的一些类中,在不同的浏览器生命周期或者某种事件驱动中,就会调用到这几个函数:
    context中的OnContextInitialized函数,调用了GetBrowserProcessHandler。

    void CefContext::OnContextInitialized() {
      CEF_REQUIRE_UIT();
    
      if (application_) {
        // Notify the handler after the global browser context has initialized.
        CefRefPtr<CefRequestContext> request_context =
            CefRequestContext::GetGlobalContext();
        auto impl = static_cast<CefRequestContextImpl*>(request_context.get());
        impl->ExecuteWhenBrowserContextInitialized(base::BindOnce(
            [](CefRefPtr<CefApp> app) {
              CefRefPtr<CefBrowserProcessHandler> handler =
                  app->GetBrowserProcessHandler();
              if (handler) {
                handler->OnContextInitialized();
              }
            },
            application_));
      }
    }
    

    在浏览器代理里:

    CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserDelegate::CreateBrowserHost(
        content::WebContents* web_contents,
        const CefBrowserSettings& settings,
        CefRefPtr<CefClient> client,
        std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
        scoped_refptr<CefBrowserInfo> browser_info,
        bool is_devtools_popup,
        CefRefPtr<ChromeBrowserHostImpl> opener,
        CefRefPtr<CefRequestContextImpl> request_context_impl) {
      CEF_REQUIRE_UIT();
      DCHECK(web_contents);
      DCHECK(platform_delegate);
      DCHECK(browser_info);
      DCHECK(request_context_impl);
    
      // If |opener| is non-nullptr it must be a popup window.
      DCHECK(!opener.get() || browser_info->is_popup());
    
      if (!client) {
        if (auto app = CefAppManager::Get()->GetApplication()) {
          if (auto bph = app->GetBrowserProcessHandler()) {
            client = bph->GetDefaultClient();
          }
        }
      }
      ...
    }
    

    这个就涉及太多的内部代码,就不一一说了,大家知道在程序启动后,由这两个函数来返回Browser和Renderer进程管理的handle类就行了。

CefBrowserProcessHandler类

上面提到了,在CefApp中返回了CefBrowserProcessHandler类的对象。

在cefsimple中,CefSimple类也充当了CefBrowserProcessHandler类的角色(继承)。在CefBrowserProcessHandler类中(cef_browser_process_handle.h),定义了下面这些函数:

///
// Class used to implement browser process callbacks. The methods of this class
// will be called on the browser process main thread unless otherwise indicated.
///
/*--cef(source=client,no_debugct_check)--*/
class    : public virtual CefBaseRefCounted {
 public:
  ///
  // Called on the browser process UI thread to retrieve the list of schemes
  // that should support cookies. If |include_defaults| is true the default
  // schemes ("http", "https", "ws" and "wss") will also be supported. Providing
  // an empty |schemes| value and setting |include_defaults| to false will
  // disable all loading and saving of cookies.
  //
  // This state will apply to the CefCookieManager associated with the global
  // CefRequestContext. It will also be used as the initial state for any new
  // CefRequestContexts created by the client. After creating a new
  // CefRequestContext the CefCookieManager::SetSupportedSchemes method may be
  // called on the associated CefCookieManager to futher override these values.
  ///
  /*--cef()--*/
  virtual void GetCookieableSchemes(std::vector<CefString>& schemes,
                                    bool& include_defaults) {}

  ///
  // Called on the browser process UI thread immediately after the CEF context
  // has been initialized.
  ///
  /*--cef()--*/
  virtual void OnContextInitialized() {}

  ///
  // Called before a child process is launched. Will be called on the browser
  // process UI thread when launching a render process and on the browser
  // process IO thread when launching a GPU or plugin process. Provides an
  // opportunity to modify the child process command line. Do not keep a
  // reference to |command_line| outside of this method.
  ///
  /*--cef()--*/
  virtual void OnBeforeChildProcessLaunch(
      CefRefPtr<CefCommandLine> command_line) {}

  ///
  // Return the handler for printing on Linux. If a print handler is not
  // provided then printing will not be supported on the Linux platform.
  ///
  /*--cef()--*/
  virtual CefRefPtr<CefPrintHandler> GetPrintHandler() { return nullptr; }

  ///
  // Called from any thread when work has been scheduled for the browser process
  // main (UI) thread. This callback is used in combination with CefSettings.
  // external_message_pump and CefDoMessageLoopWork() in cases where the CEF
  // message loop must be integrated into an existing application message loop
  // (see additional comments and warnings on CefDoMessageLoopWork). This
  // callback should schedule a CefDoMessageLoopWork() call to happen on the
  // main (UI) thread. |delay_ms| is the requested delay in milliseconds. If
  // |delay_ms| is <= 0 then the call should happen reasonably soon. If
  // |delay_ms| is > 0 then the call should be scheduled to happen after the
  // specified delay and any currently pending scheduled call should be
  // cancelled.
  ///
  /*--cef()--*/
  virtual void OnScheduleMessagePumpWork(int64 delay_ms) {}

  ///
  // Return the default client for use with a newly created browser window. If
  // null is returned the browser will be unmanaged (no callbacks will be
  // executed for that browser) and application shutdown will be blocked until
  // the browser window is closed manually. This method is currently only used
  // with the chrome runtime.
  ///
  /*--cef()--*/
  virtual CefRefPtr<CefClient> GetDefaultClient() { return nullptr; }
};
  • OnContextInitialized函数,整个浏览器进程的上下文初始化时,可以完成一些定制动作。
  • OnBeforeChildProcessLaunch,和CefApp类似,在process层面上也可以定制。
  • GetPrintHandler,浏览器进程管理了整个浏览器的本地服务,打印等,这个就是返回打印的管理与处理类,可自定义。
  • OnScheduleMessagePumpWork,在消息传递里面提到过的自己管理消息传递,配合pumpwork一起使用,后续有机会再细说,一般不使用。
  • GetDefaultClient,默认的Client类管理器,在后面会讲到。

CefRenderProcessHandler类

和CefBrowserProcessHandler类类似,返回了一个Renderer的管理器:

在cef_render_process_handle.h文件中定义为:

class CefRenderProcessHandler : public virtual CefBaseRefCounted {
 public:
  typedef cef_navigation_type_t NavigationType;

  ///
  // Called after WebKit has been initialized.
  ///
  /*--cef()--*/
  virtual void OnWebKitInitialized() {}

  ///
  // Called after a browser has been created. When browsing cross-origin a new
  // browser will be created before the old browser with the same identifier is
  // destroyed. |extra_info| is a read-only value originating from
  // CefBrowserHost::CreateBrowser(), CefBrowserHost::CreateBrowserSync(),
  // CefLifeSpanHandler::OnBeforePopup() or CefBrowserView::CreateBrowserView().
  ///
  /*--cef()--*/
  virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser,
                                CefRefPtr<CefDictionaryValue> extra_info) {}

  ///
  // Called before a browser is destroyed.
  ///
  /*--cef()--*/
  virtual void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) {}

  ///
  // Return the handler for browser load status events.
  ///
  /*--cef()--*/
  virtual CefRefPtr<CefLoadHandler> GetLoadHandler() { return nullptr; }

  ///
  // Called immediately after the V8 context for a frame has been created. To
  // retrieve the JavaScript 'window' object use the CefV8Context::GetGlobal()
  // method. V8 handles can only be accessed from the thread on which they are
  // created. A task runner for posting tasks on the associated thread can be
  // retrieved via the CefV8Context::GetTaskRunner() method.
  ///
  /*--cef()--*/
  virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
                                CefRefPtr<CefFrame> frame,
                                CefRefPtr<CefV8Context> context) {}

  ///
  // Called immediately before the V8 context for a frame is released. No
  // references to the context should be kept after this method is called.
  ///
  /*--cef()--*/
  virtual void OnContextReleased(CefRefPtr<CefBrowser> browser,
                                 CefRefPtr<CefFrame> frame,
                                 CefRefPtr<CefV8Context> context) {}

  ///
  // Called for global uncaught exceptions in a frame. Execution of this
  // callback is disabled by default. To enable set
  // CefSettings.uncaught_exception_stack_size > 0.
  ///
  /*--cef()--*/
  virtual void OnUncaughtException(CefRefPtr<CefBrowser> browser,
                                   CefRefPtr<CefFrame> frame,
                                   CefRefPtr<CefV8Context> context,
                                   CefRefPtr<CefV8Exception> exception,
                                   CefRefPtr<CefV8StackTrace> stackTrace) {}

  ///
  // Called when a new node in the the browser gets focus. The |node| value may
  // be empty if no specific node has gained focus. The node object passed to
  // this method represents a snapshot of the DOM at the time this method is
  // executed. DOM objects are only valid for the scope of this method. Do not
  // keep references to or attempt to access any DOM objects outside the scope
  // of this method.
  ///
  /*--cef(optional_param=frame,optional_param=node)--*/
  virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
                                    CefRefPtr<CefFrame> frame,
                                    CefRefPtr<CefDOMNode> node) {}

  ///
  // Called when a new message is received from a different process. Return true
  // if the message was handled or false otherwise. Do not keep a reference to
  // or attempt to access the message outside of this callback.
  ///
  /*--cef()--*/
  virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
                                        CefRefPtr<CefFrame> frame,
                                        CefProcessId source_process,
                                        CefRefPtr<CefProcessMessage> message) {
    return false;
  }
};
  • OnWebKitInitialized,渲染器进程WebKit初始化时调用。
  • OnBrowserCreated,浏览器进程启动之后,render需要配合做的一些事情可以在这里自定义。
  • OnBrowserDestroyed,浏览器进程关闭之前,render需要配合做的一些事情。
  • OnContextCreated,render进程上下文创建时使用
  • OnProcessMessageReceived,浏览器进程给render进程发送RPC信息时,render收到消息后就会调用,在CEF消息传递实战中就需要用到这个自定义函数。

文章来源:https://blog.csdn.net/pcgamer/article/details/135481573
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。