浅谈WebKit之WebCore
Chrome瀏覽器的代碼量其實是非常龐大的,要想對其有深入的理解,僅僅編譯編譯調試調試,是很難深入下去的。讓我們還是從其主要部分如多進程管理通信、WebKit、V8、Skia、WinHttp、Sanbox等著手分析其主要流程及數據結構,或許能達到事半功倍的效果,而WebKit是其中非常重要的一部分,是Chrome的核心引擎部分,其他部分都是基于它來集成的,深入了解了WebKit,對Chrome的理解就會迎刃而解,再說WebKit作為一個相對獨立的瀏覽器引擎在Safari、iPhone、Adobe AIR等中都有應用,非常值得大家深入的研究研究。
就像前面的文章所說,WebKit主要包括三個部分WebCore、JavascriptCore及Ports部分,讓我們先從WebCore部分出發吧。。。。
一、WebCore所包含的主要內容
1、從源代碼目錄結構來看
WebCore目錄主要包括如下目錄:
bindings?包含將Dom Binding給JavascriptCore方面的代碼,同時包含依據idl接口描述文件,自動生成對應于JavascriptCore的Binding實現的腳本等內容;
bridge?主要包含NPPlugin方面的接口訪問等內容;
css?主要包括與css方面相關的內容如解析、不同css規則的定義與實現、css Binding給JS的接口定義等內容;
dom?主要包括dom方面相關的內容如不同dom元素的定義與實現、dom Binding給JS的接口定義等內容;
html?主要包括html方面相關的內容如不同html元素的定義與實現、HTMLTokenizer及HTMLParser等內容;
loader?主要包括裝載資源如html頁面、css、js及image等方面內容;
page?主要包括描述一個Web頁面所涉及的內容如page、frame、frameview、frametree、setting、history、chrome、chromeclient等內容;
rendering?主要包括如何使用樣式,組織布局、顯示html元素等方面內容;
plugins?主要包括瀏覽端如何實現NPPlugin方面的內容;
svg?主要包括與svg方面相關的內容;
xml?主要包括與xml方面相關的內容如xml parser、XPath、XSLT等;
platform?主要包括與不同平臺或外部庫相關的內容如graphics(圖形輸出方面)、network(網絡處理方面)、image-decoders(解析不同圖片格式方面)等;
2、主要數據結構
為了更加簡單有效的描述瀏覽網頁的內容及過程,WebKit為了明顯區分不同方面的內容,采取了不同的namespace如webcore、javascriptcore、webkit等,webcore方面的主要數據結構有:
webcore::page、webcore::frame、webcore::FrameLoader、webcore::FrameView、Document、DOMWindow、KJSProxy、DocumentLoader、ResourceHandle、ResourceRequest、ResouceResponse、MainResourceLoader、RenderObject、RenderView等;主要數據結構描述如下:
WebView及WebFrame與page、frame之間的關系
圖一
FrameLoader、DocumentLoader、DocLoader類結構
圖二
主要Document類結構
圖三
FrameView類主要結構
圖四
總的說來,WebCore包含了瀏覽器引擎的核心部分如處理html、dom、css、svg、獲取資源、渲染頁面過程控制、回調/通知外殼程序以及與Javascript實現的Binding等等;
二、一個Http請求在WebCore中的主要流程
1、當調用webkit_web_view_open(url)時會觸發core(webView)->mainFrame()->loader()->load(uri)(即調用FrameLoader.load)來發起一個Http頁面請求;
FrameLoader.load方法的主要處理過程如圖:
圖五
2、一旦發起ResourceHandle::start,就會由網絡庫向web服務器發起一個http請求;
3、而MainResourceLoader作為一個ResouceHandleClient,提供了諸如didReceiveData()、didReceiveResponse()等回調接口以供網絡庫調用,一旦從web服務器獲得相關數據后網絡庫部分則會調用相關接口如didReceiveData等;
4、MainResouceLoader::didReceiveData的主要回調處理過程如下圖:
圖六
5、通過回調didReceiveData()方法,進而調用Node.attach()方法,這樣就會解析生成document,同時會創建frameview、domwindow等;
6、創建的frameview會觸發layoutTimerFired時間Timer,進而調用layout()方法,從而觸發RenderObject的創建、布局等,同時或許會invalidateRect,進而觸發操作系統圖形庫的paint消息事件;
7、由程序主消息處理循環接收paint消息事件,進而獲取對應frame,獲取或創建GraphicContext,然后調用frame->view()->paint(&ctx,...),從而觸發對應RenderObject樹進行重畫處理,這樣一個完整的頁面就會逐步的顯示出來。
三、網絡庫、圖形庫、Javascript實現與WebCore的集成
為方便擴展及模塊化,WebCore在處理瀏覽頁面的過程中,往往使用了類似java或gecko中接口的概念,一般先定義一組公共接口或基類,然后由不同模塊來實現。
如網絡處理部分由WebCore提供一個ResourceHandle類,而在不同的目錄如cf、curl、qt、soup、win等中在不同網絡庫的支持下對ResourceHandle類提供不同的實現,待編譯時擇機選擇對應目錄下的實現,這種方式從架構的角度看比較簡單,但往往不能讓程序同時使用多個網絡庫,進而由程序動態切換使用不同網絡庫實現,而gecko在xpcom的基礎上提供了對于這種擴展形式的支持;其中Chrome對ResouceHanle類的實現基于WinHttp網絡庫。
同樣WebCore對圖形庫的集成,也是采取這種方式來實現,如由WebCore提供一個GraphicsContext類,然后在不同的目錄如cairo、cg、qt、win、wx中在不同的圖形庫支持下對GraphicsContext提供不同的實現。其中Chrome對GraphicsContext類的實現基于Skia圖形庫。
WebCore中實現的dom、html、svg、css等,往往需要通過一定的方式輸出給Javascript的實現如JavascriptCore、V8,以便JS Engineer能認識這些dom元素等,并且能調用其中的方法,這種方式叫做Binding,為了便于將WebCore中相對固定的dom、html、svg、css接口等極其方便的Binding出去,WebKit使用了極其高效及神奇的方式來實現。
首先定義一組非標準的idl接口,然后通過運行一組perl腳本如generate-bindings.pl、CodeGenerator.pm、CodeGeneratorJS.pm等,就可根據idl接口定義,生成一組符合指定Javascript實現規則的腳本對象類。這樣極大的減輕了開發人員的投入及編碼錯誤的發生。
這一點與gecko中將不同的xpcom接口Binding給Javascript實現有本質上的差別,在gecko中通過xpconnect及一組classinfo來維護原生元素與JS對象之間的關系,不同原生元素對應的JS對象的創建及屬性方法的Binding完全依賴于xpconnect的實現及classinfo的定義,要添加刪除修改Binding的屬性與方法,只需修改classinfo;而WebKit中Binding,相對簡單明了,不同原生元素對應的JS對象的屬性與方法由idl接口文件來定義,而具體實現則交給威力強大的generate-bindings.pl來對應生成實現的代碼,這樣編譯時就可以輕松實現Binding。。。
四、參考資源
The WebKit Open Source Project
總結
以上是生活随笔為你收集整理的浅谈WebKit之WebCore的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebKit Frame对象分析
- 下一篇: 浅谈WebKit之JavaScriptC