WebKit Loader 模块介绍

webkit只是一个排版引擎,在Webkit排版/渲染一个网页之前,需要从网络上、或者本地文件系统中读到网页的http数据,对webkit来讲,他要的就是数据,不管你是从网络读的还是本地文件读的。

Loader就是这样一个模块,它承上启下,不仅负责为webkit引擎提供数据,还控制着webkit的绘制。另外,它同时还与提供数据的“来源”打交道。

先简单举例说明:

用户输入一个url,这时是Loader接收url请求,它把url传递给curl,设置curl的回调函数,当curl读到数据,loader把数据传递给Parser,开始生成DOM

一.下面重点介绍一下与Loader相关的数据结构和模块。

Frame:可以看做是浏览器外壳调用Loader的总入口,它就像我们印象中的一个网页,它关注的是页面的显示(FrameView) 、页面数据的加载(FrameLoader)、页面内的各种控制器 (Editor,EventHandler, ScriptController, etc.) 等等,它包含以下模块(只列出重点):

Document

Page

FrameView

RenderView

FrameLoader

DOMWindow

下面分别对以上模块进行介绍:

1)Document:这个类的爷爷类是Node ,它是 DOM树各元素的基类; Document有个子类是 HTMLDocument,它是整个文档 DOM树的根结点,这样就明白了:原来Document 就是描述具体文档的代码,看一下它的头文件,就更明白了,它的属性与方法就是围绕着各种各样的结点:Text Comment CDATASection Element……

2)Page:我的理解是,PageFrame(严格说是FrameView)是一一对应的,Frame关注UIPage关注数据。现在的浏览器一般都提供同时打开多个窗口,每一个窗口对应的数据就是这个Page在管理了。

page.cpp文件里,还有个重要的全局指针变量:static HashSet<Page*>* allPages; 这个变量包含了所有的page实例。

3)FrameView: 可以理解为为一个网页的ViewPort,它提供一个显示区域,同时包含的有Render根节点、layout排版相关接口、Scroll相关等。FrameViewLayout排版的总入口。

4)RenderView: FrameView差不多,只是分工不同,它管理与Render树相关的事情。

5)FrameLoader:重点,FrameLoader类将Documents加载到Frames。当点击一个链接时,FrameLoader创建一个新的处于“policy”状态的DocumentLoader对象,一旦webkit指示FrameLoader将本次加载视为一个导航(navigation)FrameLoader就推动DocumentLoader进入“provisional”状态,(在该状态,DocumentLoader发调用CURL发起一个网络请求,并等待是html还是下载文件。)同时,DocumentLoader会创建一个MainResourceLoader对象(该对象在后面单独介绍)。

6)。DOMWindow:实现了Dom的一些接口,如CreateNode等。



二、WebkitLoader有两条加载数据的主线:(从上图可以看到)

1. MainResourceLoader:该模块主要加载主网页请求。后面称为MainResource

2. DocLoader:该模块除了主网页外的所有子请求,如:.js文件,图片资源,.css文件。 后面称为SubResource

MainResource部分:

FrameLoader->DocumentLoader->MainResourceLoader-ResourceHandleDocumentLoader经历状态:1)"policy"2) "provisional" 3) "commited"分别是等待、作为navigation发送networkrequest、文件下载完毕

Subresource部分:

DocLoader->Cache->[CacheObjects]example: CacheImage->SubresourceLoader->ResourceHandle当请求一个资源时,首先查看Cache中是否存在该对象,如果存在直接返回;如果不存在,创建该Cache对象(如CacheImage),然后创建一个SubresourceLoader,加载资源。

例如:

加载图片时,DocLoader首先询问Cache,在内存中是否也存在(CachedImage对象),如果已存在,则直接加载,即省了时间又省了流量。如果图片不在Cache中,Cache首先创建一个新的CachedImage对象来代表该图片,然后由CachedImage对象调用Loader对象发起一个网络请求,Loader对象创建SubResourceLoader。后面的流程就一样了,SubResourceLoader也是直接把ResourceHandle打交道的。

接下来跟踪一下Loader发送请求的代码实现:

1. 用户输入URL后,最先调用的接口是:

FrameLoader::load(constResourceRequest& request)

ResourceRequest包含了:

KURL(处理url的一个类)setHTTPHeaderFieldsetHTTPContentType等与HTTP头部相关的函数

2.Load()通过ResourceRequest数据调用createDocumentLoader(request,substituteData)来创建一个DocumentLoader

3.Load()函数继续给request设置HttpAccept,Cache-Control HTTP头等信息。

4.设置FrameLoader::checkNavigationPolicy函数进入"Policy"状态。

5.判断该url是否在Cache中等一系列状态判断后,进入DocumentLoader::startLoadingMainResource函数准备加载MainResource。该函数首先会创建调用MainResourceLoader

6.进入MainResourceLoader::load函数,调用illSendRequest(r,ResourceResponse());做发送请求前的准备。

7.调用PolicyCheck检查policy的状态后,进入FrameLoader::callContinueLoadAfterNavigationPolicy继续往下走。

8:MainResourceLoader::loadNow(ResourceRequest&r)函数里创建ResourceHandle,在创建ResourceHandle函数中,调用start函数,start函数把ResourceHandle自已添加到ResourceHandleManagerm_resourceHandleList队列里。

同时,调用m_downloadTimer.startOneShot激活网页请求下载的定时器。(这是个毫秒级的定时器,采用定时器的原因也是为了实现异步的请法)

可以看到m_downloadTimer的定义:Timer<ResourceHandleManager> m_downloadTimer;

m_downloadTimer是实现的一个定时器模块类,在它的构造函数里已经传入了回调函数的地址:ResourceHandleManager::downloadTimerCallback

9. 一路返回到Load()函数,并返回到调用源,函数执行完毕。

10. ResourceHandleManager::downloadTimerCallback回调函数被定时器调用。

11. 可以看到downloadTimerCallback函数的代码:

调用libcurl库的接口curl_multi_fdset,curl_multi_perform等查询数据。


webkit应用场景再举例:

用户给出一个URL (直接输入或者点击链接或者JavaScript 解析等方式)。然后浏览器外壳调用FrameLoader 来装载页面。FrameLoader 首先检查一些条件(policyCheck()) ,如 URL是否非空、 URL是否可达,用户是否取消等等。然后通过DocumentLoader 启动一个MainResourceLoader 来装载页面。MainResourceLoader调用 network 模块中的接口来下载页面内容(ResourceHandle ),实际上这里的Resourcehandle已经是平台相关的内容了,接收到数据以后,会有回调函数,告诉MainResourceLoader数据已经接收到了。然后一路返回到FrameLoader 开始调用HTMLTokenizer 解析 HTML文本。解析过程中,如果遇到Javascript 脚本的话,也会调用Javascript 引擎( Webkit中的 JavascriptCore chrome 中的 V8)来解析。数据被解析完了以后,生成了一个一个的node ,生成 DOM 树和Render 树,然后通过FrameLoaderClient 调用外部的壳把内容显示出来。”


因此,总结Loader的功能:

Loader 是在WebKit里面一个很重要的连接器,通过loader发起IO下载网页,图片等数据,再通过loader发起解析,以及最后的渲染功能。


上面过程还没缕清,需要以后慢慢体味。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章