原文:Multi-process Resource Loading
背景
浏览器主进程及browser process处理所有的网络通信。原因有三点:
- Browser process可以控制每一个renderer进程的网络访问
- Browser process可以在进程间管理session状态,保持其一致性
- Browser process可以针对每个host管理最大链接数
概述
作为一个多进程应用,Chrome分为三层。最底层的是webkit库,它主要负责页面渲染工作。之上是渲染进程Renderer Process(简单来说,就是一个tab一个渲染进程)。每一个渲染进程包含一个WebKit实例。而管理这些渲染进程的则是最上层的Browser Process。这一层控制者所有的网络访问。
WebKit
WebKit中负责拉取数据的对象是ResourceLoader。每一个loader均对应一个ResourceHandle。后者用于执行网络请求。ResourceHandle的头文件在WebKit代码里。我们无意于fork它。幸运的是,ResourceHandle有一个被称为d的成员(ResourceHandleInternal)。我们移除了原有实现,替换成我们的实现。实现代码在webkit/glue/resource_handle_win.cc。尽管名字中带有win标识,但它与Win32没有一毛钱的关系。
ResourceHandleInternal实现纯虚接口ResourceLoaderBridge::Peer。该接口类定义位于webkit/glue/resource_loader_bridge.h文件中。Renderer使用该callback接口向WebKit发送数据及其它事件(什么其它事件呢??)。
WebKit中的ResourceHandleInternal通过ResourceLoaderBridge纯虚接口与WebKit对话。该接口的一个实现参见ResourceLoaderBridge::Create。Create方法由Renderer实现。而Shell则使用不同的资源加载器,所以,也提供一种不同的实现方案。
Renderer
ResourceLoaderBridge在Renderer中的实现为IPCResourceLoaderBridge。该类位于renderer/resource_dispatcher。它使用一个全局的单例对象ResourceDispatcher(每个Render Process对应一个)生成一个唯一的请求ID,然后把请求转发给Browser(通过IPC方式)。响应数据则由Browser根据请求ID回送给ResourceLoaderBridge:Peer对象。
请求与数据间的对话由common/resource_loader_ipc完成。
Browser
RenderProcessHost对象(原作者也是个懒虫,图中居然没有)接收来自Renderer的IPC请求。它把请求转发给全局对象ResourceDispatcherHost。ResourceDispatcherHost保留RenderProcessHost的指针地址,通过地址来引用render process host。ResourceDispatcherHost根据请求ID来唯一标识一个请求。
Browser将每一个请求转化为URLRequest对象。URLRequest会把请求交给其内部类URLRequestJob。URLRequestJob与具体协议有关(又是个干活的哦)。当URLRequest有通知时,它的ResourceDispatcherHost::Receiver和请求ID则用于发送通知给正确的RenderProcessHost。RenderProcessHost负责把通知发送给Renderer。
Cookies
(说到网络,Cookies是不得不谈的,它方便又恶毒。)所有的Cookies均由CookieMonster(居然叫monster)处理。该类位于/net/base目录下。我们不在WinInet(?)*享cookies。cookie monster生存于browser进程中,处理所有的网络请求。
如果一个文档需要请求cookies,Pages可以通过调用document.cookie来为它请求cookies。当该调用发生时,我们从Renderer发出一个同步消息给Browser,达到请求cookies的目的。当Browser处理cookie时,WebKit会挂起。当Renderer的I/O收到来自Browser的响应时,Renderer取消WebKit挂起,把结果回送给JavaScript引擎。