WebKit源码探索

您所在的位置:网站首页 webkit源码下载 WebKit源码探索

WebKit源码探索

2023-08-17 16:13| 来源: 网络整理| 查看: 265

前言

众所周知在iOS端有两种WebView:UIWebView和WKWebView,UIWebView在2020年已遭appstore禁止上传,也就意味着这个写起来代码少但是性能不咋地的WebView退出了iOS开发的舞台。关于WKWebView,我们知道它是多进程模型,拥有独立进程,性能高,但它究竟是如何运行的?好在WebKit是开源的,我们可以从源码角度窥探一二。本文将从WebView加载网页请求开始探索WebKit的运行机制

准备工作

所有的源码准备工作可以参考这篇文章 深入理解 WKWebView(入门篇)—— WebKit 源码调试与分析,这里有两个需要注意的点:

1、xcode workspace setting 的设置要将编译产物放到WebKitBuild,以及reletive到workspace,如下:

image.png

2、需要注意的是可以用源码里 Tools/Scripts 目录下的编译命令编译如下:

image.png

源码工程编译在我的17年丐版MacBookPro上消耗了两个多小时,接下来就是创建测试工程并添加到WebKit源码workspace中,然后在源码workspace内添加测试工程的scheme,至此准备工作完成。

进程创建流程探索

测试第一步,在默认的ViewController.m里编写一个简单的WebView加载网页的代码如下

#import "ViewController.h" #import @interface ViewController () @property (strong, nonatomic) WKWebView *webView; @end @implementation ViewController - (void)viewDidLoad {     [super viewDidLoad];     [self.view addSubview:self.webView];     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://m.baidu.com"]];     [self.webView loadRequest:request];     // Do any additional setup after loading the view. } - (WKWebView *)webView {     if (!_webView) {         WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];         configuration.preferences.javaScriptCanOpenWindowsAutomatically = YES;         [configuration.preferences setValue:@YES forKey:@"allowFileAccessFromFileURLs"];         if (@available(iOS 10.0, *)) {            [configuration setValue:@YES forKey:@"allowUniversalAccessFromFileURLs"];         }         WKUserContentController *wkUController = [[WKUserContentController alloc]init];         configuration.userContentController = wkUController;         _webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];         _webView.backgroundColor = [UIColor whiteColor];         _webView.opaque = NO;         _webView.scrollView.backgroundColor = [UIColor whiteColor];         _webView.scrollView.showsVerticalScrollIndicator = NO;         _webView.scrollView.showsHorizontalScrollIndicator = NO;         _webView.UIDelegate = self;         _webView.navigationDelegate = self;         _webView.scrollView.bounces = NO;     }     return _webView; } -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{ } -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ } -(void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{    }

选中对应的测试工程的scheme,运行。这几行代码只是简单加载一个网页,但我们可以在Xcode的debug navigator非常直观的看到WKWebView的多进程模型

image.png

可以看到这里有三个进程,按照进程创建顺序分别是APP进程,网页渲染进程,网络加载进程。

我们再来看看webview是如何创建的,在initWithFrame: configuration: 方法里打断点,重新运行

image.png

接下来到私有化初始化方法看下

image.png

这里可以通过打印看到_configuration对象的信息

image.png

继续执行

image.png

这里是一些process和UI界面的配置代码,接下来是contentview的创建

image.png

在创建代码执行完,可以在左侧debug navigator里看到渲染进程创建完成,后续的H5代码解析渲染将在这个进程中进行。我们有必要看下content view创建过程,点击跳转进去

image.png

继续跳转进入_commonInitializationWithProcessPool: configuration:

image.png

这里看到_page的初始化及设置,我们到头文件去看下这个_page是什么东西

image.png

这里可以看到_page是一个WebPageProxy对象,也就是说网页相关的操作都这这个对象来管理的,接下来是_page的一些初始化设置

image.png

image.png

这里可以看到在contentview上添加了子视图,和app生命周期的通知。最后返回WKWebview对象也就是self,完成webview初始化。

接下来代码进入webview loadRequest,为了看清具体方法的执行顺序,我们先给loadRequest下一个符号断点,然后找到WKWebview的loadRequest方法,可以看到最终通过_page调用loadRequest,在此处添加断点

image.png

image.png

然后放跑断点,程序断在_page->loadRequest(request),继续放跑,来到WebPageProxy的loadRequest

image.png

可以看到这里有个判断是否有正在运行的进程的代码,没有就初始化进程,但是通过调试发现并没有执行launchProcess代码,同时左侧debug navigator也并没有产生网络加载进程,说明网络加载进程并不是在这里生成的,接下来是创建navigation的代码,然后跳转到loadRequestWithNavigationShared函数继续加载请求

image.png

我们跳转到loadRequestWithNavigationShared函数内部看一下

image.png

这里可以看到构造了一个loadParameters参数,包装了一些配置信息,继续往下

image.png

这里进入了preconnectTo,那我们给这个函数下一个符号断点,放跑执行

image.png

这里执行了三个函数websiteDataStore(),networkProcess(),preconnectTo(),这里分别下符号断点,看一下

image.png

只是返回了m_websiteDataStore对象,这个对象存储了什么信息可以看一下,如下

image.png

这里内容很多,包括session,cookie,configuration等等的信息,接下来调用networkProcess,我们放跑看一下

image.png

可以看到这里是网络进程创建的代码,最后返回网络进程,我们可以验证一下,继续执行代码,观察左侧debug navigator是否会产生新的进程

image.png

image.png

可以看到网络进程是在这里创建的,我们再来看下网络进程是什么东西

image.png

可以看到是网络进程代理对象NetworkProcessProxy,那我们在文件导航里搜索一下,可以找到这个类定义的c++头文件

image.png

到这,webview的所有进程全部创建完毕。

总结

WKWebview的多进程模型,我们通过对源码的探索可以窥探其中的冰山一角。通过断点调试可以清楚的看到一个WKWebview包含的所有进程以及创建顺序:

app本身进程 webview页面UI进程 网络进程

那么接下来网络进程是如何请求数据和接收数据的?接收到的数据又是如何渲染到UI进程的?这些问题值得我们进一步去探索。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3