欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

【Android】Chromium架构简介

程序员文章站 2022-06-28 16:58:18
一、Chromium架构介绍1、架构概览Chromium采用是多进程架构,为什么采用多层架构呢?因为构建一个从不会挂起或崩溃的渲染引擎几乎是不可能的。构建一个完全安全的渲染引擎也是几乎不可能的。web浏览器类似一个与过去的多任务操作系统合作的单独的用户,一个错误的web页面能让整个浏览器和所有正在运行的标签页停止运行。采用彼此隔离的独立进程,这样程序中的crash通常不会影响其他进程或整个浏览器,但是进程间数据的访问会受到一些限制。架构概览浏览器的标签页使用的是独立的进程,以此保护整个应用程序免...

一、Chromium架构介绍

1、架构概览

Chromium采用是多进程架构,为什么采用多层架构呢?
因为构建一个从不会挂起或崩溃的渲染引擎几乎是不可能的。构建一个完全安全的渲染引擎也是几乎不可能的。web浏览器类似一个与过去的多任务操作系统合作的单独的用户,一个错误的web页面能让整个浏览器和所有正在运行的标签页停止运行。采用彼此隔离的独立进程,这样程序中的crash通常不会影响其他进程或整个浏览器,但是进程间数据的访问会受到一些限制。

架构概览
【Android】Chromium架构简介

浏览器的标签页使用的是独立的进程,以此保护整个应用程序免受渲染引擎中的bug和故障的伤害。同时限制每个渲染引擎进程的相互访问,以及他们与系统其他部分的访问。某些程度上,这为web浏览提供了内存保护,为操作系统提供了访问控制。

Browser(浏览器进程或浏览器):运行UI 和管理 Tab/Plugin 的主进程。
Renderer(渲染进程或渲染器):标签页相关的进程,Renderer使用webkit开源引擎来实现中断与html的布局。

2、管理渲染进程

每个Renderer都有一个全局的RenderProcess对象,管理它与Browser之间的通信,维护全局的状态。Browser为每个Renderer维护一个对应的RenderViewHost,用来管理浏览器状态,并与渲染器交流。Browser与Renderer使用IPC进行交流。

3、管理view

每个渲染进程有一个以上的RenderView对象,由RenderProcess管理(它与标签页的内容相关)。对应的RenderProcessHost维护一个与渲染器中每个view相关的RenderViewHost。每个view被赋予一个view ID,以区分同一个渲染器中的不同view。这些ID在每个渲染器内是唯一的,但在浏览器中不是,所以区分一个view需要一个RenderProcessHost和一个view ID。
浏览器与一个包含内容的特定标签页之间的交流是通过这些RenderViewHost对象来完成的,它们知道如何通过他们的RenderProcessHost向RenderProcess和RenderView发送消息。

4、组件与接口

在渲染进程中:

RenderProcess处理与浏览器中对应的RenderProcessHost的通信。每个渲染进程就有唯一的一个RenderProcess对象。这就是所有浏览器-渲染器之间的交互发生的方式。
RenderView对象与它在浏览器进程中对应的RenderViewHost和webkit嵌入层通信(通过RenderProcess)。这个对象代表了一个网页在标签页或一个弹出窗口的内容。

在浏览器进程中:

Browser对象代表了*浏览器窗口
RenderProcessHost对象代表了浏览器端浏览器的与渲染器的IPC连接。 在浏览器进程里,每个渲染进程有一个RenderProcessHost对象。
RenderViewHost对象封装了与远端浏览器的交流,RenderWidgetHost处理输入并在浏览器中为RenderWidget进行绘制。

5、共享绘制器进程

通常每个新的window或标签页是在一个新进程里打开的。浏览器会生成一个新的进程,然后指导它去创建一个RenderView。有时候,希望在标签页或窗口间共享渲染进程。一个web应用程序会在期望同步交流时,打开一个新的窗口,比如,在javascript里使用window.open。这种情况下,创建一个新的window或标签页时,需要重用打开这个window的进程。

6、检测crash或者失误的渲染

每个到浏览器进程的IPC连接会观察进程句柄。如果这些句柄是signaled(有信号的),那么渲染进程已经挂了,标签页会得到一个通知。从这时开始,会展示一个“sad tab”画面来通知用户渲染器已经挂掉了。这个页面可以按刷新按钮或者通过打开一个新的导航来重新加载。这时,如果没有对应的进程,那么就创建一个新的进程。

7、渲染器中的沙箱

WebKit是运行在独立的进程中,可以限制它对系统资源的访问。例如:可以确保渲染器唯一的网络权限是通过它的父浏览器进程实现。也可以限制它对文件系统的访问权限来使用host操作系统内置的权限。除了限制渲染器对文件系统和网络的访问权限,还可以限制它对用户的显示器以及相关的东西的一些权限。

8、归还内存

让渲染器运行在独立的进程中,赋予隐藏的标签页更低的优先级会更加直接。通常,Windows平台上的最小化的进程会把它们的内存自动放到一个“可用内存”池里。在低内存的情况下,Windows会在交换这部分内存到更高优先级内存前,把它们交换到磁盘,以保证用户可见的程序更易响应。可以对隐藏的标签页使用相同的策略。当渲染器进程没有顶层标签页时,可以释放进程的“工作集”空间,作为一个给系统的信号,让它如果必要的话,优先把这些内存交换到磁盘。

9、插件

Firefox风格的NPAPI插件运行在他们自己的进程里,与渲染器隔离。

二、Chromium网页展示

1、了解应用概念层

【Android】Chromium架构简介

如上图,每一层都做了高度的抽象,分离,进行了解耦。每个矩形代表了一个应用概念层,每一层都不了解上一层,也对上一层没有依赖。

1、WebKit:Safari,Chromium和其他所有基于WebKit的浏览器共享的渲染引擎。WebKit
Port是WebKit的一部分,用来集成平*立的系统服务,比如资源加载与图像。

2、Glue:将WebKit的类型转为Chromium的类型。一般称为“WebKit嵌入层”。这是两个browser,Chromium,和test_shell(用来测试WebKit)的基础。

3、Renderer / Render host: 这是Chromium的“多进程嵌入层”。它代理通知,并执行跨过进程指令。

4、WebContents:一个可重用的组件,是内容模块的主类。易于嵌入,允许多进程将HTML绘制成View。

5、Browser: 代表浏览器窗口,包含多个WebContent。

6、Tab Helpers:可以被绑定到WebContent的独立对象(通过WebContentsUserData混杂)。浏览器将这些独立对象中的一种绑定到WebContent给它持有,一个给网站图标,一个给信息栏等等。

2、WebKit

Chromium使用WebKit开源工程来布局web页面。这部分代码是从Apple中pull过来的,存储在/third_party/WebKit目录。WebKit主要由“WebCore”+“JavaScriptCore”组成,WebCore代表了核心的布局功能,JavaScriptCore用来运行JavaScript。一般只在测试时运行JavaScriptCore,通常情况下,使用高性能的V8 Javascript引擎来代替它。The WebKit port在最低层,是平台相关功能的实现,它们与平台无关的WebCore代码交互。大部分与操作系统无关的,可以把它认为WebCore的“Chromium port”。但某些方面,比如字体渲染,必须在不同平台上做不同的处理。

3、Glue

Chromium应用程序使用不同的类型,编码风格,以及代码布局和第三方的WebKit代码。WebKitGlue使Google编码传统与类型为WebKit提供了一个更加方便的嵌入式API(例如,我们使用std::string而非WebCore::String,使用GURL而非KURL)。代码位于/webkit/glue。glue对象通常有与WebKit对象相似的命名,但在开头有Web前缀。例如, WebCore::Frame变成了WebFrame。WebKitGlue层将Chromium代码的其他部分与WebCore数据类型隔离开,以帮助减少WebCore的改变对Chromium代码基础的影响。因此,WebCore数据类型从不直接被Chromium使用。为了Chromium的便利,需要一些WebCore对象时,会把API加入WebKit的Glue层。

test shell应用程序是一个为测试我们的WebKit port和Glue代码的裸web浏览器。它在与WebKit交流时,像Chromium那样使用一样的Glue接口。它为开发者提供了简单的方式去测试新的代码,而不用理会许多复杂的浏览器特性,线程和进程。这个应用程序也被用于运行自动化WebKit测试。然而,test shell的缺点在于,它不像Chromium那样用多进程方式实践WebKit。内容模块嵌入在一个被称为“content shell”的应用程序,使测试工作更便利。

4、渲染器的进程与线程

【Android】Chromium架构简介

Chromium的浏览器进程使用Glue接口嵌入在WebKit port中,它的工作主要是作为渲染器端到浏览器的IPC通道。渲染器中最重要的类是RenderView,位于/content/renderer/render_view_impl.cc。这个对象代表一个web页面。处理与浏览器之间所有导航相关的命令。驱动RenderWidget提供绘图和输入事件处理。RenderView与浏览器进程通过全局(每个渲染器进程)RenderProcess对象与浏览器进程交流。

每个渲染器有两个线程。渲染线程是主要的对象,比如RenderView和所有的WebKit代码运行的地方。当它与浏览器交流时,消息一开始发送到主线程,主线程轮流分发消息给浏览器进程。在其他情况里,允许从渲染器同步发送消息到浏览器。当一个来自浏览器的结果是用于后续操作时,这可以用于小量的操作。例如:JavaScript从网页请求cookie。渲染器线程会阻塞,主线程会让所有的接收到的消息排队,直到得到正确的响应。此时任何接收到的消息会突然发送给渲染器线程以执行普通的处理。

5、浏览器进程

【Android】Chromium架构简介

底层浏览器进程对象
所有的与渲染器进程交流的IPC是在浏览器的I/O线程完成的。这个线程也处理所有的网络交流,使得它不受用户界面的干扰。当一个RenderProcessHost对象在主线程完成初始化(当用户界面运行时),它会创造新的渲染器进程和一个通道代理IPC对象(有一个命名了的管道通向渲染器),自动转发所有的消息回给UI线程的RenderProcessHost。一个ResourceMessageFilter会安装在这个通道,它会过滤指定的消息,以直接在I/O线程处理(比如网络请求)。这个过滤器发生在ResourceMessageFilter::OnMessageReceived里。UI线程中的RenderProcessHost负责分发所有view相关消息给合适的RenderViewHost(它自己处理有限数量的与View相关的消息)。这种分发发生在RenderProcessHost::OnMessageReceived中。

上层浏览器进程对象
View相关消息出现在RenderViewHost::OnMessageReceived。这里处理的大部分消息,剩下的部分转发给RenderWidgetHost基类。这两个对象在渲染器里里映射到RenderView和RenderWidget。每个平台有一个view类(RenderWidgetHostView[Aura|Gtk|Mac|Win])以集成到native view系统。

在RenderView/Widget上面是WebContents对象,大部分的消息事实上结束于这个对象的函数调用。一个WebContent代表网页的内容。它是内容模块的顶层对象,并且负责在一个矩形的view中展示网页。WebContents对象包含在一个TabContentsWrapper中,它位于chrome/。负责标签页。

三、Chromium插件结构

1、概述

插件是浏览器不稳定的主要来源。插件也会在渲染器没有实际运行时,让进程沙箱化。因为进程是第三方编写的,所有无法控制他们对操作系统的访问。解决方案是:让插件在各自独立的进程中运行。

2、进程内插件

Chromium有着在进程内运行插件的能力(对测试来讲非常方便),也可以在进程外运行插件。它们都始于非多进程WebKit嵌入层,嵌入层实现WebKit::WebPlugin接口。这实际由WebPluginImpl实现。WebPluginImpl在图中的虚线以上,与WebPluginDelegate接口交流,对进程内插件而言,这个接口由WebPluginDelegateImpl实现,它会与NPAPI包装层通信。
【Android】Chromium架构简介

在还没有WebKit嵌入层的时候,WebPluginImpl是对应的嵌入层。它会与“嵌入应用程序”通过WebPluginDelegate抽象接口交流,通过切换这个接口的实现,服务与进程内插件与进程外插件,在有了额外的Chromium WebKit API之后,增加了新的WebKit::WebPlugin抽象接口,它与旧的WebPluginDelegate接口有着相同的功能。这个接口合并WebPluginImpl和WebPluginDelegateImpl,在WebKit::WebPlugin层做进程划分。

3、进程外插件

Chromium通过切换上面的图中,虚线以上几层的实现来支持跨进程插件。这干预了WebPluginImpl层和WebPluginDelegateImpl之间的IPC层,让每个模式之间共享所有的NPAPI代码。所有旧的WebPluginDelegateImpl代码,以及与它通信的NPAPI层,现在是在独立的插件进程中执行了。

渲染器/插件通信通道的两端分别由PluginChannel和PluginChannelHost代表。对于每种它所使用的插件都持有一个PluginChannelHost对象(例如,Adobe Flash和Windows Media Player)。在每个插件进程中,每个渲染器进程会有一个PluginChannel,它们各自持有一个那种插件的实例。接着,channel的每个端点,对应许多不同的插件实例。例如,如果网页中嵌有两个Adobe Flash视频,渲染器端就会有两个WebPluginDelegateProxies对象,插件端就会有两个WebPluginDelegateStubs。channel用一个IPC连接管理这些对象直接复数的通信。在下图中,可以看到上面的进程内图表的类(用灰色表示),以及中间彩色的新的进程外代码层。

【Android】Chromium架构简介

使用一个stub(存根)/proxy(代理)模型进行通信,每个IPC通道的端点有一个stub和一个proxy,分别接收和发送消息给对应的插件。这会导致许多类变得迷乱。因此,WebPluginStub被合并到WebPluginDelegateProxy,现在它处理渲染器端与一个插件实例的所有IPC通信。插件端还没有合并,还剩两个类WebPluginDelegateStub和WebPluginProxy,概念上他们是相同的对象,只是代表了通信的不同方向。

4、系统全貌

下图展示了整个系统,有浏览器和两个渲染进程,它们都与一个共享的进程外Flash进程交流。总共有三个插件实例。WebPluginStub已经合并到WebPluginDelegateProxy中了。
【Android】Chromium架构简介

本文地址:https://blog.csdn.net/sinat_36955332/article/details/109616540

相关标签: 笔记