[Chromium] Chromium Android WebView层的设计

Chromium Android WebView是Chromium专为Android WebView提供一个对Content的封装层。从整体上来看可以理解为一个特殊化的Embedder, 功能可以概括为:
   1. 对Content和部分Browser Components封装到Java实现,供AOSP WebView调用实现WebView功能。
   2. 实现Android WebView使用的单进程渲染架构。
   3. 配置网络模块,并实现特定需要的scheme解析。

Content作为一个能力提供者,所以它的API也被称为SPI, 即Service Provider Interface。CAW一方面要调用Content的接口执行操作,另一方面扩展Content需要Embedder实现的接口(Client类和Observer类)。

其架构如下:
     技术分享

其内部包括了6个部分:
native & java封装CAW为java实现,供上层的AOSP WebView使用。
ContentMainDelegate (AwMainDelegate): 像其它Embedder一个,为配合Content的启动管理者ContentMainRunner提供启动功能。
Component Clients: 为使用到的Browser Components提供客户端代码。比如AutoFill的客户端AwAutofillClient, 还有一个是WebContentsDelegate。
Renderer: 则是负责利用Renderer进程的扩展机制(基本上都是Observers), 对Renderer进行干预。
Browser:负责实现Browser进程的业务逻辑,其中也包括了net和renderer_host两个子项目。
*CAW同时需要使用到网络模块。网络模块本身是一个公共的基础组件。
*以Renderer/Browser的目录命名来区分针对不同进程下功能的实现,这在其它模块里也是普遍使用的方式,如Components。

代码的命名空间都在android_webview下。

ContentMainDelegate

代码在src/android_webview/lib/main。

ContentMainDelegate是与Content交互的中心接口,负责具体的执行启动过程,以及按需要创建出与不同进程/线程交互的四个Clients,负责Content初化配置。
  技术分享
主要功能包括:
   1. 对应上面类图中前三个函数。它可以干预启动过程,特别是在启动过程指定了一些功能的开关。比如禁用了File System API, WebRTC hardware decoding等。以下是启动的流程:
      技术分享
   2. 对应上面类图中后四个函数。可以让Embedder自定义Content的行为。比如ContentRendererClient和ContentBrowserClient, 分别是针对Renderer和Browser进程的扩展机制。下面会再展开。


API (native & java)

目录: src/android_webview/java 和src/android_webview/native
AOSP WebView对外提供一个WebView控件,而CAW则负责提供AwContents封装WebView所需要的Contents功能。如下图所示:
技术分享

另一个示例CookieManager,则是实现到net::CookieMonster的桥接:
技术分享

主要的接口类包括负责加载native library等初始化操作的AwBrowserProcess, 以及围绕着AwContents的几个核心类, 既有直接注册于Content层的Observer实现的(AwContentsClient),也有通过native操作Content的(AwSettings):
技术分享
其中AwContentsClient是一个组合的结果,来自于Content层的两个重要通知接口ConentViewClient,ContentVideoViewClient, WebContentsObserver都会转到AwContentsClient,再提供给AOSP层。
AwBrowserContext存储Browser所需要的一些对象,如SharedPreferences (Android的一个基于XML的存储机制), CookieManager等。

(SharedPreferences主要用于AwGeolocationPermissions存储在各个域名下的开关设置,是否可以集成到统一的Settings? 或者Global Settings参考SharedPreferences来实现?)

另外在WebView中定义的一些相关类,都可以在这层找到对应的实现。
   android.webview.WebStorage  <——> AwQuotaManagerBridge <—JNI—> storage::QuotaManager
   android.webview.CookieManager <——> AwCookieManager <—JNI—>net::CookieMonster



Renderer

交互的手段主要基于Renderer的扩展,包括Observer, Client和IPC机制。
 涉及的类图:
技术分享
各类的职责可以从其方法定义上就可以看出来,不再赘述。

下图可以反应出其中RenderViewObserver的机制:
技术分享
 *其中AwRenderViewHostExt是类似的类,属于在Browser进程的实现。 
 
主要的时序图:
技术分享


Browser

CAW的Browser模块实现了CAW的大部分业务逻辑,包括对Content的封装调用,以及单进程渲染架构的实现。渲染的部分和对网络模块的封装在下面另外说明。

对Content的封装主要是对content API中Browser进程部分进行封装、实现,是作为一个Embedder必需的部分,涉及的类比较多,其中以AwContentBrowserClient为核心。(回顾一下AwMainDelegate那张类图。)
技术分享



渲染

下图来自再谈Chromium WebView硬件渲染模式的演进,其中1&2可以反应出CAW需要负责WebView onDraw操作与Synchronous Compositor之间的联系。

技术分享

上面的数字已经说明了整个绘制过程。简化来看CAW的渲染基于Android View的onDraw()操作,再调回到Android View的ViewRoot。
      技术分享

  以下为主要类图:
技术分享


网络


主要类图如下:
技术分享
AwNetworkDelegate在请求的Header中添加X-Requested-With来标识是当前包所发送的请求。
AwURLRequestContextGetter除了初始化网络上下文(包括指定Android特定scheme的解析器.),还会将BrowserThread指定为网络线程。


当有第一次获取URLRequestContext时就会触发创建创建过程,建立网络上下文环境。然后就可以基于它发起加载请求。如下图所示:
技术分享

Android特别的schemes处理

上图中net::URLRequestInterceptingJobFactory使用层层嵌套的Job factory组成针不同schemes的解析链。如下图:
技术分享
要点:
  1. 实现了AndroidStreamReaderURLRequestJob支持以Java Stream的方法读取数据的请求。
  2. AndroidRequestInterceptorBase实现任务控制,并在AwURLRequestContextGetter向网络层注册分别针对content:和asset (file:///android_asset/ and file:///android_res/ )的协议解释器。

技术分享


CAW对Components的依赖

技术分享

转载请注明出处: http://blog.csdn.net/horkychen


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。