WebKit引擎介绍

更新时间:2024-06-14 19:27:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

WebKit引擎入门介绍

1 WebKit简介 .................................................................................................................................. 2

1.1 简介 ................................................................................................................................... 2 1.2 WebKit主要特点 .............................................................................................................. 3

1.2.1 引擎 ....................................................................................................................... 3 1.2.2 开源 ....................................................................................................................... 3 1.2.3高性能 .................................................................................................................... 3 1.2.4 可移植性 ............................................................................................................... 3 1.2.5 兼容性 ................................................................................................................... 3 1.2.6 遵守标准 ............................................................................................................... 3 1.2.7 安全 ....................................................................................................................... 4 1.3 WebKit主要组成 .............................................................................................................. 4

1.3.1 体系结构 ............................................................................................................... 4

2 WebCore介绍 ................................................................................................................................ 5

2.1 WebCore目录结构 ............................................................................................................ 5 2.2 Http请求在WebCore中的主要流程 .............................................................................. 6

2.2.1 工作流程 ............................................................................................................... 6 2.2.2 处理流程 ............................................................................................................... 8

3 WebKit的DOM分析 .................................................................................................................... 10

3.1 DOM原理 .......................................................................................................................... 10

3.1.1 DocView 模型 ..................................................................................................... 10 3.2 DOM解析基本算法 .......................................................................................................... 11

3.2.1 基本算法思想 ..................................................................................................... 11

4 WebKit的Ports介绍 ................................................................................................................ 15

4.1 Port概述 ........................................................................................................................ 15 4.2 WebKit Port移植实现分析 .......................................................................................... 15

4.2.1 WebCore交互接口 .............................................................................................. 15

4.2.2 连接模块loader ................................................................................................ 16 4.2.3 显示模块WebView和WebFrame ........................................................................ 16 4.2.4 Android中对Port移植方面的实现 ................................................................ 16 4.2.5 小结 ..................................................................................................................... 17

5 WebKit的JavascriptCore介绍 .............................................................................................. 17

5.1 JavaScriptCore实现特点 ............................................................................................ 18 5.2 JavaScriptCore目录的内容 ........................................................................................ 18 5.3 JavaScriptCore与WebCore交互 ................................................................................ 18 6 WebKit For Android ................................................................................................................. 19

6.1 WebKit模块目录结构 .................................................................................................... 19 6.2 Java层框架 .................................................................................................................... 21

6.2.1 主要类描述 ......................................................................................................... 21 6.2.2 数据载入器的设计 ............................................................................................. 23 6.3 C层框架 .......................................................................................................................... 24 6.4 WebView操作分析 .......................................................................................................... 24

6.4.1 WebKit模块初始化 ............................................................................................ 24 6.4.2 数据载入 ............................................................................................................. 27 6.5 刷新绘制 ......................................................................................................................... 28

1 WebKit简介

1.1 简介

WebKit 的前身是 KDE 小组的 KHTML。Apple 将 KHTML 发扬光大,推出了装备 KHTML 改进型的 WebKit 引擎的浏览器Safari,获得了非常好的反响。WebKit 引擎比 Gecko 引擎更受程序员欢迎的原因,除了其引擎的高效稳定,兼容性好外,其源码结构清晰,易于维 护,是一个重要的原因。现在浏览器的内核引擎,基本上是三分天下:

Trident: IE 以Trident 作为内核引擎。 Gecko: Firefox 是基于 Gecko 开发。

WebKit: Safari, Google Chrome 基于 Webkit 开发。 还有一个Presto:Opera,任天堂DS浏览器,发展也良好。

WebKit 内核在手机上的应用十分广泛,例如 Google 的手机Gphone、 Apple 的 iPhone, Nokia’s Series 60 browser 等所使用的 Browser 内核引擎,都是基于 WebKit。

1.2 WebKit主要特点

1.2.1 引擎

该项目的主要重点是内容部署在万维网上的,基于标准的技术,如HTML,CSS , JavaScript和DOM中。并能够嵌入WebKit在其他应用程序中,并用它作为一般用途的显示和交互引擎。

1.2.2 开源

WebKit继续自由使用的两个开源协议LGPL和BSD,在Webkit中,WebCore和JavaScriptCore是LGPL,其余是BSD授权。

1.2.3高性能

维持和改善的速度和内存使用是一个重要的目标。随着网页内容越来越丰富,越来越复杂,作为网络浏览器上运行的更有限的设备,需要提升性能,加快浏览速度。

1.2.4 可移植性

WebKit 移植到各种各样的台式机、移动、嵌入式平台和其他平台。WebKit 提供必要的基础设施,并酌情提供友好嵌入的API。

1.2.5 兼容性

用户浏览网页,兼容现有的网站是必不可少的。WebKit致力于维护和改善兼容现有的网络内容,利用回归测试,以保持WebKit的兼容性。

1.2.6 遵守标准

WebKit的目标是遵守有关的Web标准,并支持新的标准。

1.2.7 安全

保护用户安全的行为是至关重要的。迅速修复安全问题,以保护用户系统和维护他们对WebKit的信任。

1.3 WebKit主要组成

WebKit 主要包括三个部分WebCore、JavascriptCore 及Ports部分。WebKit 专注的核心部分主要是:分析Html,Javascript 的解析和布局渲染技术。分别在由WebCore/html,JavascriptCore 和WebCore/rendering来完成。

1.3.1 体系结构

WebKit的体系结构如下图:

2 WebCore介绍

2.1 WebCore目录结构

根据源代码目录结构,WebCore目录主要包括如下:

bindings:将Dom Binding 给JavascriptCore 方面的代码,同时包含依据idl接口描述文件,自动生成对应于JavascriptCore 的Binding 实现的脚本等内容;

bridge:主要包含NPPlugin 方面的接口访问等内容;

css:主要包括与css 方面相关的内容,如解析不同css 规则的定义与实现、css Binding

给JS的接口定义等内容;

dom:主要包括dom方面相关的内容,如不同dom元素的定义与实现、dom Binding给JS的接口定义等内容;

html:关于html 方面相关的内容,如不同html 元素的定义与实现、HTMLTokenizer 及HTMLParser等内容。

loader:主要包括装载资源,如html页面、css、js 及image等方面内容;

page:主要包括描述一个Web 页面所涉及的内容如page、frame、frameview、frametree、setting、history、chrome、chromeclient等内容;

rendering:主要包括如何使用样式,组织布局、显示html 元素等方面内容; plugins:主要包括浏览端如何实现NPPlugin 方面的内容; svg:主要包括与svg 方面相关的内容;

xml:主要包括与xml 方面相关的内容,如xml parser、XPath、XSLT等;

platform:主要包括与不同平台或外部库相关的内容如graphics(图形输出方面)、network(网络处理方面)、image-decoders(解析不同图片格式方面)等。

2.2 Http请求在WebCore中的主要流程

2.2.1 工作流程

如下图所示:

Http请求1IO组件32Shell控制器4ParseHTML/XHTML5Build Dom树6Build Render树7Layout 流程解析:

1. 用户向Shell发出页面请求后,页面的URL 或本地文件名被发送到Shell; 2. Shell 调用IO组件,把URL 传达到IO组件;

3. IO组件使用HTTP 协议或再调用本地IO获取HTML/XHTML源数据,返回Shell; 4. Shell 把IO 返回的HTML/XHTML source 提交HTML/XHTML分析器;

5. HTML/XHTML分析器分析HTML/XHTML代码,构建一棵DOM 树,树根为HTMLDocument; 6. 通过DOM 树,生成Render 树。 Render树,简单的说来,它是对DOM 树更进一步的描述,其描述的内容主要与布局渲染等CSS相关属性如left、 top、width、height、color、font等有关,因为不同的DOM 树结点可能会有不同的布局渲染属性,甚至布局时会按照标准动态生成一些 匿名节点,所以为了更加方便的描述布局及渲染,WebKit内核又生成一颗Render 树来描述DOM 树的布局渲染等特性,当然DOM 树与Render 树 不是一一对应,但

可以相互关联;

7. 布局管理器layout对应控件。当布局管理器对可视化元素指派好位置和大小后,可视化元素必须要严格遵守布局管理器给它分配的位置和大小,不能擅自更改,相应控件根据自己的属性进行表现自己了,如背景,外形等。

2.2.2 处理流程

流程描述:

通过向服务器发送请求服务器通过请求,发给客户端html的内容浏览器通过W3C 规范,把接受到的内容解析成DOM 树,在解析DOM 树的同时会生成对应的Render 树。布局管理器通过Render 树,开始布局。这个是一个动态的过程,DOM在这个时候会继续向服务器申

请自己需要的东西, 比如CSS,JavaScript,图片等,然后布局器动态的加载或布局,这样可以改善用户的体验,最后把整个网页render出来。

3 WebKit的DOM分析

3.1 DOM原理

3.1.1 DocView 模型

DocView 模型包括:网页标识、网页类型、内容类别、标题、关键词、摘要、正文、相关链接等要素。其中正文和相关链接要素属于网页的内容数据,而其他 6 项则属于网页的元数据。

网页标识:对 Web 上网页的唯一性标识,在 DocView 模型中使用网页的URL 作为网页标识。

网页类型:主题网页(topic)、Hub 网页(hub)、图片网页(pic)。其中,有主题网页是指网页中通过文字描述了一件或多件事物,是有一定主题的。如一张具体的新闻网页就是典型的有主题网页。Hub 网页是指专门用来提供网页导向的网页,因 而是超链聚集的网页。如门户网站的首页就是典型的 Hub 网页。图片网页是指网页的内容是通过图片的形式体现的,其中文字很少,仅是对图片的一个说明。如某个机构包含图片的人员介绍网页就是典型的图片网页。

内容类别是从语义上对网页的内容进行分类,它是计算机获取网页语义信息的一个直接手段,在 Web 上的研究领域中有着广泛的使用。它是通过特定的分类器对网页内容分类得到的,依赖于一定的分类体系。

标题、关键词和摘要是概括描述 Web 文档内容的重要的元数据,对于 Web 信息检索等领域的工作有非常重要的作用。

正文:原始网页中真正描述主题的部分,因此,在某些具体应用中用正文代替原始网页更为合理。相关链接是指在本网页中指向与正文内容相关的网页的链接,而非广告等噪音链接。将正文和相关超链重新组合就得到了净化后的网页。

超链相关的标签是 HTML 网页区别于传统文本的明显的特点之一,表示着网页间的关系,因此整理出超链标签并作合理的分析可以挖掘出网页间的 内容相关性信息。目前,有

很多构造标签树的工具(如:W3C HTML lexicalanalyzer[W3C,1997]),它们各有特点,W3C HTML lexical analyzer有很强的通用性,适合各种标识语言;HTML Tidy 则能够自动发现并修正标签的错误。

3.2 DOM解析基本算法

3.2.1 基本算法思想

1. Html 中每个tag 都是作为树中的一个节点存在的,每个tag都属于树中的某一层。 2. 辅助数据结构:栈(stack)、List、HashTable。其中HashTable[i](i 属于int 类型)是一个List,用于临时存储第i 层子Tag。

3. 顺序扫描Html 文本,当遇到”

4. 遇到这样的标志,表示可能是某个Tag的结束。解析出此结束标志的Tag 名。如果在栈中找到与此结束标志名同名的元素(此元素属于栈中第iLevel 层),那么表示找到匹配的Tag。则Tag出栈,将HashTable[iLevel+1]到HashTable[maxLevel]中的所有元素取出作为此Tag 的子节点。放入第HashTable [iLevel]中。并记录Tag的结束位置。

5. 对于xxx之间的字符串xxx,将其作为特殊的HtmlTextTag 处理。出栈,和入栈操作与普通Tag 类似。

6. 当栈为空的时候表示最后一次出栈的Tag 为根节点。 伪代码: public void Parse(){

char ch = GetCurrentChar(); //取第一个字符 while (!Eof()){

if (ch == '<'){

ch = MoveNext(); //取下一个字符

if ((ch >= 'A') && (ch <= 'Z') || (ch == '!')) { iBeginPos = Index; //记录开始位置 //表示可能是一个标签

HtmlTag tag = GetTag(); //解析此Tag if (tag != null) { //首先判断是否有文本

if (m_CurrentText.Lenght > 0) { //将文本作为一个普通Tag入栈

Stack.Push(new HtmlTextTag(m_CurrentText)); }

tag.BeginPos = iBeginPos; //记录此Tag的开始位置 Stack.Push(tag); //把Tag入栈 } }

ch = GetCurrentChar(); if (ch == '/'){

//可能是结束标签 tagName = GetTagName();

//从上到下查看Stack,如果Tag中存在 if (FindInStack(tagName)){

//在栈中找到名为tagName的元素,则把找到的元素出栈

PopTag(tagName); } } else{

//xxx之间的文本xxx,这里将作为TextTag来处理 m_CurrentText.Append(GetCurrentChar()); }

//继续处理下一个字符 ch = MoveNext(); }

//解析完成以后,如果栈不空,那么把元素出栈,并把最后一次出栈的元素作为根 if (Stack.Count > 0){

HtmlTag tag = null; while (Stack.Count > 0){

tag = Stack.Pop(); PopTag(tag); }

//最后一个元素作为根元素 if (tag != null){

m_listRoot.Add(tag); } } }

private void PopTag(HtmlTag tag) {

int iLevel = Stack.Count;

//找到了元素,把iLevel到m_IMaxLevel中所有的元素按照全部作为tag的子元素 for (int i = iLevel + 1; i < m_iMaxLevel; i++){

for (j = 0; j < HashTable[i].Count; j++){

tag.Children.Add(HashTable[i][j]); } }

//表示栈已经为空,那么最后一次出栈的tag将作为根 if (Stack.Count == 0){

m_listRoot.Add(tag); } }

private void PopTag(string tagName){ /**

* 元素出栈的时候,首先需要把当前已经存在了的HtmlTextTag入栈

* 比如:文本段1文本段2文本段3182. * 在Parse中,当解析出入栈前,需要先把\文本段1\入栈 * 在这里,解析出了结束标志 * 那么首先需要把\文本段2\入栈。 * 解析出则需要把\文本段3'入栈。

* 这样才能够保证\文本段1\和\文本段3\成为的子节点, * 而\文本段2\作为的子节点 */

if (m_CurrentText.Lenght > 0){

//将文本作为一个普通Tag入栈

Stack.Push(new HtmlTextTag(m_CurrentText)); }

HtmlTag tag = Stack.Pop(); //元素出栈 int iLevel = Stack.Count; //记录栈元素数 while (tag.Name != tagName) {

//将tag放入第iLevel层的List中 HashTable[iLevel].Add(tag); tag = Stack.Pop(); iLevel = Stack.Count; }

//元素出栈后续处理 PopTag(tag); }

private HtmlTag GetTag(){

//则表示是注释

if (\如果发现是< !--开头的元素\

SkipComment(); }

HtmlTag tag = new HtmlTag();

tag.Name = GetTagName();

//这里的Attribute我将其作为HashTable类型,Hash[属性名]=属性值 tag.Attribute = GetTagAttribute(); return tag; }

4 WebKit的Ports介绍

4.1 Port概述

WebKit Port 方面的内容很广,可将不同的图形库、网络库与WebCore集成,提供不同的Port接口供外部程序使用等,例如同样在windows 平台上可以运行的Google Chrome 和Safari 就是针对WebKit在不同平台的移植。

Port 方面的主要内容是提供不同的Port 接口供外部程序使用以及如何与外部程序交

互。WebKit 中的其它两部分WebCore、 Javascript 实现,从逻辑上讲是不直接提供接口给外部程序使用的,同时WebKit为了完成浏览器的核心功能,也需要从外部程序中通过Port 接口的方式获取一些支持。

WebKit 作为一个相对独立的整体,它与外部程序之间的交互也就有一组相对固定的接

口来定义及维护它们之间的关系,它们之间的关系与插件跟浏览器引擎之间的关系完全类似,接口相当一组协议,有的是由WebKit 来实现,而供外部程序调用,有的的正好相反。

通过前面的了解我们知道WebKit的主要功能集中在分析Html、渲染布局Web 内容以及

Javascript 实现方面等,而这些Web 内容显示在哪个窗口及消息处理的启动循环等都需要由外部程序来提供,这一切都由Ports来完成。

4.2 WebKit Port移植实现分析

4.2.1 WebCore交互接口

在 WebKit源代码目录结构中WebKit目录下分别包含gtk、mac、qt、win、wx 目录,其

分别对应不同的Port 移植方式,在每一个目录下面 都包括WebCoreSupport 目录,而在不同的WebCoreSupport目录下分别包含有对类接口 WebCore::ChromeClient 、WebCore::ContextMenuClient 、WebCore::DragClient 、WebCore::EditorClient 、

WebCore::FrameLoaderClient 、WebCore::InspectorClient 等的实现,它们代表外部程序提供给WebKit 内部使用的接口实现,其中WebCore::ChromeClient、WebCore::FrameLoaderClient非常重要。

初步了解其接口定义能基本了解其对应的含义,这些接口往往需要由Port 移植部分来提供实现,往往由WebKit内部根据一定的条件来调用。

4.2.2 连接模块loader

对于WebCore中page/loader等类提供对应port实现的支持如EVentHandlerWin.cpp 、

FrameLoaderWin.cpp 、DocumentLoaderWin.cpp、DocumentLoaderWin.cpp、WidgetWin.cpp、KeyEventWin.cpp等.Loader 是在WebKit 里面一个很重要的连接器,通过loader 发起IO下载网页,再通过loader发起解析,已经最后的渲染功能。

4.2.3 显示模块WebView和WebFrame

WebView 及WebFrame 主要功能是方便外部程序嵌入WebKit不同的Port 移植对WebView 及WebFrame的定义及实现有所不同,但其与WebCore中的Page、Frame 之间的关系图描述相一致。具体关于WebView、WebFrame的定义与实现,特别是初始化时的动作可根据不同的Port 移植而有所不同,同时初始化时会将上面提到的WebCorePort 接口实现告诉WebKit内部

4.2.4 Android中对Port移植方面的实现

Android实现有点特殊,由于Andriod 将WebKit 以一个Java 类接口的方式提供给Java 环境使用(不像Chrome、Safari 等都是将WebKit 以 一个C++动态或静态库的方式供C/C++外部程序调用),这样WebKit 内部与外部即JavaVM 的交互(如上面提到的ChromeClient、FrameLoaderClient 接口实现)需要一个Bridge 类来协调处理,同时WebView、WebFrame 接口绑定给JavaVM 的jni 接口实现也需要通过这个Bridge 来支持协调处理。具体可详细参考

android源码代码中WebCore\\platform\\android目录下的源文件。

4.2.5 小结

通过进一步了解WebCore Port 接口及其实现,可以加深这样一个认识。如果从MVC的角度来看整个基于WebKit的浏览器,WebKit 的Port 部分相当于V 部分,它提供显示页面内容及其辅助信息(如提示状态)的场所(即原生窗口)以及控制该显示场所的状态变化及消息响应(如改变大小、 鼠标移动等);而M 部分往往由WebCore来实现,至于WebCore如何组织DOM则往往由htmlparser部分根据DOM 定义来组织,如何在提 供的显示场所显示Web 内容则往往由WebCore 中的layout 部分来实现,其中充分利用了Css 定义来布局显示该显示的内容。一旦涉及控制或动态处理往往由Port 部分发起而由Javascript 脚本来实现处理,其任务由JavascriptCore或V8 (JS解析Core)来完成。

一般说来新打开一个页面,Port 部分需要提供一个主显示场所(即原生窗口),如果页面中含有iframe 标签,则需要在主显示场所内创建一个子显示场所,以显示iframe 标签对应src 的内容。如果页面中含有embed/object 等插件标签同样往往也需要在主显示场所内创建一个子显示场所(除非windowless),以交由插件实现在提供的显示场所中显示内容。特别需要说明的是我们通常看到的页面表单元素input textfield、textArea、button、radiobutton等往往不像window 图形库中的按钮、菜单、输入框等会对应一个原生窗口,页面中的表单元素在一个显示场所(即原生窗口)中完全是利用Css 等通过layout 方式来达到我们所看到的类似原生按钮、输入框、列表框、滚动条等效果,其中 特别是能准确定位元素大小、设置focus、光标显示、响应事件等,这充分的说明了浏览器引擎内部布局部分的威力所在。

从另外一个角度来看,一个页面一般说来(除非遇到iframe 或插件需要另外提供一块子画布)相当于一块画布,浏览器引擎能在其精确的位置绘制不同颜色的文字、图片、图标 等,同时根据当前的鼠标及一个模拟的输入提示光标位置,接收键盘输入操作。页面中的绝大多数元素与原生的窗口元素几乎没有关联,完全通过组合、布局、准确定位来处理一切。

5 WebKit的JavascriptCore介绍

在WebKit中其Javascript实现,同样相当于一个符合ECMAScript标准的动态库,其往往依附于浏览器引擎,由浏览器引擎来提供运行环境,并控制或发起javascript实现进行编译、

解析执行脚本、垃圾回收等,同样需提供对浏览器引擎扩展的支持如Dom Binding等;

5.1 JavaScriptCore实现特点

相对于其他的Javascript实现,JavaScriptCore提出了虚拟机的概念,在编译脚本时生成高效的bytecode,bytecode统一在一个虚拟机的环境中执行。而其高效的虚拟机实现常称为SquirrelFish,通过Announcing SquirrelFish、Introducing SquirrelFish Extreme可更进一步了解关于SquirrelFish的相关内容

5.2 JavaScriptCore目录的内容

1. assembler:jit编译中间码用到的汇编程序 2. bytecode:中间码相关的类和定义

3. 生成中间码的类实现,实际上是编译Node类

4 .interpreter:用来执行js的类,实际上就是执行CodeBlock 5. jit:执行jit汇编程序的类

6. parser:解析js用到的词法分析类,语法分析bison文件和Node类结构 7. runtime:是js的执行环境中自带的类

8. wtf:是WebCor和JavaScriptCore用到的基础类

5.3 JavaScriptCore与WebCore交互

在WebCore::Frame的数据结构中包含数据成员KJSProxy* m_jscript,而在Chrome的代码中调整为JSBridge* m_jscript;,具体不同Javascript实现如何实现与WebCore的接口,需了解不同Javascript实现逻辑,如对Javascript实现逻辑及基本原理感兴趣,可具体参考其提供的api及sample等。

6 WebKit For Android

Android平台的WebKit模块由Java层和WebKit库两个部分组成,Java层负责与Android应用程序进行通信,而WebKit类库负责实际的网页排版处理。Java层和C层库之间通过JNI和Bridge相互调用,如下图所示:

6.1 WebKit模块目录结构

Java层(根目录device\\java\\android\\android\\webkit)包含41个类:

1. BrowserFrame.java: BrowserFrame对象是对WebCore库中的Frame对象的Java层封装,用于创建WebCore中定义的Frame,及为该Frame对象提供Java层回调方法。

2. ByteArrayBuilder.java: ByteArrayBuilder辅助对象,用于byte块链表的处理。 3. CachLoader.java: URL Cache载入器对象,该对象实现StreadLoader抽象基类,用于通过CacheResult对象载入内容数据。

4. CacheManager.java: Cache管理对象,负责Java层Cache对象管理。

5. CacheSyncManager.java: Cache同步管理对象,负责同步RAM和FLASH之间的浏览器Cache数据。实际的物理数据操作在WebSyncManager对象中完成。

6. CallbackProxy.java: 该对象是用于处理WebCore与UI线程消息的代理类。当有Web事件产生时WebCore线程会调用该回调代理类,代理类会通过消息的方式通知UI线程,并且调用设置的客户对象的回调函数。

7. CellList.java: CellList定义图片集合中的Cell,管理Cell图片的绘制、状态改变以及索引。

8. CookieManager.java: 根据RFC2109规范,管理cookies。

9. CookieSyncManager.java: Cookies同步管理对象,该对象负责同步RAM和Flash之间的Cookies数据。实际的物理数据操作在基类WebSyncManager中完成。

10. DataLoader.java: 数据载入器对象,用于载入网页数据。 11. DateSorter.java: 尚未使用。

12. DownloadListener.java: 下载侦听器接口。

13. DownloadManagerCore.java: 下载管理器对象,管理下载列表。该对象运行在WebKit的线程中,通过CallbackProxy对象与UI线程交互。

14. FileLoader.java: 文件载入器,将文件数据载入到Frame中。

15. FrameLoader.java: Frame载入器,用于载入网页Frame数据littlefe。 16. HttpAuthHandler.java: Http认证处理对象,该对象会作为参数传递给BrowserCallback.displayHttpAuthDialog方法,与用户交互。

17. HttpDataTime.java: 该对象是处理HTTP日期的辅助对象。 18. JsConfirmResult.java: Js确认请求对象。

19. JsPromptResult.java: Js结果提示对象,用于向用户提示Javascript运行结果。 20. JsResult.java: Js结果对象,用于用户交互。

21. JWebCoreJavaBridge.java: 用Java与WebCore库中Timer和Cookies对象交互的桥接代码。

22. LoadListener.java: 载入器侦听器,用于处理载入器侦听消息。

23. Network.java: 该对象封装网络连接逻辑,为调用者提供更为高级的网络连接接口。

24. PanZoom.java: 用于处理图片缩放、移动等操作。

25. PanZoomCellList.java: 用于保存移动、缩放图片的Cell。 26. PerfChecker.java: 用于效率测试的功能对象。 27. SslErrorHandler.java: 用于处理SSL错误消息。

28. StreamLoader.java: StreamLoader抽象类是所有内容载入器对象的基类。该类是通过消息方式控制的状态机,用于将数据载入到Frame中。

29. TextDialog.java: 用于处理html中文本区域叠加情况,可以使用标准的文本编辑而定义的特殊EditText控件。

30. URLUtil.java: URL处理功能函数,用于编码、解码URL字符串,以及提供附加的

URL类型分析功能。

31. WebBackForwardList.java: 该对象包含WebView对象中显示的历史数据。 32. WebBackForwardListClient.java :浏览历史处理的客户接口类,所有需要接收浏览历史改变的类都需要实现该接口。

33. WebChromeClient.java: Chrome客户基类,Chrome客户对象在浏览器文档标题、进度条、图标改变时候会得到通知。

34. WebHistoryItem.java: 该对象用于保存一条网页历史数据。

35. WebIconDataBase.java: 图表数据库管理对象,所有的WebView均请求相同的图标数据库对象。

36. WebSettings.java: WebView的管理设置数据,该对象数据是通过JNI接口从底层获取。

37. WebSyncManager.java: 数据同步对象,用于RAM数据和FLASH数据的同步操作。 38. WebView.java: Web视图对象,用于基本的网页数据载入、显示等UI操作。 39. WebViewClient.java: Web视图客户对象,在Web视图中有事件产生时,该对象可以获得通知。

40. WebViewCore.java: 该对象对WebCore库进行封装,将UI线程中的数据请求发送给WebCore处理,并通过CallbackProxy的方式,通过消息通知UI线程数据处理结果。

41. WebViewDatabase.java: 该对象使用SQLiteDatabase为WebCore模块提供数据存取操作。

6.2 Java层框架

6.2.1 主要类描述

1. WebView

WebView类是WebKit模块Java层的视图类,所有需要使用Web浏览功能的Android应用程序都要创建该视图对象显示和处理请求的网络资源。目前,WebKit模块支持HTTP、HTTPS、FTP以及javascript请求。WebView作为应用程序的UI接口,为用户提供了一系列的网页浏览、用户交互接口,客户程序通过这些接口访问WebKit核心代码。 2. WebViewDatabase

WebViewDatabase是WebKit模块中针对SQLiteDatabase对象的封装,用于存储和获取运行时浏览器保存的缓冲数据、历史访问数据、浏览器配置数据等。该对象是一个单实例对象,通过getInstance方法获取WebViewDatabase的实例。WebViewDatabase是WebKit模块中的内部对象,仅供WebKit框架内部使用。 3. WebViewCore

WebViewCore类是Java层与C层WebKit核心库的交互类,客户程序调用WebView的网页浏览相关操作会转发给BrowserFrame对象。当WebKit核心库完成实际的数据分析和处理后会回调WebViweCore中定义的一系列JNI接口,这些接口会通过CallbackProxy将相关事件通知相应的UI对象。 4. CallbackProxy

CallbackProxy是一个代理类,用于UI线程和WebCore线程交互。该类定义了一系列与用户相关的通知方法,当WebCore完成相应的数据处理,则会调用CallbackProxy类中对应的方法,这些方法通过消息方式间接调用相应处理对象的处理方法。 5. BrowserFrame

BrowserFrame类负责URL资源的载入、访问历史的维护、数据缓存等操作,该类会通过JNI接口直接与WebKit C层库交互。 6. JWebCoreJavaBridge

该类为Java层WebKit代码提供与C层WebKit核心部分的Timer和Cookies操作相关的方法。

7. DownloadManagerCore

下载管理核心类,该类负责管理网络资源下载,所有的Web下载操作均有该类同一管理。该类实例运行在WebKit线程当中,与UI线程的交互是通过调用CallbackProxy对象中相应的方法完成。 8. WebSettings

该对象描述了WEB浏览器访问相关的用户配置信息。 9. DownloadListener

下载侦听接口,如果客户代码实现该接口,则在下载开始、失败、挂起、完成等情况下,DownloadManagerCore对象会调用客户代码中实现的DownloadListener方法。 10. WebBackForwardList

WebBackForwarList对象维护着用户访问历史记录,该类为客户程序提供操作访问浏览

器历史数据的相关方法。 11. WebViewClient

WebViewClient类定义了一系列事件方法,如果Android应用程序设置了WebViewClient派生对象,则在页面载入、资源载入、页面访问错误等情况发生时,该派生对象的相应方法会被调用。

12. WebBackForwardListClient

WebBackForwardListClient对象定义了对访问历史操作时可能产生的事件接口,当用户实现了该接口,则在操作访问历史时(访问历史移除、访问历史清空等)用户会得到通知。 13. WebChromeClient

WebChromeClient类定义了与浏览窗口修饰相关的事件。例如接收到Title、接收到Icon、进度变化时,WebChromeClient的相应方法会被调用。

6.2.2 数据载入器的设计

WebKit模块的Java部分框架中使用数据载入器来加载相应类型的数据,目前有CacheLoader、DataLoader以及FileLoader三类载入器,他们分别用于处理缓存数据、内存据,以及文件数据的载入操作。Java层(WebKit模块)所有的载入器都从StreamLoader继承(其父类为Handler),由于StreamLoader类的基类为Handler类,因此在构造载入器时,会开启一个事件处理线程,该线程负责实际的数据载入操作,而请求线程通过消息的方式驱动数据的载入。下图是数据载入器相关类的类图结构:

StreamLoader类定义了4个不同的消息(MSG_STATUS、MSG_HEADERS、MSG_DATA、MSG_END),分别表示发送状态消息、发送消息头消息、发送数据消息以及数据发送完毕消息。该类提供了2个抽象保护方法以及一个共有方法:setupStreamAndSendStatus保护方法主要是用于构造与通信协议相关的数据流,以及向LoadListener发送状态;buildHeaders方法是向子类提供构造特定协议消息头功能,所有载入器只有一个共有方法(load),因此当需要载入数据时,调用该方法即可。与数据载入流程相关的类还有LoaderListener以及BrowserFrame,当数据载入事件发生时,WebKit C库会更新载入进度,并且会通知BrowserFrame,BroserFrame接收到进度条变更事件后会通过CallbackProxy对象,通知View类进度条数据变更。

6.3 C层框架

略过。

6.4 WebView操作分析

6.4.1 WebKit模块初始化

Android SDK中提供了WebView类,该类为客户提供客户化浏览显示的功能,如果客户

需要加入浏览器的支持,可将该类的实例或者派生类的实例作为视图,调用Activity类的setContentView显示给用户。当客户代码中生成第一次生成WebView对象时,会初始化WebKit库(包括Java层和C层两个部分),之后用户可以操作WebView对象完成网络或者本地资源的访问。WebView对象的生成主要涉及3个类CallbackProxy、WebViewCore以及WebViewDatabase。其中CallbackProxy对象为WebKit模块中UI线程和WebKit类库提供交互功能,WebViewCore是WebKit的核心层,负责与C层交互以及WebKit模块C层类库初始化,而WebViewDatabase为WebKit模块运行时缓存、数据存储提供支持。WebKit模块初始化流程如下:

6.4.1.1 WebView实例化

1. 创建CallbackProxy对象 2. 创建WebViewCore对象

3. 调用System.loadLibrary载入webcore相关类库(C层) 4. 如果是第一次初始化WebViewCore对象,创建WebCoreTherad线程 5. 创建EventHub对象,处理WebViewCore事件 6. 获取WebIconDatabase对象实例 7. 向WebCoreThread发送初始化消息

6.4.1.2 获取WebViewDatabase实例

1. 调用System.loadLibrary方法载入webcore相关类库,该过程由Dalvik虚拟机完成,它会从动态链接库目录中寻找libWebCore.so类库,载入到内存中,并且调用WebKit初始化模块的JNI_OnLoad方法。WebKit模块的JNI_OnLoad方法中完成了如下初始化操作:

a) 初始化framebridge[register_android_webcore_framebridge]

初始化gFrameAndroidField静态变量,以及注册BrowserFrame类中的本地方法表。

b) 初始化javabridge[register_android_webcore_javabridge]

初始化gJavaBridge.mObject对象,以及注册JWebCoreJavaBridge类中的本地方法

c) 初始化资源loader[register_android_webcore_resource_loader] 初始化gResourceLoader静态变量,以及注册LoadListener类的本地方法

d) 初始化webviewcore[register_android_webkit_webviewcore]

初始化gWebCoreViewImplField静态变量,以及注册WebViewCore类的本地方法

e) 初始化webhistory[register_android_webkit_webhistory]

初始化gWebHistoryItem结构,以及注册WebBackForwardList和WebHistoryItem类的本地方法

f) 初始化webicondatabase[register_android_webkit_webicondatabase] 注册WebIconDatabase类的本地方法

g) 初始化websettings[register_android_webkit_websettings] 初始化gFieldIds静态变量,以及注册WebSettings类的本地方法

h) 初始化webview[register_android_webkit_webview]

初始化gWebViewNativeField静态变量,以及注册WebView类的本地方法

2. WebCoreThread初始化,该初始化只在第一次创建WebViewCore对象时完成,当用户代码第一次生成WebView对象,会在初始化WebViewCore类时创建WebCoreThread线程,该线程负责处理WebCore初始化事件。此时WebViewCore构造函数会被阻塞,直到一个WebView初始化请求完毕时,会在WebCoreThread线程中唤醒。

3. 创建EventStub对象,该对象处理WebView类的事件,当WebCore初始化完成后会向WebView对象发送事件,WebView类的EventStub对象处理该事件,并且完成后续初始化工作。

4. 获取WebIconDatabase对象实例。

5. 向WebViewCore发送INITIALIZE事件,并且将this指针作为消息内容传递。 WebView类主要负责处理UI相关的事件,而WebViewCore主要负责与WebCore库交互。在运行时期,UI线程和WebCore数据处理线程是运行在两个独立的线程当中。WebCoreThread线程接收到INITIALIZE线程后,会调用消息对象参数的initialize方法,而后唤醒阻塞的WebViewCoreJava线程(该线程在WebViewCore的构造函数中被阻塞)。不同的WebView对象实例有不同的WebViewCore对象实例,因此通过消息的方式可以使得UI线程和WebViewCore线程解耦合。WebCoreThread的事件处理函数,处理INITIALIZE消息时,调用的是不同WebView中WebViewCore实例的initialize方法。WebViewCore类中的initialize方法中会创建BrowserFrame对象(该对象管理整个WEB窗体,以frame相关事件),并且向WebView对象发送WEBCORE_INITIALIZED_MSG_ID消息。WebView消息处理函数,会根据消息参数1初始化指定的WebViewCore对象,并且更新WebViewCore的Frame缓冲。

6.4.2 数据载入

6.4.2.1 载入网络数据

客户代码中可以使用WebView类的loadUrl方法,请求访问指定的URL网页数据。WebView对象中保存着WebViewCore的引用,由于WebView属于UI线程,而WebViewCore属于后台线程,因此WebView对象的loadUrl被调用时,会通过消息的方式将URL信息传递给WebViewCore对象,该对象会调用成员变量mBrowserFrame的loadUrl方法,进而调用WebKit库完成数据的载入网络数据的载入分别由Java层和C层共同完成,Java层完成用户交互、资源下载等操作,而C层主要完成数据分析(建立DOM树、分析页面元素等)操作。由于UI线程和WebCore线程运行在不同的两个线程中,因此当用户请求访问网络资源时,通过消息的方式向WebViewCore对象发送载入资源请求。在Java层的WebKit模块中,所有与资源载入相关的操作都是由BrowserFrame类中对应的方法完成,这些方法是本地方法,会直接调用WebCore库的C层函数完成数据载入请求,以及资源分析等操作。如上图所示,C层的FrameLoader类是浏览框架的资源载入器,该类负责检查访问策略以及向Java层发送下载资源请求等功能。在FrameLoader中,当用户请求网络资源时,经过一系列的策略检查后会调用FrameBridge的startLoadingResource方法,该方法会回调BrowserFrame(Java)类的startLoadingResource方法,完成网络数据的下载,而后BrowserFrame (Java)类的startLoadingResource方法会返回一个LoadListener的对象,FrameLoader会删除原有的FrameLoader对象,将LoadListener对象封装成ResourceLoadHandler对象,并且将其设置为新的FrameLoader。到此完成了一次资源访问请求,接下来的任务即是WebCore库会根据资源数据进行分析和构建DOM,以及相关的数据结构。 6.4.2.2 载入本地数据

本地数据是以data://开头的URL表示,载入过程和网络数据一样,只不过在执行FrameLoader类的executeLoad方法时,会根据URL的SCHEME类型区分,调用DataLoader的requestUrl方法(参看3.1.2.1节对载入器的分析),而不是调用handleHTTPLoad建立实际的网络通信连接。 6.4.2.3 载入文件数据

文件数据是以file://开头的URL,载入的基本流程与网络数据载入流程基本一致,不同的是在运行FrameLoader类的executeLoad方法时,根据SCHEME类型,调用FileLoader的requestUrl方法,完成数据加载(参看3.1.2.1节对载入器的分析)。

6.5 刷新绘制

当用户拖动滚动条、有窗口遮盖、或者有页面事件触发都会向WebViewCore(Java层)对象发送背景重绘消息,该消息会引起网页数据的绘制操作。WebKit的数据绘制可能出于效率上的考虑,没有通过Java层,而是直接在C层使用SGL库完成。

本文来源:https://www.bwwdw.com/article/gmy3.html

Top