WebKit Bugzilla
Attachment 358961 Details for
Bug 193361
: Regression(PSON) View becomes blank after click a cross-site download link
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Prototype (with test)
193361_pson_provisional_process_wip.patch (text/plain), 77.20 KB, created by
Chris Dumez
on 2019-01-11 16:30:36 PST
(
hide
)
Description:
Prototype (with test)
Filename:
MIME Type:
Creator:
Chris Dumez
Created:
2019-01-11 16:30:36 PST
Size:
77.20 KB
patch
obsolete
>diff --git a/LayoutTests/platform/wk2/TestExpectations b/LayoutTests/platform/wk2/TestExpectations >index 8e959edaffd..9d90be8b48e 100644 >--- a/LayoutTests/platform/wk2/TestExpectations >+++ b/LayoutTests/platform/wk2/TestExpectations >@@ -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 ] >diff --git a/Source/WebCore/loader/FrameLoader.cpp b/Source/WebCore/loader/FrameLoader.cpp >index 4c26a6981b4..ebf950ba6c2 100644 >--- a/Source/WebCore/loader/FrameLoader.cpp >+++ b/Source/WebCore/loader/FrameLoader.cpp >@@ -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()); >diff --git a/Source/WebKit/Shared/WebPageCreationParameters.cpp b/Source/WebKit/Shared/WebPageCreationParameters.cpp >index ca2df40ee1d..6d07c03ad8c 100644 >--- a/Source/WebKit/Shared/WebPageCreationParameters.cpp >+++ b/Source/WebKit/Shared/WebPageCreationParameters.cpp >@@ -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) >diff --git a/Source/WebKit/Shared/WebPageCreationParameters.h b/Source/WebKit/Shared/WebPageCreationParameters.h >index ae4325cbd5f..b382ceedd44 100644 >--- a/Source/WebKit/Shared/WebPageCreationParameters.h >+++ b/Source/WebKit/Shared/WebPageCreationParameters.h >@@ -129,7 +129,7 @@ struct WebPageCreationParameters { > Vector<String> mimeTypesWithCustomContentProviders; > > bool controlledByAutomation; >- bool isSwapFromSuspended { false }; >+ bool isProcessSwap { false }; > > #if PLATFORM(MAC) > ColorSpaceData colorSpace; >diff --git a/Source/WebKit/Shared/WebPolicyAction.h b/Source/WebKit/Shared/WebPolicyAction.h >index 142a518df09..3971795c46a 100644 >--- a/Source/WebKit/Shared/WebPolicyAction.h >+++ b/Source/WebKit/Shared/WebPolicyAction.h >@@ -29,11 +29,11 @@ > > 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 > >; > }; > >diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt >index a0b6f728460..8aecb864725 100644 >--- a/Source/WebKit/Sources.txt >+++ b/Source/WebKit/Sources.txt >@@ -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 >diff --git a/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm b/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm >index cf1919c93a7..c79fcb210b5 100644 >--- a/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm >+++ b/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm >@@ -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" >@@ -4664,6 +4665,11 @@ - (void)_killWebContentProcessAndResetState > { > 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) >diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h >index 0b858c46ee4..6f3df8452b3 100644 >--- a/Source/WebKit/UIProcess/PageClient.h >+++ b/Source/WebKit/UIProcess/PageClient.h >@@ -48,6 +48,7 @@ > > OBJC_CLASS CALayer; > OBJC_CLASS NSFileWrapper; >+OBJC_CLASS NSMenu; > OBJC_CLASS NSSet; > OBJC_CLASS WKDrawingView; > OBJC_CLASS _WKRemoteObjectRegistry; >diff --git a/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp b/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp >new file mode 100644 >index 00000000000..a669f440b3e >--- /dev/null >+++ b/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp >@@ -0,0 +1,288 @@ >+/* >+ * 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 "Logging.h" >+#include "PageClient.h" >+#include "WebBackForwardList.h" >+#include "WebBackForwardListItem.h" >+#include "WebErrors.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__) >+ >+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().backgroundActivityToken()) >+#endif >+{ >+ m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID(), *this); >+ m_process->addProvisionalPageProxy(*this); >+ >+ initializeWebPage(); >+ >+ // 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); >+ } >+} >+ >+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()); >+ >+ if (m_drawingArea) { >+ auto pageProcessOverride = m_page.temporarilyOverrideProcess(m_process); >+ m_drawingArea = nullptr; >+ } >+ >+ RunLoop::main().dispatch([process = m_process.copyRef()] { >+ process->maybeShutDown(); >+ }); >+} >+ >+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::initializeWebPage() >+{ >+ auto pageProcessOverride = m_page.temporarilyOverrideProcess(m_process); >+ m_drawingArea = m_page.pageClient().createDrawingAreaProxy(); >+ >+ auto parameters = m_page.creationParameters(); >+ parameters.isProcessSwap = true; >+ m_process->send(Messages::WebProcess::CreateWebPage(m_page.pageID(), parameters), 0); >+} >+ >+void ProvisionalPageProxy::loadDataWithNavigation(API::Navigation& navigation, const IPC::DataReference& data, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, Optional<WebsitePoliciesData>&& websitePolicies) >+{ >+ auto pageProcessOverride = m_page.temporarilyOverrideProcess(m_process); >+ m_page.loadDataWithNavigation(navigation, data, MIMEType, encoding, baseURL, userData, WebCore::ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies)); >+} >+ >+void ProvisionalPageProxy::loadRequestWithNavigation(API::Navigation& navigation, WebCore::ResourceRequest&& request, WebCore::ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, Optional<WebsitePoliciesData>&& websitePolicies) >+{ >+ auto pageProcessOverride = m_page.temporarilyOverrideProcess(m_process); >+ m_page.loadRequestWithNavigation(navigation, WTFMove(request), shouldOpenExternalURLsPolicy, userData, WebCore::ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies)); >+} >+ >+void ProvisionalPageProxy::goToBackForwardItem(API::Navigation& navigation, WebBackForwardListItem& item, Optional<WebsitePoliciesData>&& websitePolicies) >+{ >+ 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()); >+ >+ auto pageProcessOverride = m_page.temporarilyOverrideProcess(m_process); >+ m_page.didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), m_navigationID, WTFMove(m_request), { }); >+ } >+} >+ >+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); >+ >+ auto pageProcessOverride = m_page.temporarilyOverrideProcess(m_process); >+ m_page.didStartProvisionalLoadForFrame(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) >+{ >+ auto pageProcessOverride = m_page.temporarilyOverrideProcess(m_process); >+ >+ RELEASE_LOG_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.didFailProvisionalLoadForFrame(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::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 >+ || decoder.messageName() == Messages::WebPageProxy::DecidePolicyForNavigationActionAsync::name() >+ || decoder.messageName() == Messages::WebPageProxy::StartURLSchemeTask::name() >+ || decoder.messageName() == Messages::WebPageProxy::DecidePolicyForResponse::name() >+ || decoder.messageName() == Messages::WebPageProxy::DidPerformClientRedirect::name() >+ || decoder.messageName() == Messages::WebPageProxy::DidChangeProvisionalURLForFrame::name() >+ || decoder.messageName() == Messages::WebPageProxy::DidNavigateWithNavigationData::name()) >+ { >+ auto pageProcessOverride = m_page.temporarilyOverrideProcess(m_process); >+ m_page.didReceiveMessage(connection, decoder); >+ 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>& encoder) >+{ >+ if (decoder.messageName() == Messages::WebPageProxy::BackForwardItemAtIndex::name() || decoder.messageName() == Messages::WebPageProxy::BackForwardGoToItem::name()) { >+ auto pageProcessOverride = m_page.temporarilyOverrideProcess(m_process); >+ m_page.didReceiveSyncMessage(connection, decoder, encoder); >+ return; >+ } >+ >+ LOG(ProcessSwapping, "Unhandled sync message %s::%s from provisional process", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data()); >+} >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/ProvisionalPageProxy.h b/Source/WebKit/UIProcess/ProvisionalPageProxy.h >new file mode 100644 >index 00000000000..edc1415549b >--- /dev/null >+++ b/Source/WebKit/UIProcess/ProvisionalPageProxy.h >@@ -0,0 +1,89 @@ >+/* >+ * 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" >+ >+namespace WebCore { >+class ResourceRequest; >+} >+ >+namespace WebKit { >+ >+class DrawingAreaProxy; >+class SuspendedPageProxy; >+class WebFrameProxy; >+class WebPageProxy; >+class WebProcessProxy; >+ >+class ProvisionalPageProxy : public IPC::MessageReceiver { >+ 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; } >+ >+ std::unique_ptr<DrawingAreaProxy> takeDrawingArea(); >+ >+ void loadDataWithNavigation(API::Navigation&, const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, Optional<WebsitePoliciesData>&& = WTF::nullopt); >+ void loadRequestWithNavigation(API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, Optional<WebsitePoliciesData>&& = WTF::nullopt); >+ void goToBackForwardItem(API::Navigation&, WebBackForwardListItem&, Optional<WebsitePoliciesData>&&); >+ void cancel(); >+ >+private: >+ // IPC::MessageReceiver >+ void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final; >+ void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&) final; >+ >+ 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 initializeWebPage(); >+ >+ 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::BackgroundActivityToken m_suspensionToken; >+#endif >+}; >+ >+} // namespace WebKit >diff --git a/Source/WebKit/UIProcess/SuspendedPageProxy.cpp b/Source/WebKit/UIProcess/SuspendedPageProxy.cpp >index f198a81533f..ff76d9f7f97 100644 >--- a/Source/WebKit/UIProcess/SuspendedPageProxy.cpp >+++ b/Source/WebKit/UIProcess/SuspendedPageProxy.cpp >@@ -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); > } >diff --git a/Source/WebKit/UIProcess/WebFrameProxy.cpp b/Source/WebKit/UIProcess/WebFrameProxy.cpp >index c77a26b7427..53c7196c2aa 100644 >--- a/Source/WebKit/UIProcess/WebFrameProxy.cpp >+++ b/Source/WebKit/UIProcess/WebFrameProxy.cpp >@@ -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) >diff --git a/Source/WebKit/UIProcess/WebPageProxy.cpp b/Source/WebKit/UIProcess/WebPageProxy.cpp >index 392743bd567..77ad60c2ad7 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.cpp >+++ b/Source/WebKit/UIProcess/WebPageProxy.cpp >@@ -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" >@@ -768,38 +769,25 @@ 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); >+ m_drawingArea = 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); >+ finishAttachingToWebProcess(); > } > >-void WebPageProxy::finishAttachingToWebProcess(IsSwapFromSuspended isSwapFromSuspended) >+void WebPageProxy::finishAttachingToWebProcess() > { > ASSERT(m_process->state() != ChildProcessProxy::State::Terminated); > >@@ -835,7 +823,7 @@ void WebPageProxy::finishAttachingToWebProcess(IsSwapFromSuspended isSwapFromSus > m_editableImageController = std::make_unique<EditableImageController>(*this); > #endif > >- initializeWebPage(isSwapFromSuspended); >+ initializeWebPage(); > > m_inspector->updateForNewPageProcess(this); > >@@ -900,12 +888,14 @@ RefPtr<API::Navigation> WebPageProxy::reattachToWebProcessWithItem(WebBackForwar > return WTFMove(navigation); > } > >-void WebPageProxy::initializeWebPage(IsSwapFromSuspended isSwapFromSuspended) >+void WebPageProxy::initializeWebPage() > { > ASSERT(isValid()); > >- m_drawingArea = pageClient().createDrawingAreaProxy(); >- ASSERT(m_drawingArea); >+ if (!m_drawingArea) { >+ m_drawingArea = pageClient().createDrawingAreaProxy(); >+ ASSERT(m_drawingArea); >+ } > > #if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA) > if (m_drawingArea->type() == DrawingAreaTypeRemoteLayerTree) { >@@ -917,14 +907,7 @@ void WebPageProxy::initializeWebPage(IsSwapFromSuspended isSwapFromSuspended) > } > #endif > >- auto parameters = creationParameters(); >- parameters.isSwapFromSuspended = isSwapFromSuspended == IsSwapFromSuspended::Yes; >- >-#if ENABLE(SERVICE_WORKER) >- parameters.hasRegisteredServiceWorkers = process().processPool().mayHaveRegisteredServiceWorkers(m_websiteDataStore); >-#endif >- >- process().send(Messages::WebProcess::CreateWebPage(m_pageID, parameters), 0); >+ process().send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters()), 0); > > m_needsToFinishInitializingWebPageAfterProcessLaunch = true; > finishInitializingWebPageAfterProcessLaunch(); >@@ -1076,7 +1059,8 @@ void WebPageProxy::loadRequestWithNavigation(API::Navigation& navigation, Resour > 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(); >@@ -2697,7 +2681,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 >@@ -2706,8 +2690,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)); > }); > } > >@@ -2743,24 +2733,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()); >@@ -2768,67 +2779,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->loadDataWithNavigation(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->loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, WTFMove(websitePolicies)); > } > > bool WebPageProxy::isPageOpenedByDOMShowingInitialEmptyDocument() const >@@ -3693,11 +3659,6 @@ void WebPageProxy::didCreateMainFrame(uint64_t 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) >@@ -3722,10 +3683,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 >@@ -3778,6 +3735,10 @@ 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); > } >@@ -3795,14 +3756,6 @@ void WebPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t na > 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); > >@@ -3910,6 +3863,11 @@ void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const Securi > > PageClientProtector protector(pageClient()); > >+ if (m_provisionalPage && m_provisionalPage->navigationID() == navigationID && &m_provisionalPage->process() != m_process.ptr()) { >+ // The load did not fail, it merely happening in a new provisional process. >+ return; >+ } >+ > WebFrameProxy* frame = m_process->webFrame(frameID); > MESSAGE_CHECK(frame); > >@@ -3948,6 +3906,10 @@ void WebPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const Securi > } > > 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() >@@ -4339,8 +4301,8 @@ void WebPageProxy::decidePolicyForNavigationActionAsync(uint64_t frameID, WebCor > auto* frame = m_process->webFrame(frameID); > MESSAGE_CHECK(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(*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 = m_process.copyRef()] (auto... args) { >+ process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, args...), m_pageID); > })); > } > >@@ -4574,12 +4536,12 @@ void WebPageProxy::decidePolicyForResponse(uint64_t frameID, const SecurityOrigi > MESSAGE_CHECK_URL(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 = m_process.copyRef()] (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)); > >@@ -6486,8 +6448,6 @@ void WebPageProxy::processWillBecomeForeground() > void WebPageProxy::resetState(ResetStateReason resetStateReason) > { > m_mainFrame = nullptr; >- m_mainFrameCreationHandler = nullptr; >- m_mainFrameWindowCreationHandler = nullptr; > > #if PLATFORM(COCOA) > m_scrollingPerformanceData = nullptr; >@@ -6778,6 +6738,10 @@ 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); >@@ -8539,6 +8503,21 @@ void WebPageProxy::simulateDeviceOrientationChange(double alpha, double beta, do > m_process->send(Messages::WebPage::SimulateDeviceOrientationChange(alpha, beta, gamma), m_pageID); > } > >+WebPageProxy::PageProcessOverride::PageProcessOverride(WebPageProxy& page, WebProcessProxy& newProcess) >+ : m_page(&page) >+ , m_previousProcess(page.process()) >+{ >+ page.m_process = newProcess; >+} >+ >+WebPageProxy::PageProcessOverride::PageProcessOverride(PageProcessOverride&&) = default; >+ >+WebPageProxy::PageProcessOverride::~PageProcessOverride() >+{ >+ if (m_page) >+ m_page->m_process = WTFMove(m_previousProcess); >+} >+ > #if ENABLE(DATA_DETECTION) > > void WebPageProxy::detectDataInAllFrames(WebCore::DataDetectorTypes types, CompletionHandler<void(const DataDetectionResult&)>&& completionHandler) >diff --git a/Source/WebKit/UIProcess/WebPageProxy.h b/Source/WebKit/UIProcess/WebPageProxy.h >index cd801b808c4..c666fdb6fb0 100644 >--- a/Source/WebKit/UIProcess/WebPageProxy.h >+++ b/Source/WebKit/UIProcess/WebPageProxy.h >@@ -225,6 +225,7 @@ class NativeWebKeyboardEvent; > class NativeWebMouseEvent; > class NativeWebWheelEvent; > class PageClient; >+class ProvisionalPageProxy; > class RemoteLayerTreeHost; > class RemoteLayerTreeScrollingPerformanceData; > class RemoteLayerTreeTransaction; >@@ -458,8 +459,7 @@ 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(); > > WeakPtr<SecKeyProxyStore> secKeyProxyStore(const WebCore::AuthenticationChallenge&); > >@@ -1025,6 +1025,19 @@ public: > WebProcessProxy& process() { return m_process; } > ProcessID processIdentifier() const; > >+ class PageProcessOverride { >+ public: >+ PageProcessOverride(WebPageProxy&, WebProcessProxy& newProcess); >+ PageProcessOverride(PageProcessOverride&&); >+ ~PageProcessOverride(); >+ >+ private: >+ RefPtr<WebPageProxy> m_page; >+ Ref<WebProcessProxy> m_previousProcess; >+ }; >+ >+ PageProcessOverride temporarilyOverrideProcess(WebProcessProxy& newProcess) { return PageProcessOverride(*this, newProcess); } >+ > WebPreferences& preferences() { return m_preferences; } > void setPreferences(WebPreferences&); > >@@ -1414,6 +1427,21 @@ 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&); >+ >+ void didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&&, URL&& unreachableURL, const UserData&); >+ void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&); >+ void didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest&&, const UserData&); >+ >+ 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); >+ >+ // 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(); >@@ -1438,12 +1466,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; >@@ -1465,12 +1487,9 @@ private: > void didCreateSubframe(uint64_t frameID); > void didCreateWindow(uint64_t frameID, WebCore::GlobalWindowIdentifier&&); > >- void didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&&, URL&& unreachableURL, const UserData&); >- void didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest&&, const UserData&); > void willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay, WebCore::LockBackForwardList); > void didCancelClientRedirectForFrame(uint64_t frameID); > void didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, URL&&); >- void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&); > void didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo&, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData&); > void didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData&); > void didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData&); >@@ -1574,18 +1593,15 @@ 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); >+ void finishAttachingToWebProcess(); > > 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); >@@ -1951,8 +1967,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; >@@ -2322,6 +2336,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 >diff --git a/Source/WebKit/UIProcess/WebProcessProxy.cpp b/Source/WebKit/UIProcess/WebProcessProxy.cpp >index db1fd58b93d..f7dfae8626c 100644 >--- a/Source/WebKit/UIProcess/WebProcessProxy.cpp >+++ b/Source/WebKit/UIProcess/WebProcessProxy.cpp >@@ -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" >@@ -436,7 +437,7 @@ Ref<WebPageProxy> WebProcessProxy::createWebPage(PageClient& pageClient, Ref<API > void WebProcessProxy::addExistingWebPage(WebPageProxy& webPage, uint64_t pageID, BeginsUsingDataStore beginsUsingDataStore) > { > ASSERT(!m_pageMap.contains(pageID)); >- ASSERT(!globalPageMap().contains(pageID)); >+ ASSERT(!globalPageMap().contains(pageID) || globalPageMap().get(pageID) == &webPage); > > if (beginsUsingDataStore == BeginsUsingDataStore::Yes) > m_processPool->pageBeginUsingWebsiteDataStore(webPage); >@@ -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); > } > } >@@ -873,7 +883,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)) >diff --git a/Source/WebKit/UIProcess/WebProcessProxy.h b/Source/WebKit/UIProcess/WebProcessProxy.h >index 75f65a7f7eb..5042630de37 100644 >--- a/Source/WebKit/UIProcess/WebProcessProxy.h >+++ b/Source/WebKit/UIProcess/WebProcessProxy.h >@@ -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; >diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >index 507edb73e74..7079b269885 100644 >--- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj >+++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj >@@ -3095,6 +3095,8 @@ > 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>"; }; >@@ -7350,6 +7352,8 @@ > 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 */, >diff --git a/Source/WebKit/WebProcess/WebPage/WebFrame.cpp b/Source/WebKit/WebProcess/WebPage/WebFrame.cpp >index 00749b477a2..ffed00c8206 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebFrame.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebFrame.cpp >@@ -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) >diff --git a/Source/WebKit/WebProcess/WebPage/WebPage.cpp b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >index 25d6dfb71d0..e4918247a67 100644 >--- a/Source/WebKit/WebProcess/WebPage/WebPage.cpp >+++ b/Source/WebKit/WebProcess/WebPage/WebPage.cpp >@@ -401,7 +401,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); >@@ -471,7 +471,7 @@ WebPage::WebPage(uint64_t pageID, WebPageCreationParameters&& parameters) > m_drawingArea->setPaintingEnabled(false); > m_drawingArea->setShouldScaleViewToFitDocument(parameters.shouldScaleViewToFitDocument); > >- if (parameters.isSwapFromSuspended) >+ if (parameters.isProcessSwap) > freezeLayerTree(LayerTreeFreezeReason::SwapFromSuspended); > > #if ENABLE(ASYNC_SCROLLING) >@@ -696,7 +696,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); > } >@@ -3053,12 +3053,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)); > } > >@@ -6312,6 +6306,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; > } >diff --git a/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm b/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm >index 91ad71ade1b..83b6599270b 100644 >--- a/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm >+++ b/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm >@@ -97,7 +97,7 @@ TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea(WebPage& webPage, c > updateLayerHostingContext(); > setColorSpace(parameters.colorSpace); > >- if (!parameters.isSwapFromSuspended) >+ if (!parameters.isProcessSwap) > attach(); > } > >diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm >index f35d8baa353..50a6628c7df 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm >+++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm >@@ -1405,7 +1405,7 @@ TEST(ProcessSwap, ServerRedirect) > > EXPECT_FALSE(serverRedirected); > EXPECT_EQ(3, numberOfDecidePolicyCalls); >- EXPECT_EQ(2u, seenPIDs.size()); >+ EXPECT_EQ(3u, seenPIDs.size()); > } > > TEST(ProcessSwap, ServerRedirect2) >@@ -1467,6 +1467,66 @@ 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; >+} >+ > enum class ShouldEnablePSON { No, Yes }; > static void runClientSideRedirectTest(ShouldEnablePSON shouldEnablePSON) > { >@@ -2232,12 +2292,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.
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 193361
:
358934
|
358950
|
358953
|
358960
|
358961
|
359047
|
359071
|
359086
|
359088
|
359092
|
359119
|
359163
|
359165
|
359166
|
359168
|
359169
|
359176
|
359256
|
359269
|
359274