写点什么

WebKit 三件套 (1):WebKit 之 WebCore 篇

作者:zhoulujun
  • 2023-04-09
    广东
  • 本文字数:2920 字

    阅读完需:约 10 分钟

导语:

Chrome 浏览器的代码量其实是非常庞大的,要想对其有深入的理解,仅仅编译编译调试调试,是很难深入下去的。让我们还是从其主要部分如多进程管理通信、WebKit、V8、Skia、WinHttp、Sanbox 等着手分析其主要流程及数据结构,或许能达到事半功倍的效果,而 WebKit 是其中非常重要的一部分,是 Chrome 的核心引擎部分,其他部分都是基于它来集成的,深入了解了 WebKit,对 Chrome 的理解就会迎刃而解,再说 WebKit 作为一个相对独立的浏览器引擎在 Safari、iPhone、Adobe AIR 等中都有应用,非常值得大家深入的研究研究。就像前面的文章所说,WebKit 主要包括三个部分 WebCore、JavascriptCore、Ports

  • Javascript 的实现(JavaScriptCore)

  • 布局渲染的实现(WebCore)

  • 外接口的支持(ports)

    WebKit 作为一个浏览器引擎,其相对于 Gecko 而言一个较大的特点就是便于移植,嵌入到其他程序中,目前大家已了解使用 WebKit 引擎的应用包括 Safari、iPhone、Chrome、Android、Nokia S60 Browser 及 KDE QT4.4 等,同时还有其他方面的移植如 Gtk、wxWidget、3D 等,可以说 WebKit 从架构上讲其 Port 移植方面的设计及应用,是非常优秀的

让我们先从 WebCore 部分出发吧

WebCore 所包含的主要内容

从源代码目录结构来看

WebCore 目录主要包括如下目录:

bindings 包含将 Dom Binding 给 JavascriptCore 方面的代码,同时包含依据 idl 接口描述文件,自动生成对应于 JavascriptCore 的 Binding 实现的脚本等内容;

  • bridge 主要包含 NPPlugin 方面的接口访问等内容;

  • css 主要包括与 css 方面相关的内容如解析、不同 css 规则的定义与实现、css Binding 给 JS 的接口定义等内容;

  • dom 主要包括 dom 方面相关的内容如不同 dom 元素的定义与实现、dom Binding 给 JS 的接口定义等内容;

  • html 主要包括 html 方面相关的内容如不同 html 元素的定义与实现、HTMLTokenizer 及 HTMLParser 等内容;

  • loader 主要包括装载资源如 html 页面、css、js 及 image 等方面内容;

  • page 主要包括描述一个 Web 页面所涉及的内容如 page、frame、frameview、frametree、setting、history、chrome、chromeclient 等内容;

  • rendering 主要包括如何使用样式,组织布局、显示 html 元素等方面内容;

  • plugins 主要包括浏览端如何实现 NPPlugin 方面的内容;

  • svg 主要包括与 svg 方面相关的内容;

  • xml 主要包括与 xml 方面相关的内容如 xml parser、XPath、XSLT 等;

  • platform 主要包括与不同平台或外部库相关的内容如 graphics(图形输出方面)、network(网络处理方面)、image-decoders(解析不同图片格式方面)等;

主要数据结构

为了更加简单有效的描述浏览网页的内容及过程,WebKit 为了明显区分不同方面的内容,采取了不同的 namespace 如 webcore、javascriptcore、webkit 等,webcore 方面的主要数据结构有:

webcore::page、webcore::frame、webcore::FrameLoader、webcore::FrameView、Document、DOMWindow、KJSProxy、DocumentLoader、ResourceHandle、ResourceRequest、ResouceResponse、MainResourceLoader、RenderObject、RenderView 等;主要数据结构描述如下:

WebView 及 WebFrame 与 page、frame 之间的关系


20210420211951501923254.jpeg


FrameLoader、DocumentLoader、DocLoader 类结构


FrameLoader、DocumentLoader、DocLoader类结构.jpeg


主要 Document 类结构


webkit主要Document类结构


FrameView 类主要结构


20210421164027442132989.jpeg


总的说来,WebCore 包含了浏览器引擎的核心部分如处理 html、dom、css、svg、获取资源、渲染页面过程控制、回调/通知外壳程序以及与 Javascript 实现的 Binding 等等;

一个 Http 请求在 WebCore 中的主要流程

1、当调用 webkit_web_view_open(url)时会触发

core(webView)->mainFrame()->loader()->load(uri)(即调用 FrameLoader.load)来发起一个 Http 页面请求;

FrameLoader.load 方法的主要处理过程如图:

20210421164027577495305.jpeg


2、一旦发起 ResourceHandle::start,就会由网络库向 web 服务器发起一个 http 请求;

3、而 MainResourceLoader 作为一个 ResouceHandleClient,提供了诸如 didReceiveData()、didReceiveResponse()等回调接口以供网络库调用,一旦从 web 服务器获得相关数据后网络库部分则会调用相关接口如 didReceiveData 等;

4、MainResouceLoader::didReceiveData 的主要回调处理过程如下图:


20210421164027658641995.jpeg


5、通过回调 didReceiveData()方法,进而调用 Node.attach()方法,这样就会解析生成 document,同时会创建 frameview、domwindow 等;

6、创建的 frameview 会触发 layoutTimerFired 时间 Timer,进而调用 layout()方法,从而触发 RenderObject 的创建、布局等,同时或许会 invalidateRect,进而触发操作系统图形库的 paint 消息事件;

7、由程序主消息处理循环接收 paint 消息事件,进而获取对应 frame,获取或创建 GraphicContext,然后调用 frame->view()->paint(&ctx,...),从而触发对应 RenderObject 树进行重画处理,这样一个完整的页面就会逐步的显示出来。

网络库、图形库、Javascript 实现与 WebCore 的集成

为方便扩展及模块化,WebCore 在处理浏览页面的过程中,往往使用了类似 java 或 gecko 中接口的概念,一般先定义一组公共接口或基类,然后由不同模块来实现。

如网络处理部分由 WebCore 提供一个 ResourceHandle 类,而在不同的目录如 cf、curl、qt、soup、win 等中在不同网络库的支持下对 ResourceHandle 类提供不同的实现,待编译时择机选择对应目录下的实现,这种方式从架构的角度看比较简单,但往往不能让程序同时使用多个网络库,进而由程序动态切换使用不同网络库实现,而 gecko 在 xpcom 的基础上提供了对于这种扩展形式的支持;其中 Chrome 对 ResouceHanle 类的实现基于 WinHttp 网络库。

同样 WebCore 对图形库的集成,也是采取这种方式来实现,如由 WebCore 提供一个 GraphicsContext 类,然后在不同的目录如 cairo、cg、qt、win、wx 中在不同的图形库支持下对 GraphicsContext 提供不同的实现。其中 Chrome 对 GraphicsContext 类的实现基于 Skia 图形库。

WebCore 中实现的 dom、html、svg、css 等,往往需要通过一定的方式输出给 Javascript 的实现如 JavascriptCore、V8,以便 JS Engineer 能认识这些 dom 元素等,并且能调用其中的方法,这种方式叫做 Binding,为了便于将 WebCore 中相对固定的 dom、html、svg、css 接口等极其方便的 Binding 出去,WebKit 使用了极其高效及神奇的方式来实现。

首先定义一组非标准的 idl 接口,然后通过运行一组 perl 脚本如 generate-bindings.pl、CodeGenerator.pm、CodeGeneratorJS.pm 等,就可根据 idl 接口定义,生成一组符合指定 Javascript 实现规则的脚本对象类。这样极大的减轻了开发人员的投入及编码错误的发生。

这一点与 gecko 中将不同的 xpcom 接口 Binding 给 Javascript 实现有本质上的差别,在 gecko 中通过 xpconnect 及一组 classinfo 来维护原生元素与 JS 对象之间的关系,不同原生元素对应的 JS 对象的创建及属性方法的 Binding 完全依赖于 xpconnect 的实现及 classinfo 的定义,要添加删除修改 Binding 的属性与方法,只需修改 classinfo;而 WebKit 中 Binding,相对简单明了,不同原生元素对应的 JS 对象的属性与方法由 idl 接口文件来定义,而具体实现则交给威力强大的 generate-bindings.pl 来对应生成实现的代码,这样编译时就可以轻松实现 Binding。


参考资源:

浅谈 WebKit 之 JavaScriptCore/V8 篇 http://ourpgh.blogspot.com/2008/09/webkitjavascriptcorev8.html

https://webkit.org/


转载本站文章《WebKit三件套(1):WebKit之WebCore篇》,请注明出处:https://www.zhoulujun.cn/html/webfront/browser/webkit/2021_0421_8630.html

用户头像

zhoulujun

关注

还未添加个人签名 2021-06-25 加入

15年草根站长,尽在:zhoulujun.cn

评论

发布
暂无评论
WebKit三件套(1):WebKit之WebCore篇_Webkit_zhoulujun_InfoQ写作社区