(譯)Chrome如何顯示網頁

http://blog.csdn.net/zengwh/article/details/4285792

  • Chromium如何顯示網頁
      • 概念上的應用層
      • WebKit
      • WebKit Port
      • Webkit膠粘層
      • 瀏覽器進程
      • 底層瀏覽器進程對象
      • 高層瀏覽器進程對象
      • 演示示例
      • “設置光標”消息的處理過程
      • 鼠標單擊消息處理過程

譯:[email protected]

 

本文檔從底層到上層描述了chromium顯示網頁。確認您已經月度了多進程架構? 的設計文檔。您將特別想了解主要的組成方塊圖。您同時也可能有興趣瞭解多進程資源加載? ,以瞭解網頁如何從網絡下載。

概念上的應用層

chrome_layers.png

每個方框表示一個概念層。通過選取或者取代各層之上的層可以構建不同的瀏覽器應該是可能的。因此,任何層都不應該依賴任何比它層次更高的層或者需要更高層次的相關信息。

  • WebKit? :Safari、Chromium和任何其他基於Webkit的瀏覽器的渲染引擎。Port是WebKit的一部分,它與依賴於系統服務的平臺集成,如資源加載和圖形。
  • Glue:轉換Webkit類型成Chromium類型。這是我們的Webkit嵌入層。它是Chromium和test_shell(允許我們測試Webkit)這輛個瀏覽器基本的部分。
  • Render/Render host:這是Chromium的多進程嵌入層。它穿透進程邊界代理各種通知和命令。您應該可以想象其他多進程瀏覽器正在使用這層,它應該依賴瀏覽器的其他服務。
  • Tab contents:瀏覽器特定的層表示標籤的內容。它與歷史系統、口令管理登應用服務綁定。它不應該,而且決不假設它嵌入在一個Chromium瀏覽器窗口裏(它也可被其他瀏覽器組件像HTML對話框使用)。
  • Broeser:表示瀏覽器窗口,它嵌入了多個標籤內容(TabContentses? )。

WebKit?

我們使用WebKit開源工程佈局網頁。這些代碼來自蘋果而且存在/third_party/WebKit目錄。WebKit主要由表示內核佈局功能的 WebCore、執行JavaScript的JavaScriptCore組成。我們僅運行JavaScriptCore進行測試,通常我們以我們更高性能的V8引擎取代它。我們並沒有實際使用蘋果稱爲WebKit的那一層,這一層是嵌入WebCore和OSX應用Safari之間的API。爲了方便,我們把參考蘋果這一層的代碼稱爲WebKit。

WebKit? Port

在最底層我們有我們的WebKit Port。這是平臺無關的WebCore的代碼的接口在特定平臺的我們的實現。這些文件位於/webkit/port,且與WebCore的目錄層次相似。我們的port大部分都是與實際OS無關:您可以認爲是Chromium port的WebCore。少數部分像字體渲染的處理在每個平臺不同。

  • 通過多進程資源加載? 系統處理網絡資源和響應。而不是直接從render進程交由OS處理。
  • 圖形上使用爲Android開發的Skia圖形庫。這是一個跨平臺的圖形庫而且可以處理許多圖象和除文本外的基本圖形元素。skia位於 /third_party/skia。主要的圖形操作的入口是/webkit/port/platform/graphics /GraphicsContextSkia.cpp。它也被許多在同一目錄的其他文件如/base/gfx使用。

Webkit膠粘層

Chromium應用使用不同的類型、代碼風格和代碼佈局而不是第三方的WebKit代碼。WebKit膠粘層提供許多方便的嵌入的API爲 WebKit使用Goole代碼方便和類型轉換(如,我們使用std::string取代WebCore::String,GURL取代KURL)。膠粘層位於/webkit/glue。膠粘對象都與Webkit對象相似,只是以"Web"作爲前綴。例如,WebCore::Frame編程 WebFrame。

WebKit? 膠粘層隔離了基於Chromium的代碼庫與WebCore數據類型,以便基於Chromium代碼修改最小化對於WebCore的影響。基於次,WebCore的數據類型決不直接在Chromium使用。API都被加到WebKit膠粘層,以方便Chromium(when it needs to poke at some WebCore? object) 。

test_shell應用是缺少網頁瀏覽器骨架的應用,用於測試我們的WebKit port和膠粘層代碼。它像Chromium一樣使用相同的膠粘(glue)接口與webkit通訊。它沒有許多複雜的瀏覽器特性、線程和進程,但是提供了一個簡單的方法給開發者測試新代碼。這個應用也用於自動運行WebKit測試。

chrome_rendering_renderer2.png

Chromium的渲染進程使用glue接口嵌入了我們的webkit port。它沒有包含非常多的代碼:它的主要任務是成爲渲染器連接瀏覽器的IPC通道。

渲染器中最重要的類是RenderView,位於/chrome/renderer/render_view.cc。這個對象表示一個網頁。它處理所有來自或者到瀏覽器進程的瀏覽相關的命令。它由RenderWidget驅動,RenderWidget提供繪製和事件處理。 RenderView與瀏覽器進程通訊通過全局的(每個渲染進程一個)RenderProcess對象。

FAQ:RenderWidget與RenderView的區別是什麼?RenderWidget通過實現在glue層稱爲 WebWidgetDelegate的抽象接口映射成WebCore::Widget對象。基本上它可以認爲是屏幕上接收輸入事件和我們需要繪製的窗口。 RenderView繼承了RenderWidget而且是標籤或者彈出窗口的內容。它處理瀏覽命令另外處理繪製和widget的輸入事件。

每個渲染器有2個線程(見chrome多進程架構? 中的圖或者chroimum的線程? )。渲染器線程執行RenderView等主要對象和所有WebKit代碼。當它與瀏覽器通訊時,消息首先發送給主線程,主線程分發消息給瀏覽器進程。另外就是這種方式允許發送從渲染器到瀏覽器的同步消息。這種方式提供了瀏覽器等待渲染器的一組操作完成後繼續。一個簡單的例子是當JavaScript讀取cookie時。渲染器線程將阻塞而且主線程將投遞所有接收到的消息直到收到正確的響應。正常的處理都是一旦主線程收到消息就順序地發送給渲染器。

瀏覽器進程

chrome_rendering_browser.png

底層瀏覽器進程對象

所有與渲染器進程的通訊都有瀏覽器的IO線程完成。 這個線程同時處理所有網絡通訊? 這也保持了與用戶接口進行交互。當主線程(用戶接口在此執行)初始化RenderProcessHost。RenderProcessHost創建新的渲染器進程和ChannelProxy對象(與渲染器通過有名管道通訊)。RenderProcessHost在瀏覽器的IO線程中執行,同時偵聽來自渲染器的有名管道數據,而且自動前向通知所有消息給UI線程中的RenderProcess。ResourceMessageFilter安裝在這個通道里,這可以查到某種需要直接在IO線程處理的消息(如網絡請求)。ResourceMessageFilter::OnMessageReceived執行消息過濾。

UI線程的RenderProcessHost負責分發視圖相關的消息給合適的RenderViewHost(它處理有限的自身的非視圖相關的消息)。RenderProcessHost::OnMessageReceived進行這些消息的分發。

高層瀏覽器進程對象

當視圖相關的消息進入RenderViewHOst::OnMessageReceived,大多數這些消息在次處理,剩下的消息交給集成 RenderWidgetHost的類處理。渲染器中對應與這兩對象的分別是RenderView和RenderWidget(關於這些對象見渲染器進程)。在微軟的Windows上,我們將每個RenderWidgetHost與RenderWidgetHostHWND關聯。 RenderWidgetHost管理事件和繪製到本地的HWND。其他的系統我們採用相似的類管理本地輸入和繪製。

在RenderView/Widget之上的是WebContents對象,大多數的消息實際上都以在這個對象上的函數調用方式結束。每個WebContents表示顯示網絡數據的標籤的內容。它受一般的TabContents類(有許多其他TabContents的規範,如歷史和下載。)驅動。WebContents是大多數瀏覽和頂層瀏覽器UI更新的切換點。

FAQ:爲什麼將WebContents和RenderViewHost分離?這兩個對象提供了不同的功能層次。您可以認爲 RenderViewHost是Chromium的多進程嵌入層。RenderViewHost對象能用於(實際上不是)渲染內容的其他部分。例如,您可想象成一個帶有web視圖的對話框。它能使用RenderViewHost去管理繪製且與渲染進程通訊,但是它不能有標籤或者常見的瀏覽命令。 RenderViewHost通過抽象接口RenderViewHostDelegate前向傳遞許多消息給WebContents。 WebContents處理瀏覽狀態和任何與web瀏覽器UI相關的操作。我們假設的對話框不必需要任何這些功能,僅需要實現它關心的 RenderViewHostDelegate的部分接口。

演示示例

其他關於瀏覽和啓動的例子在獲取Chrome源碼? .

“設置光標”消息的處理過程

設置光標是由渲染器發送給瀏覽器的一個典型的消息。在渲染器按下面過程處理:

  • 設置光標消息由WebKit內部生成。典型地一般是響應輸入事件。設置光標消息由RenderWidget::SetCursor(chrome/render/render_widget.cc)發出。
  • 它將調用RenderWidget::Send去分發消息。這個方法也被RenderView使用去發送消息給瀏覽器。然後調用RenderThread::Send。
  • 接着調用IPC::SyncChannel,這個方法實現內部代理消息給渲染器的主線程同時投遞消息給發送消息給瀏覽器的命名管道。

接着瀏覽器接管該消息:

  • RenderProcessHost? 的IPC::ChannelProxy接收所有瀏覽器IO線程的消息。它首先發送它們給 RenderMessageFilter,RenderMessageFilter將直接在IO線程分發網絡請求和相關的消息。既然我們的消息沒有被過濾掉,它將繼續交由瀏覽器的UI線程(IPC::ChannelProxy內部如此實現)。
  • RenderProcessHost? ::OnMessageReceived(chrome/browser/render_process_host.cc)獲取所有響應渲染器進程的視圖的消息。它直接處理幾種類型的消息,且對於剩下的前向通知相應的RenderViewHost去響應來自RenderView的消息。
  • 消息到達RenderViewHost::OnMessageReceived(chrome/browser /render_view_host.cc)。許多消息在這裏處理,但是設置光標的消息不在此處,因爲它是一個來自RenderWidget的消息應該交給RenderWidgetHost處理。
  • 所有RenderViewHost未處理的消息都自動地前向通知給RenderWidgetHost,包括設置光標消息。
  • 在chrome/browser/render_widget_host.cc中的消息映射最終接收RenderWidgetHost::OnMsgSetCusor然後調用合適的UI函數去設置鼠標的光標。

鼠標單擊消息處理過程

發送鼠標消息是一個從瀏覽器發送給渲染器的典型消息。

  • 瀏覽器的UI線程通過RenderWidetHostHWND::OnMouseEvent接收到窗口消息,然後調用ForwardMouseEventToRenderer。
  • 這個前向通知函數將輸入事件包裝成跨平臺的WebMouseEvent且發送給與之相關的RenderWidgetHost後結束。
  • RenderWidgetHost::ForwardInputEvent創建一個IPC消息 ViewMsg_HandleInputEvent,序列化成WebInputEvnet。然後調用 RenderWigetHost::Send 發送。
  • 這將事件前向傳遞給RenderProcessHost::Send函數,這個函數按順序將消息傳遞給IPC::ChannelProxy。
  • 內部裏,IPC::ChannnelProxy將代理此消息給瀏覽器的IO線程。然後寫入與之相應的渲染器的命名管道。

注意:許多由WebContents創建的其他類型的消息,特別是瀏覽功能的消息,這些也按照相似的過程從WebContents傳遞到RenderViewHost。

然後渲染器接管該消息。

  • 渲染器的主線程的IPC::Channel讀取由瀏覽器發送的消息,且IPC::ChannelProxy代理給渲染線程。
  • RenderView? ::OnMessageReceived獲取這個消息。許多種類型的消息都在此直接處理。但是單擊消息卻不是,它將繼續(和其他所有未處理消息一起)通過此傳遞給RenderWidget::OnMessageReceived(它按照順序前向通知 RenderWidget::OnHandleInputEvent)。
  • 輸入事件最終交給WebWidgetImpl::HandleInputEvent。這個函數將它轉成WebKit的PlatformMouseEvent類且交給WebKit內部的WebCore::Widget類處理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章