summaryrefslogtreecommitdiff
path: root/Source/WebCore/loader/FrameLoader.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-09-10 19:10:20 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-09-10 19:10:20 +0200
commit284837daa07b29d6a63a748544a90b1f5842ac5c (patch)
treeecd258180bde91fe741e0cfd2638beb3c6da7e8e /Source/WebCore/loader/FrameLoader.cpp
parent2e2ba8ff45915f40ed3e014101269c175f2a89a0 (diff)
downloadqtwebkit-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.cpp92
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);