diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
commit | 284837daa07b29d6a63a748544a90b1f5842ac5c (patch) | |
tree | ecd258180bde91fe741e0cfd2638beb3c6da7e8e /Source/WebCore/loader/FrameLoader.cpp | |
parent | 2e2ba8ff45915f40ed3e014101269c175f2a89a0 (diff) | |
download | qtwebkit-284837daa07b29d6a63a748544a90b1f5842ac5c.tar.gz |
Imported WebKit commit 68645295d2e3e09af2c942f092556f06aa5f8b0d (http://svn.webkit.org/repository/webkit/trunk@128073)
New snapshot
Diffstat (limited to 'Source/WebCore/loader/FrameLoader.cpp')
-rw-r--r-- | Source/WebCore/loader/FrameLoader.cpp | 92 |
1 files changed, 67 insertions, 25 deletions
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp index ca9ff0947..ff9a173b2 100644 --- a/Source/WebCore/loader/FrameLoader.cpp +++ b/Source/WebCore/loader/FrameLoader.cpp @@ -77,7 +77,6 @@ #include "Logging.h" #include "MIMETypeRegistry.h" #include "MainResourceLoader.h" -#include "MemoryInstrumentation.h" #include "Page.h" #include "PageCache.h" #include "PageTransitionEvent.h" @@ -99,6 +98,7 @@ #include "SerializedScriptValue.h" #include "Settings.h" #include "TextResourceDecoder.h" +#include "WebCoreMemoryInstrumentation.h" #include "WindowFeatures.h" #include "XMLDocumentParser.h" #include <wtf/CurrentTime.h> @@ -165,6 +165,43 @@ static bool isDocumentSandboxed(Frame* frame, SandboxFlags mask) return frame->document() && frame->document()->isSandboxed(mask); } +class FrameLoader::FrameProgressTracker { +public: + static PassOwnPtr<FrameProgressTracker> create(Frame* frame) { return adoptPtr(new FrameProgressTracker(frame)); } + ~FrameProgressTracker() + { + ASSERT(!m_inProgress || m_frame->page()); + if (m_inProgress) + m_frame->page()->progress()->progressCompleted(m_frame); + } + + void progressStarted() + { + ASSERT(m_frame->page()); + if (!m_inProgress) + m_frame->page()->progress()->progressStarted(m_frame); + m_inProgress = true; + } + + void progressCompleted() + { + ASSERT(m_inProgress); + ASSERT(m_frame->page()); + m_inProgress = false; + m_frame->page()->progress()->progressCompleted(m_frame); + } + +private: + FrameProgressTracker(Frame* frame) + : m_frame(frame) + , m_inProgress(false) + { + } + + Frame* m_frame; + bool m_inProgress; +}; + FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) : m_frame(frame) , m_client(client) @@ -228,6 +265,7 @@ void FrameLoader::init() m_didCallImplicitClose = true; m_networkingContext = m_client->createNetworkingContext(); + m_progressTracker = FrameProgressTracker::create(m_frame); } void FrameLoader::setDefersLoading(bool defers) @@ -680,7 +718,7 @@ void FrameLoader::checkCompleted() m_shouldCallCheckCompleted = false; if (m_frame->view()) - m_frame->view()->checkStopDelayingDeferredRepaints(); + m_frame->view()->checkFlushDeferredRepaintsAfterLoadComplete(); // Have we completed before? if (m_isComplete) @@ -715,6 +753,9 @@ void FrameLoader::checkCompleted() completed(); if (m_frame->page()) checkLoadComplete(); + + if (m_frame->view()) + m_frame->view()->checkFlushDeferredRepaintsAfterLoadComplete(); } void FrameLoader::checkTimerFired(Timer<FrameLoader>*) @@ -1087,8 +1128,7 @@ void FrameLoader::prepareForHistoryNavigation() void FrameLoader::prepareForLoadStart() { - if (Page* page = m_frame->page()) - page->progress()->progressStarted(m_frame); + m_progressTracker->progressStarted(); m_client->dispatchDidStartProvisionalLoad(); // Notify accessibility. @@ -1577,24 +1617,21 @@ void FrameLoader::setDocumentLoader(DocumentLoader* loader) m_client->prepareForDataSourceReplacement(); detachChildren(); + + // detachChildren() can trigger this frame's unload event, and therefore + // script can run and do just about anything. For example, an unload event that calls + // document.write("") on its parent frame can lead to a recursive detachChildren() + // invocation for this frame. In that case, we can end up at this point with a + // loader that hasn't been deleted but has been detached from its frame. Such a + // DocumentLoader has been sufficiently detached that we'll end up in an inconsistent + // state if we try to use it. + if (loader && !loader->frame()) + return; + if (m_documentLoader) m_documentLoader->detachFromFrame(); m_documentLoader = loader; - - // The following abomination is brought to you by the unload event. - // The detachChildren() call above may trigger a child frame's unload event, - // which could do something obnoxious like call document.write("") on - // the main frame, which results in detaching children while detaching children. - // This can cause the new m_documentLoader to be detached from its Frame*, but still - // be alive. To make matters worse, DocumentLoaders with a null Frame* aren't supposed - // to happen when they're still alive (and many places below us on the stack think the - // DocumentLoader is still usable). Ergo, we reattach loader to its Frame, and pretend - // like nothing ever happened. - if (m_documentLoader && !m_documentLoader->frame()) { - ASSERT(!m_documentLoader->isLoading()); - m_documentLoader->setFrame(m_frame); - } } void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader) @@ -1646,8 +1683,7 @@ void FrameLoader::setState(FrameState newState) void FrameLoader::clearProvisionalLoad() { setProvisionalDocumentLoader(0); - if (Page* page = m_frame->page()) - page->progress()->progressCompleted(m_frame); + m_progressTracker->progressCompleted(); setState(FrameStateComplete); } @@ -1769,6 +1805,12 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) setDocumentLoader(m_provisionalDocumentLoader.get()); setProvisionalDocumentLoader(0); + + if (pdl != m_documentLoader) { + ASSERT(m_state == FrameStateComplete); + return; + } + setState(FrameStateCommittedPage); #if ENABLE(TOUCH_EVENTS) @@ -2123,9 +2165,8 @@ void FrameLoader::checkLoadCompleteForThisFrame() return; if (!settings->needsDidFinishLoadOrderQuirk()) { + m_progressTracker->progressCompleted(); if (Page* page = m_frame->page()) { - page->progress()->progressCompleted(m_frame); - if (m_frame == page->mainFrame()) page->resetRelevantPaintedObjectCounter(); } @@ -2143,9 +2184,8 @@ void FrameLoader::checkLoadCompleteForThisFrame() } if (settings->needsDidFinishLoadOrderQuirk()) { + m_progressTracker->progressCompleted(); if (Page* page = m_frame->page()) { - page->progress()->progressCompleted(m_frame); - if (m_frame == page->mainFrame()) page->resetRelevantPaintedObjectCounter(); } @@ -2369,6 +2409,8 @@ void FrameLoader::detachFromParent() detachViewsAndDocumentLoader(); + m_progressTracker.clear(); + if (Frame* parent = m_frame->tree()->parent()) { parent->loader()->closeAndRemoveChild(m_frame); parent->loader()->scheduleCheckCompleted(); @@ -3235,7 +3277,7 @@ NetworkingContext* FrameLoader::networkingContext() const void FrameLoader::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { - MemoryClassInfo info(memoryObjectInfo, this, MemoryInstrumentation::Loader); + MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Loader); info.addInstrumentedMember(m_documentLoader); info.addInstrumentedMember(m_provisionalDocumentLoader); info.addInstrumentedMember(m_policyDocumentLoader); |