Chromium网页URL加载过程分析资料.docx
- 文档编号:26943023
- 上传时间:2023-06-24
- 格式:DOCX
- 页数:47
- 大小:46.89KB
Chromium网页URL加载过程分析资料.docx
《Chromium网页URL加载过程分析资料.docx》由会员分享,可在线阅读,更多相关《Chromium网页URL加载过程分析资料.docx(47页珍藏版)》请在冰豆网上搜索。
Chromium网页URL加载过程分析资料
Chromium网页URL加载过程分析
Chromium在Browser进程中为网页创建了一个FrameTree之后,会将网页的URL发送给Render进程进行加载。
Render进程接收到网页URL加载请求之后,会做一些必要的初始化工作,然后请求Browser进程下载网页的内容。
Browser进程一边下载网页内容,一边又通过共享内存将网页内容传递给Render进程解析,也就是创建DOMTree。
本文接下来就分析网页URL的加载过程。
Render进程之所以要请求Browser进程下载网页的内容,是因为Render进程没有网络访问权限。
出于安全考虑,Chromium将Render进程启动在一个受限环境中,使得Render进程没有网络访问权限。
那为什么不是Browser进程主动下载好网页内容再交给Render进程解析呢?
这是因为Render进程是通过WebKit加载网页URL的,WebKit不关心自己所在的进程是否有网络访问权限,它通过特定的接口访问网络。
这个特定接口由WebKit的使用者,也就是Render进程中的Content模块实现。
Content模块在实现这个接口的时候,会通过IPC请求Browser进程下载网络的内容。
这种设计方式使得WebKit可以灵活地使用:
既可以在有网络访问权限的进程中使用,也可以在没有网络访问权限的进程中使用,并且使用方式是统一的。
从前面一文可以知道,Browser进程中为要加载的网页创建了一个FrameTree之后,会向Render进程发送一个类型为FrameMsg_Navigate的IPC消息。
Render进程接收到这个IPC消息之后,处理流程如图1所示:
Render进程执行了一些初始化工作之后,就向Browser进程发送一个类型为ResourceHostMsg_RequestResource的IPC消息。
Browser进程收到这个IPC消息之后,就会通过HTTP协议请求Web服务器将网页的内容返回来。
请求得到响应后,Browser进程就会创建一块共享内存,并且通过一个类型为ResourceMsg_SetDataBuffer的IPC消息将这块共享内存传递给Render进程的。
以后每当下载到新的网页内容,Browser进程就会将它们写入到前面创建的共享内存中去,并且发送Render进程发送一个类型为ResourceMsg_DataReceived的IPC消息。
Render进程接收到这个IPC消息之后,就会从共享内存中读出Browser进程写入的内容,并且进行解析,也就是创建一个DOMTree。
这个过程一直持续到网页内容下载完成为止。
接下来,我们就从Render进程接收类型为FrameMsg_Navigate的IPC消息开始分析网页URL的加载过程。
Render进程是通过RenderFrameImpl类的成员函数OnMessageReceived接收类型为FrameMsg_Navigate的IPC消息的,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
boolRenderFrameImpl:
:
OnMessageReceived(constIPC:
:
Message&msg){
......
boolhandled=true;
IPC_BEGIN_MESSAGE_MAP(RenderFrameImpl,msg)
IPC_MESSAGE_HANDLER(FrameMsg_Navigate,OnNavigate)
......
IPC_END_MESSAGE_MAP()
returnhandled;
}
这个函数定义在文件external/chromium_org/content/renderer/render_frame_impl.cc中。
RenderFrameImpl类的成员函数OnMessageReceived将类型为FrameMsg_Navigate的IPC消息分发给另外一个成员函数OnNavigate处理,后者的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidRenderFrameImpl:
:
OnNavigate(constFrameMsg_Navigate_Params¶ms){
......
boolis_reload=RenderViewImpl:
:
IsReload(params);
......
WebFrame*frame=frame_;
......
if(is_reload){
......
}elseif(params.page_state.IsValid()){
......
}elseif(!
params.base_url_for_data_url.is_empty()){
......
}else{
//NavigatetothegivenURL.
WebURLRequestrequest(params.url);
......
frame->loadRequest(request);
......
}
......
}
这个函数定义在文件external/chromium_org/content/renderer/render_frame_impl.cc中。
从前面一文可以知道,RenderFrameImpl类的成员变量frame_指向的是一个WebLocalFrameImpl对象。
如果当前正在处理的RenderFrameImpl对象还没有加载过URL,并且当前要加载的URL不为空,RenderFrameImpl类的成员函数OnNavigate会调用成员变量frame_指向的WebLocalFrameImpl对象的成员函数loadRequest加载指定的URL。
WebLocalFrameImpl类的成员函数loadRequest的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidWebLocalFrameImpl:
:
loadRequest(constWebURLRequest&request)
{
......
constResourceRequest&resourceRequest=request.toResourceRequest();
if(resourceRequest.url().protocolIs("javascript")){
loadJavaScriptURL(resourceRequest.url());
return;
}
frame()->loader().load(FrameLoadRequest(0,resourceRequest));
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/web/WebLocalFrameImpl.cpp中。
如果参数request描述的URL指定的协议是"JavaScript",那么表示要加载的是一段JavaScript。
这时候WebLocalFrameImpl类的成员函数loadRequest会调用另外一个成员函数loadJavaScriptURL加载这段JavaScript。
在其它情况下,WebLocalFrameImpl类的成员函数loadRequest首先调用成员函数frame获得成员变量m_frame描述的一个LocalFrame对象,接着又调用这个LocalFrame对象的成员函数loader获得其成员变量m_loader描述的一个FrameLoader对象。
有了这个FrameLoader对象之后,就调用它的成员函数load加载参数request描述的URL。
WebLocalFrameImpl类的成员变量m_frame描述的LocalFrame对象和LocalFrame类的成员变量m_loader描述的FrameLoader对象的创建过程,可以参考前面一文。
接下来我们继续分析FrameLoader类的成员函数load的实现,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidFrameLoader:
:
load(constFrameLoadRequest&passedRequest)
{
......
FrameLoadRequestrequest(passedRequest);
......
FrameLoadTypenewLoadType=determineFrameLoadType(request);
NavigationActionaction(request.resourceRequest(),newLoadType,request.formState(),request.triggeringEvent());
......
loadWithNavigationAction(action,newLoadType,request.formState(),request.substituteData(),request.clientRedirect());
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/loader/FrameLoader.cpp中。
FrameLoader类的成员函数load主要是调用另外一个成员函数loadWithNavigationAction加载参数passedRequest描述的URL。
FrameLoader类的成员函数loadWithNavigationAction的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidFrameLoader:
:
loadWithNavigationAction(constNavigationAction&action,FrameLoadTypetype,PassRefPtrWillBeRawPtr
{
......
constResourceRequest&request=action.resourceRequest();
......
m_policyDocumentLoader=client()->createDocumentLoader(m_frame,request,substituteData.isValid()?
substituteData:
defaultSubstituteDataForURL(request.url()));
......
m_provisionalDocumentLoader=m_policyDocumentLoader.release();
......
m_provisionalDocumentLoader->startLoadingMainResource();
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/loader/FrameLoader.cpp中。
FrameLoader类的成员函数loadWithNavigationAction首先调用成员函数client获得一个FrameLoaderClientImpl对象,接着再调用这个FrameLoaderClientImpl对象的成员函数createDocumentLoader为参数action描述的URL创建了一个WebDataSourceImpl对象,并且保存在成员变量m_policyDocumentLoader中。
关于FrameLoader类的成员函数client和FrameLoaderClientImpl类的成员函数createDocumentLoader的实现,可以参考前面一文。
FrameLoader类的成员函数loadWithNavigationAction接下来又将成员变量m_policyDocumentLoader描述的WebDataSourceImpl对象转移到另外一个成员变量m_provisionalDocumentLoader中,最后调用这个WebDataSourceImpl对象的成员函数startLoadingMainResource加载参数action描述的URL。
WebDataSourceImpl类的成员函数startLoadingMainResource是从父类DocumentLoader继承下来的,它的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidDocumentLoader:
:
startLoadingMainResource()
{
......
FetchRequestcachedResourceRequest(request,FetchInitiatorTypeNames:
:
document,mainResourceLoadOptions);
m_mainResource=m_fetcher->fetchMainResource(cachedResourceRequest,m_substituteData);
......
m_mainResource->addClient(this);
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/loader/DocumentLoader.cpp中。
从前面一文可以知道,DocumentLoader类的成员变量m_fetcher描述的是一个ResourceFetcher对象,DocumentLoader类的成员函数startLoadingMainResource调用这个ResourceFetcher对象的成员函数fetchMainResource请求加载本地变量cachedResourceRequest描述的资源。
这个资源描述的即为上一步指定要加载的URL。
ResourceFetcher类的成员函数fetchMainResource执行结束后,会返回一个RawResource对象。
这个RawResource对象保存在WebDataSourceImpl类的成员变量m_mainResource中。
这个RawResource对象描述的是一个异步加载的资源,DocumentLoader类的成员startLoadingMainResource调用它的成员函数addClient将当前正在处理的DocumentLoader对象添加到它的内部去,用来获得异步加载的资源数据,也就是本地变量cachedResourceRequest描述的URL对应的网页内容。
RawResource类的成员函数addClient是从父类Resource继承下来的,它的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidResource:
:
addClient(ResourceClient*client)
{
if(addClientToSet(client))
didAddClient(client);
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/fetch/Resource.cpp中。
Resource类的成员函数addClient调用另外一个成员函数addClientToSet将参数client描述的一个DocumentLoader对象保存在内部,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
boolResource:
:
addClientToSet(ResourceClient*client)
{
......
m_clients.add(client);
returntrue;
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/fetch/Resource.cpp中。
Resource类的成员函数addClientToSet将参数client描述的一个DocumentLoader保存在成员变量m_clients描述的一个HashSet中,以便当前正在处理的Resource对象描述的网页内容从Web服务器下载回来的时候,可以交给它处理。
接下来我们继续分析WebDataSourceImpl类的成员函数startLoadingMainResource调用成员变量m_fetcher描述的ResourceFetcher对象的成员函数fetchMainResource加载本地变量cachedResourceRequest描述的URL的过程,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
ResourcePtr
:
fetchMainResource(FetchRequest&request,constSubstituteData&substituteData)
{
......
returntoRawResource(requestResource(Resource:
:
MainResource,request));
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp中。
ResourceFetcher类的成员函数fetchMainResource调用另外一个成员函数requestResource加载参数request描述的URL。
ResourceFetcher类的成员函数requestResource会返回一个RawResource对象给调用者,即ResourceFetcher类的成员函数fetchMainResource。
后者又会将这个RawResource对象返回给它的调用者。
ResourceFetcher类的成员函数requestResource的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
ResourcePtr
:
requestResource(Resource:
:
Typetype,FetchRequest&request)
{
......
KURLurl=request.resourceRequest().url();
......
constRevalidationPolicypolicy=determineRevalidationPolicy(type,request.mutableResourceRequest(),request.forPreload(),resource.get(),request.defer(),request.options());
switch(policy){
......
caseLoad:
resource=createResourceForLoading(type,request,request.charset());
break;
.....
}
......
if(resourceNeedsLoad(resource.get(),request,policy)){
......
if(!
m_documentLoader||!
m_documentLoader->scheduleArchiveLoad(resource.get(),request.resourceRequest()))
resource->load(this,request.options());
......
}
......
returnresource;
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp中。
ResourceFetcher类的成员函数requestResource首先调用成员函数createResourceForLoading为参数request描述的URL创建一个RawResource对象,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
ResourcePtr
:
createResourceForLoading(Resource:
:
Typetype,FetchRequest&request,constString&charset)
{
......
ResourcePtr
......
returnresource;
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp中。
ResourceFetcher类的成员函数createResourceForLoading调用函数createResource根据参数type和request创建一个RawResource对象,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
staticResource*createResource(Resource:
:
Typetype,constResourceRequest&request,constString&charse
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Chromium 网页 URL 加载 过程 分析 资料