Webkit 源代码由三大模块组成:
1). WebCore ,
2). WebKit ,
3). JavaScriptCore 。
WebCore :排版引擎焦点, WebCore 包含主要以下模块: Loader, Parser(DOM,Render), Layout,Paint 。
WebKit :移植层,主要包含: GUI , File System, Thread , Text ,图片编解码等与平台相关的函数。
JavaScriptCore : JS 虚拟机,相对独立,主要用于操作 DOM , DOM 是 W3C 界说的规范,主要用于界说外部可以操作的欣赏器内核的接口,而 Webcore 必须实现 DOM 规范。
( 详细的 DOM 规范可以查 W3c.)
- WebKit 分模块介绍 ( 这里简单列出,后面再详细介绍 )
Webkit 平台相关
1) CURL 网络库
2) LibPng, LibJpeg 图形处理相关
3) Sqlite 小型关系 数据库
WebCore 焦点
1) Loader 加载资源及 Cache 实现 (Curl)
2) DOM : HTML 词法分析与语法分析
3) DOM : DOM 节点与 Render 节点创建,形成 DOM 树
4) Render : Render 树介绍, RenderBox
5) Layout :排版介绍
6) Css Parser 模块
7) Binding-DOM 与 JavascriptCore 绑定的成果
JavascriptCore-Javascript 引擎
1) API- 基本 Javascript 成果
2) Binding 与其它成果绑定的成果 , 如 :DOM,C,JNI
3) DerviedSource 自动产生的代码
4) PCRE-Perl-Compatible Regular Expressions
5) KJS-Javascript Kernel
- 页面的整个处理流程 —( 简单介绍,详细流程在后面笔记中 )
1). 用户输入网址后,FrameLoader::Load函数会接收到URL。
2). 把URL 请求传给CURL库。
3). CURL发出Http请求,得到数据后,传给Loader,开始剖析。
4). 通过Dom Builder按W3C的Html规范生成Dom树
5). 如果有Javascript,JSEngine就通过ECMA-262标准完善Dom树
6). 在生成DOM树的同时, 同步生成Render树。
7). 剖析完后, 调用Layout排版
8). Paint出来
LibCurl库介绍
前面有说道 Webkit 仅仅是一个页面排版的引擎,所以,对 Webkit 来说,网页数据( Html 文件,图片, .Css,.Js 文件)的请求与接收都是通过第三方的库: LibCurl 来处理。
打开 Webkit 开发工程 (.Sln) 即可以看到, Libcurl 可以被静态或动态链接到主工程中。
Libcurl 就是指的 Curl, 只是在 Webkit 工程中,不作为单独的进程存在,而是被编译成动态库。
Webkit 主要用到 Curl 的以下成果:
1) Http 协议。包含: Get, Put, Post, Cookie 管理。
2) Https 协议。
3) 本地文件 缓存 。 ( 前进,退却管理 )
Webkit 详细调用了哪些 Curl 接口,详见后面 Loader 模块介绍章节。这里简单列举:
1) Curl_global_init(CURL_GLOBAL_ALL);
2) Curl_multi_init()
3) Curl_share_init()
4) Curl_share_setopt()
5) Curl_easy_getinfo()
6) Curl_multi_fdset()
7) Curl_multi_perform()
8) Curl_multi_info_read()
9) Curl_multi_cleanup()
10) Curl_share_cleanup()
11) Curl_global_cleanup();
可以看到,由于 Webkit 要支持同时请求多个 Http 数据,所以用到的是 Curl 的 Multi 接口。
在介绍 Loader 之前,先介绍一下 Libcurl ,打下基础。
以下附一篇 Libcurl 的介绍:
一、概念
1. 为啥要使用 Libcurl
1) 作为 Http 的客户端,可以直接用 Socket 毗连 办事器 ,然后对到的数据进行 Http 剖析,但要分析协议头,实现代理…这样太麻烦了。
2) Libcurl 是一个开源的客户端 Url 传输库,支持 FTP , FTPS , TFTP , HTTP , HTTPS , GOPHER , TELNET , DICT , FILE 和 LDAP ,支持 Windows , Unix , Linux 等平台,简单易用,且库文件占用空间不到 200K
- Get 和 Post 方式
客户端在 Http 毗连时向办事提交数据的方式分为 Get 和 Post 两种
1) Get 方式将所要传输的数据附在网址后面,然后一起送达 办事器 ,它的优点是效率比较高;缺点是安全性差、数据不超过 1024 个字符、必须是 7 位的 ASCII 编码;查询时常常用此方法。
2) Post 通过 Http Post 处剃头送数据,它的优点是安全性较强、支持数据量大、支持字符多;缺点是效率相对低;编辑修改时多使用此方法。
- Cookie 与 Session
1) Cookie
Cookie 是发送到客户欣赏器的文本串句柄,并保存在客户机硬盘上,可以用来在某个 Web 站点会话之间长期地保持数据。 Cookie 在客户端。
2) Session
Session 是访问者从到达某个特定主页到离开为止的那段时间。每一访问者都市单独得到一个 Session ,实现站点多个用户之间在所有页面中共享信息。 Session 在 办事器 上。
3) Libcurl 中使用 Cookie
保存 Cookie, 使之后的链接与此链接使用相同的 Cookie
A) 在封闭链接的时候把 Cookie 写入指定的文件
Curl_easy_setopt(Curl, CURLOPT_COOKIEJAR, “/Tmp/Cookie.Txt”);
B) 取用现在有的 Cookie ,而不重新得到 Cookie
Curl_easy_setopt(Curl, CURLOPT_COOKIEFILE, “/Tmp/Cookie.Txt”);
B) Http 与 Https 的区别
1) Http 是明文发送,任何人都可以拦截并读取内容
2) Https 是加密传输协议,用它传输的内容都是加密过的, Https 是 Http 的扩展,其安全基础是 SSL 协议
C) Base64 编码
1) 为啥要使用 Base64 编码
如果要传一段包含特殊字符比较多的数据,直接上传就需要处理转意符之类的许多问题,用 Base64 编码,它可以把数据转成可读的字串, Base64 由 A-Z, A-Z, +/ 总计 64 个字符组成。
2) 传送 Base64 编码的注意事项
由于 Base64 的组成部分有加号,而加号是 Url 中的转意字符,所以无论是 Get 方式还是 Post ,传到 办事器 的过程中,都市把加号转成空格,所以在传 Base64 之前需要把 Base64 编码后的加号替换成” %2B ”,这样就可以正常发送了。
#include <stduo.h>
#Include <Curl/Curl.H>
bool GetUrl(Char *Filename)
{
CURL *Curl;
CURLcode Res;
FILE *Fp;
// 返回结果用文件存储
If ((Fp = Fopen(Filename, "W")) == NULL)
Return False;
Struct Curl_slist *Headers = NULL;
Headers = Curl_slist_append(Headers, "Accept: Agent-007");
Curl = Curl_easy_init(); // 初始化
if (Curl)
{
Curl_easy_setopt(Curl, CURLOPT_PROXY, "10.99.60.201:8080");// 代理
// 改协议头
Curl_easy_setopt(Curl, CURLOPT_HTTPHEADER, Headers);
Curl_easy_setopt(Curl, CURLOPT_URL, "Http://Www.Google.Com/Search? Hl=En&Q=Xieyan0811&BtnG=Google+Search&Aq=F&Oq=Xieyan081");
Curl_easy_setopt(Curl, CURLOPT_WRITEDATA, Fp);
Res = Curl_easy_perform(Curl);
Curl_slist_free_all(Headers);
Curl_easy_cleanup(Curl);
}
fclose(Fp);
return True;
}
bool PostUrl(Char *Filename)
{
CURL *Curl;
CURLcode Res;
FILE *Fp;
If ((Fp = Fopen(Filename, "W")) == NULL)
Return False;
Curl = Curl_easy_init();
if (Curl)
{
// 指定Cookie文件
Curl_easy_setopt(Curl, CURLOPT_COOKIEFILE, "/Tmp/Cookie.Txt");
Curl_easy_setopt(Curl, CURLOPT_COOKIEJAR, "/Tmp/Cookie.Txt");
// 指定Post内容
Curl_easy_setopt(Curl, CURLOPT_POSTFIELDS, "&Logintype=Uid&U=Xieyan&Psw=Xxx86");
Curl_easy_setopt(Curl, CURLOPT_PROXY, "10.99.60.201:8080");
// 指定Url
Curl_easy_setopt(Curl, CURLOPT_URL, "Http://Mail.Sina.Com.Cn/Cgi-Bin/Login.Cgi");
Curl_easy_setopt(Curl, CURLOPT_WRITEDATA, Fp);
Res = Curl_easy_perform(Curl);
Curl_easy_cleanup(Curl);
}
Fclose(Fp);
Return True;
}
int Main(Void)
{
GetUrl("/Tmp/Get.Html");
PostUrl("/Tmp/Post.Html");
}
E) 编译
G++ Main.Cpp -O Main -Lcurl
三、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
下面分别介绍 (PS: 必须要了解这些概念,不然后面的东东都无法明白 ):
1)Document: 这个类的爷爷类是 Node ,它是 DOM 树各元素的基类; Document 有个子类是 HTMLDocument ,它是整个文档 DOM 树的根结点,这样就明白了:原来 Document 就是描述详细文档的代码,看一下它的头文件,就更明白了,它的属性与方法就是围绕着各种各样的结点: Text , Comment , CDATASection , Element ……
2)Page: 我的明白是, Page 与Webview外部接口相关, Page与Frame是一对多的关系,同时 Frame与 FrameView 是一一对应的, Frameview 存眷 UI , Page 存眷数据与接口。现在的欣赏器一般都提供同时打开多个窗口,每一个窗口对应的数据就是这个 Page 在管理了。
在 Page.Cpp 文件里,另有个重要的全局指针变量: Static HashSet