【渲染】webkit内部的WebView,page, WebFrame, Frame, document, frameView, RenderView, RenderFrame,Widget的层级关联关系以及构建过程

Render 开始的类名,比如 RenderFrame,RenderWidget,RenderView,RenderThread 都位于content层

Web开始的类名:比如 WebFrame,blink::WebView,WebWidget位于内核的glue层。内部也就是blink,webkit core

blink::WidgetBase, 

对应在browser进程中对应有:`RenderWidgetHost`, `RenderFrameHost` and `RenderViewHost`

 

更多内容: https://blog.csdn.net/csshell2002/category_5801303.html

一定要参考:Chromium网页加载过程简要介绍和学习计划_老罗的Android之旅-CSDN博客 才能更好理解底下几个模块的关系:

 

 

 

这个图来自官方文档:How Chromium Displays Web Pages。从下往上看:

       1. WebKit:网页渲染引擎层,定义在命令空间WebCore中。Port部分用来集成平台相关服务,例如资源加载和绘图服务。WebKit是一个平台无关的网页渲染引擎,但是用在具体的平台上时,需要由平台提供一些平台相关的实现,才能让WebKit跑起来。

       2. WebKit glue:由于chromium有不同的代码风格,类型,相比webkit。glue提供chromium更方便的使用webkit,比如chromium使用std::string,而部署String;GURL而不是KURL。Chromium不直接访问WebKit接口,而是通过WebKit glue接口间接访问。WebKit glue的对象命名有一个特点,均是以Web为前缀。比如WebCore::Frame 变成 WebFrame。定义在命名空间blink中(WebKit glue层和WebKit层统称为Blink模块)。

这样做也避免了webkit的变化影响到chromium的代码。

       3. Renderer/Renderer host:多进程嵌入层,定义在命令空间content中。其中,Renderer运行在Render进程中,Renderer host运行在Browser进程中。

renderer进程嵌入port通过glue接口。它没什么代码,主要是作为连接browser的通道。最重要的类是 RenderView, 位于/content/renderer/render_view_impl.cc. 它表示一个 web page. 处理来自browser的导航命令。它直接或者间接继承自RenderWidget(它提供绘制和输入事件处理)。RenderView主要处理browser进程与render进程的通信.

RenderWidget对应WebCore::Widget,具体通过实现glue层的 WebWidgetDelegate接口来实现。它就是个windows窗口,有绘制内容和处理输入。

RenderView 继承自 RenderWidget,是个tab网页或者弹出框页面. 它除了具有处理绘制和输入事件的widget功能外,还处理导航命令。

唯一例外只有RenderWidget而没有 RenderView,是下拉框,日期框。它需要显示通过本地窗口,覆盖在所有frame之上。它不是一个分离的 "web page" (RenderView)。最新的chromium代码中,将下拉框和日期框分成内部实现和外部实现。在内部实现的情况下,通过写死的html形成一个select模样的网页,最终通过内部创建frame,渲染这个网页,最终在窗口还是网页渲染成下拉框,处理按键输入也是通过网页js处理,形成结果,回传给select html element。。通过webPagePopup来显示。

browser进程:

RenderProcessHost 在main thread(UI thread)被创建时,它创建一个新的renderer 进程和一个IPC channel到renderer。它监听消息转发到UI线程。ResourceMessageFilter 过滤出特定消息能直接在IO线程中处理的,比如network请求。过滤发生在ResourceMessageFilter::OnMessageReceived。在UI线程的可视化消息被RenderProcessHost::OnMessageReceived分发到合适的 RenderViewHost 。进入 RenderViewHost::OnMessageReceived。大多数在这里被处理。剩下的被转发到 RenderWidgetHost 。它们被发送到对应renderer进程中的 RenderView 和 RenderWidget 。而不同平台会对它两有不同实现:RenderWidgetHostView[Aura|Gtk|Mac|Win]。它两是 WebContents 对象,大多数消息最后都调用到WebContents 对象。 WebContents 代表一个网页内容。它包含一个TabContentsWrapper。是chrome中的tab。

例子:

a.设置光标(从renderer进程到browser进程)。从webkit内部发出,通常是响应一个输入事件。到达contents层的 RenderWidget::SetCursor in content/renderer/render_widget.cc. RenderWidget::Send分发消息,由RenderView 发送到brwoser, RenderThread::Send发出。IPC::SyncChannel代理发出到浏览器。

 对应的IPC::ChannelProxy in the RenderProcessHost收到消息在browser进程的IO线程。ResourceMessageFilter 分发网络请求直接到IO线程。因为我们的没被过滤,还留在UI线程中。对应RenderProcess的RenderProcessHost::OnMessageReceived得到消息。它处理集中类型直接。转发剩下的到合适的RenderViewHost ,对应着发送方的RenderView 。RenderViewHost::OnMessageReceived收到消息,大多数在这里解决。但是这个来自RenderWidget 需要被RenderWidgetHost处理。在RenderViewHost 中未处理的消息自动转发到RenderWidgetHost。消息映射到 RenderWidgetHost::OnMsgSetCursor最终调用合适的UI功能设置了鼠标。

b. 鼠标点击(browser到renderer)

UI线程收到windows消息到 RenderWidgetHostViewWin::OnMouseEvent 。接着调用ForwardMouseEventToRenderer 。它打包input事件成跨平台WebMouseEvent ,发送到相关的RenderWidgetHost 。RenderWidgetHost::ForwardInputEvent建立IPC消息 ViewMsg_HandleInputEvent,把WebInputEvent 序列化进这个消息,调用RenderWidgetHost::Send发送出。这个会转到 RenderProcessHost::Send。转发到代理 IPC::ChannelProxy,在代理内部,代理消息到了browser进程的IO线程。写入到连接对应renderer进程的管道。(注意,许多消息都是从webcontents发出,尤其关于导航相关的,都遵循相同通道过程)

renderer进程的main线程的IPC::Channel读到消息, IPC::ChannelProxy代理到renderer 线程。RenderView::OnMessageReceived得到,不部分在这里被处理。click不是,它掉到 RenderWidget::OnMessageReceived,转发到RenderWidget::OnHandleInputEvent. 事件被给到WebWidgetImpl::HandleInputEvent,在这里转换成WebKit能用的 PlatformMouseEvent类。最终给到webkit内核的 Widget。(WebWidget就是个glue,将chrome的类型转成webkit的,然后给webkit。

       4. WebContents:允许将一个HTML网页以多进程方式渲染到一个区域中,定义在命令空间content中。

       5. Browser:代表一个浏览器窗口,它可以包含多个WebContents。

       6. Tab Helpers:附加在WebContents上,用来增加WebContents的功能,例如显示InfoBar。

       我们可以将第1层和第2层归结为WebKit层,第3层和第4层归结为Content层,第5层和第6层归结为浏览器层。如果以进程为边界,Tab Helpers、Browser、WebContents和Renderer host运行在Browser进程中,Renderer、WebKit glue和WebKit运行在Render进程中。

       Content层是Chromium的核心模块,它实现了Chromium的多进程架构。Content层主要向外提供的接口是WebContents,浏览器层通过这个WebContents接口就可以将一个HTML网页渲染在一个区域上。例如,Chrome就是通过Content层提供的WebContents接口实现一个浏览器的。同样我们也可以通过Content层提供的WebContents接口实现一个与Chrome类似的浏览器,甚至我们也可以通过Content层提供的WebContents接口实现一个嵌入在应用程序的浏览器控件,例如Android 4.4的WebView。

       在Content层中,一个用来渲染网页的区域称为RenderView。一个RenderView也称为一个RenderWidget。RenderView与RenderWidget的区别是,前者是描述的是一个用来显示网页内容的控件,后者描述的是一个可以接收用户输入的控件,但是它不一定是用来显示网页内容的。例如,点击网页上的选择框弹出来的窗口,是一个RenderWidget,它里面显示的内容与网页无关。

我们可以将RenderView和RenderWidget看作是一个接口。Browser进程和Render进程都需要实现这个接口。其中,Browser进程分别实现RenderView和RenderWidget接口的两个类是RenderViewHostImpl和RenderWidgetHostImpl,Render进程分别实现RenderView和RenderWidget接口的两个类是RenderViewImpl和RenderWidgetImpl。Browser进程的每一个RenderViewHostImpl对象和每一个RenderWidgetHostImpl对象在Render进程中都分别对应有一个RenderViewImpl对象和一个RenderWidgetImpl。RenderViewHostImpl对象与RenderViewImpl对象、RenderWidgetHostImpl对象与RenderWidgetImpl对象可以通过Browser进程与Render进程建立的IPC通道进行通信。

       WebKit层的WebView和WebWidget相当于Content层的RenderView和RenderWidget。我们注意到,WebKit层还有一个称为WebFrame的对象。事实上,Content层也有一个类似的对象,称为RenderFrame。WebFrame和RenderFrame都是用来描述网页的。既然已经有了RenderView和RenderWidget,为什么还需要WebFrame和RenderFrame呢?这与Chromium的Out-of-Process iframes(OOPIFs)项目有关。关于Chromium的Out-of-Process iframes(OOPIFs)项目的详细信息,可以参考官方文档:Out-of-Process iframes (OOPIFs)。


一些类

RenderWidgetHost

3种:popup,main frame,iframe
 // A RenderWidgetHost acts as the abstraction for compositing and input
// functionality. It can exist in 3 different scenarios:
//
// 1. Popups, which are spawned in situations like <select> menus or
//    HTML calendar widgets. These are browser-implemented widgets that
//    are created and owned by WebContents in response to a renderer
//    request. Since they are divorced from the web page (they are not
//    clipped to the bounds of the page), they are an independent
//    compositing and input target. As they are owned by WebContents,
//    they are also destroyed by WebContents.
//
// 2. Main frames, which are a root frame of a WebContents. These frames
//    are separated from the browser UI for compositing and input, as the
//    renderer lives in its own coordinate space. These are attached to
//    the lifetime of the main frame (currently, owned by the
//    RenderViewHost, though that should change one day as per
//    https://crbug.com/419087).
//
// 3. Child local root frames, which are iframes isolated from their
//    parent frame for security or performance purposes. This allows
//    them to be placed in an arbitrary process relative to their
//    parent frame. Since they are isolated from the parent, they live
//    in their own coordinate space and are an independent unit of
//    compositing and input. These are attached to the lifetime of
//    the local root frame, and are explicitly owned by the
//    RenderFrameHost.
//
// A RenderWidgetHost is platform-agnostic. It defers platform-specific
// behaviour to its RenderWidgetHostView, which ties the compositing
// output into the native browser UI. Child local root frames also have
// a separate "platform" RenderWidgetHostView type at this time, though
// it stretches the abstraction uncomfortably.
//
// The RenderWidgetHostView has a complex and somewhat broken lifetime as
// of this writing (see, e.g. https://crbug.com/1161585). It is eagerly
// created along with the RenderWidgetHost on the first creation, before
// the renderer process may exist. It is destroyed if the renderer process
// exits, and not recreated at that time. Then it is recreated lazily when
// the associated renderer frame/widget is recreated.

RenderWidget represents a surface that can paint and receive input. It is
// used in four contexts:
//   * Main frame for webpage (root is `blink::WebView`) 一个网页
//   * Child frame for webpage (root is RenderFrame) 子页面
//   * Popups (root is RenderWidget) 弹出框
//   * Pepper Fullscreen (root is RenderWidget)

RenderWidgetHostImpl::CreateSelfOwned 创建弹出框,是自我管理,没有人去负责释放它。

 RenderWidgetHostImpl
    : public RenderWidgetHost,
      public FrameTokenMessageQueue::Client,
      public InputRouterImplClient,
      public InputDispositionHandler,
      public RenderProcessHostObserver,
      public RenderProcessHostPriorityClient,
      public SyntheticGestureController::Delegate,
      public RenderFrameMetadataProvider::Observer,
      public blink::mojom::FrameWidgetHost,
      public blink::mojom::PopupWidgetHost,
      public blink::mojom::WidgetHost,
      public blink::mojom::PointerLockContext

WebContentsImpl 是一堆人的 delegate

WebContentsImpl : public WebContents,
                                       public FrameTree::Delegate,
                                       public RenderFrameHostDelegate,
                                       public RenderViewHostDelegate,
                                       public RenderWidgetHostDelegate,
                                       public RenderFrameHostManager::Delegate,
                                       public PageDelegate,
                                       public blink::mojom::ColorChooserFactory,
                                       public NavigationControllerDelegate,
                                       public NavigatorDelegate,
                                       public ui::NativeThemeObserver,
                                       public ui::ColorProviderSourceObserver

// WebContents is the core class in content/. A WebContents renders web content
// (usually HTML) in a rectangular area.
//
// Instantiating one is simple:
//   std::unique_ptr<content::WebContents> web_contents(
//       content::WebContents::Create(
//           content::WebContents::CreateParams(browser_context)));
//   gfx::NativeView view = web_contents->GetNativeView();
//   // |view| is an HWND, NSView*, etc.; insert it into the view hierarchy
//   // wherever it needs to go.
//
// That's it; go to your kitchen, grab a scone, and chill. WebContents will do
// all the multi-process stuff behind the scenes. More details are at
// https://www.chromium.org/developers/design-documents/multi-process-architecture
// .
//
// The owner of `std::unique_ptr<content::WebContents> web_contents` is
// responsible for ensuring that `web_contents` are destroyed (e.g. closed)
// *before* the corresponding `browser_context` is destroyed.
//
// Each WebContents has a `NavigationController`, which can be obtained from
// `GetController()`, and is used to load URLs into the WebContents, navigate
// it backwards/forwards, etc.
// See navigation_controller.h for more details.

 

InputRouterImpl

 InputRouterImpl
    : public InputRouter,
      public GestureEventQueueClient,
      public FlingControllerEventSenderClient,
      public MouseWheelEventQueueClient,
      public PassthroughTouchEventQueueClient,
      public TouchpadPinchEventQueueClient,
      public blink::mojom::WidgetInputHandlerHost

 

 

FrameWidget是个接口

与widgetBase在同一个目录

在blink的local root frame内出现,提供合成和input输入相关。扩展了FrameWidgetInputHandler,在主线程。
FrameWidgetInputHandlerImpl在合成线程。
// In interface exposed within Blink from local root frames that provides
// local-root specific things related to compositing and input. This
// class extends the FrameWidgetInputHandler implementation. All API calls
// on this class occur on the main thread. input/FrameWidgetInputHandlerImpl
// which also implements the FrameWidgetInputHandler interface runs on the
// compositor thread and proxies calls to this class.

 

RenderFrameHost 与 renderWidgetHost关系

 从renderFrame获取renderWidget:如果这个frame有localwidget,就直接取到;否则再次父Frame找。什么是localwidget,如果是main frame,从RenderViewHost中获取;否则是子frame,去获取owner renderwidget

while (frame) {
frame = frame->GetParent();
}

 

else
}

拿到renderwidgetHost后,如果是root的,去获取页面聚焦的widget控件:

  RenderWidgetHostImpl* widget_host = host_->GetRenderWidgetHost();
  if (!host_->GetParent() && widget_host->delegate()) { 这个host是root了,并且有delegate就是 webcontents。
    RenderWidgetHostImpl* target_host =
        widget_host->delegate()->GetFocusedRenderWidgetHost(widget_host); 从webcontents里面获取到聚焦的widget!!!
    if (target_host)
      widget_host = target_host;
  }

  base::OnceClosure closure =
      base::BindOnce(&InsertTextCallback::sendSuccess, std::move(callback));

  widget_host->Focus(); 让widget聚焦

  widget_host->GetWidgetInputHandler()->ImeCommitText(
      text16, std::vector<ui::ImeTextSpan>(), gfx::Range::InvalidRange(), 0,
      std::move(closure));


 

 

 


多进程架构:

由于渲染网页难免失败奔溃,而且会对系统造成影响。chrome采用多进程。每个页面对应自己的render进程,它们不能访问系统。需要远程传给browser进程访问系统。

主进程运行UI界面程序,并且管理渲染和其他进程(gpu,util进程等),称为browser进程。

处理网页和绘制的叫renderer进程。

browser进程和renderer进程是一对多的关系。

每个browser进程中的 RenderProcessHost管理在renderer进程中renderProcess,维护状态。

每个renderProcess有一个或多个RenderFrame对象,它对应frame,对应document,包含着web网页内容。对应的RenderFrameHost管理相关的document状态。RenderFrame 被指定一个routing id,因为在同一个renderer进程中有多个document时会有多个renderFrame,以便区分。由于这个id不是整个browser唯一的,区分renderFrame时需要 RenderProcessHost 和 routing ID。通过mojom通信(替换IPC)。

组件和接口:

在renderer进程:

RenderProcess 创建mojom,与RenderProcessHost 对应。每个renderer进程只有一个RenderProcess

RenderFrameRenderFrameHost 通信通过mojom,和blink layer。它是一个tab或者iframe的web document的内容。

在browser进程:

Browser 代表最高的浏览器窗口。

RenderProcessHost 表示一个browser进程方的代表与renderer进程对应的RenderProcess通信。

RenderFrameHost 封装了与 RenderFrame 的通信。RenderWidgetHost 处理input输入和绘制为了RenderWidget。

有时需要共享renderer进程,比如在window.open,它们是共源,新的document需要共享同一个进程的状态。

Giving back memory 不是当前的tab将释放内存

如何开始看chromium源码:https://www.chromium.org/developers/how-tos/getting-around-the-chrome-source-code/

webkit内部的WebView,page, WebFrame, Frame, document, frameView, RenderView, RenderFrame,Widget的层级关联关系以及构建过程


Webcore内部:

Page, Node, Element, Document, Settings

 

WebKit接口层:

WebView(WebViewImpl), WebNode, WebElement, WebDocument,WebSettings, WebFrame,

 

Platform层:

Widget.h, WebLayer,

 

WebViewImpl包含Page,WebSettings, WebLayer tree.

Page包含:Frame(main frame),FrameHost(一个被page内所有frame共享的数据结构),Settings.

Frame(LocalFrame)包含:

FrameLoader, FrameView,

有指向LocalDomWindow的引用,

FrameTree,

指向FrameHost,

指向一个FrameOwner(HTMLFrameOwnerElement)就是包含这个Frame的element.而element间接继承自Node,Node又和renderObject关联,也就是有renderer()函数。

WebLocalFrame指向WebCore::LocalFrame.

Frame.ownerRenderer()拿到一个RenderPart.继承自RenderWidget,实际上继承自RenderObject.

FrameHost,和一个page关联,是一个page内所有frame共享的结构。

FrameOwnerElement.继承自HTMLELement,是element.能够拿到renderer().

LocalDomWindow有Document指针,由于继承自FrameDestructionObserver,所以有Frame指针,这个Frame应该是mainframe.

一个Frame包含一个document么?LocalDomWindow对应整个网页么?

 

webcore就是内核功能;blink就是相当于以前的web层,即core对外的接口。比如frame被webframe封装了提供给外围。

localFrame拿到 document,page,

 

 

创建LocalDOMWindow:

->DocumentLoader::dataReceived

->DocumentLoader::commitData

->DocumentLoader::ensureWriter

->DocumentLoader::createWriterFor(LocalFrame* frame, constDocument* ownerDocument, const KURL& url,

->LocalDOMWindow::create(*frame),并把创建的dowwindow设置给frame.

可以看出此domwindow和frame一一对应,那么要看该frame是mainframe还是普通frame?

 

可以自己写一个多个frame的网页,然后加log,看看究竟创建了几个frame,几个domwindow,几个Document,几个Page,几个DocumentLoader,等等。

 

我写了一个简单的网页:

f.htm:

<body>
<iframe src="1.htm">
</iframe>
<iframe src="2.htm">
</iframe>
</body>


1.htm:

<body>
<p>hello 1</p>
</body>


2.htm:

<body>
<p>hello 2</p>
</body>
打开f.htm显示两个frame.
那么此时构建的上述类的结构关系如何?
当加载f.htm时:
Page (1个)----
Frame (mainFrame, 也是LocalFrame, 1个)
Frame包含:
1. FrameHost (1个,被page的所有frame共享)
2. FrameLoader (1个,于Frame11对应)
3. LocalDomWindow(1个,于Frame
11对应
4. Document
(1个,先创建一个,加载完成后,会destroy然后重新创建,
于frame11对应)
5.
DocumentLoader(会出现2个,应该是provisional,commited状态变换所致,最终会销毁第一个,只剩下一个),每个DocumentLoader会附带创建一个11对应的ResourceFetcher,
DocumentLoader销毁,ResourceFetcher也销毁。
6. FrameView
(1个,加载网页后,会被销毁重建,于frame
11对应)
加载网页过程中,Document会销毁重建,2个DocumentLoader中,有一个会被销毁。FrameView会被销毁重建。
f.htm加载完成,解析,发现有2个子iframe,
会生成两个子frame去加载:
子frame的结构关系:
Frame包含:
1. FrameLoader (于frame
11对应)
2. DocumentLoader
(也会建立两个,最后销毁一个),每个DocumetLoader对应一个resourceFetcher.
3. FrameView (于frame
11对应,会销毁重建)
4. Document (于frame
11对应,会销毁重建)
5. LocalDomWindow (于
frame 11 对应,会销毁重建)
最终结论:
网页中有main
frame, 每个iframe会建立子frame.
每个frame都有自己的FrameLoader,
Document, DoducmentLoader, FrameView 和LocalDomWindow.
但是FrameHost是多个frame共享的,Page也是共享的。
下面看Frame
--- element --- render之间的关联。
WebLocalFrame指向一个LocalFram.
每个LocalFrame关联一个FrameOwner,
其实是一个element:
class
HTMLFrameOwnerElement : public HTMLElement, public FrameOwner .
Element
的父类ContainerNode的父类Node有renderer()函数可以得到RenderObject*。所以Frame也可通过其Owner
Element得到renderer.
实际上Frame的render是RenderPart.
是一个很深的继承自RenderObject的子孙类。所以HTMLFrameOwnerElement有函数renderPart()得到RenderPart*.


Widget:

HTMLFrameOwnerElement拥有一个widget,ownedWidget()可以拿到。这个widget一般情况下就是FrameView.

Widget是scrollView,scrollBar,以及pluginView的基类。

Widget之间有父子关系。

 

FrameView:

Frame都有一个FrameView,FrameView就继承自ScrollView,继承自Widget.

FrameView是widget系列的东西。

FrameView有m_widgets保存若干子RenderWIdgets.

 

LocalFrame::createView中会为自己创建一个FrameView,并把它当作widget注册给HTMLFrameOwnerElement,也就是ownerRender.

classHTMLFrameElementBase : public HTMLFrameOwnerElement {

 

 

RenderView:

RenderView和Document关联,Document的attach函数创建一个RenderView, RenderView也是继承自RenderObject,他是rendertree的root.

RenderView是RenderObject系列的东西,也是render系列的东西。

 

RenderWIdget:

RenderWidget也是RenderObject系列的东西。

RenderWidget和一个widget关联。也是和一个HTMLFrameOwnerElement关联。

可以认为RenderWidget把widget包装了一层,是一个adapter,对RenderWIdget调用的一些操作会被其关联的widget处理。所以虽然RenderWidget是render系列的东西,但是他会把逻辑调用转给widget.

 

LocalDomWindow:

在DocumentLoader收到数据后,会创建LocalDomWindow并注册给Frame.

 

WebView:

继承自WebWIdget.

WebViewImpl继承自WebView.

WebView.h是接口。被chrome的content模块使用。

Content层的RenderViewImpl::initialize中就创建了WebView,并创建了WebFrame作为mainframe注册给创建的WebView.

 

下面看看FrameHost,FrameClient.

FrameClient:

FrameLoaderClient继承自FrameClient,所以Frame的FrameClient就是FrameLoaderClient.

classFrameLoaderClientImpl FINAL: public WebCore::FrameLoaderClient

 

 

 

Frame,LocalFrame, WebFrame, WebLocalFrame, WebLocalFrameImpl:

WebLocalFrameImpl继承自WebFrame.LocalFrame继承自Frame.

WebLocalFrameImpl里面会建立并关联一个LocalFrame.并把自己的FrameLoaderClientImpl关联给LocalFrame作为FrameClient.

 

WebLocalFrame的创建:

1.建立childframe:

在content的RenderFrameImpl中创建一个RenderFrameImpl和一个WebLocalFrameImpl(调用的是WebLocalFrame::create),然后把这两个content模块和WebCore模块的frame相关联。而且content模块的RenderFrameImpl作为WebLocalFrame的WebFrameClient。

Childframe何时建立?

->htmlparser解析处理token:比如处理iframetoken.

->HTMLConstructionSite::insertSelfClosingHTMLElement(AtomicHTMLToken*token)

->HTMLConstructionSite::attachLater(ContainerNode*parent, PassRefPtrWillBeRawPtr<Node> prpChild, boolselfClosing)

建立HTMLConstructionSiteTask,然后queueTask.

---------------下面是执行task----------------

->voidHTMLConstructionSite::executeQueuedTasks()

-》executeInsertTask()

->插入,replace,append节点都会引起一些下面的notify动作。

->voidContainerNode::updateTreeAfterInsertion(Node& child)

void ContainerNode::parserInsertBefore(PassRefPtrWillBeRawPtr<Node>newChild, Node& nextChild)

void ContainerNode::parserAppendChild(PassRefPtrWillBeRawPtr<Node>newChild)

-》ContainerNode::notifyNodeInserted(Node&root, ChildrenChangeSource source)当一个node被插入到domtree后,会调用这个callback:

->voidHTMLFrameElementBase::didNotifySubtreeInsertionsToDocument()

->voidHTMLFrameElementBase::setNameAndOpenURL()

->HTMLFrameElementBase::openURL(boollockBackForwardList)

->HTMLFrameOwnerElement::loadOrRedirectSubframe

->FrameLoaderClient::createFrame(url,framname,...)创建完后会调用started()

->WebLocalFrameImpl::createChildFrame

->RenderFrameImpl::createChildFrame

 

建立mainframe

content模块的RenderViewImpl::initialize中,建立一个RenderFrameImpl,和一个WebLocalFrameImpl(通过WebLocalFrame::create),并让他们关联。

并把mainframe注册给webview.

 

LocalFrame的client是WebLocalFrame的FrameLoaderClientImpl成员.

WebLocalFrame的clientRenderFrameImpl.

 

WebFrame,WebLocalFrame可以看作是把Frame,LocalFrame的内容包了一下。

WebFrame,WebLocalFrame都是blink namespace的。

Frame,LocalFrame都是webCore namespace的。

 

加载网页时,是调用WebFrame的loadrequest()函数。

进而会触发FrameLoader的一系列操作。

 

————————————————
版权声明:本文为CSDN博主「csshell2002」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/csshell2002/article/details/48313387


 

render对象关系:

RenderObject
  * RenderText
      * RenderBR
     * RenderCombineText
      * RenderCounter
     * RenderQuote
      *RenderTextFragment
      * RenderWordBreak
  * RenderLayerModelObject
      *RenderBoxModelObject
         *RenderInline
            *RenderRubyAsInline
         * RenderBox
           * RenderListBox
           * RenderListItem
           * RenderListMarker
           * RenderFrameSet
           * RenderReplica
            *RenderTableSection
            *RenderTableRow
            *RenderBlock
               *RenderFlexibleBox
                 * RenderButton
                 * RenderFullScreen
                 *RenderMenuList(PopupMenuClient)
                 * RenderSlider
              * RenderDeprecatedFlexibleBox
              * RenderDetailsMarker
              * RenderFieldset
              *RenderFileUploadControl
              * RenderFlowThread
              * RenderGrid
              * RenderLazyBlock
              * RenderTextTrackContainerElement
              * RenderMeter
              * RenderProgress
              * RenderRubyAsBlock
              * RenderRubyBase
              * RenderRubyRun
              * RenderRubyText
              *RenderScrollbarPart
              * RenderTable
              * RenderTableCaption
              * RenderTableCell
              * RenderTableCol
              * RenderTextTrackCue
              * RenderView
              * RenderTextControl
                 *RenderTextControlMultiLine
                 * RenderTextControlSingleLine
              * RenderMultiColumnBlock
              * RenderFlowThread
                 *RenderMultiColumnFlowThread
                 * RenderNamedFlowThread
              * RenderRegion
                 * RenderRegionSet
                    *RenderMultiColumnSet
              * RenderTextControl
                 * RenderTextControlSingleLine
                    *RenderSearchField (PopupMenuClient)
           * RenderReplaced
              * RenderHTMLCanvas
              * RenderImage
                 * RenderMedia
                    * RenderVideo
              * RenderWidget
                 *RenderPart
                    * RenderEmbeddedObject
                       *RenderApplet
                    * RenderFrameBase
                       *RenderFrame
                       * RenderIFrame


ScrollableArea
  * RenderLayer


WebCore::Widget
   *WebCore::Scrollbar
      *WebCore::RenderScrollbar


ScrollbarTheme
   *ScrollbarThemeComposite
      *RenderScrollbarTheme


RenderArena
RenderBoxRegionInfo


 

WebView对应一个window.

WebView有一个Page,一个WebView对应一个page.

RenderView给WebView建立一个WebFrameImpl作为最顶层的rootwebframe.

一个webView的page里面可以有WebFrame构成的树,最顶层就是mainWebFrame. Root WebFrame可以建立孩子WebFrame.

WebFrame的client是RenderFrameImpl,这个RenderFrameImpl是RenderViewImpl::initialize里面建立的。

每个WebFrame会建立自己的Frame.而每个Frame会建立自己的FrameView.

所有这些WebFrame都持有containerView也就是WebView的引用。

一个Page关联一个最顶层的WebFrame,所以关联最顶层的Frame,最顶层的Frame对应整个网页,不被销毁。他的孩子会被销毁替换。

从最顶层的frame可以访问到各孩子frame.

每个frame内部有一个frameloader。

每个frame还会建立DocumentLoader.DocumentLoader也和frame关联。

每个Frame和一个document关联。

每个Frame又会关联一个FrameView.FrameView继承自ScrollView,又继承自Widget.所以他是实际和显示相关的。

 

Frame的创建点2个:

WebFrameImpl::initializeAsMainFrame

WebFrameImpl::createChildFrame(),会先创建一个WebFrame,然后建立Frame.

都会调用Frame::create().

Frame的构造函数回传进来一个HTMLFrameOwnerElement,对于mainFrame,这个是空,对于childframe这个才有值。

 

 

render建立主frame和FrameView的流程:

1, Main frame的创建,即root frame:

RenderView被建立时,会建立mainFrame,从而会建立FrameLoader,并且会加载空文档,所以也会直接建立一个FrameView:

从上往下执行:

->IPC::ChannelProxy::Context::OnDispatchMessage

->content::ChildThread::OnMessageReceived

->content::RenderThreadImpl::OnControlMessageReceived

->content::RenderThreadImpl::OnCreateNewView

->content::RenderViewImpl::Create

->content::RenderViewImpl::Initialize

->WebKit::WebViewImpl::initializeMainFrame

->WebKit::WebFrameImpl::initializeAsMainFrame

->WebCore::FrameLoader::init

->WebCore::DocumentLoader::startLoadingMainResource

->WebCore::DocumentLoader::maybeLoadEmpty

->WebCore::DocumentLoader::finishedLoading

->WebCore::FrameLoader::commitProvisionalLoad

->FrameLoader::transitionToCommitted(PassRefPtr<CachedPage>cachedPage)

->voidFrameLoaderClientImpl::transitionToCommittedForNewPage()

->WebFrameImpl::createFrameView()

->Frame::createView(),创建FrameView.

→ 调用如下:

FrameView::create(),建立FrameView

 

ownerRenderer()->setWidget(frameView);//相当于告诉该render以后向哪里绘制

ownerRender其实是HTMLFrameOwnerElement->render(),会得到一个RenderPart,然后RenderPart->setWidget()相当于告诉该render以后向哪里绘制。HTMLFrameOwnerElement是WebFrameImpl::initializeAsMainFrame中建立Frame时传进来的。由于此时,建立的是mainframe,此时的HTMLFrameOwnerElement是空的。

 

2, 子Frame啥时候建立的?

->HTMLFrameElementBase::parseAttribute,当解析到src属性时,把src的值当作location调用下面函数:

->voidHTMLFrameElementBase::setLocation(constString&str) //str就是链接地址

->HTMLFrameElementBase::openURL(boollockBackForwardList)

->HTMLFrameOwnerElement::loadOrRedirectSubframe(constKURL&url, constAtomicString&frameName, boollockBackForwardList)//这个函数会创建childframe,并初始化childFrame,然后启动childframe的loader.

->调用如下:

RefPtr<Frame>parentFrame = document()->frame();拿到本HTMLFrameOwnerElement的document对应的主Frame.

parentFrame->loader()->client()->createFrame(url,frameName, this,..)其实调用了FrameLoaderClientImpl::createFrame,创建childframe,第三个参数this就是传入的HTMLFrameOwnerElement.也是一个HTMLElement.一个page里所有的Frame共用一个FrameLoaderClientImpl.(共用还是每个frame有一个???)

>WebFrameImpl::createChildFrame()

->Frame::create(

->Frame::Init()

->FrameLoader::init(),//启动childframe的FrameLoader.开始加载资源当资源数据到来之后会触发本Frame的FrameView的创建,当然那就是异步的了

->创建ProvisionalDocumentLoader,并调用m_provisionalDocumentLoader->startLoadingMainResource()以及activeDocLoader->startLoadingSpeculativeResource()。

childFrame->loader()->started();

toRenderWidget(renderObject)->setWidget(FrameView);renderObject是和这个HTMLElement关联的RenderObject,把它cast成RenderWidget.然后设置他的Widget为childFrame里面的FrameView.不过一般当Frame刚建立时,这个view可能是空的,所以这个操作可能不会执行。

 

下面是一个创建childframe的callstack的场景:

这个场景看样子就是加载网页的过程中,收到backgroundhtml parser发来的一些token,处理并增加一个childframe的过程。

#0 WebCore::HTMLFrameOwnerElement::loadOrRedirectSubframe(this=0x33888014, url=..., frameName=..., lockBackForwardList=true)at../../third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp:127

#1 0x6226b91c in openURL (lockBackForwardList=true, this=0x33888014) at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:93

#2 WebCore::HTMLFrameElementBase::openURL(this=0x33888014, lockBackForwardList=<optimized out>) at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:73

#3 0x627cf016 in WebCore::ChildNodeInsertionNotifier::notify(this=0x650899c0, node=<optimized out>) at../../third_party/WebKit/Source/core/dom/ContainerNodeAlgorithms.h:228

#4 0x627cf19a in WebCore::ContainerNode::parserAppendChild(this=0x3387de44, newChild=...) at../../third_party/WebKit/Source/core/dom/ContainerNode.cpp:676

#5 0x622bd6ee in WebCore::insert (task=..., lazyAttach=<optimizedout>) at../../third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp:105

#6 0x622bd708 in executeInsertTask (task=...) at../../third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp:122

#7 WebCore::executeTask (task=...) at../../third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp:162

#8 0x622be256 in WebCore::HTMLConstructionSite::executeQueuedTasks(this=<optimized out>) at../../third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp:213

#9 0x622c1396 inWebCore::HTMLDocumentParser::constructTreeFromCompactHTMLToken(this=0x6b477b68, compactToken=...) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:598

#100x622c3186 inWebCore::HTMLDocumentParser::processParsedChunkFromBackgroundParser(this=0x6b477b68, popChunk=...) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:422

#110x622c32d8 in WebCore::HTMLDocumentParser::pumpPendingSpeculations(this=0x6b477b68) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:467

#120x622c3682 inWebCore::HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser(this=0x6b477b68, chunk=...) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:317

#130x622bad76 in WTF::FunctionWrapper<void(WebCore::HTMLDocumentParser::*)(WTF::PassOwnPtr<WebCore::HTMLDocumentParser::ParsedChunk>)>::operator()(this=0x6b46b810, c=..., p1=...)

at../../third_party/WebKit/Source/wtf/Functional.h:210

#140x622badac in WTF::BoundFunctionImpl<WTF::FunctionWrapper<void(WebCore::HTMLDocumentParser::*)(WTF::PassOwnPtr<WebCore::HTMLDocumentParser::ParsedChunk>)>,void (WTF::WeakPtr<WebCore::HTMLDocumentParser>, WTF

::PassOwnPtr<WebCore::HTMLDocumentParser::ParsedChunk>)>::operator()()(this=<optimized out>) at../../third_party/WebKit/Source/wtf/Functional.h:420

#150x6222df40 in operator() (this=0x693cea08) at../../third_party/WebKit/Source/wtf/Functional.h:577

#16WTF::callFunctionObject (context=0x693cea08) at../../third_party/WebKit/Source/wtf/MainThread.cpp:62

#170x61f3a922 in Run (this=<synthetic pointer>, a1=<optimizedout>) at ../../base/bind_internal.h:171

#18MakeItSo (runnable=..., a1=<optimized out>) at../../base/bind_internal.h:871

#19base::internal::Invoker<1,base::internal::BindState<base::internal::RunnableAdapter<void(*)(void*)>, void (void*), void (void*)>, void(void*)>::Run(base::internal::BindStateBase*) (base=<optimizedout>)

at../../base/bind_internal.h:1169

#200x621dbe40 in Run (this=0x65089c38) at ../../base/callback.h:396

#21base::MessageLoop::RunTask (this=0x65089cc0, pending_task=...) at../../base/message_loop/message_loop.cc:482

#220x621dc33a in base::MessageLoop::DeferOrRunPendingTask(this=0x65089cc0, pending_task=...) at../../base/message_loop/message_loop.cc:494

#230x621dc66c in DoWork (this=<optimized out>) at../../base/message_loop/message_loop.cc:608

#24base::MessageLoop::DoWork (this=0x65089cc0) at../../base/message_loop/message_loop.cc:587

#250x621dca86 in base::MessagePumpDefault::Run (this=0x5952d468,delegate=0x65089cc0) at../../base/message_loop/message_pump_default.cc:32

#260x621dc08a in base::MessageLoop::RunInternal (this=0x65089cc0) at../../base/message_loop/message_loop.cc:436

#270x621e4572 in base::RunLoop::Run (this=0x65089ca0) at../../base/run_loop.cc:45

#280x621db8f8 in base::MessageLoop::Run (this=<optimized out>) at../../base/message_loop/message_loop.cc:307

#290x621ed86a in base::Thread::ThreadMain (this=0x1) at../../base/threading/thread.cc:203

#300x621eb4a6 in base::(anonymous namespace)::ThreadFunc(params=<optimized out>) at../../base/threading/platform_thread_posix.cc:80

#310x40104a5c in __thread_entry () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#320x40104bd8 in pthread_create () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

 

 

下面是另一个创建childframe的callstack场景:

这个场景看样子是资源加载完成后,执行完了script之后继续处理backgroundhtmlparser发来的一些任务,并插入一个子frame.

#0 WebKit::WebFrameImpl::createChildFrame (this=0x661a79c0,request=..., ownerElement=0x33888014) at../../third_party/WebKit/Source/web/WebFrameImpl.cpp:2150

#1 0x6218fea6 in WebKit::FrameLoaderClientImpl::createFrame(this=0x661a79e4, url=..., name=..., ownerElement=0x33888014,referrer=..., allowsScrolling=true, marginWidth=-1, marginHeight=-1)

at../../third_party/WebKit/Source/web/FrameLoaderClientImpl.cpp:644

#2 0x6226c03a in WebCore::HTMLFrameOwnerElement::loadOrRedirectSubframe(this=0x33888014, url=..., frameName=...,lockBackForwardList=<optimized out>)

at../../third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp:143

#3 0x6226b91c in openURL (lockBackForwardList=true, this=0x33888014) at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:93

#4 WebCore::HTMLFrameElementBase::openURL(this=0x33888014, lockBackForwardList=<optimized out>) at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:73

#5 0x627cf016 in WebCore::ChildNodeInsertionNotifier::notify(this=0x650895e8, node=<optimized out>) at../../third_party/WebKit/Source/core/dom/ContainerNodeAlgorithms.h:228

#6 0x627cf19a in WebCore::ContainerNode::parserAppendChild(this=0x338582b4, newChild=...) at../../third_party/WebKit/Source/core/dom/ContainerNode.cpp:676

#7 0x622bd6ee in WebCore::insert (task=..., lazyAttach=<optimizedout>) at../../third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp:105

#8 0x622bd708 in executeInsertTask (task=...) at../../third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp:122

#9 WebCore::executeTask (task=...) at../../third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp:162

#100x622be256 in WebCore::HTMLConstructionSite::executeQueuedTasks(this=<optimized out>) at../../third_party/WebKit/Source/core/html/parser/HTMLConstructionSite.cpp:213

#110x622c1396 inWebCore::HTMLDocumentParser::constructTreeFromCompactHTMLToken(this=0x694443e8, compactToken=...) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:598

#120x622c3186 inWebCore::HTMLDocumentParser::processParsedChunkFromBackgroundParser(this=0x694443e8, popChunk=...) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:422

#130x622c32d8 in WebCore::HTMLDocumentParser::pumpPendingSpeculations(this=0x694443e8) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:467

#140x622c3462 inWebCore::HTMLDocumentParser::resumeParsingAfterScriptExecution(this=0x694443e8) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:872

#150x622c35c2 in WebCore::HTMLDocumentParser::notifyFinished(this=0x694443e8, cachedResource=0x69234fe8) at../../third_party/WebKit/Source/core/html/parser/HTMLDocumentParser.cpp:917

#160x6275ee66 in checkNotify (this=0x69234fe8) at../../third_party/WebKit/Source/core/loader/cache/Resource.cpp:205

#17WebCore::Resource::checkNotify (this=0x69234fe8) at../../third_party/WebKit/Source/core/loader/cache/Resource.cpp:198

#180x6275d574 in WebCore::Resource::finishOnePart (this=<optimizedout>) at../../third_party/WebKit/Source/core/loader/cache/Resource.cpp:240

#190x6275d6aa in WebCore::Resource::finish(this=0x69234fe8, finishTime=<optimized out>) at../../third_party/WebKit/Source/core/loader/cache/Resource.cpp:248

#200x62754458 in didFinishLoading (finishTime=161969.75042699999,this=0x6ad2eea0) at../../third_party/WebKit/Source/core/loader/ResourceLoader.cpp:363

#21WebCore::ResourceLoader::didFinishLoading(this=0x6ad2eea0, finishTime=<optimized out>) at../../third_party/WebKit/Source/core/loader/ResourceLoader.cpp:351

#220x61f3cf48 inwebkit_glue::WebURLLoaderImpl::Context::OnCompletedRequest(this=0x6ae4aac8, error_code=<optimized out>,was_ignored_by_handler=<optimized out>, security_info=...,completion_time=...)

at../../webkit/child/weburlloader_impl.cc:726

#230x62d6bfb4 in content::ResourceDispatcher::OnRequestComplete(this=0x595bc780, request_id=<optimized out>, error_code=0,was_ignored_by_handler=<optimized out>, security_info=...,browser_completion_time=...)

at../../content/child/resource_dispatcher.cc:514

#240x62d6b648 in DispatchToMethod<content::ResourceDispatcher, void(content::ResourceDispatcher::*)(int, int, bool, std::string const&,base::TimeTicks const&), int, int, bool, std::string,base::TimeTicks> (

obj=<optimizedout>, method=

(void(content::ResourceDispatcher::*)(content::ResourceDispatcher * const,int, int, bool, const std::basic_string<char,std::char_traits<char>, std::allocator<char> > &,const base::TimeTicks &)) 0x62d6bf3d

<content::ResourceDispatcher::OnRequestComplete(int,int, bool, std::string const&, base::TimeTicks const&)>,arg=...) at ../../base/tuple.h:579

#250x62d6b694 inResourceMsg_RequestComplete::Dispatch<content::ResourceDispatcher,content::ResourceDispatcher, void(content::ResourceDispatcher::*)(int, int, bool, std::string const&,base::TimeTicks const&)>

(msg=0x69656080,obj=0x595bc780, func=

(void(content::ResourceDispatcher::*)(content::ResourceDispatcher * const,int, int, bool, const std::basic_string<char,std::char_traits<char>, std::allocator<char> > &,const base::TimeTicks &)) 0x62d6bf3d

<content::ResourceDispatcher::OnRequestComplete(int,int, bool, std::string const&, base::TimeTicks const&)>,sender=<optimized out>) at../../content/common/resource_messages.h:268

#260x62d6b8a6 in content::ResourceDispatcher::DispatchMessage(this=0x595bc780, message=...) at../../content/child/resource_dispatcher.cc:615

#270x62d6c758 in OnMessageReceived (message=..., this=0x595bc780) at../../content/child/resource_dispatcher.cc:305

#28content::ResourceDispatcher::OnMessageReceived (this=0x595bc780,message=...) at ../../content/child/resource_dispatcher.cc:268

#290x62d5a2f6 in content::ChildThread::OnMessageReceived(this=0x5952a304, msg=...) at ../../content/child/child_thread.cc:314

#300x6217331a in IPC::ChannelProxy::Context::OnDispatchMessage(this=0x594f6938, message=...) at ../../ipc/ipc_channel_proxy.cc:264

#310x6217277a in Run (a1=..., object=<optimized out>,this=0x65089b60) at ../../base/bind_internal.h:190

#32MakeItSo (a2=..., runnable=..., a1=<optimized out>) at../../base/bind_internal.h:898

#33base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void(IPC::ChannelProxy::Context::*)(IPC::Message const&)>, void(IPC::ChannelProxy::Context*, IPC::Message const&), void (I

PC::ChannelProxy::Context*,IPC::Message)>, void (IPC::ChannelProxy::Context*, IPC::Messageconst&)>::Run(base::internal::BindStateBase*)(base=0x69656068) at ../../base/bind_internal.h:1253

#340x621dbe40 in Run (this=0x65089c38) at ../../base/callback.h:396

#35base::MessageLoop::RunTask (this=0x65089cc0, pending_task=...) at../../base/message_loop/message_loop.cc:482

#360x621dc33a in base::MessageLoop::DeferOrRunPendingTask(this=0x65089cc0, pending_task=...) at../../base/message_loop/message_loop.cc:494

#370x621dc66c in DoWork (this=<optimized out>) at../../base/message_loop/message_loop.cc:608

#38base::MessageLoop::DoWork (this=0x65089cc0) at../../base/message_loop/message_loop.cc:587

#390x621dca86 in base::MessagePumpDefault::Run (this=0x5952d468,delegate=0x65089cc0) at../../base/message_loop/message_pump_default.cc:32

#400x621dc08a in base::MessageLoop::RunInternal (this=0x65089cc0) at../../base/message_loop/message_loop.cc:436

#410x621e4572 in base::RunLoop::Run (this=0x65089ca0) at../../base/run_loop.cc:45

#420x621db8f8 in base::MessageLoop::Run (this=<optimized out>) at../../base/message_loop/message_loop.cc:307

#430x621ed86a in base::Thread::ThreadMain (this=0x1) at../../base/threading/thread.cc:203

#440x621eb4a6 in base::(anonymous namespace)::ThreadFunc(params=<optimized out>) at../../base/threading/platform_thread_posix.cc:80

#450x40104a5c in __thread_entry () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#460x40104bd8 in pthread_create () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#470x00000000 in ?? ()

 

下面是第三个建立childframe的callstack场景:

这里看样子是v8脚本引擎执行一个api调用,设置了一个元素的属性,引起了一个IFrame的创建。这里的element节点是HTMLIFrameElement.有classHTMLIFrameElement FINAL : publicHTMLFrameElementBase 。可见脚本执行也会创建childframe。

#0 WebCore::HTMLFrameOwnerElement::loadOrRedirectSubframe(this=0x338880cc, url=..., frameName=..., lockBackForwardList=false)at../../third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp:127

#1 0x6226b91c in openURL (lockBackForwardList=false, this=0x338880cc)at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:93

#2 WebCore::HTMLFrameElementBase::openURL(this=0x338880cc, lockBackForwardList=<optimized out>) at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:73

#3 0x6226b9e2 in WebCore::HTMLFrameElementBase::setLocation(this=0x338880cc, str=...) at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:198

#4 0x6226ba9a in WebCore::HTMLFrameElementBase::parseAttribute(this=0x338880cc, name=..., value=...) at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:105

#5 0x6226d736 in WebCore::HTMLIFrameElement::parseAttribute(this=0x338880cc, name=..., value=...) at../../third_party/WebKit/Source/core/html/HTMLIFrameElement.cpp:97

#6 0x627f150e inWebCore::Element::attributeChanged (this=0x338880cc, name=...,newValue=..., reason=WebCore::Element::ModifiedDirectly) at../../third_party/WebKit/Source/core/dom/Element.cpp:911

#7 0x627edc84 in WebCore::Element::didModifyAttribute (this=0x338880cc,name=..., value=...) at../../third_party/WebKit/Source/core/dom/Element.cpp:2845

#8 0x627f39ba in WebCore::Element::setAttributeInternal(this=0x338880cc, index=0, name=..., newValue=...,inSynchronizationOfLazyAttribute=WebCore::Element::NotInSynchronizationOfLazyAttribute)

at../../third_party/WebKit/Source/core/dom/Element.cpp:884

#9 0x627f46b0 in WebCore::Element::setAttribute(this=0x338880cc, localName=..., value=..., es=...) at../../third_party/WebKit/Source/core/dom/Element.cpp:841

#100x62911a50 in setAttributeMethod (args=...) atgen/blink/bindings/V8Element.cpp:4151

#11WebCore::ElementV8Internal::setAttributeMethodCallback(args=...) at gen/blink/bindings/V8Element.cpp:4161

#120x61d1448c in v8::internal::FunctionCallbackArguments::Call(this=0x65089178, f=<optimized out>) at../../v8/src/arguments.cc:103

#130x61d204fc in HandleApiCallHelper<false> (isolate=0x599ea008,args=...) at ../../v8/src/builtins.cc:1272

#14Builtin_implHandleApiCall (isolate=0x599ea008, args=...) at../../v8/src/builtins.cc:1289

#15v8::internal::Builtin_HandleApiCall(args_length=4, args_object=0x650891e8, isolate=0x599ea008) at../../v8/src/builtins.cc:1288

#160x6630ab7c in ?? ()

 

下面又是一个v8引起的子frame的建立:

#0 WebCore::HTMLFrameOwnerElement::loadOrRedirectSubframe(this=0x33888184, url=..., frameName=..., lockBackForwardList=true)at../../third_party/WebKit/Source/core/html/HTMLFrameOwnerElement.cpp:127

#1 0x6226b91c in openURL (lockBackForwardList=true, this=0x33888184) at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:93

#2 WebCore::HTMLFrameElementBase::openURL (this=0x33888184,lockBackForwardList=<optimized out>) at../../third_party/WebKit/Source/core/html/HTMLFrameElementBase.cpp:73

#3 0x627cf016 in WebCore::ChildNodeInsertionNotifier::notify(this=0x650895c0, node=<optimized out>) at../../third_party/WebKit/Source/core/dom/ContainerNodeAlgorithms.h:228

#4 0x627cf39e in WebCore::updateTreeAfterInsertion (parent=0x3387f654,child=0x338b890c, attachBehavior=WebCore::AttachLazily) at../../third_party/WebKit/Source/core/dom/ContainerNode.cpp:1036

#5 0x627d061e in WebCore::ContainerNode::insertBefore (this=0x3387f654,newChild=..., refChild=<optimized out>, es=...,attachBehavior=WebCore::AttachLazily)

at../../third_party/WebKit/Source/core/dom/ContainerNode.cpp:279

#6 0x62264584 in WebCore::HTMLElement::insertAdjacent (this=0x3386f4ac,where=..., newChild=0x3388c014, es=...) at../../third_party/WebKit/Source/core/html/HTMLElement.cpp:502

#7 0x6226470c in WebCore::HTMLElement::insertAdjacentHTML(this=0x3386f4ac, where=..., markup=..., es=...) at../../third_party/WebKit/Source/core/html/HTMLElement.cpp:570

#8 0x629d212c in insertAdjacentHTMLMethod (args=...) atgen/blink/bindings/V8HTMLElement.cpp:627

#9 WebCore::HTMLElementV8Internal::insertAdjacentHTMLMethodCallback(args=...) at gen/blink/bindings/V8HTMLElement.cpp:637

#100x61d1448c in v8::internal::FunctionCallbackArguments::Call(this=0x65089788, f=<optimized out>) at../../v8/src/arguments.cc:103

#110x61d204fc in HandleApiCallHelper<false> (isolate=0x599ea008,args=...) at ../../v8/src/builtins.cc:1272

#12Builtin_implHandleApiCall (isolate=0x599ea008, args=...) at../../v8/src/builtins.cc:1289

#13v8::internal::Builtin_HandleApiCall (args_length=4,args_object=0x650897fc, isolate=0x599ea008) at../../v8/src/builtins.cc:1288

#140x6630ab7c in ?? ()

#150x6630ab7c in ?? ()

 

 

Render在一个frame的数据来了之后,建立该frame的FrameView的流程:

某个frame的数据来了之后,从下层ResourceLoader通知上来,通过DocumentLoader,到达FrameLoader,FrameLoader让DocumentLoader状态切换成commited,表明收到数据确认了,那么此时就建立该Frame的FrameView.看来子frame的frameView应该也是这个流程。

#0 WebCore::Frame::createView (this=0x59467a58, viewportSize=...,backgroundColor=...,

transparent=false,fixedLayoutSize=..., useFixedLayout=true,

horizontalScrollbarMode=WebCore::ScrollbarAuto,horizontalLock=false,

verticalScrollbarMode=WebCore::ScrollbarAuto,verticalLock=false)

at../../third_party/WebKit/Source/core/page/Frame.cpp:482

#1 0x61b23af2 in WebKit::WebFrameImpl::createFrameView(this=0x594679b0)

at../../third_party/WebKit/Source/web/WebFrameImpl.cpp:2222

这里其实缺少了一行调用stack:FrameLoaderClientImpl::transitionToCommittedForNewPage()

#2 0x620cc584 in WebCore::FrameLoader::transitionToCommitted(this=0x59467ab0, cachedPage=...)//这个函数把当前的用于加载的DocumentLoader从Provisional状态改为commited状态,这样这个DocumentLoader成为当前的正式的Documentloader.之前的Frame数据和Doucmentloader被清理。

at../../third_party/WebKit/Source/core/loader/FrameLoader.cpp:1342

#3 0x620cc6d4 in WebCore::FrameLoader::commitProvisionalLoad(this=0x59467ab0)

at../../third_party/WebKit/Source/core/loader/FrameLoader.cpp:1230

#4 0x620c4518 in WebCore::DocumentLoader::dataReceived(this=0x60e09068, resource=<optimized out>,

data=0x68b60000"<!DOCTYPE html>\r\n<html>\r\n\r\n<head>\r\n<metacharset=\"UTF-8\" />\r\n<metahttp-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\"/>\r\n<meta name=\"viewport\" content=\"width=device-

width,minimum-scale=1.0,user-"...,length=2802)

at../../third_party/WebKit/Source/core/loader/DocumentLoader.cpp:658

#5 0x620ddea4 in WebCore::RawResource::appendData(this=0x658ec3d0,

ttp-equiv=\"X-UA-Compatible\"content=\"IE=edge,chrome=1\" />\r\n<metaname=\"viewport\"content=\"width=device-width,minimum-scale=1.0,user-"...,length=2802)

at../../third_party/WebKit/Source/core/loader/cache/RawResource.cpp:49

#6 0x620d4d58 in WebCore::ResourceLoader::didReceiveData(this=0x60e0a310,

dth=device-width,minimum-scale=1.0,user-"...,length=2802, encodedDataLength=-1)

at../../third_party/WebKit/Source/core/loader/ResourceLoader.cpp:348

#7 0x618bdc38 in OnReceivedData (encoded_data_length=<optimizedout>, data_length=2802,

data=0x68b60000"<!DOCTYPE html>\r\n<html>\r\n\r\n<head>\r\n<metacharset=\"UTF-8\" />\r\n<metahttp-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\"/>\r\n<meta name=\"viewport\" content=\"width=device-

width,minimum-scale=1.0,user-"...,this=0x60e0bbc8)

at../../webkit/child/weburlloader_impl.cc:693

#8 webkit_glue::WebURLLoaderImpl::Context::OnReceivedData(this=0x60e0bbc8,

ttp-equiv=\"X-UA-Compatible\"content=\"IE=edge,chrome=1\" />\r\n<metaname=\"viewport\"content=\"width=device-width,minimum-scale=1.0,user-"...,data_length=2802, encoded_data_length=<optimized out>)

at../../webkit/child/weburlloader_impl.cc:678

#9 0x626ed3d4 in content::ResourceDispatcher::OnReceivedData(this=0x59c5b458, message=...,

request_id=0,data_offset=<optimized out>, data_length=2802,encoded_data_length=-1)

at../../content/child/resource_dispatcher.cc:417

#100x626ec7ce inResourceMsg_DataReceived::Dispatch<content::ResourceDispatcher,content::ResourceDispatcher, int, int, int, int> (msg=0x67906e98,obj=0x59c5b458, sender=<optimized out>, func=

int,int, int, int)) 0x626ed2ad<content::ResourceDispatcher::OnReceivedData(IPC::Message const&,int, int, int, int)>) at../../content/common/resource_messages.h:253

#110x626ecae2 in content::ResourceDispatcher::DispatchMessage(this=0x59c5b458, message=...)

at../../content/child/resource_dispatcher.cc:613

#120x626eda00 in OnMessageReceived (message=..., this=0x59c5b458)

at../../content/child/resource_dispatcher.cc:305

#13content::ResourceDispatcher::OnMessageReceived (this=0x59c5b458,message=...)

at../../content/child/resource_dispatcher.cc:268

#140x626db59e in content::ChildThread::OnMessageReceived(this=0x59bc231c, msg=...)

at../../content/child/child_thread.cc:314

#150x61af431a in IPC::ChannelProxy::Context::OnDispatchMessage(this=0x59bc2580, message=...)

at../../ipc/ipc_channel_proxy.cc:264

#160x61af377a in Run (a1=..., object=<optimized out>,this=0x64e0ab60)

at../../base/bind_internal.h:190

#17MakeItSo (a2=..., runnable=..., a1=<optimized out>) at../../base/bind_internal.h:898

#18base::internal::Invoker<2,base::internal::BindState<base::internal::RunnableAdapter<void(IPC::ChannelProxy::Context::*)(IPC::Message const&)>, void(IPC::ChannelProxy::Context*, IPC::Message const&), void (I

econst&)>::Run(base::internal::BindStateBase*)(base=0x67906e80) at ../../base/bind_internal.h:1253

#190x61b5ce40 in Run (this=0x64e0ac38) at ../../base/callback.h:396

#20base::MessageLoop::RunTask (this=0x64e0acc0, pending_task=...)

at../../base/message_loop/message_loop.cc:482

#210x61b5d33a in base::MessageLoop::DeferOrRunPendingTask(this=0x64e0acc0, pending_task=...)

at../../base/message_loop/message_loop.cc:494

#220x61b5d66c in DoWork (this=<optimized out>) at../../base/message_loop/message_loop.cc:608

#23base::MessageLoop::DoWork (this=0x64e0acc0) at../../base/message_loop/message_loop.cc:587

#240x61b5da86 in base::MessagePumpDefault::Run (this=0x59befeb8,delegate=0x64e0acc0)

at../../base/message_loop/message_pump_default.cc:32

#250x61b5d08a in base::MessageLoop::RunInternal (this=0x64e0acc0)

at../../base/message_loop/message_loop.cc:436

#260x61b65572 in base::RunLoop::Run (this=0x64e0aca0) at../../base/run_loop.cc:45

#270x61b5c8f8 in base::MessageLoop::Run (this=<optimized out>)

at../../base/message_loop/message_loop.cc:307

#280x61b6e86a in base::Thread::ThreadMain (this=0x1) at../../base/threading/thread.cc:203

#290x61b6c4a6 in base::(anonymous namespace)::ThreadFunc(params=<optimized out>)

at../../base/threading/platform_thread_posix.cc:80

#300x40104a5c in __thread_entry () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#310x40104bd8 in pthread_create () from/tmp/tshao-adb-gdb-libs/system/lib/libc.so

#320x00000000 in ?? ()

 

 

那么Frame::createView干了什么:

->Frame::createView(),创建FrameView.

→ 调用如下:

FrameView::create(),建立FrameView

ownerRenderer()->setWidget(frameView);ownerRender其实是HTMLFrameOwnerElement->render(),会得到一个RenderPart,然后RenderPart->setWidget()相当于告诉该render以后向哪里绘制。HTMLFrameOwnerElement是建立childFrame时传进来的,对应本frame的HTMLElement.由于此时.当建立mainframe时,HTMLFrameOwnerElement就是空的。

 

————————————————
版权声明:本文为CSDN博主「csshell2002」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/csshell2002/article/details/48312337

 

RenderFrame关系 

  1. 拿到 RenderFrameImpl, routing id

 RenderFrame* render_frame

  1. 拿到 WebLocalFrame

web_frame->GetDocument().GetFrame()

 

posted @ 2021-03-31 16:05  Bigben  阅读(1183)  评论(0编辑  收藏  举报