zoukankan      html  css  js  c++  java
  • 走进WebKit——打开新Tab(一)

    基于 Safari

    在 WebKit2 中

    打开一个新的Tab,首先调用的

    void WebProcess::createWebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
    {
        // It is necessary to check for page existence here since during a window.open() (or targeted
        // link) the WebPage gets created both in the synchronous handler and through the normal way. 
        HashMap<uint64_t, RefPtr<WebPage> >::AddResult result = m_pageMap.add(pageID, 0);
        if (result.isNewEntry) {
            ASSERT(!result.iterator->value);
            result.iterator->value = WebPage::create(pageID, parameters);

    创建WebPage

     

     

    PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)
    {
        RefPtr<WebPage> page = adoptRef(new WebPage(pageID, parameters));

    接下来进入 WebPage 的构造函数 ,构造函数中创建 PageClients, WebChromeClient, WebContextMenuClient, WebEditorClient, WebDragClient, WebBackForwardListProxy, WebInspectorClient, WebPluginClient 以及Page 对象等。

     

    WebPage::WebPage(uint64_t pageID, const WebPageCreationParameters& parameters)
        Settings::setDefaultMinDOMTimerInterval(0.004);
        Page::PageClients pageClients;
        pageClients.chromeClient = new WebChromeClient(this);
        pageClients.contextMenuClient = new WebContextMenuClient(this);
        pageClients.editorClient = new WebEditorClient(this);
        pageClients.dragClient = new WebDragClient(this);
        pageClients.backForwardClient = WebBackForwardListProxy::create(this);
        m_inspectorClient = new WebInspectorClient(this);
        pageClients.inspectorClient = m_inspectorClient;
       pageClients.plugInClient = new WebPlugInClient(this);
        m_page = adoptPtr(new Page(pageClients));
    ...


    Page 的构造函数中创建 Chrome 对象,DragCaretController对象,FocusController,ContextMenuController,

    InspectorController,Settings 等

    //WebCore

     

    Page::Page(PageClients& pageClients)
        : m_chrome(Chrome::create(this, pageClients.chromeClient))
        , m_dragCaretController(DragCaretController::create())
    #if ENABLE(DRAG_SUPPORT)
        , m_dragController(DragController::create(this, pageClients.dragClient))
    #endif
        , m_focusController(FocusController::create(this))
    #if ENABLE(CONTEXT_MENUS)
        , m_contextMenuController(ContextMenuController::create(this, pageClients.contextMenuClient))
    #endif
    #if ENABLE(INSPECTOR)
        , m_inspectorController(InspectorController::create(this, pageClients.inspectorClient))
    #endif
        , m_settings(Settings::create(this))
        , m_progress(ProgressTracker::create())
        , m_backForwardController(BackForwardController::create(this, pageClients.backForwardClient))


    Page 对象创建完之后 WebPage 还会接着创建以下对象:

    //WebKit2

     

    #if ENABLE(GEOLOCATION)
        WebCore::provideGeolocationTo(m_page.get(), new WebGeolocationClient(this));
    #endif
    #if ENABLE(NETWORK_INFO)
        WebCore::provideNetworkInfoTo(m_page.get(), new WebNetworkInfoClient(this));
    #endif
    #if ENABLE(VIBRATION)
        WebCore::provideVibrationTo(m_page.get(), new WebVibrationClient(this));
    #endif
    #if ENABLE(PROXIMITY_EVENTS)
        WebCore::provideDeviceProximityTo(m_page.get(), new WebDeviceProximityClient(this));
    #endif
    
        m_page->setCanStartMedia(false);
        m_mayStartMediaWhenInWindow = parameters.mayStartMediaWhenInWindow;
    
        m_pageGroup = WebProcess::shared().webPageGroup(parameters.pageGroupData);
        m_page->setGroupName(m_pageGroup->identifier());
        m_page->setDeviceScaleFactor(parameters.deviceScaleFactor);
    
        m_drawingArea = DrawingArea::create(this, parameters);
        m_drawingArea->setPaintingEnabled(false);
    
        updatePreferences(parameters.store);
        platformInitialize();
    
        m_mainFrame = WebFrame::createMainFrame(this);
    

    这里先看一下 WebFrame::createMainFrame(this), 创建 WebFrame,并对 frame做初始化。

     

    PassRefPtr<WebFrame> WebFrame::createMainFrame(WebPage* page)
    {
        RefPtr<WebFrame> frame = create();
    
        page->send(Messages::WebPageProxy::DidCreateMainFrame(frame->frameID()));
    
        frame->init(page, String(), 0);
    
        return frame.release(); // 这个 release 只是减少了引用计数
    }

    frame 的 init 过程会创建 Frame对象

     

    void WebFrame::init(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
    {
        RefPtr<Frame> frame = Frame::create(page->corePage(), ownerElement, &m_frameLoaderClient);


    把创建的Frame 设定成 MainFrame,关于MainFrame,Frame,Page,Document 的关系,参看《走进WebKit--开篇

    //WebCore  

     

    PassRefPtr<Frame> Frame::create(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* client)
    {
        RefPtr<Frame> frame = adoptRef(new Frame(page, ownerElement, client));
        if (!ownerElement)
            page->setMainFrame(frame);
        return frame.release();
    }



    在 Frame 的构造函数中依次给成员变量赋值 

     

            Page* m_page; 

            mutable FrameTree m_treeNode; //用来协助管理父帧和子帧,常见的是 main frame 和 iframe之间

            mutable FrameLoader m_loader; // 用来完成 Frame 的加载

            mutable NavigationScheduler m_navigationScheduler; // 页面跳转调度器

            HTMLFrameOwnerElement* m_ownerElement;

            RefPtr<FrameView> m_view; // 用于Frame 的排版

            RefPtr<Document> m_doc; // 用来管理DOM节点

            ScriptController m_script; // 脚本控制器

            mutable Editor m_editor; //处理页面编辑

            mutable FrameSelection m_selection; // 选取

            mutable EventHandler m_eventHandler; //处理鼠标事件,按键事件等 UI 交互事件

            mutable AnimationController m_animationController;

     

    inline Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient)
        : m_page(page)
        , m_treeNode(this, parentFromOwnerElement(ownerElement))
        , m_loader(this, frameLoaderClient) //
        , m_navigationScheduler(this) //
        , m_ownerElement(ownerElement)
        , m_script(this)
        , m_editor(this) //
        , m_selection(this) //
        , m_eventHandler(this) //
        , m_animationController(this)
        , m_pageZoomFactor(parentPageZoomFactor(this))
        , m_textZoomFactor(parentTextZoomFactor(this))
    #if ENABLE(ORIENTATION_EVENTS)
        , m_orientation(0)
    #endif
        , m_inViewSourceMode(false)
        , m_activeDOMObjectsAndAnimationsSuspendedCount(0)
    {
        ASSERT(page);
        AtomicString::init();
        HTMLNames::init();
        QualifiedName::init();
        MediaFeatureNames::init();
        SVGNames::init();
        XLinkNames::init();
        MathMLNames::init();
        XMLNSNames::init();
        XMLNames::init();
        WebKitFontFamilyNames::init();
    


    FrameLoader 构造函数中初始化成员变量。

     

    FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
        : m_frame(frame)
        , m_client(client)
        , m_policyChecker(frame)
        , m_history(frame)
        , m_notifer(frame)
        , m_subframeLoader(frame)
        , m_icon(frame)
        , m_mixedContentChecker(frame)
        , m_state(FrameStateProvisional)
        , m_loadType(FrameLoadTypeStandard)
        , m_delegateIsHandlingProvisionalLoadError(false)
        , m_quickRedirectComing(false)
        , m_sentRedirectNotification(false)
        , m_inStopAllLoaders(false)
        , m_isExecutingJavaScriptFormAction(false)
        , m_didCallImplicitClose(true)
        , m_wasUnloadEventEmitted(false)
        , m_pageDismissalEventBeingDispatched(NoDismissal)
        , m_isComplete(false)
        , m_needsClear(false)
        , m_checkTimer(this, &FrameLoader::checkTimerFired)
        , m_shouldCallCheckCompleted(false)
        , m_shouldCallCheckLoadComplete(false)
        , m_opener(0)
    #if PLATFORM(CHROMIUM)
        , m_didAccessInitialDocument(false)
        , m_didAccessInitialDocumentTimer(this, &FrameLoader::didAccessInitialDocumentTimerFired)
    #endif
        , m_didPerformFirstNavigation(false)
        , m_loadingFromCachedPage(false)
        , m_suppressOpenerInNewFrame(false)
        , m_forcedSandboxFlags(SandboxNone)
    {
    }

    WebFrame::init 完成后面会调用 frame->init() 进行初始化动作

    void WebFrame::init(WebPage* page, const String& frameName, HTMLFrameOwnerElement* ownerElement)
    {
        RefPtr<Frame> frame = Frame::create(page->corePage(), ownerElement, &m_frameLoaderClient);
        m_coreFrame = frame.get();
    
        frame->tree()->setName(frameName);
    
        if (ownerElement) {
            ASSERT(ownerElement->document()->frame());
            ownerElement->document()->frame()->tree()->appendChild(frame);
        }
    
        frame->init();
    }

    其实只做了一件事情,初始化 FrameLoader

     

        inline void Frame::init()
        {
            m_loader.init();
        }
    void FrameLoader::init()
    {
        // This somewhat odd set of steps gives the frame an initial empty document.
        setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, emptyString())), SubstituteData()).get());
        setProvisionalDocumentLoader(m_policyDocumentLoader.get());
        m_provisionalDocumentLoader->startLoadingMainResource();
        m_frame->document()->cancelParsing();
        m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
    
        m_networkingContext = m_client->createNetworkingContext();
        m_progressTracker = FrameProgressTracker::create(m_frame);
    }

     创建DocumentLoader过程中会创建 CachedResourceLoader,DocumentWriter 等

    刚创建的 DocumentLoader 会被 setPolicyDocumentLoader 设定成 m_policyDocumentLoader,然后被

    setProvisionalDocumentLoader设定为 m_provisionalDocumentLoader

     FrameLoader 维护了三个 DocumentLoader 对象分别对应三个不同的阶段。在后面加载过程中再做分析

       RefPtr<DocumentLoader> m_documentLoader;

       RefPtr<DocumentLoader> m_provisionalDocumentLoader;

       RefPtr<DocumentLoader> m_policyDocumentLoader;

    接下来的  m_provisionalDocumentLoader->startLoadingMainResource(); 实际上只判断是不是加载空页面就返回了。

     

       if (maybeLoadEmpty())
            return;

    maybeLoadEmpty()中关键 call stack 如下: maybeLoadEmpty() 做一些处理之后,调用 finishedLoading(),  finishedLoading()  调用 commitIfReady() ,在 commitProvisionalLoad 中完成提交。

     

     

     frame #0: 0x0000000103e402e5 WebCore`WebCore::FrameLoader::transitionToCommitted(this=0x000000010c121080, cachedPage=0x00007fff5fbfc5e8) 
        frame #1: WebCore`WebCore::FrameLoader::commitProvisionalLoad(this=0x000000010c121080) 
        frame #2: WebCore`WebCore::DocumentLoader::commitIfReady(this=0x000000010b94d400) 
        frame #3: WebCore`WebCore::DocumentLoader::finishedLoading(this=0x000000010b94d400)
        frame #4: WebCore`WebCore::DocumentLoader::maybeLoadEmpty(this=0x000000010b94d400) 

    在 transitionToCommitted 中把前面 m_provisionalDocumentLoader 赋值给 m_documentLoader, 将 m_provisionalDocumentLoader 置空,将 FrameLoader的 

    m_state 从初始化时的 FrameStateProvisional 设定成FrameStateCommittedPage, DocumentWriter 的MIMEType设定成 “text/html”, 此时 DocumentStateMachine 还是CreatingInitialEmptyDocument 状态 

    m_committed = true;

     

     

        setDocumentLoader(m_provisionalDocumentLoader.get());
        setProvisionalDocumentLoader(0);
        setState(FrameStateCommittedPage);
        m_documentLoader->writer()->setMIMEType(dl->responseMIMEType()); 
        if (m_stateMachine.creatingInitialEmptyDocument())
            return;

    返回到 finishedLoading() 中

     

    void DocumentLoader::finishedLoading()
    {
        commitIfReady();
        if (!frameLoader())
            return;
    
        if (!maybeCreateArchive()) {
            // If this is an empty document, it will not have actually been created yet. Commit dummy data so that
            // DocumentWriter::begin() gets called and creates the Document.
            if (!m_gotFirstByte)
                commitData(0, 0);
            frameLoader()->client()->finishedLoading(this);
        }
    
        m_writer.end();
        if (!m_mainDocumentError.isNull())
            return;
        clearMainResourceLoader();
        if (!frameLoader()->stateMachine()->creatingInitialEmptyDocument())
            frameLoader()->checkLoadComplete();
    }
    


    注意上面的注释,正是初始化过程的情况。 commitData(0,0) 会调用到DocumentWriter ::begin(), 在里面创建 Document 和 DOMWindow,从Document中获取DocumentParser,将WriterState 设定为 StartedWritingState

    commitData 之后就会调用 

    frameLoader()->client()->finishedLoading(this);
    m_writer.end();

    m_writer.end() 中会 把 WriterState 改成 FinishedWritingState,然后将 DocumentWriter 维护的DocumentParser 对象清理掉,

    void DocumentWriter::end()
    {
        ASSERT(m_frame->page());
        ASSERT(m_frame->document());
    
        // The parser is guaranteed to be released after this point. begin() would
        // have to be called again before we can start writing more data.
        m_state = FinishedWritingState;
    
        // http://bugs.webkit.org/show_bug.cgi?id=10854
        // The frame's last ref may be removed and it can be deleted by checkCompleted(), 
        // so we'll add a protective refcount
        RefPtr<Frame> protector(m_frame);
    
        if (!m_parser)
            return;
        // FIXME: m_parser->finish() should imply m_parser->flush().
        m_parser->flush(this);
        if (!m_parser)
            return;
        m_parser->finish();
        m_parser = 0;
    }

    至此 DocumentWriter 的状态完成跃迁:

    DocumentWriter()begin, end

    |   |  |

    WriterState : NotStartedWritingState -> StartedWritingState -> FinishedWritingState


    
    
  • 相关阅读:
    grunt in webstorm
    10+ Best Responsive HTML5 AngularJS Templates
    响应式布局
    responsive grid
    responsive layout
    js event bubble and capturing
    Understanding Service Types
    To add private variable to this Javascript literal object
    Centering HTML elements larger than their parents
    java5 新特性
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/2995392.html
Copyright © 2011-2022 走看看