FBrowserCEF3Lib浏览器开发技术交流网址

 找回密码
 立即注册
查看: 2753|回复: 0

CEF3专辑-基础篇-04-代码初试2

[复制链接]

签到天数: 32 天

[LV.5]常住居民I

10

主题

34

回帖

554

积分

中级会员LV1

太阳月亮月亮星星

积分
554
发表于 2025-2-17 14:37:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
本帖最后由 KenTien 于 2025-2-17 15:01 编辑

3.1.3. 第一个类:CefApp
操作系统调用完程序的入口函数后,CEF 框架就通过其自身的消息循环机制接管了接下来的执行工作,在上一小节中我们提到了CefApp对象,并且把这个对象传递给了 CEF 的 Initialize方法,CEF 框架收到这个对象之后,会把浏览器进程的一些逻辑交给CefApp对象执行,也就是说CefApp对象就是我们浏览器等进程的入口程序。先看头文件的代码:

[C++] 查看源码 复制代码
/*CefApp接口提供了指定进程的回调访问*/
class CefApp : public virtual CefBaseRefCounted {
public:
//即将执行命令行
  virtual void OnBeforeCommandLineProcessing(const CefString& process_type,
      CefRefPtr<CefCommandLine> command_line) {}
  // 在CEF应用程序中注册自定义的HTTP协议和URL。
  virtual void OnRegisterCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) {}
    //返回浏览器进程特定功能的处理程序。在资源进程中的多个线程上调用此方法。
  virtual CefRefPtr<CefResourceBundleHandler> GetResourceBundleHandler() {
    return nullptr;
  }
  //返回浏览器进程特定功能的处理程序。在浏览器进程中的多个线程上调用此方法。  
  virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() {
    return nullptr;
  }
    //返回浏览器进程特定功能的处理程序。在渲染器进程中的多个线程上调用此方法。
  virtual CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() {
    return nullptr;
  }
};

我们可以这样理解:一个CefApp对应了一个进程,而一个进程可以是Browser Process,可以是Renderer Process。因此,CefApp提供了GetBrowserProcessHandler和GetRendererProcessHandler来分别在相关进程中获取对应的handler。

那么CEF是如何将我们的CefApp实例关联到CEF运行中的呢?

  
[C++] 查看源码 复制代码
context->Initialize(main_args, settings, app, sandbox_info);


3.1.4. 第二个类:CefClient

CefClient接口提供对特定于浏览器等实例的回调的访问。一个CefClient实例可以在任意数量的浏览器之间共享。重要的回调包括:

所有的Handler,例如浏览器的生命周期,上下文菜单,对话框,显示通知,拖动事件,焦点事件,键盘事件等。大多数处理程序是可选的。请参阅cef_client.h中的文档,以了解不实施特定处理程序的副作用(如果有)。

从渲染过程中接收到IPC消息时调用的OnProcessMessageReceived。有关更多信息,请参见“进程间通信”部分。

首先需要解释一下什么什么是特定浏览器实例,实际上,指的是以下过程产生的浏览器实例:


   
[C++] 查看源码 复制代码
CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
        handler, url, browser_settings, nullptr, nullptr,
        new SimpleBrowserViewDelegate());
// 或
    CefBrowserHost::CreateBrowser(window_info, handler, url, browser_settings,
                                  nullptr, nullptr);



通过上述两种方式创建的浏览器实例,是一个概念上的实例,并不是指你能看得到的浏览器的窗口,窗口只是浏览器实例的宿主而已。而浏览器中发生的事件,例如:生命周期的变化,对话框等,都只会通过CefClient中返回的各种类型Handler以及这些Handler接口实例提供的方法回调。

下面是CefClient的声明:


[C++] 查看源码 复制代码
class CefClient : public virtual CefBaseRefCounted {
public:
  virtual CefRefPtr<CefAudioHandler> GetAudioHandler() { return nullptr; }

  virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() {
    return nullptr;
  }

  virtual CefRefPtr<CefDialogHandler> GetDialogHandler() { return nullptr; }

  virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() { return nullptr; }

  virtual CefRefPtr<CefDownloadHandler> GetDownloadHandler() { return nullptr; }

  virtual CefRefPtr<CefDragHandler> GetDragHandler() { return nullptr; }
    // ...... 还有很多的Handler
        
}


在这个CefClient提供了很多GetXXXHandler方法,这些方法会在合适的时候,被CEF调用以得到对应的Handler,然后再调用返回的Handler中的方法。例如,HTML页面中的Title发生变化的时候,就会调用CefClient::CefDisplayHandler()得到一个CefDisplayHandler实例,然后再调用其中的CefDisplayHandler::OnTitleChange,而这些过程不是我们调用的,而是CEF框架完成的。只是具体的实现有我们客户端代码编写。

那么现在思考一下,为什么会有这个CefClient呢?在本人看来主要是如下的理由:

在CefClient中各种回调的事件,本质上发生的地方是渲染进程。因为每当一个浏览器实例(不是浏览器进程)创建的时候,会有一个对应的渲染进程创建(也可能由于配置,而共用一个,这里先认为默认多个一对一)。渲染进程中发生的各种V8事件、下载事件,显示事件等触发后,会通过进程间通讯给到浏览器进程,然后在浏览器进程中找到与之相关的CefClient,然后从CefClient中找到对应的Handler,回调Handler对应的方法。

也就是说,将在渲染进程发生的事件,用在浏览器进程中的CefClient一定的抽象映射,而不是直接在浏览器进程处理器中进行,因为一个浏览器进程可能会创建多个渲染进程,让CefClient作为中间层避免耦合。


当然,文档也为我们指出,CefClient实例与浏览器实例可以不是一一对应的,多个浏览器实例可以共享一个CefClient,如此一来我们也可以总结关于CefClient的一点:非必要情况,不要编写具有状态的CefClient。




您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们 在线手册 视频教程 赞助支持 CEF官网 易语言官网 火山开发官网
拒绝任何人以任何形式在本网站发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表本网站立场!

网址帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!

Archiver| 手机版| 小黑屋| 联系QQ:283987887 劰载中...

Powered by Discuz! X5.0 GMT+8, 2026-9-17 07:32 , Processed in 0.020296 second(s), 11 queries , Redis On.

 川公网安备51090302000262 蜀ICP备2023034329号
快速回复 返回顶部 返回列表