Title: [244540] trunk
Revision
244540
Author
[email protected]
Date
2019-04-23 08:38:11 -0700 (Tue, 23 Apr 2019)

Log Message

[Process-Swap-On-Navigation] WebKit hangs when going back to a form submission's page due to Process-Swap-On-Navigation on iOS 12.2 and higher
https://bugs.webkit.org/show_bug.cgi?id=197097
<rdar://problem/50048318>

Reviewed by Alex Christensen.

Source/WebCore:

* loader/EmptyFrameLoaderClient.h:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::checkLoadCompleteForThisFrame):
If we still have a provisional item (new load has been started or we did not clear it because we're about to retry),
then let the client know the load will continue by passing an extra flag with the didFailProvisionalLoad.

* loader/FrameLoaderClient.h:
* loader/FrameLoaderTypes.h:

Source/WebKit:

The issue is that when doing a history navigation with form data, we try to resubmit the form.
We initially use the ReturnCacheDataDontLoad cache policy without prompting the user to get
cached data. If this fails, we sent a DidFailProvisionalLoadForFrame IPC to the UIProcess but
the WebContent process actually retries the load with ReturnCacheDataElseLoad cache policy.
This new load triggers a new decidePolicyForNavigationAction.

This would cause trouble with process-swapping because we normally destroy the
ProvisionalPageProxy as soon as we receive a DidFailProvisionalLoadForFrame IPC from the
provisional process. As a result, the provisional process would not be able to retry.

To address the issue, we add pass a flag with the DidFailProvisionalLoadForFrame IPC to
if the load will continue or not. When this flag is set, the UIProcess does not destroy
the provisional page.

* Scripts/webkit/messages.py:
Minor IPC message handler build fix.

* UIProcess/API/Cocoa/WKURLSchemeTask.mm:
(-[WKURLSchemeTaskImpl _onlyIfCached]):
* UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h:
Add new _onlyIfCached SPI to WKURLSchemeTaskPrivate to allow for API testing.

* UIProcess/ProvisionalPageProxy.cpp:
(WebKit::ProvisionalPageProxy::cancel):
Pass WillContinueLoading flag.

(WebKit::ProvisionalPageProxy::validateInput):
Consider IPC with a navigationID of 0 as valid. When the navigation is triggered by the
WebContent process, it sends us a DecidePolicyForNavigationActionAsync IPC with a navigationID
of 0, until the UIProcess can generate a valid identifier.

(WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):

(WebKit::ProvisionalPageProxy::decidePolicyForNavigationActionAsync):
When the WebPageProxy has generated a navigationID for the new WebContent process-initiated
navigation, update m_navigationID so that follow-up IPC is considered valid.

* UIProcess/ProvisionalPageProxy.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
(WebKit::WebPageProxy::didFailProvisionalLoadForFrameShared):
(WebKit::WebPageProxy::decidePolicyForNavigationActionAsyncShared):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDidFailProvisionalLoad):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.h:

Source/WebKitLegacy/mac:

* WebCoreSupport/WebFrameLoaderClient.h:
* WebCoreSupport/WebFrameLoaderClient.mm:
(WebFrameLoaderClient::dispatchDidFailProvisionalLoad):

Source/WebKitLegacy/win:

* WebCoreSupport/WebFrameLoaderClient.cpp:
(WebFrameLoaderClient::dispatchDidFailProvisionalLoad):
* WebCoreSupport/WebFrameLoaderClient.h:

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
(-[PSONScheme webView:startURLSchemeTask:]):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (244539 => 244540)


--- trunk/Source/WebCore/ChangeLog	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebCore/ChangeLog	2019-04-23 15:38:11 UTC (rev 244540)
@@ -1,3 +1,20 @@
+2019-04-23  Chris Dumez  <[email protected]>
+
+        [Process-Swap-On-Navigation] WebKit hangs when going back to a form submission's page due to Process-Swap-On-Navigation on iOS 12.2 and higher
+        https://bugs.webkit.org/show_bug.cgi?id=197097
+        <rdar://problem/50048318>
+
+        Reviewed by Alex Christensen.
+
+        * loader/EmptyFrameLoaderClient.h:
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::checkLoadCompleteForThisFrame):
+        If we still have a provisional item (new load has been started or we did not clear it because we're about to retry),
+        then let the client know the load will continue by passing an extra flag with the didFailProvisionalLoad.
+
+        * loader/FrameLoaderClient.h:
+        * loader/FrameLoaderTypes.h:
+
 2019-04-23  Carlos Garcia Campos  <[email protected]>
 
         [ATK] Implement AtkComponentIface scroll_to methods

Modified: trunk/Source/WebCore/loader/EmptyFrameLoaderClient.h (244539 => 244540)


--- trunk/Source/WebCore/loader/EmptyFrameLoaderClient.h	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebCore/loader/EmptyFrameLoaderClient.h	2019-04-23 15:38:11 UTC (rev 244540)
@@ -84,7 +84,7 @@
     void dispatchDidStartProvisionalLoad() final { }
     void dispatchDidReceiveTitle(const StringWithDirection&) final { }
     void dispatchDidCommitLoad(Optional<HasInsecureContent>) final { }
-    void dispatchDidFailProvisionalLoad(const ResourceError&) final { }
+    void dispatchDidFailProvisionalLoad(const ResourceError&, WillContinueLoading) final { }
     void dispatchDidFailLoad(const ResourceError&) final { }
     void dispatchDidFinishDocumentLoad() final { }
     void dispatchDidFinishLoad() final { }

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (244539 => 244540)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2019-04-23 15:38:11 UTC (rev 244540)
@@ -2465,7 +2465,8 @@
             if (!pdl->isLoadingInAPISense() || pdl->isStopping()) {
                 RELEASE_LOG_IF_ALLOWED("checkLoadCompleteForThisFrame: Failed provisional load (frame = %p, main = %d, isTimeout = %d, isCancellation = %d, errorCode = %d)", &m_frame, m_frame.isMainFrame(), error.isTimeout(), error.isCancellation(), error.errorCode());
                 m_provisionalLoadErrorBeingHandledURL = m_provisionalDocumentLoader->url();
-                m_client.dispatchDidFailProvisionalLoad(error);
+
+                m_client.dispatchDidFailProvisionalLoad(error, history().provisionalItem() ? WillContinueLoading::Yes : WillContinueLoading::No);
 #if ENABLE(CONTENT_FILTERING)
                 if (auto contentFilter = pdl->contentFilter())
                     contentFilter->handleProvisionalLoadFailure(error);

Modified: trunk/Source/WebCore/loader/FrameLoaderClient.h (244539 => 244540)


--- trunk/Source/WebCore/loader/FrameLoaderClient.h	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebCore/loader/FrameLoaderClient.h	2019-04-23 15:38:11 UTC (rev 244540)
@@ -177,7 +177,7 @@
     virtual void dispatchDidStartProvisionalLoad() = 0;
     virtual void dispatchDidReceiveTitle(const StringWithDirection&) = 0;
     virtual void dispatchDidCommitLoad(Optional<HasInsecureContent>) = 0;
-    virtual void dispatchDidFailProvisionalLoad(const ResourceError&) = 0;
+    virtual void dispatchDidFailProvisionalLoad(const ResourceError&, WillContinueLoading) = 0;
     virtual void dispatchDidFailLoad(const ResourceError&) = 0;
     virtual void dispatchDidFinishDocumentLoad() = 0;
     virtual void dispatchDidFinishLoad() = 0;

Modified: trunk/Source/WebCore/loader/FrameLoaderTypes.h (244539 => 244540)


--- trunk/Source/WebCore/loader/FrameLoaderTypes.h	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebCore/loader/FrameLoaderTypes.h	2019-04-23 15:38:11 UTC (rev 244540)
@@ -67,6 +67,8 @@
     ReloadExpiredOnly
 };
 
+enum class WillContinueLoading : bool { No, Yes };
+
 class PolicyCheckIdentifier {
 public:
     PolicyCheckIdentifier() = default;

Modified: trunk/Source/WebKit/ChangeLog (244539 => 244540)


--- trunk/Source/WebKit/ChangeLog	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/ChangeLog	2019-04-23 15:38:11 UTC (rev 244540)
@@ -1,3 +1,60 @@
+2019-04-23  Chris Dumez  <[email protected]>
+
+        [Process-Swap-On-Navigation] WebKit hangs when going back to a form submission's page due to Process-Swap-On-Navigation on iOS 12.2 and higher
+        https://bugs.webkit.org/show_bug.cgi?id=197097
+        <rdar://problem/50048318>
+
+        Reviewed by Alex Christensen.
+
+        The issue is that when doing a history navigation with form data, we try to resubmit the form.
+        We initially use the ReturnCacheDataDontLoad cache policy without prompting the user to get
+        cached data. If this fails, we sent a DidFailProvisionalLoadForFrame IPC to the UIProcess but
+        the WebContent process actually retries the load with ReturnCacheDataElseLoad cache policy.
+        This new load triggers a new decidePolicyForNavigationAction.
+
+        This would cause trouble with process-swapping because we normally destroy the
+        ProvisionalPageProxy as soon as we receive a DidFailProvisionalLoadForFrame IPC from the
+        provisional process. As a result, the provisional process would not be able to retry.
+
+        To address the issue, we add pass a flag with the DidFailProvisionalLoadForFrame IPC to
+        if the load will continue or not. When this flag is set, the UIProcess does not destroy
+        the provisional page.
+
+        * Scripts/webkit/messages.py:
+        Minor IPC message handler build fix.
+
+        * UIProcess/API/Cocoa/WKURLSchemeTask.mm:
+        (-[WKURLSchemeTaskImpl _onlyIfCached]):
+        * UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h:
+        Add new _onlyIfCached SPI to WKURLSchemeTaskPrivate to allow for API testing.
+
+        * UIProcess/ProvisionalPageProxy.cpp:
+        (WebKit::ProvisionalPageProxy::cancel):
+        Pass WillContinueLoading flag.
+
+        (WebKit::ProvisionalPageProxy::validateInput):
+        Consider IPC with a navigationID of 0 as valid. When the navigation is triggered by the
+        WebContent process, it sends us a DecidePolicyForNavigationActionAsync IPC with a navigationID
+        of 0, until the UIProcess can generate a valid identifier.
+
+        (WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):
+
+        (WebKit::ProvisionalPageProxy::decidePolicyForNavigationActionAsync):
+        When the WebPageProxy has generated a navigationID for the new WebContent process-initiated
+        navigation, update m_navigationID so that follow-up IPC is considered valid.
+
+        * UIProcess/ProvisionalPageProxy.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
+        (WebKit::WebPageProxy::didFailProvisionalLoadForFrameShared):
+        (WebKit::WebPageProxy::decidePolicyForNavigationActionAsyncShared):
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::dispatchDidFailProvisionalLoad):
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
+
 2019-04-22  Zalan Bujtas  <[email protected]>
 
         [ContentChangeObserver] Some dropdown menus may close without user gesture on americanexpress.com

Modified: trunk/Source/WebKit/Scripts/webkit/messages.py (244539 => 244540)


--- trunk/Source/WebKit/Scripts/webkit/messages.py	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/Scripts/webkit/messages.py	2019-04-23 15:38:11 UTC (rev 244540)
@@ -462,6 +462,7 @@
         'WebCore::TextCheckingType': ['<WebCore/TextChecking.h>'],
         'WebCore::TextIndicatorData': ['<WebCore/TextIndicator.h>'],
         'WebCore::ViewportAttributes': ['<WebCore/ViewportArguments.h>'],
+        'WebCore::WillContinueLoading': ['<WebCore/FrameLoaderTypes.h>'],
         'WebCore::SelectionRect': ['"EditorState.h"'],
         'WebKit::ActivityStateChangeID': ['"DrawingAreaInfo.h"'],
         'WebKit::BackForwardListItemState': ['"SessionState.h"'],

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.mm (244539 => 244540)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.mm	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTask.mm	2019-04-23 15:38:11 UTC (rev 244540)
@@ -70,6 +70,11 @@
     return _urlSchemeTask->task().request().nsURLRequest(WebCore::HTTPBodyUpdatePolicy::UpdateHTTPBody);
 }
 
+- (BOOL)_requestOnlyIfCached
+{
+    return _urlSchemeTask->task().request().cachePolicy() == WebCore::ResourceRequestCachePolicy::ReturnCacheDataDontLoad;
+}
+
 - (void)didReceiveResponse:(NSURLResponse *)response
 {
     auto result = _urlSchemeTask->task().didReceiveResponse(response);

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h (244539 => 244540)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKURLSchemeTaskPrivate.h	2019-04-23 15:38:11 UTC (rev 244540)
@@ -30,4 +30,6 @@
 
 - (void)_didPerformRedirection:(NSURLResponse *)response newRequest:(NSURLRequest *)request;
 
+@property (nonatomic, readonly) BOOL _requestOnlyIfCached WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @end

Modified: trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp (244539 => 244540)


--- trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp	2019-04-23 15:38:11 UTC (rev 244540)
@@ -134,7 +134,7 @@
     ASSERT(m_mainFrame);
     auto error = WebKit::cancelledError(m_request);
     error.setType(WebCore::ResourceError::Type::Cancellation);
-    didFailProvisionalLoadForFrame(m_mainFrame->frameID(), { }, m_navigationID, m_provisionalLoadURL, error, UserData { }); // Will delete |this|.
+    didFailProvisionalLoadForFrame(m_mainFrame->frameID(), { }, m_navigationID, m_provisionalLoadURL, error, WebCore::WillContinueLoading::No, UserData { }); // Will delete |this|.
 }
 
 void ProvisionalPageProxy::initializeWebPage()
@@ -189,7 +189,7 @@
     if (!m_mainFrame || m_mainFrame->frameID() != frameID)
         return false;
 
-    return !navigationID || *navigationID == m_navigationID;
+    return !navigationID || !*navigationID || *navigationID == m_navigationID;
 }
 
 void ProvisionalPageProxy::didCreateMainFrame(uint64_t frameID)
@@ -247,7 +247,7 @@
     m_page.didStartProvisionalLoadForFrameShared(m_process.copyRef(), frameID, navigationID, WTFMove(url), WTFMove(unreachableURL), userData);
 }
 
-void ProvisionalPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError& error, const UserData& userData)
+void ProvisionalPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError& error, WebCore::WillContinueLoading willContinueLoading, const UserData& userData)
 {
     if (!validateInput(frameID, navigationID))
         return;
@@ -260,7 +260,7 @@
     if (auto* pageMainFrame = m_page.mainFrame())
         pageMainFrame->didFailProvisionalLoad();
 
-    m_page.didFailProvisionalLoadForFrameShared(m_process.copyRef(), frameID, frameSecurityOrigin, navigationID, provisionalURL, error, userData); // Will delete |this|.
+    m_page.didFailProvisionalLoadForFrameShared(m_process.copyRef(), frameID, frameSecurityOrigin, navigationID, provisionalURL, error, willContinueLoading, userData); // May delete |this|.
 }
 
 void ProvisionalPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData& userData)
@@ -378,11 +378,14 @@
 
     if (decoder.messageName() == Messages::WebPageProxy::DidStartProgress::name()
         || decoder.messageName() == Messages::WebPageProxy::DidChangeProgress::name()
+        || decoder.messageName() == Messages::WebPageProxy::DidDestroyNavigation::name()
+        || decoder.messageName() == Messages::WebPageProxy::DidFinishProgress::name()
         || decoder.messageName() == Messages::WebPageProxy::BackForwardAddItem::name()
         || decoder.messageName() == Messages::WebPageProxy::LogDiagnosticMessage::name()
         || decoder.messageName() == Messages::WebPageProxy::LogDiagnosticMessageWithEnhancedPrivacy::name()
         || decoder.messageName() == Messages::WebPageProxy::LogDiagnosticMessageWithValueDictionary::name()
         || decoder.messageName() == Messages::WebPageProxy::SetNetworkRequestsInProgress::name()
+        || decoder.messageName() == Messages::WebPageProxy::WillGoToBackForwardListItem::name()
 #if USE(QUICK_LOOK)
         || decoder.messageName() == Messages::WebPageProxy::DidStartLoadForQuickLookDocumentInMainFrame::name()
         || decoder.messageName() == Messages::WebPageProxy::DidFinishLoadForQuickLookDocumentInMainFrame::name()

Modified: trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.h (244539 => 244540)


--- trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.h	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.h	2019-04-23 15:38:11 UTC (rev 244540)
@@ -74,6 +74,8 @@
     DrawingAreaProxy* drawingArea() const { return m_drawingArea.get(); }
     std::unique_ptr<DrawingAreaProxy> takeDrawingArea();
 
+    void setNavigationID(uint64_t navigationID) { m_navigationID = navigationID; }
+
 #if PLATFORM(COCOA)
     Vector<uint8_t> takeAccessibilityToken() { return WTFMove(m_accessibilityToken); }
 #endif
@@ -104,7 +106,7 @@
     void didCreateMainFrame(uint64_t frameID);
     void didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&&, URL&& unreachableURL, const UserData&);
     void didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo&, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData&);
-    void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&);
+    void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, WebCore::WillContinueLoading, const UserData&);
     void startURLSchemeTask(URLSchemeTaskParameters&&);
     void backForwardGoToItem(const WebCore::BackForwardItemIdentifier&, CompletionHandler<void(SandboxExtension::Handle&&)>&&);
     void decidePolicyForNavigationActionSync(uint64_t frameID, bool isMainFrame, WebCore::SecurityOriginData&&, WebCore::PolicyCheckIdentifier, uint64_t navigationID, NavigationActionData&&,

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (244539 => 244540)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2019-04-23 15:38:11 UTC (rev 244540)
@@ -2778,7 +2778,6 @@
     URL sourceURL = URL { URL(), pageLoadState().url() };
     if (auto* provisionalPage = provisionalPageProxy()) {
         if (provisionalPage->navigationID() == navigation->navigationID()) {
-            ASSERT(navigation->currentRequestIsRedirect());
             sourceProcess = provisionalPage->process();
             sourceURL = provisionalPage->provisionalURL();
         }
@@ -4038,7 +4037,7 @@
     frame->didReceiveServerRedirectForProvisionalLoad(url);
 }
 
-void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
+void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, WillContinueLoading willContinueLoading, const UserData& userData)
 {
     if (m_provisionalPage && m_provisionalPage->navigationID() == navigationID) {
         // The load did not fail, it is merely happening in a new provisional process.
@@ -4045,10 +4044,10 @@
         return;
     }
 
-    didFailProvisionalLoadForFrameShared(m_process.copyRef(), frameID, frameSecurityOrigin, navigationID, provisionalURL, error, userData);
+    didFailProvisionalLoadForFrameShared(m_process.copyRef(), frameID, frameSecurityOrigin, navigationID, provisionalURL, error, willContinueLoading, userData);
 }
 
-void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref<WebProcessProxy>&& process, uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
+void WebPageProxy::didFailProvisionalLoadForFrameShared(Ref<WebProcessProxy>&& process, uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, WillContinueLoading willContinueLoading, const UserData& userData)
 {
     LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " in web process pid %i didFailProvisionalLoadForFrame to provisionalURL %s", m_pageID, process->processIdentifier(), provisionalURL.utf8().data());
     RELEASE_LOG_IF_ALLOWED(Process, "didFailProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64 ", domain = %s, code = %d", process->processIdentifier(), m_pageID, frameID, error.domain().utf8().data(), error.errorCode());
@@ -4095,7 +4094,7 @@
     m_failingProvisionalLoadURL = { };
 
     // If the provisional page's load fails then we destroy the provisional page.
-    if (m_provisionalPage && m_provisionalPage->mainFrame() == frame)
+    if (m_provisionalPage && m_provisionalPage->mainFrame() == frame && willContinueLoading == WillContinueLoading::No)
         m_provisionalPage = nullptr;
 }
 
@@ -4580,7 +4579,12 @@
             navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
     }
 
-    uint64_t newNavigationID = navigation->navigationID();
+    navigationID = navigation->navigationID();
+
+    // Make sure the provisional page always has the latest navigationID.
+    if (m_provisionalPage && &m_provisionalPage->process() == process.ptr())
+        m_provisionalPage->setNavigationID(navigationID);
+
     navigation->setCurrentRequest(ResourceRequest(request), process->coreProcessIdentifier());
     navigation->setLastNavigationAction(navigationActionData);
     navigation->setOriginatingFrameInfo(originatingFrameInfoData);
@@ -4588,9 +4592,7 @@
 
 #if ENABLE(CONTENT_FILTERING)
     if (frame.didHandleContentFilterUnblockNavigation(request))
-        return receivedPolicyDecision(PolicyAction::Ignore, m_navigationState->navigation(newNavigationID), WTF::nullopt, WTFMove(sender));
-#else
-    UNUSED_PARAM(newNavigationID);
+        return receivedPolicyDecision(PolicyAction::Ignore, m_navigationState->navigation(navigationID), WTF::nullopt, WTFMove(sender));
 #endif
 
     ShouldExpectSafeBrowsingResult shouldExpectSafeBrowsingResult = ShouldExpectSafeBrowsingResult::Yes;

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (244539 => 244540)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2019-04-23 15:38:11 UTC (rev 244540)
@@ -1484,7 +1484,7 @@
 
     // Logic shared between the WebPageProxy and the ProvisionalPageProxy.
     void didStartProvisionalLoadForFrameShared(Ref<WebProcessProxy>&&, uint64_t frameID, uint64_t navigationID, URL&&, URL&& unreachableURL, const UserData&);
-    void didFailProvisionalLoadForFrameShared(Ref<WebProcessProxy>&&, uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&);
+    void didFailProvisionalLoadForFrameShared(Ref<WebProcessProxy>&&, uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, WebCore::WillContinueLoading, const UserData&);
     void didReceiveServerRedirectForProvisionalLoadForFrameShared(Ref<WebProcessProxy>&&, uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest&&, const UserData&);
     void didPerformServerRedirectShared(Ref<WebProcessProxy>&&, const String& sourceURLString, const String& destinationURLString, uint64_t frameID);
     void didPerformClientRedirectShared(Ref<WebProcessProxy>&&, const String& sourceURLString, const String& destinationURLString, uint64_t frameID);
@@ -1586,7 +1586,7 @@
     void willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay, WebCore::LockBackForwardList);
     void didCancelClientRedirectForFrame(uint64_t frameID);
     void didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, URL&&);
-    void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&);
+    void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, WebCore::WillContinueLoading, const UserData&);
     void didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo&, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData&);
     void didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData&);
     void didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData&);

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (244539 => 244540)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2019-04-23 15:38:11 UTC (rev 244540)
@@ -127,7 +127,7 @@
     WillPerformClientRedirectForFrame(uint64_t frameID, String url, double delay, enum:bool WebCore::LockBackForwardList lockBackForwardList)
     DidCancelClientRedirectForFrame(uint64_t frameID)
     DidChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, URL url)
-    DidFailProvisionalLoadForFrame(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, uint64_t navigationID, String provisionalURL, WebCore::ResourceError error, WebKit::UserData userData)
+    DidFailProvisionalLoadForFrame(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, uint64_t navigationID, String provisionalURL, WebCore::ResourceError error, enum:bool WebCore::WillContinueLoading willContinueLoading, WebKit::UserData userData)
     DidCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, String mimeType, bool hasCustomContentProvider, uint32_t loadType, WebCore::CertificateInfo certificateInfo, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, WebKit::UserData userData)
     DidFailLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceError error, WebKit::UserData userData)
     DidFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, WebKit::UserData userData)

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (244539 => 244540)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2019-04-23 15:38:11 UTC (rev 244540)
@@ -535,7 +535,7 @@
     webPage->didCommitLoad(m_frame);
 }
 
-void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
+void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error, WillContinueLoading willContinueLoading)
 {
     WebPage* webPage = m_frame->page();
     if (!webPage)
@@ -564,7 +564,7 @@
 
     // Notify the UIProcess.
     WebCore::Frame* coreFrame = m_frame ? m_frame->coreFrame() : nullptr;
-    webPage->send(Messages::WebPageProxy::DidFailProvisionalLoadForFrame(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), navigationID, m_frame->coreFrame()->loader().provisionalLoadErrorBeingHandledURL(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+    webPage->send(Messages::WebPageProxy::DidFailProvisionalLoadForFrame(m_frame->frameID(), SecurityOriginData::fromFrame(coreFrame), navigationID, m_frame->coreFrame()->loader().provisionalLoadErrorBeingHandledURL(), error, willContinueLoading, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
 
     // If we have a load listener, notify it.
     if (WebFrame::LoadListener* loadListener = m_frame->loadListener())

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h (244539 => 244540)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h	2019-04-23 15:38:11 UTC (rev 244540)
@@ -112,7 +112,7 @@
     void dispatchDidStartProvisionalLoad() final;
     void dispatchDidReceiveTitle(const WebCore::StringWithDirection&) final;
     void dispatchDidCommitLoad(Optional<WebCore::HasInsecureContent>) final;
-    void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&) final;
+    void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&, WebCore::WillContinueLoading) final;
     void dispatchDidFailLoad(const WebCore::ResourceError&) final;
     void dispatchDidFinishDocumentLoad() final;
     void dispatchDidFinishLoad() final;

Modified: trunk/Source/WebKitLegacy/mac/ChangeLog (244539 => 244540)


--- trunk/Source/WebKitLegacy/mac/ChangeLog	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKitLegacy/mac/ChangeLog	2019-04-23 15:38:11 UTC (rev 244540)
@@ -1,3 +1,15 @@
+2019-04-23  Chris Dumez  <[email protected]>
+
+        [Process-Swap-On-Navigation] WebKit hangs when going back to a form submission's page due to Process-Swap-On-Navigation on iOS 12.2 and higher
+        https://bugs.webkit.org/show_bug.cgi?id=197097
+        <rdar://problem/50048318>
+
+        Reviewed by Alex Christensen.
+
+        * WebCoreSupport/WebFrameLoaderClient.h:
+        * WebCoreSupport/WebFrameLoaderClient.mm:
+        (WebFrameLoaderClient::dispatchDidFailProvisionalLoad):
+
 2019-04-18  Daniel Bates  <[email protected]>
 
         Use existing KeyEventCodesIOS constants instead of duplicating them

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.h (244539 => 244540)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.h	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.h	2019-04-23 15:38:11 UTC (rev 244540)
@@ -117,7 +117,7 @@
     void dispatchDidStartProvisionalLoad() final;
     void dispatchDidReceiveTitle(const WebCore::StringWithDirection&) final;
     void dispatchDidCommitLoad(Optional<WebCore::HasInsecureContent>) final;
-    void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&) final;
+    void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&, WebCore::WillContinueLoading) final;
     void dispatchDidFailLoad(const WebCore::ResourceError&) final;
     void dispatchDidFinishDocumentLoad() final;
     void dispatchDidFinishLoad() final;

Modified: trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm (244539 => 244540)


--- trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKitLegacy/mac/WebCoreSupport/WebFrameLoaderClient.mm	2019-04-23 15:38:11 UTC (rev 244540)
@@ -724,7 +724,7 @@
         CallFrameLoadDelegate(implementations->didCommitLoadForFrameFunc, webView, @selector(webView:didCommitLoadForFrame:), m_webFrame.get());
 }
 
-void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
+void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error, WillContinueLoading)
 {
     m_webFrame->_private->provisionalURL = nullptr;
 

Modified: trunk/Source/WebKitLegacy/win/ChangeLog (244539 => 244540)


--- trunk/Source/WebKitLegacy/win/ChangeLog	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKitLegacy/win/ChangeLog	2019-04-23 15:38:11 UTC (rev 244540)
@@ -1,3 +1,15 @@
+2019-04-23  Chris Dumez  <[email protected]>
+
+        [Process-Swap-On-Navigation] WebKit hangs when going back to a form submission's page due to Process-Swap-On-Navigation on iOS 12.2 and higher
+        https://bugs.webkit.org/show_bug.cgi?id=197097
+        <rdar://problem/50048318>
+
+        Reviewed by Alex Christensen.
+
+        * WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebFrameLoaderClient::dispatchDidFailProvisionalLoad):
+        * WebCoreSupport/WebFrameLoaderClient.h:
+
 2019-04-20  Don Olmstead  <[email protected]>
 
         [CMake][Win] Use target oriented design for WebKitLegacy

Modified: trunk/Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.cpp (244539 => 244540)


--- trunk/Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.cpp	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.cpp	2019-04-23 15:38:11 UTC (rev 244540)
@@ -445,7 +445,7 @@
         frameLoadDelegate->didCommitLoadForFrame(webView, m_webFrame);
 }
 
-void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
+void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error, WillContinueLoading)
 {
     WebView* webView = m_webFrame->webView();
     COMPtr<IWebFrameLoadDelegate> frameLoadDelegate;

Modified: trunk/Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.h (244539 => 244540)


--- trunk/Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.h	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Source/WebKitLegacy/win/WebCoreSupport/WebFrameLoaderClient.h	2019-04-23 15:38:11 UTC (rev 244540)
@@ -94,7 +94,7 @@
     void dispatchDidStartProvisionalLoad() override;
     void dispatchDidReceiveTitle(const WebCore::StringWithDirection&) override;
     void dispatchDidCommitLoad(Optional<WebCore::HasInsecureContent>) override;
-    void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&) override;
+    void dispatchDidFailProvisionalLoad(const WebCore::ResourceError&, WebCore::WillContinueLoading) override;
     void dispatchDidFailLoad(const WebCore::ResourceError&) override;
     void dispatchDidFinishDocumentLoad() override;
     void dispatchDidFinishLoad() override;

Modified: trunk/Tools/ChangeLog (244539 => 244540)


--- trunk/Tools/ChangeLog	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Tools/ChangeLog	2019-04-23 15:38:11 UTC (rev 244540)
@@ -1,3 +1,16 @@
+2019-04-23  Chris Dumez  <[email protected]>
+
+        [Process-Swap-On-Navigation] WebKit hangs when going back to a form submission's page due to Process-Swap-On-Navigation on iOS 12.2 and higher
+        https://bugs.webkit.org/show_bug.cgi?id=197097
+        <rdar://problem/50048318>
+
+        Reviewed by Alex Christensen.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+        (-[PSONScheme webView:startURLSchemeTask:]):
+
 2019-04-23  Carlos Garcia Campos  <[email protected]>
 
         [ATK] Implement AtkComponentIface scroll_to methods

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (244539 => 244540)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2019-04-23 15:36:58 UTC (rev 244539)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2019-04-23 15:38:11 UTC (rev 244540)
@@ -276,6 +276,11 @@
         [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:redirectResponse.get() newRequest:request.get()];
     }
 
+    if ([(id<WKURLSchemeTaskPrivate>)task _requestOnlyIfCached]) {
+        [task didFailWithError:[NSError errorWithDomain:@"TestWebKitAPI" code:1 userInfo:nil]];
+        return;
+    }
+
     RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:finalURL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]);
     [task didReceiveResponse:response.get()];
 
@@ -4278,7 +4283,73 @@
     EXPECT_NE(applePID, [webView _webProcessIdentifier]);
 }
 
+static const char* crossSiteFormSubmissionBytes = R"PSONRESOURCE(
+<body>
+<form action="" method="post">
+Name: <input type="text" name="name" placeholder="Name">
+<input id="submitButton" type="submit">
+</form>
+</body>
+)PSONRESOURCE";
 
+TEST(ProcessSwap, SwapOnFormSubmission)
+{
+    auto processPoolConfiguration = psonProcessPoolConfiguration();
+    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [webViewConfiguration setProcessPool:processPool.get()];
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:crossSiteFormSubmissionBytes];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:navigationDelegate.get()];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]]];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    auto webkitPID = [webView _webProcessIdentifier];
+    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [[webView URL] absoluteString]);
+
+    [webView evaluateJavaScript:@"submitButton.click()" completionHandler:nil];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    auto applePID = [webView _webProcessIdentifier];
+    EXPECT_NE(webkitPID, applePID);
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [[webView URL] absoluteString]);
+
+    [webView reload];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    EXPECT_EQ(applePID, [webView _webProcessIdentifier]);
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [[webView URL] absoluteString]);
+
+    [webView goBack];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]);
+    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [[webView URL] absoluteString]);
+
+    [webView goForward];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    EXPECT_EQ(applePID, [webView _webProcessIdentifier]);
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [[webView URL] absoluteString]);
+
+    [webView goBack];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+#if !PLATFORM(IOS_FAMILY)
+    // This is not guaranteed on iOS because the WebProcess cache is disabled on devices with too little RAM.
+    EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]);
+#else
+    EXPECT_NE(applePID, [webView _webProcessIdentifier]);
+#endif
+    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [[webView URL] absoluteString]);
+}
+
 TEST(ProcessSwap, ClosePageAfterCrossSiteProvisionalLoad)
 {
     auto processPoolConfiguration = psonProcessPoolConfiguration();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to