chromium+blink网页加载流程

内容目录

1 加载网页的大致过程 1

2 加载网页详细过程 1

2.1.Browser准备加载 1

2.2.Render准备加载 2

2.3.browser的实际加载工作 3

2.3.1 browser开始加载request 3

2.3.2 http层的工作 3

2.3.2.1 收到responseheader 4

2.3.2.2 收到responsebody 4

2.4.Render对接收到的数据的处理 4

2.4.1 ResourceMsg_SetDataBuffer的处理 4

2.4.2 ResourceMsg_DataReceived的处理 5

2.4.3 ResourceMsg_RequestComplete的处理 5



1 加载网页的大致过程

加载网页是render,browser共同参与的过程。

  1. 用户提交一个加载申请,首先到达browser里,browser会做一些准备工作,生成navigationentry,浏览历史数据。

  2. 然后browser会通知render要加载的网页。Render创建对应的renderviewFrameLoader,DocumentLoader等,render处理完毕后,会把真正的网络加载工作交给browser完成。

  3. browserio线程负责从网络发送读取数据,数据通过sharedmem的方式发送给render.

  4. render接受倒数据后,解析处理。

2 加载网页详细过程

2.1.Browser准备加载

Webview.loadUrl

->WebViewChromium.loadUrl(glue)

->AwContents.loadUrl()(android_webview)

->ContentViewCore::loadUrl()content/browser下)

->nativeLoadUrl()

-----------native 界限---------------

->ContentViewCoreImpl::LoadUrl(),content模块

->NavigationControllerImpl::LoadURLWithParams()

->NavigationControllerImpl::LoadEntry()

->NavigationControllerImpl::NavigateToPendingEntry()

->WebContentsImpl::NavigateToPendingEntry()

->NavigatorImpl::NavigateToEntry()

通过RenderFrameHostManager创建一个RenderFrameHostImpl,

然后通知observersAboutToNavigateRenderView

然后调用RenderFrameHostImpl.Navigate()

然后通知observers:NavigateToPendingEntry().



其中,RenderFrameHostImpl.Navigate()调用:

->Send(newFrameMsg_Navigate(routing_id_, params)),发送messagerender.

2.2.Render准备加载

Render:

RenderViewImpl::OnMessageReceivedrender线程

->RenderFrameImpl::OnNavigate

更新renderViewhistorypage ids.

判断是否是reload,或者backforward, 还是新的加载。如果新的加载:

->WebLocalFrameImpl::loadRequest(constWebURLRequest& request) webkit层)

->FrameLoader::load(FrameLoadRequest&passedRequest)

->FrameLoader::loadWithNavigationAction

这里涉及到Policydocumentloader, provisional documentloader. 基本上先创建一个policydocument loader. 然后判断该request是否需要继续,如果不继续,那么此次navigation停止。不继续的例子比如shell拦截处理了本次navigation,不需要内核加载网址,如果继续就会切换到provisionaldocument loader.

->DocumentLoader::startLoadingMainResource()

->ResourceFetcher::fetchMainResource()

->ResourceFetcher::requestResource()

这里会检查该request是否已经在memcache里如果在,会尝试使用memcache里的数据。否则会继续加载。Cache里面的数据可能需要revalidate,比如需要把last-modified,etagheader信息提取出来,生成httprequest发送给server检查是否有更新。

->Resource::load()

->createresourceLoader然后ResourceLoader::start()

创建WebURLLoader.

->WebURLLoaderImpl::loadAsynchronously()(进入content)

->WebURLLoaderImpl::Context::Start(),整理requestinfo, load_flags, request body.

->IPCResourceLoaderBridge::Start()这个bridge就是resourceloaderbridge.定义在resource_dispatcher.cc.生成requestid, 并发送request消息给browser.

->ResoureDispatcher::message_sender()->send(ResourceHostMsg_RequestResource),message_sender()得到一个IPC::Sender对象。发送ResourceHostMsg_RequestResource消息

2.3.browser的实际加载工作

2.3.1 browser开始加载request

Browser

content/browser/loader模块

->ResourceDispatcherHostImpl::OnMessageReceived()

->ResourceDispatcherHostImpl::OnRequestResource()

->ResourceDispatcherHostImpl::BeginRequest()

->ResourceDispatcherHostImpl::BeginRequestInternal()

创建ResourceLoader,并启动加载。会创建AsyncResourceHandler,并传入ResourceLoader里。

->ResourceDispatcherHostImpl::StartLoading()

->ResourceLoader::StartRequest()

通知handler.onWillStart().这里会通知到所有的resourcethrottle, 也就是一些用来intercept资源加载的callback.比如InterceptNavigationResourceThrottle就是一种。可以用来拦截加载请求。可以处理第三方协议。

->ResourceLoader::StartRequestInternal()

->URLRequest::Start()net层)

先通过URLRequestJobManagerURLRequestJobFactory创建URLRequestJob.job依赖于协议,比如URLRequestHttpJob,是被URLRequestHttpJob::Factory()函数创建的,URLRequestHttpJob::Factorybuitin的创建requestjobfactory.Builtinfactory支持httphttps.

->URLRequest::StartJob(URLRequestJob*job),

->URLRequestHttpJob::Start()

设置request_info的值,搜集headers内容。

->URLRequestHttpJob::DoStartTransaction(),调用此函数前,如果需要,会异步加载cookie,并设置到header里。

->URLRequestHttpJob::StartTransactionInternal()

创建HttpCache::Transaction.并启动

2.3.2 http层的工作

->net::HttpCache::Transaction::start()net/http协议层)

URLRequestHttpJob::OnStartCompleted作为一个callback传入这个transaction.当底层数据到达后,会调用该callback.

->DoLoop().

状态机,底层还会创建HttpNetworkTransaction来从网络加载数据。如果cache里面已有数据就会使用cache里面的数据。这个模块已经是http协议层内容。该DoLoop大部分操作支持异步和同步,比如如果一个操作同步完成,就会继续loop到下一步,如果没有完成,会返回到上层调用者,当异步操作完成后,callback又会调用到DoLoop从而推动状态机前进。


涉及到的工作大体上包含:

创建本地cacheentry. 用来保存response数据到文件系统。

发送request,

接受response,解析responseheaders, meta data,并保存到cacheentry.

接受responsebody.


一些socket通讯,文件存取的操作在io线程,或者worker线程异步完成。

期间的一些关键节点,比如收到response,都会通知到上层:

2.3.2.1 收到responseheader

URLRequestHttpJob::OnStartCompleted

保存cookie,并通知上层:

->URLRequestJob::NotifyHeadersComplete

->URLRequest::NotifyResponseStarted()

->ResourceLoader::OnResponseStarted()

这里会执行security检查,比如根据是否允许加载不同hosturl.否则cancel本次浏览。这是可以配置的。

->ResourceLoader::StartReading()

读取更多responsebody数据。

->ResourceLoader::ReadMore

->URLRequest::Read

->URLRequestHttpJob::ReadRawData

让底层的transaction开始读取数据,异步完成后,调用callback:URLRequestHttpJob::OnReadCompleted

->HttpCache::Transaction::Read


2.3.2.2 收到responsebody

URLRequestHttpJob::OnReadCompleted

->URLRequest::NotifyReadCompleted

->ResourceLoader::OnReadCompleted()

先把数据发送给render,然后检查是否所有数据都接受完毕.

->ResourceLoader::CompleteRead

->BufferedResourceHandler::OnReadCompleted

->AsyncResourceHandler::OnReadCompleted

把数据共享给render,由于原本chrome是多进程的,所以使用的是sharedmem方式来共享资源.使用三个消息

  • ResourceMsg_SetDataBuffer消息

  • ResourceMsg_DataReceived消息

  • ResourceMsg_RequestComplete消息

如果第一次收到数据,sharedmemhandle告知render,使其知道哪里取数据.使用ResourceMsg_SetDataBuffer.

告诉render新来的数据的偏移和大小.使用ResourceMsg_DataReceived.

如果ResourceLoader::OnReadCompleted发现所有数据接受完毕:

->ResourceLoader::ResponseCompleted()

->AsyncResourceHandler::OnResponseCompleted

render发消息:ResourceMsg_RequestComplete告知接受完毕.

2.4.Render对接收到的数据的处理

2.4.1 ResourceMsg_SetDataBuffer的处理

ResourceDispatcher::OnSetDataBuffer()

根据sharedmem的句柄,映射指定大小的sharedmem.

使用mmap系统调用。

2.4.2 ResourceMsg_DataReceived的处理

ResourceDispatcher::OnReceivedData()

通知上层,并回复browser一个ack消息。

->WebURLLoaderImpl::Context::OnReceivedData

->ResourceLoader::didReceiveData()

->RawResource::appendData

保存数据到memcache里,然后通知resourceClient来数据了:

->DocumentLoader::dataReceived

->DocumentLoader::commitData

->DocumentWriter::addData

->HTMLDocumentParser::appendBytes

startBackgroundParser(),新起一个线程执行数据的解码,

后台执行:BackgroundHTMLParser::appendRawBytesFromParserThread,解码数据后返还给主线程:HTMLDocumentParser::didReceiveEncodingDataFromBackgroundParser

此外,还会靠BackgroundHTMLParser::pumpTokenizer把数据解析成token,发送给主线程:HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser().

->HTMLDocumentParser::pumpPendingSpeculations

->HTMLDocumentParser::processParsedChunkFromBackgroundParser(

处理收到的token,构造domtree,

->constructTreeFromCompactHTMLToken(

2.4.3 ResourceMsg_RequestComplete的处理

ResourceDispatcher::OnRequestComplete

->WebURLLoaderImpl::Context::OnCompletedRequest

->ResourceLoader::didFinishLoading

->Resource::finish

->DocumentLoader::finishedLoading

->FrameLoader::checkLoadComplete




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值