当前位置: 首页 > news >正文

理解WebKit和Chromium: Content API和CEF3

# Content API及CEF3

## 概述

相信你一定看过下面这张图(没看过的话去上官网阅读一下“how chromium displays web pages”)。

这是一幅介绍页面如何被渲染和显示的概括性的层次结构图。Renderer进程和Browser进程通过IPC来交换信息,具体的设施就是RendererHost和Renderer等相关类,其作用是把网页的内容(content)渲染成Tab的显示内容。一个Tab可能会包含多个页面的内容,因而它会管理Tab中的多个页面内容。Tab contents之上就是浏览器,Tab contents会把内容绘制在browser窗口的一个标签中

Chromium把RendererHost及其以下部分称为Content同时包括还有很多对HTML5功能实现的支持,contentAPI基于此两部分,包装成为一套公开的接口。Tab contents及以上部分称为Chrome(chrome的原意即是包装在网页内容之上的框)。浏览器中相关的功能仅仅在content API之上才有,而不存在于content API中。

上面的这个架构看起来没什么问题,但是,这对希望把chromium渲染网页的功能包装成接口,被内嵌到任何其他应用程序来说,就有着明显地不足。第一,在WebKit chromium移植中提供了一套公开的接口,但是它在renderer进程,没有很多chromium的提供的高级功能;第二,Chromium在browser进程中没有提供任何公开的接口,也就是说,如果基于RendererHost等开发一套嵌入式的接口,代价将是非常巨大的,因为这些内部使用的类及其接口是经常变动的(注意,确实变化的非常快)。

上图介绍的是WebKit的chromium移植接口和Content API在整个栈中所在的层次,“API boundary”是原来的WebKit的chromium移植所提供的公开接口,“Content API”表示的是新的content API所在的层次。层次上的向上移动带来了使用者的稳定性,HTML5功能的支持,GPU硬件加速功能,沙箱模型等的支持。这里稍微不同的地方是浏览器的功能在Content API之上,所以图片中的Application应该去除掉这一部分。图片来源于WebKit官网,略有修改。

下面我们来看一下chromium官网上所宣称引入Content API的两条原因:

1)  让Chrome的开发者们摆脱content内部的复杂工作原理和机制;

2)  给content和chrome划分清楚的界限来帮助开发者或者嵌入式的使用者们。

在了解了相关背景之后,上面的解释就相当简单明了了。

为了方便测试,chromium中有一个基于content api的简单测试程序content shell。它非常的简单,仅仅是一个壳,调用了content API并实现了部分必需的回调接口,可以用来测试和其他一些简单的功能。

CEF全称chromium embedded framework,其目的是提供一套嵌入式的接口,最初的版本是基于早期的RendererHost和chrome浏览器的很多内部接口开发而来的,在新的CEF3中,其主要依赖于公开的Content API来实现的。

为了清晰地了解它们之间的的关系,下图描述了WebKit, content API,浏览器,content shell和CEF3的层次关系。Chrome浏览器,content shell和CEF3三者都是基于content API开发的,它们只是有不同的实现,服务于不同的应用场景而已。

后面的章节将重点介绍content API和CEF3,因content shell比较简单,故略过。

## Content API

Content API不仅提供了公开和稳定的接口,而且它从诞生以来一个重要的目标就是要支持所有的HTML5功能和GPU硬件加速功能,这可以让它的使用者们不需要很多的工作即可以得到好的HTML5支持和硬件加速机制。同时,借助于现有的多进程架构,一些chromium中的新功能例如沙箱模型等也在其中得到了支持。

下面详细介绍一下Content API包含哪些部分。

Content API的相关的接口定义文件均在content/public目录下,按照功能分成六个部分:每个部分的接口一般也可以分成两类,第一类是嵌入者(embedder,这里可以是Chrome浏览器,CEF3和content shell)调用的接口,另一类是嵌入者实现的回调接口,被content API的内部实现所调用,例如参与实现的逻辑,事件的监听等。

1)App

这部分主要是跟应用程序或者进程的创建和初始化相关。

第一类,主要包括创建进程的初始化函数,content的初始化和关闭

第二类,主要是实现回调函数告诉嵌入者启动完成,进程启动,进程退出,沙盒模型初始化开始和结束等等。

2)Browser

第一类包括,对一些HTML5功能和其他一些高级功能实现的参与,例如resource,sensor,notification, speech recognition, web worker, download, web intents,等等;

第二类包括ContentBrowserClient,主要是实现部分逻辑,被Browser端(或者进程)调用,还有就是一些事件的回调函数.

3)Common

主要定义一些公共的接口,被render和browser共享,例如一些进程相关,参数,gpu相关等等

4)Plugin

仅有一个接口告诉嵌入者plugin进程被创建了

5)Render

第一类包含获取RenderThread的消息循环,注册v8 extension,计算JavaScript表达式等等

第二类包括ContentRendererClient,主要是实现部分逻辑,被Browser端(或者进程)调用,还有就是一些事件的回调函数

6)Utility

工具类接口,主要包括让嵌入者参与content API中的线程创建和消息的过滤。

## CEF和CEF3

早在content API出现之前,CEF便已出现,其目的是提供嵌入式的框架可以让渲染网页的功能方便地嵌入到应用程序之中CEF依赖于chromium浏览器,所以chromium对HTML5的支持和性能上的优势,都得以继续在CEF中体现出来。但是,根据实际测试的结果来看,情况可能并非如此。首先,其对GPU硬件加速的支持不是很好,这时因为它会把GPU内存读回到CPU内存,速度非常慢;再次,因为基于chromium的内部结构,而它们经常变化,所以CEF经常需要发生变化,这对维护来说是件很头痛的事。
得益于content API的出现,CEF的作者也基于它开发了CEF3。CEF3在保持其提供的接口基本不变的情况下,借助content API的能力,其对HTML5和GPU硬件加速提供了较好的支持。它的核心变为调用content API的接口实现content API的回调接口,来组织和包装成CEF3自己的接口以被其他开发者所使用。其好处是,CEF3的接口相对比较简单,使用起来方便,同时不需要实现很多content API的回调接口,但是缺点就是,如果需要使用content API的很多功能,CEF3的接口可能做不到,或者说只能通过直接调用content API接口来完成。

下面简单介绍一下CEF3的接口。

CefClient:回调管理类,包含5个接口用于创建其它的回调类的对象

CefLifeSpanHandler: 回调类,用于控制popup对话框的创建和关闭等操作

CefLoadHandler: 回调类,可以用来监听frame的加载开始,完成,错误等信息

CefRequestHandler: 回调类,用于监听资源加载,重定向等信息

CefDisplayHandler: 回调类,用于监听页面加载状态,地址变化,标题等得信息

CefGeolocationHandler: 回调类,用于CEF3向嵌入者申请geolocation的权限

CefApp: 与进程,命令行参数,代理,资源管理相关的回调类,用于让CEF3的调用者们定制自己的逻辑

CefBrowser: renderer进程中执行浏览相关的类,例如前进,后退等

CefBrowserHost: browser进程中的执行浏览相关的类,其会把请求发送给CefBrowser

CefFrame: 表示的是页面中的一个Frame,可以加载特定url,在该运行环境下执行JavaScript代码等。

V8:CEF3提供支持V8extension的接口,但是这有两个限制,第一,v8 extension仅在Renderer进程使用;第二,仅在沙箱模型关闭时使用。

 ## Content API和WebKit2

Content API和WebKit2的接口都是基于跨进程的结构的,按我个人的理解,它们是互相影响而又互相吸收对方的优点,它们具有相同点,又有不同点:

1)  Content API提供的是一套基于跨进程的架构模型(当然它也可以不是多进程的),这有利于browser(UI)进程的稳定,这同样对WebKit2适用;

2)  Content API不仅如此,它里面包含chromium对于HTML5,GPU硬件加速,和沙箱模型等功能的支持,而WebKit2可能并非如此;

3)  Content API是chromium提出的接口,而WebKit2是一个更加开放和公开的接口,被众多的WebKit移植所使用。

 ## 源文件目录

Content/public/app ,Content/public/browser, Content/public/render, Content/public/common,

Content/public/plugin, Content/public/utility

ContentAPI所包含的相关的目录,里面包含所有的接口

Chromium下的目录结构很多,可分为几类:编译相关,实验性工程相关,谷歌浏览器相关,专有库相关,代码相关

##chromium源码目录说明

  • Android_webview Android上的webview控件
  • Apps Chrome程序相关
  • Ash插件相关
  • Base 提供公共的功能代码
  • Blimp 支持裁剪Chrome的谷歌实验性项目
  • Blink 没用
  • Breakpad开源崩溃报告项目
  • Build 构建配置
  • BuildTools 同上
  • Cc 谷歌合成器(chromium compositor)实现部分 涉及帧/层的渲染布局以及图形合成
  • Cef Chrome的Cef封装
  • Chrome 谷歌浏览器程序核心代码
  • Chrome_elf 错误崩溃报告动态链接库实现
  • ChromeCast Chrome广播相关
  • ChromeOS
  • Clound_Print 谷歌云打印相关 提供谷歌浏览器页面预览打印清单
  • Components 浏览器基础组建目录和资源,比如关于界面资源和UI,Crash页面显示资源和界面等
  • Content 多进程沙盒浏览器核心代码
  • Courgetter 谷歌提供的二进制文件对比核心算法,在谷歌浏览器中用于比较不同版本的二进制差异
  • Cryto 加密库
  • Dbus 数据总线相关
  • Device 提供辅助设备相关支持 ,涉及蓝牙,电池,NFC,USB等
  • Docs
  • Extensions 一个可复用的模块,目前用于扩展Chrome浏览器
  • Gin V8相关的便利类,提供字典,数字缓存等功能
  • Google APIS
  • Google update
  • GPU  涉及blink,gl,ipc等
  • Headless提供无头浏览器模式 – 用于爬虫,自动化测试等
  • Infra 未知
  • IOS IOS系统相关
  • IPC 跨进程通信相关
  • Jingle P2P传输库
  • Mandoline 一个基于Mojo脚本构建Chrome的实验性库
  • Mash ?
  • Media Chrome的多媒体模块,支持音频播放和录音等功能
  • Mojo  支持多类型的沙盒内容
  • Native Client /Natice Client SDK支持在浏览器中执行多脚本语言而不限于js
  • Net 网络功能库
  • Pdf PDF格式相关
  • PPAPI Chrome扩展插件框架
  • Printing 打印相关
  • Remoting 远程控制和调试相关
  • Rlz库 用于统计软件产品分发和市场使用统计相关
  • SandBox 沙盒
  • Sdch 一种压缩格式
  • Skia Skia图像库目前用于Chrome和Android
  • Sql sqlite封装库
  • Storage 数据储存
  • StyleGuide Chrome 代码风格指南
  • Sync Chrome账号多数据同步
  • Testing
  • Third party 第三方库集合
  • Tools Chrome工具集
  • UI Chrome UI库
  • URL 网页链接解析相关
  • V8 V8 js库
  • Win8 在windows上使chrome以metro模式展现

## 参考文献

1.      http://www.chromium.org/developers/content-module/content-api

2.      http://code.google.com/p/chromiumembedded/

3.      http://trac.webkit.org/wiki/WebKit2

相关文章:

  • C++ explicit关键字详解
  • Chromium的启动流程
  • WMIC
  • Windows下调试工具Windbg入门
  • 符号文件
  • 浏览器沙箱(sandBox)到底是什么?
  • 渲染
  • URI和URL的区别比较与理解
  • CEF调试Render进程
  • Chrome V8引擎介绍
  • c++中的 extern “C“
  • 中断向量表
  • WM_NCCREATE与WM_CREATE的区别
  • GetWindowLongPtr
  • WNDCLASSEX
  • [case10]使用RSQL实现端到端的动态查询
  • [微信小程序] 使用ES6特性Class后出现编译异常
  • Android系统模拟器绘制实现概述
  • Java知识点总结(JavaIO-打印流)
  • PAT A1050
  • Vue2.x学习三:事件处理生命周期钩子
  • XML已死 ?
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 给第三方使用接口的 URL 签名实现
  • 计算机在识别图像时“看到”了什么?
  • 如何学习JavaEE,项目又该如何做?
  • 使用API自动生成工具优化前端工作流
  • 一道面试题引发的“血案”
  • MPAndroidChart 教程:Y轴 YAxis
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • $(document).ready(function(){}), $().ready(function(){})和$(function(){})三者区别
  • (附源码)php新闻发布平台 毕业设计 141646
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (论文阅读26/100)Weakly-supervised learning with convolutional neural networks
  • (四)汇编语言——简单程序
  • (一)WLAN定义和基本架构转
  • (一)为什么要选择C++
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)原始图像数据和PDF中的图像数据
  • ***微信公众号支付+微信H5支付+微信扫码支付+小程序支付+APP微信支付解决方案总结...
  • .md即markdown文件的基本常用编写语法
  • .NET MVC第五章、模型绑定获取表单数据
  • .NET 反射的使用
  • .netcore如何运行环境安装到Linux服务器
  • .NET国产化改造探索(一)、VMware安装银河麒麟
  • .NET中使用Protobuffer 实现序列化和反序列化
  • @angular/cli项目构建--Dynamic.Form
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • @Transactional 详解
  • @开发者,一文搞懂什么是 C# 计时器!
  • @四年级家长,这条香港优才计划+华侨生联考捷径,一定要看!
  • [2021 蓝帽杯] One Pointer PHP
  • [C#]C# winform实现imagecaption图像生成描述图文描述生成