Regression(PSON) View becomes blank after click a cross-site download link
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Jan 2019 20:40:02 +0000 (20:40 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Jan 2019 20:40:02 +0000 (20:40 +0000)
https://bugs.webkit.org/show_bug.cgi?id=193361
<rdar://problem/47099573>

Reviewed by Geoffrey Garen.

Source/WebCore:

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::commitProvisionalLoad):
When restoring from PageCache, make sure we notify the client that the load was committed
*before* we tell it that the navigation is complete. This would confuse the ProvisionalPageProxy
logic in the UIProcess.

Source/WebKit:

The issue tracked by rdar://problem/47099573 is that a provisional load may get
canceled (or converted into a download) *after* we've decided to process-swap.
In such cases, the view should keep displaying the current site and it should
still be interactive. However, with the previous PSON model, the view (pageProxy)
would have already swapped to the new process and would end up displaying the
initially empty document.

To address the issue, this patch introduces the concept of a provisional load
in the UIProcess, handled by a ProvisionalPageProxy which has its own privisional
process. The WebPageProxy owns the ProvisionalPageProxy but we do not commit the
provisional page until after the load was committed in the new process. This means
that the view / WebPageProxy keeps using the old process and displays the current
content until a load has committed in the provisional page. If no load commits
in the provisional process (e.g. because the load is cancelled or converted into
a download), then we merely destroy the ProvisionalPageProxy and terminate its
process, without impacting the WebPageProxy.

* Shared/WebPageCreationParameters.cpp:
(WebKit::WebPageCreationParameters::encode const):
(WebKit::WebPageCreationParameters::decode):
* Shared/WebPageCreationParameters.h:
Rename isSwapFromSuspended to isProcessSwap for clarity as we always want to
delay attaching the drawing area in case of a process-swap, no matter what
now that the previous process is kept alive until the provisional load is
committed in the new process.

* Shared/WebPolicyAction.h:
Drop Suspend policy action. At decidePolicyForNavigationAction time, in case of
process-swap, we now tell the previous process to simply ignore the load, while
we create a ProvisionalPageProxy to do the new load in a new process.
Suspension of the previous page in the old process, happens later, when a load
is actually committed in the new process.

* Sources.txt:
Add new ProvisionalPageProxy file.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _killWebContentProcessAndResetState]):
When calling _killWebContentProcessAndResetState on a WKWebView, kill both the current
process and the provisional one, to maintain previous behavior in our API tests.

* UIProcess/API/gtk/PageClientImpl.cpp:
(WebKit::PageClientImpl::createDrawingAreaProxy):
* UIProcess/API/gtk/PageClientImpl.h:
* UIProcess/API/wpe/PageClientImpl.cpp:
(WebKit::PageClientImpl::createDrawingAreaProxy):
* UIProcess/API/wpe/PageClientImpl.h:
* UIProcess/AcceleratedDrawingAreaProxy.cpp:
(WebKit::AcceleratedDrawingAreaProxy::AcceleratedDrawingAreaProxy):
(WebKit::AcceleratedDrawingAreaProxy::didUpdateBackingStoreState):
(WebKit::AcceleratedDrawingAreaProxy::sendUpdateBackingStoreState):
(WebKit::AcceleratedDrawingAreaProxy::waitForAndDispatchDidUpdateBackingStoreState):
(WebKit::AcceleratedDrawingAreaProxy::setNativeSurfaceHandleForCompositing):
(WebKit::AcceleratedDrawingAreaProxy::destroyNativeSurfaceHandleForCompositing):
* UIProcess/AcceleratedDrawingAreaProxy.h:
* UIProcess/Cocoa/WebViewImpl.h:
* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::createDrawingAreaProxy):
* UIProcess/DrawingAreaProxy.cpp:
(WebKit::DrawingAreaProxy::DrawingAreaProxy):
(WebKit::DrawingAreaProxy::~DrawingAreaProxy):
(WebKit::DrawingAreaProxy::viewExposedRectChangedTimerFired):
* UIProcess/DrawingAreaProxy.h:
(WebKit::DrawingAreaProxy::process):
* UIProcess/DrawingAreaProxyImpl.cpp:
(WebKit::DrawingAreaProxyImpl::DrawingAreaProxyImpl):
(WebKit::DrawingAreaProxyImpl::update):
* UIProcess/DrawingAreaProxyImpl.h:
* UIProcess/PageClient.h:
* UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm:
(WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
(WebKit::RemoteLayerTreeDrawingAreaProxy::~RemoteLayerTreeDrawingAreaProxy):
(WebKit::RemoteLayerTreeDrawingAreaProxy::deviceScaleFactorDidChange):
(WebKit::RemoteLayerTreeDrawingAreaProxy::sendUpdateGeometry):
(WebKit::RemoteLayerTreeDrawingAreaProxy::acceleratedAnimationDidStart):
(WebKit::RemoteLayerTreeDrawingAreaProxy::acceleratedAnimationDidEnd):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
(WebKit::RemoteLayerTreeDrawingAreaProxy::dispatchAfterEnsuringDrawing):
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::createDrawingAreaProxy):
* UIProcess/ios/WKContentView.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView _createDrawingAreaProxy:]):
* UIProcess/mac/PageClientImplMac.h:
* UIProcess/mac/PageClientImplMac.mm:
(WebKit::PageClientImpl::createDrawingAreaProxy):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::TiledCoreAnimationDrawingAreaProxy):
(WebKit::TiledCoreAnimationDrawingAreaProxy::deviceScaleFactorDidChange):
(WebKit::TiledCoreAnimationDrawingAreaProxy::colorSpaceDidChange):
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
(WebKit::TiledCoreAnimationDrawingAreaProxy::createFence):
(WebKit::TiledCoreAnimationDrawingAreaProxy::sendUpdateGeometry):
(WebKit::TiledCoreAnimationDrawingAreaProxy::adjustTransientZoom):
(WebKit::TiledCoreAnimationDrawingAreaProxy::commitTransientZoom):
(WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
* UIProcess/mac/WebPageProxyMac.mm:
* UIProcess/win/PageClientImpl.cpp:
(WebKit::PageClientImpl::createDrawingAreaProxy):
* UIProcess/win/PageClientImpl.h:
* UIProcess/win/PageClientImpl.cpp:
(WebKit::PageClientImpl::createDrawingAreaProxy):
* UIProcess/win/PageClientImpl.h:
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea):
Pass the drawing area's associated process when constructing it and store it as a member
in addition to the page. This is necessary now that a page can be associated with 2
WebProcesses at a time, each having its own drawing area.

* UIProcess/Cocoa/WebPageProxyCocoa.mm:
(WebKit::WebPageProxy::createSandboxExtensionsIfNeeded):
Pass the process.

* UIProcess/ProvisionalPageProxy.cpp: Added.
(WebKit::ProvisionalPageProxy::ProvisionalPageProxy):
(WebKit::ProvisionalPageProxy::~ProvisionalPageProxy):
(WebKit::ProvisionalPageProxy::processDidTerminate):
(WebKit::ProvisionalPageProxy::takeDrawingArea):
(WebKit::ProvisionalPageProxy::cancel):
(WebKit::ProvisionalPageProxy::processDidFinishLaunching):
(WebKit::ProvisionalPageProxy::finishInitializingWebPageAfterProcessLaunch):
(WebKit::ProvisionalPageProxy::initializeWebPage):
(WebKit::ProvisionalPageProxy::loadData):
(WebKit::ProvisionalPageProxy::loadRequest):
(WebKit::ProvisionalPageProxy::goToBackForwardItem):
(WebKit::ProvisionalPageProxy::didCreateMainFrame):
(WebKit::ProvisionalPageProxy::didPerformClientRedirect):
(WebKit::ProvisionalPageProxy::didStartProvisionalLoadForFrame):
(WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):
(WebKit::ProvisionalPageProxy::didCommitLoadForFrame):
(WebKit::ProvisionalPageProxy::didNavigateWithNavigationData):
(WebKit::ProvisionalPageProxy::didChangeProvisionalURLForFrame):
(WebKit::ProvisionalPageProxy::decidePolicyForNavigationActionAsync):
(WebKit::ProvisionalPageProxy::decidePolicyForResponse):
(WebKit::ProvisionalPageProxy::startURLSchemeTask):
(WebKit::ProvisionalPageProxy::backForwardGoToItem):
(WebKit::ProvisionalPageProxy::didReceiveMessage):
(WebKit::ProvisionalPageProxy::didReceiveSyncMessage):
* UIProcess/ProvisionalPageProxy.h: Added.
(WebKit::ProvisionalPageProxy::page):
(WebKit::ProvisionalPageProxy::mainFrame const):
(WebKit::ProvisionalPageProxy::process):
(WebKit::ProvisionalPageProxy::processSwapRequestedByClient const):
(WebKit::ProvisionalPageProxy::navigationID const):
(WebKit::ProvisionalPageProxy::drawingArea const):
New WebPageProxy-like class which is owned by the WebPageProxy and proxies IPC from
the provisional process.

* UIProcess/SuspendedPageProxy.cpp:
(WebKit::SuspendedPageProxy::~SuspendedPageProxy):
(WebKit::SuspendedPageProxy::unsuspend):
(WebKit::SuspendedPageProxy::didProcessRequestToSuspend):
Unregister the SuspendedPageProxy as an IPC message receiver a little bit earlier
when we're going to unsuspend it. This avoids conflicting with the ProvisionalPageProxy
which tries to register itself as an IPC message receiver for the same pageID when
a process-swap occurs and we're switching to a suspended page.

* UIProcess/WebFrameProxy.cpp:
(WebKit::WebFrameProxy::isMainFrame const):
WebFrameProxy::isMainFrame() relies on checking that the frame is the WebPageProxy's m_mainFrame.
Now that the WebPageProxy can have a ProvisionalPageProxy, also check if it is the ProvisionalPageProxy's
m_mainFrame to maintain previous behavior.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::provisionalDrawingArea const):
Add getter for the provisional drawing area. We normally only deal with the page's current drawing area, but
the ViewGestureController needs access to the provisional once to display the swipe gesture snapshot.

(WebKit::WebPageProxy::swapToWebProcess):
swapToWebProcess() no longer takes care of unsuspending the SuspendedPage because we now call swapToWebProcess()
later, when a load is actually committed in the provisional page / process. swapToWebProcess() now also needs
to initialize some data members such as the drawing area and the main frame as it is transferring them over from
the ProvisionalPageProxy which started the provisional load.

(WebKit::WebPageProxy::finishAttachingToWebProcess):
We no longer need IsSwapFromSuspended parameter as this is called later now, after a load has actually been
committed in the provisional process.

(WebKit::WebPageProxy::setDrawingArea):
(WebKit::WebPageProxy::initializeWebPage):
- We no longer need IsSwapFromSuspended parameter as this is called later now, after a load has actually been
  committed in the provisional process.
- Factor some code out to WebPageProxy::setDrawingArea() so that it can be shared with swapToWebProcess().

(WebKit::WebPageProxy::maybeInitializeSandboxExtensionHandle):
(WebKit::WebPageProxy::loadRequest):
(WebKit::WebPageProxy::loadRequestWithNavigationShared):
Only call setPendingAPIRequestURL() in loadRequestWithNavigation() only if ShouldTreatAsContinuingLoad is not
Yes. This avoids hitting some assertions as this was already called during the first API call if needed.

(WebKit::WebPageProxy::loadData):
(WebKit::WebPageProxy::loadDataWithNavigationShared):
(WebKit::WebPageProxy::stopLoading):
(WebKit::WebPageProxy::reload):
(WebKit::WebPageProxy::didPerformDragControllerAction):
(WebKit::WebPageProxy::findPlugin):
(WebKit::WebPageProxy::receivedNavigationPolicyDecision):
In case of process swap, tell the previous process to ignore the load instead of suspending it right away.
Suspension now happens later, only if we end up committing the provisional load in the new process.
Also discard the SuspendedPage if it failed to suspend (we only reuse its process in this case). This used
to happen a bit later but it is clearer if we do this as early as possible I think.

(WebKit::WebPageProxy::commitProvisionalPage):
When the load is committed in the new process, we call WebPageProxy::commitProvisionalPage(). It takes care of:
- Actually swapping the WebPageProxy to the new process by calling processDidTerminate() / swapToWebProcess().
- Suspending the current page.
- Letting the client know the load is comitted
- Destroy the ProvisionalPageProxy.
This work used to happen earlier in continueNavigationInNewProcess().

(WebKit::WebPageProxy::continueNavigationInNewProcess):
Moved some of the logic to commitProvisionalPage(). We now merely start the load in a new ProvisionalPageProxy,
without actually having the WebPageProxy switch to the new process yet.

(WebKit::WebPageProxy::didCreateMainFrame):
(WebKit::WebPageProxy::didCreateSubframe):
(WebKit::WebPageProxy::didCreateWindow):
Drop some code that is no longer needed, now that the ProvisionalPageProxy takes care of this.

(WebKit::WebPageProxy::didDestroyNavigation):
On process-swap, when telling the previous process to ignore the load and starting the new load in a new
ProvisionalPageProxy, the previous WebPage attempts to destroy the navigation. In this case, we ignore
the call since the navigation is merely taken over by the ProvisionalPageProxy.

(WebKit::WebPageProxy::didStartProvisionalLoadForFrame):
(WebKit::WebPageProxy::didStartProvisionalLoadForFrameShared):
Moved some PSON logic to the ProvisionalPageProxy instead.

(WebKit::WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame):
(WebKit::WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrameShared):
(WebKit::WebPageProxy::willPerformClientRedirectForFrame):
(WebKit::WebPageProxy::didCancelClientRedirectForFrame):
(WebKit::WebPageProxy::didChangeProvisionalURLForFrame):
(WebKit::WebPageProxy::didChangeProvisionalURLForFrameShared):

(WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
(WebKit::WebPageProxy::didFailProvisionalLoadForFrameShared):
When didFailProvisionalLoadForFrame() is called for a ProvisionalPageProxy, destroy it.

(WebKit::WebPageProxy::didCommitLoadForFrame):
(WebKit::WebPageProxy::didFinishDocumentLoadForFrame):
(WebKit::WebPageProxy::didFinishLoadForFrame):
(WebKit::WebPageProxy::didFailLoadForFrame):
(WebKit::WebPageProxy::didSameDocumentNavigationForFrame):
(WebKit::WebPageProxy::didReceiveTitleForFrame):
(WebKit::WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame):
(WebKit::WebPageProxy::didDisplayInsecureContentForFrame):
(WebKit::WebPageProxy::didRunInsecureContentForFrame):
(WebKit::WebPageProxy::frameDidBecomeFrameSet):
(WebKit::WebPageProxy::decidePolicyForNavigationActionAsync):
(WebKit::WebPageProxy::decidePolicyForNavigationActionAsyncShared):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
(WebKit::WebPageProxy::decidePolicyForNavigationActionSync):
(WebKit::WebPageProxy::decidePolicyForNewWindowAction):
(WebKit::WebPageProxy::decidePolicyForResponse):
(WebKit::WebPageProxy::decidePolicyForResponseShared):
(WebKit::WebPageProxy::unableToImplementPolicy):
(WebKit::WebPageProxy::willSubmitForm):
(WebKit::WebPageProxy::didNavigateWithNavigationData):
(WebKit::WebPageProxy::didNavigateWithNavigationDataShared):
(WebKit::WebPageProxy::didPerformClientRedirect):
(WebKit::WebPageProxy::didPerformClientRedirectShared):
(WebKit::WebPageProxy::didPerformServerRedirect):
(WebKit::WebPageProxy::didUpdateHistoryTitle):
(WebKit::WebPageProxy::createNewPage):
(WebKit::WebPageProxy::runJavaScriptAlert):
(WebKit::WebPageProxy::runJavaScriptConfirm):
(WebKit::WebPageProxy::runJavaScriptPrompt):
(WebKit::WebPageProxy::unavailablePluginButtonClicked):
(WebKit::WebPageProxy::runBeforeUnloadConfirmPanel):
(WebKit::WebPageProxy::runOpenPanel):
(WebKit::WebPageProxy::printFrame):
(WebKit::WebPageProxy::backForwardGoToItem):
(WebKit::WebPageProxy::backForwardGoToItemShared):
(WebKit::WebPageProxy::learnWord):
(WebKit::WebPageProxy::ignoreWord):
(WebKit::WebPageProxy::didReceiveEvent):
(WebKit::WebPageProxy::editingRangeCallback):
(WebKit::WebPageProxy::rectForCharacterRangeCallback):
(WebKit::WebPageProxy::focusedFrameChanged):
(WebKit::WebPageProxy::frameSetLargestFrameChanged):

(WebKit::WebPageProxy::provisionalProcessDidTerminate):
Cancel the provisiona load and destroy the ProvisionalPageProxy if
the provisional process crashes.

(WebKit::WebPageProxy::resetState):
Drop some code that is no longer needed.

(WebKit::WebPageProxy::creationParameters):
- Move the hasRegisteredServiceWorkers flag initialization from the call site to here now that we have
more than one call site. This was just some bad factoring.
- Take the process in parameter now that we page can be associated with several processes at a time.

(WebKit::WebPageProxy::exceededDatabaseQuota):
(WebKit::WebPageProxy::requestGeolocationPermissionForFrame):
(WebKit::WebPageProxy::requestUserMediaPermissionForFrame):
(WebKit::WebPageProxy::enumerateMediaDevicesForFrame):
(WebKit::WebPageProxy::startURLSchemeTask):
(WebKit::WebPageProxy::startURLSchemeTaskShared):
(WebKit::WebPageProxy::stopURLSchemeTask):
(WebKit::WebPageProxy::loadSynchronousURLSchemeTask):
(WebKit::WebPageProxy::checkURLReceivedFromCurrentOrPreviousWebProcess):
(WebKit::WebPageProxy::willAcquireUniversalFileReadSandboxExtension):
* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::visitedLinkStore):
(WebKit::WebPageProxy::provisionalPageProxy const):

* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::hasProvisionalPageWithID const):
(WebKit::WebProcessProxy::updateBackForwardItem):
(WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
(WebKit::WebProcessProxy::didFinishLaunching):
(WebKit::WebProcessProxy::canTerminateChildProcess):
* UIProcess/WebProcessProxy.h:
(WebKit::WebProcessProxy::addProvisionalPageProxy):
(WebKit::WebProcessProxy::removeProvisionalPageProxy):
Before updating a BackForwardListItem, we normally make sure the process has a WebPageProxy with the
item's pageID. We have to tweak the logic because there may now be no WebPageProxy with this pageID
associated with this process yet, because it is still a ProvisionalPageProxy.

* UIProcess/WebURLSchemeHandler.cpp:
(WebKit::WebURLSchemeHandler::startTask):
* UIProcess/WebURLSchemeHandler.h:
* UIProcess/WebURLSchemeTask.cpp:
(WebKit::WebURLSchemeTask::create):
(WebKit::WebURLSchemeTask::WebURLSchemeTask):
(WebKit::WebURLSchemeTask::didPerformRedirection):
(WebKit::WebURLSchemeTask::didReceiveResponse):
(WebKit::WebURLSchemeTask::didReceiveData):
(WebKit::WebURLSchemeTask::didComplete):
(WebKit::WebURLSchemeTask::pageDestroyed):
* UIProcess/WebURLSchemeTask.h:
Pass the process when constructing a WebURLSchemeTask and store it as a data member in addition to
the page. This is necessary now that a WebPageProxy can be associated with several WebProcesses.

* UIProcess/ios/ViewGestureControllerIOS.mm:
(WebKit::ViewGestureController::endSwipeGesture):
Use the provisional drawing area to display the swipe snapshot as it may differ from the one currently
associated with the page in case of process swap.

* WebKit.xcodeproj/project.pbxproj:
Add ProvisionalPageProxy class.

* WebProcess/WebPage/WebFrame.cpp:
(WebKit::toPolicyAction):
(WebKit::WebFrame::didReceivePolicyDecision):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::m_shouldAttachDrawingAreaOnPageTransition):
(WebKit::WebPage::reinitializeWebPage):
(WebKit::WebPage::didReceivePolicyDecision):
Stop dealing with WebPolicyAction::Suspend as it no longer exists.

(WebKit::WebPage::didCompletePageTransition):

(WebKit::WebPage::setIsSuspended):
Suspend the Page when setIsSuspended(true) is called, now that there is no longer a WebPolicyAction::Suspend.
setIsSuspended(true) IPC is sent when we actually commit the provisional page.

* WebProcess/WebPage/WebPage.h:

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
(-[PSONNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):

LayoutTests:

Skip test testing the cross-process DOMWindow API as I broke it with this patch.
The feature is far from ready and off by default anyway. I will add support back
in a follow-up.

* platform/wk2/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@240046 268f45cc-cd09-0410-ab3c-d52691b4dbfc

57 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/loader/FrameLoader.cpp
Source/WebKit/ChangeLog
Source/WebKit/Shared/WebPageCreationParameters.cpp
Source/WebKit/Shared/WebPageCreationParameters.h
Source/WebKit/Shared/WebPolicyAction.h
Source/WebKit/Sources.txt
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/gtk/PageClientImpl.cpp
Source/WebKit/UIProcess/API/gtk/PageClientImpl.h
Source/WebKit/UIProcess/API/wpe/PageClientImpl.cpp
Source/WebKit/UIProcess/API/wpe/PageClientImpl.h
Source/WebKit/UIProcess/AcceleratedDrawingAreaProxy.cpp
Source/WebKit/UIProcess/AcceleratedDrawingAreaProxy.h
Source/WebKit/UIProcess/Cocoa/WebPageProxyCocoa.mm
Source/WebKit/UIProcess/Cocoa/WebViewImpl.h
Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm
Source/WebKit/UIProcess/DrawingAreaProxy.cpp
Source/WebKit/UIProcess/DrawingAreaProxy.h
Source/WebKit/UIProcess/DrawingAreaProxyImpl.cpp
Source/WebKit/UIProcess/DrawingAreaProxyImpl.h
Source/WebKit/UIProcess/PageClient.h
Source/WebKit/UIProcess/ProvisionalPageProxy.cpp [new file with mode: 0644]
Source/WebKit/UIProcess/ProvisionalPageProxy.h [new file with mode: 0644]
Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h
Source/WebKit/UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm
Source/WebKit/UIProcess/SuspendedPageProxy.cpp
Source/WebKit/UIProcess/WebFrameProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebProcessProxy.cpp
Source/WebKit/UIProcess/WebProcessProxy.h
Source/WebKit/UIProcess/WebURLSchemeHandler.cpp
Source/WebKit/UIProcess/WebURLSchemeHandler.h
Source/WebKit/UIProcess/WebURLSchemeTask.cpp
Source/WebKit/UIProcess/WebURLSchemeTask.h
Source/WebKit/UIProcess/ios/PageClientImplIOS.h
Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
Source/WebKit/UIProcess/ios/ViewGestureControllerIOS.mm
Source/WebKit/UIProcess/ios/WKContentView.h
Source/WebKit/UIProcess/ios/WKContentView.mm
Source/WebKit/UIProcess/mac/PageClientImplMac.h
Source/WebKit/UIProcess/mac/PageClientImplMac.mm
Source/WebKit/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h
Source/WebKit/UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm
Source/WebKit/UIProcess/mac/WebPageProxyMac.mm
Source/WebKit/UIProcess/win/PageClientImpl.cpp
Source/WebKit/UIProcess/win/PageClientImpl.h
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/WebPage/WebFrame.cpp
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

index 16d56d1..3a5d6c4 100644 (file)
@@ -1,3 +1,17 @@
+2019-01-16  Chris Dumez  <cdumez@apple.com>
+
+        Regression(PSON) View becomes blank after click a cross-site download link
+        https://bugs.webkit.org/show_bug.cgi?id=193361
+        <rdar://problem/47099573>
+
+        Reviewed by Geoffrey Garen.
+
+        Skip test testing the cross-process DOMWindow API as I broke it with this patch.
+        The feature is far from ready and off by default anyway. I will add support back
+        in a follow-up.
+
+        * platform/wk2/TestExpectations:
+
 2019-01-16  Zalan Bujtas  <zalan@apple.com>
 
         [LFC][Out-of-flow] Set used vertical margin values when top/height/bottom are non-auto.
index 8e959ed..9d90be8 100644 (file)
@@ -733,8 +733,8 @@ http/tests/resourceLoadStatistics/remove-blocking-in-redirect.html [ Skip ]
 http/tests/resourceLoadStatistics/non-prevalent-resources-can-access-cookies-in-a-third-party-context.html [ Skip ]
 http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html [ Skip ]
 
-# Process swapping is only implemented on WebKit2.
-http/tests/navigation/process-swap-window-open.html [ Pass ]
+# This feature is currently disabled by default and unfinished <rdar://problem/38925077>.
+http/tests/navigation/process-swap-window-open.html [ Skip ]
 
 # Cross-Origin-Resource-Policy response header is only implemented in WebKit2.
 http/wpt/cross-origin-resource-policy/ [ Pass ]
index f69eee0..a94b5ee 100644 (file)
@@ -1,3 +1,17 @@
+2019-01-16  Chris Dumez  <cdumez@apple.com>
+
+        Regression(PSON) View becomes blank after click a cross-site download link
+        https://bugs.webkit.org/show_bug.cgi?id=193361
+        <rdar://problem/47099573>
+
+        Reviewed by Geoffrey Garen.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::commitProvisionalLoad):
+        When restoring from PageCache, make sure we notify the client that the load was committed
+        *before* we tell it that the navigation is complete. This would confuse the ProvisionalPageProxy
+        logic in the UIProcess.
+
 2019-01-16  Devin Rousso  <drousso@apple.com>
 
         Web Inspector: extend overlay element bounds lines to the right/below as well
index 4c26a69..ebf950b 100644 (file)
@@ -2032,11 +2032,11 @@ void FrameLoader::commitProvisionalLoad()
 
         Optional<HasInsecureContent> hasInsecureContent = cachedPage->cachedMainFrame()->hasInsecureContent();
 
+        dispatchDidCommitLoad(hasInsecureContent);
+
         // FIXME: This API should be turned around so that we ground CachedPage into the Page.
         cachedPage->restore(*m_frame.page());
 
-        dispatchDidCommitLoad(hasInsecureContent);
-
 #if PLATFORM(IOS_FAMILY)
         m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(false);
         m_frame.page()->chrome().dispatchViewportPropertiesDidChange(m_frame.page()->viewportArguments());
index 94fef3c..dba51ee 100644 (file)
@@ -1,3 +1,376 @@
+2019-01-16  Chris Dumez  <cdumez@apple.com>
+
+        Regression(PSON) View becomes blank after click a cross-site download link
+        https://bugs.webkit.org/show_bug.cgi?id=193361
+        <rdar://problem/47099573>
+
+        Reviewed by Geoffrey Garen.
+
+        The issue tracked by rdar://problem/47099573 is that a provisional load may get
+        canceled (or converted into a download) *after* we've decided to process-swap.
+        In such cases, the view should keep displaying the current site and it should
+        still be interactive. However, with the previous PSON model, the view (pageProxy)
+        would have already swapped to the new process and would end up displaying the
+        initially empty document.
+
+        To address the issue, this patch introduces the concept of a provisional load
+        in the UIProcess, handled by a ProvisionalPageProxy which has its own privisional
+        process. The WebPageProxy owns the ProvisionalPageProxy but we do not commit the
+        provisional page until after the load was committed in the new process. This means
+        that the view / WebPageProxy keeps using the old process and displays the current
+        content until a load has committed in the provisional page. If no load commits
+        in the provisional process (e.g. because the load is cancelled or converted into
+        a download), then we merely destroy the ProvisionalPageProxy and terminate its
+        process, without impacting the WebPageProxy.
+
+        * Shared/WebPageCreationParameters.cpp:
+        (WebKit::WebPageCreationParameters::encode const):
+        (WebKit::WebPageCreationParameters::decode):
+        * Shared/WebPageCreationParameters.h:
+        Rename isSwapFromSuspended to isProcessSwap for clarity as we always want to
+        delay attaching the drawing area in case of a process-swap, no matter what
+        now that the previous process is kept alive until the provisional load is
+        committed in the new process.
+
+        * Shared/WebPolicyAction.h:
+        Drop Suspend policy action. At decidePolicyForNavigationAction time, in case of
+        process-swap, we now tell the previous process to simply ignore the load, while
+        we create a ProvisionalPageProxy to do the new load in a new process.
+        Suspension of the previous page in the old process, happens later, when a load
+        is actually committed in the new process.
+
+        * Sources.txt:
+        Add new ProvisionalPageProxy file.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _killWebContentProcessAndResetState]):
+        When calling _killWebContentProcessAndResetState on a WKWebView, kill both the current
+        process and the provisional one, to maintain previous behavior in our API tests.
+
+        * UIProcess/API/gtk/PageClientImpl.cpp:
+        (WebKit::PageClientImpl::createDrawingAreaProxy):
+        * UIProcess/API/gtk/PageClientImpl.h:
+        * UIProcess/API/wpe/PageClientImpl.cpp:
+        (WebKit::PageClientImpl::createDrawingAreaProxy):
+        * UIProcess/API/wpe/PageClientImpl.h:
+        * UIProcess/AcceleratedDrawingAreaProxy.cpp:
+        (WebKit::AcceleratedDrawingAreaProxy::AcceleratedDrawingAreaProxy):
+        (WebKit::AcceleratedDrawingAreaProxy::didUpdateBackingStoreState):
+        (WebKit::AcceleratedDrawingAreaProxy::sendUpdateBackingStoreState):
+        (WebKit::AcceleratedDrawingAreaProxy::waitForAndDispatchDidUpdateBackingStoreState):
+        (WebKit::AcceleratedDrawingAreaProxy::setNativeSurfaceHandleForCompositing):
+        (WebKit::AcceleratedDrawingAreaProxy::destroyNativeSurfaceHandleForCompositing):
+        * UIProcess/AcceleratedDrawingAreaProxy.h:
+        * UIProcess/Cocoa/WebViewImpl.h:
+        * UIProcess/Cocoa/WebViewImpl.mm:
+        (WebKit::WebViewImpl::createDrawingAreaProxy):
+        * UIProcess/DrawingAreaProxy.cpp:
+        (WebKit::DrawingAreaProxy::DrawingAreaProxy):
+        (WebKit::DrawingAreaProxy::~DrawingAreaProxy):
+        (WebKit::DrawingAreaProxy::viewExposedRectChangedTimerFired):
+        * UIProcess/DrawingAreaProxy.h:
+        (WebKit::DrawingAreaProxy::process):
+        * UIProcess/DrawingAreaProxyImpl.cpp:
+        (WebKit::DrawingAreaProxyImpl::DrawingAreaProxyImpl):
+        (WebKit::DrawingAreaProxyImpl::update):
+        * UIProcess/DrawingAreaProxyImpl.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.h:
+        * UIProcess/RemoteLayerTree/RemoteLayerTreeDrawingAreaProxy.mm:
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::~RemoteLayerTreeDrawingAreaProxy):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::deviceScaleFactorDidChange):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::sendUpdateGeometry):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::acceleratedAnimationDidStart):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::acceleratedAnimationDidEnd):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
+        (WebKit::RemoteLayerTreeDrawingAreaProxy::dispatchAfterEnsuringDrawing):
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::createDrawingAreaProxy):
+        * UIProcess/ios/WKContentView.h:
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView _createDrawingAreaProxy:]):
+        * UIProcess/mac/PageClientImplMac.h:
+        * UIProcess/mac/PageClientImplMac.mm:
+        (WebKit::PageClientImpl::createDrawingAreaProxy):
+        * UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.h:
+        * UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
+        (WebKit::TiledCoreAnimationDrawingAreaProxy::TiledCoreAnimationDrawingAreaProxy):
+        (WebKit::TiledCoreAnimationDrawingAreaProxy::deviceScaleFactorDidChange):
+        (WebKit::TiledCoreAnimationDrawingAreaProxy::colorSpaceDidChange):
+        (WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
+        (WebKit::TiledCoreAnimationDrawingAreaProxy::createFence):
+        (WebKit::TiledCoreAnimationDrawingAreaProxy::sendUpdateGeometry):
+        (WebKit::TiledCoreAnimationDrawingAreaProxy::adjustTransientZoom):
+        (WebKit::TiledCoreAnimationDrawingAreaProxy::commitTransientZoom):
+        (WebKit::TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing):
+        * UIProcess/mac/WebPageProxyMac.mm:
+        * UIProcess/win/PageClientImpl.cpp:
+        (WebKit::PageClientImpl::createDrawingAreaProxy):
+        * UIProcess/win/PageClientImpl.h:
+        * UIProcess/win/PageClientImpl.cpp:
+        (WebKit::PageClientImpl::createDrawingAreaProxy):
+        * UIProcess/win/PageClientImpl.h:
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+        (WebKit::TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea):
+        Pass the drawing area's associated process when constructing it and store it as a member
+        in addition to the page. This is necessary now that a page can be associated with 2
+        WebProcesses at a time, each having its own drawing area.
+
+        * UIProcess/Cocoa/WebPageProxyCocoa.mm:
+        (WebKit::WebPageProxy::createSandboxExtensionsIfNeeded):
+        Pass the process.
+
+        * UIProcess/ProvisionalPageProxy.cpp: Added.
+        (WebKit::ProvisionalPageProxy::ProvisionalPageProxy):
+        (WebKit::ProvisionalPageProxy::~ProvisionalPageProxy):
+        (WebKit::ProvisionalPageProxy::processDidTerminate):
+        (WebKit::ProvisionalPageProxy::takeDrawingArea):
+        (WebKit::ProvisionalPageProxy::cancel):
+        (WebKit::ProvisionalPageProxy::processDidFinishLaunching):
+        (WebKit::ProvisionalPageProxy::finishInitializingWebPageAfterProcessLaunch):
+        (WebKit::ProvisionalPageProxy::initializeWebPage):
+        (WebKit::ProvisionalPageProxy::loadData):
+        (WebKit::ProvisionalPageProxy::loadRequest):
+        (WebKit::ProvisionalPageProxy::goToBackForwardItem):
+        (WebKit::ProvisionalPageProxy::didCreateMainFrame):
+        (WebKit::ProvisionalPageProxy::didPerformClientRedirect):
+        (WebKit::ProvisionalPageProxy::didStartProvisionalLoadForFrame):
+        (WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):
+        (WebKit::ProvisionalPageProxy::didCommitLoadForFrame):
+        (WebKit::ProvisionalPageProxy::didNavigateWithNavigationData):
+        (WebKit::ProvisionalPageProxy::didChangeProvisionalURLForFrame):
+        (WebKit::ProvisionalPageProxy::decidePolicyForNavigationActionAsync):
+        (WebKit::ProvisionalPageProxy::decidePolicyForResponse):
+        (WebKit::ProvisionalPageProxy::startURLSchemeTask):
+        (WebKit::ProvisionalPageProxy::backForwardGoToItem):
+        (WebKit::ProvisionalPageProxy::didReceiveMessage):
+        (WebKit::ProvisionalPageProxy::didReceiveSyncMessage):
+        * UIProcess/ProvisionalPageProxy.h: Added.
+        (WebKit::ProvisionalPageProxy::page):
+        (WebKit::ProvisionalPageProxy::mainFrame const):
+        (WebKit::ProvisionalPageProxy::process):
+        (WebKit::ProvisionalPageProxy::processSwapRequestedByClient const):
+        (WebKit::ProvisionalPageProxy::navigationID const):
+        (WebKit::ProvisionalPageProxy::drawingArea const):
+        New WebPageProxy-like class which is owned by the WebPageProxy and proxies IPC from
+        the provisional process.
+
+        * UIProcess/SuspendedPageProxy.cpp:
+        (WebKit::SuspendedPageProxy::~SuspendedPageProxy):
+        (WebKit::SuspendedPageProxy::unsuspend):
+        (WebKit::SuspendedPageProxy::didProcessRequestToSuspend):
+        Unregister the SuspendedPageProxy as an IPC message receiver a little bit earlier
+        when we're going to unsuspend it. This avoids conflicting with the ProvisionalPageProxy
+        which tries to register itself as an IPC message receiver for the same pageID when
+        a process-swap occurs and we're switching to a suspended page.
+
+        * UIProcess/WebFrameProxy.cpp:
+        (WebKit::WebFrameProxy::isMainFrame const):
+        WebFrameProxy::isMainFrame() relies on checking that the frame is the WebPageProxy's m_mainFrame.
+        Now that the WebPageProxy can have a ProvisionalPageProxy, also check if it is the ProvisionalPageProxy's
+        m_mainFrame to maintain previous behavior.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::provisionalDrawingArea const):
+        Add getter for the provisional drawing area. We normally only deal with the page's current drawing area, but
+        the ViewGestureController needs access to the provisional once to display the swipe gesture snapshot.
+
+        (WebKit::WebPageProxy::swapToWebProcess):
+        swapToWebProcess() no longer takes care of unsuspending the SuspendedPage because we now call swapToWebProcess()
+        later, when a load is actually committed in the provisional page / process. swapToWebProcess() now also needs
+        to initialize some data members such as the drawing area and the main frame as it is transferring them over from
+        the ProvisionalPageProxy which started the provisional load.
+
+        (WebKit::WebPageProxy::finishAttachingToWebProcess):
+        We no longer need IsSwapFromSuspended parameter as this is called later now, after a load has actually been
+        committed in the provisional process.
+
+        (WebKit::WebPageProxy::setDrawingArea):
+        (WebKit::WebPageProxy::initializeWebPage):
+        - We no longer need IsSwapFromSuspended parameter as this is called later now, after a load has actually been
+          committed in the provisional process.
+        - Factor some code out to WebPageProxy::setDrawingArea() so that it can be shared with swapToWebProcess().
+
+        (WebKit::WebPageProxy::maybeInitializeSandboxExtensionHandle):
+        (WebKit::WebPageProxy::loadRequest):
+        (WebKit::WebPageProxy::loadRequestWithNavigationShared):
+        Only call setPendingAPIRequestURL() in loadRequestWithNavigation() only if ShouldTreatAsContinuingLoad is not
+        Yes. This avoids hitting some assertions as this was already called during the first API call if needed.
+
+        (WebKit::WebPageProxy::loadData):
+        (WebKit::WebPageProxy::loadDataWithNavigationShared):
+        (WebKit::WebPageProxy::stopLoading):
+        (WebKit::WebPageProxy::reload):
+        (WebKit::WebPageProxy::didPerformDragControllerAction):
+        (WebKit::WebPageProxy::findPlugin):
+        (WebKit::WebPageProxy::receivedNavigationPolicyDecision):
+        In case of process swap, tell the previous process to ignore the load instead of suspending it right away.
+        Suspension now happens later, only if we end up committing the provisional load in the new process.
+        Also discard the SuspendedPage if it failed to suspend (we only reuse its process in this case). This used
+        to happen a bit later but it is clearer if we do this as early as possible I think.
+
+        (WebKit::WebPageProxy::commitProvisionalPage):
+        When the load is committed in the new process, we call WebPageProxy::commitProvisionalPage(). It takes care of:
+        - Actually swapping the WebPageProxy to the new process by calling processDidTerminate() / swapToWebProcess().
+        - Suspending the current page.
+        - Letting the client know the load is comitted
+        - Destroy the ProvisionalPageProxy.
+        This work used to happen earlier in continueNavigationInNewProcess().
+
+        (WebKit::WebPageProxy::continueNavigationInNewProcess):
+        Moved some of the logic to commitProvisionalPage(). We now merely start the load in a new ProvisionalPageProxy,
+        without actually having the WebPageProxy switch to the new process yet.
+
+        (WebKit::WebPageProxy::didCreateMainFrame):
+        (WebKit::WebPageProxy::didCreateSubframe):
+        (WebKit::WebPageProxy::didCreateWindow):
+        Drop some code that is no longer needed, now that the ProvisionalPageProxy takes care of this.
+
+        (WebKit::WebPageProxy::didDestroyNavigation):
+        On process-swap, when telling the previous process to ignore the load and starting the new load in a new
+        ProvisionalPageProxy, the previous WebPage attempts to destroy the navigation. In this case, we ignore
+        the call since the navigation is merely taken over by the ProvisionalPageProxy.
+
+        (WebKit::WebPageProxy::didStartProvisionalLoadForFrame):
+        (WebKit::WebPageProxy::didStartProvisionalLoadForFrameShared):
+        Moved some PSON logic to the ProvisionalPageProxy instead.
+
+        (WebKit::WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame):
+        (WebKit::WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrameShared):
+        (WebKit::WebPageProxy::willPerformClientRedirectForFrame):
+        (WebKit::WebPageProxy::didCancelClientRedirectForFrame):
+        (WebKit::WebPageProxy::didChangeProvisionalURLForFrame):
+        (WebKit::WebPageProxy::didChangeProvisionalURLForFrameShared):
+
+        (WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
+        (WebKit::WebPageProxy::didFailProvisionalLoadForFrameShared):
+        When didFailProvisionalLoadForFrame() is called for a ProvisionalPageProxy, destroy it.
+
+        (WebKit::WebPageProxy::didCommitLoadForFrame):
+        (WebKit::WebPageProxy::didFinishDocumentLoadForFrame):
+        (WebKit::WebPageProxy::didFinishLoadForFrame):
+        (WebKit::WebPageProxy::didFailLoadForFrame):
+        (WebKit::WebPageProxy::didSameDocumentNavigationForFrame):
+        (WebKit::WebPageProxy::didReceiveTitleForFrame):
+        (WebKit::WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame):
+        (WebKit::WebPageProxy::didDisplayInsecureContentForFrame):
+        (WebKit::WebPageProxy::didRunInsecureContentForFrame):
+        (WebKit::WebPageProxy::frameDidBecomeFrameSet):
+        (WebKit::WebPageProxy::decidePolicyForNavigationActionAsync):
+        (WebKit::WebPageProxy::decidePolicyForNavigationActionAsyncShared):
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+        (WebKit::WebPageProxy::decidePolicyForNavigationActionSync):
+        (WebKit::WebPageProxy::decidePolicyForNewWindowAction):
+        (WebKit::WebPageProxy::decidePolicyForResponse):
+        (WebKit::WebPageProxy::decidePolicyForResponseShared):
+        (WebKit::WebPageProxy::unableToImplementPolicy):
+        (WebKit::WebPageProxy::willSubmitForm):
+        (WebKit::WebPageProxy::didNavigateWithNavigationData):
+        (WebKit::WebPageProxy::didNavigateWithNavigationDataShared):
+        (WebKit::WebPageProxy::didPerformClientRedirect):
+        (WebKit::WebPageProxy::didPerformClientRedirectShared):
+        (WebKit::WebPageProxy::didPerformServerRedirect):
+        (WebKit::WebPageProxy::didUpdateHistoryTitle):
+        (WebKit::WebPageProxy::createNewPage):
+        (WebKit::WebPageProxy::runJavaScriptAlert):
+        (WebKit::WebPageProxy::runJavaScriptConfirm):
+        (WebKit::WebPageProxy::runJavaScriptPrompt):
+        (WebKit::WebPageProxy::unavailablePluginButtonClicked):
+        (WebKit::WebPageProxy::runBeforeUnloadConfirmPanel):
+        (WebKit::WebPageProxy::runOpenPanel):
+        (WebKit::WebPageProxy::printFrame):
+        (WebKit::WebPageProxy::backForwardGoToItem):
+        (WebKit::WebPageProxy::backForwardGoToItemShared):
+        (WebKit::WebPageProxy::learnWord):
+        (WebKit::WebPageProxy::ignoreWord):
+        (WebKit::WebPageProxy::didReceiveEvent):
+        (WebKit::WebPageProxy::editingRangeCallback):
+        (WebKit::WebPageProxy::rectForCharacterRangeCallback):
+        (WebKit::WebPageProxy::focusedFrameChanged):
+        (WebKit::WebPageProxy::frameSetLargestFrameChanged):
+
+        (WebKit::WebPageProxy::provisionalProcessDidTerminate):
+        Cancel the provisiona load and destroy the ProvisionalPageProxy if
+        the provisional process crashes.
+
+        (WebKit::WebPageProxy::resetState):
+        Drop some code that is no longer needed.
+
+        (WebKit::WebPageProxy::creationParameters):
+        - Move the hasRegisteredServiceWorkers flag initialization from the call site to here now that we have
+        more than one call site. This was just some bad factoring.
+        - Take the process in parameter now that we page can be associated with several processes at a time.
+
+        (WebKit::WebPageProxy::exceededDatabaseQuota):
+        (WebKit::WebPageProxy::requestGeolocationPermissionForFrame):
+        (WebKit::WebPageProxy::requestUserMediaPermissionForFrame):
+        (WebKit::WebPageProxy::enumerateMediaDevicesForFrame):
+        (WebKit::WebPageProxy::startURLSchemeTask):
+        (WebKit::WebPageProxy::startURLSchemeTaskShared):
+        (WebKit::WebPageProxy::stopURLSchemeTask):
+        (WebKit::WebPageProxy::loadSynchronousURLSchemeTask):
+        (WebKit::WebPageProxy::checkURLReceivedFromCurrentOrPreviousWebProcess):
+        (WebKit::WebPageProxy::willAcquireUniversalFileReadSandboxExtension):
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::visitedLinkStore):
+        (WebKit::WebPageProxy::provisionalPageProxy const):
+
+        * UIProcess/WebProcessProxy.cpp:
+        (WebKit::WebProcessProxy::hasProvisionalPageWithID const):
+        (WebKit::WebProcessProxy::updateBackForwardItem):
+        (WebKit::WebProcessProxy::processDidTerminateOrFailedToLaunch):
+        (WebKit::WebProcessProxy::didFinishLaunching):
+        (WebKit::WebProcessProxy::canTerminateChildProcess):
+        * UIProcess/WebProcessProxy.h:
+        (WebKit::WebProcessProxy::addProvisionalPageProxy):
+        (WebKit::WebProcessProxy::removeProvisionalPageProxy):
+        Before updating a BackForwardListItem, we normally make sure the process has a WebPageProxy with the
+        item's pageID. We have to tweak the logic because there may now be no WebPageProxy with this pageID
+        associated with this process yet, because it is still a ProvisionalPageProxy.        
+
+        * UIProcess/WebURLSchemeHandler.cpp:
+        (WebKit::WebURLSchemeHandler::startTask):
+        * UIProcess/WebURLSchemeHandler.h:
+        * UIProcess/WebURLSchemeTask.cpp:
+        (WebKit::WebURLSchemeTask::create):
+        (WebKit::WebURLSchemeTask::WebURLSchemeTask):
+        (WebKit::WebURLSchemeTask::didPerformRedirection):
+        (WebKit::WebURLSchemeTask::didReceiveResponse):
+        (WebKit::WebURLSchemeTask::didReceiveData):
+        (WebKit::WebURLSchemeTask::didComplete):
+        (WebKit::WebURLSchemeTask::pageDestroyed):
+        * UIProcess/WebURLSchemeTask.h:
+        Pass the process when constructing a WebURLSchemeTask and store it as a data member in addition to
+        the page. This is necessary now that a WebPageProxy can be associated with several WebProcesses.
+
+        * UIProcess/ios/ViewGestureControllerIOS.mm:
+        (WebKit::ViewGestureController::endSwipeGesture):
+        Use the provisional drawing area to display the swipe snapshot as it may differ from the one currently
+        associated with the page in case of process swap.
+
+        * WebKit.xcodeproj/project.pbxproj:
+        Add ProvisionalPageProxy class.
+
+        * WebProcess/WebPage/WebFrame.cpp:
+        (WebKit::toPolicyAction):
+        (WebKit::WebFrame::didReceivePolicyDecision):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::m_shouldAttachDrawingAreaOnPageTransition):
+        (WebKit::WebPage::reinitializeWebPage):
+        (WebKit::WebPage::didReceivePolicyDecision):
+        Stop dealing with WebPolicyAction::Suspend as it no longer exists.
+
+        (WebKit::WebPage::didCompletePageTransition):
+
+        (WebKit::WebPage::setIsSuspended):
+        Suspend the Page when setIsSuspended(true) is called, now that there is no longer a WebPolicyAction::Suspend.
+        setIsSuspended(true) IPC is sent when we actually commit the provisional page.
+
+        * WebProcess/WebPage/WebPage.h:
+
 2019-01-16  Tim Horton  <timothy_horton@apple.com>
 
         Frequent null-deref under TiledCoreAnimationDrawingArea::scaleViewToFitDocumentIfNeeded()
index ca2df40..6d07c03 100644 (file)
@@ -73,7 +73,7 @@ void WebPageCreationParameters::encode(IPC::Encoder& encoder) const
     encoder.encodeEnum(layerHostingMode);
     encoder << mimeTypesWithCustomContentProviders;
     encoder << controlledByAutomation;
-    encoder << isSwapFromSuspended;
+    encoder << isProcessSwap;
 
 #if PLATFORM(MAC)
     encoder << colorSpace;
@@ -227,7 +227,7 @@ Optional<WebPageCreationParameters> WebPageCreationParameters::decode(IPC::Decod
         return WTF::nullopt;
     if (!decoder.decode(parameters.controlledByAutomation))
         return WTF::nullopt;
-    if (!decoder.decode(parameters.isSwapFromSuspended))
+    if (!decoder.decode(parameters.isProcessSwap))
         return WTF::nullopt;
 
 #if PLATFORM(MAC)
index ae4325c..b382cee 100644 (file)
@@ -129,7 +129,7 @@ struct WebPageCreationParameters {
     Vector<String> mimeTypesWithCustomContentProviders;
 
     bool controlledByAutomation;
-    bool isSwapFromSuspended { false };
+    bool isProcessSwap { false };
 
 #if PLATFORM(MAC)
     ColorSpaceData colorSpace;
index 142a518..3971795 100644 (file)
 
 namespace WebKit {
 
+// FIXME: Remove this type and use WebCore::PolicyAction instead.
 enum class WebPolicyAction : uint8_t {
     Use,
     Download,
-    Ignore,
-    Suspend
+    Ignore
 };
 
 }
@@ -45,8 +45,7 @@ template<> struct EnumTraits<WebKit::WebPolicyAction> {
         WebKit::WebPolicyAction,
         WebKit::WebPolicyAction::Use,
         WebKit::WebPolicyAction::Download,
-        WebKit::WebPolicyAction::Ignore,
-        WebKit::WebPolicyAction::Suspend
+        WebKit::WebPolicyAction::Ignore
     >;
 };
 
index 340e7bf..4de0c6f 100644 (file)
@@ -230,6 +230,7 @@ UIProcess/InspectorTargetProxy.cpp
 UIProcess/PageLoadState.cpp
 UIProcess/ProcessAssertion.cpp
 UIProcess/ProcessThrottler.cpp
+UIProcess/ProvisionalPageProxy.cpp
 UIProcess/RemoteWebInspectorProxy.cpp
 UIProcess/ResponsivenessTimer.cpp
 UIProcess/ServiceWorkerProcessProxy.cpp
index 074cddf..4dfad64 100644 (file)
@@ -44,6 +44,7 @@
 #import "NavigationState.h"
 #import "ObjCObjectGraph.h"
 #import "PageClient.h"
+#import "ProvisionalPageProxy.h"
 #import "RemoteLayerTreeScrollingPerformanceData.h"
 #import "RemoteLayerTreeTransaction.h"
 #import "RemoteObjectRegistry.h"
@@ -4700,6 +4701,11 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
 {
     Ref<WebKit::WebProcessProxy> protectedProcessProxy(_page->process());
     protectedProcessProxy->requestTermination(WebKit::ProcessTerminationReason::RequestedByClient);
+
+    if (auto* provisionalPageProxy = _page->provisionalPageProxy()) {
+        Ref<WebKit::WebProcessProxy> protectedProcessProxy(provisionalPageProxy->process());
+        protectedProcessProxy->requestTermination(WebKit::ProcessTerminationReason::RequestedByClient);
+    }
 }
 
 #if PLATFORM(MAC)
index 683331d..317859d 100644 (file)
@@ -60,9 +60,9 @@ PageClientImpl::PageClientImpl(GtkWidget* viewWidget)
 }
 
 // PageClient's pure virtual functions
-std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
+std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy(WebProcessProxy& process)
 {
-    return std::make_unique<DrawingAreaProxyImpl>(*webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_viewWidget)));
+    return std::make_unique<DrawingAreaProxyImpl>(*webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(m_viewWidget)), process);
 }
 
 void PageClientImpl::setViewNeedsDisplay(const WebCore::Region& region)
index b091920..6dea8f3 100644 (file)
@@ -55,7 +55,7 @@ public:
 
 private:
     // PageClient
-    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy() override;
+    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy(WebProcessProxy&) override;
     void setViewNeedsDisplay(const WebCore::Region&) override;
     void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, bool isProgrammaticScroll) override;
     WebCore::FloatPoint viewScrollPosition() override;
index da9e6d7..2233615 100644 (file)
@@ -51,9 +51,9 @@ struct wpe_view_backend* PageClientImpl::viewBackend()
     return m_view.backend();
 }
 
-std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
+std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy(WebProcessProxy& process)
 {
-    return std::make_unique<AcceleratedDrawingAreaProxy>(m_view.page());
+    return std::make_unique<AcceleratedDrawingAreaProxy>(m_view.page(), process);
 }
 
 void PageClientImpl::setViewNeedsDisplay(const WebCore::Region&)
index d6d5a69..b699f29 100644 (file)
@@ -53,7 +53,7 @@ public:
 
 private:
     // PageClient
-    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy() override;
+    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy(WebProcessProxy&) override;
     void setViewNeedsDisplay(const WebCore::Region&) override;
     void requestScroll(const WebCore::FloatPoint&, const WebCore::IntPoint&, bool) override;
     WebCore::FloatPoint viewScrollPosition() override;
index ec846b3..39af9b3 100644 (file)
@@ -45,8 +45,8 @@
 namespace WebKit {
 using namespace WebCore;
 
-AcceleratedDrawingAreaProxy::AcceleratedDrawingAreaProxy(WebPageProxy& webPageProxy)
-    : DrawingAreaProxy(DrawingAreaTypeImpl, webPageProxy)
+AcceleratedDrawingAreaProxy::AcceleratedDrawingAreaProxy(WebPageProxy& webPageProxy, WebProcessProxy& process)
+    : DrawingAreaProxy(DrawingAreaTypeImpl, webPageProxy, process)
 {
 }
 
@@ -106,7 +106,7 @@ void AcceleratedDrawingAreaProxy::didUpdateBackingStoreState(uint64_t backingSto
     m_isWaitingForDidUpdateBackingStoreState = false;
 
     // Stop the responsiveness timer that was started in sendUpdateBackingStoreState.
-    m_webPageProxy.process().responsivenessTimer().stop();
+    process().responsivenessTimer().stop();
 
     if (layerTreeContext != m_layerTreeContext) {
         if (layerTreeContext.isEmpty() && !m_layerTreeContext.isEmpty()) {
@@ -183,13 +183,13 @@ void AcceleratedDrawingAreaProxy::sendUpdateBackingStoreState(RespondImmediately
 
     m_isWaitingForDidUpdateBackingStoreState = respondImmediatelyOrNot == RespondImmediately;
 
-    m_webPageProxy.process().send(Messages::DrawingArea::UpdateBackingStoreState(m_nextBackingStoreStateID, respondImmediatelyOrNot == RespondImmediately, m_webPageProxy.deviceScaleFactor(), m_size, m_scrollOffset), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::UpdateBackingStoreState(m_nextBackingStoreStateID, respondImmediatelyOrNot == RespondImmediately, m_webPageProxy.deviceScaleFactor(), m_size, m_scrollOffset), m_webPageProxy.pageID());
     m_scrollOffset = IntSize();
 
     if (m_isWaitingForDidUpdateBackingStoreState) {
         // Start the responsiveness timer. We will stop it when we hear back from the WebProcess
         // in didUpdateBackingStoreState.
-        m_webPageProxy.process().responsivenessTimer().start();
+        process().responsivenessTimer().start();
     }
 
     if (m_isWaitingForDidUpdateBackingStoreState && !m_layerTreeContext.isEmpty()) {
@@ -205,7 +205,7 @@ void AcceleratedDrawingAreaProxy::waitForAndDispatchDidUpdateBackingStoreState()
 
     if (!m_webPageProxy.isValid())
         return;
-    if (m_webPageProxy.process().state() == WebProcessProxy::State::Launching)
+    if (process().state() == WebProcessProxy::State::Launching)
         return;
     if (!m_webPageProxy.isViewVisible())
         return;
@@ -222,7 +222,7 @@ void AcceleratedDrawingAreaProxy::waitForAndDispatchDidUpdateBackingStoreState()
     // choose the most recent one, or the one that is closest to our current size.
 
     // The timeout, in seconds, we use when waiting for a DidUpdateBackingStoreState message when we're asked to paint.
-    m_webPageProxy.process().connection()->waitForAndDispatchImmediately<Messages::DrawingAreaProxy::DidUpdateBackingStoreState>(m_webPageProxy.pageID(), Seconds::fromMilliseconds(500));
+    process().connection()->waitForAndDispatchImmediately<Messages::DrawingAreaProxy::DidUpdateBackingStoreState>(m_webPageProxy.pageID(), Seconds::fromMilliseconds(500));
 }
 
 void AcceleratedDrawingAreaProxy::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
@@ -256,7 +256,7 @@ void AcceleratedDrawingAreaProxy::setNativeSurfaceHandleForCompositing(uint64_t
         m_pendingNativeSurfaceHandleForCompositing = handle;
         return;
     }
-    m_webPageProxy.process().send(Messages::DrawingArea::SetNativeSurfaceHandleForCompositing(handle), m_webPageProxy.pageID(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
+    process().send(Messages::DrawingArea::SetNativeSurfaceHandleForCompositing(handle), m_webPageProxy.pageID(), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
 }
 
 void AcceleratedDrawingAreaProxy::destroyNativeSurfaceHandleForCompositing()
@@ -266,7 +266,7 @@ void AcceleratedDrawingAreaProxy::destroyNativeSurfaceHandleForCompositing()
         return;
     }
     bool handled;
-    m_webPageProxy.process().sendSync(Messages::DrawingArea::DestroyNativeSurfaceHandleForCompositing(), Messages::DrawingArea::DestroyNativeSurfaceHandleForCompositing::Reply(handled), m_webPageProxy.pageID());
+    process().sendSync(Messages::DrawingArea::DestroyNativeSurfaceHandleForCompositing(), Messages::DrawingArea::DestroyNativeSurfaceHandleForCompositing::Reply(handled), m_webPageProxy.pageID());
 }
 #endif
 
index 7683c3f..c38a9bb 100644 (file)
@@ -34,7 +34,7 @@ namespace WebKit {
 
 class AcceleratedDrawingAreaProxy : public DrawingAreaProxy {
 public:
-    explicit AcceleratedDrawingAreaProxy(WebPageProxy&);
+    AcceleratedDrawingAreaProxy(WebPageProxy&, WebProcessProxy&);
     virtual ~AcceleratedDrawingAreaProxy();
 
     bool isInAcceleratedCompositingMode() const { return alwaysUseCompositing() || !m_layerTreeContext.isEmpty(); }
index 83f5e8f..354f5af 100644 (file)
@@ -121,7 +121,7 @@ void WebPageProxy::createSandboxExtensionsIfNeeded(const Vector<String>& files,
         BOOL isDirectory;
         if ([[NSFileManager defaultManager] fileExistsAtPath:files[0] isDirectory:&isDirectory] && !isDirectory) {
             SandboxExtension::createHandle("/", SandboxExtension::Type::ReadOnly, fileReadHandle);
-            willAcquireUniversalFileReadSandboxExtension();
+            willAcquireUniversalFileReadSandboxExtension(m_process);
         }
     }
 
index c68dbcc..5b2138d 100644 (file)
@@ -197,7 +197,7 @@ public:
     void setFixedLayoutSize(CGSize);
     CGSize fixedLayoutSize() const;
 
-    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy();
+    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy(WebProcessProxy&);
     bool isUsingUISideCompositing() const;
     void setDrawingAreaSize(CGSize);
     void updateLayer();
index d51ef5d..5dd1535 100644 (file)
@@ -1725,12 +1725,12 @@ CGSize WebViewImpl::fixedLayoutSize() const
     return m_page->fixedLayoutSize();
 }
 
-std::unique_ptr<WebKit::DrawingAreaProxy> WebViewImpl::createDrawingAreaProxy()
+std::unique_ptr<WebKit::DrawingAreaProxy> WebViewImpl::createDrawingAreaProxy(WebProcessProxy& process)
 {
     if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"WebKit2UseRemoteLayerTreeDrawingArea"] boolValue])
-        return std::make_unique<RemoteLayerTreeDrawingAreaProxy>(m_page);
+        return std::make_unique<RemoteLayerTreeDrawingAreaProxy>(m_page, process);
 
-    return std::make_unique<TiledCoreAnimationDrawingAreaProxy>(m_page);
+    return std::make_unique<TiledCoreAnimationDrawingAreaProxy>(m_page, process);
 }
 
 bool WebViewImpl::isUsingUISideCompositing() const
index 79568df..d36bc46 100644 (file)
 namespace WebKit {
 using namespace WebCore;
 
-DrawingAreaProxy::DrawingAreaProxy(DrawingAreaType type, WebPageProxy& webPageProxy)
+DrawingAreaProxy::DrawingAreaProxy(DrawingAreaType type, WebPageProxy& webPageProxy, WebProcessProxy& process)
     : m_type(type)
     , m_webPageProxy(webPageProxy)
+    , m_process(makeRef(process))
     , m_size(webPageProxy.viewSize())
 #if PLATFORM(MAC)
     , m_viewExposedRectChangedTimer(RunLoop::main(), this, &DrawingAreaProxy::viewExposedRectChangedTimerFired)
 #endif
 {
-    m_webPageProxy.process().addMessageReceiver(Messages::DrawingAreaProxy::messageReceiverName(), m_webPageProxy.pageID(), *this);
+    process.addMessageReceiver(Messages::DrawingAreaProxy::messageReceiverName(), m_webPageProxy.pageID(), *this);
 }
 
 DrawingAreaProxy::~DrawingAreaProxy()
 {
-    m_webPageProxy.process().removeMessageReceiver(Messages::DrawingAreaProxy::messageReceiverName(), m_webPageProxy.pageID());
+    process().removeMessageReceiver(Messages::DrawingAreaProxy::messageReceiverName(), m_webPageProxy.pageID());
 }
 
 bool DrawingAreaProxy::setSize(const IntSize& size, const IntSize& scrollDelta)
@@ -92,7 +93,7 @@ void DrawingAreaProxy::viewExposedRectChangedTimerFired()
     if (m_viewExposedRect == m_lastSentViewExposedRect)
         return;
 
-    m_webPageProxy.process().send(Messages::DrawingArea::SetViewExposedRect(m_viewExposedRect), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::SetViewExposedRect(m_viewExposedRect), m_webPageProxy.pageID());
     m_lastSentViewExposedRect = m_viewExposedRect;
 }
 #endif // PLATFORM(MAC)
index 86fb13d..3419a89 100644 (file)
@@ -48,6 +48,7 @@ namespace WebKit {
 class LayerTreeContext;
 class UpdateInfo;
 class WebPageProxy;
+class WebProcessProxy;
 
 class DrawingAreaProxy : public IPC::MessageReceiver {
     WTF_MAKE_NONCOPYABLE(DrawingAreaProxy);
@@ -107,12 +108,14 @@ public:
     virtual void dispatchPresentationCallbacksAfterFlushingLayers(const Vector<CallbackID>&) { }
 
     WebPageProxy& page() const { return m_webPageProxy; }
+    WebProcessProxy& process() { return m_process.get(); }
 
 protected:
-    explicit DrawingAreaProxy(DrawingAreaType, WebPageProxy&);
+    DrawingAreaProxy(DrawingAreaType, WebPageProxy&, WebProcessProxy&);
 
     DrawingAreaType m_type;
     WebPageProxy& m_webPageProxy;
+    Ref<WebProcessProxy> m_process;
 
     WebCore::IntSize m_size;
     WebCore::IntSize m_scrollOffset;
index 9070b5a..8c6ce8d 100644 (file)
@@ -47,8 +47,8 @@
 namespace WebKit {
 using namespace WebCore;
 
-DrawingAreaProxyImpl::DrawingAreaProxyImpl(WebPageProxy& webPageProxy)
-    : AcceleratedDrawingAreaProxy(webPageProxy)
+DrawingAreaProxyImpl::DrawingAreaProxyImpl(WebPageProxy& webPageProxy, WebProcessProxy& process)
+    : AcceleratedDrawingAreaProxy(webPageProxy, process)
     , m_discardBackingStoreTimer(RunLoop::current(), this, &DrawingAreaProxyImpl::discardBackingStore)
 {
 #if USE(GLIB_EVENT_LOOP)
@@ -124,7 +124,7 @@ void DrawingAreaProxyImpl::update(uint64_t backingStoreStateID, const UpdateInfo
     // FIXME: Handle the case where the view is hidden.
 
     incorporateUpdate(updateInfo);
-    m_webPageProxy.process().send(Messages::DrawingArea::DidUpdate(), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::DidUpdate(), m_webPageProxy.pageID());
 }
 
 void DrawingAreaProxyImpl::didUpdateBackingStoreState(uint64_t backingStoreStateID, const UpdateInfo& updateInfo, const LayerTreeContext& layerTreeContext)
index 0af777f..31a9cc7 100644 (file)
@@ -39,7 +39,7 @@ namespace WebKit {
 
 class DrawingAreaProxyImpl final : public AcceleratedDrawingAreaProxy {
 public:
-    explicit DrawingAreaProxyImpl(WebPageProxy&);
+    DrawingAreaProxyImpl(WebPageProxy&, WebProcessProxy&);
     virtual ~DrawingAreaProxyImpl();
 
     void paint(BackingStore::PlatformGraphicsContext, const WebCore::IntRect&, WebCore::Region& unpaintedRegion);
index 007b281..bf4eb2d 100644 (file)
@@ -49,6 +49,7 @@
 
 OBJC_CLASS CALayer;
 OBJC_CLASS NSFileWrapper;
+OBJC_CLASS NSMenu;
 OBJC_CLASS NSSet;
 OBJC_CLASS WKDrawingView;
 OBJC_CLASS _WKRemoteObjectRegistry;
@@ -122,6 +123,7 @@ class WebFrameProxy;
 class WebOpenPanelResultListenerProxy;
 class WebPageProxy;
 class WebPopupMenuProxy;
+class WebProcessProxy;
 
 enum class ContinueUnsafeLoad : bool { No, Yes };
 
@@ -158,7 +160,7 @@ public:
     virtual ~PageClient() { }
 
     // Create a new drawing area proxy for the given page.
-    virtual std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy() = 0;
+    virtual std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy(WebProcessProxy&) = 0;
 
     // Tell the view to invalidate the given region. The region is in view coordinates.
     virtual void setViewNeedsDisplay(const WebCore::Region&) = 0;
diff --git a/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp b/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp
new file mode 100644 (file)
index 0000000..14fbac8
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ProvisionalPageProxy.h"
+
+#include "APINavigation.h"
+#include "DrawingAreaProxy.h"
+#include "FormDataReference.h"
+#include "Logging.h"
+#include "PageClient.h"
+#include "URLSchemeTaskParameters.h"
+#include "WebBackForwardList.h"
+#include "WebBackForwardListItem.h"
+#include "WebErrors.h"
+#include "WebNavigationDataStore.h"
+#include "WebNavigationState.h"
+#include "WebPageMessages.h"
+#include "WebPageProxy.h"
+#include "WebPageProxyMessages.h"
+#include "WebProcessMessages.h"
+#include "WebProcessProxy.h"
+#include <WebCore/ShouldTreatAsContinuingLoad.h>
+
+namespace WebKit {
+
+#define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(m_page.isAlwaysOnLoggingAllowed(), channel, "%p - ProvisionalPageProxy::" fmt, this, ##__VA_ARGS__)
+#define RELEASE_LOG_ERROR_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_ERROR_IF(m_page.isAlwaysOnLoggingAllowed(), channel, "%p - ProvisionalPageProxy::" fmt, this, ##__VA_ARGS__)
+
+ProvisionalPageProxy::ProvisionalPageProxy(WebPageProxy& page, Ref<WebProcessProxy>&& process, std::unique_ptr<SuspendedPageProxy> suspendedPage, uint64_t navigationID, bool isServerRedirect, const WebCore::ResourceRequest& request, ProcessSwapRequestedByClient processSwapRequestedByClient)
+    : m_page(page)
+    , m_process(WTFMove(process))
+    , m_navigationID(navigationID)
+    , m_isServerRedirect(isServerRedirect)
+    , m_request(request)
+    , m_processSwapRequestedByClient(processSwapRequestedByClient)
+#if PLATFORM(IOS_FAMILY)
+    , m_suspensionToken(m_process->throttler().foregroundActivityToken())
+#endif
+{
+    m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID(), *this);
+    m_process->addProvisionalPageProxy(*this);
+
+    // 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 (suspendedPage) {
+        ASSERT(&suspendedPage->process() == m_process.ptr());
+        suspendedPage->unsuspend();
+        m_mainFrame = WebFrameProxy::create(m_page, suspendedPage->mainFrameID());
+        m_process->frameCreated(suspendedPage->mainFrameID(), *m_mainFrame);
+    }
+
+    initializeWebPage();
+}
+
+ProvisionalPageProxy::~ProvisionalPageProxy()
+{
+    m_process->removeProvisionalPageProxy(*this);
+
+    if (m_wasCommitted)
+        return;
+
+    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
+    m_process->send(Messages::WebPage::Close(), m_page.pageID());
+
+    RunLoop::main().dispatch([process = m_process.copyRef()] {
+        process->maybeShutDown();
+    });
+}
+
+void ProvisionalPageProxy::processDidTerminate()
+{
+    RELEASE_LOG_ERROR_IF_ALLOWED(ProcessSwapping, "processDidTerminate: pageID = %" PRIu64, m_page.pageID());
+    m_page.provisionalProcessDidTerminate();
+}
+
+std::unique_ptr<DrawingAreaProxy> ProvisionalPageProxy::takeDrawingArea()
+{
+    return WTFMove(m_drawingArea);
+}
+
+void ProvisionalPageProxy::cancel()
+{
+    // If the provisional load started, then indicate that it failed due to cancellation by calling didFailProvisionalLoadForFrame().
+    if (m_provisionalLoadURL.isEmpty())
+        return;
+
+    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "cancel: Simulating a didFailProvisionalLoadForFrame for pageID = %" PRIu64, m_page.pageID());
+    ASSERT(m_mainFrame);
+    auto error = WebKit::cancelledError(m_request);
+    error.setType(WebCore::ResourceError::Type::Cancellation);
+    didFailProvisionalLoadForFrame(m_mainFrame->frameID(), { }, m_navigationID, m_provisionalLoadURL, error, UserData { }); // Will delete |this|.
+}
+
+void ProvisionalPageProxy::processDidFinishLaunching()
+{
+    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "processDidFinishLaunching: pageID = %" PRIu64, m_page.pageID());
+    finishInitializingWebPageAfterProcessLaunch();
+}
+
+void ProvisionalPageProxy::finishInitializingWebPageAfterProcessLaunch()
+{
+    ASSERT(m_process->state() == WebProcessProxy::State::Running);
+
+    // FIXME: The WebPageProxy delays adding the visited link store until after the process has launched
+    // so the ProvisionalPageProxy does the same. However, do we really need to?
+    m_process->addVisitedLinkStore(m_page.visitedLinkStore());
+}
+
+void ProvisionalPageProxy::initializeWebPage()
+{
+    m_drawingArea = m_page.pageClient().createDrawingAreaProxy(m_process);
+
+    auto parameters = m_page.creationParameters(m_process);
+    parameters.isProcessSwap = true;
+    m_process->send(Messages::WebProcess::CreateWebPage(m_page.pageID(), parameters), 0);
+
+    if (m_process->state() == WebProcessProxy::State::Running)
+        finishInitializingWebPageAfterProcessLaunch();
+}
+
+void ProvisionalPageProxy::loadData(API::Navigation& navigation, const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, Optional<WebsitePoliciesData>&& websitePolicies)
+{
+    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "loadData: pageID = %" PRIu64, m_page.pageID());
+
+    m_page.loadDataWithNavigationShared(m_process, navigation, data, MIMEType, encoding, baseURL, userData, WebCore::ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
+}
+
+void ProvisionalPageProxy::loadRequest(API::Navigation& navigation, WebCore::ResourceRequest&& request, WebCore::ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, Optional<WebsitePoliciesData>&& websitePolicies)
+{
+    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "loadRequest: pageID = %" PRIu64, m_page.pageID());
+
+    m_page.loadRequestWithNavigationShared(m_process, navigation, WTFMove(request), shouldOpenExternalURLsPolicy, userData, WebCore::ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
+}
+
+void ProvisionalPageProxy::goToBackForwardItem(API::Navigation& navigation, WebBackForwardListItem& item, Optional<WebsitePoliciesData>&& websitePolicies)
+{
+    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "goToBackForwardItem: pageID = %" PRIu64, m_page.pageID());
+
+    auto itemStates = m_page.backForwardList().filteredItemStates([this, targetItem = &item](auto& 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_page.pageID());
+    m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item.itemID(), *navigation.backForwardFrameLoadType(), WebCore::ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies)), m_page.pageID());
+    m_process->responsivenessTimer().start();
+}
+
+void ProvisionalPageProxy::didCreateMainFrame(uint64_t frameID)
+{
+    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "didCreateMainFrame: pageID = %" PRIu64 ", frameID = %" PRIu64, m_page.pageID(), frameID);
+    ASSERT(!m_mainFrame);
+
+    m_mainFrame = WebFrameProxy::create(m_page, frameID);
+
+    // Add the frame to the process wide map.
+    m_process->frameCreated(frameID, *m_mainFrame);
+
+    // This navigation was destroyed so no need to notify of redirect.
+    if (!m_page.navigationState().hasNavigation(m_navigationID))
+        return;
+
+    // Restore the main frame's committed URL as some clients may rely on it until the next load is committed.
+    if (auto* mainFrame = m_page.mainFrame())
+        m_mainFrame->frameLoadState().setURL(mainFrame->frameLoadState().url());
+
+    // 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 (m_isServerRedirect) {
+        m_mainFrame->frameLoadState().didStartProvisionalLoad(m_request.url());
+        m_page.didReceiveServerRedirectForProvisionalLoadForFrameShared(m_process, m_mainFrame->frameID(), m_navigationID, WTFMove(m_request), { });
+    }
+}
+
+void ProvisionalPageProxy::didPerformClientRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
+{
+    m_page.didPerformClientRedirectShared(m_process, sourceURLString, destinationURLString, frameID);
+}
+
+void ProvisionalPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
+{
+    // If the previous provisional load used the same process, we may receive IPC for this previous provisional's main frame that we need to ignore.
+    if (!m_mainFrame || m_mainFrame->frameID() != frameID)
+        return;
+
+    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "didStartProvisionalLoadForFrame: pageID = %" PRIu64 ", frameID = %" PRIu64 ", navigationID = %" PRIu64, m_page.pageID(), frameID, navigationID);
+    ASSERT(m_provisionalLoadURL.isNull());
+    m_provisionalLoadURL = url;
+
+    // Merely following a server side redirect so there is no need to send a didStartProvisionalLoad again.
+    if (m_isServerRedirect)
+        return;
+
+    // Clients expect the Page's main frame's expectedURL to be the provisional one when a provisional load is started.
+    if (auto* pageMainFrame = m_page.mainFrame())
+        pageMainFrame->didStartProvisionalLoad(url);
+
+    m_page.didStartProvisionalLoadForFrameShared(m_process, frameID, navigationID, WTFMove(url), WTFMove(unreachableURL), userData);
+}
+
+void ProvisionalPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError& error, const UserData& userData)
+{
+    RELEASE_LOG_ERROR_IF_ALLOWED(ProcessSwapping, "didFailProvisionalLoadForFrame: pageID = %" PRIu64 ", frameID = %" PRIu64 ", navigationID = %" PRIu64, m_page.pageID(), frameID, navigationID);
+    m_provisionalLoadURL = { };
+
+    // Make sure the Page's main frame's expectedURL gets cleared since we updated it in didStartProvisionalLoad.
+    if (auto* pageMainFrame = m_page.mainFrame())
+        pageMainFrame->didFailProvisionalLoad();
+
+    m_page.didFailProvisionalLoadForFrameShared(m_process, frameID, frameSecurityOrigin, navigationID, provisionalURL, error, userData); // Will delete |this|.
+}
+
+void ProvisionalPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData& userData)
+{
+    // If the previous provisional load used the same process, we may receive IPC for this previous provisional's main frame that we need to ignore.
+    if (!m_mainFrame || m_mainFrame->frameID() != frameID)
+        return;
+
+    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "didCommitLoadForFrame: pageID = %" PRIu64 ", frameID = %" PRIu64 ", navigationID = %" PRIu64, m_page.pageID(), frameID, navigationID);
+    m_provisionalLoadURL = { };
+    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
+
+    m_wasCommitted = true;
+    m_page.commitProvisionalPage(frameID, navigationID, mimeType, frameHasCustomContentProvider, frameLoadType, certificateInfo, containsPluginDocument, forcedHasInsecureContent, userData); // Will delete |this|.
+}
+
+void ProvisionalPageProxy::didNavigateWithNavigationData(const WebNavigationDataStore& store, uint64_t frameID)
+{
+    m_page.didNavigateWithNavigationDataShared(m_process, store, frameID);
+}
+
+void ProvisionalPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, URL&& url)
+{
+    m_page.didChangeProvisionalURLForFrameShared(m_process, frameID, navigationID, WTFMove(url));
+}
+
+void ProvisionalPageProxy::decidePolicyForNavigationActionAsync(uint64_t frameID, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, FrameInfoData&& frameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&& request, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, uint64_t listenerID)
+{
+    m_page.decidePolicyForNavigationActionAsyncShared(m_process, frameID, WTFMove(frameSecurityOrigin), navigationID, WTFMove(navigationActionData), WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
+}
+
+void ProvisionalPageProxy::decidePolicyForResponse(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, const UserData& userData)
+{
+    m_page.decidePolicyForResponseShared(m_process, frameID, frameSecurityOrigin, navigationID, response, request, canShowMIMEType, listenerID, userData);
+}
+
+void ProvisionalPageProxy::startURLSchemeTask(URLSchemeTaskParameters&& parameters)
+{
+    m_page.startURLSchemeTaskShared(m_process, WTFMove(parameters));
+}
+
+void ProvisionalPageProxy::backForwardGoToItem(const WebCore::BackForwardItemIdentifier& identifier, SandboxExtension::Handle& handle)
+{
+    m_page.backForwardGoToItemShared(m_process, identifier, handle);
+}
+
+void ProvisionalPageProxy::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
+{
+    ASSERT(decoder.messageReceiverName() == Messages::WebPageProxy::messageReceiverName());
+
+    if (decoder.messageName() == Messages::WebPageProxy::DidStartProgress::name()
+        || decoder.messageName() == Messages::WebPageProxy::DidChangeProgress::name()
+        || decoder.messageName() == Messages::WebPageProxy::BackForwardAddItem::name()
+        || decoder.messageName() == Messages::WebPageProxy::LogDiagnosticMessage::name()
+        || decoder.messageName() == Messages::WebPageProxy::LogDiagnosticMessageWithEnhancedPrivacy::name()
+        || decoder.messageName() == Messages::WebPageProxy::SetNetworkRequestsInProgress::name()
+#if PLATFORM(COCOA)
+        || decoder.messageName() == Messages::WebPageProxy::RegisterWebProcessAccessibilityToken::name()
+#endif
+        )
+    {
+        m_page.didReceiveMessage(connection, decoder);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::StartURLSchemeTask::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::StartURLSchemeTask>(decoder, this, &ProvisionalPageProxy::startURLSchemeTask);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::DecidePolicyForNavigationActionAsync::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::DecidePolicyForNavigationActionAsync>(decoder, this, &ProvisionalPageProxy::decidePolicyForNavigationActionAsync);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::DecidePolicyForResponse::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::DecidePolicyForResponse>(decoder, this, &ProvisionalPageProxy::decidePolicyForResponse);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::DidChangeProvisionalURLForFrame::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::DidChangeProvisionalURLForFrame>(decoder, this, &ProvisionalPageProxy::didChangeProvisionalURLForFrame);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::DidNavigateWithNavigationData::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::DidNavigateWithNavigationData>(decoder, this, &ProvisionalPageProxy::didNavigateWithNavigationData);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::DidPerformClientRedirect::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::DidPerformClientRedirect>(decoder, this, &ProvisionalPageProxy::didPerformClientRedirect);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::DidCreateMainFrame::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::DidCreateMainFrame>(decoder, this, &ProvisionalPageProxy::didCreateMainFrame);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::DidStartProvisionalLoadForFrame::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::DidStartProvisionalLoadForFrame>(decoder, this, &ProvisionalPageProxy::didStartProvisionalLoadForFrame);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::DidFailProvisionalLoadForFrame::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::DidFailProvisionalLoadForFrame>(decoder, this, &ProvisionalPageProxy::didFailProvisionalLoadForFrame);
+        return;
+    }
+
+    if (decoder.messageName() == Messages::WebPageProxy::DidCommitLoadForFrame::name()) {
+        IPC::handleMessage<Messages::WebPageProxy::DidCommitLoadForFrame>(decoder, this, &ProvisionalPageProxy::didCommitLoadForFrame);
+        return;
+    }
+
+    LOG(ProcessSwapping, "Unhandled message %s::%s from provisional process", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
+}
+
+void ProvisionalPageProxy::didReceiveSyncMessage(IPC::Connection& connection, IPC::Decoder& decoder, std::unique_ptr<IPC::Encoder>& replyEncoder)
+{
+    if (decoder.messageName() == Messages::WebPageProxy::BackForwardGoToItem::name()) {
+        IPC::handleMessageLegacySync<Messages::WebPageProxy::BackForwardGoToItem>(decoder, *replyEncoder, this, &ProvisionalPageProxy::backForwardGoToItem);
+        return;
+    }
+
+    m_page.didReceiveSyncMessage(connection, decoder, replyEncoder);
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit/UIProcess/ProvisionalPageProxy.h b/Source/WebKit/UIProcess/ProvisionalPageProxy.h
new file mode 100644 (file)
index 0000000..dd1519e
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "MessageReceiver.h"
+#include <wtf/WeakPtr.h>
+
+namespace WebCore {
+class ResourceRequest;
+}
+
+namespace WebKit {
+
+class DrawingAreaProxy;
+class SuspendedPageProxy;
+class WebFrameProxy;
+struct WebNavigationDataStore;
+class WebPageProxy;
+class WebProcessProxy;
+
+class ProvisionalPageProxy : public IPC::MessageReceiver, public CanMakeWeakPtr<ProvisionalPageProxy> {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ProvisionalPageProxy(WebPageProxy&, Ref<WebProcessProxy>&&, std::unique_ptr<SuspendedPageProxy>, uint64_t navigationID, bool isServerRedirect, const WebCore::ResourceRequest&, ProcessSwapRequestedByClient);
+    ~ProvisionalPageProxy();
+
+    WebPageProxy& page() { return m_page; }
+    WebFrameProxy* mainFrame() const { return m_mainFrame.get(); }
+    WebProcessProxy& process() { return m_process.get(); }
+    ProcessSwapRequestedByClient processSwapRequestedByClient() const { return m_processSwapRequestedByClient; }
+    uint64_t navigationID() const { return m_navigationID; }
+
+    DrawingAreaProxy* drawingArea() const { return m_drawingArea.get(); }
+    std::unique_ptr<DrawingAreaProxy> takeDrawingArea();
+
+    void loadData(API::Navigation&, const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, Optional<WebsitePoliciesData>&& = WTF::nullopt);
+    void loadRequest(API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, Optional<WebsitePoliciesData>&& = WTF::nullopt);
+    void goToBackForwardItem(API::Navigation&, WebBackForwardListItem&, Optional<WebsitePoliciesData>&&);
+    void cancel();
+
+    void processDidFinishLaunching();
+    void processDidTerminate();
+
+private:
+    // IPC::MessageReceiver
+    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
+    void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&) final;
+
+    void decidePolicyForNavigationActionAsync(uint64_t frameID, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&&, FrameInfoData&&, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData&, uint64_t listenerID);
+    void decidePolicyForResponse(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, uint64_t listenerID, const UserData&);
+    void didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, URL&&);
+    void didNavigateWithNavigationData(const WebNavigationDataStore&, uint64_t frameID);
+    void didPerformClientRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID);
+    void didCreateMainFrame(uint64_t frameID);
+    void didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&&, URL&& unreachableURL, const UserData&);
+    void didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo&, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData&);
+    void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&);
+    void startURLSchemeTask(URLSchemeTaskParameters&&);
+    void backForwardGoToItem(const WebCore::BackForwardItemIdentifier&, SandboxExtension::Handle&);
+
+    void initializeWebPage();
+    void finishInitializingWebPageAfterProcessLaunch();
+
+    WebPageProxy& m_page;
+    Ref<WebProcessProxy> m_process;
+    std::unique_ptr<DrawingAreaProxy> m_drawingArea;
+    RefPtr<WebFrameProxy> m_mainFrame;
+    uint64_t m_navigationID;
+    bool m_isServerRedirect;
+    WebCore::ResourceRequest m_request;
+    ProcessSwapRequestedByClient m_processSwapRequestedByClient;
+    bool m_wasCommitted { false };
+    URL m_provisionalLoadURL;
+
+#if PLATFORM(IOS_FAMILY)
+    ProcessThrottler::ForegroundActivityToken m_suspensionToken;
+#endif
+};
+
+} // namespace WebKit
index 32f2886..f94ad3f 100644 (file)
@@ -40,7 +40,7 @@ class RemoteScrollingCoordinatorTransaction;
 
 class RemoteLayerTreeDrawingAreaProxy final : public DrawingAreaProxy {
 public:
-    explicit RemoteLayerTreeDrawingAreaProxy(WebPageProxy&);
+    RemoteLayerTreeDrawingAreaProxy(WebPageProxy&, WebProcessProxy&);
     virtual ~RemoteLayerTreeDrawingAreaProxy();
 
     const RemoteLayerTreeHost& remoteLayerTreeHost() const { return *m_remoteLayerTreeHost; }
index 35946bb..a380a50 100644 (file)
@@ -105,8 +105,8 @@ namespace WebKit {
 using namespace IPC;
 using namespace WebCore;
 
-RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy(WebPageProxy& webPageProxy)
-    : DrawingAreaProxy(DrawingAreaTypeRemoteLayerTree, webPageProxy)
+RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy(WebPageProxy& webPageProxy, WebProcessProxy& process)
+    : DrawingAreaProxy(DrawingAreaTypeRemoteLayerTree, webPageProxy, process)
     , m_remoteLayerTreeHost(std::make_unique<RemoteLayerTreeHost>(*this))
 {
 #if HAVE(IOSURFACE)
@@ -115,7 +115,7 @@ RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy(WebPageProxy& w
     IOSurfacePool::sharedPool().setPoolSize(0);
 #endif
 
-    m_webPageProxy.process().addMessageReceiver(Messages::RemoteLayerTreeDrawingAreaProxy::messageReceiverName(), m_webPageProxy.pageID(), *this);
+    process.addMessageReceiver(Messages::RemoteLayerTreeDrawingAreaProxy::messageReceiverName(), m_webPageProxy.pageID(), *this);
 
     if (m_webPageProxy.preferences().tiledScrollingIndicatorVisible())
         initializeDebugIndicator();
@@ -124,7 +124,7 @@ RemoteLayerTreeDrawingAreaProxy::RemoteLayerTreeDrawingAreaProxy(WebPageProxy& w
 RemoteLayerTreeDrawingAreaProxy::~RemoteLayerTreeDrawingAreaProxy()
 {
     m_callbacks.invalidate(CallbackBase::Error::OwnerWasInvalidated);
-    m_webPageProxy.process().removeMessageReceiver(Messages::RemoteLayerTreeDrawingAreaProxy::messageReceiverName(), m_webPageProxy.pageID());
+    process().removeMessageReceiver(Messages::RemoteLayerTreeDrawingAreaProxy::messageReceiverName(), m_webPageProxy.pageID());
 
 #if PLATFORM(IOS_FAMILY)
     [m_displayLinkHandler invalidate];
@@ -161,7 +161,7 @@ void RemoteLayerTreeDrawingAreaProxy::sizeDidChange()
 
 void RemoteLayerTreeDrawingAreaProxy::deviceScaleFactorDidChange()
 {
-    m_webPageProxy.process().send(Messages::DrawingArea::SetDeviceScaleFactor(m_webPageProxy.deviceScaleFactor()), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::SetDeviceScaleFactor(m_webPageProxy.deviceScaleFactor()), m_webPageProxy.pageID());
 }
 
 void RemoteLayerTreeDrawingAreaProxy::didUpdateGeometry()
@@ -179,7 +179,7 @@ void RemoteLayerTreeDrawingAreaProxy::didUpdateGeometry()
 void RemoteLayerTreeDrawingAreaProxy::sendUpdateGeometry()
 {
     m_lastSentSize = m_size;
-    m_webPageProxy.process().send(Messages::DrawingArea::UpdateGeometry(m_size, false /* flushSynchronously */, MachSendRight()), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::UpdateGeometry(m_size, false /* flushSynchronously */, MachSendRight()), m_webPageProxy.pageID());
     m_isWaitingForDidUpdateGeometry = true;
 }
 
@@ -264,12 +264,12 @@ void RemoteLayerTreeDrawingAreaProxy::commitLayerTree(const RemoteLayerTreeTrans
 
 void RemoteLayerTreeDrawingAreaProxy::acceleratedAnimationDidStart(uint64_t layerID, const String& key, MonotonicTime startTime)
 {
-    m_webPageProxy.process().send(Messages::DrawingArea::AcceleratedAnimationDidStart(layerID, key, startTime), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::AcceleratedAnimationDidStart(layerID, key, startTime), m_webPageProxy.pageID());
 }
 
 void RemoteLayerTreeDrawingAreaProxy::acceleratedAnimationDidEnd(uint64_t layerID, const String& key)
 {
-    m_webPageProxy.process().send(Messages::DrawingArea::AcceleratedAnimationDidEnd(layerID, key), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::AcceleratedAnimationDidEnd(layerID, key), m_webPageProxy.pageID());
 }
 
 static const float indicatorInset = 10;
@@ -430,7 +430,7 @@ void RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay()
     // Waiting for CA to commit is insufficient, because the render server can still be
     // using our backing store. We can improve this by waiting for the render server to commit
     // if we find API to do so, but for now we will make extra buffers if need be.
-    m_webPageProxy.process().send(Messages::DrawingArea::DidUpdate(), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::DidUpdate(), m_webPageProxy.pageID());
 
     m_lastVisibleTransactionID = m_transactionIDForPendingCACommit;
 
@@ -458,7 +458,7 @@ void RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState(ActivityStat
     }();
 
     auto startTime = MonotonicTime::now();
-    while (m_webPageProxy.process().connection()->waitForAndDispatchImmediately<Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree>(m_webPageProxy.pageID(), activityStateUpdateTimeout - (MonotonicTime::now() - startTime), IPC::WaitForOption::InterruptWaitingIfSyncMessageArrives)) {
+    while (process().connection()->waitForAndDispatchImmediately<Messages::RemoteLayerTreeDrawingAreaProxy::CommitLayerTree>(m_webPageProxy.pageID(), activityStateUpdateTimeout - (MonotonicTime::now() - startTime), IPC::WaitForOption::InterruptWaitingIfSyncMessageArrives)) {
         if (activityStateChangeID == ActivityStateChangeAsynchronous || activityStateChangeID <= m_activityStateChangeID)
             return;
     }
@@ -471,7 +471,7 @@ void RemoteLayerTreeDrawingAreaProxy::dispatchAfterEnsuringDrawing(WTF::Function
         return;
     }
 
-    m_webPageProxy.process().send(Messages::DrawingArea::AddTransactionCallbackID(m_callbacks.put(WTFMove(callbackFunction), m_webPageProxy.process().throttler().backgroundActivityToken())), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::AddTransactionCallbackID(m_callbacks.put(WTFMove(callbackFunction), process().throttler().backgroundActivityToken())), m_webPageProxy.pageID());
 }
 
 void RemoteLayerTreeDrawingAreaProxy::hideContentUntilPendingUpdate()
index f198a81..ff76d9f 100644 (file)
@@ -100,7 +100,9 @@ SuspendedPageProxy::~SuspendedPageProxy()
     // If the suspended page was not consumed before getting destroyed, then close the corresponding page
     // on the WebProcess side.
     m_process->send(Messages::WebPage::Close(), m_page.pageID());
-    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
+
+    if (m_suspensionState == SuspensionState::Suspending)
+        m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
 
     // We call maybeShutDown() asynchronously since the SuspendedPage is currently being removed from the WebProcessPool
     // and we want to avoid re-entering WebProcessPool methods.
@@ -134,7 +136,6 @@ void SuspendedPageProxy::unsuspend()
     ASSERT(m_suspensionState == SuspensionState::Suspended);
 
     m_suspensionState = SuspensionState::Resumed;
-    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
     m_process->send(Messages::WebPage::SetIsSuspended(false), m_page.pageID());
 }
 
@@ -151,6 +152,8 @@ void SuspendedPageProxy::didProcessRequestToSuspend(SuspensionState newSuspensio
     m_suspensionToken = nullptr;
 #endif
 
+    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
+
     if (m_readyToUnsuspendHandler)
         m_readyToUnsuspendHandler(this);
 }
index c77a26b..53c7196 100644 (file)
@@ -27,6 +27,7 @@
 #include "WebFrameProxy.h"
 
 #include "APINavigation.h"
+#include "ProvisionalPageProxy.h"
 #include "WebCertificateInfo.h"
 #include "WebFramePolicyListenerProxy.h"
 #include "WebPageMessages.h"
@@ -74,7 +75,7 @@ bool WebFrameProxy::isMainFrame() const
     if (!m_page)
         return false;
 
-    return this == m_page->mainFrame();
+    return this == m_page->mainFrame() || (m_page->provisionalPageProxy() && this == m_page->provisionalPageProxy()->mainFrame());
 }
 
 void WebFrameProxy::loadURL(const URL& url)
index 0c8a687..3bbf68c 100644 (file)
@@ -77,6 +77,7 @@
 #include "PluginInformation.h"
 #include "PluginProcessManager.h"
 #include "PrintInfo.h"
+#include "ProvisionalPageProxy.h"
 #include "SafeBrowsingWarning.h"
 #include "ShareSheetCallbackID.h"
 #include "SharedBufferDataReference.h"
 // This controls what strategy we use for mouse wheel coalescing.
 #define MERGE_WHEEL_EVENTS 1
 
-#define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, m_process->connection())
-#define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(url), m_process->connection())
+#define MESSAGE_CHECK(process, assertion) MESSAGE_CHECK_BASE(assertion, process.connection())
+#define MESSAGE_CHECK_URL(process, url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(process, url), process.connection())
 
 #define RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - WebPageProxy::" fmt, this, ##__VA_ARGS__)
 
@@ -545,6 +546,13 @@ PAL::SessionID WebPageProxy::sessionID() const
     return m_websiteDataStore->sessionID();
 }
 
+DrawingAreaProxy* WebPageProxy::provisionalDrawingArea() const
+{
+    if (m_provisionalPage && m_provisionalPage->drawingArea())
+        return m_provisionalPage->drawingArea();
+    return drawingArea();
+}
+
 void WebPageProxy::changeWebsiteDataStore(WebsiteDataStore& websiteDataStore)
 {
     m_process->processPool().pageEndUsingWebsiteDataStore(*this);
@@ -768,38 +776,26 @@ bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, Opt
     return true;
 }
 
-void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, std::unique_ptr<SuspendedPageProxy>&& destinationSuspendedPage, IsSwapFromSuspended isSwapFromSuspended)
+void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, std::unique_ptr<DrawingAreaProxy>&& drawingArea, RefPtr<WebFrameProxy>&& mainFrame)
 {
     ASSERT(!m_isClosed);
     RELEASE_LOG_IF_ALLOWED(Loading, "swapToWebProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
 
     m_process = WTFMove(process);
+    ASSERT(!m_drawingArea);
+    setDrawingArea(WTFMove(drawingArea));
+    ASSERT(!m_mainFrame);
+    m_mainFrame = WTFMove(mainFrame);
     m_isValid = true;
 
-    // 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) {
-        if (!destinationSuspendedPage->failedToSuspend()) {
-            ASSERT(!m_mainFrame);
-            ASSERT(&destinationSuspendedPage->process() == m_process.ptr());
-            destinationSuspendedPage->unsuspend();
-            m_mainFrame = WebFrameProxy::create(*this, destinationSuspendedPage->mainFrameID());
-            m_process->frameCreated(destinationSuspendedPage->mainFrameID(), *m_mainFrame);
-        } else {
-            // We failed to suspend the page so destroy it now and merely reuse its WebContent process.
-            destinationSuspendedPage = nullptr;
-        }
-    }
-
     m_process->addExistingWebPage(*this, m_pageID, WebProcessProxy::BeginsUsingDataStore::No);
     m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
 
-    finishAttachingToWebProcess(isSwapFromSuspended);
+    // No need to initialize the WebPage since it was created when we created the ProvisionalPageProxy.
+    finishAttachingToWebProcess(ShouldInitializeWebPage::No);
 }
 
-void WebPageProxy::finishAttachingToWebProcess(IsSwapFromSuspended isSwapFromSuspended)
+void WebPageProxy::finishAttachingToWebProcess(ShouldInitializeWebPage shouldInitializePage)
 {
     ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
 
@@ -835,7 +831,8 @@ void WebPageProxy::finishAttachingToWebProcess(IsSwapFromSuspended isSwapFromSus
     m_editableImageController = std::make_unique<EditableImageController>(*this);
 #endif
 
-    initializeWebPage(isSwapFromSuspended);
+    if (shouldInitializePage == ShouldInitializeWebPage::Yes)
+        initializeWebPage();
 
     m_inspector->updateForNewPageProcess(this);
 
@@ -900,12 +897,11 @@ RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwar
     return WTFMove(navigation);
 }
 
-void WebPageProxy::initializeWebPage(IsSwapFromSuspended isSwapFromSuspended)
+void WebPageProxy::setDrawingArea(std::unique_ptr<DrawingAreaProxy>&& drawingArea)
 {
-    ASSERT(isValid());
-
-    m_drawingArea = pageClient().createDrawingAreaProxy();
-    ASSERT(m_drawingArea);
+    m_drawingArea = WTFMove(drawingArea);
+    if (!m_drawingArea)
+        return;
 
 #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
     if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) {
@@ -916,15 +912,16 @@ void WebPageProxy::initializeWebPage(IsSwapFromSuspended isSwapFromSuspended)
 #endif
     }
 #endif
+}
 
-    auto parameters = creationParameters();
-    parameters.isSwapFromSuspended = isSwapFromSuspended == IsSwapFromSuspended::Yes;
+void WebPageProxy::initializeWebPage()
+{
+    ASSERT(isValid());
 
-#if ENABLE(SERVICE_WORKER)
-    parameters.hasRegisteredServiceWorkers = process().processPool().mayHaveRegisteredServiceWorkers(m_websiteDataStore);
-#endif
+    setDrawingArea(pageClient().createDrawingAreaProxy(m_process));
+    ASSERT(m_drawingArea);
 
-    process().send(Messages::WebProcess::CreateWebPage(m_pageID, parameters), 0);
+    process().send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters(m_process)), 0);
 
     m_needsToFinishInitializingWebPageAfterProcessLaunch = true;
     finishInitializingWebPageAfterProcessLaunch();
@@ -1034,12 +1031,12 @@ bool WebPageProxy::tryClose()
     return false;
 }
 
-bool WebPageProxy::maybeInitializeSandboxExtensionHandle(const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
+bool WebPageProxy::maybeInitializeSandboxExtensionHandle(WebProcessProxy& process, const URL& url, SandboxExtension::Handle& sandboxExtensionHandle)
 {
     if (!url.isLocalFile())
         return false;
 
-    if (m_process->hasAssumedReadAccessToURL(url))
+    if (process.hasAssumedReadAccessToURL(url))
         return false;
 
     // Inspector resources are in a directory with assumed access.
@@ -1063,20 +1060,21 @@ RefPtr<API::Navigation> WebPageProxy::loadRequest(ResourceRequest&& request, Sho
     RELEASE_LOG_IF_ALLOWED(Loading, "loadRequest: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
 
     auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request), m_backForwardList->currentItem());
-    loadRequestWithNavigation(navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, ShouldTreatAsContinuingLoad::No);
+    loadRequestWithNavigationShared(m_process, navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, ShouldTreatAsContinuingLoad::No);
     return WTFMove(navigation);
 }
 
-void WebPageProxy::loadRequestWithNavigation(API::Navigation& navigation, ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
+void WebPageProxy::loadRequestWithNavigationShared(WebProcessProxy& process, API::Navigation& navigation, ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
 {
     ASSERT(!m_isClosed);
 
-    RELEASE_LOG_IF_ALLOWED(Loading, "loadRequestWithNavigation: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
+    RELEASE_LOG_IF_ALLOWED(Loading, "loadRequestWithNavigation: webPID = %i, pageID = %" PRIu64, process.processIdentifier(), m_pageID);
 
     auto transaction = m_pageLoadState.transaction();
 
     auto url = request.url();
-    m_pageLoadState.setPendingAPIRequestURL(transaction, url);
+    if (shouldTreatAsContinuingLoad != ShouldTreatAsContinuingLoad::Yes)
+        m_pageLoadState.setPendingAPIRequestURL(transaction, url);
 
     if (!isValid())
         reattachToWebProcess();
@@ -1085,19 +1083,19 @@ void WebPageProxy::loadRequestWithNavigation(API::Navigation& navigation, Resour
     loadParameters.navigationID = navigation.navigationID();
     loadParameters.request = WTFMove(request);
     loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
-    loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
+    loadParameters.userData = UserData(process.transformObjectsToHandles(userData).get());
     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
     loadParameters.websitePolicies = WTFMove(websitePolicies);
     loadParameters.lockHistory = navigation.lockHistory();
     loadParameters.lockBackForwardList = navigation.lockBackForwardList();
     loadParameters.clientRedirectSourceForHistory = navigation.clientRedirectSourceForHistory();
-    bool createdExtension = maybeInitializeSandboxExtensionHandle(url, loadParameters.sandboxExtensionHandle);
+    bool createdExtension = maybeInitializeSandboxExtensionHandle(process, url, loadParameters.sandboxExtensionHandle);
     if (createdExtension)
-        willAcquireUniversalFileReadSandboxExtension();
+        willAcquireUniversalFileReadSandboxExtension(process);
     addPlatformLoadParameters(loadParameters);
 
-    m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
-    m_process->responsivenessTimer().start();
+    process.send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
+    process.responsivenessTimer().start();
 }
 
 RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
@@ -1162,13 +1160,13 @@ RefPtr<API::Navigation> WebPageProxy::loadData(const IPC::DataReference& data, c
     }
 
     auto navigation = m_navigationState->createLoadDataNavigation(std::make_unique<API::SubstituteData>(data.vector(), MIMEType, encoding, baseURL, userData));
-    loadDataWithNavigation(navigation, data, MIMEType, encoding, baseURL, userData, ShouldTreatAsContinuingLoad::No);
+    loadDataWithNavigationShared(m_process, navigation, data, MIMEType, encoding, baseURL, userData, ShouldTreatAsContinuingLoad::No);
     return WTFMove(navigation);
 }
 
-void WebPageProxy::loadDataWithNavigation(API::Navigation& navigation, const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
+void WebPageProxy::loadDataWithNavigationShared(WebProcessProxy& process, API::Navigation& navigation, const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& websitePolicies)
 {
-    RELEASE_LOG_IF_ALLOWED(Loading, "loadDataWithNavigation: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
+    RELEASE_LOG_IF_ALLOWED(Loading, "loadDataWithNavigation: webPID = %i, pageID = %" PRIu64, process.processIdentifier(), m_pageID);
 
     ASSERT(!m_isClosed);
 
@@ -1186,13 +1184,13 @@ void WebPageProxy::loadDataWithNavigation(API::Navigation& navigation, const IPC
     loadParameters.encodingName = encoding;
     loadParameters.baseURLString = baseURL;
     loadParameters.shouldTreatAsContinuingLoad = shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes;
-    loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
+    loadParameters.userData = UserData(process.transformObjectsToHandles(userData).get());
     loadParameters.websitePolicies = WTFMove(websitePolicies);
     addPlatformLoadParameters(loadParameters);
 
-    m_process->assumeReadAccessToBaseURL(*this, baseURL);
-    m_process->send(Messages::WebPage::LoadData(loadParameters), m_pageID);
-    m_process->responsivenessTimer().start();
+    process.assumeReadAccessToBaseURL(*this, baseURL);
+    process.send(Messages::WebPage::LoadData(loadParameters), m_pageID);
+    process.responsivenessTimer().start();
 }
 
 void WebPageProxy::loadAlternateHTML(const IPC::DataReference& htmlData, const String& encoding, const URL& baseURL, const URL& unreachableURL, API::Object* userData)
@@ -1294,6 +1292,10 @@ void WebPageProxy::stopLoading()
     }
 
     m_process->send(Messages::WebPage::StopLoading(), m_pageID);
+    if (m_provisionalPage) {
+        m_provisionalPage->cancel();
+        m_provisionalPage = nullptr;
+    }
     m_process->responsivenessTimer().start();
 }
 
@@ -1309,9 +1311,9 @@ RefPtr<API::Navigation> WebPageProxy::reload(OptionSet<WebCore::ReloadOption> op
         m_pageLoadState.setPendingAPIRequestURL(transaction, url);
 
         // We may not have an extension yet if back/forward list was reinstated after a WebProcess crash or a browser relaunch
-        bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), url), sandboxExtensionHandle);
+        bool createdExtension = maybeInitializeSandboxExtensionHandle(m_process, URL(URL(), url), sandboxExtensionHandle);
         if (createdExtension)
-            willAcquireUniversalFileReadSandboxExtension();
+            willAcquireUniversalFileReadSandboxExtension(m_process);
     }
 
     if (!isValid())
@@ -2092,7 +2094,7 @@ void WebPageProxy::performDragControllerAction(DragControllerAction action, Drag
 
 void WebPageProxy::didPerformDragControllerAction(uint64_t dragOperation, WebCore::DragHandlingMethod dragHandlingMethod, bool mouseIsOverFileInput, unsigned numberOfItemsToBeAccepted, const IntRect& insertionRect, const IntRect& editableElementRect)
 {
-    MESSAGE_CHECK(dragOperation <= DragOperationDelete);
+    MESSAGE_CHECK(m_process.get(), dragOperation <= DragOperationDelete);
 
     m_currentDragOperation = static_cast<DragOperation>(dragOperation);
     m_currentDragHandlingMethod = dragHandlingMethod;
@@ -2405,7 +2407,7 @@ void WebPageProxy::findPlugin(const String& mimeType, uint32_t processType, cons
 {
     PageClientProtector protector(pageClient());
 
-    MESSAGE_CHECK_URL(urlString);
+    MESSAGE_CHECK_URL(process(), urlString);
 
     URL pluginURL = URL { URL(), urlString };
     String newMimeType = mimeType.convertToASCIILowercase();
@@ -2698,7 +2700,7 @@ void WebPageProxy::receivedNavigationPolicyDecision(WebPolicyAction policyAction
         }
 
         if (processForNavigation.ptr() != &process()) {
-            policyAction = isPageOpenedByDOMShowingInitialEmptyDocument() ? WebPolicyAction::Ignore : WebPolicyAction::Suspend;
+            policyAction = WebPolicyAction::Ignore;
             RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction, swapping process %i with process %i for navigation, reason: %{public}s", processIdentifier(), processForNavigation->processIdentifier(), reason.utf8().data());
             LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), processForNavigation->processIdentifier(), navigation->navigationID(), navigation->loggingString());
         } else
@@ -2707,8 +2709,14 @@ void WebPageProxy::receivedNavigationPolicyDecision(WebPolicyAction policyAction
         bool shouldProcessSwap = processForNavigation.ptr() != &process();
         receivedPolicyDecision(policyAction, navigation.ptr(), shouldProcessSwap ? WTF::nullopt : WTFMove(data), WTFMove(sender));
 
-        if (shouldProcessSwap)
-            continueNavigationInNewProcess(navigation, destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr, WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
+        if (!shouldProcessSwap)
+            return;
+
+        auto suspendedPage = destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr;
+        if (suspendedPage && suspendedPage->failedToSuspend())
+            suspendedPage = nullptr;
+
+        continueNavigationInNewProcess(navigation, WTFMove(suspendedPage), WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
     });
 }
 
@@ -2744,24 +2752,45 @@ void WebPageProxy::receivedPolicyDecision(WebPolicyAction action, API::Navigatio
     sender->send(action, navigation ? navigation->navigationID() : 0, downloadID, WTFMove(websitePolicies));
 }
 
-void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& process, ProcessSwapRequestedByClient processSwapRequestedByClient, Optional<WebsitePoliciesData>&& websitePolicies)
+void WebPageProxy::commitProvisionalPage(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData& userData)
 {
-    RELEASE_LOG_IF_ALLOWED(Loading, "continueNavigationInNewProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
-    LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
+    ASSERT(m_provisionalPage);
+    RELEASE_LOG_IF_ALLOWED(Loading, "commitProvisionalPage: previousPID = %i, newPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_provisionalPage->process().processIdentifier(), m_pageID);
 
-    Ref<WebProcessProxy> previousProcess = m_process.copyRef();
     Optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? makeOptional(m_mainFrame->frameID()) : WTF::nullopt;
-    auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : URL();
 
-    ASSERT(m_process.ptr() != process.ptr());
+    ASSERT(m_process.ptr() != &m_provisionalPage->process());
 
     processDidTerminate(ProcessTerminationReason::NavigationSwap);
 
     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
-    bool didSuspendPreviousPage = suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess, processSwapRequestedByClient);
+    auto* navigation = navigationState().navigation(m_provisionalPage->navigationID());
+    bool didSuspendPreviousPage = navigation ? suspendCurrentPageIfPossible(*navigation, mainFrameIDInPreviousProcess, m_provisionalPage->processSwapRequestedByClient()) : false;
     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::No);
 
-    swapToWebProcess(WTFMove(process), WTFMove(suspendedPageProxy), didSuspendPreviousPage ? IsSwapFromSuspended::Yes : IsSwapFromSuspended::No);
+    // There is no way we'll be able to return to the page in the previous page so close it.
+    if (!didSuspendPreviousPage)
+        m_process->send(Messages::WebPage::Close(), pageID());
+
+    swapToWebProcess(m_provisionalPage->process(), m_provisionalPage->takeDrawingArea(), m_provisionalPage->mainFrame());
+
+    didCommitLoadForFrame(frameID, navigationID, mimeType, frameHasCustomContentProvider, frameLoadType, certificateInfo, containsPluginDocument, forcedHasInsecureContent, userData);
+
+    m_provisionalPage = nullptr;
+}
+
+void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& newProcess, ProcessSwapRequestedByClient processSwapRequestedByClient, Optional<WebsitePoliciesData>&& websitePolicies)
+{
+    RELEASE_LOG_IF_ALLOWED(Loading, "continueNavigationInNewProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
+    LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
+
+    if (m_provisionalPage) {
+        if (m_provisionalPage->navigationID() != navigation.navigationID())
+            m_provisionalPage->cancel();
+        m_provisionalPage = nullptr;
+    }
+
+    m_provisionalPage = std::make_unique<ProvisionalPageProxy>(*this, newProcess.copyRef(), WTFMove(suspendedPageProxy), navigation.navigationID(), navigation.currentRequestIsRedirect(), navigation.currentRequest(), processSwapRequestedByClient);
 
     if (auto* item = navigation.targetItem()) {
         LOG(Loading, "WebPageProxy %p continueNavigationInNewProcess to back item URL %s", this, item->url().utf8().data());
@@ -2769,67 +2798,22 @@ void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, s
         auto transaction = m_pageLoadState.transaction();
         m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
 
-        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, WTFMove(websitePolicies)), m_pageID);
-        m_process->responsivenessTimer().start();
-
+        m_provisionalPage->goToBackForwardItem(navigation, *item, WTFMove(websitePolicies));
         return;
     }
 
     if (m_backForwardList->currentItem() && (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.
-        m_process->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
+        newProcess->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
     }
 
     // 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(), ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
+        m_provisionalPage->loadData(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get(), WTFMove(websitePolicies));
     else
-        loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
-
-    ASSERT(!m_mainFrame);
-    m_mainFrameCreationHandler = [this, weakThis = makeWeakPtr(*this), navigationID = navigation.navigationID(), request =  navigation.currentRequest(), mainFrameURL, isServerRedirect = navigation.currentRequestIsRedirect()]() mutable {
-        if (!weakThis)
-            return;
-
-        ASSERT(m_mainFrame);
-        // This navigation was destroyed so no need to notify of redirect.
-        if (!navigationState().navigation(navigationID))
-            return;
-
-        // Restore the main frame's committed URL as some clients may rely on it until the next load is committed.
-        m_mainFrame->frameLoadState().setURL(mainFrameURL);
-
-        // Normally, notification of a server redirect comes from the WebContent process.
-        // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
-        // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
-        if (isServerRedirect) {
-            m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
-            didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigationID, WTFMove(request), { });
-        }
-    };
-
-    if (!m_process->processPool().configuration().processSwapsOnWindowOpenWithOpener() || !isPageOpenedByDOMShowingInitialEmptyDocument() || !mainFrameIDInPreviousProcess) {
-        // There is no way we'll be able to return to the page in the previous page so close it.
-        if (!didSuspendPreviousPage)
-            previousProcess->send(Messages::WebPage::Close(), m_pageID);
-        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());
-    };
+        m_provisionalPage->loadRequest(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, WTFMove(websitePolicies));
 }
 
 bool WebPageProxy::isPageOpenedByDOMShowingInitialEmptyDocument() const
@@ -3687,25 +3671,20 @@ void WebPageProxy::didCreateMainFrame(uint64_t frameID)
 
     PageClientProtector protector(pageClient());
 
-    MESSAGE_CHECK(!m_mainFrame);
-    MESSAGE_CHECK(m_process->canCreateFrame(frameID));
+    MESSAGE_CHECK(m_process.get(), !m_mainFrame);
+    MESSAGE_CHECK(m_process.get(), m_process->canCreateFrame(frameID));
 
     m_mainFrame = WebFrameProxy::create(*this, frameID);
 
     // Add the frame to the process wide map.
     m_process->frameCreated(frameID, *m_mainFrame);
-
-    if (m_mainFrameCreationHandler) {
-        m_mainFrameCreationHandler();
-        m_mainFrameCreationHandler = nullptr;
-    }
 }
 
 void WebPageProxy::didCreateSubframe(uint64_t frameID)
 {
     PageClientProtector protector(pageClient());
 
-    MESSAGE_CHECK(m_mainFrame);
+    MESSAGE_CHECK(m_process.get(), m_mainFrame);
 
     // The DecidePolicyForNavigationActionSync IPC is synchronous and may therefore get processed before the DidCreateSubframe one.
     // When this happens, decidePolicyForNavigationActionSync() calls didCreateSubframe() and we need to ignore the DidCreateSubframe
@@ -3713,7 +3692,7 @@ void WebPageProxy::didCreateSubframe(uint64_t frameID)
     if (m_process->webFrame(frameID))
         return;
 
-    MESSAGE_CHECK(m_process->canCreateFrame(frameID));
+    MESSAGE_CHECK(m_process.get(), m_process->canCreateFrame(frameID));
     
     auto subFrame = WebFrameProxy::create(*this, frameID);
 
@@ -3723,10 +3702,6 @@ void WebPageProxy::didCreateSubframe(uint64_t frameID)
 
 void WebPageProxy::didCreateWindow(uint64_t frameID, GlobalWindowIdentifier&& windowIdentifier)
 {
-    if (m_mainFrame && m_mainFrame->frameID() == frameID) {
-        if (auto mainFrameWindowCreationHandler = WTFMove(m_mainFrameWindowCreationHandler))
-            mainFrameWindowCreationHandler(windowIdentifier);
-    }
 }
 
 double WebPageProxy::estimatedProgress() const
@@ -3779,33 +3754,34 @@ void WebPageProxy::didDestroyNavigation(uint64_t navigationID)
 {
     PageClientProtector protector(pageClient());
 
+    // On process-swap, the previous process tries to destroy the navigation but the provisional process is actually taking over the navigation.
+    if (m_provisionalPage && m_provisionalPage->navigationID() == navigationID)
+        return;
+
     // FIXME: Message check the navigationID.
     m_navigationState->didDestroyNavigation(navigationID);
 }
 
 void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
 {
+    didStartProvisionalLoadForFrameShared(m_process, frameID, navigationID, WTFMove(url), WTFMove(unreachableURL), userData);
+}
+
+void WebPageProxy::didStartProvisionalLoadForFrameShared(WebProcessProxy& process, uint64_t frameID, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
+{
     PageClientProtector protector(pageClient());
 
-    WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK_URL(url);
+    WebFrameProxy* frame = process.webFrame(frameID);
+    MESSAGE_CHECK(process, frame);
+    MESSAGE_CHECK_URL(process, url);
 
     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
     RefPtr<API::Navigation> navigation;
     if (frame->isMainFrame() && navigationID)
         navigation = navigationState().navigation(navigationID);
 
-    // If this seemingly new load is actually continuing a server redirect for a previous navigation in a new process,
-    // then we ignore this notification.
-    if (navigation && navigation->currentRequestIsRedirect()) {
-        auto navigationProcessIdentifier = navigation->currentRequestProcessIdentifier();
-        if (navigationProcessIdentifier && *navigationProcessIdentifier != m_process->coreProcessIdentifier())
-            return;
-    }
-
-    LOG(Loading, "WebPageProxy %" PRIu64 " in process pid %i didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", m_pageID, m_process->processIdentifier(), frameID, navigationID, url.string().utf8().data());
-    RELEASE_LOG_IF_ALLOWED(Loading, "didStartProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
+    LOG(Loading, "WebPageProxy %" PRIu64 " in process pid %i didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", m_pageID, process.processIdentifier(), frameID, navigationID, url.string().utf8().data());
+    RELEASE_LOG_IF_ALLOWED(Loading, "didStartProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, process.processIdentifier(), m_pageID, frameID);
 
     auto transaction = m_pageLoadState.transaction();
 
@@ -3824,21 +3800,26 @@ void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t na
 
     m_pageLoadState.commitChanges();
     if (m_loaderClient)
-        m_loaderClient->didStartProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
+        m_loaderClient->didStartProvisionalLoadForFrame(*this, *frame, navigation.get(), process.transformHandlesToObjects(userData.object()).get());
     else if (frame->isMainFrame())
-        m_navigationClient->didStartProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
+        m_navigationClient->didStartProvisionalNavigation(*this, navigation.get(), process.transformHandlesToObjects(userData.object()).get());
 }
 
 void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, ResourceRequest&& request, const UserData& userData)
 {
+    didReceiveServerRedirectForProvisionalLoadForFrameShared(m_process, frameID, navigationID, WTFMove(request), userData);
+}
+
+void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrameShared(WebProcessProxy& process, uint64_t frameID, uint64_t navigationID, ResourceRequest&& request, const UserData& userData)
+{
     LOG(Loading, "WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", frameID, navigationID, request.url().string().utf8().data());
-    RELEASE_LOG_IF_ALLOWED(Loading, "didReceiveServerRedirectForProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
+    RELEASE_LOG_IF_ALLOWED(Loading, "didReceiveServerRedirectForProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, process.processIdentifier(), m_pageID, frameID);
 
     PageClientProtector protector(pageClient());
 
-    WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK_URL(request.url());
+    WebFrameProxy* frame = process.webFrame(frameID);
+    MESSAGE_CHECK(process, frame);
+    MESSAGE_CHECK_URL(process, request.url());
 
     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
     RefPtr<API::Navigation> navigation = navigationID ? navigationState().navigation(navigationID) : nullptr;
@@ -3854,9 +3835,9 @@ void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t f
 
     m_pageLoadState.commitChanges();
     if (m_loaderClient)
-        m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(*this, *frame, frame->isMainFrame() ? navigation.get() : nullptr, m_process->transformHandlesToObjects(userData.object()).get());
+        m_loaderClient->didReceiveServerRedirectForProvisionalLoadForFrame(*this, *frame, frame->isMainFrame() ? navigation.get() : nullptr, process.transformHandlesToObjects(userData.object()).get());
     else if (frame->isMainFrame())
-        m_navigationClient->didReceiveServerRedirectForProvisionalNavigation(*this, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
+        m_navigationClient->didReceiveServerRedirectForProvisionalNavigation(*this, navigation.get(), process.transformHandlesToObjects(userData.object()).get());
 }
 
 void WebPageProxy::willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay, WebCore::LockBackForwardList)
@@ -3866,7 +3847,7 @@ void WebPageProxy::willPerformClientRedirectForFrame(uint64_t frameID, const Str
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     if (frame->isMainFrame())
         m_navigationClient->willPerformClientRedirect(*this, url, delay);
@@ -3879,20 +3860,25 @@ void WebPageProxy::didCancelClientRedirectForFrame(uint64_t frameID)
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     if (frame->isMainFrame())
         m_navigationClient->didCancelClientRedirect(*this);
 }
 
-void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t, URL&& url)
+void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, URL&& url)
+{
+    didChangeProvisionalURLForFrameShared(m_process, frameID, navigationID, WTFMove(url));
+}
+
+void WebPageProxy::didChangeProvisionalURLForFrameShared(WebProcessProxy& process, uint64_t frameID, uint64_t, URL&& url)
 {
     PageClientProtector protector(pageClient());
 
-    WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK(frame->frameLoadState().state() == FrameLoadState::State::Provisional);
-    MESSAGE_CHECK_URL(url);
+    WebFrameProxy* frame = process.webFrame(frameID);
+    MESSAGE_CHECK(process, frame);
+    MESSAGE_CHECK(process, frame->frameLoadState().state() == FrameLoadState::State::Provisional);
+    MESSAGE_CHECK_URL(process, url);
 
     auto transaction = m_pageLoadState.transaction();
 
@@ -3906,16 +3892,26 @@ void WebPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t, U
 
 void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
 {
-    LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " in web process pid %i didFailProvisionalLoadForFrame to provisionalURL %s", m_pageID, m_process->processIdentifier(), provisionalURL.utf8().data());
-    RELEASE_LOG_IF_ALLOWED(Process, "didFailProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64 ", domain = %s, code = %d", m_process->processIdentifier(), m_pageID, frameID, error.domain().utf8().data(), error.errorCode());
+    if (m_provisionalPage && m_provisionalPage->navigationID() == navigationID) {
+        // The load did not fail, it is merely happening in a new provisional process.
+        return;
+    }
+
+    didFailProvisionalLoadForFrameShared(m_process, frameID, frameSecurityOrigin, navigationID, provisionalURL, error, userData);
+}
+
+void WebPageProxy::didFailProvisionalLoadForFrameShared(WebProcessProxy& process, uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const ResourceError& error, const UserData& userData)
+{
+    LOG(Loading, "(Loading) WebPageProxy %" PRIu64 " in web process pid %i didFailProvisionalLoadForFrame to provisionalURL %s", m_pageID, process.processIdentifier(), provisionalURL.utf8().data());
+    RELEASE_LOG_IF_ALLOWED(Process, "didFailProvisionalLoadForFrame: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64 ", domain = %s, code = %d", process.processIdentifier(), m_pageID, frameID, error.domain().utf8().data(), error.errorCode());
 
     PageClientProtector protector(pageClient());
 
-    WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    WebFrameProxy* frame = process.webFrame(frameID);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     if (m_controlledByAutomation) {
-        if (auto* automationSession = process().processPool().automationSession())
+        if (auto* automationSession = process.processPool().automationSession())
             automationSession->navigationOccurredForFrame(*frame);
     }
 
@@ -3940,15 +3936,19 @@ void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const Securi
     m_failingProvisionalLoadURL = provisionalURL;
 
     if (m_loaderClient)
-        m_loaderClient->didFailProvisionalLoadWithErrorForFrame(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
+        m_loaderClient->didFailProvisionalLoadWithErrorForFrame(*this, *frame, navigation.get(), error, process.transformHandlesToObjects(userData.object()).get());
     else if (frame->isMainFrame())
-        m_navigationClient->didFailProvisionalNavigationWithError(*this, *frame, navigation.get(), error, m_process->transformHandlesToObjects(userData.object()).get());
+        m_navigationClient->didFailProvisionalNavigationWithError(*this, *frame, navigation.get(), error, process.transformHandlesToObjects(userData.object()).get());
     else {
-            // FIXME: Get the main frame's current navigation.
-            m_navigationClient->didFailProvisionalLoadInSubframeWithError(*this, *frame, frameSecurityOrigin, nullptr, error, m_process->transformHandlesToObjects(userData.object()).get());
+        // FIXME: Get the main frame's current navigation.
+        m_navigationClient->didFailProvisionalLoadInSubframeWithError(*this, *frame, frameSecurityOrigin, nullptr, error, process.transformHandlesToObjects(userData.object()).get());
     }
 
     m_failingProvisionalLoadURL = { };
+
+    // If the provisional page's load fails then we destroy the provisional page.
+    if (m_provisionalPage && m_provisionalPage->mainFrame() == frame)
+        m_provisionalPage = nullptr;
 }
 
 void WebPageProxy::clearLoadDependentCallbacks()
@@ -3969,7 +3969,7 @@ void WebPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
     RefPtr<API::Navigation> navigation;
@@ -4063,7 +4063,7 @@ void WebPageProxy::didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navi
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     if (m_controlledByAutomation) {
         if (auto* automationSession = process().processPool().automationSession())
@@ -4087,7 +4087,7 @@ void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
     RefPtr<API::Navigation> navigation;
@@ -4132,7 +4132,7 @@ void WebPageProxy::didFailLoadForFrame(uint64_t frameID, uint64_t navigationID,
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
     RefPtr<API::Navigation> navigation;
@@ -4174,8 +4174,8 @@ void WebPageProxy::didSameDocumentNavigationForFrame(uint64_t frameID, uint64_t
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK_URL(url);
+    MESSAGE_CHECK(m_process.get(), frame);
+    MESSAGE_CHECK_URL(process(), url);
 
     // FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
     RefPtr<API::Navigation> navigation;
@@ -4227,7 +4227,7 @@ void WebPageProxy::didReceiveTitleForFrame(uint64_t frameID, const String& title
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     auto transaction = m_pageLoadState.transaction();
 
@@ -4253,7 +4253,7 @@ void WebPageProxy::didFirstVisuallyNonEmptyLayoutForFrame(uint64_t frameID, cons
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     if (m_loaderClient)
         m_loaderClient->didFirstVisuallyNonEmptyLayoutForFrame(*this, *frame, m_process->transformHandlesToObjects(userData.object()).get());
@@ -4284,7 +4284,7 @@ void WebPageProxy::didDisplayInsecureContentForFrame(uint64_t frameID, const Use
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     auto transaction = m_pageLoadState.transaction();
     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
@@ -4298,7 +4298,7 @@ void WebPageProxy::didRunInsecureContentForFrame(uint64_t frameID, const UserDat
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     auto transaction = m_pageLoadState.transaction();
     m_pageLoadState.didDisplayOrRunInsecureContent(transaction);
@@ -4321,7 +4321,7 @@ void WebPageProxy::frameDidBecomeFrameSet(uint64_t frameID, bool value)
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     frame->setIsFrameSet(value);
     if (frame->isMainFrame())
@@ -4337,15 +4337,20 @@ void WebPageProxy::beginSafeBrowsingCheck(const URL&, bool, WebFramePolicyListen
 
 void WebPageProxy::decidePolicyForNavigationActionAsync(uint64_t frameID, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, FrameInfoData&& frameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&& request, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, uint64_t listenerID)
 {
-    auto* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    decidePolicyForNavigationActionAsyncShared(m_process, frameID, WTFMove(frameSecurityOrigin), navigationID, WTFMove(navigationActionData), WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
+}
+
+void WebPageProxy::decidePolicyForNavigationActionAsyncShared(WebProcessProxy& process, uint64_t frameID, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, FrameInfoData&& frameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&& request, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, uint64_t listenerID)
+{
+    auto* frame = process.webFrame(frameID);
+    MESSAGE_CHECK(process, frame);
 
-    decidePolicyForNavigationAction(*frame, WTFMove(frameSecurityOrigin), navigationID, WTFMove(navigationActionData), WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, PolicyDecisionSender::create([this, protectedThis = makeRef(*this), frameID, listenerID] (auto... args) {
-        m_process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, args...), m_pageID);
+    decidePolicyForNavigationAction(process, *frame, WTFMove(frameSecurityOrigin), navigationID, WTFMove(navigationActionData), WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, PolicyDecisionSender::create([this, protectedThis = makeRef(*this), frameID, listenerID, process = makeRef(process)] (auto... args) {
+        process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, args...), m_pageID);
     }));
 }
 
-void WebPageProxy::decidePolicyForNavigationAction(WebFrameProxy& frame, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, FrameInfoData&& originatingFrameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&& request, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, Ref<PolicyDecisionSender>&& sender)
+void WebPageProxy::decidePolicyForNavigationAction(WebProcessProxy& process, WebFrameProxy& frame, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, FrameInfoData&& originatingFrameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&& request, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, Ref<PolicyDecisionSender>&& sender)
 {
     LOG(Loading, "WebPageProxy::decidePolicyForNavigationAction - Original URL %s, current target URL %s", originalRequest.url().string().utf8().data(), request.url().string().utf8().data());
 
@@ -4360,8 +4365,8 @@ void WebPageProxy::decidePolicyForNavigationAction(WebFrameProxy& frame, WebCore
     if (!fromAPI)
         m_pageLoadState.clearPendingAPIRequestURL(transaction);
 
-    MESSAGE_CHECK_URL(request.url());
-    MESSAGE_CHECK_URL(originalRequest.url());
+    MESSAGE_CHECK_URL(process, request.url());
+    MESSAGE_CHECK_URL(process, originalRequest.url());
 
     RefPtr<API::Navigation> navigation;
     if (navigationID)
@@ -4387,7 +4392,7 @@ void WebPageProxy::decidePolicyForNavigationAction(WebFrameProxy& frame, WebCore
     }
 
     uint64_t newNavigationID = navigation->navigationID();
-    navigation->setCurrentRequest(ResourceRequest(request), m_process->coreProcessIdentifier());
+    navigation->setCurrentRequest(ResourceRequest(request), process.coreProcessIdentifier());
     navigation->setLastNavigationAction(navigationActionData);
     navigation->setOriginatingFrameInfo(originatingFrameInfoData);
     navigation->setDestinationFrameSecurityOrigin(frameSecurityOrigin);
@@ -4446,7 +4451,7 @@ void WebPageProxy::decidePolicyForNavigationAction(WebFrameProxy& frame, WebCore
         beginSafeBrowsingCheck(request.url(), frame.isMainFrame(), listener);
 
     API::Navigation* mainFrameNavigation = frame.isMainFrame() ? navigation.get() : nullptr;
-    WebFrameProxy* originatingFrame = m_process->webFrame(originatingFrameInfoData.frameID);
+    WebFrameProxy* originatingFrame = process.webFrame(originatingFrameInfoData.frameID);
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     if (auto* resourceLoadStatisticsStore = websiteDataStore().resourceLoadStatistics())
@@ -4455,21 +4460,21 @@ void WebPageProxy::decidePolicyForNavigationAction(WebFrameProxy& frame, WebCore
 #endif
 
     if (m_policyClient)
-        m_policyClient->decidePolicyForNavigationAction(*this, &frame, WTFMove(navigationActionData), originatingFrame, originalRequest, WTFMove(request), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
+        m_policyClient->decidePolicyForNavigationAction(*this, &frame, WTFMove(navigationActionData), originatingFrame, originalRequest, WTFMove(request), WTFMove(listener), process.transformHandlesToObjects(userData.object()).get());
     else {
         auto destinationFrameInfo = API::FrameInfo::create(frame, frameSecurityOrigin.securityOrigin());
         RefPtr<API::FrameInfo> sourceFrameInfo;
         if (!fromAPI && originatingFrame == &frame)
             sourceFrameInfo = destinationFrameInfo.copyRef();
         else if (!fromAPI)
-            sourceFrameInfo = API::FrameInfo::create(originatingFrameInfoData, originatingPageID ? m_process->webPage(originatingPageID) : nullptr);
+            sourceFrameInfo = API::FrameInfo::create(originatingFrameInfoData, originatingPageID ? process.webPage(originatingPageID) : nullptr);
 
-        auto userInitiatedActivity = m_process->userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
+        auto userInitiatedActivity = process.userInitiatedActivity(navigationActionData.userGestureTokenIdentifier);
         bool shouldOpenAppLinks = !m_shouldSuppressAppLinksInNextNavigationPolicyDecision && destinationFrameInfo->isMainFrame() && !hostsAreEqual(URL({ }, m_mainFrame->url()), request.url()) && navigationActionData.navigationType != WebCore::NavigationType::BackForward;
 
         auto navigationAction = API::NavigationAction::create(WTFMove(navigationActionData), sourceFrameInfo.get(), destinationFrameInfo.ptr(), WTF::nullopt, WTFMove(request), originalRequest.url(), shouldOpenAppLinks, WTFMove(userInitiatedActivity), mainFrameNavigation);
 
-        m_navigationClient->decidePolicyForNavigationAction(*this, WTFMove(navigationAction), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
+        m_navigationClient->decidePolicyForNavigationAction(*this, WTFMove(navigationAction), WTFMove(listener), process.transformHandlesToObjects(userData.object()).get());
     }
 
     m_shouldSuppressAppLinksInNextNavigationPolicyDecision = false;
@@ -4523,7 +4528,7 @@ void WebPageProxy::decidePolicyForNavigationActionSync(uint64_t frameID, bool is
         RELEASE_ASSERT(frame);
     }
 
-    decidePolicyForNavigationAction(*frame, WTFMove(frameSecurityOrigin), navigationID, WTFMove(navigationActionData), WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, sender.copyRef());
+    decidePolicyForNavigationAction(m_process, *frame, WTFMove(frameSecurityOrigin), navigationID, WTFMove(navigationActionData), WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, sender.copyRef());
 
     // If the client did not respond synchronously, proceed with the load.
     sender->send(WebPolicyAction::Use, navigationID, DownloadID(), WTF::nullopt);
@@ -4534,8 +4539,8 @@ void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, const Securi
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK_URL(request.url());
+    MESSAGE_CHECK(m_process.get(), frame);
+    MESSAGE_CHECK_URL(process(), request.url());
 
     auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), listenerID, frameID] (WebPolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning) mutable {
         // FIXME: Assert the API::WebsitePolicies* is nullptr here once clients of WKFramePolicyListenerUseWithPolicies go away.
@@ -4565,30 +4570,35 @@ void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, const Securi
 
 void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, const UserData& userData)
 {
+    decidePolicyForResponseShared(m_process, frameID, frameSecurityOrigin, navigationID, response, request, canShowMIMEType, listenerID, userData);
+}
+
+void WebPageProxy::decidePolicyForResponseShared(WebProcessProxy& process, uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const ResourceResponse& response, const ResourceRequest& request, bool canShowMIMEType, uint64_t listenerID, const UserData& userData)
+{
     PageClientProtector protector(pageClient());
 
     m_decidePolicyForResponseRequest = request;
 
-    WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK_URL(request.url());
-    MESSAGE_CHECK_URL(response.url());
+    WebFrameProxy* frame = process.webFrame(frameID);
+    MESSAGE_CHECK(process, frame);
+    MESSAGE_CHECK_URL(process, request.url());
+    MESSAGE_CHECK_URL(process, response.url());
 
     RefPtr<API::Navigation> navigation = navigationID ? m_navigationState->navigation(navigationID) : nullptr;
-    auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frameID, listenerID, navigation = WTFMove(navigation)] (WebPolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning) mutable {
+    auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frameID, listenerID, navigation = WTFMove(navigation), process = makeRef(process)] (WebPolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning) mutable {
         // FIXME: Assert the API::WebsitePolicies* is nullptr here once clients of WKFramePolicyListenerUseWithPolicies go away.
         RELEASE_ASSERT(processSwapRequestedByClient == ProcessSwapRequestedByClient::No);
         ASSERT_UNUSED(safeBrowsingWarning, !safeBrowsingWarning);
-        receivedPolicyDecision(policyAction, navigation.get(), WTF::nullopt, PolicyDecisionSender::create([this, protectedThis = WTFMove(protectedThis), frameID, listenerID] (auto... args) {
-            m_process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, args...), m_pageID);
+        receivedPolicyDecision(policyAction, navigation.get(), WTF::nullopt, PolicyDecisionSender::create([this, protectedThis = WTFMove(protectedThis), frameID, listenerID, process = WTFMove(process)] (auto... args) {
+            process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, args...), m_pageID);
         }));
     }, ShouldExpectSafeBrowsingResult::No));
 
     if (m_policyClient)
-        m_policyClient->decidePolicyForResponse(*this, *frame, response, request, canShowMIMEType, WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
+        m_policyClient->decidePolicyForResponse(*this, *frame, response, request, canShowMIMEType, WTFMove(listener), process.transformHandlesToObjects(userData.object()).get());
     else {
         auto navigationResponse = API::NavigationResponse::create(API::FrameInfo::create(*frame, frameSecurityOrigin.securityOrigin()).get(), request, response, canShowMIMEType);
-        m_navigationClient->decidePolicyForNavigationResponse(*this, WTFMove(navigationResponse), WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
+        m_navigationClient->decidePolicyForNavigationResponse(*this, WTFMove(navigationResponse), WTFMove(listener), process.transformHandlesToObjects(userData.object()).get());
     }
 }
 
@@ -4597,7 +4607,7 @@ void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     if (!m_policyClient)
         return;
@@ -4609,10 +4619,10 @@ void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError
 void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, const UserData& userData)
 {
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     WebFrameProxy* sourceFrame = m_process->webFrame(sourceFrameID);
-    MESSAGE_CHECK(sourceFrame);
+    MESSAGE_CHECK(m_process.get(), sourceFrame);
 
     m_formClient->willSubmitForm(*this, *frame, *sourceFrame, textFieldValues, m_process->transformHandlesToObjects(userData.object()).get(), [this, protectedThis = makeRef(*this), frameID, listenerID]() {
         m_process->send(Messages::WebPage::ContinueWillSubmitForm(frameID, listenerID), m_pageID);
@@ -4626,39 +4636,49 @@ void WebPageProxy::contentRuleListNotification(URL&& url, Vector<String>&& ident
     
 void WebPageProxy::didNavigateWithNavigationData(const WebNavigationDataStore& store, uint64_t frameID) 
 {
-    RELEASE_LOG_IF_ALLOWED(Loading, "didNavigateWithNavigationData: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
+    didNavigateWithNavigationDataShared(m_process, store, frameID);
+}
+
+void WebPageProxy::didNavigateWithNavigationDataShared(WebProcessProxy& process, const WebNavigationDataStore& store, uint64_t frameID)
+{
+    RELEASE_LOG_IF_ALLOWED(Loading, "didNavigateWithNavigationDataShared: webPID = %i, pageID = %" PRIu64, process.processIdentifier(), m_pageID);
 
     PageClientProtector protector(pageClient());
 
-    WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK(frame->page() == this);
+    WebFrameProxy* frame = process.webFrame(frameID);
+    MESSAGE_CHECK(process, frame);
+    MESSAGE_CHECK(process, frame->page() == this);
 
     if (frame->isMainFrame())
         m_historyClient->didNavigateWithNavigationData(*this, store);
-    process().processPool().historyClient().didNavigateWithNavigationData(process().processPool(), *this, store, *frame);
+    process.processPool().historyClient().didNavigateWithNavigationData(process.processPool(), *this, store, *frame);
 }
 
 void WebPageProxy::didPerformClientRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
 {
-    RELEASE_LOG_IF_ALLOWED(Loading, "didPerformClientRedirect: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, m_process->processIdentifier(), m_pageID, frameID);
+    didPerformClientRedirectShared(m_process, sourceURLString, destinationURLString, frameID);
+}
+
+void WebPageProxy::didPerformClientRedirectShared(WebProcessProxy& process, const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
+{
+    RELEASE_LOG_IF_ALLOWED(Loading, "didPerformClientRedirectShared: webPID = %i, pageID = %" PRIu64 ", frameID = %" PRIu64, process.processIdentifier(), m_pageID, frameID);
 
     PageClientProtector protector(pageClient());
 
     if (sourceURLString.isEmpty() || destinationURLString.isEmpty())
         return;
     
-    WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK(frame->page() == this);
-    MESSAGE_CHECK_URL(sourceURLString);
-    MESSAGE_CHECK_URL(destinationURLString);
+    WebFrameProxy* frame = process.webFrame(frameID);
+    MESSAGE_CHECK(process, frame);
+    MESSAGE_CHECK(process, frame->page() == this);
+    MESSAGE_CHECK_URL(process, sourceURLString);
+    MESSAGE_CHECK_URL(process, destinationURLString);
 
     if (frame->isMainFrame()) {
         m_historyClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString);
         m_navigationClient->didPerformClientRedirect(*this, sourceURLString, destinationURLString);
     }
-    process().processPool().historyClient().didPerformClientRedirect(process().processPool(), *this, sourceURLString, destinationURLString, *frame);
+    process.processPool().historyClient().didPerformClientRedirect(process.processPool(), *this, sourceURLString, destinationURLString, *frame);
 }
 
 void WebPageProxy::didPerformServerRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
@@ -4671,11 +4691,11 @@ void WebPageProxy::didPerformServerRedirect(const String& sourceURLString, const
         return;
     
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK(frame->page() == this);
+    MESSAGE_CHECK(m_process.get(), frame);
+    MESSAGE_CHECK(m_process.get(), frame->page() == this);
 
-    MESSAGE_CHECK_URL(sourceURLString);
-    MESSAGE_CHECK_URL(destinationURLString);
+    MESSAGE_CHECK_URL(process(), sourceURLString);
+    MESSAGE_CHECK_URL(process(), destinationURLString);
 
     if (frame->isMainFrame())
         m_historyClient->didPerformServerRedirect(*this, sourceURLString, destinationURLString);
@@ -4687,10 +4707,10 @@ void WebPageProxy::didUpdateHistoryTitle(const String& title, const String& url,
     PageClientProtector protector(pageClient());
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
-    MESSAGE_CHECK(frame->page() == this);
+    MESSAGE_CHECK(m_process.get(), frame);
+    MESSAGE_CHECK(m_process.get(), frame->page() == this);
 
-    MESSAGE_CHECK_URL(url);
+    MESSAGE_CHECK_URL(process(), url);
 
     if (frame->isMainFrame())
         m_historyClient->didUpdateHistoryTitle(*this, title, url);
@@ -4701,7 +4721,7 @@ void WebPageProxy::didUpdateHistoryTitle(const String& title, const String& url,
 
 void WebPageProxy::createNewPage(const FrameInfoData& originatingFrameInfoData, uint64_t originatingPageID, ResourceRequest&& request, WindowFeatures&& windowFeatures, NavigationActionData&& navigationActionData, Messages::WebPageProxy::CreateNewPage::DelayedReply&& reply)
 {
-    MESSAGE_CHECK(m_process->webFrame(originatingFrameInfoData.frameID));
+    MESSAGE_CHECK(m_process.get(), m_process->webFrame(originatingFrameInfoData.frameID));
     auto originatingFrameInfo = API::FrameInfo::create(originatingFrameInfoData, m_process->webPage(originatingPageID));
 
     auto mainFrameURL = m_mainFrame->url();
@@ -4714,7 +4734,7 @@ void WebPageProxy::createNewPage(const FrameInfoData& originatingFrameInfoData,
 
         newPage->setOpenedByDOM();
 
-        reply(newPage->pageID(), newPage->creationParameters());
+        reply(newPage->pageID(), newPage->creationParameters(m_process));
 
         WebsiteDataStore::cloneSessionData(*this, *newPage);
         newPage->m_shouldSuppressAppLinksInNextNavigationPolicyDecision = hostsAreEqual(URL({ }, mainFrameURL), request.url());
@@ -4766,7 +4786,7 @@ void WebPageProxy::closePage(bool stopResponsivenessTimer)
 void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, Messages::WebPageProxy::RunJavaScriptAlert::DelayedReply&& reply)
 {
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
 #if PLATFORM(IOS_FAMILY)
     exitFullscreenImmediately();
@@ -4785,7 +4805,7 @@ void WebPageProxy::runJavaScriptAlert(uint64_t frameID, const SecurityOriginData
 void WebPageProxy::runJavaScriptConfirm(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, Messages::WebPageProxy::RunJavaScriptConfirm::DelayedReply&& reply)
 {
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
 #if PLATFORM(IOS_FAMILY)
     exitFullscreenImmediately();
@@ -4805,7 +4825,7 @@ void WebPageProxy::runJavaScriptConfirm(uint64_t frameID, const SecurityOriginDa
 void WebPageProxy::runJavaScriptPrompt(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, const String& defaultValue, Messages::WebPageProxy::RunJavaScriptPrompt::DelayedReply&& reply)
 {
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
 #if PLATFORM(IOS_FAMILY)
     exitFullscreenImmediately();
@@ -4856,10 +4876,10 @@ void WebPageProxy::processDidFinishLaunching()
 #if ENABLE(NETSCAPE_PLUGIN_API)
 void WebPageProxy::unavailablePluginButtonClicked(uint32_t opaquePluginUnavailabilityReason, const String& mimeType, const String& pluginURLString, const String& pluginspageAttributeURLString, const String& frameURLString, const String& pageURLString)
 {
-    MESSAGE_CHECK_URL(pluginURLString);
-    MESSAGE_CHECK_URL(pluginspageAttributeURLString);
-    MESSAGE_CHECK_URL(frameURLString);
-    MESSAGE_CHECK_URL(pageURLString);
+    MESSAGE_CHECK_URL(process(), pluginURLString);
+    MESSAGE_CHECK_URL(process(), pluginspageAttributeURLString);
+    MESSAGE_CHECK_URL(process(), frameURLString);
+    MESSAGE_CHECK_URL(process(), pageURLString);
 
     String newMimeType = mimeType;
     PluginModuleInfo plugin = m_process->processPool().pluginInfoStore().findPlugin(newMimeType, URL(URL(), pluginURLString));
@@ -4985,7 +5005,7 @@ void WebPageProxy::rootViewToAccessibilityScreen(const IntRect& viewRect, IntRec
 void WebPageProxy::runBeforeUnloadConfirmPanel(uint64_t frameID, const SecurityOriginData& securityOrigin, const String& message, Messages::WebPageProxy::RunBeforeUnloadConfirmPanel::DelayedReply&& reply)
 {
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     // Per ยง18 User Prompts in the WebDriver spec, "User prompts that are spawned from beforeunload
     // event handlers, are dismissed implicitly upon navigation or close window, regardless of the
@@ -5030,7 +5050,7 @@ void WebPageProxy::runOpenPanel(uint64_t frameID, const SecurityOriginData& fram
     }
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     Ref<API::OpenPanelParameters> parameters = API::OpenPanelParameters::create(settings);
     m_openPanelResultListener = WebOpenPanelResultListenerProxy::create(this);
@@ -5067,7 +5087,7 @@ void WebPageProxy::printFrame(uint64_t frameID)
     m_isPerformingDOMPrintOperation = true;
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     m_uiClient->printFrame(*this, *frame);
 
@@ -5356,13 +5376,18 @@ void WebPageProxy::backForwardAddItem(BackForwardListItemState&& itemState)
 
 void WebPageProxy::backForwardGoToItem(const BackForwardItemIdentifier& itemID, SandboxExtension::Handle& sandboxExtensionHandle)
 {
+    backForwardGoToItemShared(m_process, itemID, sandboxExtensionHandle);
+}
+
+void WebPageProxy::backForwardGoToItemShared(WebProcessProxy& process, const BackForwardItemIdentifier& itemID, SandboxExtension::Handle& sandboxExtensionHandle)
+{
     WebBackForwardListItem* item = m_backForwardList->itemForID(itemID);
     if (!item)
         return;
 
-    bool createdExtension = maybeInitializeSandboxExtensionHandle(URL(URL(), item->url()), sandboxExtensionHandle);
+    bool createdExtension = maybeInitializeSandboxExtensionHandle(process, URL(URL(), item->url()), sandboxExtensionHandle);
     if (createdExtension)
-        willAcquireUniversalFileReadSandboxExtension();
+        willAcquireUniversalFileReadSandboxExtension(process);
     m_backForwardList->goToItem(*item);
 }
 
@@ -5841,7 +5866,7 @@ void WebPageProxy::getGuessesForWord(const String& word, const String& context,
 
 void WebPageProxy::learnWord(const String& word)
 {
-    MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
+    MESSAGE_CHECK(m_process.get(), m_pendingLearnOrIgnoreWordMessageCount);
     --m_pendingLearnOrIgnoreWordMessageCount;
 
     TextChecker::learnWord(spellDocumentTag(), word);
@@ -5849,7 +5874,7 @@ void WebPageProxy::learnWord(const String& word)
 
 void WebPageProxy::ignoreWord(const String& word)
 {
-    MESSAGE_CHECK(m_pendingLearnOrIgnoreWordMessageCount);
+    MESSAGE_CHECK(m_process.get(), m_pendingLearnOrIgnoreWordMessageCount);
     --m_pendingLearnOrIgnoreWordMessageCount;
 
     TextChecker::ignoreWord(spellDocumentTag(), word);
@@ -5950,9 +5975,9 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
         LOG(MouseHandling, "WebPageProxy::didReceiveEvent: %s (queue size %zu)", webMouseEventTypeString(type), m_mouseEventQueue.size());
 
         // Retire the last sent event now that WebProcess is done handling it.
-        MESSAGE_CHECK(!m_mouseEventQueue.isEmpty());
+        MESSAGE_CHECK(m_process.get(), !m_mouseEventQueue.isEmpty());
         NativeWebMouseEvent event = m_mouseEventQueue.takeFirst();
-        MESSAGE_CHECK(type == event.type());
+        MESSAGE_CHECK(m_process.get(), type == event.type());
 
         if (!m_mouseEventQueue.isEmpty()) {
             LOG(MouseHandling, " UIProcess: handling a queued mouse event from didReceiveEvent");
@@ -5967,7 +5992,7 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
     }
 
     case WebEvent::Wheel: {
-        MESSAGE_CHECK(!m_currentlyProcessedWheelEvents.isEmpty());
+        MESSAGE_CHECK(m_process.get(), !m_currentlyProcessedWheelEvents.isEmpty());
 
         std::unique_ptr<Vector<NativeWebWheelEvent>> oldestCoalescedEvent = m_currentlyProcessedWheelEvents.takeFirst();
 
@@ -5988,10 +6013,10 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
     case WebEvent::Char: {
         LOG(KeyHandling, "WebPageProxy::didReceiveEvent: %s (queue empty %d)", webKeyboardEventTypeString(type), m_keyEventQueue.isEmpty());
 
-        MESSAGE_CHECK(!m_keyEventQueue.isEmpty());
+        MESSAGE_CHECK(m_process.get(), !m_keyEventQueue.isEmpty());
         NativeWebKeyboardEvent event = m_keyEventQueue.takeFirst();
 
-        MESSAGE_CHECK(type == event.type());
+        MESSAGE_CHECK(m_process.get(), type == event.type());
 
         bool canProcessMoreKeyEvents = !m_keyEventQueue.isEmpty();
         if (canProcessMoreKeyEvents) {
@@ -6018,10 +6043,10 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
     case WebEvent::GestureStart:
     case WebEvent::GestureChange:
     case WebEvent::GestureEnd: {
-        MESSAGE_CHECK(!m_gestureEventQueue.isEmpty());
+        MESSAGE_CHECK(m_process.get(), !m_gestureEventQueue.isEmpty());
         NativeWebGestureEvent event = m_gestureEventQueue.takeFirst();
 
-        MESSAGE_CHECK(type == event.type());
+        MESSAGE_CHECK(m_process.get(), type == event.type());
 
         if (!handled)
             pageClient().gestureEventWasNotHandledByWebCore(event);
@@ -6040,10 +6065,10 @@ void WebPageProxy::didReceiveEvent(uint32_t opaqueType, bool handled)
     case WebEvent::TouchMove:
     case WebEvent::TouchEnd:
     case WebEvent::TouchCancel: {
-        MESSAGE_CHECK(!m_touchEventQueue.isEmpty());
+        MESSAGE_CHECK(m_process.get(), !m_touchEventQueue.isEmpty());
         QueuedTouchEvents queuedEvents = m_touchEventQueue.takeFirst();
 
-        MESSAGE_CHECK(type == queuedEvents.forwardedEvent.type());
+        MESSAGE_CHECK(m_process.get(), type == queuedEvents.forwardedEvent.type());
 
         pageClient().doneWithTouchEvent(queuedEvents.forwardedEvent, handled);
         for (size_t i = 0; i < queuedEvents.deferredTouchEvents.size(); ++i) {
@@ -6171,7 +6196,7 @@ void WebPageProxy::unsignedCallback(uint64_t result, CallbackID callbackID)
 
 void WebPageProxy::editingRangeCallback(const EditingRange& range, CallbackID callbackID)
 {
-    MESSAGE_CHECK(range.isValid());
+    MESSAGE_CHECK(m_process.get(), range.isValid());
 
     auto callback = m_callbacks.take<EditingRangeCallback>(callbackID);
     if (!callback) {
@@ -6272,7 +6297,7 @@ void WebPageProxy::logScrollingEvent(uint32_t eventType, MonotonicTime timestamp
 
 void WebPageProxy::rectForCharacterRangeCallback(const IntRect& rect, const EditingRange& actualRange, CallbackID callbackID)
 {
-    MESSAGE_CHECK(actualRange.isValid());
+    MESSAGE_CHECK(m_process.get(), actualRange.isValid());
 
     auto callback = m_callbacks.take<RectForCharacterRangeCallback>(callbackID);
     if (!callback) {
@@ -6305,7 +6330,7 @@ void WebPageProxy::focusedFrameChanged(uint64_t frameID)
     }
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     m_focusedFrame = frame;
 }
@@ -6318,7 +6343,7 @@ void WebPageProxy::frameSetLargestFrameChanged(uint64_t frameID)
     }
 
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     m_frameSetLargestFrame = frame;
 }
@@ -6403,6 +6428,13 @@ void WebPageProxy::processDidTerminate(ProcessTerminationReason reason)
     stopAllURLSchemeTasks();
 }
 
+void WebPageProxy::provisionalProcessDidTerminate()
+{
+    ASSERT(m_provisionalPage);
+    m_provisionalPage->cancel();
+    m_provisionalPage = nullptr;
+}
+
 static bool shouldReloadAfterProcessTermination(ProcessTerminationReason reason)
 {
     switch (reason) {
@@ -6490,8 +6522,6 @@ void WebPageProxy::processWillBecomeForeground()
 void WebPageProxy::resetState(ResetStateReason resetStateReason)
 {
     m_mainFrame = nullptr;
-    m_mainFrameCreationHandler = nullptr;
-    m_mainFrameWindowCreationHandler = nullptr;
 
 #if PLATFORM(COCOA)
     m_scrollingPerformanceData = nullptr;
@@ -6680,7 +6710,7 @@ void WebPageProxy::resetStateAfterProcessExited(ProcessTerminationReason termina
     m_process->processTerminated();
 }
 
-WebPageCreationParameters WebPageProxy::creationParameters()
+WebPageCreationParameters WebPageProxy::creationParameters(WebProcessProxy& process)
 {
     WebPageCreationParameters parameters;
 
@@ -6782,9 +6812,13 @@ WebPageCreationParameters WebPageProxy::creationParameters()
     parameters.applicationManifest = m_configuration->applicationManifest() ? Optional<WebCore::ApplicationManifest>(m_configuration->applicationManifest()->applicationManifest()) : WTF::nullopt;
 #endif
 
+#if ENABLE(SERVICE_WORKER)
+    parameters.hasRegisteredServiceWorkers = process.processPool().mayHaveRegisteredServiceWorkers(m_websiteDataStore);
+#endif
+
     parameters.needsFontAttributes = m_needsFontAttributes;
 
-    m_process->addWebUserContentControllerProxy(m_userContentController, parameters);
+    process.addWebUserContentControllerProxy(m_userContentController, parameters);
 
     return parameters;
 }
@@ -6855,7 +6889,7 @@ void WebPageProxy::exceededDatabaseQuota(uint64_t frameID, const String& originI
     ExceededDatabaseQuotaRecords::Record* record = records.next();
     while (record) {
         WebFrameProxy* frame = m_process->webFrame(record->frameID);
-        MESSAGE_CHECK(frame);
+        MESSAGE_CHECK(m_process.get(), frame);
 
         auto origin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(record->originIdentifier)->securityOrigin());
         m_uiClient->exceededDatabaseQuota(this, frame, origin.ptr(), record->databaseName, record->displayName, record->currentQuota, record->currentOriginUsage, record->currentDatabaseUsage, record->expectedUsage, WTFMove(record->reply));
@@ -6872,7 +6906,7 @@ void WebPageProxy::reachedApplicationCacheOriginQuota(const String& originIdenti
 void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID, uint64_t frameID, String originIdentifier)
 {
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     // FIXME: Geolocation should probably be using toString() as its string representation instead of databaseIdentifier().
     auto origin = API::SecurityOrigin::create(SecurityOriginData::fromDatabaseIdentifier(originIdentifier)->securityOrigin());
@@ -6911,7 +6945,7 @@ UserMediaPermissionRequestManagerProxy& WebPageProxy::userMediaPermissionRequest
 void WebPageProxy::requestUserMediaPermissionForFrame(uint64_t userMediaID, uint64_t frameID, const WebCore::SecurityOriginData&  userMediaDocumentOriginData, const WebCore::SecurityOriginData& topLevelDocumentOriginData, const WebCore::MediaStreamRequest& request)
 {
 #if ENABLE(MEDIA_STREAM)
-    MESSAGE_CHECK(m_process->webFrame(frameID));
+    MESSAGE_CHECK(m_process.get(), m_process->webFrame(frameID));
 
     userMediaPermissionRequestManager().requestUserMediaPermissionForFrame(userMediaID, frameID, userMediaDocumentOriginData.securityOrigin(), topLevelDocumentOriginData.securityOrigin(), request);
 #else
@@ -6927,7 +6961,7 @@ void WebPageProxy::enumerateMediaDevicesForFrame(uint64_t userMediaID, uint64_t
 {
 #if ENABLE(MEDIA_STREAM)
     WebFrameProxy* frame = m_process->webFrame(frameID);
-    MESSAGE_CHECK(frame);
+    MESSAGE_CHECK(m_process.get(), frame);
 
     userMediaPermissionRequestManager().enumerateMediaDevicesForFrame(userMediaID, frameID, userMediaDocumentOriginData.securityOrigin(), topLevelDocumentOriginData.securityOrigin());
 #else
@@ -8144,16 +8178,21 @@ WebURLSchemeHandler* WebPageProxy::urlSchemeHandlerForScheme(const String& schem
 
 void WebPageProxy::startURLSchemeTask(URLSchemeTaskParameters&& parameters)
 {
+    startURLSchemeTaskShared(m_process, WTFMove(parameters));
+}
+
+void WebPageProxy::startURLSchemeTaskShared(WebProcessProxy& process, URLSchemeTaskParameters&& parameters)
+{
     auto iterator = m_urlSchemeHandlersByIdentifier.find(parameters.handlerIdentifier);
-    MESSAGE_CHECK(iterator != m_urlSchemeHandlersByIdentifier.end());
+    MESSAGE_CHECK(m_process.get(), iterator != m_urlSchemeHandlersByIdentifier.end());
 
-    iterator->value->startTask(*this, parameters.taskIdentifier, WTFMove(parameters.request), nullptr);
+    iterator->value->startTask(*this, process, parameters.taskIdentifier, WTFMove(parameters.request), nullptr);
 }
 
 void WebPageProxy::stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier)
 {
     auto iterator = m_urlSchemeHandlersByIdentifier.find(handlerIdentifier);
-    MESSAGE_CHECK(iterator != m_urlSchemeHandlersByIdentifier.end());
+    MESSAGE_CHECK(m_process.get(), iterator != m_urlSchemeHandlersByIdentifier.end());
 
     iterator->value->stopTask(*this, taskIdentifier);
 }
@@ -8161,9 +8200,9 @@ void WebPageProxy::stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskId
 void WebPageProxy::loadSynchronousURLSchemeTask(URLSchemeTaskParameters&& parameters, Messages::WebPageProxy::LoadSynchronousURLSchemeTask::DelayedReply&& reply)
 {
     auto iterator = m_urlSchemeHandlersByIdentifier.find(parameters.handlerIdentifier);
-    MESSAGE_CHECK(iterator != m_urlSchemeHandlersByIdentifier.end());
+    MESSAGE_CHECK(m_process.get(), iterator != m_urlSchemeHandlersByIdentifier.end());
 
-    iterator->value->startTask(*this, parameters.taskIdentifier, WTFMove(parameters.request), WTFMove(reply));
+    iterator->value->startTask(*this, m_process, parameters.taskIdentifier, WTFMove(parameters.request), WTFMove(reply));
 }
 
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
@@ -8502,12 +8541,12 @@ void WebPageProxy::updateCurrentModifierState()
 #endif
 }
 
-bool WebPageProxy::checkURLReceivedFromCurrentOrPreviousWebProcess(const String& urlString)
+bool WebPageProxy::checkURLReceivedFromCurrentOrPreviousWebProcess(WebProcessProxy& process, const String& urlString)
 {
-    return checkURLReceivedFromCurrentOrPreviousWebProcess(URL(URL(), urlString));
+    return checkURLReceivedFromCurrentOrPreviousWebProcess(process, URL(URL(), urlString));
 }
 
-bool WebPageProxy::checkURLReceivedFromCurrentOrPreviousWebProcess(const URL& url)
+bool WebPageProxy::checkURLReceivedFromCurrentOrPreviousWebProcess(WebProcessProxy& process, const URL& url)
 {
     if (!url.isLocalFile())
         return true;
@@ -8524,7 +8563,7 @@ bool WebPageProxy::checkURLReceivedFromCurrentOrPreviousWebProcess(const URL& ur
     if (std::find_if(m_previouslyVisitedPaths.begin(), localPathsEnd, startsWithURLPath) != localPathsEnd)
         return true;
 
-    return m_process->checkURLReceivedFromWebProcess(url);
+    return process.checkURLReceivedFromWebProcess(url);
 }
 
 void WebPageProxy::addPreviouslyVisitedPath(const String& path)
@@ -8532,10 +8571,10 @@ void WebPageProxy::addPreviouslyVisitedPath(const String& path)
     m_previouslyVisitedPaths.add(path);
 }
 
-void WebPageProxy::willAcquireUniversalFileReadSandboxExtension()
+void WebPageProxy::willAcquireUniversalFileReadSandboxExtension(WebProcessProxy& process)
 {
     m_mayHaveUniversalFileReadSandboxExtension = true;
-    process().willAcquireUniversalFileReadSandboxExtension();
+    process.willAcquireUniversalFileReadSandboxExtension();
 }
 
 void WebPageProxy::simulateDeviceOrientationChange(double alpha, double beta, double gamma)
index de98694..d1d8904 100644 (file)
@@ -225,6 +225,7 @@ class NativeWebKeyboardEvent;
 class NativeWebMouseEvent;
 class NativeWebWheelEvent;
 class PageClient;
+class ProvisionalPageProxy;
 class RemoteLayerTreeHost;
 class RemoteLayerTreeScrollingPerformanceData;
 class RemoteLayerTreeTransaction;
@@ -357,6 +358,7 @@ public:
     WebFrameProxy* frameSetLargestFrame() const { return m_frameSetLargestFrame.get(); }
 
     DrawingAreaProxy* drawingArea() const { return m_drawingArea.get(); }
+    DrawingAreaProxy* provisionalDrawingArea() const;
 
     WebNavigationState& navigationState() { return *m_navigationState.get(); }
 
@@ -379,6 +381,7 @@ public:
 
     bool addsVisitedLinks() const { return m_addsVisitedLinks; }
     void setAddsVisitedLinks(bool addsVisitedLinks) { m_addsVisitedLinks = addsVisitedLinks; }
+    VisitedLinkStore& visitedLinkStore() { return m_visitedLinkStore; }
 
     void exitFullscreenImmediately();
     void fullscreenMayReturnToInline();
@@ -458,8 +461,8 @@ public:
     API::IconLoadingClient& iconLoadingClient() { return *m_iconLoadingClient; }
     void setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&&);
 
-    enum class IsSwapFromSuspended { No, Yes };
-    void initializeWebPage(IsSwapFromSuspended = IsSwapFromSuspended::No);
+    void initializeWebPage();
+    void setDrawingArea(std::unique_ptr<DrawingAreaProxy>&&);
 
     WeakPtr<SecKeyProxyStore> secKeyProxyStore(const WebCore::AuthenticationChallenge&);
         
@@ -997,6 +1000,7 @@ public:
     void processDidBecomeUnresponsive();
     void processDidBecomeResponsive();
     void processDidTerminate(ProcessTerminationReason);
+    void provisionalProcessDidTerminate();
     void dispatchProcessDidTerminate(ProcessTerminationReason);
     void willChangeProcessIsResponsive();
     void didChangeProcessIsResponsive();
@@ -1058,7 +1062,7 @@ public:
     void didChooseFilesForOpenPanel(const Vector<String>&);
     void didCancelForOpenPanel();
 
-    WebPageCreationParameters creationParameters();
+    WebPageCreationParameters creationParameters(WebProcessProxy&);
 
     void handleDownloadRequest(DownloadProxy*);
 
@@ -1415,6 +1419,28 @@ public:
     EditableImageController& editableImageController() { return *m_editableImageController; }
 #endif
 
+    ProvisionalPageProxy* provisionalPageProxy() const { return m_provisionalPage.get(); }
+    void commitProvisionalPage(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo&, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData&);
+
+    // Logic shared between the WebPageProxy and the ProvisionalPageProxy.
+    void didStartProvisionalLoadForFrameShared(WebProcessProxy&, uint64_t frameID, uint64_t navigationID, URL&&, URL&& unreachableURL, const UserData&);
+    void didFailProvisionalLoadForFrameShared(WebProcessProxy&, uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&);
+    void didReceiveServerRedirectForProvisionalLoadForFrameShared(WebProcessProxy&, uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest&&, const UserData&);
+    void didPerformClientRedirectShared(WebProcessProxy&, const String& sourceURLString, const String& destinationURLString, uint64_t frameID);
+    void didNavigateWithNavigationDataShared(WebProcessProxy&, const WebNavigationDataStore&, uint64_t frameID);
+    void didChangeProvisionalURLForFrameShared(WebProcessProxy&, uint64_t frameID, uint64_t navigationID, URL&&);
+    void decidePolicyForNavigationActionAsyncShared(WebProcessProxy&, uint64_t frameID, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&&, FrameInfoData&&, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData&, uint64_t listenerID);
+    void decidePolicyForResponseShared(WebProcessProxy&, uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const WebCore::ResourceResponse&, const WebCore::ResourceRequest&, bool canShowMIMEType, uint64_t listenerID, const UserData&);
+    void startURLSchemeTaskShared(WebProcessProxy&, URLSchemeTaskParameters&&);
+    void loadDataWithNavigationShared(WebProcessProxy&, API::Navigation&, const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& = WTF::nullopt);
+    void loadRequestWithNavigationShared(WebProcessProxy&, API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& = WTF::nullopt);
+    void backForwardGoToItemShared(WebProcessProxy&, const WebCore::BackForwardItemIdentifier&, SandboxExtension::Handle&);
+
+    // IPC::MessageReceiver
+    // Implemented in generated WebPageProxyMessageReceiver.cpp
+    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
+    void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&) override;
+
 private:
     WebPageProxy(PageClient&, WebProcessProxy&, uint64_t pageID, Ref<API::PageConfiguration>&&);
     void platformInitialize();
@@ -1439,12 +1465,6 @@ private:
 
     void setUserAgent(String&&);
 
-    // IPC::MessageReceiver
-    // Implemented in generated WebPageProxyMessageReceiver.cpp
-    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
-    void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&) override;
-
-
     // IPC::MessageSender
     bool sendMessage(std::unique_ptr<IPC::Encoder>, OptionSet<IPC::SendOption>) override;
     IPC::Connection* messageSenderConnection() override;
@@ -1496,7 +1516,7 @@ private:
 
     void didDestroyNavigation(uint64_t navigationID);
 
-    void decidePolicyForNavigationAction(WebFrameProxy&, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&&, FrameInfoData&&, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData&, Ref<PolicyDecisionSender>&&);
+    void decidePolicyForNavigationAction(WebProcessProxy&, WebFrameProxy&, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&&, FrameInfoData&&, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData&, Ref<PolicyDecisionSender>&&);
     void decidePolicyForNavigationActionAsync(uint64_t frameID, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&&, FrameInfoData&&, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData&, uint64_t listenerID);
     void decidePolicyForNavigationActionSync(uint64_t frameID, bool isMainFrame, WebCore::SecurityOriginData&& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&&, FrameInfoData&&, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, WebCore::ResourceRequest&&, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData&, Messages::WebPageProxy::DecidePolicyForNavigationActionSync::DelayedReply&&);
     void decidePolicyForNewWindowAction(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, NavigationActionData&&, WebCore::ResourceRequest&&, const String& frameName, uint64_t listenerID, const UserData&);
@@ -1575,18 +1595,16 @@ private:
     void setCanShortCircuitHorizontalWheelEvents(bool canShortCircuitHorizontalWheelEvents) { m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents; }
 
     void reattachToWebProcess();
-    void swapToWebProcess(Ref<WebProcessProxy>&&, std::unique_ptr<SuspendedPageProxy>&&, IsSwapFromSuspended);
+    void swapToWebProcess(Ref<WebProcessProxy>&&, std::unique_ptr<DrawingAreaProxy>&&, RefPtr<WebFrameProxy>&& mainFrame);
     void didFailToSuspendAfterProcessSwap();
     void didSuspendAfterProcessSwap();
 
-    void finishAttachingToWebProcess(IsSwapFromSuspended = IsSwapFromSuspended::No);
+    enum class ShouldInitializeWebPage { No, Yes };
+    void finishAttachingToWebProcess(ShouldInitializeWebPage = ShouldInitializeWebPage::Yes);
 
     RefPtr<API::Navigation> reattachToWebProcessForReload();
     RefPtr<API::Navigation> reattachToWebProcessWithItem(WebBackForwardListItem&);
 
-    void loadDataWithNavigation(API::Navigation&, const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& = WTF::nullopt);
-    void loadRequestWithNavigation(API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& = WTF::nullopt);
-
     void requestNotificationPermission(uint64_t notificationID, const String& originString);
     void showNotification(const String& title, const String& body, const String& iconURL, const String& tag, const String& lang, WebCore::NotificationDirection, const String& originString, uint64_t notificationID);
     void cancelNotification(uint64_t notificationID);
@@ -1745,7 +1763,7 @@ private:
     void setPluginComplexTextInputState(uint64_t pluginComplexTextInputIdentifier, uint64_t complexTextInputState);
 #endif
 
-    bool maybeInitializeSandboxExtensionHandle(const URL&, SandboxExtension::Handle&);
+    bool maybeInitializeSandboxExtensionHandle(WebProcessProxy&, const URL&, SandboxExtension::Handle&);
 
 #if USE(AUTOMATIC_TEXT_REPLACEMENT)
     void toggleSmartInsertDelete();
@@ -1864,9 +1882,9 @@ private:
     void stopURLSchemeTask(uint64_t handlerIdentifier, uint64_t taskIdentifier);
     void loadSynchronousURLSchemeTask(URLSchemeTaskParameters&&, Messages::WebPageProxy::LoadSynchronousURLSchemeTask::DelayedReply&&);
 
-    bool checkURLReceivedFromCurrentOrPreviousWebProcess(const String&);
-    bool checkURLReceivedFromCurrentOrPreviousWebProcess(const URL&);
-    void willAcquireUniversalFileReadSandboxExtension();
+    bool checkURLReceivedFromCurrentOrPreviousWebProcess(WebProcessProxy&, const String&);
+    bool checkURLReceivedFromCurrentOrPreviousWebProcess(WebProcessProxy&, const URL&);
+    void willAcquireUniversalFileReadSandboxExtension(WebProcessProxy&);
 
     void handleAutoFillButtonClick(const UserData&);
 
@@ -1952,8 +1970,6 @@ private:
     Ref<WebsiteDataStore> m_websiteDataStore;
 
     RefPtr<WebFrameProxy> m_mainFrame;
-    Function<void()> m_mainFrameCreationHandler;
-    Function<void(const WebCore::GlobalWindowIdentifier&)> m_mainFrameWindowCreationHandler;
 
     RefPtr<WebFrameProxy> m_focusedFrame;
     RefPtr<WebFrameProxy> m_frameSetLargestFrame;
@@ -2324,6 +2340,8 @@ private:
     bool m_needsFontAttributes { false };
     bool m_mayHaveUniversalFileReadSandboxExtension { false };
 
+    std::unique_ptr<ProvisionalPageProxy> m_provisionalPage;
+
 #if HAVE(PENCILKIT)
     std::unique_ptr<EditableImageController> m_editableImageController;
 #endif
index db1fd58..6be9dc3 100644 (file)
@@ -34,6 +34,7 @@
 #include "Logging.h"
 #include "PluginInfoStore.h"
 #include "PluginProcessManager.h"
+#include "ProvisionalPageProxy.h"
 #include "TextChecker.h"
 #include "TextCheckerState.h"
 #include "UIMessagePortChannelProvider.h"
@@ -584,6 +585,15 @@ bool WebProcessProxy::fullKeyboardAccessEnabled()
 }
 #endif
 
+bool WebProcessProxy::hasProvisionalPageWithID(uint64_t pageID) const
+{
+    for (auto* provisionalPage : m_provisionalPages) {
+        if (provisionalPage->page().pageID() == pageID)
+            return true;
+    }
+    return false;
+}
+
 void WebProcessProxy::updateBackForwardItem(const BackForwardListItemState& itemState)
 {
     if (auto* item = WebBackForwardListItem::itemForID(itemState.identifier)) {
@@ -591,7 +601,7 @@ void WebProcessProxy::updateBackForwardItem(const BackForwardListItemState& item
         // the back/forward items page.
         // e.g. The old web process is navigating to about:blank for suspension.
         // We ignore these updates.
-        if (m_pageMap.contains(item->pageID()))
+        if (m_pageMap.contains(item->pageID()) || hasProvisionalPageWithID(item->pageID()))
             item->setPageState(itemState.pageState);
     }
 }
@@ -694,6 +704,7 @@ void WebProcessProxy::processDidTerminateOrFailedToLaunch()
         webConnection->didClose();
 
     auto pages = copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values());
+    auto provisionalPages = WTF::map(m_provisionalPages, [](auto* provisionalPage) { return makeWeakPtr(provisionalPage); });
 
     shutDown();
 
@@ -708,6 +719,11 @@ void WebProcessProxy::processDidTerminateOrFailedToLaunch()
 
     for (auto& page : pages)
         page->processDidTerminate(ProcessTerminationReason::Crash);
+
+    for (auto& provisionalPage : provisionalPages) {
+        if (provisionalPage)
+            provisionalPage->processDidTerminate();
+    }
 }
 
 void WebProcessProxy::didReceiveInvalidMessage(IPC::Connection& connection, IPC::StringReference messageReceiverName, IPC::StringReference messageName)
@@ -780,6 +796,12 @@ void WebProcessProxy::didFinishLaunching(ProcessLauncher* launcher, IPC::Connect
         page->processDidFinishLaunching();
     }
 
+    for (auto* provisionalPage : m_provisionalPages) {
+        ASSERT(this == &provisionalPage->process());
+        provisionalPage->processDidFinishLaunching();
+    }
+
+
     RELEASE_ASSERT(!m_webConnection);
     m_webConnection = WebConnectionToWebProcess::create(this);
 
@@ -873,7 +895,7 @@ void WebProcessProxy::maybeShutDown()
 
 bool WebProcessProxy::canTerminateChildProcess()
 {
-    if (!m_pageMap.isEmpty() || m_processPool->hasSuspendedPageFor(*this))
+    if (!m_pageMap.isEmpty() || m_processPool->hasSuspendedPageFor(*this) || !m_provisionalPages.isEmpty())
         return false;
 
     if (!m_processPool->shouldTerminate(this))
index 75f65a7..5042630 100644 (file)
@@ -70,6 +70,7 @@ namespace WebKit {
 class NetworkProcessProxy;
 class ObjCObjectGraph;
 class PageClient;
+class ProvisionalPageProxy;
 class UserMediaCaptureManagerProxy;
 class VisitedLinkStore;
 class WebBackForwardListItem;
@@ -124,6 +125,9 @@ public:
     enum class EndsUsingDataStore : bool { No, Yes };
     void removeWebPage(WebPageProxy&, uint64_t pageID, EndsUsingDataStore);
 
+    void addProvisionalPageProxy(ProvisionalPageProxy& provisionalPage) { ASSERT(!m_provisionalPages.contains(&provisionalPage)); m_provisionalPages.add(&provisionalPage); }
+    void removeProvisionalPageProxy(ProvisionalPageProxy& provisionalPage) { ASSERT(m_provisionalPages.contains(&provisionalPage)); m_provisionalPages.remove(&provisionalPage); }
+
     typename WebPageProxyMap::ValuesConstIteratorRange pages() const { return m_pageMap.values(); }
     unsigned pageCount() const { return m_pageMap.size(); }
     unsigned visiblePageCount() const { return m_visiblePageCounter.value(); }
@@ -330,6 +334,8 @@ private:
 
     void logDiagnosticMessageForResourceLimitTermination(const String& limitKey);
 
+    bool hasProvisionalPageWithID(uint64_t pageID) const;
+
     enum class IsWeak { No, Yes };
     template<typename T> class WeakOrStrongPtr {
     public:
@@ -373,6 +379,7 @@ private:
 
     WebPageProxyMap m_pageMap;
     WebFrameProxyMap m_frameMap;
+    HashSet<ProvisionalPageProxy*> m_provisionalPages;
     UserInitiatedActionMap m_userInitiatedActionMap;
 
     HashSet<VisitedLinkStore*> m_visitedLinkStores;
index a09edd9..5ba7fce 100644 (file)
@@ -48,9 +48,9 @@ WebURLSchemeHandler::~WebURLSchemeHandler()
     ASSERT(m_tasks.isEmpty());
 }
 
-void WebURLSchemeHandler::startTask(WebPageProxy& page, uint64_t taskIdentifier, ResourceRequest&& request, SyncLoadCompletionHandler&& completionHandler)
+void WebURLSchemeHandler::startTask(WebPageProxy& page, WebProcessProxy& process, uint64_t taskIdentifier, ResourceRequest&& request, SyncLoadCompletionHandler&& completionHandler)
 {
-    auto result = m_tasks.add(taskIdentifier, WebURLSchemeTask::create(*this, page, taskIdentifier, WTFMove(request), WTFMove(completionHandler)));
+    auto result = m_tasks.add(taskIdentifier, WebURLSchemeTask::create(*this, page, process, taskIdentifier, WTFMove(request), WTFMove(completionHandler)));
     ASSERT(result.isNewEntry);
 
     auto pageEntry = m_tasksByPageIdentifier.add(page.pageID(), HashSet<uint64_t>());
index b784a53..ac812f2 100644 (file)
@@ -42,6 +42,7 @@ class ResourceRequest;
 namespace WebKit {
 
 class WebPageProxy;
+class WebProcessProxy;
 
 using SyncLoadCompletionHandler = CompletionHandler<void(const WebCore::ResourceResponse&, const WebCore::ResourceError&, const IPC::DataReference&)>;
 
@@ -52,7 +53,7 @@ public:
 
     uint64_t identifier() const { return m_identifier; }
 
-    void startTask(WebPageProxy&, uint64_t taskIdentifier, WebCore::ResourceRequest&&, SyncLoadCompletionHandler&&);
+    void startTask(WebPageProxy&, WebProcessProxy&, uint64_t taskIdentifier, WebCore::ResourceRequest&&, SyncLoadCompletionHandler&&);
     void stopTask(WebPageProxy&, uint64_t taskIdentifier);
     void stopAllTasksForPage(WebPageProxy&);
     void taskCompleted(WebURLSchemeTask&);
index e1cde8d..19a6bb8 100644 (file)
 namespace WebKit {
 using namespace WebCore;
 
-Ref<WebURLSchemeTask> WebURLSchemeTask::create(WebURLSchemeHandler& handler, WebPageProxy& page, uint64_t resourceIdentifier, ResourceRequest&& request, SyncLoadCompletionHandler&& syncCompletionHandler)
+Ref<WebURLSchemeTask> WebURLSchemeTask::create(WebURLSchemeHandler& handler, WebPageProxy& page, WebProcessProxy& process, uint64_t resourceIdentifier, ResourceRequest&& request, SyncLoadCompletionHandler&& syncCompletionHandler)
 {
-    return adoptRef(*new WebURLSchemeTask(handler, page, resourceIdentifier, WTFMove(request), WTFMove(syncCompletionHandler)));
+    return adoptRef(*new WebURLSchemeTask(handler, page, process, resourceIdentifier, WTFMove(request), WTFMove(syncCompletionHandler)));
 }
 
-WebURLSchemeTask::WebURLSchemeTask(WebURLSchemeHandler& handler, WebPageProxy& page, uint64_t resourceIdentifier, ResourceRequest&& request, SyncLoadCompletionHandler&& syncCompletionHandler)
+WebURLSchemeTask::WebURLSchemeTask(WebURLSchemeHandler& handler, WebPageProxy& page, WebProcessProxy& process, uint64_t resourceIdentifier, ResourceRequest&& request, SyncLoadCompletionHandler&& syncCompletionHandler)
     : m_urlSchemeHandler(handler)
     , m_page(&page)
+    , m_process(makeRef(process))
     , m_identifier(resourceIdentifier)
     , m_pageIdentifier(page.pageID())
     , m_request(WTFMove(request))
@@ -69,7 +70,7 @@ auto WebURLSchemeTask::didPerformRedirection(WebCore::ResourceResponse&& respons
         m_syncResponse = response;
 
     m_request = request;
-    m_page->send(Messages::WebPage::URLSchemeTaskDidPerformRedirection(m_urlSchemeHandler->identifier(), m_identifier, response, request));
+    m_process->send(Messages::WebPage::URLSchemeTaskDidPerformRedirection(m_urlSchemeHandler->identifier(), m_identifier, response, request), m_page->pageID());
 
     return ExceptionType::None;
 }
@@ -92,7 +93,7 @@ auto WebURLSchemeTask::didReceiveResponse(const ResourceResponse& response) -> E
     if (isSync())
         m_syncResponse = response;
 
-    m_page->send(Messages::WebPage::URLSchemeTaskDidReceiveResponse(m_urlSchemeHandler->identifier(), m_identifier, response));
+    m_process->send(Messages::WebPage::URLSchemeTaskDidReceiveResponse(m_urlSchemeHandler->identifier(), m_identifier, response), m_page->pageID());
     return ExceptionType::None;
 }
 
@@ -117,7 +118,7 @@ auto WebURLSchemeTask::didReceiveData(Ref<SharedBuffer>&& buffer) -> ExceptionTy
         return ExceptionType::None;
     }
 
-    m_page->send(Messages::WebPage::URLSchemeTaskDidReceiveData(m_urlSchemeHandler->identifier(), m_identifier, { buffer }));
+    m_process->send(Messages::WebPage::URLSchemeTaskDidReceiveData(m_urlSchemeHandler->identifier(), m_identifier, { buffer }), m_page->pageID());
     return ExceptionType::None;
 }
 
@@ -142,7 +143,7 @@ auto WebURLSchemeTask::didComplete(const ResourceError& error) -> ExceptionType
         m_syncData = nullptr;
     }
 
-    m_page->send(Messages::WebPage::URLSchemeTaskDidComplete(m_urlSchemeHandler->identifier(), m_identifier, error));
+    m_process->send(Messages::WebPage::URLSchemeTaskDidComplete(m_urlSchemeHandler->identifier(), m_identifier, error), m_page->pageID());
     m_urlSchemeHandler->taskCompleted(*this);
 
     return ExceptionType::None;
@@ -152,6 +153,7 @@ void WebURLSchemeTask::pageDestroyed()
 {
     ASSERT(m_page);
     m_page = nullptr;
+    m_process = nullptr;
     m_stopped = true;
     
     if (isSync())
index 415f7f3..d48a408 100644 (file)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "WebProcessProxy.h"
 #include <WebCore/ResourceRequest.h>
 #include <WebCore/ResourceResponse.h>
 #include <WebCore/SharedBuffer.h>
@@ -53,7 +54,7 @@ using SyncLoadCompletionHandler = CompletionHandler<void(const WebCore::Resource
 class WebURLSchemeTask : public RefCounted<WebURLSchemeTask>, public InstanceCounted<WebURLSchemeTask> {
     WTF_MAKE_NONCOPYABLE(WebURLSchemeTask);
 public:
-    static Ref<WebURLSchemeTask> create(WebURLSchemeHandler&, WebPageProxy&, uint64_t identifier, WebCore::ResourceRequest&&, SyncLoadCompletionHandler&&);
+    static Ref<WebURLSchemeTask> create(WebURLSchemeHandler&, WebPageProxy&, WebProcessProxy&, uint64_t identifier, WebCore::ResourceRequest&&, SyncLoadCompletionHandler&&);
 
     uint64_t identifier() const { return m_identifier; }
     uint64_t pageID() const { return m_pageIdentifier; }
@@ -77,12 +78,13 @@ public:
     void pageDestroyed();
 
 private:
-    WebURLSchemeTask(WebURLSchemeHandler&, WebPageProxy&, uint64_t identifier, WebCore::ResourceRequest&&, SyncLoadCompletionHandler&&);
+    WebURLSchemeTask(WebURLSchemeHandler&, WebPageProxy&, WebProcessProxy&, uint64_t identifier, WebCore::ResourceRequest&&, SyncLoadCompletionHandler&&);
 
     bool isSync() const { return !!m_syncCompletionHandler; }
 
     Ref<WebURLSchemeHandler> m_urlSchemeHandler;
     WebPageProxy* m_page;
+    RefPtr<WebProcessProxy> m_process;
     uint64_t m_identifier;
     uint64_t m_pageIdentifier;
     WebCore::ResourceRequest m_request;
index 5da6f99..9183f8c 100644 (file)
@@ -53,7 +53,7 @@ public:
     
 private:
     // PageClient
-    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy() override;
+    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy(WebProcessProxy&) override;
     void setViewNeedsDisplay(const WebCore::Region&) override;
     void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, bool isProgrammaticScroll) override;
     WebCore::FloatPoint viewScrollPosition() override;
index b237ef5..b610724 100644 (file)
@@ -81,9 +81,9 @@ PageClientImpl::~PageClientImpl()
 {
 }
 
-std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
+std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy(WebProcessProxy& process)
 {
-    return [m_contentView _createDrawingAreaProxy];
+    return [m_contentView _createDrawingAreaProxy:process];
 }
 
 void PageClientImpl::setViewNeedsDisplay(const Region&)
index 93319d2..483a476 100644 (file)
@@ -324,7 +324,7 @@ void ViewGestureController::endSwipeGesture(WebBackForwardListItem* targetItem,
     uint64_t pageID = m_webPageProxy.pageID();
     GestureID gestureID = m_currentGestureID;
     m_provisionalLoadCallback = [this, pageID, gestureID] {
-        auto drawingArea = m_webPageProxy.drawingArea();
+        auto drawingArea = m_webPageProxy.provisionalDrawingArea();
         if (!drawingArea) {
             removeSwipeSnapshot();
             return;
index 11fd8a0..a0607e3 100644 (file)
@@ -46,6 +46,7 @@ class DrawingAreaProxy;
 class RemoteLayerTreeTransaction;
 class WebFrameProxy;
 class WebPageProxy;
+class WebProcessProxy;
 class WebProcessPool;
 }
 
@@ -86,7 +87,7 @@ class WebProcessPool;
 
 - (void)_webViewDestroyed;
 
-- (std::unique_ptr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy;
+- (std::unique_ptr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy:(WebKit::WebProcessProxy&)process;
 - (void)_processDidExit;
 - (void)_processWillSwap;
 - (void)_didRelaunchProcess;
index c27ebca..ced85e8 100644 (file)
@@ -520,9 +520,9 @@ static void storeAccessibilityRemoteConnectionInformation(id element, pid_t pid,
 
 #pragma mark PageClientImpl methods
 
-- (std::unique_ptr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy
+- (std::unique_ptr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy:(WebKit::WebProcessProxy&)process
 {
-    return std::make_unique<WebKit::RemoteLayerTreeDrawingAreaProxy>(*_page);
+    return std::make_unique<WebKit::RemoteLayerTreeDrawingAreaProxy>(*_page, process);
 }
 
 - (void)_processDidExit
index 12dc25a..08ffea4 100644 (file)
@@ -61,7 +61,7 @@ public:
 
 private:
     // PageClient
-    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy() override;
+    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy(WebProcessProxy&) override;
     void setViewNeedsDisplay(const WebCore::Region&) override;
     void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, bool isProgrammaticScroll) override;
     WebCore::FloatPoint viewScrollPosition() override;
index 5d7c238..b48ac3f 100644 (file)
@@ -123,9 +123,9 @@ void PageClientImpl::setImpl(WebViewImpl& impl)
     m_impl = makeWeakPtr(impl);
 }
 
-std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
+std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy(WebProcessProxy& process)
 {
-    return m_impl->createDrawingAreaProxy();
+    return m_impl->createDrawingAreaProxy(process);
 }
 
 void PageClientImpl::setViewNeedsDisplay(const WebCore::Region&)
index 179bd28..f2f2702 100644 (file)
@@ -33,7 +33,7 @@ namespace WebKit {
 
 class TiledCoreAnimationDrawingAreaProxy : public DrawingAreaProxy {
 public:
-    explicit TiledCoreAnimationDrawingAreaProxy(WebPageProxy&);
+    TiledCoreAnimationDrawingAreaProxy(WebPageProxy&, WebProcessProxy&);
     virtual ~TiledCoreAnimationDrawingAreaProxy();
 
 private:
index bc8bc41..77c8380 100644 (file)
@@ -42,8 +42,8 @@ namespace WebKit {
 using namespace IPC;
 using namespace WebCore;
 
-TiledCoreAnimationDrawingAreaProxy::TiledCoreAnimationDrawingAreaProxy(WebPageProxy& webPageProxy)
-    : DrawingAreaProxy(DrawingAreaTypeTiledCoreAnimation, webPageProxy)
+TiledCoreAnimationDrawingAreaProxy::TiledCoreAnimationDrawingAreaProxy(WebPageProxy& webPageProxy, WebProcessProxy& process)
+    : DrawingAreaProxy(DrawingAreaTypeTiledCoreAnimation, webPageProxy, process)
     , m_isWaitingForDidUpdateGeometry(false)
 {
 }
@@ -55,7 +55,7 @@ TiledCoreAnimationDrawingAreaProxy::~TiledCoreAnimationDrawingAreaProxy()
 
 void TiledCoreAnimationDrawingAreaProxy::deviceScaleFactorDidChange()
 {
-    m_webPageProxy.process().send(Messages::DrawingArea::SetDeviceScaleFactor(m_webPageProxy.deviceScaleFactor()), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::SetDeviceScaleFactor(m_webPageProxy.deviceScaleFactor()), m_webPageProxy.pageID());
 }
 
 void TiledCoreAnimationDrawingAreaProxy::sizeDidChange()
@@ -73,7 +73,7 @@ void TiledCoreAnimationDrawingAreaProxy::sizeDidChange()
 
 void TiledCoreAnimationDrawingAreaProxy::colorSpaceDidChange()
 {
-    m_webPageProxy.process().send(Messages::DrawingArea::SetColorSpace(m_webPageProxy.colorSpace()), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::SetColorSpace(m_webPageProxy.colorSpace()), m_webPageProxy.pageID());
 }
 
 void TiledCoreAnimationDrawingAreaProxy::viewLayoutSizeDidChange()
@@ -122,7 +122,7 @@ void TiledCoreAnimationDrawingAreaProxy::didUpdateGeometry()
 void TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState(ActivityStateChangeID)
 {
     Seconds activityStateUpdateTimeout = Seconds::fromMilliseconds(250);
-    m_webPageProxy.process().connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::DidUpdateActivityState>(m_webPageProxy.pageID(), activityStateUpdateTimeout, IPC::WaitForOption::InterruptWaitingIfSyncMessageArrives);
+    process().connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::DidUpdateActivityState>(m_webPageProxy.pageID(), activityStateUpdateTimeout, IPC::WaitForOption::InterruptWaitingIfSyncMessageArrives);
 }
 
 void TiledCoreAnimationDrawingAreaProxy::intrinsicContentSizeDidChange(const IntSize& newIntrinsicContentSize)
@@ -151,19 +151,19 @@ MachSendRight TiledCoreAnimationDrawingAreaProxy::createFence()
     // will likely get dropped on the floor (if the Web process is terminated)
     // or queued up until process launch completes, and there's nothing useful
     // to synchronize in these cases.
-    if (!m_webPageProxy.process().connection())
+    if (!process().connection())
         return MachSendRight();
 
     // Don't fence if we have incoming synchronous messages, because we may not
     // be able to reply to the message until the fence times out.
-    if (m_webPageProxy.process().connection()->hasIncomingSyncMessage())
+    if (process().connection()->hasIncomingSyncMessage())
         return MachSendRight();
 
     MachSendRight fencePort = MachSendRight::adopt([rootLayerContext createFencePort]);
 
     // Invalidate the fence if a synchronous message arrives while it's installed,
     // because we won't be able to reply during the fence-wait.
-    uint64_t callbackID = m_webPageProxy.process().connection()->installIncomingSyncMessageCallback([rootLayerContext] {
+    uint64_t callbackID = process().connection()->installIncomingSyncMessageCallback([rootLayerContext] {
         [rootLayerContext invalidateFences];
     });
     RefPtr<WebPageProxy> retainedPage = &m_webPageProxy;
@@ -182,17 +182,17 @@ void TiledCoreAnimationDrawingAreaProxy::sendUpdateGeometry()
     ASSERT(!m_isWaitingForDidUpdateGeometry);
 
     willSendUpdateGeometry();
-    m_webPageProxy.process().send(Messages::DrawingArea::UpdateGeometry(m_size, true /* flushSynchronously */, createFence()), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::UpdateGeometry(m_size, true /* flushSynchronously */, createFence()), m_webPageProxy.pageID());
 }
 
 void TiledCoreAnimationDrawingAreaProxy::adjustTransientZoom(double scale, FloatPoint origin)
 {
-    m_webPageProxy.process().send(Messages::DrawingArea::AdjustTransientZoom(scale, origin), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::AdjustTransientZoom(scale, origin), m_webPageProxy.pageID());
 }
 
 void TiledCoreAnimationDrawingAreaProxy::commitTransientZoom(double scale, FloatPoint origin)
 {
-    m_webPageProxy.process().send(Messages::DrawingArea::CommitTransientZoom(scale, origin), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::CommitTransientZoom(scale, origin), m_webPageProxy.pageID());
 }
 
 void TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing(WTF::Function<void (CallbackBase::Error)>&& callback)
@@ -202,7 +202,7 @@ void TiledCoreAnimationDrawingAreaProxy::dispatchAfterEnsuringDrawing(WTF::Funct
         return;
     }
 
-    m_webPageProxy.process().send(Messages::DrawingArea::AddTransactionCallbackID(m_callbacks.put(WTFMove(callback), nullptr)), m_webPageProxy.pageID());
+    process().send(Messages::DrawingArea::AddTransactionCallbackID(m_callbacks.put(WTFMove(callback), nullptr)), m_webPageProxy.pageID());
 }
 
 void TiledCoreAnimationDrawingAreaProxy::dispatchPresentationCallbacksAfterFlushingLayers(const Vector<CallbackID>& callbackIDs)
index 084af87..62be410 100644 (file)
@@ -65,7 +65,7 @@
 #import <wtf/text/StringConcatenate.h>
 
 #define MESSAGE_CHECK(assertion) MESSAGE_CHECK_BASE(assertion, process().connection())
-#define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(url), m_process->connection())
+#define MESSAGE_CHECK_URL(url) MESSAGE_CHECK_BASE(checkURLReceivedFromCurrentOrPreviousWebProcess(m_process, url), m_process->connection())
 
 @interface NSApplication ()
 - (BOOL)isSpeaking;
index 80e2c2d..170c2d7 100644 (file)
@@ -43,9 +43,9 @@ PageClientImpl::PageClientImpl(WebView& view)
 }
 
 // PageClient's pure virtual functions
-std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
+std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy(WebProcessProxy& process)
 {
-    return std::make_unique<DrawingAreaProxyImpl>(*m_view.page());
+    return std::make_unique<DrawingAreaProxyImpl>(*m_view.page(), process);
 }
 
 void PageClientImpl::setViewNeedsDisplay(const WebCore::Region& region)
index a01b68f..66572bb 100644 (file)
@@ -53,7 +53,7 @@ public:
     HWND viewWidget();
 private:
     // PageClient
-    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy() override;
+    std::unique_ptr<DrawingAreaProxy> createDrawingAreaProxy(WebProcessProxy&) override;
     void setViewNeedsDisplay(const WebCore::Region&) override;
     void requestScroll(const WebCore::FloatPoint& scrollPosition, const WebCore::IntPoint& scrollOrigin, bool isProgrammaticScroll) override;
     WebCore::FloatPoint viewScrollPosition() override;
index 809621f..3f0571d 100644 (file)
                466BC0381FA266C9002FA9C1 /* WebSWContextManagerConnection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebSWContextManagerConnection.cpp; sourceTree = "<group>"; };
                466BC0391FA266C9002FA9C1 /* WebSWContextManagerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSWContextManagerConnection.h; sourceTree = "<group>"; };
                466BC03A1FA266C9002FA9C1 /* WebSWContextManagerConnection.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebSWContextManagerConnection.messages.in; sourceTree = "<group>"; };
+               4683569A21E81CC7006E27A3 /* ProvisionalPageProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProvisionalPageProxy.h; sourceTree = "<group>"; };
+               4683569B21E81CC7006E27A3 /* ProvisionalPageProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProvisionalPageProxy.cpp; sourceTree = "<group>"; };
                46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackgroundProcessResponsivenessTimer.cpp; sourceTree = "<group>"; };
                46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackgroundProcessResponsivenessTimer.h; sourceTree = "<group>"; };
                46DF06391F3905E5001980BB /* NetworkCORSPreflightChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkCORSPreflightChecker.cpp; sourceTree = "<group>"; };
                                86E67A22190F411800004AB7 /* ProcessThrottler.cpp */,
                                86E67A21190F411800004AB7 /* ProcessThrottler.h */,
                                83048AE51ACA45DC0082C832 /* ProcessThrottlerClient.h */,
+                               4683569B21E81CC7006E27A3 /* ProvisionalPageProxy.cpp */,
+                               4683569A21E81CC7006E27A3 /* ProvisionalPageProxy.h */,
                                A55BA81B1BA25B1E007CD33D /* RemoteWebInspectorProxy.cpp */,
                                A55BA8191BA25B1E007CD33D /* RemoteWebInspectorProxy.h */,
                                A55BA81A1BA25B1E007CD33D /* RemoteWebInspectorProxy.messages.in */,
index 00749b4..ffed00c 100644 (file)
@@ -263,8 +263,6 @@ static WebCore::PolicyAction toPolicyAction(WebPolicyAction policyAction)
         return WebCore::PolicyAction::Ignore;
     case WebPolicyAction::Download:
         return WebCore::PolicyAction::Download;
-    case WebPolicyAction::Suspend:
-        break;
     }
     ASSERT_NOT_REACHED();
     return WebCore::PolicyAction::Ignore;
@@ -272,11 +270,8 @@ static WebCore::PolicyAction toPolicyAction(WebPolicyAction policyAction)
 
 void WebFrame::didReceivePolicyDecision(uint64_t listenerID, WebPolicyAction action, uint64_t navigationID, DownloadID downloadID, Optional<WebsitePoliciesData>&& websitePolicies)
 {
-    if (!m_coreFrame || !m_policyListenerID || listenerID != m_policyListenerID || !m_policyFunction) {
-        if (action == WebPolicyAction::Suspend)
-            page()->send(Messages::WebPageProxy::DidFailToSuspendAfterProcessSwap());
+    if (!m_coreFrame || !m_policyListenerID || listenerID != m_policyListenerID || !m_policyFunction)
         return;
-    }
 
     FramePolicyFunction function = WTFMove(m_policyFunction);
     bool forNavigationAction = m_policyFunctionForNavigationAction == ForNavigationAction::Yes;
@@ -292,16 +287,7 @@ void WebFrame::didReceivePolicyDecision(uint64_t listenerID, WebPolicyAction act
             documentLoader->setNavigationID(navigationID);
     }
 
-    bool shouldSuspend = false;
-    if (action == WebPolicyAction::Suspend) {
-        shouldSuspend = true;
-        action = WebPolicyAction::Ignore;
-    }
-
     function(toPolicyAction(action));
-
-    if (shouldSuspend)
-        page()->suspendForProcessSwap();
 }
 
 void WebFrame::startDownload(const WebCore::ResourceRequest& request, const String& suggestedName)
index 7620311..dd97d6e 100644 (file)
@@ -402,7 +402,7 @@ WebPage::WebPage(uint64_t pageID, WebPageCreationParameters&& parameters)
     , m_overrideContentSecurityPolicy { parameters.overrideContentSecurityPolicy }
     , m_cpuLimit(parameters.cpuLimit)
 #if PLATFORM(MAC)
-    , m_shouldAttachDrawingAreaOnPageTransition(parameters.isSwapFromSuspended)
+    , m_shouldAttachDrawingAreaOnPageTransition(parameters.isProcessSwap)
 #endif
 {
     ASSERT(m_pageID);
@@ -473,8 +473,8 @@ WebPage::WebPage(uint64_t pageID, WebPageCreationParameters&& parameters)
     m_drawingArea->setPaintingEnabled(false);
     m_drawingArea->setShouldScaleViewToFitDocument(parameters.shouldScaleViewToFitDocument);
 
-    if (parameters.isSwapFromSuspended)
-        freezeLayerTree(LayerTreeFreezeReason::SwapFromSuspended);
+    if (parameters.isProcessSwap)
+        freezeLayerTree(LayerTreeFreezeReason::ProcessSwap);
 
 #if ENABLE(ASYNC_SCROLLING)
     m_useAsyncScrolling = parameters.store.getBoolValueForKey(WebPreferencesKey::threadedScrollingEnabledKey());
@@ -698,7 +698,7 @@ void WebPage::reinitializeWebPage(WebPageCreationParameters&& parameters)
         m_drawingArea->updatePreferences(parameters.store);
         m_drawingArea->setPaintingEnabled(true);
 #if PLATFORM(MAC)
-        m_shouldAttachDrawingAreaOnPageTransition = parameters.isSwapFromSuspended;
+        m_shouldAttachDrawingAreaOnPageTransition = parameters.isProcessSwap;
 #endif
         unfreezeLayerTree(LayerTreeFreezeReason::PageSuspended);
     }
@@ -3055,12 +3055,6 @@ void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, We
     WebFrame* frame = WebProcess::singleton().webFrame(frameID);
     if (!frame)
         return;
-    if (policyAction == WebPolicyAction::Suspend) {
-        ASSERT(frame == m_mainFrame);
-        setIsSuspended(true);
-
-        WebProcess::singleton().sendPrewarmInformation(mainWebFrame()->url());
-    }
     frame->didReceivePolicyDecision(listenerID, policyAction, navigationID, downloadID, WTFMove(websitePolicies));
 }
 
@@ -3102,7 +3096,7 @@ void WebPage::didCompletePageTransition()
 
     bool isInitialEmptyDocument = !m_mainFrame;
     if (!isInitialEmptyDocument)
-        unfreezeLayerTree(LayerTreeFreezeReason::SwapFromSuspended);
+        unfreezeLayerTree(LayerTreeFreezeReason::ProcessSwap);
 
 #if PLATFORM(MAC)
     if (m_shouldAttachDrawingAreaOnPageTransition && !isInitialEmptyDocument) {
@@ -6314,6 +6308,10 @@ void WebPage::setIsSuspended(bool suspended)
     if (m_isSuspended) {
         // Unfrozen on drawing area reset.
         freezeLayerTree(LayerTreeFreezeReason::PageSuspended);
+
+        WebProcess::singleton().sendPrewarmInformation(mainWebFrame()->url());
+
+        suspendForProcessSwap();
     } else
         m_shouldResetDrawingAreaAfterSuspend = true;
 }
index 715e124..f3b934e 100644 (file)
@@ -696,7 +696,7 @@ public:
         ProcessSuspended        = 1 << 2,
         PageSuspended           = 1 << 3,
         Printing                = 1 << 4,
-        SwapFromSuspended       = 1 << 5,
+        ProcessSwap             = 1 << 5,
     };
     void freezeLayerTree(LayerTreeFreezeReason);
     void unfreezeLayerTree(LayerTreeFreezeReason);
index fb848da..5ff56be 100644 (file)
@@ -97,7 +97,7 @@ TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea(WebPage& webPage, c
     updateLayerHostingContext();
     setColorSpace(parameters.colorSpace);
 
-    if (!parameters.isSwapFromSuspended)
+    if (!parameters.isProcessSwap)
         attach();
 }
 
index f53ced5..823b08c 100644 (file)
@@ -1,3 +1,16 @@
+2019-01-16  Chris Dumez  <cdumez@apple.com>
+
+        Regression(PSON) View becomes blank after click a cross-site download link
+        https://bugs.webkit.org/show_bug.cgi?id=193361
+        <rdar://problem/47099573>
+
+        Reviewed by Geoffrey Garen.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+        (-[PSONNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
+
 2019-01-16  Zalan Bujtas  <zalan@apple.com>
 
         [LFC][Out-of-flow] Set used vertical margin values when top/height/bottom are non-auto.
index f35d8ba..17c3e22 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -72,6 +72,7 @@ static bool serverRedirected;
 static HashSet<pid_t> seenPIDs;
 static bool willPerformClientRedirect;
 static bool didPerformClientRedirect;
+static bool shouldConvertToDownload;
 static RetainPtr<NSURL> clientRedirectSourceURL;
 static RetainPtr<NSURL> clientRedirectDestinationURL;
 
@@ -128,6 +129,11 @@ static RetainPtr<NSURL> clientRedirectDestinationURL;
     didRepondToPolicyDecisionCall = true;
 }
 
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
+{
+    decisionHandler(shouldConvertToDownload ? _WKNavigationResponsePolicyBecomeDownload : WKNavigationResponsePolicyAllow);
+}
+
 - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
 {
     seenPIDs.add([webView _webProcessIdentifier]);
@@ -1467,6 +1473,109 @@ TEST(ProcessSwap, ServerRedirect2)
     EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", [[webView URL] absoluteString]);
 }
 
+static const char* linkToWebKitBytes = R"PSONRESOURCE(
+<body>
+  <a id="testLink" href="pson://www.webkit.org/main.html">Link</a>
+</body>
+)PSONRESOURCE";
+
+TEST(ProcessSwap, PolicyCancelAfterServerRedirect)
+{
+    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    processPoolConfiguration.get().processSwapsOnNavigation = YES;
+    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.google.com/main.html" toData:linkToWebKitBytes];
+    [handler addRedirectFromURLString:@"pson://www.webkit.org/main.html" toURLString:@"pson://www.apple.com/ignore.html"];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"pson"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:navigationDelegate.get()];
+
+    navigationDelegate->decidePolicyForNavigationAction = ^(WKNavigationAction *action, void (^decisionHandler)(WKNavigationActionPolicy)) {
+        if ([action.request.URL.absoluteString hasSuffix:@"ignore.html"]) {
+            decisionHandler(WKNavigationActionPolicyCancel);
+            return;
+        }
+        decisionHandler(WKNavigationActionPolicyAllow);
+    };
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.google.com/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    auto pidAfterFirstLoad = [webView _webProcessIdentifier];
+
+    EXPECT_EQ(1, numberOfDecidePolicyCalls);
+
+    [webView evaluateJavaScript:@"testLink.click()" completionHandler:nil];
+
+    TestWebKitAPI::Util::run(&failed);
+    failed = false;
+    done = false;
+
+    EXPECT_EQ(3, numberOfDecidePolicyCalls);
+
+    // We should still be on google.com.
+    EXPECT_EQ(pidAfterFirstLoad, [webView _webProcessIdentifier]);
+    EXPECT_WK_STREQ(@"pson://www.google.com/main.html", [[webView URL] absoluteString]);
+
+    [webView evaluateJavaScript:@"testLink.innerText" completionHandler: [&] (id innerText, NSError *error) {
+        EXPECT_WK_STREQ(@"Link", innerText);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+}
+
+TEST(ProcessSwap, CrossSiteDownload)
+{
+    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    processPoolConfiguration.get().processSwapsOnNavigation = YES;
+    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.google.com/main.html" toData:linkToWebKitBytes];
+    [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:"Hello"];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"pson"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:navigationDelegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.google.com/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+    auto pidAfterFirstLoad = [webView _webProcessIdentifier];
+
+    shouldConvertToDownload = true;
+    [webView evaluateJavaScript:@"testLink.click()" completionHandler:nil];
+
+    TestWebKitAPI::Util::run(&failed);
+    failed = false;
+    shouldConvertToDownload = false;
+
+    // We should still be on google.com.
+    EXPECT_EQ(pidAfterFirstLoad, [webView _webProcessIdentifier]);
+    EXPECT_WK_STREQ(@"pson://www.google.com/main.html", [[webView URL] absoluteString]);
+
+    [webView evaluateJavaScript:@"testLink.innerText" completionHandler: [&] (id innerText, NSError *error) {
+        EXPECT_WK_STREQ(@"Link", innerText);
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+}
+
 enum class ShouldEnablePSON { No, Yes };
 static void runClientSideRedirectTest(ShouldEnablePSON shouldEnablePSON)
 {
@@ -2232,12 +2341,27 @@ TEST(ProcessSwap, PageShowHide)
 
     EXPECT_EQ(7u, [receivedMessages count]);
     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow NOT persisted", receivedMessages.get()[0]);
-    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[1]);
-    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow NOT persisted", receivedMessages.get()[2]);
-    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pagehide persisted", receivedMessages.get()[3]);
-    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow persisted", receivedMessages.get()[4]);
-    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[5]);
-    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow persisted", receivedMessages.get()[6]);
+    if ([receivedMessages.get()[1] hasPrefix:@"pson://www.webkit.org/main.html"]) {
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[1]);
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow NOT persisted", receivedMessages.get()[2]);
+    } else {
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow NOT persisted", receivedMessages.get()[1]);
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[2]);
+    }
+    if ([receivedMessages.get()[3] hasPrefix:@"pson://www.apple.com/main.html"]) {
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pagehide persisted", receivedMessages.get()[3]);
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow persisted", receivedMessages.get()[4]);
+    } else {
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow persisted", receivedMessages.get()[3]);
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pagehide persisted", receivedMessages.get()[4]);
+    }
+    if ([receivedMessages.get()[5] hasPrefix:@"pson://www.webkit.org/main.html"]) {
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[5]);
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow persisted", receivedMessages.get()[6]);
+    } else {
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow persisted", receivedMessages.get()[5]);
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[6]);
+    }
 }
 
 // Disabling the page cache explicitly is (for some reason) not available on iOS.
@@ -2307,12 +2431,27 @@ TEST(ProcessSwap, LoadUnload)
 
     EXPECT_EQ(7u, [receivedMessages count]);
     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[0]);
-    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[1]);
-    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[2]);
-    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - unload", receivedMessages.get()[3]);
-    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[4]);
-    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[5]);
-    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[6]);
+    if ([receivedMessages.get()[1] hasPrefix:@"pson://www.webkit.org/main.html"]) {
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[1]);
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[2]);
+    } else {
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[1]);
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[2]);
+    }
+    if ([receivedMessages.get()[3] hasPrefix:@"pson://www.apple.com/main.html"]) {
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - unload", receivedMessages.get()[3]);
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[4]);
+    } else {
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[3]);
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - unload", receivedMessages.get()[4]);
+    }
+    if ([receivedMessages.get()[5] hasPrefix:@"pson://www.webkit.org/main.html"]) {
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[5]);
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[6]);
+    } else {
+        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[5]);
+        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[6]);
+    }
 }
 
 TEST(ProcessSwap, WebInspector)