打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
chromium:LoadUrl之后会发生哪些事情之资源下载

本文链接:https://blog.csdn.net/Fantasy_116/article/details/47048115

一 综述

  本文主要分析在Android系统上,基于chromium内核的浏览器loadUrl的流程。

作为android开发者都知道WebViewAndroi系统非常重要的组件,任何需要和网络打交道的app都需要WebView,而访问网络资源,加载一个网页页非常简单,形如

webview.loadUrl("http://m.baidu.com");就会在webview中把百度首页展示出来,是不是非常的神奇。

  那么本文会基于chromium44版本的content_shell_test和Android WebView 分析一下Browser的loadUrl后,内核到底发生了什么?有必要提一下,android4.4(Kitkat)以后,Android系统的WebView内核支持从WebKit切换成了google自家chromium/blink内核。给整个webview的架构带来了巨大的变化。应用开发者看到的是webview,下面与它对接的是WebViewChromium类,然后WebViewChromuim会调用AwContentsAwContents紧接着会相关到ContentViewCore, 如图1所示

图1 Android WebView架构图

上图中WebViewProvider是一个接口类,WebViewChromiumWebViewProvider的具体实现类,同时又起着连接Chromium的作用。

Android 4.4上,代码结构如下:

#1 frameworks/base/core/java/android/webkit

这里是对Application可见的WebViewWebViewSettings等等。

#2 frameworks/webview/chromium/java

这里是桥接层代码,比较重要的类是WebViewChromium,起到实现WebViewProvider接口,以及连接到chromium

#3 frameworks/webview/plat_support/

由于WebView的内核是chromium,在页面绘制时还需要调用Android系统相关接口,所以,这里主要是提供Android平台支持。

#4 external/chromium_org/android_webview/

这里是chromiumAndroid平台上的顶层入口部分。

二 WebView loadUrl

Application使用WebView进行网页显示时,都会调用loadUrl,并将想访问的网页URL作为参数传入:WebView.loadUrl()--->WebViewProvider.loadUrl()

WebViewProvider是一个接口类型,具体实现是WebViewChromium类。

WebViewChromium作用在代码中已有清晰的解释:This class is the delegate to which WebViewProxy forwards all API callsMost of the actual functionality is implemented by AwContents (or ContentViewCore within it)。

同时,这段解释还说明了其内部功能的正真实现是由AwContentsContentViewCore完成的。

--->WebViewChromium.loadUrl()-->loadUrlOnUiThread(loadUrlParams) --->AwContents.loadUrl(loadUrlParams)

AwContentsloadUrl中会调用NavigationControllerloadUrl,而NavigationController又是一个接口类,它的具体实现是NavigationControllerImpl类。

--->NavigationControllerImpl.loadUrl(params)

通过JNI进入到native层的navigation_controller_impl.cc, 

NavigationControllerImpl::LoadURL()--->LoadURLWithParams()

--->NavigationControllerImpl::LoadEntry(NavigationEntryImpl* entry)

--->NavigationControllerImpl::NavigateToPendingEntry()

--->NavigationControllerDelegate::NavigateToPendingEntry()

NavigationControllerDelegate是一个虚基类,它的主要作用是Interface for objects embedding a NavigationController to provide the functionality NavigationController needs.

WebContentsImpl实现了NavigationControllerDelegate

--->WebContentsImpl::NavigateToPendingEntry()

--->NavigatorImpl.NavigateToPendingEntry() //30内核没有这个调用

--->NavigatorImpl::NavigateToEntry() //30内核没有这个调用

--->RenderViewHostImpl::Navigate(navigate_params)

以上过程发生在Application --> Android_webview-->content如下图图2所示。

图2 LoadUrlcontent中流程

RenderViewHostImpl通过IPCRenderViewImpl发送异步IPC加载消息:Send(new FrameMsg_Navigate(routing_id_, params))RenderViewImpl接收到IPC消息后,进行处理

RenderViewImpl::OnNavigate(),在这里把url以及其他所有信息打包到一个WebURLRequest中,调用Blink中的WebFrame至此,LoadUrl已经走到Blink了,开始发起网络请求loadRequest(request);

WebFrameWebFrameImpl的基类,

WebFrame只是提供了简单的树节点之间的操作,其他大部分功能都是由WebFrameImpl实现。WebFrame的各类关系如下图图3所示。

 

图3 WebFrame以及子类

WebFrameImplloadRequest中,request会被进一步封装成FrameLoadRequest,然后进入到FrameLoaderloadFrameLoadRequest)中,

--->FrameLoader::loadWithNavigationAction在该方法中,创建了DocumentLoader

 m_policyDocumentLoader = m_client->createDocumentLoader(request, substituteData.isValid() ? substituteData : defaultSubstituteDataForURL(request.url()));

且该对象从m_policyDocumentLoader变为m_provisionalDocumentLoader m_provisionalDocumentLoader = m_policyDocumentLoader.release();

--->DocumentLoader中调用startLoadingMainResourcem_provisionalDocumentLoader->startLoadingMainResource();

--->ResourceFetecher中调用

m_mainResource = m_fetcher->fetchMainResource(cachedResourceRequest, m_substituteData);

--------------------------------------------------------------------------------//未核实

其中m_mainResourceRawResource

Resource是基类,ResourceFetcher会根据requestresource类型的不同,创建不同类型的资源,resource类型一共有13种,分别为MainResourceImageCSSStyleSheetScriptFontRawSVGDocumentXSLStyleSheetLinkPrefetchLinkSubresourceTextTrackImportResource, Media等,Resource及其部分子类如图4所示。

图4 Resource及其部分子类

继续执行到requestResource(),在这里,首先判断请求的资源在本地cache中是否已存在,然后继续判断是否是reloadload以及revalidate等来决定不同资源加载策略。

因为是load执行会到createResourceForLoading(),继续执行createResource(),创建好resource后,执行resource->load(this, request.options());

这里的resource会根据加载的资源类型创建不同的resource,因为这里是主文档,所以是RawResource,它继承于基类Resource

---->m_loader = ResourceLoader::create(fetcher, this, request, options);

m_loader->start();

---->ResourceLoader::start();

在这里通过m_loader = adoptPtr(blink::Platform::current()->createURLLoader());

创建不同平台的WebURLLoaderWebURLLoader是虚基类。

其实现类是content中的web_url_loader_impl.h

---->WebURLLoaderImpl::loadAsynchronously()

--->WebURLLoaderImpl::Context::Start()

---->ResourceDispatcher::StartAsync( request_info, request_body.get(), this);

在这里会创建IPC消息:

Send(new ResourceHostMsg_RequestResource( request_info.routing_id, request_id, *request));

--->ResourceDispatcherHostImpl::OnMessageReceived()

接收到消息,并继续处理,

--->ResourceDispatcherHostImpl::OnRequestResource

-->BeginRequest()

-->BeginRequestInternal()

-->StartLoading()

--->ResourceLoaderStartRequest()

-->ResourceLoader::StartRequestInternal(),

接着会转到URLRequest中,

--->URLRequest::Start()

 -->URLRequest::StartJob().

接下来的流程就是调用网络库相关函数,进行资源下载等操作。

当接收到网络数据后,首先回调URLRequestFileJob::DidRead(scoped_refptr<IOBuffer> buf, int result) URLRequestFileJobURLRequestJob的子类,URLRequestFileJob会调用父类的

NotifyReadComplete()--->URLRequestJob::NotifyReadComplete(int bytes_read) 去读取数据,然后调用URLRequest::NotifyReadComplete(),

--->ResourceLoader::OnReadCompleted()

---->CompleteRead(bytes_read)

---->LayeredResourceHandler::OnReadCompleted()

---->BufferResourceHandler::OnReadCompleted()

---->AsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer)

然后它会向ResourceDispatcher发送IPC消息

filter->Send(new ResourceMsg_DataReceived(GetRequestID(), data_offset, bytes_read, encoded_data_length));

把获取的数据向内部传送,ResourceDispatcher会继续把数据向内部

传送,通过request_info->peer->OnReceivedData(data_ptr, data_lenght, ecoded_data_length),传送到WebURLLoaderImpl::Context::OnReceivedData();WebURLLoaderImpl::Context

有一个成员变量WebURLLoaderClient* client_,它的实现子类就是ResourceLoaderWebURLLoaderImpl::Context::OnReceivedData()会调用client_->didReceivedData(),至此,数据传到了WebKit内部,ResourceLoader::didReceivedData()会继续调用RawResourceappendData(),在RawResource::appendData()中回调用RawResourceClient::dataReceived(),把数据继续传到了DocumentLoader,接着就开始进行文档解析和DOMTree创建了,具体请看下一篇分析。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
androidwebviewjsalert对话框不能弹出解决办法
Android的webview加载本地html、本apk内html和远程URL
Chromium网页Render Object Tree创建过程分析
webView详解
Android WebView使用实例(html5、文件下载和远程URL)
WebView的用法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服