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对应整个网页么?
创建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的client是RenderFrameImpl.
WebFrame,WebLocalFrame可以看作是把Frame,LocalFrame的内容包了一下。
WebFrame,WebLocalFrame都是blinknamespace的。
Frame,LocalFrame都是webCorenamespace的。
加载网页时,是调用WebFrame的loadrequest()函数。
进而会触发FrameLoader的一系列操作。