Chromium如何顯示Web頁面


Displaying A Web Page In Chrome

概念化的應用分層

s1UD_M3hHfzYDGIEg7yotXQ

參見原文檔:http://goo.gl/MsEJX

每一個box代表一個抽象層。下層不依賴於上層。

  • WebKit:渲染引擎。Safari,Chrome / Chromium均在使用。國內的則有百度瀏覽器,QQ瀏覽器,獵豹等。Port(即移植)是webkit的一部分,它負責整合與系統相關的服務,如資源下載,圖像解碼等。
  • Glue:膠水層。負責把WebKit的數據類型轉換為Chromium的數據類型(與android平台中的glue含義一致)。他屬於webkit嵌入層。正是這一層的作用使得webkit可以嵌入到系統中。它也是Chromium和test_shell的基礎。
  • Renderer/Render host:Chromium的多進程部件。它處理通知及命令。
  • WebContents:Content模塊的主類,一個可以利用的組件。使用他就可以實現多進程渲染。更多細節請點擊content module pages
  • Browser:代表瀏覽器窗口。它包含多個WebContent。
  • Tab Helpers:一群獨立對象。它們可以附着到一個WebContents上。

WebKit

我們使用開源的WebKit實現網頁布局。這部分代碼是從Apple拉取的,放在third_party/WebKit目錄下(啟用blink后不一樣了親。。。)。WebKit由兩個引擎構成:WebCore和JavaScriptCore。WebCore負責網頁布局;JavaScriptCore負責運行js代碼。我們僅在測試的情況下才會運行JavascriptCore。正常情況,我們使用我們自己的V8引擎。它的性能比JavaScriptCore要好的多。我們沒有使用WebKit這一層(Apple的稱呼)。

WebKit Port (移植或適配層)

在底層,我們有自己的WebKit適配層(port)。與平台相關的功能接口均在這里面實現。這些代碼位於WebKit目錄下的chromium目錄。其實,許多的移植是與os無關的。但像字體渲染是必須和平台綁定在一起的。

  • 網絡流量由多進程資源加載系統處理,而不是依賴於os。
  • 圖像使用為Android開發的Skia圖形庫。這是一個跨平台的圖形庫,處理所有的圖像和圖形。Skia代碼位於/third_party/skia目錄下。圖形操作的入口位於/webkit/port/platform/graphics/GraphicsContextSkia.cpp中。

WebKit glue (膠水層)

Chromium應用使用不同於WebKit源代碼的數據類型,代碼風格,以及代碼布局。WebKit glue提供一個更加方便的嵌入API。該API使用google代碼類型,比如,我們使用std:string代替WebCore::String,使用GURL替換KURL。glue代碼位於/webkit/glue目錄下。glue的對象命名與WebKit的對象類似,但均以”Web”開頭。比如,WebCore::Frame變成WebFrame。

WebKit glue層將Chromium代碼與WebCore的數據類型分離,把WebCore對Chromium的影響降到最低。所以,WebCore中的數據類型絕對不會被Chromium直接使用。

“test shell”應用是一個“裸”的web瀏覽器,僅用於測試WebKit移植和glue代碼。它使用glue接口與WebKit通信。Chromium也是這樣做的。它向開發者提供一個更簡便的測試新代碼的方式,不需要關注眾多復雜的瀏覽器feature,線程及進程。WebKit的自動化測試也是由這個應用跑的。但是,test shell的缺點就是它畢竟和Chromium不一樣。content模塊嵌入到一個叫“content shell”的應用中。

Render進程

Renderingintherenderer-v2

Chromium的render進程通過glue接口嵌入WebKit port。它沒有太多的代碼:它的首要職責是作為連接browser的IPC channel另一端 - Renderer。

Renderer中最為重要的類是RenderView,位於/content/renderer/render_view_impl.cc。這個對象代表一個web頁面(web page)。它處理所有的navigation相關的命令。這些命令可以來自Browser進程或者發向Browser進程。RenderView類繼承自RenderWidget。RenderWidget提供繪制和輸入事件的處理。RenderView與Browser進程間通過全局對象RenderProcess通信。

FAQ:RenderWidget和RenderView兩者間有什么不同?

RenderWidget實現了glue層的抽象接口WebWidgetDelegate,以此映射到WebCore::Widget。這是屏幕上最基本的一個窗口。該窗口會接收輸入事件並且繪制的結果也送到該窗口中。RenderView繼承自RenderWidget。它是一個tab或一個彈出窗口的內容。它處理navigational性質的命令(導航命令??)。RenderWidget僅在一種情況下可以獨立於RenderView存在:web頁面上的選擇框。這些框通常帶有向下的箭頭。這個箭頭用於彈出可選項。這個選擇框性友用native窗口渲染。因為只有這樣,選擇框才能出現在其他元素的上面。這些窗口需要接收輸入事件,但並沒有一個分離的“web page”(即RenderView)來做這件事。

Renderer中的線程

每一個Renderer有兩個線程。一個是render thread(即渲染線程);另一個是主線程。像RenderView和WebKit代碼均運行在這個線程里面。當Renderer需要與Browser通信時,消息先被發給主線程。主線程負責把消息轉發給Browser進程。除了別的之外,這種機制也允許我們以同步方式向Browser發送消息。這種情況發生在一小部分操作時。這些操作通常需要等待瀏覽器的返回結果才可以繼續。比如,通過js獲取一個page的cookies。此時,Renderer線程就會阻塞。主線程把收到的所有消息入隊直到收到正確的響應。這期間收到的任何消息均會被送到Renderer線程,走正常的處理流程。

Browser進程

rendering browser

 

低級對象(low-level browser process objects)

所有Renderer進程的IPC通信都是在Browser的I/O線程中完成的。這個線程也處理網絡通信。該方案可以避免對用戶交互的影響。

當主線程初始化完一個RenderProcessHost對象后,該對象會創建一個新的Renderer進程並分配一個ChannelProxy給Renderer(以命名管道方式)。該對象運行在瀏覽器的I/O線程里,監聽該命名管道並自動把消息轉發給RenderProcessHost對象(該對象在UI線程,即主線程里)。一個ResourceMessageFilter對象會被安裝到Channel上,用於過慮特定的消息。這些特定的消息可以被I/O線程直接處理,如網絡請求。這種過濾行為發生在ResourceMessageFilter::OnMessageReceived里。UI線程里的RenderProcessHost負責分發所有view相關的消息給相應的RenderViewHost。這種分發行為發生在RenderProcessHost::OnMessageReceived里。

高級瀏覽進程對象(High-level browser process objects)

View相關的消息來到RenderViewHost::OnMessageReceived中。這些消息有大部分在這里被處理掉。剩下的則被轉發給RenderWidgetHost基類。這兩個類分別映射到Renderer中的RenderView和RenderWidget。每一個平台均會有一個view class(RenderWidgetHostView[Aura|Gtk|Mac|Win]),實現到native view系統的整合。

WebContents對象位於RenderView/Widget之上。大多數消息在這個對象被方法調用消費掉。一個WebContents代表一個web page的內容。它是content模塊的頂層對象。它負責在一個矩形視圖(view)里顯示一個web page。要查閱細節,請點擊“Content Module Pages”。

WebContents對象被一個叫做TabContentsWrapper包含。該類位於chrome目錄,代表一個tab(即標簽頁)。

兩個說明性示例

Set Cursor(光標)消息的生命周期

暫無

鼠標點擊消息的生命周期

暫無


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM