Title: [237355] trunk
Revision
237355
Author
[email protected]
Date
2018-10-23 10:54:34 -0700 (Tue, 23 Oct 2018)

Log Message

[PSON] Add support for cross-site client-side redirects
https://bugs.webkit.org/show_bug.cgi?id=190806
<rdar://problem/45047344>

Reviewed by Geoffrey Garen.

Source/WebCore:

Add support for cross-site client-side redirects so that it swaps process and so that the back
forward list looks as expected. To support this, the following changes had to be done:
- The NavigationAction now provides additional information so that the WebProcess can communicate
  things about the client-side redirect to the UIProcess: lockHistory / lockBackForwardList and
  clientRedirectSourceForHistory.
- If the UIProcess decides to process-swap on a client-side redirect, we pass the client-side
  redirect information to the new WebContent process via LoadRequest struct. WebCore then takes
  care of setting things up using this information so that it recognizes that it is continuing
  a load that is a client side redirect.
- We also need to pass the current BackForwardListItem / HistoryItem to the new WebContent
  process so that the new process can truly lock history and keep updating the *current*
  HistoryItem, instead of creating a new HistoryItem.
- After a process swap, when we re-construct the WebFrameProxy for the main frame in the new
  process, we now set the frame's URL in the UIProcess to the URL it had before we swapped.
  Clients such as Safari, rely on the main frame's URL being the expected value (the last
  committed load URL) until the next load is committed when receiving didPerformRedirect
  calls. Because we are destroying the main frame on process-swapping, we were losing the
  last committed URL and Safari would hit assertions.

With this model, the willPerformClientRedirect IPC is still sent from the previous WebProcess
and the didPerformClientRedirect IPC is now sent by the new WebProcess. No change should be
observable from the client's point of view.

* loader/FrameLoadRequest.h:
(WebCore::FrameLoadRequest::setLockHistory):
(WebCore::FrameLoadRequest::setlockBackForwardList):
(WebCore::FrameLoadRequest::clientRedirectSourceForHistory const):
(WebCore::FrameLoadRequest::setClientRedirectSourceForHistory):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadURL):
(WebCore::FrameLoader::load):
* loader/HistoryController.cpp:
(WebCore::HistoryController::updateForRedirectWithLockedBackForwardList):
* loader/HistoryController.h:
* loader/NavigationAction.h:
(WebCore::NavigationAction::lockHistory const):
(WebCore::NavigationAction::setLockHistory):
(WebCore::NavigationAction::lockBackForwardList const):
(WebCore::NavigationAction::setLockBackForwardList):

Source/WebKit:

* Shared/LoadParameters.cpp:
(WebKit::LoadParameters::encode const):
(WebKit::LoadParameters::decode):
* Shared/LoadParameters.h:
* Shared/NavigationActionData.cpp:
(WebKit::NavigationActionData::encode const):
(WebKit::NavigationActionData::decode):
* Shared/NavigationActionData.h:
* Shared/WebBackForwardListItem.cpp:
(WebKit::WebBackForwardListItem::setSuspendedPage):
* UIProcess/API/APINavigation.h:
(API::Navigation::setLockHistory):
(API::Navigation::lockHistory const):
(API::Navigation::setLockBackForwardList):
(API::Navigation::lockBackForwardList const):
(API::Navigation::setClientRedirectSourceForHistory):
(API::Navigation::clientRedirectSourceForHistory const):
* UIProcess/API/APINavigationClient.h:
(API::NavigationClient::willPerformClientRedirect):
(API::NavigationClient::didPerformClientRedirect):
* UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h:
* UIProcess/Cocoa/NavigationState.h:
* UIProcess/Cocoa/NavigationState.mm:
(WebKit::NavigationState::setNavigationDelegate):
(WebKit::NavigationState::NavigationClient::didPerformClientRedirect):
* UIProcess/FrameLoadState.h:
(WebKit::FrameLoadState::setURL):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::loadRequestWithNavigation):
(WebKit::WebPageProxy::continueNavigationInNewProcess):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
(WebKit::WebPageProxy::didPerformClientRedirect):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::loadRequest):
(WebKit::WebPage::setCurrentHistoryItemForReattach):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
(-[PSONNavigationDelegate _webView:willPerformClientRedirectToURL:delay:]):
(-[PSONNavigationDelegate _webView:didPerformClientRedirectFromURL:toURL:]):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (237354 => 237355)


--- trunk/Source/WebCore/ChangeLog	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebCore/ChangeLog	2018-10-23 17:54:34 UTC (rev 237355)
@@ -1,3 +1,51 @@
+2018-10-23  Chris Dumez  <[email protected]>
+
+        [PSON] Add support for cross-site client-side redirects
+        https://bugs.webkit.org/show_bug.cgi?id=190806
+        <rdar://problem/45047344>
+
+        Reviewed by Geoffrey Garen.
+
+        Add support for cross-site client-side redirects so that it swaps process and so that the back
+        forward list looks as expected. To support this, the following changes had to be done:
+        - The NavigationAction now provides additional information so that the WebProcess can communicate
+          things about the client-side redirect to the UIProcess: lockHistory / lockBackForwardList and
+          clientRedirectSourceForHistory.
+        - If the UIProcess decides to process-swap on a client-side redirect, we pass the client-side
+          redirect information to the new WebContent process via LoadRequest struct. WebCore then takes
+          care of setting things up using this information so that it recognizes that it is continuing
+          a load that is a client side redirect.
+        - We also need to pass the current BackForwardListItem / HistoryItem to the new WebContent
+          process so that the new process can truly lock history and keep updating the *current*
+          HistoryItem, instead of creating a new HistoryItem.
+        - After a process swap, when we re-construct the WebFrameProxy for the main frame in the new
+          process, we now set the frame's URL in the UIProcess to the URL it had before we swapped.
+          Clients such as Safari, rely on the main frame's URL being the expected value (the last
+          committed load URL) until the next load is committed when receiving didPerformRedirect
+          calls. Because we are destroying the main frame on process-swapping, we were losing the
+          last committed URL and Safari would hit assertions.
+
+        With this model, the willPerformClientRedirect IPC is still sent from the previous WebProcess
+        and the didPerformClientRedirect IPC is now sent by the new WebProcess. No change should be
+        observable from the client's point of view.
+
+        * loader/FrameLoadRequest.h:
+        (WebCore::FrameLoadRequest::setLockHistory):
+        (WebCore::FrameLoadRequest::setlockBackForwardList):
+        (WebCore::FrameLoadRequest::clientRedirectSourceForHistory const):
+        (WebCore::FrameLoadRequest::setClientRedirectSourceForHistory):
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::loadURL):
+        (WebCore::FrameLoader::load):
+        * loader/HistoryController.cpp:
+        (WebCore::HistoryController::updateForRedirectWithLockedBackForwardList):
+        * loader/HistoryController.h:
+        * loader/NavigationAction.h:
+        (WebCore::NavigationAction::lockHistory const):
+        (WebCore::NavigationAction::setLockHistory):
+        (WebCore::NavigationAction::lockBackForwardList const):
+        (WebCore::NavigationAction::setLockBackForwardList):
+
 2018-10-23  Jer Noble  <[email protected]>
 
         Use WeakPtr and GenericTaskQueue within ObjC classes used by MediaPlayerPrivateAVFoundationObjC

Modified: trunk/Source/WebCore/loader/FrameLoadRequest.h (237354 => 237355)


--- trunk/Source/WebCore/loader/FrameLoadRequest.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebCore/loader/FrameLoadRequest.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -72,7 +72,14 @@
     bool hasSubstituteData() { return m_substituteData.isValid(); }
 
     LockHistory lockHistory() const { return m_lockHistory; }
+    void setLockHistory(LockHistory value) { m_lockHistory = value; }
+
     LockBackForwardList lockBackForwardList() const { return m_lockBackForwardList; }
+    void setlockBackForwardList(LockBackForwardList value) { m_lockBackForwardList = value; }
+
+    const String& clientRedirectSourceForHistory() const { return m_clientRedirectSourceForHistory; }
+    void setClientRedirectSourceForHistory(const String& clientRedirectSourceForHistory) { m_clientRedirectSourceForHistory = clientRedirectSourceForHistory; }
+
     ShouldSendReferrer shouldSendReferrer() const { return m_shouldSendReferrer; }
     AllowNavigationToInvalidURL allowNavigationToInvalidURL() const { return m_allowNavigationToInvalidURL; }
     NewFrameOpenerPolicy newFrameOpenerPolicy() const { return m_newFrameOpenerPolicy; }
@@ -97,6 +104,7 @@
     ResourceRequest m_resourceRequest;
     String m_frameName;
     SubstituteData m_substituteData;
+    String m_clientRedirectSourceForHistory;
 
     bool m_shouldCheckNewWindowPolicy { false };
     bool m_shouldTreatAsContinuingLoad { false };

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (237354 => 237355)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2018-10-23 17:54:34 UTC (rev 237355)
@@ -1360,6 +1360,8 @@
     if (m_frame.page() && m_frame.page()->openedViaWindowOpenWithOpener())
         action.setOpenedViaWindowOpenWithOpener();
     action.setHasOpenedFrames(!m_openedFrames.isEmpty());
+    action.setLockHistory(lockHistory);
+    action.setLockBackForwardList(frameLoadRequest.lockBackForwardList());
 
     if (!targetFrame && !effectiveFrameName.isEmpty()) {
         action = "" frameLoadRequest));
@@ -1458,6 +1460,13 @@
     addSameSiteInfoToRequestIfNeeded(loader->request());
     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, request);
 
+    if (request.shouldTreatAsContinuingLoad() && request.lockHistory() == LockHistory::Yes) {
+        // The load we're continuing is a client-side redirect so set things up accordingly.
+        loader->setClientRedirectSourceForHistory(request.clientRedirectSourceForHistory());
+        loader->setIsClientRedirect(true);
+        m_loadType = FrameLoadType::RedirectWithLockedBackForwardList;
+    }
+
     SetForScope<bool> currentLoadShouldBeTreatedAsContinuingLoadGuard(m_currentLoadShouldBeTreatedAsContinuingLoad, request.shouldTreatAsContinuingLoad());
     load(loader.get(), request.shouldSkipSafeBrowsingCheck());
 }
@@ -1495,7 +1504,7 @@
         type = FrameLoadType::Same;
     } else if (shouldTreatURLAsSameAsCurrent(newDocumentLoader.unreachableURL()) && isReload(m_loadType))
         type = m_loadType;
-    else if (m_loadType == FrameLoadType::RedirectWithLockedBackForwardList && !newDocumentLoader.unreachableURL().isEmpty() && newDocumentLoader.substituteData().isValid())
+    else if (m_loadType == FrameLoadType::RedirectWithLockedBackForwardList && ((!newDocumentLoader.unreachableURL().isEmpty() && newDocumentLoader.substituteData().isValid()) || m_currentLoadShouldBeTreatedAsContinuingLoad))
         type = FrameLoadType::RedirectWithLockedBackForwardList;
     else
         type = FrameLoadType::Standard;

Modified: trunk/Source/WebCore/loader/HistoryController.cpp (237354 => 237355)


--- trunk/Source/WebCore/loader/HistoryController.cpp	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebCore/loader/HistoryController.cpp	2018-10-23 17:54:34 UTC (rev 237355)
@@ -440,7 +440,7 @@
         if (Page* page = m_frame.page())
             addVisitedLink(*page, historyURL);
 
-        if (!m_frame.loader().documentLoader()->didCreateGlobalHistoryEntry() && m_frame.loader().documentLoader()->unreachableURL().isEmpty() && !m_frame.document()->url().isEmpty())
+        if (!m_frame.loader().documentLoader()->didCreateGlobalHistoryEntry() && m_frame.loader().documentLoader()->unreachableURL().isEmpty())
             m_frame.loader().client().updateGlobalHistoryRedirectLinks();
     }
 }

Modified: trunk/Source/WebCore/loader/HistoryController.h (237354 => 237355)


--- trunk/Source/WebCore/loader/HistoryController.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebCore/loader/HistoryController.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -75,7 +75,7 @@
     void updateForFrameLoadCompleted();
 
     HistoryItem* currentItem() const { return m_currentItem.get(); }
-    void setCurrentItem(HistoryItem&);
+    WEBCORE_EXPORT void setCurrentItem(HistoryItem&);
     void setCurrentItemTitle(const StringWithDirection&);
     bool currentItemShouldBeReplaced() const;
     WEBCORE_EXPORT void replaceCurrentItem(HistoryItem*);

Modified: trunk/Source/WebCore/loader/NavigationAction.h (237354 => 237355)


--- trunk/Source/WebCore/loader/NavigationAction.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebCore/loader/NavigationAction.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -130,6 +130,12 @@
     void setTargetBackForwardItem(HistoryItem&);
     const std::optional<BackForwardItemIdentifier>& targetBackForwardItemIdentifier() const { return m_targetBackForwardItemIdentifier; }
 
+    LockHistory lockHistory() const { return m_lockHistory; }
+    void setLockHistory(LockHistory lockHistory) { m_lockHistory = lockHistory; }
+
+    LockBackForwardList lockBackForwardList() const { return m_lockBackForwardList; }
+    void setLockBackForwardList(LockBackForwardList lockBackForwardList) { m_lockBackForwardList = lockBackForwardList; }
+
 private:
     // Do not add a strong reference to the originating document or a subobject that holds the
     // originating document. See comment above the class for more details.
@@ -147,6 +153,8 @@
     bool m_openedViaWindowOpenWithOpener { false };
     std::optional<PageIDAndFrameIDPair> m_opener;
     std::optional<BackForwardItemIdentifier> m_targetBackForwardItemIdentifier;
+    LockHistory m_lockHistory { LockHistory::No };
+    LockBackForwardList m_lockBackForwardList { LockBackForwardList::No };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (237354 => 237355)


--- trunk/Source/WebKit/ChangeLog	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/ChangeLog	2018-10-23 17:54:34 UTC (rev 237355)
@@ -1,3 +1,51 @@
+2018-10-23  Chris Dumez  <[email protected]>
+
+        [PSON] Add support for cross-site client-side redirects
+        https://bugs.webkit.org/show_bug.cgi?id=190806
+        <rdar://problem/45047344>
+
+        Reviewed by Geoffrey Garen.
+
+        * Shared/LoadParameters.cpp:
+        (WebKit::LoadParameters::encode const):
+        (WebKit::LoadParameters::decode):
+        * Shared/LoadParameters.h:
+        * Shared/NavigationActionData.cpp:
+        (WebKit::NavigationActionData::encode const):
+        (WebKit::NavigationActionData::decode):
+        * Shared/NavigationActionData.h:
+        * Shared/WebBackForwardListItem.cpp:
+        (WebKit::WebBackForwardListItem::setSuspendedPage):
+        * UIProcess/API/APINavigation.h:
+        (API::Navigation::setLockHistory):
+        (API::Navigation::lockHistory const):
+        (API::Navigation::setLockBackForwardList):
+        (API::Navigation::lockBackForwardList const):
+        (API::Navigation::setClientRedirectSourceForHistory):
+        (API::Navigation::clientRedirectSourceForHistory const):
+        * UIProcess/API/APINavigationClient.h:
+        (API::NavigationClient::willPerformClientRedirect):
+        (API::NavigationClient::didPerformClientRedirect):
+        * UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h:
+        * UIProcess/Cocoa/NavigationState.h:
+        * UIProcess/Cocoa/NavigationState.mm:
+        (WebKit::NavigationState::setNavigationDelegate):
+        (WebKit::NavigationState::NavigationClient::didPerformClientRedirect):
+        * UIProcess/FrameLoadState.h:
+        (WebKit::FrameLoadState::setURL):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::loadRequestWithNavigation):
+        (WebKit::WebPageProxy::continueNavigationInNewProcess):
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+        (WebKit::WebPageProxy::didPerformClientRedirect):
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::loadRequest):
+        (WebKit::WebPage::setCurrentHistoryItemForReattach):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2018-10-23  Claudio Saavedra  <[email protected]>
 
         [WPE][GTK] Pass full certificate chain in CertificateInfo coder

Modified: trunk/Source/WebKit/Shared/LoadParameters.cpp (237354 => 237355)


--- trunk/Source/WebKit/Shared/LoadParameters.cpp	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/Shared/LoadParameters.cpp	2018-10-23 17:54:34 UTC (rev 237355)
@@ -50,6 +50,9 @@
     encoder << shouldTreatAsContinuingLoad;
     encoder << userData;
     encoder << forSafeBrowsing;
+    encoder.encodeEnum(lockHistory);
+    encoder.encodeEnum(lockBackForwardList);
+    encoder << clientRedirectSourceForHistory;
 
     platformEncode(encoder);
 }
@@ -108,7 +111,19 @@
 
     if (!decoder.decode(data.forSafeBrowsing))
         return false;
-    
+
+    if (!decoder.decodeEnum(data.lockHistory))
+        return false;
+
+    if (!decoder.decodeEnum(data.lockBackForwardList))
+        return false;
+
+    std::optional<String> clientRedirectSourceForHistory;
+    decoder >> clientRedirectSourceForHistory;
+    if (!clientRedirectSourceForHistory)
+        return false;
+    data.clientRedirectSourceForHistory = WTFMove(*clientRedirectSourceForHistory);
+
     if (!platformDecode(decoder, data))
         return false;
 

Modified: trunk/Source/WebKit/Shared/LoadParameters.h (237354 => 237355)


--- trunk/Source/WebKit/Shared/LoadParameters.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/Shared/LoadParameters.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -28,6 +28,7 @@
 #include "DataReference.h"
 #include "SandboxExtension.h"
 #include "UserData.h"
+#include <WebCore/FrameLoaderTypes.h>
 #include <WebCore/ResourceRequest.h>
 
 OBJC_CLASS NSDictionary;
@@ -63,6 +64,9 @@
     bool shouldTreatAsContinuingLoad { false };
     UserData userData;
     bool forSafeBrowsing { false };
+    WebCore::LockHistory lockHistory { WebCore::LockHistory::No };
+    WebCore::LockBackForwardList lockBackForwardList { WebCore::LockBackForwardList::No };
+    String clientRedirectSourceForHistory;
 
 #if PLATFORM(COCOA)
     RetainPtr<NSDictionary> dataDetectionContext;

Modified: trunk/Source/WebKit/Shared/NavigationActionData.cpp (237354 => 237355)


--- trunk/Source/WebKit/Shared/NavigationActionData.cpp	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/Shared/NavigationActionData.cpp	2018-10-23 17:54:34 UTC (rev 237355)
@@ -51,6 +51,9 @@
     encoder << opener;
     encoder << requesterOrigin;
     encoder << targetBackForwardItemIdentifier;
+    encoder.encodeEnum(lockHistory);
+    encoder.encodeEnum(lockBackForwardList);
+    encoder << clientRedirectSourceForHistory;
 }
 
 std::optional<NavigationActionData> NavigationActionData::decode(IPC::Decoder& decoder)
@@ -128,11 +131,24 @@
     decoder >> targetBackForwardItemIdentifier;
     if (!targetBackForwardItemIdentifier)
         return std::nullopt;
-        
+
+    WebCore::LockHistory lockHistory;
+    if (!decoder.decodeEnum(lockHistory))
+        return std::nullopt;
+
+    WebCore::LockBackForwardList lockBackForwardList;
+    if (!decoder.decodeEnum(lockBackForwardList))
+        return std::nullopt;
+
+    std::optional<String> clientRedirectSourceForHistory;
+    decoder >> clientRedirectSourceForHistory;
+    if (!clientRedirectSourceForHistory)
+        return std::nullopt;
+
     return {{ WTFMove(navigationType), WTFMove(modifiers), WTFMove(mouseButton), WTFMove(syntheticClickType), WTFMove(*userGestureTokenIdentifier),
         WTFMove(*canHandleRequest), WTFMove(shouldOpenExternalURLsPolicy), WTFMove(*downloadAttribute), WTFMove(clickLocationInRootViewCoordinates),
         WTFMove(*isRedirect), *treatAsSameOriginNavigation, *hasOpenedFrames, *openedViaWindowOpenWithOpener, WTFMove(*opener), WTFMove(*requesterOrigin),
-        WTFMove(*targetBackForwardItemIdentifier) }};
+        WTFMove(*targetBackForwardItemIdentifier), lockHistory, lockBackForwardList, WTFMove(*clientRedirectSourceForHistory) }};
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/Shared/NavigationActionData.h (237354 => 237355)


--- trunk/Source/WebKit/Shared/NavigationActionData.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/Shared/NavigationActionData.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -58,6 +58,9 @@
     std::optional<std::pair<uint64_t, uint64_t>> opener;
     WebCore::SecurityOriginData requesterOrigin;
     std::optional<WebCore::BackForwardItemIdentifier> targetBackForwardItemIdentifier;
+    WebCore::LockHistory lockHistory;
+    WebCore::LockBackForwardList lockBackForwardList;
+    WTF::String clientRedirectSourceForHistory;
 };
 
 }

Modified: trunk/Source/WebKit/Shared/WebBackForwardListItem.cpp (237354 => 237355)


--- trunk/Source/WebKit/Shared/WebBackForwardListItem.cpp	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/Shared/WebBackForwardListItem.cpp	2018-10-23 17:54:34 UTC (rev 237355)
@@ -115,7 +115,6 @@
 
 void WebBackForwardListItem::setSuspendedPage(SuspendedPageProxy& page)
 {
-    ASSERT(!m_suspendedPage);
     m_suspendedPage = makeWeakPtr(page);
 }
 

Modified: trunk/Source/WebKit/UIProcess/API/APINavigation.h (237354 => 237355)


--- trunk/Source/WebKit/UIProcess/API/APINavigation.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/UIProcess/API/APINavigation.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -101,6 +101,15 @@
     void setRequesterOrigin(const WebCore::SecurityOriginData& origin) { m_requesterOrigin = origin; }
     const WebCore::SecurityOriginData& requesterOrigin() const { return m_requesterOrigin; }
 
+    void setLockHistory(WebCore::LockHistory lockHistory) { m_lockHistory = lockHistory; }
+    WebCore::LockHistory lockHistory() const { return m_lockHistory; }
+
+    void setLockBackForwardList(WebCore::LockBackForwardList lockBackForwardList) { m_lockBackForwardList = lockBackForwardList; }
+    WebCore::LockBackForwardList lockBackForwardList() const { return m_lockBackForwardList; }
+
+    void setClientRedirectSourceForHistory(const WTF::String& clientRedirectSourceForHistory) { m_clientRedirectSourceForHistory = clientRedirectSourceForHistory; }
+    WTF::String clientRedirectSourceForHistory() const { return m_clientRedirectSourceForHistory; }
+
 #if !LOG_DISABLED
     const char* loggingString() const;
 #endif
@@ -127,6 +136,9 @@
     bool m_openedViaWindowOpenWithOpener { false };
     std::optional<std::pair<uint64_t, uint64_t>> m_opener;
     WebCore::SecurityOriginData m_requesterOrigin;
+    WebCore::LockHistory m_lockHistory;
+    WebCore::LockBackForwardList m_lockBackForwardList;
+    WTF::String m_clientRedirectSourceForHistory;
 };
 
 } // namespace API

Modified: trunk/Source/WebKit/UIProcess/API/APINavigationClient.h (237354 => 237355)


--- trunk/Source/WebKit/UIProcess/API/APINavigationClient.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/UIProcess/API/APINavigationClient.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -73,7 +73,8 @@
 
     virtual void didStartProvisionalNavigation(WebKit::WebPageProxy&, Navigation*, Object*) { }
     virtual void didReceiveServerRedirectForProvisionalNavigation(WebKit::WebPageProxy&, Navigation*, Object*) { }
-    virtual void willPerformClientRedirect(WebKit::WebPageProxy&, const WTF::String&, double) { }
+    virtual void willPerformClientRedirect(WebKit::WebPageProxy&, const WTF::String& destinationURL, double) { }
+    virtual void didPerformClientRedirect(WebKit::WebPageProxy&, const WTF::String& sourceURL, const WTF::String& destinationURL) { }
     virtual void didCancelClientRedirect(WebKit::WebPageProxy&) { }
     virtual void didFailProvisionalNavigationWithError(WebKit::WebPageProxy&, WebKit::WebFrameProxy&, Navigation*, const WebCore::ResourceError&, Object*) { }
     virtual void didFailProvisionalLoadInSubframeWithError(WebKit::WebPageProxy&, WebKit::WebFrameProxy&, const WebCore::SecurityOriginData&, Navigation*, const WebCore::ResourceError&, Object*) { }

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h (237354 => 237355)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -68,6 +68,7 @@
 - (void)_webView:(WKWebView *)webView navigation:(WKNavigation *)navigation didFailProvisionalLoadInSubframe:(WKFrameInfo *)subframe withError:(NSError *)error;
 
 - (void)_webView:(WKWebView *)webView willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)delay;
+- (void)_webView:(WKWebView *)webView didPerformClientRedirectFromURL:(NSURL *)sourceURL toURL:(NSURL *)destinationURL;
 - (void)_webViewDidCancelClientRedirect:(WKWebView *)webView;
 
 - (void)_webView:(WKWebView *)webView navigationDidFinishDocumentLoad:(WKNavigation *)navigation;

Modified: trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.h (237354 => 237355)


--- trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -98,6 +98,7 @@
         void didStartProvisionalNavigation(WebPageProxy&, API::Navigation*, API::Object*) override;
         void didReceiveServerRedirectForProvisionalNavigation(WebPageProxy&, API::Navigation*, API::Object*) override;
         void willPerformClientRedirect(WebPageProxy&, const WTF::String&, double) override;
+        void didPerformClientRedirect(WebPageProxy&, const WTF::String&, const WTF::String&) override;
         void didCancelClientRedirect(WebPageProxy&) override;
         void didFailProvisionalNavigationWithError(WebPageProxy&, WebFrameProxy&, API::Navigation*, const WebCore::ResourceError&, API::Object*) override;
         void didFailProvisionalLoadInSubframeWithError(WebPageProxy&, WebFrameProxy&, const WebCore::SecurityOriginData&, API::Navigation*, const WebCore::ResourceError&, API::Object*) override;
@@ -195,6 +196,7 @@
         bool webViewDidFailProvisionalNavigationWithError : 1;
         bool webViewNavigationDidFailProvisionalLoadInSubframeWithError : 1;
         bool webViewWillPerformClientRedirect : 1;
+        bool webViewDidPerformClientRedirect : 1;
         bool webViewDidCancelClientRedirect : 1;
         bool webViewDidCommitNavigation : 1;
         bool webViewNavigationDidFinishDocumentLoad : 1;

Modified: trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm (237354 => 237355)


--- trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm	2018-10-23 17:54:34 UTC (rev 237355)
@@ -157,6 +157,7 @@
 
     m_navigationDelegateMethods.webViewNavigationDidFailProvisionalLoadInSubframeWithError = [delegate respondsToSelector:@selector(_webView:navigation:didFailProvisionalLoadInSubframe:withError:)];
     m_navigationDelegateMethods.webViewWillPerformClientRedirect = [delegate respondsToSelector:@selector(_webView:willPerformClientRedirectToURL:delay:)];
+    m_navigationDelegateMethods.webViewDidPerformClientRedirect = [delegate respondsToSelector:@selector(_webView:didPerformClientRedirectFromURL:toURL:)];
     m_navigationDelegateMethods.webViewDidCancelClientRedirect = [delegate respondsToSelector:@selector(_webViewDidCancelClientRedirect:)];
     m_navigationDelegateMethods.webViewNavigationDidFinishDocumentLoad = [delegate respondsToSelector:@selector(_webView:navigationDidFinishDocumentLoad:)];
     m_navigationDelegateMethods.webViewNavigationDidSameDocumentNavigation = [delegate respondsToSelector:@selector(_webView:navigation:didSameDocumentNavigation:)];
@@ -704,6 +705,21 @@
     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webView:m_navigationState.m_webView willPerformClientRedirectToURL:url delay:delay];
 }
 
+void NavigationState::NavigationClient::didPerformClientRedirect(WebPageProxy& page, const WTF::String& sourceURLString, const WTF::String& destinationURLString)
+{
+    if (!m_navigationState.m_navigationDelegateMethods.webViewDidPerformClientRedirect)
+        return;
+
+    auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
+    if (!navigationDelegate)
+        return;
+
+    WebCore::URL sourceURL(WebCore::URL(), sourceURLString);
+    WebCore::URL destinationURL(WebCore::URL(), destinationURLString);
+
+    [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webView:m_navigationState.m_webView didPerformClientRedirectFromURL:sourceURL toURL:destinationURL];
+}
+
 void NavigationState::NavigationClient::didCancelClientRedirect(WebPageProxy& page)
 {
     if (!m_navigationState.m_navigationDelegateMethods.webViewDidCancelClientRedirect)

Modified: trunk/Source/WebKit/UIProcess/FrameLoadState.h (237354 => 237355)


--- trunk/Source/WebKit/UIProcess/FrameLoadState.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/UIProcess/FrameLoadState.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -51,6 +51,7 @@
 
     State state() const { return m_state; }
     const WebCore::URL& url() const { return m_url; }
+    void setURL(const WebCore::URL& url) { m_url = url; }
     const WebCore::URL& provisionalURL() const { return m_provisionalURL; }
 
     void setUnreachableURL(const WebCore::URL&);

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (237354 => 237355)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2018-10-23 17:54:34 UTC (rev 237355)
@@ -103,6 +103,7 @@
 #include "WebImage.h"
 #include "WebInspectorProxy.h"
 #include "WebInspectorUtilities.h"
+#include "WebNavigationDataStore.h"
 #include "WebNavigationState.h"
 #include "WebNotificationManagerProxy.h"
 #include "WebOpenPanelResultListenerProxy.h"
@@ -1017,6 +1018,9 @@
     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
+    loadParameters.lockHistory = navigation.lockHistory();
+    loadParameters.lockBackForwardList = navigation.lockBackForwardList();
+    loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
     bool createdExtension = maybeInitializeSandboxExtensionHandle(url, loadParameters.sandboxExtensionHandle);
     if (createdExtension)
         m_process->willAcquireUniversalFileReadSandboxExtension();
@@ -2548,6 +2552,7 @@
 
     Ref<WebProcessProxy> previousProcess = m_process.copyRef();
     std::optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? std::make_optional(m_mainFrame->frameID()) : std::nullopt;
+    auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : WebCore::URL();
 
     ASSERT(m_process.ptr() != process.ptr());
 
@@ -2575,21 +2580,34 @@
         return;
     }
 
+    if (navigation.lockBackForwardList() == LockBackForwardList::Yes || navigation.lockHistory() == LockHistory::Yes) {
+        // If WebCore is supposed to lock the history for this load, then the new process needs to know about the current history item so it can update
+        // it instead of creating a new one.
+        auto itemStates = m_backForwardList->filteredItemStates([currentItem = m_backForwardList->currentItem()](WebBackForwardListItem& item) {
+            return &item == currentItem;
+        });
+        RELEASE_ASSERT(itemStates.size() == 1);
+        m_process->send(Messages::WebPage::SetCurrentHistoryItemForReattach(itemStates[0]), m_pageID);
+    }
+
     // FIXME: Work out timing of responding with the last policy delegate, etc
     ASSERT(!navigation.currentRequest().isEmpty());
     loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes);
 
-    // Normally, notification of a server redirect comes from the WebContent process.
-    // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
-    // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
-    if (navigation.currentRequestIsRedirect()) {
-        ASSERT(!m_mainFrame);
-        m_mainFrameCreationHandler = [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), request =  navigation.currentRequest()]() mutable {
-            ASSERT(m_mainFrame);
+    ASSERT(!m_mainFrame);
+    m_mainFrameCreationHandler = [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), request =  navigation.currentRequest(), mainFrameURL, isServerRedirect = navigation.currentRequestIsRedirect()]() mutable {
+        ASSERT(m_mainFrame);
+        // Restore the main frame's committed URL as some clients may rely on it until the next load is committed.
+        m_mainFrame->frameLoadState().setURL(mainFrameURL);
+
+        // Normally, notification of a server redirect comes from the WebContent process.
+        // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
+        // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
+        if (isServerRedirect) {
             m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
             didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigation->navigationID(), WTFMove(request), { });
-        };
-    }
+        }
+    };
 
     bool isInitialNavigationInNewWindow = openedByDOM() && !hasCommittedAnyProvisionalLoads();
     if (!isInitialNavigationInNewWindow || !mainFrameIDInPreviousProcess)
@@ -4115,6 +4133,9 @@
         navigation->setOpenedViaWindowOpenWithOpener();
     navigation->setOpener(navigationActionData.opener);
     navigation->setRequesterOrigin(navigationActionData.requesterOrigin);
+    navigation->setLockHistory(navigationActionData.lockHistory);
+    navigation->setLockBackForwardList(navigationActionData.lockBackForwardList);
+    navigation->setClientRedirectSourceForHistory(navigationActionData.clientRedirectSourceForHistory);
 
 #if ENABLE(CONTENT_FILTERING)
     if (frame.didHandleContentFilterUnblockNavigation(request))
@@ -4302,8 +4323,10 @@
     MESSAGE_CHECK_URL(sourceURLString);
     MESSAGE_CHECK_URL(destinationURLString);
 
-    if (frame->isMainFrame())
+    if (frame->isMainFrame()) {
         m_historyClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString);
+        m_navigationClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString);
+    }
     process().processPool().historyClient().didPerformClientRedirect(process().processPool(), *this, sourceURLString, destinationURLString, *frame);
 }
 

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (237354 => 237355)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2018-10-23 17:54:34 UTC (rev 237355)
@@ -871,6 +871,8 @@
     if (auto& requester = navigationAction.requester())
         navigationActionData.requesterOrigin = requester->securityOrigin().data();
     navigationActionData.targetBackForwardItemIdentifier = navigationAction.targetBackForwardItemIdentifier();
+    navigationActionData.lockHistory = navigationAction.lockHistory();
+    navigationActionData.lockBackForwardList = navigationAction.lockBackForwardList();
 
     WebCore::Frame* coreFrame = m_frame->coreFrame();
     if (!coreFrame)
@@ -884,6 +886,8 @@
     if (!documentLoader)
         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
 
+    navigationActionData.clientRedirectSourceForHistory = documentLoader->clientRedirectSourceForHistory();
+
     // Notify the UIProcess.
     Ref<WebFrame> protect(*m_frame);
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (237354 => 237355)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2018-10-23 17:54:34 UTC (rev 237355)
@@ -1307,6 +1307,9 @@
     ShouldOpenExternalURLsPolicy externalURLsPolicy = static_cast<ShouldOpenExternalURLsPolicy>(loadParameters.shouldOpenExternalURLsPolicy);
     frameLoadRequest.setShouldOpenExternalURLsPolicy(externalURLsPolicy);
     frameLoadRequest.setShouldTreatAsContinuingLoad(loadParameters.shouldTreatAsContinuingLoad);
+    frameLoadRequest.setLockHistory(loadParameters.lockHistory);
+    frameLoadRequest.setlockBackForwardList(loadParameters.lockBackForwardList);
+    frameLoadRequest.setClientRedirectSourceForHistory(loadParameters.clientRedirectSourceForHistory);
 
     corePage()->userInputBridge().loadRequest(WTFMove(frameLoadRequest));
 
@@ -2606,6 +2609,14 @@
     restoreSessionInternal(itemStates, WasRestoredByAPIRequest::No, WebBackForwardListProxy::OverwriteExistingItem::Yes);
 }
 
+void WebPage::setCurrentHistoryItemForReattach(WebKit::BackForwardListItemState&& itemState)
+{
+    auto historyItem = toHistoryItem(itemState);
+    auto& historyItemRef = historyItem.get();
+    static_cast<WebBackForwardListProxy&>(corePage()->backForward().client()).addItemFromUIProcess(itemState.identifier, WTFMove(historyItem), m_pageID, WebBackForwardListProxy::OverwriteExistingItem::Yes);
+    corePage()->mainFrame().loader().history().setCurrentItem(historyItemRef);
+}
+
 void WebPage::requestFontAttributesAtSelectionStart(CallbackID callbackID)
 {
     auto attributes = m_page->focusController().focusedOrMainFrame().editor().fontAttributesAtSelectionStart();

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (237354 => 237355)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2018-10-23 17:54:34 UTC (rev 237355)
@@ -1209,6 +1209,7 @@
     void restoreSession(const Vector<BackForwardListItemState>&);
     void didRemoveBackForwardItem(const WebCore::BackForwardItemIdentifier&);
     void updateBackForwardListForReattach(const Vector<WebKit::BackForwardListItemState>&);
+    void setCurrentHistoryItemForReattach(WebKit::BackForwardListItemState&&);
 
     void requestFontAttributesAtSelectionStart(CallbackID);
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (237354 => 237355)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2018-10-23 17:54:34 UTC (rev 237355)
@@ -157,6 +157,7 @@
     
     RestoreSession(Vector<WebKit::BackForwardListItemState> itemStates)
     UpdateBackForwardListForReattach(Vector<WebKit::BackForwardListItemState> itemStates)
+    SetCurrentHistoryItemForReattach(struct WebKit::BackForwardListItemState itemState)
 
     DidRemoveBackForwardItem(struct WebCore::BackForwardItemIdentifier backForwardItemID)
 

Modified: trunk/Tools/ChangeLog (237354 => 237355)


--- trunk/Tools/ChangeLog	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Tools/ChangeLog	2018-10-23 17:54:34 UTC (rev 237355)
@@ -1,3 +1,17 @@
+2018-10-23  Chris Dumez  <[email protected]>
+
+        [PSON] Add support for cross-site client-side redirects
+        https://bugs.webkit.org/show_bug.cgi?id=190806
+        <rdar://problem/45047344>
+
+        Reviewed by Geoffrey Garen.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+        (-[PSONNavigationDelegate _webView:willPerformClientRedirectToURL:delay:]):
+        (-[PSONNavigationDelegate _webView:didPerformClientRedirectFromURL:toURL:]):
+
 2018-10-23  Claudio Saavedra  <[email protected]>
 
         [WPE][GTK] Pass full certificate chain in CertificateInfo coder

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (237354 => 237355)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2018-10-23 17:54:34 UTC (rev 237355)
@@ -68,6 +68,11 @@
 static bool receivedMessage;
 static bool serverRedirected;
 static HashSet<pid_t> seenPIDs;
+static bool willPerformClientRedirect;
+static bool didPerformClientRedirect;
+static RetainPtr<NSURL> clientRedirectSourceURL;
+static RetainPtr<NSURL> clientRedirectDestinationURL;
+
 @interface PSONMessageHandler : NSObject <WKScriptMessageHandler>
 @end
 
@@ -124,6 +129,20 @@
     serverRedirected = true;
 }
 
+- (void)_webView:(WKWebView *)webView willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)delay
+{
+    clientRedirectDestinationURL = URL;
+    willPerformClientRedirect = true;
+}
+
+- (void)_webView:(WKWebView *)webView didPerformClientRedirectFromURL:(NSURL *)sourceURL toURL:(NSURL *)destinationURL
+{
+    EXPECT_TRUE(willPerformClientRedirect);
+    EXPECT_WK_STREQ([clientRedirectDestinationURL absoluteString], [destinationURL absoluteString]);
+    clientRedirectSourceURL = sourceURL;
+    didPerformClientRedirect = true;
+}
+
 @end
 
 static RetainPtr<WKWebView> createdWebView;
@@ -245,6 +264,22 @@
 </head>
 )PSONRESOURCE";
 
+static const char* linkToCrossSiteClientSideRedirectBytes = R"PSONRESOURCE(
+<body>
+  <a id="testLink" href="" to cross-site client-side redirect</a>
+</body>
+)PSONRESOURCE";
+
+static const char* crossSiteClientSideRedirectBytes = R"PSONRESOURCE(
+<body>
+<script>
+_onload_ = () => {
+  location = "pson://www.apple.com/main.html";
+};
+</script>
+</body>
+)PSONRESOURCE";
+
 #if PLATFORM(MAC)
 
 static const char* windowOpenCrossSiteNoOpenerTestBytes = R"PSONRESOURCE(
@@ -1097,6 +1132,143 @@
     EXPECT_EQ(2u, seenPIDs.size());
 }
 
+enum class ShouldEnablePSON { No, Yes };
+static void runClientSideRedirectTest(ShouldEnablePSON shouldEnablePSON)
+{
+    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    processPoolConfiguration.get().processSwapsOnNavigation = shouldEnablePSON == ShouldEnablePSON::Yes ? YES : NO;
+    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:linkToCrossSiteClientSideRedirectBytes];
+    [handler addMappingFromURLString:@"pson://www.google.com/clientSideRedirect.html" toData:crossSiteClientSideRedirectBytes];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"pson"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto webkitPID = [webView _webProcessIdentifier];
+
+    // Navigate to the page doing a client-side redirect to apple.com.
+    [webView evaluateJavaScript:@"testLink.click()" completionHandler:nil];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    EXPECT_WK_STREQ(@"pson://www.google.com/clientSideRedirect.html", [[webView URL] absoluteString]);
+    auto googlePID = [webView _webProcessIdentifier];
+    if (shouldEnablePSON == ShouldEnablePSON::Yes)
+        EXPECT_NE(webkitPID, googlePID);
+    else
+        EXPECT_EQ(webkitPID, googlePID);
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [[webView URL] absoluteString]);
+
+    auto applePID = [webView _webProcessIdentifier];
+    if (shouldEnablePSON == ShouldEnablePSON::Yes) {
+        EXPECT_NE(webkitPID, applePID);
+        EXPECT_NE(webkitPID, googlePID);
+    } else {
+        EXPECT_EQ(webkitPID, applePID);
+        EXPECT_EQ(webkitPID, googlePID);
+    }
+
+    EXPECT_TRUE(willPerformClientRedirect);
+    EXPECT_TRUE(didPerformClientRedirect);
+    EXPECT_WK_STREQ(@"pson://www.google.com/clientSideRedirect.html", [clientRedirectSourceURL absoluteString]);
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [clientRedirectDestinationURL absoluteString]);
+
+    willPerformClientRedirect = false;
+    didPerformClientRedirect = false;
+    clientRedirectSourceURL = nullptr;
+    clientRedirectDestinationURL = nullptr;
+
+    // Validate Back/Forward list.
+    auto* backForwardList = [webView backForwardList];
+    auto* currentItem = backForwardList.currentItem;
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [currentItem.URL absoluteString]);
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [currentItem.initialURL absoluteString]);
+    EXPECT_TRUE(!backForwardList.forwardItem);
+
+    EXPECT_EQ(1U, backForwardList.backList.count);
+
+    auto* backItem = backForwardList.backItem;
+    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [backItem.URL absoluteString]);
+    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [backItem.initialURL absoluteString]);
+
+    // Navigate back.
+    [webView goBack];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [[webView URL] absoluteString]);
+    EXPECT_FALSE(willPerformClientRedirect);
+    EXPECT_FALSE(didPerformClientRedirect);
+
+    auto pidAfterBackNavigation = [webView _webProcessIdentifier];
+    EXPECT_EQ(webkitPID, pidAfterBackNavigation);
+
+    // Validate Back/Forward list.
+    currentItem = backForwardList.currentItem;
+    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [currentItem.URL absoluteString]);
+    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [currentItem.initialURL absoluteString]);
+
+    EXPECT_TRUE(!backForwardList.backItem);
+    EXPECT_EQ(1U, backForwardList.forwardList.count);
+
+    auto* forwardItem = backForwardList.forwardItem;
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [forwardItem.URL absoluteString]);
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [forwardItem.initialURL absoluteString]);
+
+    // Navigate forward.
+    [webView goForward];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [[webView URL] absoluteString]);
+    EXPECT_FALSE(willPerformClientRedirect);
+    EXPECT_FALSE(didPerformClientRedirect);
+
+    auto pidAfterForwardNavigation = [webView _webProcessIdentifier];
+    EXPECT_EQ(applePID, pidAfterForwardNavigation);
+
+    // Validate Back/Forward list.
+    currentItem = backForwardList.currentItem;
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [currentItem.URL absoluteString]);
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [currentItem.initialURL absoluteString]);
+    EXPECT_TRUE(!backForwardList.forwardItem);
+
+    EXPECT_EQ(1U, backForwardList.backList.count);
+
+    // FIXME: uncomment the following once <rdar://problem/45058938> has been fixed. When enabling PSON
+    // the backItem's URL currently becomes about:blank.
+    // backItem = backForwardList.backItem;
+    // EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [backItem.URL absoluteString]);
+    // EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [backItem.initialURL absoluteString]);
+}
+
+TEST(ProcessSwap, CrossSiteClientSideRedirectWithoutPSON)
+{
+    runClientSideRedirectTest(ShouldEnablePSON::No);
+}
+
+TEST(ProcessSwap, CrossSiteClientSideRedirectWithPSON)
+{
+    runClientSideRedirectTest(ShouldEnablePSON::Yes);
+}
+
 static const char* sessionStorageTestBytes = R"PSONRESOURCE(
 <head>
 <script>
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to