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.)

  1. 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. 页面的整个处理流程 —( 简单介绍,详细流程在后面笔记中 )

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

  1. Get 和 Post 方式

客户端在 Http 毗连时向办事提交数据的方式分为 Get 和 Post 两种

1) Get 方式将所要传输的数据附在网址后面,然后一起送达 办事器 ,它的优点是效率比较高;缺点是安全性差、数据不超过 1024 个字符、必须是 7 位的 ASCII 编码;查询时常常用此方法。

2) Post 通过 Http Post 处剃头送数据,它的优点是安全性较强、支持数据量大、支持字符多;缺点是效率相对低;编辑修改时多使用此方法。

  1. 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

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐