iOS之深入解析WKWebView的WebKit源码调试与分析
生活随笔
收集整理的這篇文章主要介紹了
iOS之深入解析WKWebView的WebKit源码调试与分析
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、前言
- 移動(dòng)互聯(lián)網(wǎng)時(shí)代,網(wǎng)頁(yè)依舊是內(nèi)容展示的重要媒介,這離不開(kāi) WebKit 瀏覽內(nèi)核技術(shù)的支持與發(fā)展。在 iOS 平臺(tái)下開(kāi)發(fā)者們需要通過(guò) WKWebView 框架來(lái)與 WebKit 打交道。
- 雖然蘋果官方提供了關(guān)于 WKWebView 的 API 與使用說(shuō)明,但這并不能滿足開(kāi)發(fā)者們的需求,各類復(fù)雜場(chǎng)景依舊讓我們焦頭爛額,而解決方案卻不易尋找。此時(shí),優(yōu)秀的開(kāi)發(fā)者們將目光移向蘋果開(kāi)源的 WebKit 內(nèi)核代碼,試圖從中尋找解惑之道,卻發(fā)現(xiàn)依舊困難重重,坎坷不斷,主要問(wèn)題如下:
-
- 內(nèi)核源碼復(fù)雜難懂:動(dòng)輒幾個(gè) G 的源碼,且缺乏關(guān)鍵代碼注釋與說(shuō)明,跟蹤分析工作量大;系統(tǒng)兼容分支較多,一塊代碼可能區(qū)分 iOS、Mac、嵌入式等分支;歷史代碼或?qū)嶒?yàn)功能較多,導(dǎo)致查看源碼并不容易縷清邏輯。
-
- 無(wú)法結(jié)合業(yè)務(wù)代碼分析:異常問(wèn)題往往在復(fù)雜場(chǎng)景下才會(huì)出現(xiàn),缺乏業(yè)務(wù)代碼的結(jié)合,問(wèn)題無(wú)法復(fù)現(xiàn),也就無(wú)法定位問(wèn)題,最終容易走上猜測(cè)原因、更換方案嘗試修復(fù)的路子。
二、源碼下載
- 編譯及調(diào)試之前,需要獲取一份蘋果官方的 WebKit 源碼:
-
- github 下載 WebKit 源碼
-
- 官方下載 WebKit 源碼
- 下載后的 WebKit 工程通過(guò) Xcode( Xcode 是蘋果官方推薦的 iOS 應(yīng)用開(kāi)發(fā)工具)打開(kāi)后目錄如下圖:
- 其中g(shù)test / MiniBrowser / MobblieMiniBrowser / TestWebKitAPI / WebKitTestRunner 倉(cāng)庫(kù)為測(cè)試倉(cāng)庫(kù)。考慮到編譯效率的問(wèn)題,通常情況下不需要編譯測(cè)試倉(cāng)庫(kù)。由于本文后面將描述如何有效利用這些測(cè)試倉(cāng)庫(kù),此處選擇進(jìn)行全源碼編譯。
三、源碼編譯
① Embedded Builds
- 下載的 WebKit 目錄里面有一個(gè)Tools/Scripts 目錄,這里面有各種腳本,包括使用命令行編譯 WebKit 的腳本,其中一個(gè)重要的腳本就是 configure-Xcode-for-embedded-development,在 Mac 終端控制臺(tái)運(yùn)行如下命令:
- 之所以需要執(zhí)行這個(gè)腳本,是因?yàn)?iOS 屬于嵌入式平臺(tái),編譯嵌入式平臺(tái)的 WebKit 需要用到一些命令行工具,Xcode 正是利用該腳本構(gòu)建這些命令行工具。否則,在編譯諸如 JavaScriptCore 等工程的時(shí)候,找不到對(duì)應(yīng)的架構(gòu),就會(huì)報(bào)如下錯(cuò)誤:
② 通過(guò) Xcode 進(jìn)行編譯,設(shè)置構(gòu)建產(chǎn)物存儲(chǔ)位置
- 在打開(kāi)工程后,選擇 Xcode 的 File 菜單,選擇Workspace Settings,然后打開(kāi) Workspace 設(shè)置窗口,如下圖所示:
- 接下來(lái)選擇 Advanced 按鈕,打開(kāi)如下窗口,按紅框所示,將工程編譯目錄配置為 WebKitBuild,點(diǎn)擊完成:
- 準(zhǔn)備工作終于完成了,接下來(lái)就可以開(kāi)始編譯了。
③ 開(kāi)始編譯
- 首先選中 All Source 選項(xiàng),配置 scheme 選擇模擬器運(yùn)行,然后點(diǎn)擊 Xcode 的構(gòu)建按鈕開(kāi)始構(gòu)建:
- 此處請(qǐng)耐心等待,首次編譯耗時(shí)較長(zhǎng),本文測(cè)試是在 i5 處理器 8G 內(nèi)存 MacBook Pro 機(jī)器上測(cè)試的,測(cè)試全源碼編譯耗時(shí) 1h。編譯成功后會(huì)彈出 MiniBrowser 不可用 警告(屬于 Mac 應(yīng)用工程),忽視即可。此時(shí)內(nèi)核編譯工作結(jié)束,接下來(lái)我們繼續(xù)進(jìn)入下一步,創(chuàng)建調(diào)試工程,進(jìn)行源碼探索。
- 聲明:推薦先使用命令行編譯一遍,再用 Xcode 編譯。從實(shí)踐來(lái)看,如果編譯過(guò)程中出錯(cuò),命令行編譯方式更易追蹤到具體異常信息。
四、創(chuàng)建調(diào)試工程
① 了解 WebKit 運(yùn)行機(jī)制及源碼:使用官方 Demo 工程調(diào)試
- 編譯完成后,在工程產(chǎn)物 WebKitBuild 目錄中會(huì)有一個(gè) MobileMiniBrower APP。此時(shí)可以在工程 scheme 配置中選擇 MobileMiniBrowser APP 進(jìn)行工程構(gòu)建,該 APP 是蘋果官方的瀏覽器 Demo (如下圖所示),可通過(guò)地址欄執(zhí)行地址輸入,前進(jìn)/后退以及多 Tab 等功能,可在源碼里進(jìn)行斷點(diǎn)測(cè)試:
② 分析實(shí)際業(yè)務(wù)問(wèn)題:使用自定義工程調(diào)試
- 針對(duì)這類需求,就需要按照如下步驟在工程中使用編譯成功的 WebKit.framework 去替換系統(tǒng)的 WebKit.framework:
-
- 首先,用 Xcode 新建一個(gè)新的 Project,示例里面是 TestWKWebView,并將這個(gè) Project 添加到 WebKit 的工程空間 WebKit.xcworkspace 中,編譯產(chǎn)物按照 WebKit 編譯所述,同樣輸出到 WebKitBuild 目錄。
-
- 做好上面的設(shè)置之后,就可以編寫測(cè)試程序,在測(cè)試程序中打上斷點(diǎn),這時(shí)你會(huì)發(fā)現(xiàn)系統(tǒng) WebKit 庫(kù)已經(jīng)被替換,斷點(diǎn)可跳轉(zhuǎn)源碼,即可愉快的進(jìn)行源碼探索了。
- 走到這一步后,大家可以發(fā)現(xiàn),WebKit 源碼很龐大,哪怕代碼 run 起來(lái)了,如何下斷點(diǎn)分析問(wèn)題依舊很難把控。
五、源碼實(shí)戰(zhàn)分析
① WebKit 的多進(jìn)程機(jī)制
- 在 iOS 系統(tǒng)中,通常一個(gè)應(yīng)用對(duì)應(yīng)一個(gè)進(jìn)程,但是在 WebKit 的發(fā)展過(guò)程中,基于穩(wěn)定性與安全性考慮,引入了多進(jìn)程的概念,避免單一頁(yè)面的異常影響整體 app 運(yùn)行:
-
- UIProcess:應(yīng)用程序所在進(jìn)程,WKWebView 代碼和 WebKit 框架已加載到你的進(jìn)程空間中;
-
- WebContent:又稱 WebProcess,JS 和 DOM 內(nèi)存分配所在的位置,即網(wǎng)頁(yè)內(nèi)容渲染與 js 執(zhí)行所處進(jìn)程;
-
- Network Process:負(fù)責(zé)發(fā)出與 Web 請(qǐng)求關(guān)聯(lián)的基礎(chǔ)網(wǎng)絡(luò)請(qǐng)求;
-
- Storage Process:用于數(shù)據(jù)庫(kù)和服務(wù)工作者的存儲(chǔ)。
- 單 webview 模型 Demo 進(jìn)行內(nèi)核分析:
-
- 在工程中簡(jiǎn)單使用一個(gè) WKWebView 來(lái)進(jìn)行網(wǎng)絡(luò)加載,以百度首頁(yè)為例,運(yùn)行項(xiàng)目后,點(diǎn)擊調(diào)試模式中的 show the debug navigator 選項(xiàng),該功能是 debug 下的資源分析模塊。
-
- 現(xiàn)在可以查看各進(jìn)程的 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)使用情況,當(dāng)然也可以進(jìn)行 Instruments 分析。
-
- 進(jìn)程分布如下:
| Demo 進(jìn)程 | 1個(gè) |
| NetWorking 進(jìn)程 | 1個(gè) |
| WebContent 進(jìn)程 | n個(gè)(每打開(kāi)一個(gè)新頁(yè)面,新增一個(gè) WebContent 進(jìn)程,可復(fù)用) |
- 多 webview 模型 Demo 進(jìn)行內(nèi)核分析:
-
- 使用多個(gè) WKWebView 進(jìn)行網(wǎng)絡(luò)加載,每加載一個(gè)網(wǎng)頁(yè),創(chuàng)建一個(gè)新的 WKWebView 實(shí)例。
-
- 進(jìn)程分布如下:
| Demo 進(jìn)程 | 1個(gè) |
| NetWorking 進(jìn)程 | 1個(gè) |
| WebConent 進(jìn)程 | n個(gè)(每打開(kāi)一個(gè)新頁(yè)面,新增一個(gè) WebContent 進(jìn)程,可復(fù)用) |
- 綜上所述:
-
- WebContent 進(jìn)程對(duì)應(yīng)的是每一個(gè)新開(kāi)的網(wǎng)頁(yè),該進(jìn)程視內(nèi)存情況可進(jìn)行復(fù)用,某一 WebContent 進(jìn)程的異常并不會(huì)影響到主 app 進(jìn)程,常見(jiàn)的異常現(xiàn)象為白屏。
-
- UIProcess 進(jìn)程為 app 所在進(jìn)程,WKWebView 在該進(jìn)程中提供了大量 API 供開(kāi)發(fā)者與內(nèi)核交互,也是開(kāi)發(fā)者最熟悉的一部分。
-
- NetWorking 進(jìn)程,無(wú)論多 WKWebView 還是單 WKWebView 場(chǎng)景,都只有唯一的 NetWorking 進(jìn)程,這種設(shè)計(jì)主要便于網(wǎng)絡(luò)請(qǐng)求管理以及保證網(wǎng)絡(luò)緩存、cookie 等管理的一致性。
- 有了上述理解,再去看 Xcode 下 WebKit 的文件目錄,目錄也按照進(jìn)程職責(zé)進(jìn)行了較為合理的劃分:
- 因此,在調(diào)試過(guò)程中,除了根據(jù)已知關(guān)聯(lián) API 或代碼堆棧進(jìn)行全局搜索或單步斷點(diǎn)調(diào)試外,我們還可以多結(jié)合三大進(jìn)程的工作職責(zé)進(jìn)行問(wèn)題分析與查找。另外,既然可以查看各進(jìn)程的 CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)等狀態(tài)了,對(duì)這方面有性能要求的,可以用來(lái)查看一個(gè)網(wǎng)頁(yè)加載時(shí)各進(jìn)程具體的資源消耗是多少。
② TestWebKitAPI 工程
- 使用源碼工程,除了代碼分析外,蘋果系統(tǒng)還提供了大量的系統(tǒng) API 相關(guān)功能測(cè)試,這些測(cè)試基于 gtest 框架實(shí)現(xiàn),集成在 TestWebKitAPI 工程里,實(shí)踐中按照如下思路可利用 TestWebKitAPI 工程進(jìn)行一些接口分析與測(cè)試:
-
- 了解各類 API(包括私有 API )的測(cè)試用例,通過(guò)這類代碼示范與說(shuō)明,便于我們深入了解接口的使用規(guī)范,更好的理解 API 的設(shè)計(jì)思路。
-
- 利用該框架可進(jìn)行 gtest 測(cè)試,gtest 是一個(gè)跨平臺(tái)的 (Liunx、Mac OS X、Windows、Cygwin、Windows CE and Symbian) C++單元測(cè)試框架,由 google 公司發(fā)布,它能在不同平臺(tái)上編寫 C++ 測(cè)試代碼。gtest 框架提供了豐富的斷言、致命和非致命判斷、參數(shù)化、”死亡測(cè)試”等。在 WebKit 內(nèi)核源碼中已有大量的基于gtest 框架的測(cè)試代碼積累,當(dāng)我們做了一些 trick 操作時(shí),基于 TestWebKitAPI 工程做自動(dòng)化測(cè)試,也是一種不錯(cuò)的選擇。
③ Tips
- WebKit 源碼調(diào)試可能在一般情況下不會(huì)用到,但是對(duì)于 WebKit 復(fù)雜問(wèn)題的分析與解決,結(jié)合業(yè)務(wù)對(duì) WebKit 源碼進(jìn)行探索與分析,還是有一定意義的。
- 特殊場(chǎng)景下,開(kāi)發(fā)者可能對(duì)一些 API 進(jìn)行特殊使用,這個(gè)時(shí)候可斷點(diǎn)調(diào)試的源碼能更好幫助我們規(guī)避風(fēng)險(xiǎn)。
- 蘋果官方禁止了在真機(jī)上替換 WebKit 內(nèi)核,我們可以編譯對(duì)應(yīng)的真機(jī)庫(kù),但是無(wú)法進(jìn)行安裝調(diào)試,因此本文里的內(nèi)容都是在模擬器進(jìn)行的。
- 因 WebKit 源碼在不斷更新,因此下載編譯過(guò)程中可能會(huì)遇到一些不兼容問(wèn)題,一般可通過(guò)注釋相關(guān)不兼容代碼解決。
總結(jié)
以上是生活随笔為你收集整理的iOS之深入解析WKWebView的WebKit源码调试与分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Swift之深入解析协议Protocol
- 下一篇: iOS之深入解析WKWebView加载的