<!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>[238353] trunk/Source/WebKit</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/238353">238353</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2018-11-17 14:06:56 -0800 (Sat, 17 Nov 2018)</dd>
</dl>

<h3>Log Message</h3>
<pre>[PSON] ASSERTION FAILED: m_uncommittedState.state == State::Committed
https://bugs.webkit.org/show_bug.cgi?id=191781

Reviewed by Ryosuke Niwa.

The crash was happening when switching to a suspended page that is not yet done
suspending (e.g. in case of very fast back/forward navigation). The WebPageProxy
would reattach to the suspended process and get load notifications that it did
not expect since it did not schedule any load yet. Those notifications are for
the about:blank load we do for page suspension.

To address the issue, make swapToWebProcess() asynchronous and take a completion
handler. When we try to unsuspend a SuspendedPageProxy, we first make sure it
is actually done suspending. If it is not done suspending, we wait until it is
before telling in to unsuspend and proceeding with the new load.

* UIProcess/SuspendedPageProxy.cpp:
(WebKit::SuspendedPageProxy::unsuspend):
(WebKit::SuspendedPageProxy::didFinishLoad):
* UIProcess/SuspendedPageProxy.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::swapToWebProcess):
(WebKit::WebPageProxy::continueNavigationInNewProcess):
* UIProcess/WebPageProxy.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitUIProcessSuspendedPageProxycpp">trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessSuspendedPageProxyh">trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxycpp">trunk/Source/WebKit/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxyh">trunk/Source/WebKit/UIProcess/WebPageProxy.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (238352 => 238353)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2018-11-17 22:01:15 UTC (rev 238352)
+++ trunk/Source/WebKit/ChangeLog       2018-11-17 22:06:56 UTC (rev 238353)
</span><span class="lines">@@ -1,5 +1,32 @@
</span><span class="cx"> 2018-11-17  Chris Dumez  <cdumez@apple.com>
</span><span class="cx"> 
</span><ins>+        [PSON] ASSERTION FAILED: m_uncommittedState.state == State::Committed
+        https://bugs.webkit.org/show_bug.cgi?id=191781
+
+        Reviewed by Ryosuke Niwa.
+
+        The crash was happening when switching to a suspended page that is not yet done
+        suspending (e.g. in case of very fast back/forward navigation). The WebPageProxy
+        would reattach to the suspended process and get load notifications that it did
+        not expect since it did not schedule any load yet. Those notifications are for
+        the about:blank load we do for page suspension.
+
+        To address the issue, make swapToWebProcess() asynchronous and take a completion
+        handler. When we try to unsuspend a SuspendedPageProxy, we first make sure it
+        is actually done suspending. If it is not done suspending, we wait until it is
+        before telling in to unsuspend and proceeding with the new load.
+
+        * UIProcess/SuspendedPageProxy.cpp:
+        (WebKit::SuspendedPageProxy::unsuspend):
+        (WebKit::SuspendedPageProxy::didFinishLoad):
+        * UIProcess/SuspendedPageProxy.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::swapToWebProcess):
+        (WebKit::WebPageProxy::continueNavigationInNewProcess):
+        * UIProcess/WebPageProxy.h:
+
+2018-11-17  Chris Dumez  <cdumez@apple.com>
+
</ins><span class="cx">         Unreviewed follow-up to r238343 to address debug assertions in 2 API tests.
</span><span class="cx"> 
</span><span class="cx">         * UIProcess/Network/NetworkProcessProxy.cpp:
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessSuspendedPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp (238352 => 238353)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp     2018-11-17 22:01:15 UTC (rev 238352)
+++ trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp        2018-11-17 22:06:56 UTC (rev 238353)
</span><span class="lines">@@ -103,13 +103,22 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SuspendedPageProxy::unsuspend()
</del><ins>+void SuspendedPageProxy::unsuspend(CompletionHandler<void()>&& completionHandler)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_isSuspended);
</span><span class="cx"> 
</span><del>-    m_isSuspended = false;
-    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
-    m_process->send(Messages::WebPage::SetIsSuspended(false), m_page.pageID());
</del><ins>+    auto doUnsuspend = [this, completionHandler = WTFMove(completionHandler)]() mutable {
+        m_isSuspended = false;
+        m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
+        m_process->send(Messages::WebPage::SetIsSuspended(false), m_page.pageID());
+        completionHandler();
+    };
+
+    if (!m_finishedSuspending) {
+        ASSERT(!m_finishedSuspendingHandler);
+        m_finishedSuspendingHandler = WTFMove(doUnsuspend);
+    } else
+        doUnsuspend();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SuspendedPageProxy::didFinishLoad()
</span><span class="lines">@@ -116,11 +125,12 @@
</span><span class="cx"> {
</span><span class="cx">     LOG(ProcessSwapping, "SuspendedPageProxy %s from process %i finished transition to suspended", loggingString(), m_process->processIdentifier());
</span><span class="cx"> 
</span><del>-#if !LOG_DISABLED
</del><span class="cx">     m_finishedSuspending = true;
</span><del>-#endif
</del><span class="cx"> 
</span><span class="cx">     m_process->send(Messages::WebProcess::UpdateActivePages(), 0);
</span><ins>+
+    if (auto finishedSuspendingHandler = WTFMove(m_finishedSuspendingHandler))
+        finishedSuspendingHandler();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SuspendedPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder& decoder)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessSuspendedPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h (238352 => 238353)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h       2018-11-17 22:01:15 UTC (rev 238352)
+++ trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h  2018-11-17 22:06:56 UTC (rev 238353)
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx">     uint64_t mainFrameID() const { return m_mainFrameID; }
</span><span class="cx">     const String& registrableDomain() const { return m_registrableDomain; }
</span><span class="cx"> 
</span><del>-    void unsuspend();
</del><ins>+    void unsuspend(CompletionHandler<void()>&&);
</ins><span class="cx"> 
</span><span class="cx"> #if !LOG_DISABLED
</span><span class="cx">     const char* loggingString() const;
</span><span class="lines">@@ -66,9 +66,8 @@
</span><span class="cx"> 
</span><span class="cx">     bool m_isSuspended { true };
</span><span class="cx"> 
</span><del>-#if !LOG_DISABLED
</del><span class="cx">     bool m_finishedSuspending { false };
</span><del>-#endif
</del><ins>+    CompletionHandler<void()> m_finishedSuspendingHandler;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (238352 => 238353)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp   2018-11-17 22:01:15 UTC (rev 238352)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp      2018-11-17 22:06:56 UTC (rev 238353)
</span><span class="lines">@@ -750,7 +750,7 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, API::Navigation& navigation, std::optional<uint64_t> mainFrameIDInPreviousProcess)
</del><ins>+void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, API::Navigation& navigation, std::optional<uint64_t> mainFrameIDInPreviousProcess, CompletionHandler<void()>&& completionHandler)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!m_isClosed);
</span><span class="cx">     RELEASE_LOG_IF_ALLOWED(Process, "%p WebPageProxy::swapToWebProcess\n", this);
</span><span class="lines">@@ -760,29 +760,39 @@
</span><span class="cx">         if (backForwardListItem->suspendedPage() && &backForwardListItem->suspendedPage()->process() == process.ptr()) {
</span><span class="cx">             destinationSuspendedPage = this->process().processPool().takeSuspendedPage(*backForwardListItem->suspendedPage());
</span><span class="cx">             ASSERT(destinationSuspendedPage);
</span><del>-            destinationSuspendedPage->unsuspend();
</del><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
-    bool didSuspendPreviousPage = suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess);
-    m_process->removeWebPage(*this, m_pageID);
</del><ins>+    auto* destinationSuspendedPagePtr = destinationSuspendedPage.get();
+    auto doSwap = [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), process = WTFMove(process), mainFrameIDInPreviousProcess, destinationSuspendedPage = WTFMove(destinationSuspendedPage), completionHandler = WTFMove(completionHandler)]() mutable {
+        processDidTerminate(ProcessTerminationReason::NavigationSwap);
</ins><span class="cx"> 
</span><del>-    m_process = WTFMove(process);
-    m_isValid = true;
</del><ins>+        m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
+        bool didSuspendPreviousPage = suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess);
+        m_process->removeWebPage(*this, m_pageID);
</ins><span class="cx"> 
</span><del>-    // If we are reattaching to a SuspendedPage, then the WebProcess' WebPage already exists and
-    // WebPageProxy::didCreateMainFrame() will not be called to initialize m_mainFrame. In such
-    // case, we need to initialize m_mainFrame to reflect the fact the the WebProcess' WebPage
-    // already exists and already has a main frame.
-    if (destinationSuspendedPage) {
-        ASSERT(!m_mainFrame);
-        ASSERT(&destinationSuspendedPage->process() == m_process.ptr());
-        m_mainFrame = WebFrameProxy::create(*this, destinationSuspendedPage->mainFrameID());
-        m_process->frameCreated(destinationSuspendedPage->mainFrameID(), *m_mainFrame);
-    }
</del><ins>+        m_process = WTFMove(process);
+        m_isValid = true;
</ins><span class="cx"> 
</span><del>-    finishAttachingToWebProcess(didSuspendPreviousPage ? ShouldDelayAttachingDrawingArea::Yes : ShouldDelayAttachingDrawingArea::No);
</del><ins>+        // If we are reattaching to a SuspendedPage, then the WebProcess' WebPage already exists and
+        // WebPageProxy::didCreateMainFrame() will not be called to initialize m_mainFrame. In such
+        // case, we need to initialize m_mainFrame to reflect the fact the the WebProcess' WebPage
+        // already exists and already has a main frame.
+        if (destinationSuspendedPage) {
+            ASSERT(!m_mainFrame);
+            ASSERT(&destinationSuspendedPage->process() == m_process.ptr());
+            m_mainFrame = WebFrameProxy::create(*this, destinationSuspendedPage->mainFrameID());
+            m_process->frameCreated(destinationSuspendedPage->mainFrameID(), *m_mainFrame);
+        }
+
+        finishAttachingToWebProcess(didSuspendPreviousPage ? ShouldDelayAttachingDrawingArea::Yes : ShouldDelayAttachingDrawingArea::No);
+        completionHandler();
+    };
+
+    if (destinationSuspendedPagePtr)
+        destinationSuspendedPagePtr->unsuspend(WTFMove(doSwap));
+    else
+        doSwap();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::finishAttachingToWebProcess(ShouldDelayAttachingDrawingArea shouldDelayAttachingDrawingArea)
</span><span class="lines">@@ -2648,71 +2658,69 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_process.ptr() != process.ptr());
</span><span class="cx"> 
</span><del>-    processDidTerminate(ProcessTerminationReason::NavigationSwap);
</del><ins>+    swapToWebProcess(WTFMove(process), navigation, mainFrameIDInPreviousProcess, [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess, mainFrameURL = WTFMove(mainFrameURL)]() mutable {
+        if (auto* item = navigation->targetItem()) {
+            LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
</ins><span class="cx"> 
</span><del>-    swapToWebProcess(WTFMove(process), navigation, mainFrameIDInPreviousProcess);
</del><ins>+            auto transaction = m_pageLoadState.transaction();
+            m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
</ins><span class="cx"> 
</span><del>-    if (auto* item = navigation.targetItem()) {
-        LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
</del><ins>+            auto itemStates = m_backForwardList->filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
+                if (auto* page = item.suspendedPage()) {
+                    if (&page->process() == m_process.ptr())
+                        return false;
+                }
+                return &item != targetItem;
+            });
+            m_process->send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)), m_pageID);
+            m_process->send(Messages::WebPage::GoToBackForwardItem(navigation->navigationID(), item->itemID(), *navigation->backForwardFrameLoadType(), ShouldTreatAsContinuingLoad::Yes), m_pageID);
+            m_process->responsivenessTimer().start();
</ins><span class="cx"> 
</span><del>-        auto transaction = m_pageLoadState.transaction();
-        m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
</del><ins>+            return;
+        }
</ins><span class="cx"> 
</span><del>-        auto itemStates = m_backForwardList->filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
-            if (auto* page = item.suspendedPage()) {
-                if (&page->process() == m_process.ptr())
-                    return false;
-            }
-            return &item != targetItem;
-        });
-        m_process->send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)), m_pageID);
-        m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item->itemID(), *navigation.backForwardFrameLoadType(), ShouldTreatAsContinuingLoad::Yes), m_pageID);
-        m_process->responsivenessTimer().start();
</del><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"> 
</span><del>-        return;
-    }
</del><ins>+        // FIXME: Work out timing of responding with the last policy delegate, etc
+        ASSERT(!navigation->currentRequest().isEmpty());
+        if (auto& substituteData = navigation->substituteData())
+            loadDataWithNavigation(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get());
+        else
+            loadRequestWithNavigation(navigation, ResourceRequest { navigation->currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes);
</ins><span class="cx"> 
</span><del>-    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);
-    }
</del><ins>+        ASSERT(!m_mainFrame);
+        m_mainFrameCreationHandler = [this, protectedThis = makeRef(*this), navigation = navigation.copyRef(), 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);
</ins><span class="cx"> 
</span><del>-    // FIXME: Work out timing of responding with the last policy delegate, etc
-    ASSERT(!navigation.currentRequest().isEmpty());
-    if (auto& substituteData = navigation.substituteData())
-        loadDataWithNavigation(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get());
-    else
-        loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes);
</del><ins>+            // 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), { });
+            }
+        };
</ins><span class="cx"> 
</span><del>-    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);
</del><ins>+        bool isInitialNavigationInNewWindow = openedByDOM() && !hasCommittedAnyProvisionalLoads();
+        if (!isInitialNavigationInNewWindow || !mainFrameIDInPreviousProcess)
+            return;
</ins><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 (isServerRedirect) {
-            m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
-            didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigation->navigationID(), WTFMove(request), { });
-        }
-    };
-
-    bool isInitialNavigationInNewWindow = openedByDOM() && !hasCommittedAnyProvisionalLoads();
-    if (!isInitialNavigationInNewWindow || !mainFrameIDInPreviousProcess)
-        return;
-
-    m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess = *mainFrameIDInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) {
-        ASSERT(m_mainFrame);
-        GlobalFrameIdentifier navigatedFrameIdentifierInNewProcess { pageID(), m_mainFrame->frameID() };
-        previousProcess->send(Messages::WebPage::FrameBecameRemote(mainFrameIDInPreviousProcess, navigatedFrameIdentifierInNewProcess, windowIdentifier), pageID());
-    };
</del><ins>+        m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess = *mainFrameIDInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) {
+            ASSERT(m_mainFrame);
+            GlobalFrameIdentifier navigatedFrameIdentifierInNewProcess { pageID(), m_mainFrame->frameID() };
+            previousProcess->send(Messages::WebPage::FrameBecameRemote(mainFrameIDInPreviousProcess, navigatedFrameIdentifierInNewProcess, windowIdentifier), pageID());
+        };
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::setUserAgent(String&& userAgent)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (238352 => 238353)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.h     2018-11-17 22:01:15 UTC (rev 238352)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h        2018-11-17 22:06:56 UTC (rev 238353)
</span><span class="lines">@@ -1543,7 +1543,7 @@
</span><span class="cx">     void setCanShortCircuitHorizontalWheelEvents(bool canShortCircuitHorizontalWheelEvents) { m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents; }
</span><span class="cx"> 
</span><span class="cx">     void reattachToWebProcess();
</span><del>-    void swapToWebProcess(Ref<WebProcessProxy>&&, API::Navigation&, std::optional<uint64_t> mainFrameIDInPreviousProcess);
</del><ins>+    void swapToWebProcess(Ref<WebProcessProxy>&&, API::Navigation&, std::optional<uint64_t> mainFrameIDInPreviousProcess, CompletionHandler<void()>&&);
</ins><span class="cx"> 
</span><span class="cx">     void finishAttachingToWebProcess(ShouldDelayAttachingDrawingArea = ShouldDelayAttachingDrawingArea::No);
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>