Chromium网页Render Object Tree创建过程分析.docx
- 文档编号:27665776
- 上传时间:2023-07-03
- 格式:DOCX
- 页数:33
- 大小:111.44KB
Chromium网页Render Object Tree创建过程分析.docx
《Chromium网页Render Object Tree创建过程分析.docx》由会员分享,可在线阅读,更多相关《Chromium网页Render Object Tree创建过程分析.docx(33页珍藏版)》请在冰豆网上搜索。
Chromium网页RenderObjectTree创建过程分析
Chromium网页RenderObjectTree创建过程分析
在前面一文中,我们分析了网页DOMTree的创建过程。
网页DOMTree创建完成之后,WebKit会根据它的内容创建一个RenderObjectTree。
RenderObjectTree是和网页渲染有关的一个Tree。
这意味着只有在DOMTree中需要渲染的节点才会在RenderObjectTree中有对应节点。
本文接下来就分析网页RenderObjectTree的创建过程。
从前面一文可以知道,每一个HTML标签在DOMTree中都有一个对应的HTMLElement节点。
相应地,在DOMTree中每一个需要渲染的HTMLElement节点在RenderObjectTree中都有一个对应的RenderObject节点,如图1所示:
从图1还可以看到,RenderObjectTree创建完成之后,WebKit还会继续根据它的内容创建一个RenderLayerTree和一个GraphicsLayerTree。
本文主要关注RenderObjectTree的创建过程。
从前面一文还可以知道,DOMTree是在网页内容的下载过程中创建的。
一旦网页内容下载完成,DOMTree就创建完成了。
网页的RenderObjectTree与DOMTree不一样,它是在网页内容下载完成之后才开始创建的。
因此,接下来我们就从网页内容下载完成时开始分析网页的RenderObjectTree的创建过程。
从前面一文可以知道,WebKit是通过Browser进程下载网页内容的。
Browser进程一方面通过Net模块中的URLRequest类去Web服务器请求网页内容,另一方面又通过Content模块中的ResourceLoader类的成员函数OnReadCompleted不断地获得URLRequest类请求回来的网页内容,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidResourceLoader:
:
OnReadCompleted(net:
:
URLRequest*unused,intbytes_read){
......
CompleteRead(bytes_read);
......
if(bytes_read>0){
StartReading(true);//Readthenextchunk.
}else{
//URLRequestreportedanEOF.CallResponseCompleted.
DCHECK_EQ(0,bytes_read);
ResponseCompleted();
}
}
这个函数定义在文件external/chromium_org/content/browser/loader/resource_loader.cc中。
参数bytes_read表示当前这次从URLRequest类中读取回来的网页内容的长度。
当这个长度值等于0的时候,就表示所有的网页内容已经读取完毕。
这时候ResourceLoader类的成员函数OnReadCompleted就会调用另外一个成员函数ResponseCompleted进行下一步处理。
ResourceLoader类的成员函数ResponseCompleted的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidResourceLoader:
:
ResponseCompleted(){
......
handler_->OnResponseCompleted(request_->status(),security_info,&defer);
......
}
这个函数定义在文件external/chromium_org/content/browser/loader/resource_loader.cc中。
在前面一文中,我们假设ResourceLoader类的成员变量handler_指向的是一个AsyncResourceHandler对象。
ResourceLoader类的成员函数ResponseCompleted调用这个AsyncResourceHandler对象的成员函数OnResponseCompleted进行下一步处理。
AsyncResourceHandler类的成员函数OnResponseCompleted的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidAsyncResourceHandler:
:
OnResponseCompleted(
constnet:
:
URLRequestStatus&status,
conststd:
:
string&security_info,
bool*defer){
constResourceRequestInfoImpl*info=GetRequestInfo();
......
ResourceMsg_RequestCompleteDatarequest_complete_data;
request_complete_data.error_code=error_code;
request_complete_data.was_ignored_by_handler=was_ignored_by_handler;
request_complete_data.exists_in_cache=request()->response_info().was_cached;
request_complete_data.security_info=security_info;
request_complete_pletion_time=TimeTicks:
:
Now();
request_complete_data.encoded_data_length=
request()->GetTotalReceivedBytes();
info->filter()->Send(
newResourceMsg_RequestComplete(GetRequestID(),request_complete_data));
}
这个函数定义在文件external/chromium_org/content/browser/loader/async_resource_handler.cc中。
AsyncResourceHandler类的成员函数OnResponseCompleted所做的事情是向Render进程发送一个类型为ResourceMsg_RequestComplete的IPC消息,用来通知Render进程它所请求的网页内容已下载完毕。
Render进程是通过ResourceDispatcher类的成员函数DispatchMessage接收类型为ResourceMsg_RequestComplete的IPC消息的,如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidResourceDispatcher:
:
DispatchMessage(constIPC:
:
Message&message){
IPC_BEGIN_MESSAGE_MAP(ResourceDispatcher,message)
......
IPC_MESSAGE_HANDLER(ResourceMsg_RequestComplete,OnRequestComplete)
IPC_END_MESSAGE_MAP()
}
这个函数定义在文件external/chromium_org/content/child/resource_dispatcher.cc中。
从这里可以看到,ResourceDispatcher类的成员函数DispatchMessage将类型为ResourceMsg_RequestComplete的IPC消息分发给另外一个成员函数OnRequestComplete处理。
ResourceDispatcher类的成员函数OnRequestComplete的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidResourceDispatcher:
:
OnRequestComplete(
intrequest_id,
constResourceMsg_RequestCompleteData&request_complete_data){
......
PendingRequestInfo*request_info=GetPendingRequestInfo(request_id);
......
RequestPeer*peer=request_info->peer;
......
peer->OnCompletedRequest(request_complete_data.error_code,
request_complete_data.was_ignored_by_handler,
request_complete_data.exists_in_cache,
request_complete_data.security_info,
renderer_completion_time,
request_complete_data.encoded_data_length);
}
这个函数定义在文件external/chromium_org/content/child/resource_dispatcher.cc中。
从前面一文可以知道,Render进程在请求Browser进程下载指定URL对应的网页内容之前,会创建一个PendingRequestInfo对象。
这个PendingRequestInfo对象以一个RequestID为键值保存在ResourceDispatcher类的内部。
这个RequestID即为参数request_id描述的RequestID。
因此,ResourceDispatcher类的成员函数OnRequestComplete可以通过参数request_id获得一个PendingRequestInfo对象。
有了这个PendingRequestInfo对象之后,ResourceDispatcher类的成员函数OnSetDataBuffer再通过它的成员变量peer获得一个WebURLLoaderImpl:
:
Context对象,并且调用它的成员函数OnCompletedRequest通知它下载网页内容的请求已完成。
WebURLLoaderImpl:
:
Context类的成员函数OnCompletedRequest的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidWebURLLoaderImpl:
:
Context:
:
OnCompletedRequest(
interror_code,
boolwas_ignored_by_handler,
boolstale_copy_in_cache,
conststd:
:
string&security_info,
constbase:
:
TimeTicks&completion_time,
int64total_transfer_size){
......
if(client_){
if(error_code!
=net:
:
OK){
client_->didFail(loader_,CreateError(request_.url(),
stale_copy_in_cache,
error_code));
}else{
client_->didFinishLoading(
loader_,(completion_time-TimeTicks()).InSecondsF(),
total_transfer_size);
}
}
......
}
这个函数定义在文件external/chromium_org/content/child/web_url_loader_impl.cc中。
从前面一文可以知道,WebURLLoaderImpl:
:
Context类的成员变量client_指向的是WebKit模块中的一个ResourceLoader对象。
在成功下载完成网页内容的情况下,WebURLLoaderImpl:
:
Context类的成员函数OnCompletedRequest调用这个ResourceLoader对象的成员函数didFinishLoading通知WebKit结束解析网页内容。
ResourceLoader类的成员函数didFinishLoading的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidResourceLoader:
:
didFinishLoading(blink:
:
WebURLLoader*,doublefinishTime,int64encodedDataLength)
{
......
m_resource->finish(finishTime);
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/fetch/ResourceLoader.cpp中。
ResourceLoader类的成员变量m_resource描述的是一个RawResource对象。
这个RawResource对象的创建过程可以参考前面一文。
ResourceLoader类的成员函数didFinishLoading调用这个RawResource对象的成员函数finish结束加载网页内容。
RawResource类的成员函数finish是从父类Resource继承下来的,它的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidResource:
:
finish(doublefinishTime)
{
......
finishOnePart();
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/fetch/Resource.cpp中。
Resource类的成员函数finish调用另外一个成员函数finishOnePart结束加载网页的内容。
注意Resource类的成员函数finishOnePart的命名。
有前面一文中,我们提到,当网页内容的MIME类型为“multipart/x-mixed-replace”时,下载回来网页内容实际是包含多个部分的,每一个部分都有着自己的MIME类型。
每一个部分下载完成时,都会调用Resource类的成员函数finishOnePart进行处理。
为了统一接口,对于MIME类型不是“multipart/x-mixed-replace”的网页内容而言,下载回来的网页内容也是当作一个部分进行整体处理。
Resource类的成员函数finishOnePart的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidResource:
:
finishOnePart()
{
......
checkNotify();
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/fetch/Resource.cpp中。
Resource类的成员函数finishOnePart调用另外一个成员函数checkNotify通知当前正在前处理的Resource对象的Client,它们所关注的资源,也就是网页内容,已经下载完成了。
Resource类的成员函数checkNotify的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidResource:
:
checkNotify()
{
......
ResourceClientWalker
while(ResourceClient*c=w.next())
c->notifyFinished(this);
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/fetch/Resource.cpp中。
从前面一文可以知道,在Resource类的成员变量m_clients中,保存有一个DocumentLoader对象。
这个DocumentLoader对象是从ResourceClient类继承下来的,它负责创建和加载网页的文档对象。
Resource类的成员函数checkNotify会调用这个DocumentLoader对象的成员函数notifyFinished通知它要加载的网页的内容已经下载完成了。
DocumentLoader类的成员函数notifyFinished的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidDocumentLoader:
:
notifyFinished(Resource*resource)
{
......
if(!
m_mainResource->errorOccurred()&&!
m_mainResource->wasCanceled()){
finishedLoading(m_mainResource->loadFinishTime());
return;
}
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/loader/DocumentLoader.cpp中。
DocumentLoader类的成员变量m_mainResource指向的是一个RawResource对象。
这个RawResource对象和前面分析的ResourceLoader类的成员变量m_resource指向的是同一个RawResource对象。
这个RawResource对象代表正在请求下载的网页内容。
在网页内容成功下载完成的情况下,DocumentLoader类的成员函数notifyFinished就会调用另外一个成员函数finishedLoading进行结束处理。
DocumentLoader类的成员函数finishedLoading的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidDocumentLoader:
:
finishedLoading(doublefinishTime)
{
......
endWriting(m_writer.get());
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/loader/DocumentLoader.cpp中。
从前面一文可以知道,DocumentLoader类的成员变量m_writer指向的是一个DocumentWriter对象。
DocumentLoader类的成员函数finishedLoading调用另外一个成员函数endWriting告诉这个DocumentWriter对象结束对正在加载的网页内容的解析。
DocumentLoader类的成员函数endWriting的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidDocumentLoader:
:
endWriting(DocumentWriter*writer)
{
......
m_writer->end();
.....
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/loader/DocumentLoader.cpp中。
DocumentLoader类的成员函数endWriting调用上述DocumentWriter对象的成员函数end结束对正在加载的网页内容的解析。
DocumentWriter类的成员函数end的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidDocumentWriter:
:
end()
{
......
m_parser->finish();
......
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/loader/DocumentWriter.cpp中。
从前面一文可以知道,DocumentWriter类的成员变量m_parser指向的是一个HTMLDocumentParser对象。
DocumentWriter类的成员函数end调用这个HTMLDocumentParser对象的成员函数finish结束对正在加载的网页内容的解析。
HTMLDocumentParser类的成员函数finish的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
voidHTMLDocumentParser:
:
finish()
{
......
attemptToEnd();
}
这个函数定义在文件external/chromium_org/third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp中。
HTMLDocumentParser类的成员函数finish调用另外一个成员函数attemptToEnd结束对正在加载的网页内容的解析。
HTMLDocumentParser类的成员函数attemptToEnd的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
v
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Chromium网页Render Object Tree创建过程分析 Chromium 网页 Render Tree 创建 过程 分析