Diff
Modified: trunk/Source/WebKit/ChangeLog (222307 => 222308)
--- trunk/Source/WebKit/ChangeLog 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/ChangeLog 2017-09-21 02:48:38 UTC (rev 222308)
@@ -1,3 +1,34 @@
+2017-09-20 Chris Dumez <[email protected]>
+
+ [WK2] Add API to get the redirect chain of a WKDownload
+ https://bugs.webkit.org/show_bug.cgi?id=176628
+ <rdar://problem/34338279>
+
+ Reviewed by Alex Christensen.
+
+ Add API to get the redirect chain of a WKDwnload. The redirect chain includes redirects
+ that happened during initial load, before the load was converted into a download.
+
+ * UIProcess/API/C/WKDownload.cpp:
+ (WKDownloadCopyRedirectChain):
+ * UIProcess/API/C/WKDownload.h:
+ * UIProcess/API/Cocoa/_WKDownload.h:
+ * UIProcess/API/Cocoa/_WKDownload.mm:
+ (-[_WKDownload originatingWebView]):
+ (-[_WKDownload redirectChain]):
+ * UIProcess/Downloads/DownloadProxy.cpp:
+ (WebKit::DownloadProxy::willSendRequest):
+ * UIProcess/Downloads/DownloadProxy.h:
+ (WebKit::DownloadProxy::setRedirectChain):
+ (WebKit::DownloadProxy::redirectChain const):
+ * UIProcess/WebFrameProxy.cpp:
+ (WebKit::WebFrameProxy::didStartProvisionalLoad):
+ (WebKit::WebFrameProxy::didReceiveServerRedirectForProvisionalLoad):
+ * UIProcess/WebFrameProxy.h:
+ (WebKit::WebFrameProxy::redirectChain const):
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::receivedPolicyDecision):
+
2017-09-20 Alex Christensen <[email protected]>
Add infrastructure for adding custom headers to requests per website
Modified: trunk/Source/WebKit/UIProcess/API/C/WKDownload.cpp (222307 => 222308)
--- trunk/Source/WebKit/UIProcess/API/C/WKDownload.cpp 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/UIProcess/API/C/WKDownload.cpp 2017-09-21 02:48:38 UTC (rev 222308)
@@ -26,6 +26,7 @@
#include "config.h"
#include "WKDownload.h"
+#include "APIArray.h"
#include "APIData.h"
#include "APIURLRequest.h"
#include "DownloadProxy.h"
@@ -63,3 +64,13 @@
{
return toAPI(toImpl(download)->originatingPage());
}
+
+WKArrayRef WKDownloadCopyRedirectChain(WKDownloadRef download)
+{
+ auto& redirectChain = toImpl(download)->redirectChain();
+ Vector<RefPtr<API::Object>> urls;
+ urls.reserveInitialCapacity(redirectChain.size());
+ for (auto& redirectURL : redirectChain)
+ urls.uncheckedAppend(API::URL::create(redirectURL.string()));
+ return toAPI(&API::Array::create(WTFMove(urls)).leakRef());
+}
Modified: trunk/Source/WebKit/UIProcess/API/C/WKDownload.h (222307 => 222308)
--- trunk/Source/WebKit/UIProcess/API/C/WKDownload.h 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/UIProcess/API/C/WKDownload.h 2017-09-21 02:48:38 UTC (rev 222308)
@@ -43,6 +43,7 @@
WK_EXPORT WKDataRef WKDownloadGetResumeData(WKDownloadRef download);
WK_EXPORT void WKDownloadCancel(WKDownloadRef download);
WK_EXPORT WKPageRef WKDownloadGetOriginatingPage(WKDownloadRef download);
+WK_EXPORT WKArrayRef WKDownloadCopyRedirectChain(WKDownloadRef download);
#ifdef __cplusplus
}
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.h (222307 => 222308)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.h 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.h 2017-09-21 02:48:38 UTC (rev 222308)
@@ -38,6 +38,7 @@
@property (nonatomic, readonly) NSURLRequest *request;
@property (nonatomic, readonly, weak) WKWebView *originatingWebView;
+@property (nonatomic, readonly, copy) NSArray<NSURL *> *redirectChain WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
@end
Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.mm (222307 => 222308)
--- trunk/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.mm 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/_WKDownload.mm 2017-09-21 02:48:38 UTC (rev 222308)
@@ -58,7 +58,15 @@
if (auto* originatingPage = _download->originatingPage())
return [[fromWebPageProxy(*originatingPage) retain] autorelease];
return nil;
+}
+-(NSArray<NSURL *> *)redirectChain
+{
+ auto& redirectURLs = _download->redirectChain();
+ NSMutableArray<NSURL *> *nsURLs = [NSMutableArray arrayWithCapacity:redirectURLs.size()];
+ for (const auto& redirectURL : redirectURLs)
+ [nsURLs addObject:(NSURL *)redirectURL];
+ return nsURLs;
}
#pragma mark WKObject protocol implementation
Modified: trunk/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp (222307 => 222308)
--- trunk/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/UIProcess/Downloads/DownloadProxy.cpp 2017-09-21 02:48:38 UTC (rev 222308)
@@ -107,6 +107,9 @@
m_request = request;
m_suggestedFilename = suggestedFilename;
+ if (m_redirectChain.isEmpty() || m_redirectChain.last() != request.url())
+ m_redirectChain.append(request.url());
+
if (!m_processPool)
return;
@@ -144,8 +147,9 @@
if (!m_processPool)
return;
- RefPtr<DownloadProxy> protectedThis(this);
- m_processPool->downloadClient().willSendRequest(m_processPool.get(), this, proposedRequest, redirectResponse, [protectedThis](const ResourceRequest& newRequest) {
+ m_processPool->downloadClient().willSendRequest(m_processPool.get(), this, proposedRequest, redirectResponse, [this, protectedThis = makeRef(*this)](const ResourceRequest& newRequest) {
+ m_redirectChain.append(newRequest.url());
+
#if USE(NETWORK_SESSION)
if (!protectedThis->m_processPool)
return;
@@ -155,8 +159,6 @@
return;
networkProcessProxy->send(Messages::NetworkProcess::ContinueWillSendRequest(protectedThis->m_downloadID, newRequest), 0);
-#else
- UNUSED_PARAM(newRequest);
#endif
});
}
Modified: trunk/Source/WebKit/UIProcess/Downloads/DownloadProxy.h (222307 => 222308)
--- trunk/Source/WebKit/UIProcess/Downloads/DownloadProxy.h 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/UIProcess/Downloads/DownloadProxy.h 2017-09-21 02:48:38 UTC (rev 222308)
@@ -44,6 +44,7 @@
class ProtectionSpace;
class ResourceError;
class ResourceResponse;
+class URL;
}
namespace WebKit {
@@ -73,6 +74,9 @@
WebPageProxy* originatingPage() const;
void setOriginatingPage(WebPageProxy*);
+ void setRedirectChain(Vector<WebCore::URL>&& redirectChain) { m_redirectChain = WTFMove(redirectChain); }
+ const Vector<WebCore::URL>& redirectChain() const { return m_redirectChain; }
+
private:
explicit DownloadProxy(DownloadProxyMap&, WebProcessPool&, const WebCore::ResourceRequest&);
@@ -109,6 +113,7 @@
String m_suggestedFilename;
WeakPtr<WebPageProxy> m_originatingPage;
+ Vector<WebCore::URL> m_redirectChain;
};
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp (222307 => 222308)
--- trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp 2017-09-21 02:48:38 UTC (rev 222308)
@@ -132,11 +132,18 @@
void WebFrameProxy::didStartProvisionalLoad(const URL& url)
{
+ ASSERT(m_provisionalLoadRedirectChain.isEmpty());
+ m_provisionalLoadRedirectChain = { url };
+
m_frameLoadState.didStartProvisionalLoad(url);
}
void WebFrameProxy::didReceiveServerRedirectForProvisionalLoad(const URL& url)
{
+ // didReceiveServerRedirectForProvisionalLoad() often gets called twice for the same redirect.
+ if (m_provisionalLoadRedirectChain.isEmpty() || m_provisionalLoadRedirectChain.last() != url)
+ m_provisionalLoadRedirectChain.append(url);
+
m_frameLoadState.didReceiveServerRedirectForProvisionalLoad(url);
}
@@ -158,11 +165,13 @@
void WebFrameProxy::didFinishLoad()
{
+ m_provisionalLoadRedirectChain.clear();
m_frameLoadState.didFinishLoad();
}
void WebFrameProxy::didFailLoad()
{
+ m_provisionalLoadRedirectChain.clear();
m_frameLoadState.didFailLoad();
}
Modified: trunk/Source/WebKit/UIProcess/WebFrameProxy.h (222307 => 222308)
--- trunk/Source/WebKit/UIProcess/WebFrameProxy.h 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/UIProcess/WebFrameProxy.h 2017-09-21 02:48:38 UTC (rev 222308)
@@ -90,6 +90,7 @@
bool containsPluginDocument() const { return m_containsPluginDocument; }
const String& title() const { return m_title; }
+ Vector<WebCore::URL>&& takeProvisionalLoadRedirectChain() { return WTFMove(m_provisionalLoadRedirectChain); }
WebCertificateInfo* certificateInfo() const { return m_certificateInfo.get(); }
@@ -142,7 +143,7 @@
RefPtr<WebCertificateInfo> m_certificateInfo;
RefPtr<WebFrameListenerProxy> m_activeListener;
uint64_t m_frameID;
-
+ Vector<WebCore::URL> m_provisionalLoadRedirectChain;
#if ENABLE(CONTENT_FILTERING)
WebCore::ContentFilterUnblockHandler m_contentFilterUnblockHandler;
#endif
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (222307 => 222308)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2017-09-21 02:48:38 UTC (rev 222308)
@@ -2278,6 +2278,8 @@
if (action == PolicyDownload) {
// Create a download proxy.
auto* download = m_process->processPool().createDownloadProxy(m_decidePolicyForResponseRequest, this);
+ download->setRedirectChain(frame.takeProvisionalLoadRedirectChain());
+
downloadID = download->downloadID();
handleDownloadRequest(download);
m_decidePolicyForResponseRequest = { };
Modified: trunk/Tools/ChangeLog (222307 => 222308)
--- trunk/Tools/ChangeLog 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Tools/ChangeLog 2017-09-21 02:48:38 UTC (rev 222308)
@@ -1,3 +1,22 @@
+2017-09-20 Chris Dumez <[email protected]>
+
+ [WK2] Add API to get the redirect chain of a WKDownload
+ https://bugs.webkit.org/show_bug.cgi?id=176628
+ <rdar://problem/34338279>
+
+ Reviewed by Alex Christensen.
+
+ Add API test coverage for the 2 cases:
+ 1. Download started as a download and is redirected while
+ downloading.
+ 2. Download started as a load and was redirected during the
+ initial load.
+
+ * TestWebKitAPI/Tests/WebKitCocoa/Download.mm:
+ (-[RedirectedDownloadDelegate _download:didReceiveServerRedirectToURL:]):
+ (-[RedirectedDownloadDelegate _downloadDidFinish:]):
+ (TEST):
+
2017-09-20 Alex Christensen <[email protected]>
Add infrastructure for adding custom headers to requests per website
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Download.mm (222307 => 222308)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Download.mm 2017-09-21 01:34:12 UTC (rev 222307)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/Download.mm 2017-09-21 02:48:38 UTC (rev 222308)
@@ -46,7 +46,7 @@
#import <wtf/text/WTFString.h>
static bool isDone;
-static bool hasReceivedRedirect;
+static unsigned redirectCount = 0;
static bool hasReceivedResponse;
static NSURL *sourceURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
static WKWebView* expectedOriginatingWebView;
@@ -468,12 +468,24 @@
- (void)_download:(_WKDownload *)download didReceiveServerRedirectToURL:(NSURL *)url
{
- EXPECT_STREQ("http://pass/", [url.absoluteString UTF8String]);
- hasReceivedRedirect = true;
+ if (!redirectCount)
+ EXPECT_STREQ("http://redirect/?pass", [url.absoluteString UTF8String]);
+ else
+ EXPECT_STREQ("http://pass/", [url.absoluteString UTF8String]);
+ ++redirectCount = true;
}
- (void)_downloadDidFinish:(_WKDownload *)download
{
+ NSArray<NSURL *> *redirectChain = download.redirectChain;
+ EXPECT_EQ(3U, redirectChain.count);
+ if (redirectChain.count > 0)
+ EXPECT_STREQ("http://redirect/?redirect/?pass", [redirectChain[0].absoluteString UTF8String]);
+ if (redirectChain.count > 1)
+ EXPECT_STREQ("http://redirect/?pass", [redirectChain[1].absoluteString UTF8String]);
+ if (redirectChain.count > 2)
+ EXPECT_STREQ("http://pass/", [redirectChain[2].absoluteString UTF8String]);
+
WebCore::deleteFile(_destinationPath);
isDone = true;
}
@@ -484,7 +496,7 @@
{
[TestProtocol registerWithScheme:@"http"];
- hasReceivedRedirect = false;
+ redirectCount = 0;
isDone = false;
auto delegate = adoptNS([[UIDownloadAsFileTestDelegate alloc] init]);
@@ -497,7 +509,9 @@
auto window = adoptNS([[NSWindow alloc] initWithContentRect:[webView frame] styleMask:NSWindowStyleMaskBorderless backing:NSBackingStoreBuffered defer:YES]);
[[window contentView] addSubview:webView.get()];
- [webView synchronouslyLoadHTMLString:@"<a style='display: block; height: 100%; width: 100%' href=''>test</a>"];
+ // Do 2 loads in the same view to make sure the redirect chain is properly cleared between loads.
+ [webView synchronouslyLoadHTMLString:@"<div>First load</div>"];
+ [webView synchronouslyLoadHTMLString:@"<a style='display: block; height: 100%; width: 100%' href=''>test</a>"];
expectedOriginatingWebView = webView.get();
NSPoint clickPoint = NSMakePoint(100, 100);
@@ -506,10 +520,54 @@
isDone = false;
TestWebKitAPI::Util::run(&isDone);
- EXPECT_TRUE(hasReceivedRedirect);
+ EXPECT_EQ(1U, redirectCount);
[TestProtocol unregister];
}
+TEST(_WKDownload, RedirectedLoadConvertedToDownload)
+{
+ [TestProtocol registerWithScheme:@"http"];
+
+ auto navigationDelegate = adoptNS([[ConvertResponseToDownloadNavigationDelegate alloc] init]);
+ auto downloadDelegate = adoptNS([[RedirectedDownloadDelegate alloc] init]);
+
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+ [webView setNavigationDelegate:navigationDelegate.get()];
+ [[[webView configuration] processPool] _setDownloadDelegate:downloadDelegate.get()];
+
+ expectedOriginatingWebView = webView.get();
+ isDone = false;
+ redirectCount = 0;
+ hasReceivedResponse = false;
+ [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://redirect/?redirect/?pass"]]];
+ TestWebKitAPI::Util::run(&isDone);
+ EXPECT_EQ(0U, redirectCount);
+
+ [TestProtocol unregister];
+}
+
+TEST(_WKDownload, RedirectedSubframeLoadConvertedToDownload)
+{
+ [TestProtocol registerWithScheme:@"http"];
+
+ auto navigationDelegate = adoptNS([[ConvertResponseToDownloadNavigationDelegate alloc] init]);
+ auto downloadDelegate = adoptNS([[RedirectedDownloadDelegate alloc] init]);
+
+ auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600)]);
+ [webView setNavigationDelegate:navigationDelegate.get()];
+ [[[webView configuration] processPool] _setDownloadDelegate:downloadDelegate.get()];
+
+ expectedOriginatingWebView = webView.get();
+ isDone = false;
+ redirectCount = 0;
+ hasReceivedResponse = false;
+ [webView loadHTMLString:@"<body><iframe src=''></iframe></body>" baseURL:nil];
+ TestWebKitAPI::Util::run(&isDone);
+ EXPECT_EQ(0U, redirectCount);
+
+ [TestProtocol unregister];
+}
+
#endif
#endif