加载 html 页面时,一个正常的加载流程

来源:互联网 发布:淘宝减肥药排行榜 编辑:程序博客网 时间:2024/06/04 17:45

 WebKit,Loader,Network,ResouceLoader,SubresourceLoader

一、类结构及接口
Loader 模块是 Network 模块的客户。 Network 模块提供指定资源的获取和上传功能,获取的资源可能来自网络、本地文件或者缓存。对不同 HTTP 实现的适配会在 Network 层完成,所以 Loader 接触到的基本上是同 OS 和 HTTP 实现无关的 Network 层接口。

如上是 Loader 和 NetWork 之间的类关系图, ResourceHandleClient 是 ResourceHandle 的客户,它定义一系列虚函数,这些虚函数是 ResouceHandle 的回调,继承类实现这些接口。

ResouceHandleClient 的接口同网络传输过程息息相关,一般为某一个网络事件对应的回调。下面是其中的一些接口。

// 一般情况下,在发起网络请求前调用,可以设置特定的 Http

头部,比如 user agent 等,在重定向请求的时候,也会自动调

void willSendRequest(ResourceHandle*, ResourceRequest&, const

ResourceResponse&)

// 上传数据的时候,在 TCP wrtie 事件的时候,向对方发送数据的

时候调用, loader 可以根据这个回调显示上传进度。

void didSendData(ResourceHandle*, unsigned long long

/*bytesSent*/, unsigned long long /*totalBytesToBeSent*/)

// 收到第一个响应包,此时至少 http 的部分头部已经解析(如

status code ), loader 根据响应的头部信息判断请求是否成功

等。

void didReceiveResponse(ResourceHandle*,

const   ResourceResponse&)

// 收到 HTTP 响应数据,类似 tcp 的 read 事件,来 http 响应数据

了, Network 的设计机制是来一段数据上传一段数据。

void didReceiveData(ResourceHandle*, const char*, int,

  int /*lengthReceived*/)

    // 加载完成,数据来齐。

void didFinishLoading(ResourceHandle*, double /*finishTime*/)

// 加载失败

void didFail(ResourceHandle*, const ResourceError&)

// 要求用户鉴权

void didReceiveAuthenticationChallenge(ResourceHandle*,

const AuthenticationChallenge&)

WebCore 把要加载的资源分成两类,一类是主资源,比如 HTML 页面,或者下载项,一类是派生资源,比如 HTML 页面中内嵌的图片或者脚本链接。这两类资源对于回调的处理有很大的不同,比如,同样是下载失败,主资源可能需要向用户报错,派生资源比如页面中的一张图下载失败,可能就是图不显示或者显示代替说明文字而已,不向用户报错。因此有了 MainResourceLoader 和 SubresourceLoader 之分。它们的公共基类 ResourceLoader 则完成一些两种资源下载都需要完成的操作,比如通过回调将加载进程告知上层应用。

ResourceLoader 通过 ResourceNotifier 类将回调传导到 FrameLoaderClient 类。   

主资源的加载是立刻发起的,而派生资源则可能会为了优化网络,在队列中等待 ( 这里的立刻发起是 loader 层面的,不是 Network 层面的 ) 。 ResourceScheduler 这个类就是用来管理资源加载的调度。主要调度对象就是派生资源,会根据 host 来影响资源加载的先后顺序。

主资源和派生资源的加载还有一个区别,主资源目前是没有缓存的,而派生资源是有缓存机制的。这里的缓存指的是 Resouce Cache ,用于保存原始数据(比如 CSS , JS 等),以及解码过的图片数据,通过 Resource Cache 可以节省网络请求和图片解码的时候。不同于 Page Cache , Page Cache 存的是 DOM 树和 Render 树的数据结构,用来在前进后退的时候快速显示页面。

二、加载流程
    下图是加载 html 页面时,一个正常的加载流程。

三、主资源加载过程

香港六he綵图库  http://www.hshk8.com  香港六he綵开.奖结果 http://www.caibaow.com  香港六he綵图库资料  http://www.46tm.com

1.        DocumentLoader 调用 MainResourceLoader::load 向 loader 发起请求

2.        调用 MainResourceLoader::loadNow

3.        调用 MainResourceLoader::willSendRequest

4.        调用 ResourceLoader::willSendRequest, 将 callback 通过 ResourceNotifier 传导给 FrameLoaderClient 。 Client 可以在回调中操作 ResourceRequest ,比如设置请求头部。

香港六he綵网站  http://www.dayyw.com  香港六和綵公司  http://www.jfniuw.com  香港六he綵开.奖记录  http://www.dzmww.com

5.        调用 PolicyChecker::checkNavigationPolicy 过滤掉重复请求等

6.        loader 调用 ResourceHandle::create 向 Network 发起加载请求

7.        收到第一个 HTTP 响应数据包 ,Network 回调 MainResourceLoader::didReceiveResponse ,主要处理 HTTP 头部。

8.        调用 PolicyChecker:: checkContentPolicy, 并最终通过 FrameLoaderClient 的 dispatchDecidePolicyForMIMEType 判断是否为下载请求(存在 "Content-Disposition"http 头部)

香港六he綵资料  http://www.58hcw.com  香港六he綵开.奖现场  http://www.aichi28.com  香港六he綵开.奖  http://www.tiantss.com

9.        调用 MainResourceLoader::continueAfterContentPolicy ,根据 ResourceResponse 检测是否发生错误。

10.   调用 ResourceLoader::didReceiveResponse ,将 callback 通过 ResourceNotifier 传导给 FrameLoaderClient 。

11.   收到 HTTP 体部数据,调用 MainResourceLoader::didReceiveData

12.   调用 ResourceLoader::didReceiveData ,将 callback 通过 ResourceNotifier 传导给 FrameLoaderClient

13.   调用 MainResourceLoader::addData

香港六he綵网站  http://www.dayyw.com  香港六和綵公司  http://www.jfniuw.com  香港六he綵开.奖记录  http://www.dzmww.com

14.   调用 DocumentLoader::receivedData

15.   调用 DocumentLoader::commitLoad

16.   调用 FrameLoader::commitProvisionalLoad , FrameLoader 从 provisional 状态跃迁到 Committed 状态

17.   调用 FrameLoaderClientQt::committedLoad

香港六he綵图库  http://www.hshk8.com  香港六he綵开.奖结果 http://www.caibaow.com  香港六he綵图库资料  http://www.46tm.com

18.   调用 DocumentLoader::commitData ,启动 Writer 对象来处理数据( DocumentWriter::setEncoding , DocumentWriter::addData )

19.   调用 DocumentWriter::addData

20.   调用 DocumentParser::appendByte

香港六he綵资料  http://www.58hcw.com  香港六he綵开.奖现场  http://www.aichi28.com  香港六he綵开.奖  http://www.tiantss.com

21.   调用 DecodedDataDocumentParser::appendBytes 对文本编码进行解码

22.   调用 HTMLDocumentParser::append ,进行 HTML 解析

23.   数据来齐,调用 MainResourceLoader::didFinishLoading

香港六he綵网站  http://www.dayyw.com  香港六和綵公司  http://www.jfniuw.com  香港六he綵开.奖记录  http://www.dzmww.com

24.   调用 FrameLoader::finishedLoading

25.   调用 DocumentLoader::finishedLoading

26.   调用 FrameLoader::finishedLoadingDocument ,启动 writer 对象接收剩余数据,重复 19-22 进行解析

27.   调用 DocumentWriter::end 结束接收数据(调用 Document::finishParsing )

香港六he綵资料  http://www.58hcw.com  香港六he綵开.奖现场  http://www.aichi28.com  香港六he綵开.奖  http://www.tiantss.com

28.   调用 HTMLDocumentParser::finish

四、派生资源加载流程
  在派生资源的加载中, SubresourceLoader 更多起到的是一个转发的作用,通过它的 client ( SubresourceLoaderClient 类)来完成操作。

香港六he綵网站  http://www.dayyw.com  香港六和綵公司  http://www.jfniuw.com  香港六he綵开.奖记录  http://www.dzmww.com

   各个加载阶段的处理在 SubresourceLoaderClient 的派生类 CachedResourceRequest,Loader,IconLoader 中完成。 Client 会创建 SubresourceLoader 。

请求发起阶段, ResourceLoadScheduler 负责对 SubresourceLoader 进行调度。

香港六he綵网站  http://www.dayyw.com  香港六和綵公司  http://www.jfniuw.com  香港六he綵开.奖记录  http://www.dzmww.com

   Document 类会创建 CachedResourceLoader 类的对象 m_cachedResourceLoader, 这个类 ( 对象 ) 提供了对 Document 的派生资源的访问接口 requestImage , requestCSSStyleSheet , requestUserCSSStyleSheet , requestScript , requestFont , requestXSLStyleSheet , requestLinkPrefetch 。为了实现这些接口, CachedResourceLoader 需要创建 CachedResourceRequest 对象来发起请求。

香港六he綵资料  http://www.58hcw.com  香港六he綵开.奖现场  http://www.aichi28.com  香港六he綵开.奖  http://www.tiantss.com

一般情况下,一个 Document 拥有一个 CachedResourceLoader 类实例。

MemoryCache 类则对提供缓存条目的管理,可以方便地进行 add , remove ,缓存淘汰等。具体的缓存条目则是通过 CachedResource 类存储, MemoryCache 类维护了一个 HashMap 存储所有缓存条目。

HashMap <String,CachedResource> m_resources;

香港六he綵图库  http://www.hshk8.com  香港六he綵开.奖结果 http://www.caibaow.com  香港六he綵图库资料  http://www.46tm.com

CachedResourceRequest 依赖于 CachedResource, 在 CacheResourceRequest 的构造函数中,会传入 CachedResource 对象作为参数。 CachedResource 既存储响应体部,也存储同 cache 相关的头部。在发起请求前,会检查是否有 cache 的 validator ,在收到响应的时候,则需要更新对应的头部。 CachedResource 类实现了 RFC2616 中的缓存一节。实际上 CachedResource 类真正完成了同网络的通信。 CachedResource 类根据申请的资源类型派生出不同的子类。

香港六he綵图库  http://www.hshk8.com  香港六he綵开.奖结果 http://www.caibaow.com  香港六he綵图库资料  http://www.46tm.com

      CachedResource 类的使用者必须是 CachedResourceClient, 在这个类中维护了 CachedResourceClient 类的集合 m_clients 。每一个 Client 通过 addClient 和 removeClient 将自己加入到该类的 Client 集合中。 CachedResourceClientWalker 则提供了 CachedResouceClient 的一个遍历接口。当数据来齐的时候, CachedResource 类会通过 CachedResouceClient::notifyFinished 接口通知使用者。

原创粉丝点击