目录

深入了解现代网络浏览器(2/4)【译】

导航栏里都发生了些什么

这是 4 篇博客系列中的第 2 篇,来窥探 Chrome 的内部工作原理。在上一篇文章中,我们探讨了进程和线程在处理浏览器不同模块时的区别。本篇文章我们将会更深层次地挖掘线程和进程为了渲染一个网站是如何进行有序通信的。

我们来看一个浏览器里简单的例子:在浏览器中输入一个 URL 地址,接着浏览器会从网络中请求数据然后渲染出一个页面。在这篇文章中,我们将会聚焦于用户请求一个站点随后浏览器准备渲染页面这一部分,也就是我们熟知的导航。

始于一个浏览器进程

正如我们已经在 上篇中阐述过的 GPU/CPU/内存/多进程架构 一样,浏览器进程处理了其每个标签页的所有任务。浏览器进程拥有像 UI 线程这样绘制按钮或者输入框的进程,还有网络线程从网络中接收数据,存储线程控制文件的访问等等这些进程。当我们在地址栏中输入一个 URL 地址时,我们的输入就会被浏览器进程里的 UI 线程处理。

/images/chrome/01.avif
图1:上方是浏览器的用户界面,下方则是浏览器进程的示意图,其中包含了用户界面、网络和存储线程。

一个简单的导航

第一步:处理输入

当用户开始在地址栏中输入的时候,UI 线程首要询问的是“这是一个搜索关键词还是一个地址咧?”。在 Chrome 中,地址栏同样是一个搜索框,所以 UI 线程需要解析并且决定是要把输入发送给搜索引擎,还是直接显示这个你请求的网站。

/images/chrome/02.avif
图2:UI 线程询问此输入是搜索关键字还是一个地址

第二步:开始导航

当用户敲了回车键,UI 线程会初始化一个网络命令去获取网站内容,此时在标签页的左上角会显示一个转圈圈的 loading ,随后网络线程会通过合适的协议,比如 DNS 查询为该请求建立 TLS 链接。

/images/chrome/03.avif
图3:UI 线程与网络线程通信,以导航到 mysite.com 站点
此时网络进程可能会收到一个服务器的重定向头信息,比如 HTTP 301 ,这种情况下,网络线程就会和 UI 线程对于服务器正在请求重定向进行通信,然后向另一个 URL 发起请求。

第三步:读取响应

当响应正文开始返回的时候,网络线程就会在必要时查看字节流的前几个字节,响应头中的 Content-Type 字段说明了数据的类型,但是由于它可能会出错或是不准确,所以此处会有一个 MIME Type Sniffing 检查来确认该数据是什么类型。这算是 源码 中提到的一个“小花招”,具体可以参见文章中的注释以了解不同的浏览器是如何处理 content-type/payload 的。

/images/chrome/04.avif
图4:响应头包含了 Content-Type 用以说明数据类型,而 payload 表示真实传输的数据

如果服务器返回的是一个 HTML 文件,那么下一步浏览器就会向渲染进程传递数据以渲染页面,但如果是一个 zip 文件或其他格式的文件,就意味着这是一个下载请求,此时浏览器需要把数据传递给下载管理器以下载文件。

/images/chrome/05.avif
图5:网络线程询问响应的数据是否是一个来自安全站点的 HTML

这也正是 SafeBrowsing 发生的时机。如果域名和响应数据看起来像个恶意的网站,这时网络线程会警惕性地显示一个提示页面,而且也会触发 Cross Origin Read Blcoking(CORB) 检测,以确保被攻击的垮站数据不会被传递给渲染进程。

第四步:查找渲染器进程

当所有的检测工作都已完成,并且网络线程也能够确信浏览器可以处理这个请求站点时,网络线程就会告诉 UI 线程数据已就绪,UI 线程就会寻找一个渲染器进程继续渲染这个网页。

/images/chrome/06.avif
图6:网络线程告诉 UI 线程去寻找一个渲染器进程