Chromium网页Frame Tree创建过程分析Word文档格式.docx
- 文档编号:21530248
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:58
- 大小:123.68KB
Chromium网页Frame Tree创建过程分析Word文档格式.docx
《Chromium网页Frame Tree创建过程分析Word文档格式.docx》由会员分享,可在线阅读,更多相关《Chromium网页Frame Tree创建过程分析Word文档格式.docx(58页珍藏版)》请在冰豆网上搜索。
关于Chromium的BrowsingInstance,可以参考官方文档:
ProcessModels,它对应于HTML5规范中的BrowsingContext。
我们观察代表网页B的子Node,它关联有一个RenderFrameHost对象和三个RenderFrameProxyHost对象。
其中,RenderFrameHost对象描述的是网页B本身,另外三个RenderFrameProxyHosts对象描述的是网页A、C和D。
表示网页B可以通过JavaScript接口window.postMessage向网页A、C和D发送消息。
假设图1所示的网页A、B、C和D分别在不同的Render进程中渲染,如图3所示:
在负责加载和渲染网页B的Render进程中,有一个RenderFrame对象,代表图1所示的网页B。
负责加载和渲染网页B的Render进程还包含有五个RenderFrameProxy对象,分别代表图1所示的两个网页A实例、两个网页C实例和一个网页D实例。
在负责渲染网页A、C和D的Render进程中,也有类似的RenderFrame对象和RenderFrameProxy对象。
Browser进程的RenderFrameHost对象和Render进程的RenderFrame对象是一一对应的。
同样,Browser进程的RenderFrameHostProxy对象和Render进程的RenderFrameProxy对象也是一一对应的。
RenderFrame对象和RenderFrameProxy对象的存在,使得在同一个BrowsingInstance或者BrowsingContext中的网页可以通过Javascript接口window.postMessage相互发送消息。
例如,当网页B要向网页A发送消息时,负责加载和渲染网页B的Render进程就会在当前进程中找到与网页B对应的RenderFrame对象,以及与网页A对应的RenderFrameProxy对象,然后将要发送的消息从找到的RenderFrame对象传递给找到的RenderFrameProxy对象即可。
与网页A对应RenderFrameProxy对象接收到消息之后,会进一步将该消息发送给负责加载和渲染网页A的Render进程处理,从而完成消息的发送和处理过程。
接下来,我们就结合源码分析Chromium为网页创建FrameTree的过程,这个过程涉及到WebContents、RenderFrameHost和RenderFrame等重要对象的创建。
前面提到,FrameTree是在Browser进程中创建的,并且与一个WebContents对象关联。
从前面一文可以知道,WebContents是Chromium的Content模块提供的一个高级接口,通过这个接口可以将一个网页渲染在一个可视区域中。
我们可以认为,一个WebContents对象就是用来实现一个网页的加载、解析、渲染和导航等功能的。
FrameTree是在与其关联的WebContents对象的创建过程中创建的,因此接下来我们就从WebContents对象的创建过程开始分析FrameTree的创建过程。
以一文提到的ShellAPK为例,它会为每一个要加载的网页在Native层创建一个Shell。
在创建这个Shell的过程中,就会同时创建一个WebContents对象。
从前面一文可以知道,ShellAPK是通过调用Native层的Shell类的静态成员函数CreateNewWindow为要加载的网页创建一个Shell的,它的实现如下所示:
[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片
Shell*Shell:
:
CreateNewWindow(BrowserContext*browser_context,
constGURL&
url,
SiteInstance*site_instance,
introuting_id,
constgfx:
Size&
initial_size){
WebContents:
CreateParamscreate_params(browser_context,site_instance);
create_params.routing_id=routing_id;
create_params.initial_size=AdjustWindowSize(initial_size);
WebContents*web_contents=WebContents:
Create(create_params);
Shell*shell=CreateShell(web_contents,create_params.initial_size);
......
returnshell;
}
这个函数定义在文件external/chromium_org/content/shell/browser/shell.cc中。
Shell类的静态成员函数CreateNewWindow首先是调用WebContents类的静态成员函数Create创建一个WebContentsImpl对象,接着再调用Shell类的静态成员函数CreateShell根据前面创建的WebContentsImpl对象创建一个Shell对象,并且返回给调用者。
接下来,我们先分析WebContents类的静态成员函数Create的实现,接着再分析Shell类的静态成员函数CreateShell的实现。
WebContents类的静态成员函数Create的实现如下所示:
WebContents*WebContents:
Create(constWebContents:
CreateParams&
params){
returnWebContentsImpl:
CreateWithOpener(
params,static_cast<
WebContentsImpl*>
(params.opener));
这个函数定义在文件external/chromium_org/content/browser/web_contents/web_contents_impl.cc中。
WebContents类的静态成员函数Create调用另外一个静态成员函数CreateWithOpener创建一个WebContentsImpl对象,并且返回给调用者。
WebContents类的静态成员函数CreateWithOpener的实现如下所示:
WebContentsImpl*WebContentsImpl:
constWebContents:
params,
WebContentsImpl*opener){
WebContentsImpl*new_contents=newWebContentsImpl(
params.browser_context,params.opener_suppressed?
NULL:
opener);
new_contents->
Init(params);
returnnew_contents;
WebContents类的静态成员函数CreateWithOpener首先是创建一个WebContentsImpl对象。
在将这个WebContentsImpl对象返回给调用者之前,会先调用它的成员函数Init对它进行初始化。
接下来,我们先分析WebContentsImpl对象的创建过程,即WebContentsImpl类的构造函数的实现,接下来再分析WebContentsImpl对象的初始化过程,即WebContentsImpl类的成员函数Init的实现。
WebContentsImpl类的构造函数的实现如下所示:
WebContentsImpl:
WebContentsImpl(
BrowserContext*browser_context,
WebContentsImpl*opener)
:
......,
controller_(this,browser_context),
frame_tree_(newNavigatorImpl(&
controller_,this),
this,this,this,this),
......{
WebContentsImpl类的成员变量controller_描述的是一个NavigationControllerImpl对象。
后面我们可以看到,这个NavigationControllerImpl对象负责执行加载URL的操作。
现在我们分析它的创建过程,如下所示:
NavigationControllerImpl:
NavigationControllerImpl(
NavigationControllerDelegate*delegate,
BrowserContext*browser_context)
delegate_(delegate),
这个函数定义在文件external/chromium_org/content/browser/frame_host/navigation_controller_impl.cc中。
从前面的调用过程可以知道,参数delegate指向的是一个WebContentsImpl对象。
这个WebContentsImpl对象保存在NavigationControllerImpl类的成员变量delegate_中。
回到WebContentsImpl类的构造函数中,它构造了一个NavigationControllerImpl对象之后,接下来又根据该NavigationControllerImpl对象创建一个NavigatorImpl对象。
这个NavigatorImpl对象也是在加载URL时使用到的,它的创建过程如下所示:
NavigatorImpl:
NavigatorImpl(
NavigationControllerImpl*navigation_controller,
NavigatorDelegate*delegate)
controller_(navigation_controller),
delegate_(delegate){
这个函数定义在文件external/chromium_org/content/browser/frame_host/navigator_impl.cc
从前面的调用过程可以知道,参数navigation_controller和delegate指向的分别是一个NavigationControllerImpl对象和一个WebContentsImpl对象,它们分别保存在NavigatorImpl类的成员变量controller_和delegate_中。
再回到WebContentsImpl类的构造函数中,它创建了一个NavigatorImpl对象之后,又根据该NavigatorImpl对象创建一个FrameTree对象,并且保存在成员变量frame_tree_中。
这个FrameTree对象描述的就是一个FrameTree。
接下来我们继续分析FrameTree对象的创建过程,也就是FrameTree类的构造函数的实现,如下所示:
FrameTree:
FrameTree(Navigator*navigator,
RenderFrameHostDelegate*render_frame_delegate,
RenderViewHostDelegate*render_view_delegate,
RenderWidgetHostDelegate*render_widget_delegate,
RenderFrameHostManager:
Delegate*manager_delegate)
render_frame_delegate_(render_frame_delegate),
render_view_delegate_(render_view_delegate),
render_widget_delegate_(render_widget_delegate),
manager_delegate_(manager_delegate),
root_(newFrameTreeNode(this,
navigator,
render_frame_delegate,
render_view_delegate,
render_widget_delegate,
manager_delegate,
std:
string())),
这个函数定义在文件external/chromium_org/content/browser/frame_host/frame_tree.cc中。
从前面的调用过程可以知道,参数navigator指向的是一个NavigatorImpl对象,其余四个参数指向的是同一个WebContentsImpl对象,分别被保存在FrameTree类的成员变量render_frame_delegate_、render_view_delegate_、render_widget_delegate_和manager_delegate_中。
FrameTree类的构造函数接下来做的一件事情是创建一个FrameTreeNode对象,并且保存在成员变量root_中,作为当前正在创建的FrameTree的根节点。
这个根节点描述的就是后面要加载的网页。
FrameTreeNode对象的创建过程,即FrameTreeNode类的构造函数的实现,如下所示:
FrameTreeNode:
FrameTreeNode(FrameTree*frame_tree,
Navigator*navigator,
Delegate*manager_delegate,
conststd:
string&
name)
frame_tree_(frame_tree),
navigator_(navigator),
render_manager_(this,
manager_delegate),
......{}
这个函数定义在文件external/chromium_org/content/browser/frame_host/frame_tree_node.cc中。
从前面的调用过程可以知道,参数frame_tree和navigator指向的分别是一个FrameTree对象和一个NavigatorImpl对象,它们分别被保存在FrameTreeNode类的成员变量frame_tree_和navigator_中。
FrameTreeNode类的构造函数接下来做的一件事情是构造一个RenderFrameHostManager对象,并且保存在成员变量render_manager_中。
这个RenderFrameHostManager对象负责管理与当前正在创建的FrameTreeNode对象关联的一个RenderFrameHost对象,它的构造过程如下所示:
RenderFrameHostManager:
RenderFrameHostManager(
FrameTreeNode*frame_tree_node,
Delegate*delegate)
frame_tree_node_(frame_tree_node),
这个函数定义在文件external/chromium_org/content/browser/frame_host/render_frame_host_manager.cc中。
从前面的调用过程可以知道,参数frame_tree_node指向的是一个FrameTreeNode对象,它被保存在RenderFrameHostManager类的成员变量frame_tree_node_中,其余四个参数指向的是同一个WebContentsImpl对象,分别被保存在RenderFrameHostManager类的成员变量delegate_、render_frame_delegate_、render_view_delegate_和render_widget_delegate_中。
这一步执行完成之后,一个FrameTree就创建出来了。
这是一个只有根节点的FrameTree。
根节点描述的网页就是接下来要进行加载的。
根节点描述的网页加载完成之后,就会进行解析。
在解析的过程中,如果碰到iframe标签,那么就会创建另外一个子节点,并且添加到当前正在创建的FrameTree中去。
返回到WebContents类的静态成员函数CreateWithOpener中,它创建了一个WebContentsImpl对象之后,接下来会调用这个WebContentsImpl对象的成员函数Init执行初始化工作,如下所示:
voidWebContentsImpl:
Init(constWebContents:
GetRenderManager()->
Init(
params.browser_context,params.site_instance,params.routing_id,
params.main_frame_routing_id);
if(browser_plugin_guest_){
}else{
//RegularWebContentsView.
view_.reset(CreateWebContentsView(
this,delegate,&
render_view_host_delegate_view_));
}
WebContentsImpl类的成员函数Init首先是调用成员函数
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Chromium网页Frame Tree创建过程分析 Chromium 网页 Frame Tree 创建 过程 分析