Diff
Modified: trunk/Source/WebKit/ChangeLog (230173 => 230174)
--- trunk/Source/WebKit/ChangeLog 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/ChangeLog 2018-04-02 20:05:48 UTC (rev 230174)
@@ -1,3 +1,67 @@
+2018-04-02 Brady Eidson <beid...@apple.com>
+
+ Process swapping on navigation needs to handle server redirects.
+ <rdar://problem/38690465> and https://bugs.webkit.org/show_bug.cgi?id=184142
+
+ Reviewed by Alex Christensen.
+
+ The same rules we apply to process swapping for basic navigations need to apply
+ to server redirects as well.
+
+ There's three interesting cases we need to support that are covered by new API tests:
+ 1 - The initial load in a WKWebView redirects cross-origin.
+ 2 - A WKWebView is showing content from a.com, we start a load to b.com, and that redirects to c.com
+ 3 - A WKWebView is showing content from a.com, we start a load to a.com, that that redirects to b.com.
+
+ Supporting all 3 of these brought their own little challenges.
+
+ By teaching Navigation objects more about redirects I was able to support all 3 cases.
+
+ * UIProcess/API/APINavigation.cpp:
+ (API::Navigation::Navigation):
+ (API::Navigation::setCurrentRequest):
+ (API::Navigation::appendRedirectionURL):
+ (API::Navigation::loggingString const):
+ (API::Navigation::loggingURL const): Deleted.
+ * UIProcess/API/APINavigation.h:
+ (API::Navigation::originalRequest const):
+ (API::Navigation::currentRequest const):
+ (API::Navigation::currentRequestProcessIdentifier const):
+ (API::Navigation::setCurrentRequestIsRedirect):
+ (API::Navigation::currentRequestIsRedirect const):
+ (API::Navigation::request const): Deleted.
+
+ * UIProcess/API/Cocoa/WKNavigation.mm:
+ (-[WKNavigation _request]):
+
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::receivedPolicyDecision):
+ (WebKit::WebPageProxy::continueNavigationInNewProcess): If this continued navigation is currently in a server
+ redirect, save off a lambda to synthesize a "did receive server redirect" callback once the new WebProcess is running.
+ (WebKit::WebPageProxy::didCreateMainFrame):
+ (WebKit::WebPageProxy::didStartProvisionalLoadForFrame): Possibly ignore this notification if it is really a
+ cross-origin redirect that is just starting back up in a new WebProcess.
+ (WebKit::WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame):
+ (WebKit::WebPageProxy::didCommitLoadForFrame):
+ (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+ (WebKit::WebPageProxy::resetStateAfterProcessExited): Do not clear pageLoadState if the process is exitting for
+ a navigation swap, as we will need to pick up where we left off when the load continues in a new WebProcess.
+ * UIProcess/WebPageProxy.h:
+ * UIProcess/WebPageProxy.messages.in:
+
+ * UIProcess/WebProcessPool.cpp:
+ (WebKit::WebProcessPool::processForNavigation): If a process has never committed any provisional load, it can always
+ be used to continue a navigation.
+ * UIProcess/WebProcessPool.h:
+
+ * UIProcess/WebProcessProxy.h:
+ (WebKit::WebProcessProxy::didCommitProvisionalLoad):
+ (WebKit::WebProcessProxy::hasCommittedAnyProvisionalLoads const):
+
+ * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+ (WebKit::WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad):
+ (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
+
2018-04-02 Wenson Hsieh <wenson_hs...@apple.com>
[Extra zoom mode] Zoom level is sometimes excessive when zooming to focused form controls
Modified: trunk/Source/WebKit/UIProcess/API/APINavigation.cpp (230173 => 230174)
--- trunk/Source/WebKit/UIProcess/API/APINavigation.cpp 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/UIProcess/API/APINavigation.cpp 2018-04-02 20:05:48 UTC (rev 230174)
@@ -41,13 +41,16 @@
Navigation::Navigation(WebNavigationState& state, WebCore::ResourceRequest&& request)
: m_navigationID(state.generateNavigationID())
- , m_request(WTFMove(request))
+ , m_originalRequest(WTFMove(request))
+ , m_currentRequest(m_originalRequest)
{
- m_redirectChain.append(m_request.url());
+ m_redirectChain.append(m_originalRequest.url());
}
Navigation::Navigation(WebNavigationState& state, WebBackForwardListItem& item, FrameLoadType backForwardFrameLoadType)
: m_navigationID(state.generateNavigationID())
+ , m_originalRequest(item.url())
+ , m_currentRequest(m_originalRequest)
, m_backForwardListItem(&item)
, m_backForwardFrameLoadType(backForwardFrameLoadType)
{
@@ -57,16 +60,22 @@
{
}
-void Navigation::appendRedirectionURL(const WebCore::URL& url)
+void Navigation::setCurrentRequest(ResourceRequest&& request, ProcessIdentifier processIdentifier)
{
+ m_currentRequest = WTFMove(request);
+ m_currentRequestProcessIdentifier = processIdentifier;
+}
+
+void Navigation::appendRedirectionURL(const URL& url)
+{
if (m_redirectChain.isEmpty() || m_redirectChain.last() != url)
m_redirectChain.append(url);
}
#if !LOG_DISABLED
-WTF::String Navigation::loggingURL() const
+WTF::String Navigation::loggingString() const
{
- return m_backForwardListItem ? m_backForwardListItem->url() : m_request.url().string();
+ return makeString("Most recent URL: ", m_currentRequest.url().string(), " Back/forward list item URL: '", m_backForwardListItem ? m_backForwardListItem->url() : String { }, String::format("' (%p)", m_backForwardListItem.get()));
}
#endif
Modified: trunk/Source/WebKit/UIProcess/API/APINavigation.h (230173 => 230174)
--- trunk/Source/WebKit/UIProcess/API/APINavigation.h 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/UIProcess/API/APINavigation.h 2018-04-02 20:05:48 UTC (rev 230174)
@@ -26,6 +26,7 @@
#pragma once
#include "APIObject.h"
+#include <WebCore/Process.h>
#include <WebCore/ResourceRequest.h>
#include <wtf/Ref.h>
@@ -62,7 +63,14 @@
uint64_t navigationID() const { return m_navigationID; }
- const WebCore::ResourceRequest& request() const { return m_request; }
+ const WebCore::ResourceRequest& originalRequest() const { return m_originalRequest; }
+ void setCurrentRequest(WebCore::ResourceRequest&&, WebCore::ProcessIdentifier);
+ const WebCore::ResourceRequest& currentRequest() const { return m_currentRequest; }
+ std::optional<WebCore::ProcessIdentifier> currentRequestProcessIdentifier() const { return m_currentRequestProcessIdentifier; }
+
+ void setCurrentRequestIsRedirect(bool isRedirect) { m_isRedirect = isRedirect; }
+ bool currentRequestIsRedirect() const { return m_isRedirect; }
+
WebKit::WebBackForwardListItem* backForwardListItem() { return m_backForwardListItem.get(); }
std::optional<WebCore::FrameLoadType> backForwardFrameLoadType() const { return m_backForwardFrameLoadType; }
@@ -82,7 +90,7 @@
const std::optional<std::pair<uint64_t, uint64_t>>& opener() const { return m_opener; }
#if !LOG_DISABLED
- WTF::String loggingURL() const;
+ WTF::String loggingString() const;
#endif
private:
@@ -91,10 +99,13 @@
Navigation(WebKit::WebNavigationState&, WebKit::WebBackForwardListItem&, WebCore::FrameLoadType);
uint64_t m_navigationID;
- WebCore::ResourceRequest m_request;
+ WebCore::ResourceRequest m_originalRequest;
+ WebCore::ResourceRequest m_currentRequest;
+ std::optional<WebCore::ProcessIdentifier> m_currentRequestProcessIdentifier;
Vector<WebCore::URL> m_redirectChain;
bool m_wasUserInitiated { true };
bool m_shouldForceDownload { false };
+ bool m_isRedirect { false };
RefPtr<WebKit::WebBackForwardListItem> m_backForwardListItem;
std::optional<WebCore::FrameLoadType> m_backForwardFrameLoadType;
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKNavigation.mm (230173 => 230174)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKNavigation.mm 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKNavigation.mm 2018-04-02 20:05:48 UTC (rev 230174)
@@ -43,7 +43,7 @@
- (NSURLRequest *)_request
{
- return _navigation->request().nsURLRequest(WebCore::DoNotUpdateHTTPBody);
+ return _navigation->originalRequest().nsURLRequest(WebCore::DoNotUpdateHTTPBody);
}
#pragma mark WKObject protocol implementation
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (230173 => 230174)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-04-02 20:05:48 UTC (rev 230174)
@@ -2352,8 +2352,9 @@
if (action == PolicyAction::Use && navigation) {
auto proposedProcess = process().processPool().processForNavigation(*this, *navigation, action);
+
if (proposedProcess.ptr() != &process()) {
- LOG(Loading, "Switching to new process for navigation %" PRIu64 " to url '%s' (WebBackForwardListItem %p)", navigation->navigationID(), navigation->loggingURL().utf8().data(), navigation->backForwardListItem());
+ LOG(Loading, "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));
@@ -2367,8 +2368,9 @@
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.loggingURL().utf8().data());
+ LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString().utf8().data());
+ ASSERT(m_process.ptr() != process.ptr());
attachToProcessForNavigation(WTFMove(process));
if (auto* item = navigation.backForwardListItem()) {
@@ -2384,7 +2386,20 @@
}
// FIXME: Work out timing of responding with the last policy delegate, etc
- loadRequestWithNavigation(navigation, ResourceRequest { navigation.request() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, NavigationPolicyCheck::Bypass);
+ ASSERT(!navigation.currentRequest().isEmpty());
+ loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, NavigationPolicyCheck::Bypass);
+
+ // Normally, notification of a server redirect comes from the WebContent process.
+ // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
+ // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
+ if (navigation.currentRequestIsRedirect()) {
+ ASSERT(!m_mainFrame);
+ m_mainFrameCreationHandler = [this, protectedThis = makeRef(*this), navigation = makeRef(navigation), request = navigation.currentRequest()]() mutable {
+ ASSERT(m_mainFrame);
+ m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
+ didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigation->navigationID(), WTFMove(request), { });
+ };
+ }
}
void WebPageProxy::setUserAgent(String&& userAgent)
@@ -3193,6 +3208,11 @@
// Add the frame to the process wide map.
m_process->frameCreated(frameID, m_mainFrame.get());
+
+ if (m_mainFrameCreationHandler) {
+ m_mainFrameCreationHandler();
+ m_mainFrameCreationHandler = nullptr;
+ }
}
void WebPageProxy::didCreateSubframe(uint64_t frameID)
@@ -3269,10 +3289,6 @@
{
PageClientProtector protector(m_pageClient);
- auto transaction = m_pageLoadState.transaction();
-
- m_pageLoadState.clearPendingAPIRequestURL(transaction);
-
WebFrameProxy* frame = m_process->webFrame(frameID);
MESSAGE_CHECK(frame);
MESSAGE_CHECK_URL(url);
@@ -3282,6 +3298,20 @@
if (frame->isMainFrame() && navigationID)
navigation = &navigationState().navigation(navigationID);
+ // If this seemingly new load is actually continuing a server redirect for a previous navigation in a new process,
+ // then we ignore this notification.
+ if (navigation && navigation->currentRequestIsRedirect()) {
+ auto navigationProcessIdentifier = navigation->currentRequestProcessIdentifier();
+ if (navigationProcessIdentifier && *navigationProcessIdentifier != m_process->coreProcessIdentifier())
+ return;
+ }
+
+ LOG(Loading, "WebPageProxy::didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", frameID, navigationID, url.string().utf8().data());
+
+ auto transaction = m_pageLoadState.transaction();
+
+ m_pageLoadState.clearPendingAPIRequestURL(transaction);
+
if (frame->isMainFrame()) {
if (m_pageLoadStart)
reportPageLoadResult(ResourceError { ResourceError::Type::Cancellation });
@@ -3302,27 +3332,29 @@
m_loaderClient->didStartProvisionalLoadForFrame(*this, *frame, navigation.get(), m_process->transformHandlesToObjects(userData.object()).get());
}
-void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&& url, const UserData& userData)
+void WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, ResourceRequest&& request, const UserData& userData)
{
+ LOG(Loading, "WebPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", frameID, navigationID, request.url().string().utf8().data());
+
PageClientProtector protector(m_pageClient);
WebFrameProxy* frame = m_process->webFrame(frameID);
MESSAGE_CHECK(frame);
- MESSAGE_CHECK_URL(url);
+ MESSAGE_CHECK_URL(request.url());
// FIXME: We should message check that navigationID is not zero here, but it's currently zero for some navigations through the page cache.
RefPtr<API::Navigation> navigation;
if (navigationID) {
navigation = &navigationState().navigation(navigationID);
- navigation->appendRedirectionURL(url);
+ navigation->appendRedirectionURL(request.url());
}
auto transaction = m_pageLoadState.transaction();
if (frame->isMainFrame())
- m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, url);
+ m_pageLoadState.didReceiveServerRedirectForProvisionalLoad(transaction, request.url());
- frame->didReceiveServerRedirectForProvisionalLoad(url);
+ frame->didReceiveServerRedirectForProvisionalLoad(request.url());
m_pageLoadState.commitChanges();
if (m_navigationClient) {
@@ -3443,6 +3475,8 @@
if (frame->isMainFrame() && navigationID)
navigation = &navigationState().navigation(navigationID);
+ m_process->didCommitProvisionalLoad();
+
#if PLATFORM(IOS)
if (frame->isMainFrame()) {
m_hasReceivedLayerTreeTransactionAfterDidCommitLoad = false;
@@ -3791,7 +3825,7 @@
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)
{
- LOG(Loading, "WebPageProxy::didStartProvisionalLoadForFrame - Target url %s", originalRequest.url().string().utf8().data());
+ LOG(Loading, "WebPageProxy::decidePolicyForNavigationAction - Original URL %s, current target URL %s", originalRequest.url().string().utf8().data(), request.url().string().utf8().data());
PageClientProtector protector(m_pageClient);
@@ -3806,15 +3840,19 @@
MESSAGE_CHECK_URL(request.url());
MESSAGE_CHECK_URL(originalRequest.url());
- uint64_t newNavigationID { 0 };
- Ref<WebFramePolicyListenerProxy> listener = frame->setUpPolicyListenerProxy(listenerID, PolicyListenerType::NavigationAction);
Ref<API::Navigation> navigation = navigationID ? makeRef(m_navigationState->navigation(navigationID)) : m_navigationState->createLoadRequestNavigation(ResourceRequest(request));
- newNavigationID = navigation->navigationID();
+ ASSERT(navigation->originalRequest().url() == originalRequest.url());
+
+ uint64_t newNavigationID = navigation->navigationID();
navigation->setWasUserInitiated(!!navigationActionData.userGestureTokenIdentifier);
navigation->setShouldForceDownload(!navigationActionData.downloadAttribute.isNull());
+ navigation->setCurrentRequest(ResourceRequest(request), m_process->coreProcessIdentifier());
+ navigation->setCurrentRequestIsRedirect(navigationActionData.isRedirect);
navigation->setIsCrossOriginWindowOpenNavigation(navigationActionData.isCrossOriginWindowOpenNavigation);
navigation->setOpener(navigationActionData.opener);
+
+ auto listener = makeRef(frame->setUpPolicyListenerProxy(listenerID, PolicyListenerType::NavigationAction));
listener->setNavigation(WTFMove(navigation));
#if ENABLE(CONTENT_FILTERING)
@@ -5803,9 +5841,12 @@
m_touchEventQueue.clear();
#endif
- PageLoadState::Transaction transaction = m_pageLoadState.transaction();
- m_pageLoadState.reset(transaction);
+ if (terminationReason != ProcessTerminationReason::NavigationSwap) {
+ PageLoadState::Transaction transaction = m_pageLoadState.transaction();
+ m_pageLoadState.reset(transaction);
+ }
+ // FIXME: <rdar://problem/38676604> In case of process swaps, the old process should gracefully suspend instead of terminating.
m_process->processTerminated();
}
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (230173 => 230174)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-04-02 20:05:48 UTC (rev 230174)
@@ -1339,7 +1339,7 @@
void didCreateSubframe(uint64_t frameID);
void didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&&, WebCore::URL&& unreachableURL, const UserData&);
- void didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&&, const UserData&);
+ void didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest&&, const UserData&);
void willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay);
void didCancelClientRedirectForFrame(uint64_t frameID);
void didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL&&);
@@ -1777,6 +1777,8 @@
Ref<WebsiteDataStore> m_websiteDataStore;
RefPtr<WebFrameProxy> m_mainFrame;
+ Function<void()> m_mainFrameCreationHandler;
+
RefPtr<WebFrameProxy> m_focusedFrame;
RefPtr<WebFrameProxy> m_frameSetLargestFrame;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (230173 => 230174)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in 2018-04-02 20:05:48 UTC (rev 230174)
@@ -116,7 +116,7 @@
# Frame load messages
DidStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL url, WebCore::URL unreachableURL, WebKit::UserData userData)
- DidReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL url, WebKit::UserData userData)
+ DidReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest request, WebKit::UserData userData)
WillPerformClientRedirectForFrame(uint64_t frameID, String url, double delay)
DidCancelClientRedirectForFrame(uint64_t frameID)
DidChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, WebCore::URL url)
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (230173 => 230174)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2018-04-02 20:05:48 UTC (rev 230174)
@@ -1985,6 +1985,9 @@
if (!m_configuration->processSwapsOnNavigation())
return page.process();
+ if (!page.process().hasCommittedAnyProvisionalLoads())
+ return page.process();
+
// FIXME: We should support process swap when a window has an opener.
if (navigation.opener())
return page.process();
@@ -1994,9 +1997,9 @@
return createNewWebProcess(page.websiteDataStore());
}
- auto targetURL = navigation.request().url();
+ auto targetURL = navigation.currentRequest().url();
auto url = "" { ParsedURLString, page.pageLoadState().url() };
- if (!url.isValid() || url.isBlankURL() || protocolHostAndPortAreEqual(url, targetURL))
+ if (!url.isValid() || url.isEmpty() || url.isBlankURL() || protocolHostAndPortAreEqual(url, targetURL))
return page.process();
action = ""
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (230173 => 230174)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.h 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h 2018-04-02 20:05:48 UTC (rev 230174)
@@ -78,6 +78,7 @@
class HTTPCookieStore;
class InjectedBundleClient;
class LegacyContextHistoryClient;
+class Navigation;
class PageConfiguration;
}
Modified: trunk/Source/WebKit/UIProcess/WebProcessProxy.h (230173 => 230174)
--- trunk/Source/WebKit/UIProcess/WebProcessProxy.h 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/UIProcess/WebProcessProxy.h 2018-04-02 20:05:48 UTC (rev 230174)
@@ -205,6 +205,9 @@
void checkProcessLocalPortForActivity(const WebCore::MessagePortIdentifier&, CompletionHandler<void(WebCore::MessagePortChannelProvider::HasActivity)>&&);
+ void didCommitProvisionalLoad() { m_hasCommittedAnyProvisionalLoads = true; }
+ bool hasCommittedAnyProvisionalLoads() const { return m_hasCommittedAnyProvisionalLoads; }
+
protected:
static uint64_t generatePageID();
WebProcessProxy(WebProcessPool&, WebsiteDataStore&);
@@ -329,6 +332,8 @@
HashSet<WebCore::MessagePortIdentifier> m_processEntangledPorts;
HashMap<uint64_t, Function<void()>> m_messageBatchDeliveryCompletionHandlers;
HashMap<uint64_t, CompletionHandler<void(WebCore::MessagePortChannelProvider::HasActivity)>> m_localPortActivityCompletionHandlers;
+
+ bool m_hasCommittedAnyProvisionalLoads { false };
};
} // namespace WebKit
Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (230173 => 230174)
--- trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp 2018-04-02 20:05:48 UTC (rev 230174)
@@ -35,6 +35,7 @@
#include "InjectedBundleBackForwardListItem.h"
#include "InjectedBundleDOMWindowExtension.h"
#include "InjectedBundleNavigationAction.h"
+#include "Logging.h"
#include "NavigationActionData.h"
#include "NetworkConnectionToWebProcessMessages.h"
#include "NetworkProcessConnection.h"
@@ -306,11 +307,13 @@
WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().provisionalDocumentLoader());
RefPtr<API::Object> userData;
+ LOG(Loading, "WebProcess %i - dispatchDidReceiveServerRedirectForProvisionalLoad to request url %s", getpid(), documentLoader.request().url().string().utf8().data());
+
// Notify the bundle client.
webPage->injectedBundleLoaderClient().didReceiveServerRedirectForProvisionalLoadForFrame(*webPage, *m_frame, userData);
// Notify the UIProcess.
- webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.url(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+ webPage->send(Messages::WebPageProxy::DidReceiveServerRedirectForProvisionalLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), documentLoader.request(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
}
void WebFrameLoaderClient::dispatchDidChangeProvisionalURL()
@@ -818,6 +821,8 @@
return;
}
+ LOG(Loading, "WebProcess %i - dispatchDecidePolicyForNavigationAction to request url %s", getpid(), request.url().string().utf8().data());
+
m_isDecidingNavigationPolicyDecision = true;
if (m_frame->isMainFrame())
webPage->didStartNavigationPolicyCheck();
Modified: trunk/Tools/ChangeLog (230173 => 230174)
--- trunk/Tools/ChangeLog 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Tools/ChangeLog 2018-04-02 20:05:48 UTC (rev 230174)
@@ -1,3 +1,17 @@
+2018-04-02 Brady Eidson <beid...@apple.com>
+
+ Process swapping on navigation needs to handle server redirects.
+ <rdar://problem/38690465> and https://bugs.webkit.org/show_bug.cgi?id=184142
+
+ Reviewed by Alex Christensen.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+ (-[PSONNavigationDelegate webView:didFinishNavigation:]):
+ (-[PSONNavigationDelegate webView:decidePolicyForNavigationAction:decisionHandler:]):
+ (-[PSONNavigationDelegate webView:didReceiveServerRedirectForProvisionalNavigation:]):
+ (-[PSONScheme addRedirectFromURLString:toURLString:]):
+ (-[PSONScheme webView:startURLSchemeTask:]):
+
2018-04-02 Thibault Saunier <tsaun...@igalia.com>
webkitpy: Use current environment value for GST_DEBUG(_FILE) and DOT_DIR env vars
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (230173 => 230174)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm 2018-04-02 19:59:42 UTC (rev 230173)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm 2018-04-02 20:05:48 UTC (rev 230174)
@@ -28,6 +28,7 @@
#import "PlatformUtilities.h"
#import "Test.h"
#import <WebKit/WKNavigationDelegate.h>
+#import <WebKit/WKNavigationPrivate.h>
#import <WebKit/WKPreferencesPrivate.h>
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKUIDelegatePrivate.h>
@@ -44,6 +45,7 @@
#import <WebKit/_WKWebsitePolicies.h>
#import <wtf/Deque.h>
#import <wtf/HashMap.h>
+#import <wtf/HashSet.h>
#import <wtf/RetainPtr.h>
#import <wtf/Vector.h>
#import <wtf/text/StringHash.h>
@@ -57,6 +59,8 @@
static RetainPtr<NSMutableArray> receivedMessages = adoptNS([@[] mutableCopy]);
static bool receivedMessage;
+static bool serverRedirected;
+static HashSet<pid_t> seenPIDs;
@interface PSONMessageHandler : NSObject <WKScriptMessageHandler>
@end
@@ -75,6 +79,7 @@
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
+ seenPIDs.add([webView _webProcessIdentifier]);
done = true;
}
@@ -81,9 +86,16 @@
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
++numberOfDecidePolicyCalls;
+ seenPIDs.add([webView _webProcessIdentifier]);
decisionHandler(WKNavigationActionPolicyAllow);
}
+- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
+{
+ seenPIDs.add([webView _webProcessIdentifier]);
+ serverRedirected = true;
+}
+
@end
static RetainPtr<WKWebView> createdWebView;
@@ -117,8 +129,10 @@
@interface PSONScheme : NSObject <WKURLSchemeHandler> {
const char* _bytes;
+ HashMap<String, String> _redirects;
}
- (instancetype)initWithBytes:(const char*)bytes;
+- (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString;
@end
@implementation PSONScheme
@@ -130,9 +144,25 @@
return self;
}
+- (void)addRedirectFromURLString:(NSString *)sourceURLString toURLString:(NSString *)destinationURLString
+{
+ _redirects.set(sourceURLString, destinationURLString);
+}
+
- (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]);
+ NSURL *finalURL = task.request.URL;
+ auto target = _redirects.get(task.request.URL.absoluteString);
+ if (!target.isEmpty()) {
+ auto redirectResponse = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:nil expectedContentLength:0 textEncodingName:nil]);
+
+ finalURL = [NSURL URLWithString:(NSString *)target];
+ auto request = adoptNS([[NSURLRequest alloc] initWithURL:finalURL]);
+
+ [(id<WKURLSchemeTaskPrivate>)task _didPerformRedirection:redirectResponse.get() newRequest:request.get()];
+ }
+
+ RetainPtr<NSURLResponse> response = adoptNS([[NSURLResponse alloc] initWithURL:finalURL MIMEType:@"text/html" expectedContentLength:1 textEncodingName:nil]);
[task didReceiveResponse:response.get()];
if (_bytes) {
@@ -444,4 +474,137 @@
#endif // PLATFORM(MAC)
+TEST(ProcessSwap, ServerRedirectFromNewWebView)
+{
+ 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]);
+ [handler addRedirectFromURLString:@"pson://host/main1.html" toURLString:@"psonredirected://host/main1.html"];
+ [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://host/main1.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&serverRedirected);
+ serverRedirected = false;
+
+ seenPIDs.add([webView _webProcessIdentifier]);
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ seenPIDs.add([webView _webProcessIdentifier]);
+
+ EXPECT_FALSE(serverRedirected);
+ EXPECT_EQ(2, numberOfDecidePolicyCalls);
+ EXPECT_EQ(1u, seenPIDs.size());
+}
+
+TEST(ProcessSwap, ServerRedirect)
+{
+ 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> handler1 = adoptNS([[PSONScheme alloc] init]);
+ [handler1 addRedirectFromURLString:@"pson://host/main1.html" toURLString:@"psonredirected://host/main1.html"];
+ [webViewConfiguration setURLSchemeHandler:handler1.get() forURLScheme:@"pson"];
+ RetainPtr<PSONScheme> handler2 = adoptNS([[PSONScheme alloc] init]);
+ [webViewConfiguration setURLSchemeHandler:handler2.get() forURLScheme:@"originalload"];
+
+ 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:@"originalload://host/main1.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ auto pidAfterFirstLoad = [webView _webProcessIdentifier];
+
+ EXPECT_EQ(1, numberOfDecidePolicyCalls);
+ EXPECT_EQ(1u, seenPIDs.size());
+ EXPECT_TRUE(*seenPIDs.begin() == pidAfterFirstLoad);
+
+ request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://host/main1.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&serverRedirected);
+ serverRedirected = false;
+
+ seenPIDs.add([webView _webProcessIdentifier]);
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ seenPIDs.add([webView _webProcessIdentifier]);
+
+ EXPECT_FALSE(serverRedirected);
+ EXPECT_EQ(3, numberOfDecidePolicyCalls);
+ EXPECT_EQ(2u, seenPIDs.size());
+}
+
+TEST(ProcessSwap, ServerRedirect2)
+{
+ // This tests a load that *starts out* to the same origin as the previous load, but then redirects to a new origin.
+ 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> handler1 = adoptNS([[PSONScheme alloc] init]);
+ [handler1 addRedirectFromURLString:@"pson://host/main2.html" toURLString:@"psonredirected://host/main1.html"];
+ [webViewConfiguration setURLSchemeHandler:handler1.get() forURLScheme:@"pson"];
+ RetainPtr<PSONScheme> handler2 = adoptNS([[PSONScheme alloc] init]);
+ [webViewConfiguration setURLSchemeHandler:handler2.get() forURLScheme:@"psonredirected"];
+
+ 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://host/main1.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ auto pidAfterFirstLoad = [webView _webProcessIdentifier];
+
+ EXPECT_FALSE(serverRedirected);
+ EXPECT_EQ(1, numberOfDecidePolicyCalls);
+ EXPECT_EQ(1u, seenPIDs.size());
+ EXPECT_TRUE(*seenPIDs.begin() == pidAfterFirstLoad);
+
+ request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://host/main2.html"]];
+ [webView loadRequest:request];
+
+ TestWebKitAPI::Util::run(&serverRedirected);
+ serverRedirected = false;
+
+ seenPIDs.add([webView _webProcessIdentifier]);
+
+ TestWebKitAPI::Util::run(&done);
+ done = false;
+
+ seenPIDs.add([webView _webProcessIdentifier]);
+
+ EXPECT_FALSE(serverRedirected);
+ EXPECT_EQ(3, numberOfDecidePolicyCalls);
+ EXPECT_EQ(2u, seenPIDs.size());
+}
+
+
#endif // WK_API_ENABLED