Chromium Code Reviews| Index: third_party/WebKit/Source/core/loader/FrameLoader.cpp |
| diff --git a/third_party/WebKit/Source/core/loader/FrameLoader.cpp b/third_party/WebKit/Source/core/loader/FrameLoader.cpp |
| index 1b97f12d7356eb16609dd82bf054464bb0442093..16ed06b1b2f3a6d4081f5eb3481fe051d559aebe 100644 |
| --- a/third_party/WebKit/Source/core/loader/FrameLoader.cpp |
| +++ b/third_party/WebKit/Source/core/loader/FrameLoader.cpp |
| @@ -189,8 +189,7 @@ FrameLoader::FrameLoader(LocalFrame* frame) |
| &FrameLoader::checkTimerFired), |
| m_forcedSandboxFlags(SandboxNone), |
| m_dispatchingDidClearWindowObjectInMainWorld(false), |
| - m_protectProvisionalLoader(false), |
| - m_isNavigationHandledByClient(false) { |
| + m_protectProvisionalLoader(false) { |
| DCHECK(m_frame); |
| TRACE_EVENT_OBJECT_CREATED_WITH_ID("loading", "FrameLoader", this); |
| takeObjectSnapshot(); |
| @@ -703,8 +702,7 @@ static bool shouldSendFinishNotification(LocalFrame* frame) { |
| return true; |
| } |
| -static bool shouldSendCompleteNotification(LocalFrame* frame, |
| - bool isNavigationHandledByClient) { |
| +static bool shouldSendCompleteNotification(LocalFrame* frame) { |
| // FIXME: We might have already sent stop notifications and be re-completing. |
| if (!frame->isLoading()) |
| return false; |
| @@ -744,7 +742,7 @@ void FrameLoader::checkCompleted() { |
| return; |
| } |
| - if (shouldSendCompleteNotification(m_frame, m_isNavigationHandledByClient)) { |
| + if (shouldSendCompleteNotification(m_frame)) { |
| m_progressTracker->progressCompleted(); |
| // Retry restoring scroll offset since finishing loading disables content |
| // size clamping. |
| @@ -1241,13 +1239,6 @@ void FrameLoader::stopAllLoaders() { |
| m_inStopAllLoaders = true; |
| - if (m_isNavigationHandledByClient) { |
|
Nate Chapin
2017/02/24 23:42:06
Because we know have a dummy DocumentLoader for th
clamy
2017/03/02 14:37:18
Acknowledged.
|
| - client()->dispatchDidFailProvisionalLoad( |
| - ResourceError::cancelledError(String()), StandardCommit); |
| - } |
| - |
| - clearNavigationHandledByClient(); |
| - |
| for (Frame* child = m_frame->tree().firstChild(); child; |
| child = child->tree().nextSibling()) { |
| if (child->isLocalFrame()) |
| @@ -1379,10 +1370,7 @@ void FrameLoader::commitProvisionalLoad() { |
| client()->transitionToCommittedForNewPage(); |
| - // PlzNavigate: We need to ensure that script initiated navigations are |
| - // honored. |
| - if (!m_isNavigationHandledByClient) |
|
Nate Chapin
2017/02/24 23:42:06
I'm not sure this was right. If we committed a loa
|
| - m_frame->navigationScheduler().cancel(); |
| + m_frame->navigationScheduler().cancel(); |
| m_frame->editor().clearLastEditCommand(); |
| @@ -1511,6 +1499,8 @@ void FrameLoader::loadFailed(DocumentLoader* loader, |
| HistoryCommitType historyCommitType = |
| loadTypeToCommitType(loader->loadType()); |
| if (loader == m_provisionalDocumentLoader) { |
| + if (!m_provisionalDocumentLoader->didStart()) |
| + InspectorInstrumentation::frameClearedScheduledClientNavigation(m_frame); |
| m_provisionalDocumentLoader->setSentDidFinishLoad(); |
| client()->dispatchDidFailProvisionalLoad(error, historyCommitType); |
| if (loader != m_provisionalDocumentLoader) |
| @@ -1622,7 +1612,7 @@ bool FrameLoader::shouldClose(bool isReload) { |
| return shouldClose; |
| } |
| -bool FrameLoader::shouldContinueForNavigationPolicy( |
| +NavigationPolicy FrameLoader::shouldContinueForNavigationPolicy( |
| const ResourceRequest& request, |
| const SubstituteData& substituteData, |
| DocumentLoader* loader, |
| @@ -1634,7 +1624,7 @@ bool FrameLoader::shouldContinueForNavigationPolicy( |
| HTMLFormElement* form) { |
| // Don't ask if we are loading an empty URL. |
| if (request.url().isEmpty() || substituteData.isValid()) |
| - return true; |
| + return NavigationPolicyCurrentTab; |
| // If we're loading content into |m_frame| (NavigationPolicyCurrentTab), check |
| // against the parent's Content Security Policy and kill the load if that |
| @@ -1652,7 +1642,7 @@ bool FrameLoader::shouldContinueForNavigationPolicy( |
| // page load. |
| m_frame->document()->enforceSandboxFlags(SandboxOrigin); |
| m_frame->owner()->dispatchLoad(); |
| - return false; |
| + return NavigationPolicyIgnore; |
| } |
| } |
| } |
| @@ -1662,48 +1652,36 @@ bool FrameLoader::shouldContinueForNavigationPolicy( |
| if (isFormSubmission && |
| !m_frame->document()->contentSecurityPolicy()->allowFormAction( |
| request.url())) |
| - return false; |
| + return NavigationPolicyIgnore; |
| bool replacesCurrentHistoryItem = |
| frameLoadType == FrameLoadTypeReplaceCurrentItem; |
| policy = client()->decidePolicyForNavigation(request, loader, type, policy, |
| replacesCurrentHistoryItem, |
| isClientRedirect, form); |
| - if (policy == NavigationPolicyCurrentTab) |
| - return true; |
| - if (policy == NavigationPolicyIgnore) |
| - return false; |
| - if (policy == NavigationPolicyHandledByClient) { |
|
Nate Chapin
2017/02/24 23:42:06
All of this case should be handling in the main st
|
| - setNavigationHandledByClient(); |
| - // Mark the frame as loading since the embedder is handling the navigation. |
| - m_progressTracker->progressStarted(frameLoadType); |
| - |
| - m_frame->navigationScheduler().cancel(); |
| - |
| - // If this is a form submit, dispatch that a form is being submitted |
| - // since the embedder is handling the navigation. |
| - if (form) |
| - client()->dispatchWillSubmitForm(form); |
| - |
| - m_frame->document()->cancelParsing(); |
| - |
| - return false; |
| + if (policy == NavigationPolicyCurrentTab || |
| + policy == NavigationPolicyIgnore || |
| + policy == NavigationPolicyHandledByClient || |
| + policy == NavigationPolicyHandledByClientForInitialHistory) { |
| + return policy; |
| } |
| + |
| if (!LocalDOMWindow::allowPopUp(*m_frame) && |
| !UserGestureIndicator::utilizeUserGesture()) |
| - return false; |
| + return NavigationPolicyIgnore; |
| client()->loadURLExternally(request, policy, String(), |
| replacesCurrentHistoryItem); |
| - return false; |
| + return NavigationPolicyIgnore; |
| } |
| -bool FrameLoader::checkLoadCanStart(FrameLoadRequest& frameLoadRequest, |
| - FrameLoadType type, |
| - NavigationPolicy navigationPolicy, |
| - NavigationType navigationType) { |
| +NavigationPolicy FrameLoader::checkLoadCanStart( |
| + FrameLoadRequest& frameLoadRequest, |
| + FrameLoadType type, |
| + NavigationPolicy navigationPolicy, |
| + NavigationType navigationType) { |
| if (m_frame->document()->pageDismissalEventBeingDispatched() != |
| Document::NoDismissal) { |
| - return false; |
| + return NavigationPolicyIgnore; |
| } |
| // Record the latest requiredCSP value that will be used when sending this |
| @@ -1712,25 +1690,12 @@ bool FrameLoader::checkLoadCanStart(FrameLoadRequest& frameLoadRequest, |
| recordLatestRequiredCSP(); |
| modifyRequestForCSP(resourceRequest, nullptr); |
| - if (!shouldContinueForNavigationPolicy( |
| - resourceRequest, frameLoadRequest.substituteData(), nullptr, |
| - frameLoadRequest.shouldCheckMainWorldContentSecurityPolicy(), |
| - navigationType, navigationPolicy, type, |
| - frameLoadRequest.clientRedirect() == |
| - ClientRedirectPolicy::ClientRedirect, |
| - frameLoadRequest.form())) { |
| - return false; |
| - } |
| - |
| - m_frame->document()->cancelParsing(); |
|
Nate Chapin
2017/02/24 23:42:06
Here and below moved in to startLoad(), since they
|
| - detachDocumentLoader(m_provisionalDocumentLoader); |
| - |
| - // beforeunload fired above, and detaching a DocumentLoader can fire events, |
| - // which can detach this frame. |
| - if (!m_frame->host()) |
| - return false; |
| - |
| - return true; |
| + return shouldContinueForNavigationPolicy( |
| + resourceRequest, frameLoadRequest.substituteData(), nullptr, |
| + frameLoadRequest.shouldCheckMainWorldContentSecurityPolicy(), |
| + navigationType, navigationPolicy, type, |
| + frameLoadRequest.clientRedirect() == ClientRedirectPolicy::ClientRedirect, |
| + frameLoadRequest.form()); |
| } |
| void FrameLoader::startLoad(FrameLoadRequest& frameLoadRequest, |
| @@ -1747,50 +1712,46 @@ void FrameLoader::startLoad(FrameLoadRequest& frameLoadRequest, |
| ? WebURLRequest::FrameTypeTopLevel |
| : WebURLRequest::FrameTypeNested); |
| - if (!checkLoadCanStart(frameLoadRequest, type, navigationPolicy, |
| - navigationType)) { |
| - if (m_isNavigationHandledByClient) { |
| - // PlzNavigate: if the navigation is a commit of a client-handled |
| - // navigation, record that there is no longer a navigation handled by the |
| - // client. |
| - if (!frameLoadRequest.resourceRequest().checkForBrowserSideNavigation()) { |
| - clearNavigationHandledByClient(); |
| - } else { |
| - DocumentLoader* loader = createDocumentLoader( |
| - resourceRequest, frameLoadRequest, type, navigationType); |
| - // PlzNavigate: If the navigation is handled by the client, then the |
| - // didFinishDocumentLoad() event occurs before the |
| - // didStartProvisionalLoad() notification which occurs after the |
| - // navigation |
| - // is committed. This causes a number of layout tests to fail. We |
| - // workaround this by invoking the didStartProvisionalLoad() |
| - // notification |
| - // here. Consumers of the didStartProvisionalLoad() notification rely on |
| - // the provisional loader and save navigation state in it. We want to |
| - // avoid |
| - // this dependency on the provisional loader. For now we create a |
| - // temporary |
| - // loader and pass it to the didStartProvisionalLoad() function. |
| - // TODO(ananta) |
| - // We should get rid of the dependency on the DocumentLoader in |
| - // consumers |
| - // of |
| - // the didStartProvisionalLoad() notification. |
| - client()->dispatchDidStartProvisionalLoad(loader); |
|
Nate Chapin
2017/02/24 23:42:06
All of this is handled in the main path below, tho
|
| - DCHECK(loader); |
| - loader->setSentDidFinishLoad(); |
| - loader->detachFromFrame(); |
| - } |
| + bool hadPlaceholderClientDocumentLoader = |
|
Nate Chapin
2017/02/24 23:42:05
I don't like this name. Suggestions welcome if you
|
| + m_provisionalDocumentLoader && !m_provisionalDocumentLoader->didStart(); |
| + navigationPolicy = checkLoadCanStart(frameLoadRequest, type, navigationPolicy, |
| + navigationType); |
| + if (navigationPolicy == NavigationPolicyIgnore) { |
| + if (hadPlaceholderClientDocumentLoader && |
| + !resourceRequest.checkForBrowserSideNavigation()) { |
| + detachDocumentLoader(m_provisionalDocumentLoader); |
| } |
| return; |
| } |
| + // For PlzNavigate placeholer DocumentLoaders, don't send failure callbacks |
| + // for a placeholder simply being replaced with a new DocumentLoader. |
| + if (hadPlaceholderClientDocumentLoader) |
| + m_provisionalDocumentLoader->setSentDidFinishLoad(); |
| + m_frame->document()->cancelParsing(); |
| + detachDocumentLoader(m_provisionalDocumentLoader); |
| + |
| + // beforeunload fired above, and detaching a DocumentLoader can fire events, |
| + // which can detach this frame. |
| + if (!m_frame->host()) |
| + return; |
| + |
| + m_progressTracker->progressStarted(type); |
| + // TODO(japhet): This case wants to flag the frame as loading and do nothing |
| + // else. It'd be nice if it could go through the placeholder DocumentLoader |
| + // path, too. |
| + if (navigationPolicy == NavigationPolicyHandledByClientForInitialHistory) |
| + return; |
| + DCHECK(navigationPolicy == NavigationPolicyCurrentTab || |
| + navigationPolicy == NavigationPolicyHandledByClient); |
| + |
| m_provisionalDocumentLoader = createDocumentLoader( |
| resourceRequest, frameLoadRequest, type, navigationType); |
| // PlzNavigate: We need to ensure that script initiated navigations are |
| // honored. |
| - if (!m_isNavigationHandledByClient) { |
| + if (!hadPlaceholderClientDocumentLoader || |
| + navigationPolicy == NavigationPolicyHandledByClient) { |
| m_frame->navigationScheduler().cancel(); |
| m_checkTimer.stop(); |
| } |
| @@ -1798,29 +1759,23 @@ void FrameLoader::startLoad(FrameLoadRequest& frameLoadRequest, |
| if (frameLoadRequest.form()) |
| client()->dispatchWillSubmitForm(frameLoadRequest.form()); |
| - bool isNavigationHandledByClient = m_isNavigationHandledByClient; |
| - // If the loader wasn't waiting for the client to handle a navigation, update |
| - // the progress tracker. Otherwise don't, as it was already notified before |
| - // sending the navigation to teh client. |
| - if (!m_isNavigationHandledByClient) |
|
Nate Chapin
2017/02/24 23:42:06
Remove the need for this if() by teaching progress
|
| - m_progressTracker->progressStarted(type); |
| - else |
| - m_isNavigationHandledByClient = false; |
| - |
| m_provisionalDocumentLoader->appendRedirect( |
| m_provisionalDocumentLoader->getRequest().url()); |
| - // TODO(ananta) |
| + // TODO(ananta): |
| // We should get rid of the dependency on the DocumentLoader in consumers of |
| // the didStartProvisionalLoad() notification. |
| client()->dispatchDidStartProvisionalLoad(m_provisionalDocumentLoader); |
| DCHECK(m_provisionalDocumentLoader); |
| - m_provisionalDocumentLoader->startLoadingMainResource(); |
| - |
| - // This should happen after the request is sent, so we don't use |
| - // clearNavigationHandledByClient() above. |
| - if (isNavigationHandledByClient) |
| + if (navigationPolicy == NavigationPolicyCurrentTab) { |
| + m_provisionalDocumentLoader->startLoadingMainResource(); |
| + // This should happen after the request is sent, so that the state |
| + // the inspector stored in the matching frameScheduledClientNavigation() |
| + // is available while sending the request. |
| InspectorInstrumentation::frameClearedScheduledClientNavigation(m_frame); |
| + } else { |
| + InspectorInstrumentation::frameScheduledClientNavigation(m_frame); |
| + } |
| takeObjectSnapshot(); |
| } |
| @@ -2028,14 +1983,4 @@ DocumentLoader* FrameLoader::createDocumentLoader( |
| return loader; |
| } |
| -void FrameLoader::setNavigationHandledByClient() { |
| - m_isNavigationHandledByClient = true; |
| - InspectorInstrumentation::frameScheduledClientNavigation(m_frame); |
| -} |
| - |
| -void FrameLoader::clearNavigationHandledByClient() { |
| - m_isNavigationHandledByClient = false; |
| - InspectorInstrumentation::frameClearedScheduledClientNavigation(m_frame); |
| -} |
| - |
| } // namespace blink |