REGRESSION (iOS 15.2): Loading gets stuck after back-navigation involving COOP header
https://bugs.webkit.org/show_bug.cgi?id=235475
<rdar://problem/87948317>
Reviewed by Geoffrey Garen.
Source/WebCore:
Make sure ShouldTreatAsContinuingLoad is properly propagated for back/forward navigations,
not just regular loadRequests.
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadURL):
(WebCore::FrameLoader::loadWithNavigationAction):
(WebCore::FrameLoader::loadPostRequest):
(WebCore::FrameLoader::continueLoadAfterNewWindowPolicy):
(WebCore::FrameLoader::loadDifferentDocumentItem):
* loader/FrameLoader.h:
Source/WebKit:
WebPageProxy::continueNavigationInNewProcess() was failing to pass the identifier of the
NetworkResourceLoader that needs to be resumed to ProvisionalPageProxy::goToBackForwardItem().
It was only passing it to ProvisionalPageProxy::loadRequest(), which is used for non-back/forward
navigations. As a result, in case of COOP process-swap on back/forward navigation, the network
process would start a fresh load instead of resuming the existing one. The fresh load would get
a COOP header and thus trigger yet another process swap (and so on in a loop).
Also fix an issue where ProvisionalPageProxy::goToBackForwardItem() would always use
ShouldTreatAsContinuingLoad::YesAfterNavigationPolicyDecision even in the case of a COOP
process-swap. In the case of a COOP process-swap, we should pass in
ShouldTreatAsContinuingLoad::YesAfterProvisionalLoadStarted. This was causing us to
do an extra call to didStartProvisionalLoad() and was causing the new API test to hit
an assertion on debug builds.
Covered by new API test.
* UIProcess/ProvisionalPageProxy.cpp:
(WebKit::ProvisionalPageProxy::goToBackForwardItem):
* UIProcess/ProvisionalPageProxy.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::launchProcessForReload):
(WebKit::WebPageProxy::goToBackForwardItem):
(WebKit::WebPageProxy::continueNavigationInNewProcess):
(WebKit::WebPageProxy::triggerBrowsingContextGroupSwitchForNavigation):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::loadRequest):
(WebKit::WebPage::loadData):
(WebKit::WebPage::goToBackForwardItem):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
Tools:
Add API test coverage.
* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@288605 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 3e8f92f..d06f44e 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,22 @@
+2022-01-25 Chris Dumez <cdumez@apple.com>
+
+ REGRESSION (iOS 15.2): Loading gets stuck after back-navigation involving COOP header
+ https://bugs.webkit.org/show_bug.cgi?id=235475
+ <rdar://problem/87948317>
+
+ Reviewed by Geoffrey Garen.
+
+ Make sure ShouldTreatAsContinuingLoad is properly propagated for back/forward navigations,
+ not just regular loadRequests.
+
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::loadURL):
+ (WebCore::FrameLoader::loadWithNavigationAction):
+ (WebCore::FrameLoader::loadPostRequest):
+ (WebCore::FrameLoader::continueLoadAfterNewWindowPolicy):
+ (WebCore::FrameLoader::loadDifferentDocumentItem):
+ * loader/FrameLoader.h:
+
2022-01-25 Eric Carlson <eric.carlson@apple.com>
[macOS] Add new screen and window capture backend
diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp
index 7254737..8e3be5f 100644
--- a/Source/WebCore/loader/FrameLoader.cpp
+++ b/Source/WebCore/loader/FrameLoader.cpp
@@ -1401,7 +1401,7 @@
if (isSystemPreview)
request.setSystemPreviewInfo(frameLoadRequest.systemPreviewInfo());
#endif
- loadWithNavigationAction(request, WTFMove(action), newLoadType, WTFMove(formState), allowNavigationToInvalidURL, [this, isRedirect, sameURL, newLoadType, protectedFrame = Ref { m_frame }, completionHandler = completionHandlerCaller.release()] () mutable {
+ loadWithNavigationAction(request, WTFMove(action), newLoadType, WTFMove(formState), allowNavigationToInvalidURL, frameLoadRequest.shouldTreatAsContinuingLoad(), [this, isRedirect, sameURL, newLoadType, protectedFrame = Ref { m_frame }, completionHandler = completionHandlerCaller.release()] () mutable {
if (isRedirect) {
m_quickRedirectComing = false;
if (m_provisionalDocumentLoader)
@@ -1479,7 +1479,7 @@
load(loader.get());
}
-void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler<void()>&& completionHandler)
+void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, CompletionHandler<void()>&& completionHandler)
{
FRAMELOADER_RELEASE_LOG(ResourceLoading, "loadWithNavigationAction: frame load started");
@@ -1491,6 +1491,7 @@
Ref<DocumentLoader> loader = m_client->createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, action.initiatedByMainFrame(), action.shouldOpenExternalURLsPolicy());
+ loader->setIsContinuingLoadAfterProvisionalLoadStarted(shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::YesAfterProvisionalLoadStarted);
if (action.lockHistory() == LockHistory::Yes && m_documentLoader)
loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
@@ -3082,7 +3083,7 @@
if (!frameName.isEmpty()) {
// The search for a target frame is done earlier in the case of form submission.
if (auto* targetFrame = formState ? nullptr : findFrameForNavigation(frameName)) {
- targetFrame->loader().loadWithNavigationAction(workingResourceRequest, WTFMove(action), loadType, WTFMove(formState), allowNavigationToInvalidURL, WTFMove(completionHandler));
+ targetFrame->loader().loadWithNavigationAction(workingResourceRequest, WTFMove(action), loadType, WTFMove(formState), allowNavigationToInvalidURL, request.shouldTreatAsContinuingLoad(), WTFMove(completionHandler));
return;
}
@@ -3101,7 +3102,7 @@
// must grab this now, since this load may stop the previous load and clear this flag
bool isRedirect = m_quickRedirectComing;
- loadWithNavigationAction(workingResourceRequest, WTFMove(action), loadType, WTFMove(formState), allowNavigationToInvalidURL, [this, isRedirect, protectedFrame = Ref { m_frame }, completionHandler = WTFMove(completionHandler)] () mutable {
+ loadWithNavigationAction(workingResourceRequest, WTFMove(action), loadType, WTFMove(formState), allowNavigationToInvalidURL, request.shouldTreatAsContinuingLoad(), [this, isRedirect, protectedFrame = Ref { m_frame }, completionHandler = WTFMove(completionHandler)] () mutable {
if (isRedirect) {
m_quickRedirectComing = false;
if (m_provisionalDocumentLoader)
@@ -3597,7 +3598,7 @@
NavigationAction newAction { *frame->document(), request, InitiatedByMainFrame::Unknown, NavigationType::Other, action.shouldOpenExternalURLsPolicy(), nullptr, action.downloadAttribute() };
newAction.setShouldReplaceDocumentIfJavaScriptURL(action.shouldReplaceDocumentIfJavaScriptURL());
- mainFrame->loader().loadWithNavigationAction(request, WTFMove(newAction), FrameLoadType::Standard, formState, allowNavigationToInvalidURL);
+ mainFrame->loader().loadWithNavigationAction(request, WTFMove(newAction), FrameLoadType::Standard, formState, allowNavigationToInvalidURL, ShouldTreatAsContinuingLoad::No);
}
void FrameLoader::requestFromDelegate(ResourceRequest& request, ResourceLoaderIdentifier& identifier, ResourceError& error)
@@ -3885,7 +3886,7 @@
action.setTargetBackForwardItem(item);
action.setSourceBackForwardItem(fromItem);
- loadWithNavigationAction(request, WTFMove(action), loadType, { }, AllowNavigationToInvalidURL::Yes);
+ loadWithNavigationAction(request, WTFMove(action), loadType, { }, AllowNavigationToInvalidURL::Yes, shouldTreatAsContinuingLoad);
}
// Loads content into this frame, as specified by history item
diff --git a/Source/WebCore/loader/FrameLoader.h b/Source/WebCore/loader/FrameLoader.h
index ad5a380..6c7f508 100644
--- a/Source/WebCore/loader/FrameLoader.h
+++ b/Source/WebCore/loader/FrameLoader.h
@@ -381,7 +381,7 @@
void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, RefPtr<FormState>&&, AllowNavigationToInvalidURL, CompletionHandler<void()>&& = [] { }); // Calls continueLoadAfterNavigationPolicy
void load(DocumentLoader&); // Calls loadWithDocumentLoader
- void loadWithNavigationAction(const ResourceRequest&, NavigationAction&&, FrameLoadType, RefPtr<FormState>&&, AllowNavigationToInvalidURL, CompletionHandler<void()>&& = [] { }); // Calls loadWithDocumentLoader
+ void loadWithNavigationAction(const ResourceRequest&, NavigationAction&&, FrameLoadType, RefPtr<FormState>&&, AllowNavigationToInvalidURL, ShouldTreatAsContinuingLoad, CompletionHandler<void()>&& = [] { }); // Calls loadWithDocumentLoader
void loadPostRequest(FrameLoadRequest&&, const String& referrer, FrameLoadType, Event*, RefPtr<FormState>&&, CompletionHandler<void()>&&);
void loadURL(FrameLoadRequest&&, const String& referrer, FrameLoadType, Event*, RefPtr<FormState>&&, std::optional<PrivateClickMeasurement>&&, CompletionHandler<void()>&&);
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 79a5a7d..96daec6 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,42 @@
+2022-01-25 Chris Dumez <cdumez@apple.com>
+
+ REGRESSION (iOS 15.2): Loading gets stuck after back-navigation involving COOP header
+ https://bugs.webkit.org/show_bug.cgi?id=235475
+ <rdar://problem/87948317>
+
+ Reviewed by Geoffrey Garen.
+
+ WebPageProxy::continueNavigationInNewProcess() was failing to pass the identifier of the
+ NetworkResourceLoader that needs to be resumed to ProvisionalPageProxy::goToBackForwardItem().
+ It was only passing it to ProvisionalPageProxy::loadRequest(), which is used for non-back/forward
+ navigations. As a result, in case of COOP process-swap on back/forward navigation, the network
+ process would start a fresh load instead of resuming the existing one. The fresh load would get
+ a COOP header and thus trigger yet another process swap (and so on in a loop).
+
+ Also fix an issue where ProvisionalPageProxy::goToBackForwardItem() would always use
+ ShouldTreatAsContinuingLoad::YesAfterNavigationPolicyDecision even in the case of a COOP
+ process-swap. In the case of a COOP process-swap, we should pass in
+ ShouldTreatAsContinuingLoad::YesAfterProvisionalLoadStarted. This was causing us to
+ do an extra call to didStartProvisionalLoad() and was causing the new API test to hit
+ an assertion on debug builds.
+
+ Covered by new API test.
+
+ * UIProcess/ProvisionalPageProxy.cpp:
+ (WebKit::ProvisionalPageProxy::goToBackForwardItem):
+ * UIProcess/ProvisionalPageProxy.h:
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::launchProcessForReload):
+ (WebKit::WebPageProxy::goToBackForwardItem):
+ (WebKit::WebPageProxy::continueNavigationInNewProcess):
+ (WebKit::WebPageProxy::triggerBrowsingContextGroupSwitchForNavigation):
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::loadRequest):
+ (WebKit::WebPage::loadData):
+ (WebKit::WebPage::goToBackForwardItem):
+ * WebProcess/WebPage/WebPage.h:
+ * WebProcess/WebPage/WebPage.messages.in:
+
2022-01-25 Eric Carlson <eric.carlson@apple.com>
[macOS] Add new screen and window capture backend
diff --git a/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp b/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
index f38122a..63454a9 100644
--- a/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
+++ b/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
@@ -198,9 +198,9 @@
m_page.loadRequestWithNavigationShared(m_process.copyRef(), m_webPageID, navigation, WTFMove(request), navigation.lastNavigationAction().shouldOpenExternalURLsPolicy, userData, shouldTreatAsContinuingLoad, isNavigatingToAppBoundDomain, WTFMove(websitePolicies), existingNetworkResourceLoadIdentifierToResume);
}
-void ProvisionalPageProxy::goToBackForwardItem(API::Navigation& navigation, WebBackForwardListItem& item, RefPtr<API::WebsitePolicies>&& websitePolicies)
+void ProvisionalPageProxy::goToBackForwardItem(API::Navigation& navigation, WebBackForwardListItem& item, RefPtr<API::WebsitePolicies>&& websitePolicies, WebCore::ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume)
{
- PROVISIONALPAGEPROXY_RELEASE_LOG(ProcessSwapping, "goToBackForwardItem:");
+ PROVISIONALPAGEPROXY_RELEASE_LOG(ProcessSwapping, "goToBackForwardItem: existingNetworkResourceLoadIdentifierToResume=%" PRIu64, valueOrDefault(existingNetworkResourceLoadIdentifierToResume).toUInt64());
auto itemStates = m_page.backForwardList().filteredItemStates([this, targetItem = &item](auto& item) {
if (auto* backForwardCacheEntry = item.backForwardCacheEntry()) {
@@ -215,7 +215,7 @@
websitePoliciesData = websitePolicies->data();
send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)));
- send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item.itemID(), *navigation.backForwardFrameLoadType(), WebCore::ShouldTreatAsContinuingLoad::YesAfterNavigationPolicyDecision, WTFMove(websitePoliciesData), m_page.lastNavigationWasAppInitiated()));
+ send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item.itemID(), *navigation.backForwardFrameLoadType(), shouldTreatAsContinuingLoad, WTFMove(websitePoliciesData), m_page.lastNavigationWasAppInitiated(), existingNetworkResourceLoadIdentifierToResume));
m_process->startResponsivenessTimer();
}
diff --git a/Source/WebKit/UIProcess/ProvisionalPageProxy.h b/Source/WebKit/UIProcess/ProvisionalPageProxy.h
index aa1f487..22d2bb1 100644
--- a/Source/WebKit/UIProcess/ProvisionalPageProxy.h
+++ b/Source/WebKit/UIProcess/ProvisionalPageProxy.h
@@ -107,7 +107,7 @@
void loadData(API::Navigation&, const IPC::DataReference&, const String& mimeType, const String& encoding, const String& baseURL, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, std::optional<NavigatingToAppBoundDomain>, std::optional<WebsitePoliciesData>&&, WebCore::SubstituteData::SessionHistoryVisibility);
void loadRequest(API::Navigation&, WebCore::ResourceRequest&&, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, std::optional<NavigatingToAppBoundDomain>, std::optional<WebsitePoliciesData>&& = std::nullopt, std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume = std::nullopt);
- void goToBackForwardItem(API::Navigation&, WebBackForwardListItem&, RefPtr<API::WebsitePolicies>&&);
+ void goToBackForwardItem(API::Navigation&, WebBackForwardListItem&, RefPtr<API::WebsitePolicies>&&, WebCore::ShouldTreatAsContinuingLoad, std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume = std::nullopt);
void cancel();
void unfreezeLayerTreeDueToSwipeAnimation();
diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp
index 5042d88..5aa3c07 100644
--- a/Source/WebKit/UIProcess/WebPageProxy.cpp
+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp
@@ -1098,7 +1098,7 @@
}
// We allow stale content when reloading a WebProcess that's been killed or crashed.
- send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, std::nullopt, m_lastNavigationWasAppInitiated));
+ send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), m_backForwardList->currentItem()->itemID(), FrameLoadType::IndexedBackForward, ShouldTreatAsContinuingLoad::No, std::nullopt, m_lastNavigationWasAppInitiated, std::nullopt));
m_process->startResponsivenessTimer();
return navigation;
@@ -1846,7 +1846,7 @@
m_pageLoadState.setPendingAPIRequest(transaction, { navigation ? navigation->navigationID() : 0, item.url() });
m_process->markProcessAsRecentlyUsed();
- send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, std::nullopt, m_lastNavigationWasAppInitiated));
+ send(Messages::WebPage::GoToBackForwardItem(navigation ? navigation->navigationID() : 0, item.itemID(), frameLoadType, ShouldTreatAsContinuingLoad::No, std::nullopt, m_lastNavigationWasAppInitiated, std::nullopt));
m_process->startResponsivenessTimer();
return navigation;
@@ -3631,7 +3631,7 @@
auto transaction = m_pageLoadState.transaction();
m_pageLoadState.setPendingAPIRequest(transaction, { navigation->navigationID(), item->url() });
- m_provisionalPage->goToBackForwardItem(navigation, *item, WTFMove(websitePolicies));
+ m_provisionalPage->goToBackForwardItem(navigation, *item, WTFMove(websitePolicies), shouldTreatAsContinuingLoad, existingNetworkResourceLoadIdentifierToResume);
return;
}
@@ -5698,7 +5698,7 @@
{
ASSERT(browsingContextGroupSwitchDecision != BrowsingContextGroupSwitchDecision::StayInGroup);
RefPtr<API::Navigation> navigation = navigationID ? m_navigationState->navigation(navigationID) : nullptr;
- WEBPAGEPROXY_RELEASE_LOG(ProcessSwapping, "triggerBrowsingContextGroupSwitchForNavigation: Process-swapping due to Cross-Origin-Opener-Policy, newProcessIsCrossOriginIsolated=%d, navigation=%p", browsingContextGroupSwitchDecision == BrowsingContextGroupSwitchDecision::NewIsolatedGroup, navigation.get());
+ WEBPAGEPROXY_RELEASE_LOG(ProcessSwapping, "triggerBrowsingContextGroupSwitchForNavigation: Process-swapping due to Cross-Origin-Opener-Policy, newProcessIsCrossOriginIsolated=%d, navigation=%p existingNetworkResourceLoadIdentifierToResume=%" PRIu64, browsingContextGroupSwitchDecision == BrowsingContextGroupSwitchDecision::NewIsolatedGroup, navigation.get(), existingNetworkResourceLoadIdentifierToResume.toUInt64());
if (!navigation)
return completionHandler(false);
diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
index ba2d3fa..fc18509 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp
@@ -1683,6 +1683,8 @@
void WebPage::loadRequest(LoadParameters&& loadParameters)
{
+ WEBPAGE_RELEASE_LOG(Loading, "loadRequest: navigationID=%" PRIu64 ", shouldTreatAsContinuingLoad=%u, lastNavigationWasAppInitiated=%d, existingNetworkResourceLoadIdentifierToResume=%" PRIu64, loadParameters.navigationID, static_cast<unsigned>(loadParameters.shouldTreatAsContinuingLoad), loadParameters.request.isAppInitiated(), valueOrDefault(loadParameters.existingNetworkResourceLoadIdentifierToResume).toUInt64());
+
setLastNavigationWasAppInitiated(loadParameters.request.isAppInitiated());
#if ENABLE(APP_BOUND_DOMAINS)
@@ -1758,6 +1760,8 @@
void WebPage::loadData(LoadParameters&& loadParameters)
{
+ WEBPAGE_RELEASE_LOG(Loading, "loadData: navigationID=%" PRIu64 ", shouldTreatAsContinuingLoad=%u", loadParameters.navigationID, static_cast<unsigned>(loadParameters.shouldTreatAsContinuingLoad));
+
platformDidReceiveLoadParameters(loadParameters);
auto sharedBuffer = SharedBuffer::create(loadParameters.data.data(), loadParameters.data.size());
@@ -1871,14 +1875,20 @@
}
}
-void WebPage::goToBackForwardItem(uint64_t navigationID, const BackForwardItemIdentifier& backForwardItemID, FrameLoadType backForwardType, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, std::optional<WebsitePoliciesData>&& websitePolicies, bool lastNavigationWasAppInitiated)
+void WebPage::goToBackForwardItem(uint64_t navigationID, const BackForwardItemIdentifier& backForwardItemID, FrameLoadType backForwardType, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, std::optional<WebsitePoliciesData>&& websitePolicies, bool lastNavigationWasAppInitiated, std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume)
{
+ WEBPAGE_RELEASE_LOG(Loading, "goToBackForwardItem: navigationID=%" PRIu64 ", backForwardItemID=%s, shouldTreatAsContinuingLoad=%u, lastNavigationWasAppInitiated=%d, existingNetworkResourceLoadIdentifierToResume=%" PRIu64, navigationID, backForwardItemID.string().utf8().data(), static_cast<unsigned>(shouldTreatAsContinuingLoad), lastNavigationWasAppInitiated, valueOrDefault(existingNetworkResourceLoadIdentifierToResume).toUInt64());
SendStopResponsivenessTimer stopper;
m_lastNavigationWasAppInitiated = lastNavigationWasAppInitiated;
if (auto* documentLoader = corePage()->mainFrame().loader().documentLoader())
documentLoader->setLastNavigationWasAppInitiated(lastNavigationWasAppInitiated);
+ WebProcess::singleton().webLoaderStrategy().setExistingNetworkResourceLoadIdentifierToResume(existingNetworkResourceLoadIdentifierToResume);
+ auto resumingLoadScope = makeScopeExit([] {
+ WebProcess::singleton().webLoaderStrategy().setExistingNetworkResourceLoadIdentifierToResume(std::nullopt);
+ });
+
ASSERT(isBackForwardLoadType(backForwardType));
HistoryItem* item = WebBackForwardListProxy::itemForID(backForwardItemID);
diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.h b/Source/WebKit/WebProcess/WebPage/WebPage.h
index 0292074..fedbe60 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.h
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.h
@@ -1602,7 +1602,7 @@
void navigateToPDFLinkWithSimulatedClick(const String& url, WebCore::IntPoint documentPoint, WebCore::IntPoint screenPoint);
void getPDFFirstPageSize(WebCore::FrameIdentifier, CompletionHandler<void(WebCore::FloatSize)>&&);
void reload(uint64_t navigationID, uint32_t reloadOptions, SandboxExtension::Handle&&);
- void goToBackForwardItem(uint64_t navigationID, const WebCore::BackForwardItemIdentifier&, WebCore::FrameLoadType, WebCore::ShouldTreatAsContinuingLoad, std::optional<WebsitePoliciesData>&&, bool lastNavigationWasAppInitiated);
+ void goToBackForwardItem(uint64_t navigationID, const WebCore::BackForwardItemIdentifier&, WebCore::FrameLoadType, WebCore::ShouldTreatAsContinuingLoad, std::optional<WebsitePoliciesData>&&, bool lastNavigationWasAppInitiated, std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume);
void tryRestoreScrollPosition();
void setInitialFocus(bool forward, bool isKeyboardEventValid, const WebKeyboardEvent&, CompletionHandler<void()>&&);
void updateIsInWindow(bool isInitialState = false);
diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
index 6f91a2a..7b5f3d8 100644
--- a/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
+++ b/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
@@ -167,7 +167,7 @@
ScrollBy(uint32_t scrollDirection, enum:uint8_t WebCore::ScrollGranularity scrollGranularity)
CenterSelectionInVisibleArea()
- GoToBackForwardItem(uint64_t navigationID, struct WebCore::BackForwardItemIdentifier backForwardItemID, enum:uint8_t WebCore::FrameLoadType backForwardType, enum:uint8_t WebCore::ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, std::optional<WebKit::WebsitePoliciesData> websitePolicies, bool lastNavigationWasAppInitiated)
+ GoToBackForwardItem(uint64_t navigationID, struct WebCore::BackForwardItemIdentifier backForwardItemID, enum:uint8_t WebCore::FrameLoadType backForwardType, enum:uint8_t WebCore::ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, std::optional<WebKit::WebsitePoliciesData> websitePolicies, bool lastNavigationWasAppInitiated, std::optional<WebKit::NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume)
TryRestoreScrollPosition()
LoadURLInFrame(URL url, String referrer, WebCore::FrameIdentifier frameID)
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index 400fa7d..07e014f 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,15 @@
+2022-01-25 Chris Dumez <cdumez@apple.com>
+
+ REGRESSION (iOS 15.2): Loading gets stuck after back-navigation involving COOP header
+ https://bugs.webkit.org/show_bug.cgi?id=235475
+ <rdar://problem/87948317>
+
+ Reviewed by Geoffrey Garen.
+
+ Add API test coverage.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+
2022-01-25 Eric Carlson <eric.carlson@apple.com>
[macOS] Add new screen and window capture backend
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm
index c922b63..f494630 100644
--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm
+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm
@@ -7348,6 +7348,45 @@
} while (isFrozen);
}
+TEST(ProcessSwap, NavigateBackAfterNavigatingAwayFromCOOP)
+{
+ using namespace TestWebKitAPI;
+
+ HTTPServer server({
+ { "/source.html", { { { "Content-Type", "text/html" }, { "Cross-Origin-Opener-Policy", "same-origin" } }, "foo" } },
+ { "/destination.html", { "bar" } },
+ }, HTTPServer::Protocol::Https);
+
+ auto processPoolConfiguration = psonProcessPoolConfiguration();
+ auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+
+ auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+ [webViewConfiguration setProcessPool:processPool.get()];
+ for (_WKExperimentalFeature *feature in [WKPreferences _experimentalFeatures]) {
+ if ([feature.key isEqualToString:@"CrossOriginOpenerPolicyEnabled"])
+ [[webViewConfiguration preferences] _setEnabled:YES forExperimentalFeature:feature];
+ else if ([feature.key isEqualToString:@"CrossOriginEmbedderPolicyEnabled"])
+ [[webViewConfiguration preferences] _setEnabled:YES forExperimentalFeature:feature];
+ }
+
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+ auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+ [webView setNavigationDelegate:navigationDelegate.get()];
+
+ done = false;
+ [webView loadRequest:server.request("/source.html")];
+ Util::run(&done);
+ done = false;
+
+ [webView loadRequest:server.request("/destination.html")];
+ Util::run(&done);
+ done = false;
+
+ [webView goBack];
+ Util::run(&done);
+ done = false;
+}
+
enum class IsSameOrigin : bool { No, Yes };
enum class DoServerSideRedirect : bool { No, Yes };
static void runCOOPProcessSwapTest(const char* sourceCOOP, const char* sourceCOEP, const char* destinationCOOP, const char* destinationCOEP, IsSameOrigin isSameOrigin, DoServerSideRedirect doServerSideRedirect, ExpectSwap expectSwap)