| Index: Source/core/loader/FrameLoader.cpp
|
| diff --git a/Source/core/loader/FrameLoader.cpp b/Source/core/loader/FrameLoader.cpp
|
| index dc50a14425cea7863423ffa4dad060ba53a1865e..d518ab26c2b24d0c43b6a9ad4bac35eede00c14f 100644
|
| --- a/Source/core/loader/FrameLoader.cpp
|
| +++ b/Source/core/loader/FrameLoader.cpp
|
| @@ -442,17 +442,10 @@ void FrameLoader::loadDone()
|
| checkCompleted();
|
| }
|
|
|
| -bool FrameLoader::allChildrenAreComplete() const
|
| +static bool allDescendantsAreComplete(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)) {
|
| + if (child->isLoadingAsChild())
|
| 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 allDescendantsAreComplete(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 (!allDescendantsAreComplete(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;
|
|
|
| - // Any frame that hasn't completed yet?
|
| - if (!allChildrenAreComplete())
|
| + // We might have declined to run the load event due to an imminent content-initiated navigation.
|
| + if (!frame->document()->loadEventFinished())
|
| + return false;
|
| + return true;
|
| +}
|
| +
|
| +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)
|
|
|