Diff
Modified: trunk/Source/WTF/ChangeLog (230639 => 230640)
--- trunk/Source/WTF/ChangeLog 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WTF/ChangeLog 2018-04-13 18:04:22 UTC (rev 230640)
@@ -1,3 +1,14 @@
+2018-04-13 Brady Eidson <beid...@apple.com>
+
+ Introduce SuspendedPageProxy to keep old web processes around after their WebPageProxy has been swapped to a new one.
+ https://bugs.webkit.org/show_bug.cgi?id=184559
+
+ Reviewed by Alex Christensen.
+
+ * wtf/DebugUtilities.h:
+ (WTF::debugString): Add a debug utility to easily construct a "const char*" that is released after a spin of the run loop.
+ This greatly eases uses our String classes and functions inside of "%s" style environments like printf and LOG.
+
2018-04-12 Michael Catanzaro <mcatanz...@igalia.com>
Remove unused crash hook functionality
Modified: trunk/Source/WTF/wtf/DebugUtilities.h (230639 => 230640)
--- trunk/Source/WTF/wtf/DebugUtilities.h 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WTF/wtf/DebugUtilities.h 2018-04-13 18:04:22 UTC (rev 230640)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,11 +23,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef WTF_DebugUtilities_h
-#define WTF_DebugUtilities_h
+#pragma once
#include <wtf/Assertions.h>
#include <wtf/ProcessID.h>
+#include <wtf/text/StringConcatenate.h>
#define SLEEP_THREAD_FOR_DEBUGGER() \
do { \
@@ -40,4 +40,24 @@
WTFBreakpointTrap(); \
} while (0)
-#endif /* WTF_DebugUtilities_h */
+namespace WTF {
+
+template<typename... StringTypes>
+const char* debugString(StringTypes... strings)
+{
+ String result = tryMakeString(strings...);
+ if (!result)
+ CRASH();
+
+ auto cString = result.utf8();
+ const char* cStringData = cString.data();
+
+ callOnMainThread([cString = WTFMove(cString)] {
+ });
+
+ return cStringData;
+}
+
+} // namespace WTF
+
+using WTF::debugString;
Modified: trunk/Source/WebCore/ChangeLog (230639 => 230640)
--- trunk/Source/WebCore/ChangeLog 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebCore/ChangeLog 2018-04-13 18:04:22 UTC (rev 230640)
@@ -1,3 +1,24 @@
+2018-04-13 Brady Eidson <beid...@apple.com>
+
+ Introduce SuspendedPageProxy to keep old web processes around after their WebPageProxy has been swapped to a new one.
+ https://bugs.webkit.org/show_bug.cgi?id=184559
+
+ Reviewed by Alex Christensen.
+
+ Covered by new API test.
+
+ WebCore changes rework the meaning of a "ForSuspension" policy to simply navigate the page to about:blank.
+
+ * loader/DocumentLoader.cpp:
+ (WebCore::DocumentLoader::redirectReceived):
+ (WebCore::DocumentLoader::willSendRequest):
+ (WebCore::DocumentLoader::startLoadingMainResource):
+ * loader/DocumentLoader.h:
+
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::init):
+ (WebCore::FrameLoader::continueLoadAfterNavigationPolicy):
+
2018-04-13 Chris Dumez <cdu...@apple.com>
input.webkitEntries does not work as expected when folder contains accented chars
Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (230639 => 230640)
--- trunk/Source/WebCore/loader/DocumentLoader.cpp 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp 2018-04-13 18:04:22 UTC (rev 230640)
@@ -519,7 +519,7 @@
ASSERT_UNUSED(resource, &resource == m_mainResource);
#if ENABLE(SERVICE_WORKER)
bool isRedirectionFromServiceWorker = redirectResponse.source() == ResourceResponse::Source::ServiceWorker;
- willSendRequest(WTFMove(request), redirectResponse, [isRedirectionFromServiceWorker, completionHandler = WTFMove(completionHandler), protectedThis = makeRef(*this), this] (auto&& request) mutable {
+ willSendRequest(WTFMove(request), redirectResponse, ShouldContinue::Yes, [isRedirectionFromServiceWorker, completionHandler = WTFMove(completionHandler), protectedThis = makeRef(*this), this] (auto&& request) mutable {
ASSERT(!m_substituteData.isValid());
if (request.isNull() || !m_mainDocumentError.isNull() || !m_frame) {
completionHandler({ });
@@ -552,11 +552,11 @@
});
});
#else
- willSendRequest(WTFMove(request), redirectResponse, WTFMove(completionHandler));
+ willSendRequest(WTFMove(request), redirectResponse, ShouldContinue::Yes, WTFMove(completionHandler));
#endif
}
-void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const ResourceResponse& redirectResponse, CompletionHandler<void(ResourceRequest&&)>&& completionHandler)
+void DocumentLoader::willSendRequest(ResourceRequest&& newRequest, const ResourceResponse& redirectResponse, ShouldContinue shouldContinue, CompletionHandler<void(ResourceRequest&&)>&& completionHandler)
{
// Note that there are no asserts here as there are for the other callbacks. This is due to the
// fact that this "callback" is sent when starting every load, and the state of callback
@@ -564,6 +564,8 @@
// callbacks is meant to prevent.
ASSERT(!newRequest.isNull());
+ ASSERT(shouldContinue != ShouldContinue::No);
+
bool didReceiveRedirectResponse = !redirectResponse.isNull();
if (!frameLoader()->checkIfFormActionAllowedByCSP(newRequest.url(), didReceiveRedirectResponse)) {
cancelMainResourceLoad(frameLoader()->cancelledError(newRequest));
@@ -630,21 +632,16 @@
setRequest(newRequest);
- // FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate
- // listener. But there's no way to do that in practice. So instead we cancel later if the
- // listener tells us to. In practice that means the navigation policy needs to be decided
- // synchronously for these redirect cases.
- if (!didReceiveRedirectResponse)
+ if (!didReceiveRedirectResponse && shouldContinue != ShouldContinue::ForSuspension)
return completionHandler(WTFMove(newRequest));
- ASSERT(!m_waitingForNavigationPolicy);
- m_waitingForNavigationPolicy = true;
- frameLoader()->policyChecker().checkNavigationPolicy(ResourceRequest(newRequest), didReceiveRedirectResponse, [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (ResourceRequest&& request, FormState*, ShouldContinue shouldContinue) mutable {
+ auto navigationPolicyCompletionHandler = [this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (ResourceRequest&& request, FormState*, ShouldContinue shouldContinue) mutable {
m_waitingForNavigationPolicy = false;
switch (shouldContinue) {
case ShouldContinue::ForSuspension:
- FALLTHROUGH;
- // FIXME: Setup this page for suspension (e.g. Page Cache) here.
+ // We handle suspension by navigating forward to about:blank, which leaves us setup to navigate back to resume.
+ request = { blankURL() };
+ break;
case ShouldContinue::No:
stopLoadingForPolicyChange();
break;
@@ -653,7 +650,17 @@
}
completionHandler(WTFMove(request));
- });
+ };
+
+ ASSERT(!m_waitingForNavigationPolicy);
+ m_waitingForNavigationPolicy = true;
+
+ if (shouldContinue == ShouldContinue::ForSuspension) {
+ navigationPolicyCompletionHandler(WTFMove(newRequest), nullptr, shouldContinue);
+ return;
+ }
+
+ frameLoader()->policyChecker().checkNavigationPolicy(ResourceRequest(newRequest), didReceiveRedirectResponse, WTFMove(navigationPolicyCompletionHandler));
}
bool DocumentLoader::tryLoadingRequestFromApplicationCache()
@@ -1655,8 +1662,10 @@
return true;
}
-void DocumentLoader::startLoadingMainResource()
+void DocumentLoader::startLoadingMainResource(ShouldContinue shouldContinue)
{
+ ASSERT(shouldContinue != ShouldContinue::No);
+
m_mainDocumentError = ResourceError();
timing().markStartTimeAndFetchStart();
ASSERT(!m_mainResource);
@@ -1681,7 +1690,7 @@
ASSERT(timing().startTime());
ASSERT(timing().fetchStart());
- willSendRequest(ResourceRequest(m_request), ResourceResponse(), [this, protectedThis = makeRef(*this)] (ResourceRequest&& request) mutable {
+ willSendRequest(ResourceRequest(m_request), ResourceResponse(), shouldContinue, [this, protectedThis = makeRef(*this)] (ResourceRequest&& request) mutable {
m_request = request;
// willSendRequest() may lead to our Frame being detached or cancelling the load via nulling the ResourceRequest.
Modified: trunk/Source/WebCore/loader/DocumentLoader.h (230639 => 230640)
--- trunk/Source/WebCore/loader/DocumentLoader.h 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebCore/loader/DocumentLoader.h 2018-04-13 18:04:22 UTC (rev 230640)
@@ -84,6 +84,8 @@
class SubresourceLoader;
class SubstituteResource;
+enum class ShouldContinue;
+
using ResourceLoaderMap = HashMap<unsigned long, RefPtr<ResourceLoader>>;
enum class AutoplayPolicy {
@@ -237,7 +239,7 @@
void setDefersLoading(bool);
void setMainResourceDataBufferingPolicy(DataBufferingPolicy);
- void startLoadingMainResource();
+ void startLoadingMainResource(ShouldContinue);
WEBCORE_EXPORT void cancelMainResourceLoad(const ResourceError&);
void willContinueMainResourceLoadAfterRedirect(const ResourceRequest&);
@@ -351,7 +353,7 @@
void clearArchiveResources();
#endif
- void willSendRequest(ResourceRequest&&, const ResourceResponse&, CompletionHandler<void(ResourceRequest&&)>&&);
+ void willSendRequest(ResourceRequest&&, const ResourceResponse&, ShouldContinue, CompletionHandler<void(ResourceRequest&&)>&&);
void finishedLoading();
void mainReceivedError(const ResourceError&);
WEBCORE_EXPORT void redirectReceived(CachedResource&, ResourceRequest&&, const ResourceResponse&, CompletionHandler<void(ResourceRequest&&)>&&) override;
Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (230639 => 230640)
--- trunk/Source/WebCore/loader/FrameLoader.cpp 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp 2018-04-13 18:04:22 UTC (rev 230640)
@@ -306,7 +306,7 @@
// This somewhat odd set of steps gives the frame an initial empty document.
setPolicyDocumentLoader(m_client.createDocumentLoader(ResourceRequest(URL(ParsedURLString, emptyString())), SubstituteData()).ptr());
setProvisionalDocumentLoader(m_policyDocumentLoader.get());
- m_provisionalDocumentLoader->startLoadingMainResource();
+ m_provisionalDocumentLoader->startLoadingMainResource(ShouldContinue::Yes);
Ref<Frame> protect(m_frame);
m_frame.document()->cancelParsing();
@@ -3231,7 +3231,7 @@
diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultFail, ShouldSample::Yes);
}
- WTF::Function<void(void)> completionHandler = [this] {
+ CompletionHandler<void(void)> completionHandler = [this, shouldContinue] {
if (!m_provisionalDocumentLoader)
return;
@@ -3251,7 +3251,12 @@
}
m_loadingFromCachedPage = false;
- m_provisionalDocumentLoader->startLoadingMainResource();
+
+ // We handle suspension by navigating forward to about:blank, which leaves us setup to navigate back to resume.
+ if (shouldContinue == ShouldContinue::ForSuspension)
+ m_provisionalDocumentLoader->willContinueMainResourceLoadAfterRedirect({ blankURL() });
+
+ m_provisionalDocumentLoader->startLoadingMainResource(shouldContinue);
};
if (!formState) {
Modified: trunk/Source/WebKit/ChangeLog (230639 => 230640)
--- trunk/Source/WebKit/ChangeLog 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/ChangeLog 2018-04-13 18:04:22 UTC (rev 230640)
@@ -1,3 +1,76 @@
+2018-04-13 Brady Eidson <beid...@apple.com>
+
+ Introduce SuspendedPageProxy to keep old web processes around after their WebPageProxy has been swapped to a new one.
+ https://bugs.webkit.org/show_bug.cgi?id=184559
+
+ Reviewed by Alex Christensen.
+
+ Before this patch, when a WebPageProxy navigates and is swapped to a new process, the old process almost always goes away.
+
+ This is not desirable for a few reasons:
+ 1 - We can't keep the PageCache working for back/forward scenarios
+ 2 - We throw away a "foo.com" web process, meaning the next time we need to host a "foo.com" web page we have to launch
+ and initialize a new web process.
+
+ This patch adds a SuspendedPageProxy object to keep around the old web process and to manage communication with it.
+
+ For now, a WebPageProxy keeps exactly one "suspended page" representing the most recently visited page and its process.
+ Additionally, that process is never reused.
+
+ So no benefit is achieved with this patch, but it enables future benefits.
+
+ * Platform/Logging.h:
+
+ * Shared/WebBackForwardListItem.cpp:
+ (WebKit::WebBackForwardListItem::setSuspendedPage):
+ * Shared/WebBackForwardListItem.h:
+
+ New object to represent the state of a WebPageProxy in an old web process that is not currently hosting the view.
+ * UIProcess/SuspendedPageProxy.cpp: Added.
+ (WebKit::SuspendedPageProxy::SuspendedPageProxy):
+ (WebKit::SuspendedPageProxy::~SuspendedPageProxy):
+ (WebKit::SuspendedPageProxy::webProcessDidClose):
+ (WebKit::SuspendedPageProxy::didFinishLoad):
+ (WebKit::SuspendedPageProxy::didReceiveMessage):
+ (WebKit::SuspendedPageProxy::loggingString const):
+ * UIProcess/SuspendedPageProxy.h: Copied from Source/WebKit/Platform/Logging.h.
+ (WebKit::SuspendedPageProxy::create):
+ (WebKit::SuspendedPageProxy::page const):
+ (WebKit::SuspendedPageProxy::process const):
+ (WebKit::SuspendedPageProxy::item const):
+ (WebKit::SuspendedPageProxy::finishedSuspending const):
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::reattachToWebProcess):
+ (WebKit::WebPageProxy::attachToProcessForNavigation):
+ (WebKit::WebPageProxy::maybeCreateSuspendedPage):
+ (WebKit::WebPageProxy::suspendedPageProcessClosed):
+ (WebKit::WebPageProxy::receivedPolicyDecision):
+ (WebKit::WebPageProxy::didFinishLoadForFrame):
+ * UIProcess/WebPageProxy.h:
+
+ * UIProcess/WebProcessProxy.cpp:
+ (WebKit::WebProcessProxy::suspendWebPageProxy):
+ (WebKit::WebProcessProxy::suspendedPageWasDestroyed):
+ (WebKit::WebProcessProxy::removeWebPage):
+ (WebKit::WebProcessProxy::didReceiveMessage): Optionally pass WebPageProxy messages along to SuspendedPageProxy objects.
+ (WebKit::WebProcessProxy::didClose):
+ (WebKit::WebProcessProxy::maybeShutDown):
+ (WebKit::WebProcessProxy::canTerminateChildProcess): Don't terminate child processes if they still have suspended pages.
+ * UIProcess/WebProcessProxy.h:
+
+ * WebKit.xcodeproj/project.pbxproj:
+
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::setIsSuspended):
+ * WebProcess/WebPage/WebPage.h:
+ (WebKit::WebPage::isSuspended const): For now, used only by WebProcess::updateActivePages. Will have more uses soon.
+ * WebProcess/WebPage/WebPage.messages.in:
+
+ * WebProcess/WebProcess.messages.in:
+ * WebProcess/cocoa/WebProcessCocoa.mm:
+ (WebKit::WebProcess::updateActivePages): Allow the UIProcess to request an update of the web processes user visible name.
+
2018-04-13 Daniel Bates <daba...@apple.com>
Inline NetworkLoad::sharedWillSendRedirectedRequest() into NetworkLoad::willPerformHTTPRedirection()
Modified: trunk/Source/WebKit/Platform/Logging.h (230639 => 230640)
--- trunk/Source/WebKit/Platform/Logging.h 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/Platform/Logging.h 2018-04-13 18:04:22 UTC (rev 230640)
@@ -62,6 +62,7 @@
M(Printing) \
M(Process) \
M(ProcessSuspension) \
+ M(ProcessSwapping) \
M(RemoteLayerTree) \
M(Resize) \
M(ResourceLoadStatistics) \
Modified: trunk/Source/WebKit/Shared/WebBackForwardListItem.cpp (230639 => 230640)
--- trunk/Source/WebKit/Shared/WebBackForwardListItem.cpp 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/Shared/WebBackForwardListItem.cpp 2018-04-13 18:04:22 UTC (rev 230640)
@@ -103,4 +103,9 @@
return highestItemID;
}
+void WebBackForwardListItem::setSuspendedPage(SuspendedPageProxy& page)
+{
+ m_suspendedPage = &page;
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/Shared/WebBackForwardListItem.h (230639 => 230640)
--- trunk/Source/WebKit/Shared/WebBackForwardListItem.h 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/Shared/WebBackForwardListItem.h 2018-04-13 18:04:22 UTC (rev 230640)
@@ -41,6 +41,8 @@
namespace WebKit {
+class SuspendedPageProxy;
+
class WebBackForwardListItem : public API::ObjectImpl<API::Object::Type::BackForwardListItem> {
public:
static Ref<WebBackForwardListItem> create(BackForwardListItemState&&, uint64_t pageID);
@@ -63,6 +65,7 @@
ViewSnapshot* snapshot() const { return m_itemState.snapshot.get(); }
void setSnapshot(RefPtr<ViewSnapshot>&& snapshot) { m_itemState.snapshot = WTFMove(snapshot); }
#endif
+ void setSuspendedPage(SuspendedPageProxy&);
static uint64_t highestUsedItemID();
@@ -71,6 +74,7 @@
BackForwardListItemState m_itemState;
uint64_t m_pageID;
+ SuspendedPageProxy* m_suspendedPage { nullptr };
};
typedef Vector<Ref<WebBackForwardListItem>> BackForwardListItemVector;
Added: trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp (0 => 230640)
--- trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp (rev 0)
+++ trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp 2018-04-13 18:04:22 UTC (rev 230640)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2018 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 "SuspendedPageProxy.h"
+
+#include "Logging.h"
+#include "WebPageMessages.h"
+#include "WebPageProxy.h"
+#include "WebPageProxyMessages.h"
+#include "WebProcessMessages.h"
+#include "WebProcessProxy.h"
+#include <wtf/DebugUtilities.h>
+
+namespace WebKit {
+
+#if !LOG_DISABLED
+static const HashSet<IPC::StringReference>& messageNamesToIgnoreWhileSuspended()
+{
+ static NeverDestroyed<HashSet<IPC::StringReference>> messageNames;
+ static std::once_flag onceFlag;
+ std::call_once(onceFlag, [] {
+ messageNames.get().add("BackForwardAddItem");
+ messageNames.get().add("ClearAllEditCommands");
+ messageNames.get().add("DidChangeContentSize");
+ messageNames.get().add("DidChangeMainDocument");
+ messageNames.get().add("DidChangeProgress");
+ messageNames.get().add("DidCommitLoadForFrame");
+ messageNames.get().add("DidDestroyNavigation");
+ messageNames.get().add("DidFinishDocumentLoadForFrame");
+ messageNames.get().add("DidFinishProgress");
+ messageNames.get().add("DidFirstLayoutForFrame");
+ messageNames.get().add("DidFirstVisuallyNonEmptyLayoutForFrame");
+ messageNames.get().add("DidNavigateWithNavigationData");
+ messageNames.get().add("DidReachLayoutMilestone");
+ messageNames.get().add("DidSaveToPageCache");
+ messageNames.get().add("DidStartProgress");
+ messageNames.get().add("DidStartProvisionalLoadForFrame");
+ messageNames.get().add("EditorStateChanged");
+ messageNames.get().add("PageExtendedBackgroundColorDidChange");
+ messageNames.get().add("SetRenderTreeSize");
+ messageNames.get().add("SetStatusText");
+ });
+
+ return messageNames;
+}
+#endif
+
+SuspendedPageProxy::SuspendedPageProxy(WebPageProxy& page, WebProcessProxy& process, WebBackForwardListItem& item)
+ : m_page(page)
+ , m_process(&process)
+ , m_backForwardListItem(item)
+{
+ m_backForwardListItem->setSuspendedPage(*this);
+ m_process->send(Messages::WebPage::SetIsSuspended(true), m_page.pageID());
+}
+
+SuspendedPageProxy::~SuspendedPageProxy()
+{
+ if (m_process)
+ m_process->suspendedPageWasDestroyed(*this);
+}
+
+void SuspendedPageProxy::webProcessDidClose(WebProcessProxy& process)
+{
+ ASSERT_UNUSED(process, &process == m_process);
+ m_process = nullptr;
+
+ m_page.suspendedPageProcessClosed(*this);
+}
+
+void SuspendedPageProxy::didFinishLoad()
+{
+ ASSERT(m_process);
+ LOG(ProcessSwapping, "SuspendedPageProxy %s from process %i finished transition to suspended", loggingString(), m_process->processIdentifier());
+
+ m_finishedSuspending = true;
+
+ m_process->send(Messages::WebProcess::UpdateActivePages(), 0);
+}
+
+void SuspendedPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder& decoder)
+{
+ ASSERT(decoder.messageReceiverName() == Messages::WebPageProxy::messageReceiverName());
+
+ if (decoder.messageName() == Messages::WebPageProxy::DidFinishLoadForFrame::name()) {
+ didFinishLoad();
+ return;
+ }
+#if !LOG_DISABLED
+ if (messageNamesToIgnoreWhileSuspended().contains(decoder.messageName()))
+ LOG(ProcessSwapping, "SuspendedPageProxy received unexpected WebPageProxy message '%s'", decoder.messageName().toString().data());
+#endif
+}
+
+#if !LOG_DISABLED
+const char* SuspendedPageProxy::loggingString() const
+{
+ return debugString("(", String::format("%p", this), "page ID ", String::number(m_page.pageID()), ", m_finishedSuspending ", String::number(m_finishedSuspending), ")");
+}
+#endif
+
+} // namespace WebKit
Copied: trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h (from rev 230639, trunk/Source/WebKit/Platform/Logging.h) (0 => 230640)
--- trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h (rev 0)
+++ trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h 2018-04-13 18:04:22 UTC (rev 230640)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 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 "Connection.h"
+#include "WebBackForwardListItem.h"
+#include <wtf/RefCounted.h>
+
+namespace WebKit {
+
+class WebPageProxy;
+class WebProcessProxy;
+
+class SuspendedPageProxy : public RefCounted<SuspendedPageProxy> {
+public:
+ static Ref<SuspendedPageProxy> create(WebPageProxy& page, WebProcessProxy& process, WebBackForwardListItem& item)
+ {
+ return adoptRef(*new SuspendedPageProxy(page, process, item));
+ }
+
+ virtual ~SuspendedPageProxy();
+
+ void didReceiveMessage(IPC::Connection&, IPC::Decoder&);
+
+ WebPageProxy& page() const { return m_page; }
+ WebProcessProxy* process() const { return m_process; }
+ WebBackForwardListItem& item() const { return m_backForwardListItem; }
+
+ bool finishedSuspending() const { return m_finishedSuspending; }
+
+ void webProcessDidClose(WebProcessProxy&);
+
+#if !LOG_DISABLED
+ const char* loggingString() const;
+#endif
+
+private:
+ SuspendedPageProxy(WebPageProxy&, WebProcessProxy&, WebBackForwardListItem&);
+
+ void didFinishLoad();
+
+ WebPageProxy& m_page;
+ WebProcessProxy* m_process;
+ Ref<WebBackForwardListItem> m_backForwardListItem;
+
+ bool m_finishedSuspending { false };
+};
+
+} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (230639 => 230640)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-04-13 18:04:22 UTC (rev 230640)
@@ -642,7 +642,7 @@
void WebPageProxy::reattachToWebProcess()
{
auto process = makeRef(m_process->processPool().createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get()));
- reattachToWebProcess(WTFMove(process));
+ reattachToWebProcess(WTFMove(process), false);
}
void WebPageProxy::attachToProcessForNavigation(Ref<WebProcessProxy>&& process)
@@ -653,18 +653,45 @@
// FIXME: this is to fix the ASSERT(isValid()) inside reattachToWebProcess, some other way to fix this is needed.
m_isValid = false;
- reattachToWebProcess(WTFMove(process));
+ reattachToWebProcess(WTFMove(process), true);
}
-void WebPageProxy::reattachToWebProcess(Ref<WebProcessProxy>&& process)
+SuspendedPageProxy* WebPageProxy::maybeCreateSuspendedPage(WebProcessProxy& process)
{
+ ASSERT(!m_suspendedPage || m_suspendedPage->process() != &process);
+
+ auto* currentItem = m_backForwardList->currentItem();
+ if (!currentItem) {
+ LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " unable to create suspended page for process pid %i - No current back/forward item", pageID(), process.processIdentifier());
+ return nullptr;
+ }
+
+ m_suspendedPage = SuspendedPageProxy::create(*this, process, *currentItem);
+
+ LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " created suspended page %s for process pid %i, back/forward item %" PRIu64, pageID(), m_suspendedPage->loggingString(), process.processIdentifier(), currentItem->itemID());
+
+ return m_suspendedPage.get();
+}
+
+void WebPageProxy::suspendedPageProcessClosed(SuspendedPageProxy& page)
+{
+ ASSERT_UNUSED(page, &page == m_suspendedPage.get());
+ m_suspendedPage = nullptr;
+}
+
+void WebPageProxy::reattachToWebProcess(Ref<WebProcessProxy>&& process, bool suspendInOldProcess)
+{
ASSERT(!m_isClosed);
ASSERT(!isValid());
m_isValid = true;
- m_process->removeWebPage(*this, m_pageID);
- m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
+ if (!suspendInOldProcess) {
+ m_process->removeWebPage(*this, m_pageID);
+ m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
+ } else
+ m_process->suspendWebPageProxy(*this);
+
m_process = WTFMove(process);
ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
@@ -2354,7 +2381,7 @@
auto proposedProcess = process().processPool().processForNavigation(*this, *navigation, action);
if (proposedProcess.ptr() != &process()) {
- LOG(Loading, "Switching from process %i to new process for navigation %" PRIu64 " '%s'", processIdentifier(), navigation->navigationID(), navigation->loggingString().utf8().data());
+ LOG(ProcessSwapping, "Switching from process %i to new process for navigation %" PRIu64 " '%s'", processIdentifier(), navigation->navigationID(), navigation->loggingString().utf8().data());
RunLoop::main().dispatch([this, protectedThis = makeRef(*this), navigation = makeRef(*navigation), proposedProcess = WTFMove(proposedProcess)]() mutable {
continueNavigationInNewProcess(navigation.get(), WTFMove(proposedProcess));
@@ -3571,6 +3598,8 @@
void WebPageProxy::didFinishLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData& userData)
{
+ LOG(Loading, "WebPageProxy::didFinishLoadForFrame - WebPageProxy %p with navigationID %llu didFinishLoad", this, navigationID);
+
PageClientProtector protector(m_pageClient);
WebFrameProxy* frame = m_process->webFrame(frameID);
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (230639 => 230640)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-04-13 18:04:22 UTC (rev 230640)
@@ -44,6 +44,7 @@
#include "ProcessThrottler.h"
#include "SandboxExtension.h"
#include "ShareableBitmap.h"
+#include "SuspendedPageProxy.h"
#include "SystemPreviewController.h"
#include "UserMediaPermissionRequestManagerProxy.h"
#include "VisibleContentRectUpdateInfo.h"
@@ -1286,6 +1287,9 @@
WebPreferencesStore preferencesStore() const;
+ SuspendedPageProxy* maybeCreateSuspendedPage(WebProcessProxy&);
+ void suspendedPageProcessClosed(SuspendedPageProxy&);
+
private:
WebPageProxy(PageClient&, WebProcessProxy&, uint64_t pageID, Ref<API::PageConfiguration>&&);
void platformInitialize();
@@ -1436,7 +1440,7 @@
void reattachToWebProcess();
void attachToProcessForNavigation(Ref<WebProcessProxy>&&);
- void reattachToWebProcess(Ref<WebProcessProxy>&&);
+ void reattachToWebProcess(Ref<WebProcessProxy>&&, bool suspendInOldProcess);
RefPtr<API::Navigation> reattachToWebProcessForReload();
RefPtr<API::Navigation> reattachToWebProcessWithItem(WebBackForwardListItem&);
@@ -2129,6 +2133,11 @@
#endif
std::optional<MonotonicTime> m_pageLoadStart;
+
+ // FIXME: Support more than one suspended page per WebPageProxy,
+ // and have a global collection of them per process pool
+ // (e.g. for that process pool's page cache)
+ RefPtr<SuspendedPageProxy> m_suspendedPage;
};
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp (230639 => 230640)
--- trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp 2018-04-13 18:04:22 UTC (rev 230640)
@@ -34,6 +34,7 @@
#include "Logging.h"
#include "PluginInfoStore.h"
#include "PluginProcessManager.h"
+#include "SuspendedPageProxy.h"
#include "TextChecker.h"
#include "TextCheckerState.h"
#include "UIMessagePortChannelProvider.h"
@@ -395,6 +396,27 @@
updateBackgroundResponsivenessTimer();
}
+void WebProcessProxy::suspendWebPageProxy(WebPageProxy& webPage)
+{
+ if (auto* suspendedPage = webPage.maybeCreateSuspendedPage(*this)) {
+ LOG(ProcessSwapping, "WebProcessProxy pid %i added suspended page %s", processIdentifier(), suspendedPage->loggingString());
+ m_suspendedPageMap.set(webPage.pageID(), suspendedPage);
+ }
+
+ removeWebPage(webPage, webPage.pageID());
+ removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), webPage.pageID());
+}
+
+void WebProcessProxy::suspendedPageWasDestroyed(SuspendedPageProxy& suspendedPage)
+{
+ LOG(ProcessSwapping, "WebProcessProxy pid %i suspended page %s was destroyed", processIdentifier(), suspendedPage.loggingString());
+
+ ASSERT(m_suspendedPageMap.contains(suspendedPage.page().pageID()));
+ m_suspendedPageMap.remove(suspendedPage.page().pageID());
+
+ maybeShutDown();
+}
+
void WebProcessProxy::removeWebPage(WebPageProxy& webPage, uint64_t pageID)
{
auto* removedPage = m_pageMap.take(pageID);
@@ -414,12 +436,7 @@
for (auto itemID : itemIDsToRemove)
m_backForwardListItemMap.remove(itemID);
- // If this was the last WebPage open in that web process, and we have no other reason to keep it alive, let it go.
- // We only allow this when using a network process, as otherwise the WebProcess needs to preserve its session state.
- if (state() == State::Terminated || !canTerminateChildProcess())
- return;
-
- shutDown();
+ maybeShutDown();
}
void WebProcessProxy::addVisitedLinkStore(VisitedLinkStore& store)
@@ -637,6 +654,15 @@
return;
}
+ // WebPageProxy messages are normally handled by the normal "dispatchMessage" up above.
+ // If they were not handled there, then they may potentially be handled by SuspendedPageProxy objects.
+ if (decoder.messageReceiverName() == Messages::WebPageProxy::messageReceiverName()) {
+ if (auto* suspendedPage = m_suspendedPageMap.get(decoder.destinationID())) {
+ suspendedPage->didReceiveMessage(connection, decoder);
+ return;
+ }
+ }
+
// FIXME: Add unhandled message logging.
}
@@ -680,6 +706,10 @@
for (auto& page : pages)
page->processDidTerminate(ProcessTerminationReason::Crash);
+ for (auto* suspendedPage : copyToVectorOf<SuspendedPageProxy*>(m_suspendedPageMap.values()))
+ suspendedPage->webProcessDidClose(*this);
+
+ m_suspendedPageMap.clear();
}
void WebProcessProxy::didReceiveInvalidMessage(IPC::Connection& connection, IPC::StringReference messageReceiverName, IPC::StringReference messageName)
@@ -827,9 +857,17 @@
m_userInitiatedActionMap.remove(identifier);
}
+void WebProcessProxy::maybeShutDown()
+{
+ if (state() == State::Terminated || !canTerminateChildProcess())
+ return;
+
+ shutDown();
+}
+
bool WebProcessProxy::canTerminateChildProcess()
{
- if (!m_pageMap.isEmpty())
+ if (!m_pageMap.isEmpty() || !m_suspendedPageMap.isEmpty())
return false;
if (!m_processPool->shouldTerminate(this))
Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (230639 => 230640)
--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h 2018-04-13 18:04:22 UTC (rev 230640)
@@ -66,6 +66,7 @@
class NetworkProcessProxy;
class ObjCObjectGraph;
class PageClient;
+class SuspendedPageProxy;
class UserMediaCaptureManagerProxy;
class VisitedLinkStore;
class WebBackForwardListItem;
@@ -208,6 +209,9 @@
void didCommitProvisionalLoad() { m_hasCommittedAnyProvisionalLoads = true; }
bool hasCommittedAnyProvisionalLoads() const { return m_hasCommittedAnyProvisionalLoads; }
+ void suspendWebPageProxy(WebPageProxy&);
+ void suspendedPageWasDestroyed(SuspendedPageProxy&);
+
protected:
static uint64_t generatePageID();
WebProcessProxy(WebProcessPool&, WebsiteDataStore&);
@@ -221,6 +225,7 @@
// Called when the web process has crashed or we know that it will terminate soon.
// Will potentially cause the WebProcessProxy object to be freed.
void shutDown();
+ void maybeShutDown();
// IPC message handlers.
void addOrUpdateBackForwardItem(uint64_t itemID, uint64_t pageID, const PageState&);
@@ -298,6 +303,7 @@
HashSet<String> m_localPathsWithAssumedReadAccess;
WebPageProxyMap m_pageMap;
+ HashMap<uint64_t, SuspendedPageProxy*> m_suspendedPageMap;
WebFrameProxyMap m_frameMap;
WebBackForwardListItemMap m_backForwardListItemMap;
UserInitiatedActionMap m_userInitiatedActionMap;
Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (230639 => 230640)
--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj 2018-04-13 18:04:22 UTC (rev 230640)
@@ -1070,6 +1070,7 @@
515BE1B41D5917FF00DD7C68 /* UIGamepad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 515BE1AC1D555C5100DD7C68 /* UIGamepad.cpp */; };
515BE1B51D5917FF00DD7C68 /* UIGamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = 515BE1AD1D555C5100DD7C68 /* UIGamepad.h */; };
515BE1B71D5A94FD00DD7C68 /* UIGamepadProviderMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 515BE1B61D5A94F900DD7C68 /* UIGamepadProviderMac.mm */; };
+ 515C415C207D7CAE00726E02 /* SuspendedPageProxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 515C415A207D74E000726E02 /* SuspendedPageProxy.cpp */; };
515E7727183DD6F60007203F /* AsyncRequest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 515E7725183DD6F60007203F /* AsyncRequest.cpp */; };
515E7728183DD6F60007203F /* AsyncRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 515E7726183DD6F60007203F /* AsyncRequest.h */; };
5160BFE113381DF900918999 /* LoggingFoundation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5160BFE013381DF900918999 /* LoggingFoundation.mm */; };
@@ -3486,6 +3487,8 @@
515BE1B01D59006900DD7C68 /* GamepadData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GamepadData.h; sourceTree = "<group>"; };
515BE1B11D5902B600DD7C68 /* GamepadData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GamepadData.cpp; sourceTree = "<group>"; };
515BE1B61D5A94F900DD7C68 /* UIGamepadProviderMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = UIGamepadProviderMac.mm; path = UIProcess/Gamepad/mac/UIGamepadProviderMac.mm; sourceTree = SOURCE_ROOT; };
+ 515C415A207D74E000726E02 /* SuspendedPageProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SuspendedPageProxy.cpp; sourceTree = "<group>"; };
+ 515C415B207D74E100726E02 /* SuspendedPageProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SuspendedPageProxy.h; sourceTree = "<group>"; };
515E7725183DD6F60007203F /* AsyncRequest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AsyncRequest.cpp; sourceTree = "<group>"; };
515E7726183DD6F60007203F /* AsyncRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncRequest.h; sourceTree = "<group>"; };
5160BFE013381DF900918999 /* LoggingFoundation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LoggingFoundation.mm; sourceTree = "<group>"; };
@@ -7269,6 +7272,8 @@
414DEDD51F9EDDDF0047C40D /* ServiceWorkerProcessProxy.h */,
51A4D5A816CAC4FF000E615E /* StatisticsRequest.cpp */,
514BDED216C98EDD00E4E25E /* StatisticsRequest.h */,
+ 515C415A207D74E000726E02 /* SuspendedPageProxy.cpp */,
+ 515C415B207D74E100726E02 /* SuspendedPageProxy.h */,
318A1F04204F4764003480BC /* SystemPreviewController.cpp */,
3157135D2040A9B20084F9CF /* SystemPreviewController.h */,
1AA417C912C00CCA002BE67B /* TextChecker.h */,
@@ -10893,6 +10898,7 @@
5118E9AC1F295977003EF9F5 /* StorageToWebProcessConnectionMessageReceiver.cpp in Sources */,
1AE00D6B18327C1200087DD7 /* StringReference.cpp in Sources */,
296BD85E15019BC30071F424 /* StringUtilities.mm in Sources */,
+ 515C415C207D7CAE00726E02 /* SuspendedPageProxy.cpp in Sources */,
318A1F05204F4764003480BC /* SystemPreviewController.cpp in Sources */,
3157135E2040A9B20084F9CF /* SystemPreviewControllerCocoa.mm in Sources */,
1ZZ417EF12C00D87002BE67B /* TextCheckerCompletion.cpp in Sources */,
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (230639 => 230640)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2018-04-13 18:04:22 UTC (rev 230640)
@@ -5866,6 +5866,11 @@
handler->taskDidComplete(taskIdentifier, error);
}
+void WebPage::setIsSuspended(bool suspended)
+{
+ m_isSuspended = suspended;
+}
+
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
static uint64_t nextRequestStorageAccessContextId()
{
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (230639 => 230640)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2018-04-13 18:04:22 UTC (rev 230640)
@@ -1072,6 +1072,8 @@
UserContentControllerIdentifier userContentControllerIdentifier() const { return m_userContentController->identifier(); }
+ bool isSuspended() const { return m_isSuspended; }
+
private:
WebPage(uint64_t pageID, WebPageCreationParameters&&);
@@ -1388,6 +1390,8 @@
void urlSchemeTaskDidReceiveData(uint64_t handlerIdentifier, uint64_t taskIdentifier, const IPC::DataReference&);
void urlSchemeTaskDidComplete(uint64_t handlerIdentifier, uint64_t taskIdentifier, const WebCore::ResourceError&);
+ void setIsSuspended(bool);
+
RefPtr<WebImage> snapshotAtSize(const WebCore::IntRect&, const WebCore::IntSize& bitmapSize, SnapshotOptions);
RefPtr<WebImage> snapshotNode(WebCore::Node&, SnapshotOptions, unsigned maximumPixelCount = std::numeric_limits<unsigned>::max());
#if USE(CF)
@@ -1705,6 +1709,7 @@
std::unique_ptr<WebCredentialsMessenger> m_credentialsMessenger;
#endif
+ bool m_isSuspended { false };
};
} // namespace WebKit
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (230639 => 230640)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2018-04-13 18:04:22 UTC (rev 230640)
@@ -491,6 +491,8 @@
URLSchemeTaskDidReceiveData(uint64_t handlerIdentifier, uint64_t taskIdentifier, IPC::DataReference data)
URLSchemeTaskDidComplete(uint64_t handlerIdentifier, uint64_t taskIdentifier, WebCore::ResourceError error)
+ SetIsSuspended(bool suspended)
+
#if HAVE(CFNETWORK_STORAGE_PARTITIONING)
StorageAccessResponse(bool wasGranted, uint64_t contextId)
#endif
Modified: trunk/Source/WebKit/WebProcess/WebProcess.messages.in (230639 => 230640)
--- trunk/Source/WebKit/WebProcess/WebProcess.messages.in 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/WebProcess/WebProcess.messages.in 2018-04-13 18:04:22 UTC (rev 230640)
@@ -128,6 +128,8 @@
CheckProcessLocalPortForActivity(struct WebCore::MessagePortIdentifier port, uint64_t callbackIdentifier)
MessagesAvailableForPort(struct WebCore::MessagePortIdentifier port)
+ UpdateActivePages()
+
#if PLATFORM(MAC)
SetScreenProperties(uint32_t primaryScreenID, HashMap<uint32_t, WebCore::ScreenProperties> screenProperties)
#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
Modified: trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm (230639 => 230640)
--- trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm 2018-04-13 18:04:22 UTC (rev 230640)
@@ -387,7 +387,7 @@
auto activePageURLs = adoptNS([[NSMutableArray alloc] init]);
for (auto& page : m_pageMap.values()) {
- if (page->usesEphemeralSession())
+ if (page->usesEphemeralSession() || page->isSuspended())
continue;
if (NSURL *originAsURL = origin(*page))
Modified: trunk/Tools/ChangeLog (230639 => 230640)
--- trunk/Tools/ChangeLog 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Tools/ChangeLog 2018-04-13 18:04:22 UTC (rev 230640)
@@ -1,3 +1,12 @@
+2018-04-13 Brady Eidson <beid...@apple.com>
+
+ Introduce SuspendedPageProxy to keep old web processes around after their WebPageProxy has been swapped to a new one.
+ https://bugs.webkit.org/show_bug.cgi?id=184559
+
+ Reviewed by Alex Christensen.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+
2018-04-13 Chris Dumez <cdu...@apple.com>
input.webkitEntries does not work as expected when folder contains accented chars
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (230639 => 230640)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm 2018-04-13 17:37:31 UTC (rev 230639)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm 2018-04-13 18:04:22 UTC (rev 230640)
@@ -751,4 +751,44 @@
EXPECT_EQ(1u, seenPIDs.size());
}
+TEST(ProcessSwap, OnePreviousProcessRemains)
+{
+ auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+ [processPoolConfiguration setProcessSwapsOnNavigation: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]);
+ [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
+
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+ auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+ [webView setNavigationDelegate:delegate.get()];
+
+ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://host1/main.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://host2/main.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://host3/main.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ // Navigations to 3 different domains, we expect to have seen 3 different PIDs
+ EXPECT_EQ(3u, seenPIDs.size());
+
+ // But only 2 of those processes should still be alive
+ EXPECT_EQ(2u, [processPool _webProcessCount]);
+}
+
#endif // WK_API_ENABLED