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