学校:上海交通大学软件工程 学历:硕士 行业:从事流媒体移动开发 QQ: 412595942 邮箱:yiikai1987910@gmail.com
分类: C/C++
2013-02-06 18:08:03
Webkit的作用在这就不多做介绍了,本篇主要还是个人在源码分析了webkit之后的心得总结!
webkit有上千个类,在这么错综复杂的结构里看流程无疑找死,好吧,用GDB调试看吧!
环境:webkit + Qt4.8.4 + gdb
调试之前,当然先要生成调试版本的程序了,关于调试环境的搭建后续文章会阐述。。。。。。。
现在就开始总结加载流程吧!
当我们在浏览器中输入网站地址后,会通过把url赋给ResourceRequest这个类,并将ResourceRequest作为类参数传给Frameloader的load方法,ResourceRequest从头文件看貌似是关于网络协议的一系列接口封装(以后再深入了解这个类,应该可以提取出来做自己为用)。之后通过CreateDocumentLoader创建出documentloader对象(该对象负责对于请求资源动作的一系列封装,eg.请求数据,数据请求完成等动作的响应,其实就是对于下载接口的一层封装),并作为参数传给frameloader的load方法。
在该方法中,获取之前得到的ResourceRequest对象,通过addExtraFieldsToMainResourceRequest对于ResourceRequest对象中的一些关于http的头信息的内如注册,比如Agent字段和Accept字段等(其实就是填充HTTP协议头),接着通过调用loadwithDocumentloader进行正式的下载流程。
先来看下之前操作流程的栈信息:
注:frameloader doucmentloader 和resourceRequest这几个类之间都是你中有我我中有你的好基友,所以都可以在各自的类中分别调用到
接着往下看,进入loadwithDocumentloader之后,获取之前的resourceRequest对象的url,并将该url对象给到KURL类中(该类又是一个对于URL的功能封装),之后通过Documentloader的startloadingMainResource方法开始加载主页面数据(一般网页就是html文件),接着创建mainresourceloader类对象(这个类看名字就知道是做什么的了)
通过调用loadnow开始进行下载工作。
先来看下之前操作流程的栈信息:
因为我用的是Qt的port,所以具体的下载动作由Qt来做了,接着看数据接收的操作。
当数据下载完之后,mainresourceloader的didreceivedata负责接收下载下来的数据,把接收的数据给到Documentloader,再由Documentloader的方法commitload发布加载的内容(在这一步中,浏览器先将旧的页面清除掉在加载新的页面),之后进过很多步的转发,给到了DOM文件夹中的DecodeDataDocumentParse的appendBytes。从这开始正式进入HTML的解压和词法解析流程,这之后将对HTML内容解析工作。
先来看下之前操作流程的栈信息:
总结下主要流程:
1. DocumentLoader 调用 MainResourceLoader::load 向 loader 发起请求
2. 调用 MainResourceLoader::loadNow
3. 调用 MainResourceLoader::willSendRequest
4. 调用 ResourceLoader::willSendRequest, 将 callback 通过 ResourceNotifier 传导给 FrameLoaderClient 。 Client 可以在回调中操作 ResourceRequest ,比如设置请求头部。
5. 调用 PolicyChecker::checkNavigationPolicy 过滤掉重复请求等
6. loader 调用 ResourceHandle::create 向 Network 发起加载请求
7. 收到第一个 HTTP 响应数据包 ,Network 回调MainResourceLoader::didReceiveResponse ,主要处理 HTTP 头部。
8. 调用 PolicyChecker:: checkContentPolicy, 并最终通过 FrameLoaderClient 的dispatchDecidePolicyForMIMEType 判断是否为下载请求(存在 "Content-Disposition"http 头部)
9. 调用 MainResourceLoader::continueAfterContentPolicy ,根据ResourceResponse 检测是否发生错误。
10. 调用 ResourceLoader::didReceiveResponse ,将 callback 通过 ResourceNotifier传导给 FrameLoaderClient 。
11. 收到 HTTP 体部数据,调用 MainResourceLoader::didReceiveData
12. 调用 ResourceLoader::didReceiveData ,将 callback 通过 ResourceNotifier 传导给 FrameLoaderClient
13. 调用 MainResourceLoader::addData
14. 调用 DocumentLoader::receivedData
15. 调用 DocumentLoader::commitLoad
16. 调用 FrameLoader::commitProvisionalLoad , FrameLoader 从 provisional 状态跃迁到 Committed 状态
17. 调用 FrameLoaderClientQt::committedLoad
18. 调用 DocumentLoader::commitData ,启动 Writer 对象来处理数据(DocumentWriter::setEncoding , DocumentWriter::addData )
19. 调用 DocumentWriter::addData
20. 调用 DocumentParser::appendByte
21. 调用 DecodedDataDocumentParser::appendBytes 对文本编码进行解码
22. 调用 HTMLDocumentParser::append ,进行 HTML 解析
好了,下载加载流程就到这,下篇会带来详细的HTML词法解析和压缩流程
CU博客助理2013-04-09 13:58:19
嘉宾点评: 首先要恭喜DBOYaoao,基于Qt用GDB对webkit进行调试还真不是谁都能想到也不是谁都能做到的,曾经有人为了优化webkit也做过同样的事情。不过这不重要,重要的是大家都看到苹果落了地,不少还被苹果砸了头,但他们并没有想更没有再进一步思考。而你,开了一个好头,让CU的朋友们见识了一次街头魔术真人揭秘秀。而我特别想做两点补充:第一,如果DBOYaoao可以深入研究PC平台和手机平台的主流浏览器引擎的话,以后畅销书《大话浏览器XX》作者定是非你莫属;第二,对于IT技术小白而言,编代码编的再好,工资上升的空间依旧有限,而若想拥有更丰厚的回报,就应该向博主DBOYaoao好好学习,洞察黑盒背后的原理,这才是王道!
(以上是邀请嘉宾的点评,感谢您参与“原创博文评选”获奖结果即将公布)