Index: Source/core/loader/FrameLoader.cpp |
diff --git a/Source/core/loader/FrameLoader.cpp b/Source/core/loader/FrameLoader.cpp |
index dc50a14425cea7863423ffa4dad060ba53a1865e..c941ae3d072a7e07e6e621c395bd56346169bbc1 100644 |
--- a/Source/core/loader/FrameLoader.cpp |
+++ b/Source/core/loader/FrameLoader.cpp |
@@ -247,10 +247,10 @@ bool FrameLoader::closeURL() |
void FrameLoader::didExplicitOpen() |
{ |
// Calling document.open counts as committing the first real document load. |
- if (!m_stateMachine.committedFirstRealDocumentLoad()) { |
+ if (!m_stateMachine.committedFirstRealDocumentLoad()) |
m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad); |
- m_progressTracker->progressStarted(); |
- } |
+ |
+ m_progressTracker->progressStarted(); |
Nate Chapin
2015/01/12 18:39:30
I should probably explicitly mention what this is
dcheng
2015/01/13 00:20:52
Does this mean a document.write() with no document
Nate Chapin
2015/01/13 21:13:00
I just tested it, and yes :(
Updated this patch t
|
// Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results |
// from a subsequent window.document.open / window.document.write call. |
@@ -442,17 +442,10 @@ void FrameLoader::loadDone() |
checkCompleted(); |
} |
-bool FrameLoader::allChildrenAreComplete() const |
+static bool allChildrenAreComplete(Frame* frame) |
{ |
- for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) { |
- if (!child->isLocalFrame()) { |
- if (!child->checkLoadComplete()) { |
- return false; |
- } |
- continue; |
- } |
- LocalFrame* frame = toLocalFrame(child); |
- if (!frame->document()->isLoadCompleted() || frame->loader().m_provisionalDocumentLoader) |
+ for (Frame* child = frame->tree().firstChild(); child; child = child->tree().traverseNext(frame)) { |
dcheng
2015/01/09 22:52:25
I assume you intentionally changed this from nextS
Nate Chapin
2015/01/12 18:39:30
Done.
|
+ if (child->isLoading()) |
return false; |
} |
return true; |
@@ -461,44 +454,57 @@ bool FrameLoader::allChildrenAreComplete() const |
bool FrameLoader::allAncestorsAreComplete() const |
{ |
for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree().parent()) { |
- if (ancestor->isLocalFrame()) { |
- if (!toLocalFrame(ancestor)->document()->loadEventFinished()) |
- return false; |
- } else { |
- if (!ancestor->checkLoadComplete()) { |
- return false; |
- } |
- } |
- |
+ if (ancestor->isLoading()) |
+ return false; |
} |
return true; |
} |
-void FrameLoader::checkCompleted() |
+static bool shouldComplete(Document* document) |
{ |
- RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get()); |
+ if (document->parsing() || document->isInDOMContentLoaded()) |
+ return false; |
+ if (!document->haveImportsLoaded()) |
+ return false; |
+ if (document->fetcher()->requestCount()) |
+ return false; |
+ if (document->isDelayingLoadEvent()) |
+ return false; |
+ return allChildrenAreComplete(document->frame()); |
+} |
- if (m_frame->document()->isLoadCompleted() && m_stateMachine.committedFirstRealDocumentLoad()) |
- return; |
+static bool shouldSendCompleteNotifications(LocalFrame* frame) |
+{ |
+ // Don't send stop notifications for inital empty documents, since they don't generate start notifications. |
+ if (!frame->loader().stateMachine()->committedFirstRealDocumentLoad()) |
+ return false; |
- // Are we still parsing? |
- if (m_frame->document()->parsing() || m_frame->document()->isInDOMContentLoaded()) |
- return; |
+ // FIXME: We might have already sent stop notifications and be re-completing. |
+ if (!frame->isLoading()) |
+ return false; |
- // Still waiting imports? |
- if (!m_frame->document()->haveImportsLoaded()) |
- return; |
+ // The readystatechanged or load event may have disconnected this frame. |
+ if (!frame->client()) |
+ return false; |
- // Still waiting for images/scripts? |
- if (m_frame->document()->fetcher()->requestCount()) |
- return; |
+ // An event might have restarted a child frame. |
+ if (!allChildrenAreComplete(frame)) |
+ return false; |
- // Still waiting for elements that don't go through a FrameLoader? |
- if (m_frame->document()->isDelayingLoadEvent()) |
- return; |
+ // An event might have restarted this frame by scheduling a new navigation. |
+ if (frame->loader().provisionalDocumentLoader()) |
+ return false; |
+ |
+ // We might have declined to run the load event due to an imminent content-initiated navigation. |
+ if (!frame->document()->loadEventFinished()) |
+ return false; |
+ return true; |
+} |
- // Any frame that hasn't completed yet? |
- if (!allChildrenAreComplete()) |
+void FrameLoader::checkCompleted() |
+{ |
+ RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get()); |
+ if (!shouldComplete(m_frame->document())) |
return; |
// OK, completed. |
@@ -514,11 +520,20 @@ void FrameLoader::checkCompleted() |
if (m_frame->view()) |
m_frame->view()->handleLoadCompleted(); |
+ if (shouldSendCompleteNotifications(m_frame)) { |
+ m_loadType = FrameLoadTypeStandard; |
+ m_progressTracker->progressCompleted(); |
+ m_frame->localDOMWindow()->finishedLoading(); |
+ |
+ // Report mobile vs. desktop page statistics. This will only report on Android. |
+ if (m_frame->isMainFrame()) |
+ m_frame->document()->viewportDescription().reportMobilePageStats(m_frame); |
+ client()->dispatchDidFinishLoad(); |
+ } |
+ |
Frame* parent = m_frame->tree().parent(); |
if (parent && parent->isLocalFrame()) |
toLocalFrame(parent)->loader().checkCompleted(); |
- if (m_frame->page()) |
- checkLoadComplete(); |
} |
void FrameLoader::checkTimerFired(Timer<FrameLoader>*) |
@@ -989,39 +1004,6 @@ FrameLoadType FrameLoader::loadType() const |
return m_loadType; |
} |
-bool FrameLoader::checkLoadCompleteForThisFrame() |
-{ |
- ASSERT(client()->hasWebView()); |
- RefPtrWillBeRawPtr<LocalFrame> protect(m_frame.get()); |
- |
- bool allChildrenAreDoneLoading = true; |
- for (RefPtrWillBeRawPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) { |
- allChildrenAreDoneLoading &= child->checkLoadComplete(); |
- } |
- if (!allChildrenAreDoneLoading) |
- return false; |
- |
- if (!m_frame->isLoading()) |
- return true; |
- if (m_provisionalDocumentLoader || !m_documentLoader) |
- return false; |
- if (!m_frame->document()->loadEventFinished()) |
- return false; |
- if (!m_stateMachine.committedFirstRealDocumentLoad()) |
- return true; |
- |
- m_progressTracker->progressCompleted(); |
- m_frame->localDOMWindow()->finishedLoading(); |
- |
- // Report mobile vs. desktop page statistics. This will only report on Android. |
- if (m_frame->isMainFrame()) |
- m_frame->document()->viewportDescription().reportMobilePageStats(m_frame); |
- |
- client()->dispatchDidFinishLoad(); |
- m_loadType = FrameLoadTypeStandard; |
- return true; |
-} |
- |
void FrameLoader::restoreScrollPositionAndViewState() |
{ |
FrameView* view = m_frame->view(); |
@@ -1069,13 +1051,6 @@ void FrameLoader::restoreScrollPositionAndViewState() |
} |
} |
-// Called every time a resource is completely loaded or an error is received. |
-void FrameLoader::checkLoadComplete() |
-{ |
- ASSERT(client()->hasWebView()); |
- m_frame->page()->mainFrame()->checkLoadComplete(); |
-} |
- |
String FrameLoader::userAgent(const KURL& url) const |
{ |
String userAgent = client()->userAgent(url); |
@@ -1132,10 +1107,7 @@ void FrameLoader::receivedMainResourceError(DocumentLoader* loader, const Resour |
m_progressTracker->progressCompleted(); |
} |
} |
- |
checkCompleted(); |
- if (m_frame->page()) |
- checkLoadComplete(); |
} |
bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url) |