《深入理解Android》一2.1 浏览器工作原理概述

本节书摘来自华章出版社《深入理解Android》一书中的第2章,第2.1节,作者孟德国 王耀龙 周金利 黎欢,更多章节内容可以访问云栖社区“华章计算机”公众号查看

2.1 浏览器工作原理概述

众所周知,万维网(World Wide Web,WWW)以统一资源定位符(Uniform Resource Locator,URL)作为地址空间编码,以超文本传送协议(HyperText Transfer Protocol,HTTP)请求和应答,以超文本标记语言(HyperText Markup Language,HTML)记录并以超链接(hyperlink)互相关联起来的网页(web page)文档作为内容单元,构成了人类有史以来最为庞大的资料信息库。浏览器(browser application)即是专门用来访问和浏览万维网页面的客户端软件,也是现代计算机系统中应用最为广泛的软件之一,其重要性不言而喻。浏览器内部最主要也是最重要的模块是负责页面渲染的排版引擎(layout engine),也可称作浏览器的内核(kernel),其余的部分可统称为浏览器的外壳(browser shell)。
下面将从页面、排版引擎和浏览器外壳应用三个方面对万维网和浏览器技术的基本概念和原理逐一地做简单介绍。

2.1.1 页面

现代Web Page通常由三部分组成:描述页面结构和内容的HTML语言,控制页面动态逻辑的JavaScript脚本,设定页面风格样式的层叠样式表(Cascading Style Sheets,CSS)。
HTML是为创建和描述可在浏览器中展现的网页信息而设计的一种文本格式标记语言,最初于1982年由Tim Berners-Lee创建,后来成为国际标准,由万维网联盟(W3C)维护。HTML由SGML(Standard Generalized Markup Language)简化发展而来,能够结构化地表示文档的构成和内容(如标题、段落、文本、表格),以及一定的外观(如宽、高、颜色)和语义(如注释、链接)。HTML页面由多种尖括号<>包围起来的标签元素以树形结构组成,其顶级标签为,内容标签为

,标签中可内嵌JavaScript脚本和CSS。当前W3C推荐使用的HTML标准有XHTML 1.1、HTML 4.01和HTML 5。
JavaScript是一种内置于浏览器的动态、弱类型、基于原型的网页脚本语言。一般来说,完整的JavaScript应该包括以下几个部分:
ECMAScript:描述了该语言的语法和基本对象;
文档对象模型(DOM):描述处理网页内容的方法和接口;
浏览器对象模型(BOM):描述与浏览器进行交互的方法和接口。
JavaScript的出现使得网页由单纯的静态HTML变成动态可编程的DHTML,开发者可用JavaScript来完成读写DOM,向页面添加交互行为,对浏览器事件做出响应,创建和发起网络请求等许多工作。
层叠样式表(CSS)的发明是为了将网页的内容描述与显示风格的描述分隔出来,HTML中只包含结构和内容的描述信息,CSS则只包含样式的描述信息。单独把一些显示风格信息如字体颜色、背景、排版方式等统一放在CSS文本中,可以大大简化HTML文件,同时增强可读性和修改灵活性。
Web Page一般由前端(front end)开发设计人员直接编写或者由服务器端的脚本动态生成,通过Web服务器以HTTP协议发布,供浏览器访问,这种方式即是通常所说的B/S架构(Browser/Server Architecture)。

2.1.2 内核

浏览器的内核或称排版引擎,负责请求网络页面资源加以解析排版并呈现给用户。从资源的下载到最终的页面展现,可简单地理解成一个线性串联的变换过程的组合,原始输入为URL地址,最终输出为页面Bitmap,中间依次经过了Loader、Parser、Layout和Paint模块,如图2-1所示。

image

  1. Loader
    Loader模块(如图2-2所示)负责处理所有的HTTP请求以及网络资源的缓存,相当于是从URL输入到Page Resource输出的变换过程。HTML页面中通常有外链的JS/CSS/Image资源,为了不阻塞后续解析过程,一般会有两个IO管道同时存在,一个负责主页面下载,一个负责各种外链资源的下载。

image

 虽然大部分情况下不同资源可以并发下载异步解析(如图片资源可以在主页面解析显示完成后再被显示),但JS脚本可能会要求改变页面,因此有时保持执行顺序和下载管道后续处理的阻塞是不可避免的。

  1. Parser
    Parser模块主要负责解析HTML页面,完成从HTML文本到HTML语法树再到文档对象树(Document Object Model Tree,DOM Tree)的映射过程。

HTML语法树生成如图2-3所示是一个典型的语法解析过程,可以分成两个子过程:词法解析和语法解析。词法解析按照词法规则(如正则表达式)将HTML文本分割成大量的标记(token),并去除其中无关的字符如空格。语法解析按照语法规则(如上下文无关文法)匹配Token序列生成语法树,通常有自上而下和自下而上两种匹配方式。
浏览器内核中对HTML页面真正的内部表示并不是语法树,而是W3C组织规范的文档对象模型 (Document Object Model,DOM)。DOM也是树形结构,以Document对象为根。DOM节点基本和HTML语法树节点一一对应,因此在语法解析过程中,通常直接生成最终的DOM树。下面这个HTML文档对应的语法树如图2-4所示,而实际构建的DOM树如图2-5所示。

image

<html> 
 <body>
    <p>Hello, World</p>
    <div><img src=”example.png”/><div/>
 </body>
</html>

image

 不同的页面标签对应不同类型的DOM树节点,如

标签会对应HTMLDiv-Element。DOM节点类型构成一个继承体系,详情可参见WebKit源码中WebCore/dom和WebCore/html两个目录。
页面中所有的CSS由样式表CSSStyleSheet集合构成,而CSSStyleSheet是一系列CSSRule的集合,每一条CSSRule则由选择器CSSStyleSelector部分和声明CSSStyleDeclaration部分构成,而CSSStyleDeclaration是CSS属性和值的Key-Value集合。图2-6显示了某一CSS样式表经过CSSParser解析后在浏览内核中的基本表示。
CSS解析完毕后会进行CSSRule的匹配过程,即寻找满足每条CSS规则Selector部分的HTML元素,然后将其Declaration部分应用于该元素。实际的规则匹配过程会考虑到默认和继承的CSS属性、匹配的效率及规则的优先级等因素。

image

JavaScript一般由单独的脚本引擎解析执行,它的作用通常是动态地改变DOM树(比如为DOM节点添加事件响应处理函数),即根据时间(timer)或事件(event)映射一棵DOM树到另一棵DOM树。
简单来说,经过了Parser模块的处理,内核把页面文本转换成了一棵节点带CSS Style、会响应自定义事件的Styled DOM树。

  1. Layout
    顾名思义,Layout过程就是排版,它包含两大过程。

步骤1:创建布局树。
布局树(或者叫做渲染树、Render Tree,如图2-7所示)和DOM树大体能一一对应,两者在内核中同时存在但作用不同。DOM树是HTML文档的对象表示,同时也作为JavaScript操纵HTML的对象接口。Render树是DOM树的排版表示,用以计算可视DOM节点的布局信息(如宽、高、坐标)和后续阶段的绘制显示。
 并非所有DOM节点都可视,也就是并非所有DOM树节点都会对应生成一个Render树节点。例如,

标签(HTMLHeadElement节点)不表示任何排版区域,因而没有对应的Render节点。同时,DOM树可视节点的CSS Style就是其对应Render树节点的Style。

image

步骤2:计算布局。
布局就是安排和计算页面中每个元素大小位置等几何信息的过程。HTML 采用流式布局模型,基本的原则是页面元素在顺序遍历过程中依次按从左至右、从上至下的排列方式确定各自的位置区域。一个HTML元素对应一个以CSS盒子模型(如图2-8所示)描述的方块区域,盒子模型决定了内容、边框和边框内外填充区(Padding、Margin)的大小。HTML元素分成两个基本类型,Inline和Block。Inline元素不会换行,按从左到右来布局。Block元素的出现意味着需要从上至下换到下一行来布局。除了这种基本的顺序按照元素的Inline和Block来进行流式布局之外,还有特殊指定的一些布局方式,如Absolute/Fixed/Relative三种定位布局以及Float浮动布局。简单情况下,布局可以顺序遍历一次Render树完成,但也有需要迭代的情况。当祖先元素的大小位置依赖于后代元素或者互相依赖时,一次遍历就无法完成布局,如Table元素的宽高未明确指定而其下某一子元素Tr指定其高度为父Table高度的30%的情况。

image

经过了Layout阶段的处理,我们把带Style的DOM树变换成包含布局信息和绘制信息的Render树,接下来的显示工作就交由Paint模块进行操作了。

  1. Paint
    Paint模块负责将Render树映射成可视的图形,它会遍历Render树调用每个Render节点的绘制方法将其内容显示在一块画布或者位图上,并最终呈现在浏览器应用窗口中成为用户看到的实际页面。每个节点对应的大小位置等信息都已经由Layout阶段计算好了,节点的内容取决于对应的HTML元素,或是文本,或是图片,或是UI控件。

通常情况下,布局和绘制是相当耗时的操作。如果DOM树每次略有改动都要重新布局和绘制一次,效率会相当低下。因此,一般浏览内核都会实现一种增量布局和增量绘制的方式。当一个DOM树节点(或者它的子节点)内容或者样式发生变化时,内核会确定其影响范围,在布局阶段会标记出受该节点布局影响的其他节点(比如可能是子节点),在绘制阶段则会标记出一个Dirty区域并通知系统重绘。
按照HTML相关规范,页面元素的CSS属性也规定了其绘制顺序,如根据不同Layer必须按顺序绘制,否则覆盖叠加效果会出现错误,如元素的边框轮廓和内容背景的绘制次序也有规定。
基本上浏览内核的工作原理即如上所述,不同浏览器的具体实现架构不尽相同,所采用的术语名称可能不一样,但都需要完成上述各个阶段的工作。例如,Mozilla Firefox浏览器使用的Gecko排版引擎主要流程如图2-9所示。
image

2.1.3 外壳

浏览器作为一个完整软件,除了对用户透明和不可见的渲染引擎作为内核外,还需要有供用户交互使用的外壳UI界面,图2-10给出了一个浏览器Shell的基本模块架构。目前的主流浏览器基本都会提供如下功能:
地址栏URI输入;
前进后退和刷新停止的控制按钮;
主页、网络导航和搜索;
历史、书签和下载管理;
多标签页浏览和会话管理;
查找、缩放和全屏;
数据持久化如Cookie、LocalStorage等;
选项设置;
插件和功能扩展。

image

由于Ajax、HTML 5等前端技术和浏览引擎的迅猛发展,今天的浏览器已经超出了展现某URL上网页内容这一基本功能的范畴,网页可作为绘图、办公、游戏、即时通信等应用的载体。Web App已经成为现实,浏览器也从单一的工具软件向Web OS的方向演进。每一个Web Page或Web App可看成对应于传统操作系统中的一个Native App,排版引擎作为Kernel执行Web App,浏览外壳作为GUI Shell供用户操作使用,多标签浏览器相当于多任务操作系统,Google的Chrome浏览器和由此演变而来的Chrome OS可看作这一想法的实施典型。图2-11描述了Chrome浏览器和WebKit排版引擎之间的层次结构和调用关系,图2-12则给出了Chrome多进程设计的核心架构。

image

image

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值