Skip to content

Commit 1a127f5

Browse files
magomezspenap
authored andcommitted
Add env var to allow keeping the existent navigation on a fragment load
Fragment navigation should be cancelled if there is ongoing navigation Fragment navigation is synchronous, while navigation is asynchronous. It can happen that fragment navigation starts when navigation is in the policy or provisional step of loading. In that case, we should cancel the requested fragment navigation and make the navigation finish.
1 parent 96cfadb commit 1a127f5

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

Source/WebCore/loader/FrameLoader.cpp

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,15 +1638,38 @@ void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& ref
16381638

16391639
if (!dispatchNavigateEvent(newURL, newLoadType, action.downloadAttribute(), historyHandling, true))
16401640
return;
1641+
static bool keepNavigationOnFragmentLoad = false;
1642+
static bool keepNavigationOnFragmentLoadInitialized = false;
1643+
1644+
if (!keepNavigationOnFragmentLoadInitialized) {
1645+
keepNavigationOnFragmentLoad = !!getenv("WPE_KEEP_NAVIGATION_ON_FRAGMENT_LOAD");
1646+
keepNavigationOnFragmentLoadInitialized = true;
1647+
}
16411648

16421649
oldDocumentLoader->setTriggeringAction(WTFMove(action));
16431650
oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
1644-
policyChecker().stopCheck();
1651+
auto loadType = policyChecker().loadType();
1652+
bool resetLoadTypeAfterFragmentNavigation = false;
1653+
if (keepNavigationOnFragmentLoad && ((m_policyDocumentLoader && !equalIgnoringFragmentIdentifier(m_policyDocumentLoader->request().url(), frameLoadRequest.resourceRequest().url())) || (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), frameLoadRequest.resourceRequest().url())))) {
1654+
resetLoadTypeAfterFragmentNavigation = true;
1655+
1656+
const auto fragmentNavigationURL = frameLoadRequest.resourceRequest().url();
1657+
const auto navigationURL = m_policyDocumentLoader ? m_policyDocumentLoader->request().url(): m_provisionalDocumentLoader->request().url();
1658+
FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadURL: navigation to: %s will be continued after fragment navigation to url: %s",
1659+
navigationURL.string().utf8().data(), fragmentNavigationURL.string().utf8().data());
1660+
} else {
1661+
policyChecker().stopCheck();
1662+
}
1663+
16451664
policyChecker().setLoadType(newLoadType);
16461665
RELEASE_ASSERT(!isBackForwardLoadType(newLoadType) || history().provisionalItem());
16471666
policyChecker().checkNavigationPolicy(WTFMove(request), ResourceResponse { } /* redirectResponse */, oldDocumentLoader.get(), WTFMove(formState), [this, protectedThis = Ref { *this }, requesterOrigin = Ref { frameLoadRequest.requesterSecurityOrigin() }, historyHandling] (const ResourceRequest& request, WeakPtr<FormState>&&, NavigationPolicyDecision navigationPolicyDecision) {
16481667
continueFragmentScrollAfterNavigationPolicy(request, requesterOrigin.ptr(), navigationPolicyDecision == NavigationPolicyDecision::ContinueLoad, historyHandling);
16491668
}, PolicyDecisionMode::Synchronous);
1669+
1670+
if (resetLoadTypeAfterFragmentNavigation)
1671+
policyChecker().setLoadType(loadType);
1672+
16501673
return;
16511674
}
16521675

@@ -3716,8 +3739,16 @@ void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequ
37163739
// frame to be deallocated.
37173740
Ref frame = m_frame.get();
37183741

3742+
static bool keepNavigationOnFragmentLoad = false;
3743+
static bool keepNavigationOnFragmentLoadInitialized = false;
3744+
3745+
if (!keepNavigationOnFragmentLoadInitialized) {
3746+
keepNavigationOnFragmentLoad = !!getenv("WPE_KEEP_NAVIGATION_ON_FRAGMENT_LOAD");
3747+
keepNavigationOnFragmentLoadInitialized = true;
3748+
}
3749+
37193750
// If we have a provisional request for a different document, a fragment scroll should cancel it.
3720-
if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
3751+
if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url()) && !keepNavigationOnFragmentLoad) {
37213752
protectedProvisionalDocumentLoader()->stopLoading();
37223753
FRAMELOADER_RELEASE_LOG(ResourceLoading, "continueFragmentScrollAfterNavigationPolicy: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
37233754
setProvisionalDocumentLoader(nullptr);

Source/WebCore/loader/PolicyChecker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,10 @@ void PolicyChecker::checkNavigationPolicy(ResourceRequest&& request, const Resou
292292
}
293293

294294
auto documentLoader = frameLoader->loaderForWebsitePolicies();
295+
// PolicyDecisionMode::Synchronous means that it is a FragmentNavigation and in that case we should use documentLoader,
296+
// because there can be ongoing (in policy or provisional state) navigation.
297+
if (policyDecisionMode == PolicyDecisionMode::Synchronous)
298+
documentLoader = frameLoader->documentLoader();
295299
auto clientRedirectSourceForHistory = documentLoader ? documentLoader->clientRedirectSourceForHistory() : String();
296300
auto navigationID = documentLoader ? documentLoader->navigationID() : std::nullopt;
297301
bool hasOpener = !!frame->opener();

0 commit comments

Comments
 (0)