WebKit Loader 模塊介紹

webkit只是一個排版引擎,在Webkit排版/渲染一個網頁之前,需要從網絡上、或者本地文件系統中讀到網頁的http數據,對webkit來講,他要的就是數據,不管你是從網絡讀的還是本地文件讀的。

Loader就是這樣一個模塊,它承上啓下,不僅負責爲webkit引擎提供數據,還控制着webkit的繪製。另外,它同時還與提供數據的“來源”打交道。

先簡單舉例說明:

用戶輸入一個url,這時是Loader接收url請求,它把url傳遞給curl,設置curl的回調函數,當curl讀到數據,loader把數據傳遞給Parser,開始生成DOM

一.下面重點介紹一下與Loader相關的數據結構和模塊。

Frame:可以看做是瀏覽器外殼調用Loader的總入口,它就像我們印象中的一個網頁,它關注的是頁面的顯示(FrameView) 、頁面數據的加載(FrameLoader)、頁面內的各種控制器 (Editor,EventHandler, ScriptController, etc.) 等等,它包含以下模塊(只列出重點):

Document

Page

FrameView

RenderView

FrameLoader

DOMWindow

下面分別對以上模塊進行介紹:

1)Document:這個類的爺爺類是Node ,它是 DOM樹各元素的基類; Document有個子類是 HTMLDocument,它是整個文檔 DOM樹的根結點,這樣就明白了:原來Document 就是描述具體文檔的代碼,看一下它的頭文件,就更明白了,它的屬性與方法就是圍繞着各種各樣的結點:Text Comment CDATASection Element……

2)Page:我的理解是,PageFrame(嚴格說是FrameView)是一一對應的,Frame關注UIPage關注數據。現在的瀏覽器一般都提供同時打開多個窗口,每一個窗口對應的數據就是這個Page在管理了。

page.cpp文件裏,還有個重要的全局指針變量:static HashSet<Page*>* allPages; 這個變量包含了所有的page實例。

3)FrameView: 可以理解爲爲一個網頁的ViewPort,它提供一個顯示區域,同時包含的有Render根節點、layout排版相關接口、Scroll相關等。FrameViewLayout排版的總入口。

4)RenderView: FrameView差不多,只是分工不同,它管理與Render樹相關的事情。

5)FrameLoader:重點,FrameLoader類將Documents加載到Frames。當點擊一個鏈接時,FrameLoader創建一個新的處於“policy”狀態的DocumentLoader對象,一旦webkit指示FrameLoader將本次加載視爲一個導航(navigation)FrameLoader就推動DocumentLoader進入“provisional”狀態,(在該狀態,DocumentLoader發調用CURL發起一個網絡請求,並等待是html還是下載文件。)同時,DocumentLoader會創建一個MainResourceLoader對象(該對象在後面單獨介紹)。

6)。DOMWindow:實現了Dom的一些接口,如CreateNode等。



二、WebkitLoader有兩條加載數據的主線:(從上圖可以看到)

1. MainResourceLoader:該模塊主要加載主網頁請求。後面稱爲MainResource

2. DocLoader:該模塊除了主網頁外的所有子請求,如:.js文件,圖片資源,.css文件。 後面稱爲SubResource

MainResource部分:

FrameLoader->DocumentLoader->MainResourceLoader-ResourceHandleDocumentLoader經歷狀態:1)"policy"2) "provisional" 3) "commited"分別是等待、作爲navigation發送networkrequest、文件下載完畢

Subresource部分:

DocLoader->Cache->[CacheObjects]example: CacheImage->SubresourceLoader->ResourceHandle當請求一個資源時,首先查看Cache中是否存在該對象,如果存在直接返回;如果不存在,創建該Cache對象(如CacheImage),然後創建一個SubresourceLoader,加載資源。

例如:

加載圖片時,DocLoader首先詢問Cache,在內存中是否也存在(CachedImage對象),如果已存在,則直接加載,即省了時間又省了流量。如果圖片不在Cache中,Cache首先創建一個新的CachedImage對象來代表該圖片,然後由CachedImage對象調用Loader對象發起一個網絡請求,Loader對象創建SubResourceLoader。後面的流程就一樣了,SubResourceLoader也是直接把ResourceHandle打交道的。

接下來跟蹤一下Loader發送請求的代碼實現:

1. 用戶輸入URL後,最先調用的接口是:

FrameLoader::load(constResourceRequest& request)

ResourceRequest包含了:

KURL(處理url的一個類)setHTTPHeaderFieldsetHTTPContentType等與HTTP頭部相關的函數

2.Load()通過ResourceRequest數據調用createDocumentLoader(request,substituteData)來創建一個DocumentLoader

3.Load()函數繼續給request設置HttpAccept,Cache-Control HTTP頭等信息。

4.設置FrameLoader::checkNavigationPolicy函數進入"Policy"狀態。

5.判斷該url是否在Cache中等一系列狀態判斷後,進入DocumentLoader::startLoadingMainResource函數準備加載MainResource。該函數首先會創建調用MainResourceLoader

6.進入MainResourceLoader::load函數,調用illSendRequest(r,ResourceResponse());做發送請求前的準備。

7.調用PolicyCheck檢查policy的狀態後,進入FrameLoader::callContinueLoadAfterNavigationPolicy繼續往下走。

8:MainResourceLoader::loadNow(ResourceRequest&r)函數裏創建ResourceHandle,在創建ResourceHandle函數中,調用start函數,start函數把ResourceHandle自已添加到ResourceHandleManagerm_resourceHandleList隊列裏。

同時,調用m_downloadTimer.startOneShot激活網頁請求下載的定時器。(這是個毫秒級的定時器,採用定時器的原因也是爲了實現異步的請法)

可以看到m_downloadTimer的定義:Timer<ResourceHandleManager> m_downloadTimer;

m_downloadTimer是實現的一個定時器模塊類,在它的構造函數裏已經傳入了回調函數的地址:ResourceHandleManager::downloadTimerCallback

9. 一路返回到Load()函數,並返回到調用源,函數執行完畢。

10. ResourceHandleManager::downloadTimerCallback回調函數被定時器調用。

11. 可以看到downloadTimerCallback函數的代碼:

調用libcurl庫的接口curl_multi_fdset,curl_multi_perform等查詢數據。


webkit應用場景再舉例:

用戶給出一個URL (直接輸入或者點擊鏈接或者JavaScript 解析等方式)。然後瀏覽器外殼調用FrameLoader 來裝載頁面。FrameLoader 首先檢查一些條件(policyCheck()) ,如 URL是否非空、 URL是否可達,用戶是否取消等等。然後通過DocumentLoader 啓動一個MainResourceLoader 來裝載頁面。MainResourceLoader調用 network 模塊中的接口來下載頁面內容(ResourceHandle ),實際上這裏的Resourcehandle已經是平臺相關的內容了,接收到數據以後,會有回調函數,告訴MainResourceLoader數據已經接收到了。然後一路返回到FrameLoader 開始調用HTMLTokenizer 解析 HTML文本。解析過程中,如果遇到Javascript 腳本的話,也會調用Javascript 引擎( Webkit中的 JavascriptCore chrome 中的 V8)來解析。數據被解析完了以後,生成了一個一個的node ,生成 DOM 樹和Render 樹,然後通過FrameLoaderClient 調用外部的殼把內容顯示出來。”


因此,總結Loader的功能:

Loader 是在WebKit裏面一個很重要的連接器,通過loader發起IO下載網頁,圖片等數據,再通過loader發起解析,以及最後的渲染功能。


上面過程還沒縷清,需要以後慢慢體味。


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