Chromium显示网页

原文链接:http://dev.chromium.org/developers/design-documents/displaying-a-web-page-in-chrome

概念应用层

s1UD_M3hHfzYDGIEg7yotXQ

每个框代表一个概念应用层。没有一层需要知道或者依赖他的上层。

  • WebKit:渲染引擎。Port是一个集成平台相关的系统服务的部分,比如资源加载和图像。
  • Glue:转换webkit类型到chromium类型。
  • Renderer / Render host:这是Chromium多进程嵌入层。它跨进程间代理通知和命令。
  • WebContents:Content模块的主类,一个可重用组件。很容易嵌入到一个view,让多进程渲染html。
  • Browser:代表浏览器窗口,包含多个WebContents。
  • Tab Helpers:单个对象能够附加到WebContents(通过WebContentsUserData插入)。浏览器能够附加一个属性给WebContentses。

WebKit

WebKit是网页布局的开源项目。代码来自apple现在存在 /third_party/WebKit 目录。WebKit主要包括WebCore(核心的布局功能)和JavaScriptCore(运行JavaScript)。我们运行JavaScriptCore只是为了测试目的,通常我们用更高性能的V8 JavaScript引擎代替。chromium实际上并不使用apple所谓的WebKit层,因为他跟OS X操作系统嵌入太深。为了方便笼统称呼来自apple的代码为WebKit。

WebKit Port

在最底层chromium有自己的WebKit Port。这是我们实现的所需特性平台有关的功能接口与平台无关的WebCore代码。这些文件在WebKit目录下。

WebKit glue

与third-party目录下的WebKit代码相比,chromium使用不用的类型,代码风格。由于WebKit glue使用了google编程风格和类型,更容易的api嵌入到Webkit中。

render process

Renderingintherenderer-v2

renderer 里面最重要的是位于/content/renderer/render_view_impl.cc的RenderView类。这个对象代表着网页。它处理所有发送和来自浏览器导航相关的命令。它派生自拥有绘制和输入事件处理的RenderWidget类。RenderView与 browser process通信时通过全局的RenderProcess 对象。

renderer中的线程

每个renderer都有两个线程。render线程是像RenderView和WebKit的代码在其中运行。当与浏览器通信时,消息首先发送到render线程,然后在发送到浏览器进程。

浏览器进程

rendering browser

低级浏览器对象

浏览器跟渲染进程的IPC通信都是在I/O线程里面完成的。这个线程还处理所有的网络通信,防止用户界面的干扰。

当一个RenderProcessHost在主线程里面初始化后,它创建一个新的渲染进程和一个ChannelProxy IPC对象(通过命名管道到达渲染进程)。这个对象运行在浏览器的I/O线程,并监听连接到渲染进程的命名管道,自动带回所有消息到UI线程的RenderProcessHost对象。一个ResourceMessageFilter设置在中间,用来过滤耨写I/O线程直接处理的消息,比如网络请求。这个过滤器在ResourceMessageFilter::OnMessageReceived。

UI线程里面的RenderProcessHost负责调度某个视图相关的消息到对应的RenderViewHost。这个调度发生在RenderProcessHost::OnMessageReceived。

高级浏览器对象

 

视图相关的消息来到RenderViewHost::OnMessageReceived。大多数消息就在这里处理,剩余的转发到了RenderWidgetHost的基类。这两个对象对应着基类的RenderView和RenderWidget。

上面的RenderView/Widget都是WebContents对象。WebContents代表这网页的内容。他是顶层的内容模块对象,负责在一个矩形视图里面显示网页。

WebContents对象包含一个TabContentsWrapper,代表一个标签。

说明性例子

设置光标消息的生命周期

设置鼠标光标消息是从渲染进程到浏览器消息的典型例子。在渲染进程里面:

  • WebKit内部产生设置鼠标光标消息。这个消息从content/renderer/render_widget.cc中的RenderWidget::SetCursor开始。
  • 它会调用RenderWidget::Send去调度这个消息。RenderView同样使用这样的方法给浏览器发送消息。它将会调用RenderThread::Send。
  • 它将会调用IPC::SyncChannel,内部把消息代理到主线程,然后通过命名管道发送到浏览器。

在浏览器这边:

  • RenderProcessHost里面的IPC::ChannelProxy在I/O线程里面接收到消息。一开始ResourceMessageFilter会调度网络请求和相关的消息直接到I/O线程。但是我们这个消息不会被过滤掉,它会继续被发送到UI线程。
  • Rcontent/browser/renderer_host/render_process_host_impl.cc里面的enderProcessHost::OnMessageReceived从对应渲染进程里得到所有的视图消息。它自己会处理一部分消息,其他的会通过RenderViewHost被转发到对应的RenderView。
  • 当消息到达content/browser/renderer_host/render_view_host_impl.cc中RenderViewHost::OnMessageReceived,很多消息直接在这里处理,但是我们这个消息会到 RenderWidgetHost里面。
  • 所有RenderViewHost未处理的消息自动转发到RenderWidgetHost,包括我们的设置鼠标光标消息。
  • content/browser/renderer_host/render_view_host_impl.cc里面的RenderWidgetHost::OnMsgSetCursor最终收到消息,做正确的处理。

设置鼠标点击消息的生命周期

鼠标点击消息是个从浏览器到渲染进程的典型例子。

  • 当RenderWidgetHostViewWin::OnMouseEvent调用ForwardMouseEventToRenderer会在UI线程收到windows消息。
  • 转发函数会打包输入事件到WebMouseEvent,然后发送到RenderWidgetHost。
  • RenderWidgetHost::ForwardInputEvent创建一个IPC消息ViewMsg_HandleInputEven,串行化WebInputEvent到里面,然后调用RenderWidgetHost::Send。
  • 消息又被转发到RenderProcessHost::Send,然后再给IPC::ChannelProxy。
  • IPC::ChannelProxy将消息代理到I/O线程,然后写入对应渲染进程的命名管道中。

WebContents还创建许多其他类型的消息。它们都有从WebContents到RenderViewHost类似的传递路线。

渲染进程接管了下面的控制:

  • 主线程的IPC::Channel收到了来自浏览器的消息,IPC::ChannelProxy代理消息到渲染线程。
  • RenderView::OnMessageReceived得到消息,许多消息直接在这里处理。但是点击消息一直传递到RenderWidget::OnMessageReceived然后又传递到RenderWidget::OnHandleInputEvent。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注