<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[237355] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/237355">237355</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2018-10-23 10:54:34 -0700 (Tue, 23 Oct 2018)</dd>
</dl>

<h3>Log Message</h3>
<pre>[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:]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreloaderFrameLoadRequesth">trunk/Source/WebCore/loader/FrameLoadRequest.h</a></li>
<li><a href="#trunkSourceWebCoreloaderFrameLoadercpp">trunk/Source/WebCore/loader/FrameLoader.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderHistoryControllercpp">trunk/Source/WebCore/loader/HistoryController.cpp</a></li>
<li><a href="#trunkSourceWebCoreloaderHistoryControllerh">trunk/Source/WebCore/loader/HistoryController.h</a></li>
<li><a href="#trunkSourceWebCoreloaderNavigationActionh">trunk/Source/WebCore/loader/NavigationAction.h</a></li>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitSharedLoadParameterscpp">trunk/Source/WebKit/Shared/LoadParameters.cpp</a></li>
<li><a href="#trunkSourceWebKitSharedLoadParametersh">trunk/Source/WebKit/Shared/LoadParameters.h</a></li>
<li><a href="#trunkSourceWebKitSharedNavigationActionDatacpp">trunk/Source/WebKit/Shared/NavigationActionData.cpp</a></li>
<li><a href="#trunkSourceWebKitSharedNavigationActionDatah">trunk/Source/WebKit/Shared/NavigationActionData.h</a></li>
<li><a href="#trunkSourceWebKitSharedWebBackForwardListItemcpp">trunk/Source/WebKit/Shared/WebBackForwardListItem.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPIAPINavigationh">trunk/Source/WebKit/UIProcess/API/APINavigation.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPIAPINavigationClienth">trunk/Source/WebKit/UIProcess/API/APINavigationClient.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessAPICocoaWKNavigationDelegatePrivateh">trunk/Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessCocoaNavigationStateh">trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessCocoaNavigationStatemm">trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessFrameLoadStateh">trunk/Source/WebKit/UIProcess/FrameLoadState.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxycpp">trunk/Source/WebKit/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebCoreSupportWebFrameLoaderClientcpp">trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagecpp">trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPageh">trunk/Source/WebKit/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagemessagesin">trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKitCocoaProcessSwapOnNavigationmm">trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2018-10-23  Chris Dumez  <cdumez@apple.com>
+
+        [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):
+
</ins><span class="cx"> 2018-10-23  Jer Noble  <jer.noble@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Use WeakPtr and GenericTaskQueue within ObjC classes used by MediaPlayerPrivateAVFoundationObjC
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderFrameLoadRequesth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/FrameLoadRequest.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -72,7 +72,14 @@
</span><span class="cx">     bool hasSubstituteData() { return m_substituteData.isValid(); }
</span><span class="cx"> 
</span><span class="cx">     LockHistory lockHistory() const { return m_lockHistory; }
</span><ins>+    void setLockHistory(LockHistory value) { m_lockHistory = value; }
+
</ins><span class="cx">     LockBackForwardList lockBackForwardList() const { return m_lockBackForwardList; }
</span><ins>+    void setlockBackForwardList(LockBackForwardList value) { m_lockBackForwardList = value; }
+
+    const String& clientRedirectSourceForHistory() const { return m_clientRedirectSourceForHistory; }
+    void setClientRedirectSourceForHistory(const String& clientRedirectSourceForHistory) { m_clientRedirectSourceForHistory = clientRedirectSourceForHistory; }
+
</ins><span class="cx">     ShouldSendReferrer shouldSendReferrer() const { return m_shouldSendReferrer; }
</span><span class="cx">     AllowNavigationToInvalidURL allowNavigationToInvalidURL() const { return m_allowNavigationToInvalidURL; }
</span><span class="cx">     NewFrameOpenerPolicy newFrameOpenerPolicy() const { return m_newFrameOpenerPolicy; }
</span><span class="lines">@@ -97,6 +104,7 @@
</span><span class="cx">     ResourceRequest m_resourceRequest;
</span><span class="cx">     String m_frameName;
</span><span class="cx">     SubstituteData m_substituteData;
</span><ins>+    String m_clientRedirectSourceForHistory;
</ins><span class="cx"> 
</span><span class="cx">     bool m_shouldCheckNewWindowPolicy { false };
</span><span class="cx">     bool m_shouldTreatAsContinuingLoad { false };
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderFrameLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1360,6 +1360,8 @@
</span><span class="cx">     if (m_frame.page() && m_frame.page()->openedViaWindowOpenWithOpener())
</span><span class="cx">         action.setOpenedViaWindowOpenWithOpener();
</span><span class="cx">     action.setHasOpenedFrames(!m_openedFrames.isEmpty());
</span><ins>+    action.setLockHistory(lockHistory);
+    action.setLockBackForwardList(frameLoadRequest.lockBackForwardList());
</ins><span class="cx"> 
</span><span class="cx">     if (!targetFrame && !effectiveFrameName.isEmpty()) {
</span><span class="cx">         action = action.copyWithShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(m_frame, frameLoadRequest));
</span><span class="lines">@@ -1458,6 +1460,13 @@
</span><span class="cx">     addSameSiteInfoToRequestIfNeeded(loader->request());
</span><span class="cx">     applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, request);
</span><span class="cx"> 
</span><ins>+    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;
+    }
+
</ins><span class="cx">     SetForScope<bool> currentLoadShouldBeTreatedAsContinuingLoadGuard(m_currentLoadShouldBeTreatedAsContinuingLoad, request.shouldTreatAsContinuingLoad());
</span><span class="cx">     load(loader.get(), request.shouldSkipSafeBrowsingCheck());
</span><span class="cx"> }
</span><span class="lines">@@ -1495,7 +1504,7 @@
</span><span class="cx">         type = FrameLoadType::Same;
</span><span class="cx">     } else if (shouldTreatURLAsSameAsCurrent(newDocumentLoader.unreachableURL()) && isReload(m_loadType))
</span><span class="cx">         type = m_loadType;
</span><del>-    else if (m_loadType == FrameLoadType::RedirectWithLockedBackForwardList && !newDocumentLoader.unreachableURL().isEmpty() && newDocumentLoader.substituteData().isValid())
</del><ins>+    else if (m_loadType == FrameLoadType::RedirectWithLockedBackForwardList && ((!newDocumentLoader.unreachableURL().isEmpty() && newDocumentLoader.substituteData().isValid()) || m_currentLoadShouldBeTreatedAsContinuingLoad))
</ins><span class="cx">         type = FrameLoadType::RedirectWithLockedBackForwardList;
</span><span class="cx">     else
</span><span class="cx">         type = FrameLoadType::Standard;
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderHistoryControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/HistoryController.cpp (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -440,7 +440,7 @@
</span><span class="cx">         if (Page* page = m_frame.page())
</span><span class="cx">             addVisitedLink(*page, historyURL);
</span><span class="cx"> 
</span><del>-        if (!m_frame.loader().documentLoader()->didCreateGlobalHistoryEntry() && m_frame.loader().documentLoader()->unreachableURL().isEmpty() && !m_frame.document()->url().isEmpty())
</del><ins>+        if (!m_frame.loader().documentLoader()->didCreateGlobalHistoryEntry() && m_frame.loader().documentLoader()->unreachableURL().isEmpty())
</ins><span class="cx">             m_frame.loader().client().updateGlobalHistoryRedirectLinks();
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderHistoryControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/HistoryController.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -75,7 +75,7 @@
</span><span class="cx">     void updateForFrameLoadCompleted();
</span><span class="cx"> 
</span><span class="cx">     HistoryItem* currentItem() const { return m_currentItem.get(); }
</span><del>-    void setCurrentItem(HistoryItem&);
</del><ins>+    WEBCORE_EXPORT void setCurrentItem(HistoryItem&);
</ins><span class="cx">     void setCurrentItemTitle(const StringWithDirection&);
</span><span class="cx">     bool currentItemShouldBeReplaced() const;
</span><span class="cx">     WEBCORE_EXPORT void replaceCurrentItem(HistoryItem*);
</span></span></pre></div>
<a id="trunkSourceWebCoreloaderNavigationActionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/loader/NavigationAction.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -130,6 +130,12 @@
</span><span class="cx">     void setTargetBackForwardItem(HistoryItem&);
</span><span class="cx">     const std::optional<BackForwardItemIdentifier>& targetBackForwardItemIdentifier() const { return m_targetBackForwardItemIdentifier; }
</span><span class="cx"> 
</span><ins>+    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; }
+
</ins><span class="cx"> private:
</span><span class="cx">     // Do not add a strong reference to the originating document or a subobject that holds the
</span><span class="cx">     // originating document. See comment above the class for more details.
</span><span class="lines">@@ -147,6 +153,8 @@
</span><span class="cx">     bool m_openedViaWindowOpenWithOpener { false };
</span><span class="cx">     std::optional<PageIDAndFrameIDPair> m_opener;
</span><span class="cx">     std::optional<BackForwardItemIdentifier> m_targetBackForwardItemIdentifier;
</span><ins>+    LockHistory m_lockHistory { LockHistory::No };
+    LockBackForwardList m_lockBackForwardList { LockBackForwardList::No };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2018-10-23  Chris Dumez  <cdumez@apple.com>
+
+        [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:
+
</ins><span class="cx"> 2018-10-23  Claudio Saavedra  <csaavedra@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         [WPE][GTK] Pass full certificate chain in CertificateInfo coder
</span></span></pre></div>
<a id="trunkSourceWebKitSharedLoadParameterscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Shared/LoadParameters.cpp (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -50,6 +50,9 @@
</span><span class="cx">     encoder << shouldTreatAsContinuingLoad;
</span><span class="cx">     encoder << userData;
</span><span class="cx">     encoder << forSafeBrowsing;
</span><ins>+    encoder.encodeEnum(lockHistory);
+    encoder.encodeEnum(lockBackForwardList);
+    encoder << clientRedirectSourceForHistory;
</ins><span class="cx"> 
</span><span class="cx">     platformEncode(encoder);
</span><span class="cx"> }
</span><span class="lines">@@ -108,7 +111,19 @@
</span><span class="cx"> 
</span><span class="cx">     if (!decoder.decode(data.forSafeBrowsing))
</span><span class="cx">         return false;
</span><del>-    
</del><ins>+
+    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);
+
</ins><span class="cx">     if (!platformDecode(decoder, data))
</span><span class="cx">         return false;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitSharedLoadParametersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Shared/LoadParameters.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include "DataReference.h"
</span><span class="cx"> #include "SandboxExtension.h"
</span><span class="cx"> #include "UserData.h"
</span><ins>+#include <WebCore/FrameLoaderTypes.h>
</ins><span class="cx"> #include <WebCore/ResourceRequest.h>
</span><span class="cx"> 
</span><span class="cx"> OBJC_CLASS NSDictionary;
</span><span class="lines">@@ -63,6 +64,9 @@
</span><span class="cx">     bool shouldTreatAsContinuingLoad { false };
</span><span class="cx">     UserData userData;
</span><span class="cx">     bool forSafeBrowsing { false };
</span><ins>+    WebCore::LockHistory lockHistory { WebCore::LockHistory::No };
+    WebCore::LockBackForwardList lockBackForwardList { WebCore::LockBackForwardList::No };
+    String clientRedirectSourceForHistory;
</ins><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx">     RetainPtr<NSDictionary> dataDetectionContext;
</span></span></pre></div>
<a id="trunkSourceWebKitSharedNavigationActionDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Shared/NavigationActionData.cpp (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -51,6 +51,9 @@
</span><span class="cx">     encoder << opener;
</span><span class="cx">     encoder << requesterOrigin;
</span><span class="cx">     encoder << targetBackForwardItemIdentifier;
</span><ins>+    encoder.encodeEnum(lockHistory);
+    encoder.encodeEnum(lockBackForwardList);
+    encoder << clientRedirectSourceForHistory;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> std::optional<NavigationActionData> NavigationActionData::decode(IPC::Decoder& decoder)
</span><span class="lines">@@ -128,11 +131,24 @@
</span><span class="cx">     decoder >> targetBackForwardItemIdentifier;
</span><span class="cx">     if (!targetBackForwardItemIdentifier)
</span><span class="cx">         return std::nullopt;
</span><del>-        
</del><ins>+
+    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;
+
</ins><span class="cx">     return {{ WTFMove(navigationType), WTFMove(modifiers), WTFMove(mouseButton), WTFMove(syntheticClickType), WTFMove(*userGestureTokenIdentifier),
</span><span class="cx">         WTFMove(*canHandleRequest), WTFMove(shouldOpenExternalURLsPolicy), WTFMove(*downloadAttribute), WTFMove(clickLocationInRootViewCoordinates),
</span><span class="cx">         WTFMove(*isRedirect), *treatAsSameOriginNavigation, *hasOpenedFrames, *openedViaWindowOpenWithOpener, WTFMove(*opener), WTFMove(*requesterOrigin),
</span><del>-        WTFMove(*targetBackForwardItemIdentifier) }};
</del><ins>+        WTFMove(*targetBackForwardItemIdentifier), lockHistory, lockBackForwardList, WTFMove(*clientRedirectSourceForHistory) }};
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKitSharedNavigationActionDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Shared/NavigationActionData.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -58,6 +58,9 @@
</span><span class="cx">     std::optional<std::pair<uint64_t, uint64_t>> opener;
</span><span class="cx">     WebCore::SecurityOriginData requesterOrigin;
</span><span class="cx">     std::optional<WebCore::BackForwardItemIdentifier> targetBackForwardItemIdentifier;
</span><ins>+    WebCore::LockHistory lockHistory;
+    WebCore::LockBackForwardList lockBackForwardList;
+    WTF::String clientRedirectSourceForHistory;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKitSharedWebBackForwardListItemcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Shared/WebBackForwardListItem.cpp (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -115,7 +115,6 @@
</span><span class="cx"> 
</span><span class="cx"> void WebBackForwardListItem::setSuspendedPage(SuspendedPageProxy& page)
</span><span class="cx"> {
</span><del>-    ASSERT(!m_suspendedPage);
</del><span class="cx">     m_suspendedPage = makeWeakPtr(page);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPIAPINavigationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/APINavigation.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -101,6 +101,15 @@
</span><span class="cx">     void setRequesterOrigin(const WebCore::SecurityOriginData& origin) { m_requesterOrigin = origin; }
</span><span class="cx">     const WebCore::SecurityOriginData& requesterOrigin() const { return m_requesterOrigin; }
</span><span class="cx"> 
</span><ins>+    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; }
+
</ins><span class="cx"> #if !LOG_DISABLED
</span><span class="cx">     const char* loggingString() const;
</span><span class="cx"> #endif
</span><span class="lines">@@ -127,6 +136,9 @@
</span><span class="cx">     bool m_openedViaWindowOpenWithOpener { false };
</span><span class="cx">     std::optional<std::pair<uint64_t, uint64_t>> m_opener;
</span><span class="cx">     WebCore::SecurityOriginData m_requesterOrigin;
</span><ins>+    WebCore::LockHistory m_lockHistory;
+    WebCore::LockBackForwardList m_lockBackForwardList;
+    WTF::String m_clientRedirectSourceForHistory;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace API
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPIAPINavigationClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/APINavigationClient.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -73,7 +73,8 @@
</span><span class="cx"> 
</span><span class="cx">     virtual void didStartProvisionalNavigation(WebKit::WebPageProxy&, Navigation*, Object*) { }
</span><span class="cx">     virtual void didReceiveServerRedirectForProvisionalNavigation(WebKit::WebPageProxy&, Navigation*, Object*) { }
</span><del>-    virtual void willPerformClientRedirect(WebKit::WebPageProxy&, const WTF::String&, double) { }
</del><ins>+    virtual void willPerformClientRedirect(WebKit::WebPageProxy&, const WTF::String& destinationURL, double) { }
+    virtual void didPerformClientRedirect(WebKit::WebPageProxy&, const WTF::String& sourceURL, const WTF::String& destinationURL) { }
</ins><span class="cx">     virtual void didCancelClientRedirect(WebKit::WebPageProxy&) { }
</span><span class="cx">     virtual void didFailProvisionalNavigationWithError(WebKit::WebPageProxy&, WebKit::WebFrameProxy&, Navigation*, const WebCore::ResourceError&, Object*) { }
</span><span class="cx">     virtual void didFailProvisionalLoadInSubframeWithError(WebKit::WebPageProxy&, WebKit::WebFrameProxy&, const WebCore::SecurityOriginData&, Navigation*, const WebCore::ResourceError&, Object*) { }
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessAPICocoaWKNavigationDelegatePrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -68,6 +68,7 @@
</span><span class="cx"> - (void)_webView:(WKWebView *)webView navigation:(WKNavigation *)navigation didFailProvisionalLoadInSubframe:(WKFrameInfo *)subframe withError:(NSError *)error;
</span><span class="cx"> 
</span><span class="cx"> - (void)_webView:(WKWebView *)webView willPerformClientRedirectToURL:(NSURL *)URL delay:(NSTimeInterval)delay;
</span><ins>+- (void)_webView:(WKWebView *)webView didPerformClientRedirectFromURL:(NSURL *)sourceURL toURL:(NSURL *)destinationURL;
</ins><span class="cx"> - (void)_webViewDidCancelClientRedirect:(WKWebView *)webView;
</span><span class="cx"> 
</span><span class="cx"> - (void)_webView:(WKWebView *)webView navigationDidFinishDocumentLoad:(WKNavigation *)navigation;
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessCocoaNavigationStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -98,6 +98,7 @@
</span><span class="cx">         void didStartProvisionalNavigation(WebPageProxy&, API::Navigation*, API::Object*) override;
</span><span class="cx">         void didReceiveServerRedirectForProvisionalNavigation(WebPageProxy&, API::Navigation*, API::Object*) override;
</span><span class="cx">         void willPerformClientRedirect(WebPageProxy&, const WTF::String&, double) override;
</span><ins>+        void didPerformClientRedirect(WebPageProxy&, const WTF::String&, const WTF::String&) override;
</ins><span class="cx">         void didCancelClientRedirect(WebPageProxy&) override;
</span><span class="cx">         void didFailProvisionalNavigationWithError(WebPageProxy&, WebFrameProxy&, API::Navigation*, const WebCore::ResourceError&, API::Object*) override;
</span><span class="cx">         void didFailProvisionalLoadInSubframeWithError(WebPageProxy&, WebFrameProxy&, const WebCore::SecurityOriginData&, API::Navigation*, const WebCore::ResourceError&, API::Object*) override;
</span><span class="lines">@@ -195,6 +196,7 @@
</span><span class="cx">         bool webViewDidFailProvisionalNavigationWithError : 1;
</span><span class="cx">         bool webViewNavigationDidFailProvisionalLoadInSubframeWithError : 1;
</span><span class="cx">         bool webViewWillPerformClientRedirect : 1;
</span><ins>+        bool webViewDidPerformClientRedirect : 1;
</ins><span class="cx">         bool webViewDidCancelClientRedirect : 1;
</span><span class="cx">         bool webViewDidCommitNavigation : 1;
</span><span class="cx">         bool webViewNavigationDidFinishDocumentLoad : 1;
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessCocoaNavigationStatemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -157,6 +157,7 @@
</span><span class="cx"> 
</span><span class="cx">     m_navigationDelegateMethods.webViewNavigationDidFailProvisionalLoadInSubframeWithError = [delegate respondsToSelector:@selector(_webView:navigation:didFailProvisionalLoadInSubframe:withError:)];
</span><span class="cx">     m_navigationDelegateMethods.webViewWillPerformClientRedirect = [delegate respondsToSelector:@selector(_webView:willPerformClientRedirectToURL:delay:)];
</span><ins>+    m_navigationDelegateMethods.webViewDidPerformClientRedirect = [delegate respondsToSelector:@selector(_webView:didPerformClientRedirectFromURL:toURL:)];
</ins><span class="cx">     m_navigationDelegateMethods.webViewDidCancelClientRedirect = [delegate respondsToSelector:@selector(_webViewDidCancelClientRedirect:)];
</span><span class="cx">     m_navigationDelegateMethods.webViewNavigationDidFinishDocumentLoad = [delegate respondsToSelector:@selector(_webView:navigationDidFinishDocumentLoad:)];
</span><span class="cx">     m_navigationDelegateMethods.webViewNavigationDidSameDocumentNavigation = [delegate respondsToSelector:@selector(_webView:navigation:didSameDocumentNavigation:)];
</span><span class="lines">@@ -704,6 +705,21 @@
</span><span class="cx">     [static_cast<id <WKNavigationDelegatePrivate>>(navigationDelegate) _webView:m_navigationState.m_webView willPerformClientRedirectToURL:url delay:delay];
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+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];
+}
+
</ins><span class="cx"> void NavigationState::NavigationClient::didCancelClientRedirect(WebPageProxy& page)
</span><span class="cx"> {
</span><span class="cx">     if (!m_navigationState.m_navigationDelegateMethods.webViewDidCancelClientRedirect)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessFrameLoadStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/FrameLoadState.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx"> 
</span><span class="cx">     State state() const { return m_state; }
</span><span class="cx">     const WebCore::URL& url() const { return m_url; }
</span><ins>+    void setURL(const WebCore::URL& url) { m_url = url; }
</ins><span class="cx">     const WebCore::URL& provisionalURL() const { return m_provisionalURL; }
</span><span class="cx"> 
</span><span class="cx">     void setUnreachableURL(const WebCore::URL&);
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -103,6 +103,7 @@
</span><span class="cx"> #include "WebImage.h"
</span><span class="cx"> #include "WebInspectorProxy.h"
</span><span class="cx"> #include "WebInspectorUtilities.h"
</span><ins>+#include "WebNavigationDataStore.h"
</ins><span class="cx"> #include "WebNavigationState.h"
</span><span class="cx"> #include "WebNotificationManagerProxy.h"
</span><span class="cx"> #include "WebOpenPanelResultListenerProxy.h"
</span><span class="lines">@@ -1017,6 +1018,9 @@
</span><span class="cx">     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
</span><span class="cx">     loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
</span><span class="cx">     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
</span><ins>+    loadParameters.lockHistory = navigation.lockHistory();
+    loadParameters.lockBackForwardList = navigation.lockBackForwardList();
+    loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
</ins><span class="cx">     bool createdExtension = maybeInitializeSandboxExtensionHandle(url, loadParameters.sandboxExtensionHandle);
</span><span class="cx">     if (createdExtension)
</span><span class="cx">         m_process->willAcquireUniversalFileReadSandboxExtension();
</span><span class="lines">@@ -2548,6 +2552,7 @@
</span><span class="cx"> 
</span><span class="cx">     Ref<WebProcessProxy> previousProcess = m_process.copyRef();
</span><span class="cx">     std::optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? std::make_optional(m_mainFrame->frameID()) : std::nullopt;
</span><ins>+    auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : WebCore::URL();
</ins><span class="cx"> 
</span><span class="cx">     ASSERT(m_process.ptr() != process.ptr());
</span><span class="cx"> 
</span><span class="lines">@@ -2575,21 +2580,34 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    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);
+    }
+
</ins><span class="cx">     // FIXME: Work out timing of responding with the last policy delegate, etc
</span><span class="cx">     ASSERT(!navigation.currentRequest().isEmpty());
</span><span class="cx">     loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes);
</span><span class="cx"> 
</span><del>-    // 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);
</del><ins>+    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) {
</ins><span class="cx">             m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
</span><span class="cx">             didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigation->navigationID(), WTFMove(request), { });
</span><del>-        };
-    }
</del><ins>+        }
+    };
</ins><span class="cx"> 
</span><span class="cx">     bool isInitialNavigationInNewWindow = openedByDOM() && !hasCommittedAnyProvisionalLoads();
</span><span class="cx">     if (!isInitialNavigationInNewWindow || !mainFrameIDInPreviousProcess)
</span><span class="lines">@@ -4115,6 +4133,9 @@
</span><span class="cx">         navigation->setOpenedViaWindowOpenWithOpener();
</span><span class="cx">     navigation->setOpener(navigationActionData.opener);
</span><span class="cx">     navigation->setRequesterOrigin(navigationActionData.requesterOrigin);
</span><ins>+    navigation->setLockHistory(navigationActionData.lockHistory);
+    navigation->setLockBackForwardList(navigationActionData.lockBackForwardList);
+    navigation->setClientRedirectSourceForHistory(navigationActionData.clientRedirectSourceForHistory);
</ins><span class="cx"> 
</span><span class="cx"> #if ENABLE(CONTENT_FILTERING)
</span><span class="cx">     if (frame.didHandleContentFilterUnblockNavigation(request))
</span><span class="lines">@@ -4302,8 +4323,10 @@
</span><span class="cx">     MESSAGE_CHECK_URL(sourceURLString);
</span><span class="cx">     MESSAGE_CHECK_URL(destinationURLString);
</span><span class="cx"> 
</span><del>-    if (frame->isMainFrame())
</del><ins>+    if (frame->isMainFrame()) {
</ins><span class="cx">         m_historyClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString);
</span><ins>+        m_navigationClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString);
+    }
</ins><span class="cx">     process().processPool().historyClient().didPerformClientRedirect(process().processPool(), *this, sourceURLString, destinationURLString, *frame);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebCoreSupportWebFrameLoaderClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -871,6 +871,8 @@
</span><span class="cx">     if (auto& requester = navigationAction.requester())
</span><span class="cx">         navigationActionData.requesterOrigin = requester->securityOrigin().data();
</span><span class="cx">     navigationActionData.targetBackForwardItemIdentifier = navigationAction.targetBackForwardItemIdentifier();
</span><ins>+    navigationActionData.lockHistory = navigationAction.lockHistory();
+    navigationActionData.lockBackForwardList = navigationAction.lockBackForwardList();
</ins><span class="cx"> 
</span><span class="cx">     WebCore::Frame* coreFrame = m_frame->coreFrame();
</span><span class="cx">     if (!coreFrame)
</span><span class="lines">@@ -884,6 +886,8 @@
</span><span class="cx">     if (!documentLoader)
</span><span class="cx">         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
</span><span class="cx"> 
</span><ins>+    navigationActionData.clientRedirectSourceForHistory = documentLoader->clientRedirectSourceForHistory();
+
</ins><span class="cx">     // Notify the UIProcess.
</span><span class="cx">     Ref<WebFrame> protect(*m_frame);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1307,6 +1307,9 @@
</span><span class="cx">     ShouldOpenExternalURLsPolicy externalURLsPolicy = static_cast<ShouldOpenExternalURLsPolicy>(loadParameters.shouldOpenExternalURLsPolicy);
</span><span class="cx">     frameLoadRequest.setShouldOpenExternalURLsPolicy(externalURLsPolicy);
</span><span class="cx">     frameLoadRequest.setShouldTreatAsContinuingLoad(loadParameters.shouldTreatAsContinuingLoad);
</span><ins>+    frameLoadRequest.setLockHistory(loadParameters.lockHistory);
+    frameLoadRequest.setlockBackForwardList(loadParameters.lockBackForwardList);
+    frameLoadRequest.setClientRedirectSourceForHistory(loadParameters.clientRedirectSourceForHistory);
</ins><span class="cx"> 
</span><span class="cx">     corePage()->userInputBridge().loadRequest(WTFMove(frameLoadRequest));
</span><span class="cx"> 
</span><span class="lines">@@ -2606,6 +2609,14 @@
</span><span class="cx">     restoreSessionInternal(itemStates, WasRestoredByAPIRequest::No, WebBackForwardListProxy::OverwriteExistingItem::Yes);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+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);
+}
+
</ins><span class="cx"> void WebPage::requestFontAttributesAtSelectionStart(CallbackID callbackID)
</span><span class="cx"> {
</span><span class="cx">     auto attributes = m_page->focusController().focusedOrMainFrame().editor().fontAttributesAtSelectionStart();
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -1209,6 +1209,7 @@
</span><span class="cx">     void restoreSession(const Vector<BackForwardListItemState>&);
</span><span class="cx">     void didRemoveBackForwardItem(const WebCore::BackForwardItemIdentifier&);
</span><span class="cx">     void updateBackForwardListForReattach(const Vector<WebKit::BackForwardListItemState>&);
</span><ins>+    void setCurrentHistoryItemForReattach(WebKit::BackForwardListItemState&&);
</ins><span class="cx"> 
</span><span class="cx">     void requestFontAttributesAtSelectionStart(CallbackID);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -157,6 +157,7 @@
</span><span class="cx">     
</span><span class="cx">     RestoreSession(Vector<WebKit::BackForwardListItemState> itemStates)
</span><span class="cx">     UpdateBackForwardListForReattach(Vector<WebKit::BackForwardListItemState> itemStates)
</span><ins>+    SetCurrentHistoryItemForReattach(struct WebKit::BackForwardListItemState itemState)
</ins><span class="cx"> 
</span><span class="cx">     DidRemoveBackForwardItem(struct WebCore::BackForwardItemIdentifier backForwardItemID)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog    2018-10-23 17:26:55 UTC (rev 237354)
+++ trunk/Tools/ChangeLog       2018-10-23 17:54:34 UTC (rev 237355)
</span><span class="lines">@@ -1,3 +1,17 @@
</span><ins>+2018-10-23  Chris Dumez  <cdumez@apple.com>
+
+        [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:]):
+
</ins><span class="cx"> 2018-10-23  Claudio Saavedra  <csaavedra@igalia.com>
</span><span class="cx"> 
</span><span class="cx">         [WPE][GTK] Pass full certificate chain in CertificateInfo coder
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKitCocoaProcessSwapOnNavigationmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (237354 => 237355)</h4>
<pre class="diff"><span>
<span class="info">--- 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)
</span><span class="lines">@@ -68,6 +68,11 @@
</span><span class="cx"> static bool receivedMessage;
</span><span class="cx"> static bool serverRedirected;
</span><span class="cx"> static HashSet<pid_t> seenPIDs;
</span><ins>+static bool willPerformClientRedirect;
+static bool didPerformClientRedirect;
+static RetainPtr<NSURL> clientRedirectSourceURL;
+static RetainPtr<NSURL> clientRedirectDestinationURL;
+
</ins><span class="cx"> @interface PSONMessageHandler : NSObject <WKScriptMessageHandler>
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="lines">@@ -124,6 +129,20 @@
</span><span class="cx">     serverRedirected = true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (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;
+}
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> static RetainPtr<WKWebView> createdWebView;
</span><span class="lines">@@ -245,6 +264,22 @@
</span><span class="cx"> </head>
</span><span class="cx"> )PSONRESOURCE";
</span><span class="cx"> 
</span><ins>+static const char* linkToCrossSiteClientSideRedirectBytes = R"PSONRESOURCE(
+<body>
+  <a id="testLink" href="pson://www.google.com/clientSideRedirect.html">Link 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";
+
</ins><span class="cx"> #if PLATFORM(MAC)
</span><span class="cx"> 
</span><span class="cx"> static const char* windowOpenCrossSiteNoOpenerTestBytes = R"PSONRESOURCE(
</span><span class="lines">@@ -1097,6 +1132,143 @@
</span><span class="cx">     EXPECT_EQ(2u, seenPIDs.size());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+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);
+}
+
</ins><span class="cx"> static const char* sessionStorageTestBytes = R"PSONRESOURCE(
</span><span class="cx"> <head>
</span><span class="cx"> <script>
</span></span></pre>
</div>
</div>

</body>
</html>