内容目录
2.4.1 ResourceMsg_SetDataBuffer的处理 4
2.4.2 ResourceMsg_DataReceived的处理 5
2.4.3 ResourceMsg_RequestComplete的处理 5
1 加载网页的大致过程
加载网页是render,browser共同参与的过程。
-
用户提交一个加载申请,首先到达browser里,browser会做一些准备工作,生成navigationentry,浏览历史数据。
-
然后browser会通知render要加载的网页。Render创建对应的renderview,FrameLoader,DocumentLoader等,render处理完毕后,会把真正的网络加载工作交给browser完成。
-
browser的io线程负责从网络发送读取数据,数据通过sharedmem的方式发送给render.
-
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,
然后通知observers:AboutToNavigateRenderView
然后调用RenderFrameHostImpl.Navigate()
然后通知observers:NavigateToPendingEntry().
其中,RenderFrameHostImpl.Navigate()调用:
->Send(newFrameMsg_Navigate(routing_id_, params)),发送message给render.
2.2.Render准备加载
Render:
RenderViewImpl::OnMessageReceived,render线程
->RenderFrameImpl::OnNavigate
更新renderView的historypage 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,etag等header信息提取出来,生成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层)
先通过URLRequestJobManager和URLRequestJobFactory创建URLRequestJob.job依赖于协议,比如URLRequestHttpJob,是被URLRequestHttpJob::Factory()函数创建的,URLRequestHttpJob::Factory是buitin的创建requestjob的factory.Builtin的factory支持http和https.
->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检查,比如根据是否允许加载不同host的url.否则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消息
如果第一次收到数据,把sharedmem的handle告知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