Diff
Modified: trunk/Source/WebCore/ChangeLog (229777 => 229778)
--- trunk/Source/WebCore/ChangeLog 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebCore/ChangeLog 2018-03-21 00:05:58 UTC (rev 229778)
@@ -1,3 +1,35 @@
+2018-03-20 Brady Eidson <beid...@apple.com>
+
+ First piece of process swapping on navigation.
+ https://bugs.webkit.org/show_bug.cgi?id=183665
+
+ Reviewed by Andy Estes.
+
+ Covered by API test(s)
+
+ This patch:
+ - A new PolicyAction::Suspend for future use in this feature
+ - Makes sure that loads triggered as part of a process swap do *not* re-consult the policy delegate
+
+ * loader/DocumentLoader.cpp:
+ (WebCore::DocumentLoader::continueAfterContentPolicy):
+
+ * loader/FrameLoadRequest.h:
+ (WebCore::FrameLoadRequest::setShouldCheckNavigationPolicy):
+ (WebCore::FrameLoadRequest::shouldCheckNavigationPolicy const):
+
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::load):
+ (WebCore::FrameLoader::loadWithDocumentLoader):
+ * loader/FrameLoader.h:
+
+ * loader/FrameLoaderTypes.h: Add a new Policy type "Suspend" to be used in the future
+ by the process-swap-on-navigation mechanism.
+
+ * loader/PolicyChecker.cpp:
+ (WebCore::PolicyChecker::checkNavigationPolicy):
+ (WebCore::PolicyChecker::checkNewWindowPolicy):
+
2018-03-20 Chris Dumez <cdu...@apple.com>
QuickLook.NavigationDelegate API test is failing on iOS with async policy delegates
Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (229777 => 229778)
--- trunk/Source/WebCore/loader/DocumentLoader.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -896,6 +896,9 @@
static_cast<ResourceLoader*>(mainResourceLoader())->didFail(interruptedForPolicyChangeError());
return;
}
+ case PolicyAction::Suspend:
+ // It is invalid to get a Suspend policy based on navigation response.
+ RELEASE_ASSERT_NOT_REACHED();
case PolicyAction::Ignore:
if (ResourceLoader* mainResourceLoader = this->mainResourceLoader())
InspectorInstrumentation::continueWithPolicyIgnore(*m_frame, mainResourceLoader->identifier(), *this, m_response);
Modified: trunk/Source/WebCore/loader/FrameLoadRequest.h (229777 => 229778)
--- trunk/Source/WebCore/loader/FrameLoadRequest.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebCore/loader/FrameLoadRequest.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -60,6 +60,9 @@
void setShouldCheckNewWindowPolicy(bool checkPolicy) { m_shouldCheckNewWindowPolicy = checkPolicy; }
bool shouldCheckNewWindowPolicy() const { return m_shouldCheckNewWindowPolicy; }
+ void setShouldCheckNavigationPolicy(bool checkPolicy) { m_shouldCheckNavigationPolicy = checkPolicy; }
+ bool shouldCheckNavigationPolicy() const { return m_shouldCheckNavigationPolicy; }
+
const SubstituteData& substituteData() const { return m_substituteData; }
void setSubstituteData(const SubstituteData& data) { m_substituteData = data; }
bool hasSubstituteData() { return m_substituteData.isValid(); }
@@ -89,6 +92,7 @@
SubstituteData m_substituteData;
bool m_shouldCheckNewWindowPolicy { false };
+ bool m_shouldCheckNavigationPolicy { true };
LockHistory m_lockHistory;
LockBackForwardList m_lockBackForwardList;
ShouldSendReferrer m_shouldSendReferrer;
Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (229777 => 229778)
--- trunk/Source/WebCore/loader/FrameLoader.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -123,6 +123,7 @@
#include "XMLDocumentParser.h"
#include <wtf/CompletionHandler.h>
#include <wtf/Ref.h>
+#include <wtf/SetForScope.h>
#include <wtf/StdLibExtras.h>
#include <wtf/SystemTracing.h>
#include <wtf/text/CString.h>
@@ -1403,6 +1404,7 @@
Ref<DocumentLoader> loader = m_client.createDocumentLoader(request.resourceRequest(), request.substituteData());
applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, request);
+ SetForScope<bool> currentLoadShouldCheckNavigationPolicyGuard(m_currentLoadShouldCheckNavigationPolicy, request.shouldCheckNavigationPolicy());
load(loader.ptr());
}
@@ -1538,6 +1540,11 @@
m_frame.navigationScheduler().cancel(true);
+ if (!m_currentLoadShouldCheckNavigationPolicy) {
+ continueLoadAfterNavigationPolicy(loader->request(), formState, true, allowNavigationToInvalidURL);
+ return;
+ }
+
policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), false /* didReceiveRedirectResponse */, loader, formState, [this, protectedFrame = makeRef(m_frame), allowNavigationToInvalidURL, completionHandler = completionHandlerCaller.release()] (const ResourceRequest& request, FormState* formState, bool shouldContinue) {
continueLoadAfterNavigationPolicy(request, formState, shouldContinue, allowNavigationToInvalidURL);
completionHandler();
Modified: trunk/Source/WebCore/loader/FrameLoader.h (229777 => 229778)
--- trunk/Source/WebCore/loader/FrameLoader.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebCore/loader/FrameLoader.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -461,6 +461,7 @@
std::optional<ResourceRequestCachePolicy> m_overrideCachePolicyForTesting;
std::optional<ResourceLoadPriority> m_overrideResourceLoadPriorityForTesting;
bool m_isStrictRawResourceValidationPolicyDisabledForTesting { false };
+ bool m_currentLoadShouldCheckNavigationPolicy { true };
URL m_previousURL;
RefPtr<HistoryItem> m_requestedHistoryItem;
Modified: trunk/Source/WebCore/loader/FrameLoaderTypes.h (229777 => 229778)
--- trunk/Source/WebCore/loader/FrameLoaderTypes.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebCore/loader/FrameLoaderTypes.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -41,7 +41,8 @@
enum class PolicyAction {
Use,
Download,
- Ignore
+ Ignore,
+ Suspend,
};
enum class ReloadOption {
@@ -158,7 +159,8 @@
WebCore::PolicyAction,
WebCore::PolicyAction::Use,
WebCore::PolicyAction::Download,
- WebCore::PolicyAction::Ignore
+ WebCore::PolicyAction::Ignore,
+ WebCore::PolicyAction::Suspend
>;
};
Modified: trunk/Source/WebCore/loader/PolicyChecker.cpp (229777 => 229778)
--- trunk/Source/WebCore/loader/PolicyChecker.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebCore/loader/PolicyChecker.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -159,6 +159,9 @@
FALLTHROUGH;
case PolicyAction::Ignore:
return function({ }, nullptr, false);
+ case PolicyAction::Suspend:
+ LOG(Loading, "PolicyAction::Suspend encountered - Treating as PolicyAction::Ignore for now");
+ return function({ }, nullptr, false);
case PolicyAction::Use:
if (!m_frame.loader().client().canHandleRequest(request)) {
handleUnimplementablePolicy(m_frame.loader().client().cannotShowURLError(request));
@@ -186,6 +189,9 @@
case PolicyAction::Ignore:
function({ }, nullptr, { }, { }, false);
return;
+ case PolicyAction::Suspend:
+ // It is invalid to get a "Suspend" policy for new windows, as the old document is not going away.
+ RELEASE_ASSERT_NOT_REACHED();
case PolicyAction::Use:
function(request, formState.get(), frameName, navigationAction, true);
return;
Modified: trunk/Source/WebKit/ChangeLog (229777 => 229778)
--- trunk/Source/WebKit/ChangeLog 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/ChangeLog 2018-03-21 00:05:58 UTC (rev 229778)
@@ -1,3 +1,94 @@
+2018-03-20 Brady Eidson <beid...@apple.com>
+
+ First piece of process swapping on navigation.
+ https://bugs.webkit.org/show_bug.cgi?id=183665
+
+ Reviewed by Andy Estes.
+
+ This patch adds the first pieces of the following feature:
+ "When a navigation originating inside a WKWebView goes to a different origin,
+ swap to a new WebProcess for that navigation"
+
+ There are significant bugs to be resolved and significant optimizations to be made.
+ Which is why the feature is disabled by default.
+
+ Besides the core logic implementing the feature, this patch does a lot of related
+ work such as:
+ - Removing some now-invalid ASSERTs
+ - Adding some ASSERTs
+ - Update various switch states to handle the new "Suspend" policy and "NavigationSwap"
+ process termination reason
+
+ * NetworkProcess/NetworkDataTaskBlob.cpp:
+ (WebKit::NetworkDataTaskBlob::dispatchDidReceiveResponse):
+
+ * NetworkProcess/capture/NetworkDataTaskReplay.cpp:
+ (WebKit::NetworkCapture::NetworkDataTaskReplay::didReceiveResponse):
+
+ * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+ (toNSURLSessionResponseDisposition):
+
+ * Platform/Logging.h:
+
+ * Shared/LoadParameters.cpp:
+ (WebKit::LoadParameters::encode const):
+ (WebKit::LoadParameters::decode):
+ * Shared/LoadParameters.h:
+
+ * Shared/ProcessTerminationReason.h: Add "NavigationSwap" as a process termination reason.
+
+ * UIProcess/API/APINavigation.h:
+
+ * UIProcess/API/APIProcessPoolConfiguration.cpp:
+ (API::ProcessPoolConfiguration::copy):
+
+ * UIProcess/API/C/WKAPICast.h:
+ (WebKit::toAPI):
+
+ * UIProcess/Cocoa/NavigationState.mm:
+ (WebKit::wkProcessTerminationReason):
+
+ * UIProcess/WebFramePolicyListenerProxy.cpp:
+ (WebKit::WebFramePolicyListenerProxy::WebFramePolicyListenerProxy):
+ * UIProcess/WebFramePolicyListenerProxy.h:
+ (WebKit::WebFramePolicyListenerProxy::create):
+ (WebKit::WebFramePolicyListenerProxy::policyListenerType const):
+
+ * UIProcess/WebFrameProxy.cpp:
+ (WebKit::WebFrameProxy::setUpPolicyListenerProxy):
+ (WebKit::WebFrameProxy::activePolicyListenerProxy):
+ * UIProcess/WebFrameProxy.h:
+
+ * UIProcess/WebNavigationState.cpp:
+ (WebKit::WebNavigationState::navigation):
+ (WebKit::WebNavigationState::takeNavigation):
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::reattachToWebProcess):
+ (WebKit::WebPageProxy::attachToProcessForNavigation): Pretend that the existing process
+ terminated using the new "NavigationSwap" reason, then manually start the next load.
+ (WebKit::WebPageProxy::loadRequest):
+ (WebKit::WebPageProxy::loadRequestWithNavigation):
+ (WebKit::WebPageProxy::receivedPolicyDecision):
+ (WebKit::WebPageProxy::continueNavigationInNewProcess):
+ (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+ (WebKit::WebPageProxy::decidePolicyForResponse):
+ (WebKit::WebPageProxy::processDidTerminate):
+ (WebKit::WebPageProxy::resetState):
+ (WebKit::WebPageProxy::resetStateAfterProcessExited):
+ * UIProcess/WebPageProxy.h:
+
+ * UIProcess/WebProcessPool.cpp:
+ (WebKit::WebProcessPool::processForNavigation): Determine which process should be used
+ for a proposed navigation, creating a new one if necessary.
+ * UIProcess/WebProcessPool.h:
+
+ * UIProcess/WebStorage/StorageManager.cpp:
+ (WebKit::StorageManager::SessionStorageNamespace::setAllowedConnection):
+
+ * WebProcess/WebPage/WebPage.cpp:
+ (WebKit::WebPage::loadRequest):
+
2018-03-20 Youenn Fablet <you...@apple.com>
ServiceWorkerClientFetch::didReceiveData should check for m_encodedDataLength
Modified: trunk/Source/WebKit/NetworkProcess/NetworkDataTaskBlob.cpp (229777 => 229778)
--- trunk/Source/WebKit/NetworkProcess/NetworkDataTaskBlob.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/NetworkProcess/NetworkDataTaskBlob.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -317,6 +317,9 @@
m_buffer.resize(bufferSize);
read();
break;
+ case PolicyAction::Suspend:
+ LOG_ERROR("PolicyAction::Suspend encountered - Treating as PolicyAction::Ignore for now");
+ FALLTHROUGH;
case PolicyAction::Ignore:
break;
case PolicyAction::Download:
Modified: trunk/Source/WebKit/NetworkProcess/capture/NetworkDataTaskReplay.cpp (229777 => 229778)
--- trunk/Source/WebKit/NetworkProcess/capture/NetworkDataTaskReplay.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/NetworkProcess/capture/NetworkDataTaskReplay.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -252,6 +252,9 @@
case WebCore::PolicyAction::Use:
enqueueEventHandler();
break;
+ case WebCore::PolicyAction::Suspend:
+ LOG_ERROR("PolicyAction::Suspend encountered - Treating as PolicyAction::Ignore for now");
+ FALLTHROUGH;
case WebCore::PolicyAction::Ignore:
complete();
break;
Modified: trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm (229777 => 229778)
--- trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm 2018-03-21 00:05:58 UTC (rev 229778)
@@ -62,6 +62,9 @@
static NSURLSessionResponseDisposition toNSURLSessionResponseDisposition(WebCore::PolicyAction disposition)
{
switch (disposition) {
+ case WebCore::PolicyAction::Suspend:
+ LOG_ERROR("PolicyAction::Suspend encountered - Treating as PolicyAction::Ignore for now");
+ FALLTHROUGH;
case WebCore::PolicyAction::Ignore:
return NSURLSessionResponseCancel;
case WebCore::PolicyAction::Use:
Modified: trunk/Source/WebKit/Platform/Logging.h (229777 => 229778)
--- trunk/Source/WebKit/Platform/Logging.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/Platform/Logging.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -50,6 +50,7 @@
M(IPC) \
M(KeyHandling) \
M(Layers) \
+ M(Loading) \
M(Network) \
M(NetworkCache) \
M(NetworkCacheSpeculativePreloading) \
Modified: trunk/Source/WebKit/Shared/LoadParameters.cpp (229777 => 229778)
--- trunk/Source/WebKit/Shared/LoadParameters.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/Shared/LoadParameters.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -48,6 +48,7 @@
encoder << unreachableURLString;
encoder << provisionalLoadErrorURLString;
encoder << shouldOpenExternalURLsPolicy;
+ encoder << shouldCheckNavigationPolicy;
encoder << userData;
platformEncode(encoder);
@@ -102,6 +103,9 @@
if (!decoder.decode(data.shouldOpenExternalURLsPolicy))
return false;
+ if (!decoder.decode(data.shouldCheckNavigationPolicy))
+ return false;
+
if (!decoder.decode(data.userData))
return false;
Modified: trunk/Source/WebKit/Shared/LoadParameters.h (229777 => 229778)
--- trunk/Source/WebKit/Shared/LoadParameters.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/Shared/LoadParameters.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -62,6 +62,7 @@
String provisionalLoadErrorURLString;
uint64_t shouldOpenExternalURLsPolicy;
+ bool shouldCheckNavigationPolicy { true };
UserData userData;
#if PLATFORM(COCOA)
Modified: trunk/Source/WebKit/Shared/ProcessTerminationReason.h (229777 => 229778)
--- trunk/Source/WebKit/Shared/ProcessTerminationReason.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/Shared/ProcessTerminationReason.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -31,7 +31,8 @@
ExceededMemoryLimit,
ExceededCPULimit,
RequestedByClient,
- Crash
+ Crash,
+ NavigationSwap,
};
}
Modified: trunk/Source/WebKit/UIProcess/API/APINavigation.h (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/API/APINavigation.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/API/APINavigation.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -36,6 +36,7 @@
namespace API {
class Navigation : public ObjectImpl<Object::Type::Navigation> {
+ WTF_MAKE_NONCOPYABLE(Navigation);
public:
static Ref<Navigation> create(WebKit::WebNavigationState& state)
{
@@ -64,7 +65,7 @@
private:
explicit Navigation(WebKit::WebNavigationState&);
- explicit Navigation(WebKit::WebNavigationState&, WebCore::ResourceRequest&&);
+ Navigation(WebKit::WebNavigationState&, WebCore::ResourceRequest&&);
uint64_t m_navigationID;
WebCore::ResourceRequest m_request;
Modified: trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/API/APIProcessPoolConfiguration.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -127,6 +127,7 @@
copy->m_ctDataConnectionServiceType = this->m_ctDataConnectionServiceType;
#endif
copy->m_presentingApplicationPID = this->m_presentingApplicationPID;
+ copy->m_processSwapsOnNavigation = this->m_processSwapsOnNavigation;
return copy;
}
Modified: trunk/Source/WebKit/UIProcess/API/C/WKAPICast.h (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/API/C/WKAPICast.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/API/C/WKAPICast.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -236,6 +236,10 @@
return kWKProcessTerminationReasonExceededMemoryLimit;
case ProcessTerminationReason::ExceededCPULimit:
return kWKProcessTerminationReasonExceededCPULimit;
+ case ProcessTerminationReason::NavigationSwap:
+ // We probably shouldn't bother coming up with a new C-API type for process-swapping.
+ // "Requested by client" seems like the best match for existing types.
+ FALLTHROUGH;
case ProcessTerminationReason::RequestedByClient:
return kWKProcessTerminationReasonRequestedByClient;
case ProcessTerminationReason::Crash:
Modified: trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/Cocoa/NavigationState.mm 2018-03-21 00:05:58 UTC (rev 229778)
@@ -962,6 +962,10 @@
return _WKProcessTerminationReasonExceededMemoryLimit;
case ProcessTerminationReason::ExceededCPULimit:
return _WKProcessTerminationReasonExceededCPULimit;
+ case ProcessTerminationReason::NavigationSwap:
+ // We probably shouldn't bother coming up with a new API type for process-swapping.
+ // "Requested by client" seems like the best match for existing types.
+ FALLTHROUGH;
case ProcessTerminationReason::RequestedByClient:
return _WKProcessTerminationReasonRequestedByClient;
case ProcessTerminationReason::Crash:
Modified: trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.cpp (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -32,8 +32,9 @@
namespace WebKit {
-WebFramePolicyListenerProxy::WebFramePolicyListenerProxy(WebFrameProxy* frame, uint64_t listenerID)
+WebFramePolicyListenerProxy::WebFramePolicyListenerProxy(WebFrameProxy* frame, uint64_t listenerID, PolicyListenerType policyType)
: WebFrameListenerProxy(frame, listenerID)
+ , m_policyType(policyType)
{
}
Modified: trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.h (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -35,13 +35,19 @@
namespace WebKit {
+enum class PolicyListenerType {
+ NavigationAction,
+ NewWindowAction,
+ Response,
+};
+
class WebFramePolicyListenerProxy : public WebFrameListenerProxy {
public:
static const Type APIType = Type::FramePolicyListener;
- static Ref<WebFramePolicyListenerProxy> create(WebFrameProxy* frame, uint64_t listenerID)
+ static Ref<WebFramePolicyListenerProxy> create(WebFrameProxy* frame, uint64_t listenerID, PolicyListenerType policyType)
{
- return adoptRef(*new WebFramePolicyListenerProxy(frame, listenerID));
+ return adoptRef(*new WebFramePolicyListenerProxy(frame, listenerID, policyType));
}
void use(std::optional<WebsitePoliciesData>&&);
@@ -48,8 +54,10 @@
void download();
void ignore();
+ PolicyListenerType policyListenerType() const { return m_policyType; }
+
private:
- WebFramePolicyListenerProxy(WebFrameProxy*, uint64_t listenerID);
+ WebFramePolicyListenerProxy(WebFrameProxy*, uint64_t listenerID, PolicyListenerType);
Type type() const override { return APIType; }
@@ -56,6 +64,8 @@
#if DELEGATE_REF_COUNTING_TO_COCOA
void* operator new(size_t size) { return newObject(size, APIType); }
#endif
+
+ PolicyListenerType m_policyType;
};
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -187,14 +187,22 @@
m_page->receivedPolicyDecision(action, *this, listenerID, navigation, WTFMove(data));
}
-WebFramePolicyListenerProxy& WebFrameProxy::setUpPolicyListenerProxy(uint64_t listenerID)
+WebFramePolicyListenerProxy& WebFrameProxy::setUpPolicyListenerProxy(uint64_t listenerID, PolicyListenerType policyListenerType)
{
if (m_activeListener)
m_activeListener->invalidate();
- m_activeListener = WebFramePolicyListenerProxy::create(this, listenerID);
+ m_activeListener = WebFramePolicyListenerProxy::create(this, listenerID, policyListenerType);
return *static_cast<WebFramePolicyListenerProxy*>(m_activeListener.get());
}
+WebFramePolicyListenerProxy* WebFrameProxy::activePolicyListenerProxy()
+{
+ if (!m_activeListener || m_activeListener->type() != WebFramePolicyListenerProxy::APIType)
+ return nullptr;
+
+ return static_cast<WebFramePolicyListenerProxy*>(m_activeListener.get());
+}
+
void WebFrameProxy::changeWebsiteDataStore(WebsiteDataStore& websiteDataStore)
{
if (!m_page)
Modified: trunk/Source/WebKit/UIProcess/WebFrameProxy.h (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebFrameProxy.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebFrameProxy.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -52,6 +52,7 @@
class WebFramePolicyListenerProxy;
class WebPageProxy;
class WebsiteDataStore;
+enum class PolicyListenerType;
struct WebsitePoliciesData;
typedef GenericCallback<API::Data*> DataCallback;
@@ -116,7 +117,10 @@
// Policy operations.
void receivedPolicyDecision(WebCore::PolicyAction, uint64_t listenerID, API::Navigation*, std::optional<WebsitePoliciesData>&&);
- WebFramePolicyListenerProxy& setUpPolicyListenerProxy(uint64_t listenerID);
+
+ WebFramePolicyListenerProxy& setUpPolicyListenerProxy(uint64_t listenerID, PolicyListenerType);
+ WebFramePolicyListenerProxy* activePolicyListenerProxy();
+
void changeWebsiteDataStore(WebsiteDataStore&);
#if ENABLE(CONTENT_FILTERING)
Modified: trunk/Source/WebKit/UIProcess/WebNavigationState.cpp (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebNavigationState.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebNavigationState.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -79,7 +79,8 @@
API::Navigation& WebNavigationState::navigation(uint64_t navigationID)
{
ASSERT(navigationID);
-
+ ASSERT(m_navigations.contains(navigationID));
+
return *m_navigations.get(navigationID);
}
@@ -86,6 +87,7 @@
Ref<API::Navigation> WebNavigationState::takeNavigation(uint64_t navigationID)
{
ASSERT(navigationID);
+ ASSERT(m_navigations.contains(navigationID));
return m_navigations.take(navigationID).releaseNonNull();
}
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -639,15 +639,31 @@
void WebPageProxy::reattachToWebProcess()
{
+ auto process = makeRef(m_process->processPool().createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get()));
+ reattachToWebProcess(WTFMove(process));
+}
+
+void WebPageProxy::attachToProcessForNavigation(Ref<WebProcessProxy>&& process)
+{
+ // FIXME: If this WebPageProxy is the only one hosted in its WebProcess, does this make it go away?
+ // We need to be prepared to reuse it later.
+ processDidTerminate(ProcessTerminationReason::NavigationSwap);
+
+ // FIXME: this is to fix the ASSERT(isValid()) inside reattachToWebProcess, some other way to fix this is needed.
+ m_isValid = false;
+ reattachToWebProcess(WTFMove(process));
+}
+
+void WebPageProxy::reattachToWebProcess(Ref<WebProcessProxy>&& process)
+{
ASSERT(!m_isClosed);
ASSERT(!isValid());
- ASSERT(m_process->state() == WebProcessProxy::State::Terminated);
m_isValid = true;
m_process->removeWebPage(*this, m_pageID);
m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
- m_process = m_process->processPool().createNewWebProcessRespectingProcessCountLimit(m_websiteDataStore.get());
+ m_process = WTFMove(process);
ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
if (m_process->state() == ChildProcessProxy::State::Running)
@@ -874,7 +890,14 @@
return nullptr;
auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request));
+ loadRequestWithNavigation(navigation.get(), WTFMove(request), shouldOpenExternalURLsPolicy, userData, NavigationPolicyCheck::Require);
+ return WTFMove(navigation);
+}
+void WebPageProxy::loadRequestWithNavigation(API::Navigation& navigation, ResourceRequest&& request, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, API::Object* userData, NavigationPolicyCheck navigationPolicyCheck)
+{
+ ASSERT(!m_isClosed);
+
auto transaction = m_pageLoadState.transaction();
auto url = ""
@@ -884,10 +907,11 @@
reattachToWebProcess();
LoadParameters loadParameters;
- loadParameters.navigationID = navigation->navigationID();
+ loadParameters.navigationID = navigation.navigationID();
loadParameters.request = WTFMove(request);
loadParameters.shouldOpenExternalURLsPolicy = (uint64_t)shouldOpenExternalURLsPolicy;
loadParameters.userData = UserData(process().transformObjectsToHandles(userData).get());
+ loadParameters.shouldCheckNavigationPolicy = navigationPolicyCheck == NavigationPolicyCheck::Require;
bool createdExtension = maybeInitializeSandboxExtensionHandle(url, loadParameters.sandboxExtensionHandle);
if (createdExtension)
m_process->willAcquireUniversalFileReadSandboxExtension();
@@ -895,8 +919,6 @@
m_process->send(Messages::WebPage::LoadRequest(loadParameters), m_pageID);
m_process->responsivenessTimer().start();
-
- return WTFMove(navigation);
}
RefPtr<API::Navigation> WebPageProxy::loadFile(const String& fileURLString, const String& resourceDirectoryURLString, API::Object* userData)
@@ -2355,6 +2377,21 @@
return;
}
+ auto* activePolicyListener = frame.activePolicyListenerProxy();
+ if (activePolicyListener) {
+ ASSERT(activePolicyListener->listenerID() == listenerID);
+
+ if (action == PolicyAction::Use && navigation) {
+ auto proposedProcess = process().processPool().processForNavigation(*this, navigation->request().url());
+ if (proposedProcess.ptr() != &process()) {
+ action = ""
+ RunLoop::main().dispatch([this, protectedThis = makeRef(*this), navigation = makeRef(*navigation), proposedProcess = WTFMove(proposedProcess)]() mutable {
+ continueNavigationInNewProcess(navigation.get(), WTFMove(proposedProcess));
+ });
+ }
+ }
+ }
+
// If we received a policy decision while in decidePolicyForNavigationAction the decision will
// be sent back to the web process by decidePolicyForNavigationAction.
if (m_inDecidePolicyForNavigationAction) {
@@ -2368,6 +2405,16 @@
m_process->send(Messages::WebPage::DidReceivePolicyDecision(frame.frameID(), listenerID, action, navigation ? navigation->navigationID() : 0, downloadID, websitePolicies), m_pageID);
}
+void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, Ref<WebProcessProxy>&& process)
+{
+ LOG(Loading, "Continuing navigation %" PRIu64 " to URL %s in a new web process", navigation.navigationID(), navigation.request().url().string().utf8().data());
+
+ attachToProcessForNavigation(WTFMove(process));
+
+ // FIXME: Work out timing of responding with the last policy delegate, etc
+ loadRequestWithNavigation(navigation, ResourceRequest { navigation.request() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, NavigationPolicyCheck::Bypass);
+}
+
void WebPageProxy::setUserAgent(String&& userAgent)
{
if (m_userAgent == userAgent)
@@ -3768,6 +3815,8 @@
void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, NavigationActionData&& navigationActionData, const FrameInfoData& originatingFrameInfoData, uint64_t originatingPageID, const WebCore::ResourceRequest& originalRequest, ResourceRequest&& request, uint64_t listenerID, const UserData& userData, bool& receivedPolicyAction, uint64_t& newNavigationID, WebCore::PolicyAction& policyAction, DownloadID& downloadID, std::optional<WebsitePoliciesData>& websitePolicies)
{
+ LOG(Loading, "WebPageProxy::didStartProvisionalLoadForFrame - Target url %s", originalRequest.url().string().utf8().data());
+
PageClientProtector protector(m_pageClient);
auto transaction = m_pageLoadState.transaction();
@@ -3781,7 +3830,7 @@
MESSAGE_CHECK_URL(request.url());
MESSAGE_CHECK_URL(originalRequest.url());
- Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
+ Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID, PolicyListenerType::NavigationAction);
if (!navigationID) {
auto navigation = m_navigationState->createLoadRequestNavigation(ResourceRequest(request));
newNavigationID = navigation->navigationID();
@@ -3847,7 +3896,7 @@
MESSAGE_CHECK(frame);
MESSAGE_CHECK_URL(request.url());
- Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
+ Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID, PolicyListenerType::NewWindowAction);
if (m_navigationClient) {
RefPtr<API::FrameInfo> sourceFrameInfo;
@@ -3873,9 +3922,11 @@
MESSAGE_CHECK_URL(request.url());
MESSAGE_CHECK_URL(response.url());
- Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID);
- if (navigationID)
- listener->setNavigation(m_navigationState->navigation(navigationID));
+ Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID, PolicyListenerType::Response);
+ if (navigationID) {
+ auto& navigation = m_navigationState->navigation(navigationID);
+ listener->setNavigation(navigation);
+ }
if (m_navigationClient) {
auto navigationResponse = API::NavigationResponse::create(API::FrameInfo::create(*frame, frameSecurityOrigin.securityOrigin()).get(), request, response, canShowMIMEType);
@@ -5590,14 +5641,19 @@
// There is a nested transaction in resetStateAfterProcessExited() that we don't want to commit before the client call.
PageLoadState::Transaction transaction = m_pageLoadState.transaction();
- resetStateAfterProcessExited();
+ resetStateAfterProcessExited(reason);
- navigationState().clearAllNavigations();
+ // For bringup of process swapping, NavigationSwap termination will not go out to clients.
+ // If it does *during* process swapping, and the client triggers a reload, that causes bizarre WebKit re-entry.
+ // FIXME: This might have to change
+ if (reason != ProcessTerminationReason::NavigationSwap) {
+ navigationState().clearAllNavigations();
- if (m_navigationClient)
- m_navigationClient->processDidTerminate(*this, reason);
- else if (reason != ProcessTerminationReason::RequestedByClient)
- m_loaderClient->processDidCrash(*this);
+ if (m_navigationClient)
+ m_navigationClient->processDidTerminate(*this, reason);
+ else if (reason != ProcessTerminationReason::RequestedByClient)
+ m_loaderClient->processDidCrash(*this);
+ }
if (m_controlledByAutomation) {
if (auto* automationSession = process().processPool().automationSession())
@@ -5737,10 +5793,11 @@
CallbackBase::Error error;
switch (resetStateReason) {
+ case ResetStateReason::NavigationSwap:
+ FALLTHROUGH;
case ResetStateReason::PageInvalidated:
error = CallbackBase::Error::OwnerWasInvalidated;
break;
-
case ResetStateReason::WebProcessExited:
error = CallbackBase::Error::ProcessExited;
break;
@@ -5763,13 +5820,16 @@
#endif
}
-void WebPageProxy::resetStateAfterProcessExited()
+void WebPageProxy::resetStateAfterProcessExited(ProcessTerminationReason terminationReason)
{
if (!isValid())
return;
+#if !ASSERT_DISABLED
// FIXME: It's weird that resetStateAfterProcessExited() is called even though the process is launching.
- ASSERT(m_process->state() == WebProcessProxy::State::Launching || m_process->state() == WebProcessProxy::State::Terminated);
+ if (terminationReason != ProcessTerminationReason::NavigationSwap)
+ ASSERT(m_process->state() == WebProcessProxy::State::Launching || m_process->state() == WebProcessProxy::State::Terminated);
+#endif
#if PLATFORM(IOS)
m_activityToken = nullptr;
@@ -5786,7 +5846,8 @@
m_pageClient.processDidExit();
- resetState(ResetStateReason::WebProcessExited);
+ auto resetStateReason = terminationReason == ProcessTerminationReason::NavigationSwap ? ResetStateReason::NavigationSwap : ResetStateReason::WebProcessExited;
+ resetState(resetStateReason);
m_pageClient.clearAllEditCommands();
m_pendingLearnOrIgnoreWordMessageCount = 0;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -1305,9 +1305,10 @@
enum class ResetStateReason {
PageInvalidated,
WebProcessExited,
+ NavigationSwap,
};
void resetState(ResetStateReason);
- void resetStateAfterProcessExited();
+ void resetStateAfterProcessExited(ProcessTerminationReason);
void setUserAgent(String&&);
@@ -1441,9 +1442,18 @@
void setCanShortCircuitHorizontalWheelEvents(bool canShortCircuitHorizontalWheelEvents) { m_canShortCircuitHorizontalWheelEvents = canShortCircuitHorizontalWheelEvents; }
void reattachToWebProcess();
+ void attachToProcessForNavigation(Ref<WebProcessProxy>&&);
+ void reattachToWebProcess(Ref<WebProcessProxy>&&);
+
RefPtr<API::Navigation> reattachToWebProcessForReload();
RefPtr<API::Navigation> reattachToWebProcessWithItem(WebBackForwardListItem*);
+ enum class NavigationPolicyCheck {
+ Require,
+ Bypass,
+ };
+ void loadRequestWithNavigation(API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, NavigationPolicyCheck);
+
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);
@@ -1685,7 +1695,6 @@
void contentFilterDidBlockLoadForFrame(const WebCore::ContentFilterUnblockHandler&, uint64_t frameID);
#endif
- uint64_t generateNavigationID();
API::DiagnosticLoggingClient* effectiveDiagnosticLoggingClient(WebCore::ShouldSample);
void dispatchActivityStateChange();
@@ -1732,6 +1741,8 @@
void reportPageLoadResult(const WebCore::ResourceError& = { });
+ void continueNavigationInNewProcess(API::Navigation&, Ref<WebProcessProxy>&&);
+
PageClient& m_pageClient;
Ref<API::PageConfiguration> m_configuration;
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -1940,4 +1940,16 @@
}
#endif
+Ref<WebProcessProxy> WebProcessPool::processForNavigation(WebPageProxy& page, const URL& targetURL)
+{
+ if (!m_configuration->processSwapsOnNavigation())
+ return page.process();
+
+ auto url = "" { ParsedURLString, page.pageLoadState().url() };
+ if (protocolHostAndPortAreEqual(url, targetURL) || url.isBlankURL())
+ return page.process();
+
+ return createNewWebProcess(page.websiteDataStore());
+}
+
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -442,6 +442,8 @@
BackgroundWebProcessToken backgroundWebProcessToken() const { return BackgroundWebProcessToken(m_backgroundWebProcessCounter.count()); }
#endif
+ Ref<WebProcessProxy> processForNavigation(WebPageProxy&, const WebCore::URL&);
+
private:
void platformInitialize();
Modified: trunk/Source/WebKit/UIProcess/WebStorage/StorageManager.cpp (229777 => 229778)
--- trunk/Source/WebKit/UIProcess/WebStorage/StorageManager.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/UIProcess/WebStorage/StorageManager.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -425,8 +425,6 @@
void StorageManager::SessionStorageNamespace::setAllowedConnection(IPC::Connection* allowedConnection)
{
- ASSERT(!allowedConnection || !m_allowedConnection);
-
m_allowedConnection = allowedConnection;
}
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (229777 => 229778)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2018-03-21 00:05:58 UTC (rev 229778)
@@ -1261,6 +1261,7 @@
FrameLoadRequest frameLoadRequest { *m_mainFrame->coreFrame(), loadParameters.request, ShouldOpenExternalURLsPolicy::ShouldNotAllow };
ShouldOpenExternalURLsPolicy externalURLsPolicy = static_cast<ShouldOpenExternalURLsPolicy>(loadParameters.shouldOpenExternalURLsPolicy);
frameLoadRequest.setShouldOpenExternalURLsPolicy(externalURLsPolicy);
+ frameLoadRequest.setShouldCheckNavigationPolicy(loadParameters.shouldCheckNavigationPolicy);
corePage()->userInputBridge().loadRequest(WTFMove(frameLoadRequest));
Modified: trunk/Tools/ChangeLog (229777 => 229778)
--- trunk/Tools/ChangeLog 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Tools/ChangeLog 2018-03-21 00:05:58 UTC (rev 229778)
@@ -1,3 +1,29 @@
+2018-03-20 Brady Eidson <beid...@apple.com>
+
+ First piece of process swapping on navigation.
+ https://bugs.webkit.org/show_bug.cgi?id=183665
+
+ Reviewed by Andy Estes.
+
+ Expose the "swaps processes on navigation" setting in MiniBrowser UI for testing:
+
+ * MiniBrowser/mac/AppDelegate.m:
+ (defaultConfiguration):
+ * MiniBrowser/mac/SettingsController.h:
+ * MiniBrowser/mac/SettingsController.m:
+ (-[SettingsController _populateMenu]):
+ (-[SettingsController validateMenuItem:]):
+ (-[SettingsController processSwapOnNavigationEnabled]):
+ (-[SettingsController toggleProcessSwapOnNavigation:]):
+
+ Makes sure the current behavior is tested:
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm: Added.
+ (-[PSONNavigationDelegate webView:didFinishNavigation:]):
+ (-[PSONScheme webView:startURLSchemeTask:]):
+ (-[PSONScheme webView:stopURLSchemeTask:]):
+ (TEST):
+
2018-03-20 Chris Dumez <cdu...@apple.com>
QuickLook.NavigationDelegate API test is failing on iOS with async policy delegates
Modified: trunk/Tools/MiniBrowser/mac/AppDelegate.m (229777 => 229778)
--- trunk/Tools/MiniBrowser/mac/AppDelegate.m 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Tools/MiniBrowser/mac/AppDelegate.m 2018-03-21 00:05:58 UTC (rev 229778)
@@ -98,6 +98,8 @@
processConfiguration.diskCacheSpeculativeValidationEnabled = ![SettingsController shared].networkCacheSpeculativeRevalidationDisabled;
if ([SettingsController shared].perWindowWebProcessesDisabled)
processConfiguration.maximumProcessCount = 1;
+ if ([SettingsController shared].processSwapOnNavigationEnabled)
+ processConfiguration.processSwapsOnNavigation = true;
configuration.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease];
Modified: trunk/Tools/MiniBrowser/mac/SettingsController.h (229777 => 229778)
--- trunk/Tools/MiniBrowser/mac/SettingsController.h 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Tools/MiniBrowser/mac/SettingsController.h 2018-03-21 00:05:58 UTC (rev 229778)
@@ -59,6 +59,7 @@
@property (nonatomic, readonly) BOOL loadsAllSiteIcons;
@property (nonatomic, readonly) BOOL usesGameControllerFramework;
@property (nonatomic, readonly) BOOL networkCacheSpeculativeRevalidationDisabled;
+@property (nonatomic, readonly) BOOL processSwapOnNavigationEnabled;
@property (nonatomic, readonly) NSString *defaultURL;
Modified: trunk/Tools/MiniBrowser/mac/SettingsController.m (229777 => 229778)
--- trunk/Tools/MiniBrowser/mac/SettingsController.m 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Tools/MiniBrowser/mac/SettingsController.m 2018-03-21 00:05:58 UTC (rev 229778)
@@ -70,6 +70,7 @@
static NSString * const PerWindowWebProcessesDisabledKey = @"PerWindowWebProcessesDisabled";
static NSString * const NetworkCacheSpeculativeRevalidationDisabledKey = @"NetworkCacheSpeculativeRevalidationDisabled";
+static NSString * const ProcessSwapOnNavigationKey = @"ProcessSwapOnNavigation";
typedef NS_ENUM(NSInteger, DebugOverylayMenuItemTag) {
NonFastScrollableRegionOverlayTag = 100,
@@ -179,6 +180,7 @@
[self _addItemWithTitle:@"Load All Site Icons Per-Page" action:@selector(toggleLoadsAllSiteIcons:) indented:YES];
[self _addItemWithTitle:@"Use GameController.framework on macOS (Restart required)" action:@selector(toggleUsesGameControllerFramework:) indented:YES];
[self _addItemWithTitle:@"Disable network cache speculative revalidation" action:@selector(toggleNetworkCacheSpeculativeRevalidationDisabled:) indented:YES];
+ [self _addItemWithTitle:@"Enable Process Swap on Navigation" action:@selector(toggleProcessSwapOnNavigation:) indented:YES];
NSMenuItem *debugOverlaysSubmenuItem = [[NSMenuItem alloc] initWithTitle:@"Debug Overlays" action:nil keyEquivalent:@""];
NSMenu *debugOverlaysMenu = [[NSMenu alloc] initWithTitle:@"Debug Overlays"];
@@ -270,6 +272,8 @@
[menuItem setState:[self usesGameControllerFramework] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleNetworkCacheSpeculativeRevalidationDisabled:))
[menuItem setState:[self networkCacheSpeculativeRevalidationDisabled] ? NSControlStateValueOn : NSControlStateValueOff];
+ else if (action == @selector(toggleProcessSwapOnNavigation:))
+ [menuItem setState:[self processSwapOnNavigationEnabled] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(toggleUseUISideCompositing:))
[menuItem setState:[self useUISideCompositing] ? NSControlStateValueOn : NSControlStateValueOff];
else if (action == @selector(togglePerWindowWebProcessesDisabled:))
@@ -485,6 +489,16 @@
[self _toggleBooleanDefault:NetworkCacheSpeculativeRevalidationDisabledKey];
}
+- (BOOL)processSwapOnNavigationEnabled
+{
+ return [[NSUserDefaults standardUserDefaults] boolForKey:ProcessSwapOnNavigationKey];
+}
+
+- (void)toggleProcessSwapOnNavigation:(id)sender
+{
+ [self _toggleBooleanDefault:ProcessSwapOnNavigationKey];
+}
+
- (BOOL)isSpaceReservedForBanners
{
return [[NSUserDefaults standardUserDefaults] boolForKey:ReserveSpaceForBannersPreferenceKey];
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (229777 => 229778)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2018-03-20 23:10:36 UTC (rev 229777)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2018-03-21 00:05:58 UTC (rev 229778)
@@ -183,6 +183,7 @@
51714EB81CF8CA17004723C4 /* WebProcessKillIDBCleanup.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51714EB61CF8C7A4004723C4 /* WebProcessKillIDBCleanup.mm */; };
517E7E04151119C100D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 517E7E031511187500D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.html */; };
5182C22E1F2BCE540059BA7C /* WKURLSchemeHandler-leaks.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5182C22D1F2BCB410059BA7C /* WKURLSchemeHandler-leaks.mm */; };
+ 518C1153205B0504001FF4AE /* ProcessSwapOnNavigation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 518C1152205B04F9001FF4AE /* ProcessSwapOnNavigation.mm */; };
5198A2401EA7E59F008910B7 /* InitialWarmedProcessUsed.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5198A23F1EA7E595008910B7 /* InitialWarmedProcessUsed.mm */; };
51A5877D1D1B49CD004BA9AF /* IndexedDBMultiProcess-3.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51A5877C1D1B3D8D004BA9AF /* IndexedDBMultiProcess-3.html */; };
51A587851D2739E3004BA9AF /* IndexedDBDatabaseProcessKill-1.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51A587821D272EB5004BA9AF /* IndexedDBDatabaseProcessKill-1.html */; };
@@ -1363,6 +1364,7 @@
517E7DFB15110EA600D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MemoryCachePruneWithinResourceLoadDelegate.mm; sourceTree = "<group>"; };
517E7E031511187500D0B008 /* MemoryCachePruneWithinResourceLoadDelegate.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = MemoryCachePruneWithinResourceLoadDelegate.html; sourceTree = "<group>"; };
5182C22D1F2BCB410059BA7C /* WKURLSchemeHandler-leaks.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "WKURLSchemeHandler-leaks.mm"; sourceTree = "<group>"; };
+ 518C1152205B04F9001FF4AE /* ProcessSwapOnNavigation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProcessSwapOnNavigation.mm; sourceTree = "<group>"; };
5198A23F1EA7E595008910B7 /* InitialWarmedProcessUsed.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = InitialWarmedProcessUsed.mm; sourceTree = "<group>"; };
51A5877C1D1B3D8D004BA9AF /* IndexedDBMultiProcess-3.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "IndexedDBMultiProcess-3.html"; sourceTree = "<group>"; };
51A587821D272EB5004BA9AF /* IndexedDBDatabaseProcessKill-1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "IndexedDBDatabaseProcessKill-1.html"; sourceTree = "<group>"; };
@@ -2177,6 +2179,7 @@
83BAEE8C1EF4625500DDE894 /* PluginLoadClientPolicies.mm */,
C95501BE19AD2FAF0049BE3E /* Preferences.mm */,
7C1AF7931E8DCBAB002645B9 /* PrepareForMoveToWindow.mm */,
+ 518C1152205B04F9001FF4AE /* ProcessSwapOnNavigation.mm */,
5798E2AF1CAF5C2800C5CBA0 /* ProvisionalURLNotChange.mm */,
A1C4FB6C1BACCE50003742D0 /* QuickLook.mm */,
1A4F81D01BDFFDCF004E672E /* RemoteObjectRegistry.h */,
@@ -3736,6 +3739,7 @@
7CCE7F2F1A411B1000447C4C /* WKBrowsingContextLoadDelegateTest.mm in Sources */,
7C54A4BE1AA11CCA00380F78 /* WKBundleFileHandle.cpp in Sources */,
5CE354D91E70DA5C00BEFE3B /* WKContentExtensionStore.mm in Sources */,
+ 518C1153205B0504001FF4AE /* ProcessSwapOnNavigation.mm in Sources */,
2D838B1F1EEF3A5C009B980E /* WKContentViewEditingActions.mm in Sources */,
370CE22A1F57343400E7410B /* WKContentViewTargetForAction.mm in Sources */,
51D124981E763B02002B2820 /* WKHTTPCookieStore.mm in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (0 => 229778)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm 2018-03-21 00:05:58 UTC (rev 229778)
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#import "config.h"
+
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import <WebKit/WKNavigationDelegate.h>
+#import <WebKit/WKPreferencesPrivate.h>
+#import <WebKit/WKProcessPoolPrivate.h>
+#import <WebKit/WKURLSchemeHandler.h>
+#import <WebKit/WKURLSchemeTaskPrivate.h>
+#import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WKWebsiteDataStorePrivate.h>
+#import <WebKit/WKWebsiteDataStoreRef.h>
+#import <WebKit/WebKit.h>
+#import <WebKit/_WKExperimentalFeature.h>
+#import <WebKit/_WKProcessPoolConfiguration.h>
+#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
+#import <wtf/Deque.h>
+#import <wtf/HashMap.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/Vector.h>
+#import <wtf/text/StringHash.h>
+#import <wtf/text/WTFString.h>
+
+#if WK_API_ENABLED
+
+static bool done;
+static int numberOfDecidePolicyCalls;
+
+@interface PSONNavigationDelegate : NSObject <WKNavigationDelegate>
+@end
+
+@implementation PSONNavigationDelegate
+
+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
+{
+ done = true;
+}
+
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
+{
+ ++numberOfDecidePolicyCalls;
+ decisionHandler(WKNavigationActionPolicyAllow);
+}
+
+@end
+
+@interface PSONScheme : NSObject <WKURLSchemeHandler> {
+}
+@end
+
+@implementation PSONScheme
+
+- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)task
+{
+ RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]);
+ [task didReceiveResponse:response.get()];
+ [task didReceiveData:[@"Hello" dataUsingEncoding:NSUTF8StringEncoding]];
+ [task didFinish];
+}
+
+- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)task
+{
+}
+
+@end
+
+TEST(ProcessSwap, Basic)
+{
+ 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()];
+ RetainPtr<PSONScheme> handler = adoptNS([[PSONScheme alloc] init]);
+ [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON1"];
+ [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON2"];
+
+ 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:@"pson1://host/main1.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ auto pid1 = [webView _webProcessIdentifier];
+
+ request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson1://host/main2.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ auto pid2 = [webView _webProcessIdentifier];
+
+ request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson2://host/main2.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ auto pid3 = [webView _webProcessIdentifier];
+
+ EXPECT_EQ(pid1, pid2);
+ EXPECT_FALSE(pid2 == pid3);
+
+ // 3 loads, 3 decidePolicy calls (e.g. the load that did perform a process swap should not have generated an additional decidePolicy call)
+ EXPECT_EQ(numberOfDecidePolicyCalls, 3);
+}
+
+#endif // WK_API_ENABLED