Index: Source/core/loader/FrameLoader.cpp |
diff --git a/Source/core/loader/FrameLoader.cpp b/Source/core/loader/FrameLoader.cpp |
index 304c371f5110d69c71512192e838c482890aecb1..88d994da3e9427334ea4f709df7f5ff61c5bf3d1 100644 |
--- a/Source/core/loader/FrameLoader.cpp |
+++ b/Source/core/loader/FrameLoader.cpp |
@@ -267,6 +267,12 @@ void FrameLoader::didExplicitOpen() |
m_frame->navigationScheduler().cancel(); |
} |
+void FrameLoader::didStartForFrame(DocumentLoader* loader) |
+{ |
+ if (m_state == FrameStateProvisional && loader == m_provisionalDocumentLoader.get()) |
+ stopDocumentLoaders(); |
+} |
+ |
void FrameLoader::clear() |
{ |
if (m_stateMachine.creatingInitialEmptyDocument()) |
@@ -768,6 +774,12 @@ void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, con |
void FrameLoader::stopAllLoaders() |
{ |
+ stopProvisionalLoaders(); |
+ stopDocumentLoaders(); |
+} |
+ |
+void FrameLoader::stopProvisionalLoaders() |
+{ |
if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal) |
return; |
@@ -781,25 +793,46 @@ void FrameLoader::stopAllLoaders() |
m_inStopAllLoaders = true; |
- for (RefPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) |
- child->loader().stopAllLoaders(); |
- if (m_provisionalDocumentLoader) |
+ if (m_provisionalDocumentLoader) { |
m_provisionalDocumentLoader->stopLoading(); |
- if (m_documentLoader) |
- m_documentLoader->stopLoading(); |
- |
- if (m_provisionalDocumentLoader) |
m_provisionalDocumentLoader->detachFromFrame(); |
+ } |
+ |
m_provisionalDocumentLoader = 0; |
- m_checkTimer.stop(); |
+ m_inStopAllLoaders = false; |
+ |
+ if (m_state == FrameStateProvisional) |
+ m_client->didStopActiveLoader(); |
+} |
+ |
+void FrameLoader::stopDocumentLoaders() |
+{ |
+ if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal) |
+ return; |
+ |
+ // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this. |
+ if (m_inStopAllLoaders) |
+ return; |
+ |
+ // Calling stopLoading() on the provisional document loader can blow away |
+ // the frame from underneath. |
+ RefPtr<Frame> protect(m_frame); |
+ |
+ m_inStopAllLoaders = true; |
+ |
+ for (RefPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) |
+ child->loader().stopAllLoaders(); |
+ |
+ if (m_documentLoader) |
+ m_documentLoader->stopLoading(); |
m_inStopAllLoaders = false; |
// detachFromParent() can be called multiple times on same Frame, which |
// means we may no longer have a FrameLoaderClient to talk to. |
if (m_client) |
- m_client->didStopAllLoaders(); |
+ m_client->didStopActiveLoader(); |
} |
void FrameLoader::didAccessInitialDocument() |
@@ -1292,8 +1325,7 @@ void FrameLoader::loadWithNavigationAction(const NavigationAction& action, Frame |
return; |
} |
- // A new navigation is in progress, so don't clear the history's provisional item. |
- stopAllLoaders(); |
+ stopProvisionalLoaders(); |
// <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders() |
// might detach the current FrameLoader, in which case we should bail on this newly defunct load. |