Diff
Modified: trunk/Source/WebKit/ChangeLog (223430 => 223431)
--- trunk/Source/WebKit/ChangeLog 2017-10-16 20:28:53 UTC (rev 223430)
+++ trunk/Source/WebKit/ChangeLog 2017-10-16 20:29:35 UTC (rev 223431)
@@ -1,3 +1,39 @@
+2017-10-16 Chris Dumez <[email protected]>
+
+ [WK2][NetworkSession] Add support for resuming downloads
+ https://bugs.webkit.org/show_bug.cgi?id=177625
+ <rdar://problem/34345975>
+
+ Reviewed by Alex Christensen.
+
+ Add support for resuming downloads for the WK2 NETWORK_SESSION code path.
+
+ This was tested manually. I was unable to write an API test because our tests
+ do not run an HTTP server and CFNetwork does not seem to generate resume data
+ when cancelling a download over non-HTTP.
+
+ * NetworkProcess/Downloads/Download.cpp:
+ (WebKit::Download::didReceiveChallenge):
+ (WebKit::Download::continueCanAuthenticateAgainstProtectionSpace):
+ * NetworkProcess/Downloads/Download.h:
+ * NetworkProcess/Downloads/DownloadManager.cpp:
+ (WebKit::DownloadManager::continueCanAuthenticateAgainstProtectionSpace):
+ (WebKit::DownloadManager::resumeDownload):
+ * NetworkProcess/Downloads/cocoa/DownloadCocoa.mm:
+ (WebKit::Download::resume):
+ This currently includes a workaround for <rdar://problem/34745171>. We update the
+ resume data to include the NSURLSessionResumeInfoLocalPath key with the final
+ destination path so that CFNetwork looks for the temporary data at the right
+ location.
+
+ * NetworkProcess/cocoa/NetworkSessionCocoa.h:
+ * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+ (-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
+ (WebKit::NetworkSessionCocoa::downloadTaskWithResumeData):
+ * Shared/Authentication/AuthenticationManager.cpp:
+ (WebKit::AuthenticationManager::didReceiveAuthenticationChallenge):
+ * Shared/Authentication/AuthenticationManager.h:
+
2017-10-16 Adrian Perez de Castro <[email protected]>
[WPE] Build failure due to invalid cast of EGLNativeWindowType when targetting 64-bit ARM
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/Download.cpp (223430 => 223431)
--- trunk/Source/WebKit/NetworkProcess/Downloads/Download.cpp 2017-10-16 20:28:53 UTC (rev 223430)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/Download.cpp 2017-10-16 20:29:35 UTC (rev 223431)
@@ -34,10 +34,16 @@
#include "DownloadProxyMessages.h"
#include "Logging.h"
#include "NetworkDataTask.h"
+#include "NetworkProcess.h"
+#include "NetworkSession.h"
#include "SandboxExtension.h"
#include "WebCoreArgumentCoders.h"
#include <WebCore/NotImplemented.h>
+#if PLATFORM(COCOA)
+#include "NetworkDataTaskCocoa.h"
+#endif
+
using namespace WebCore;
#define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), Network, "%p - Download::" fmt, this, ##__VA_ARGS__)
@@ -146,6 +152,41 @@
platformCancelNetworkLoad();
}
+#if USE(NETWORK_SESSION)
+void Download::didReceiveChallenge(const WebCore::AuthenticationChallenge& challenge, ChallengeCompletionHandler&& completionHandler)
+{
+ if (challenge.protectionSpace().isPasswordBased() && !challenge.proposedCredential().isEmpty() && !challenge.previousFailureCount()) {
+ completionHandler(AuthenticationChallengeDisposition::UseCredential, challenge.proposedCredential());
+ return;
+ }
+
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+ m_challenge = challenge;
+ m_challengeCompletionHandler = WTFMove(completionHandler);
+ send(Messages::DownloadProxy::CanAuthenticateAgainstProtectionSpace(challenge.protectionSpace()));
+#else
+ NetworkProcess::singleton().authenticationManager().didReceiveAuthenticationChallenge(*this, challenge, WTFMove(completionHandler));
+#endif
+}
+
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+void Download::continueCanAuthenticateAgainstProtectionSpace(bool canAuthenticate)
+{
+ ASSERT(m_challengeCompletionHandler);
+ auto completionHandler = std::exchange(m_challengeCompletionHandler, nullptr);
+ if (!canAuthenticate) {
+ if (NetworkSession::allowsSpecificHTTPSCertificateForHost(*m_challenge))
+ completionHandler(AuthenticationChallengeDisposition::UseCredential, serverTrustCredential(*m_challenge));
+ else
+ completionHandler(AuthenticationChallengeDisposition::RejectProtectionSpace, { });
+ return;
+ }
+
+ NetworkProcess::singleton().authenticationManager().didReceiveAuthenticationChallenge(*this, *m_challenge, WTFMove(completionHandler));
+}
+#endif // USE(PROTECTION_SPACE_AUTH_CALLBACK)
+#endif // USE(NETWORK_SESSION)
+
#if !USE(NETWORK_SESSION)
void Download::didStart()
{
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/Download.h (223430 => 223431)
--- trunk/Source/WebKit/NetworkProcess/Downloads/Download.h 2017-10-16 20:28:53 UTC (rev 223430)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/Download.h 2017-10-16 20:29:35 UTC (rev 223431)
@@ -38,6 +38,8 @@
#include <wtf/RetainPtr.h>
#if USE(NETWORK_SESSION)
+#include "NetworkDataTask.h"
+#include <WebCore/AuthenticationChallenge.h>
#if PLATFORM(COCOA)
OBJC_CLASS NSURLSessionDownloadTask;
#endif
@@ -101,6 +103,10 @@
#if USE(NETWORK_SESSION)
void setSandboxExtension(RefPtr<SandboxExtension>&& sandboxExtension) { m_sandboxExtension = WTFMove(sandboxExtension); }
+ void didReceiveChallenge(const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler&&);
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+ void continueCanAuthenticateAgainstProtectionSpace(bool canAuthenticate);
+#endif
#else
const WebCore::ResourceRequest& request() const { return m_request; }
void didReceiveAuthenticationChallenge(const WebCore::AuthenticationChallenge&);
@@ -146,6 +152,10 @@
RetainPtr<NSURLSessionDownloadTask> m_downloadTask;
#endif
PAL::SessionID m_sessionID;
+#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
+ std::optional<WebCore::AuthenticationChallenge> m_challenge;
+ ChallengeCompletionHandler m_challengeCompletionHandler;
+#endif
#else // USE(NETWORK_SESSION)
WebCore::ResourceRequest m_request;
String m_responseMIMEType;
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/DownloadManager.cpp (223430 => 223431)
--- trunk/Source/WebKit/NetworkProcess/Downloads/DownloadManager.cpp 2017-10-16 20:28:53 UTC (rev 223430)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/DownloadManager.cpp 2017-10-16 20:29:35 UTC (rev 223431)
@@ -89,10 +89,15 @@
#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
void DownloadManager::continueCanAuthenticateAgainstProtectionSpace(DownloadID downloadID, bool canAuthenticate)
{
- auto* pendingDownload = m_pendingDownloads.get(downloadID);
- ASSERT(pendingDownload);
- if (pendingDownload)
+ if (auto* pendingDownload = m_pendingDownloads.get(downloadID)) {
pendingDownload->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate);
+ return;
+ }
+ if (auto* download = m_downloads.get(downloadID)) {
+ download->continueCanAuthenticateAgainstProtectionSpace(canAuthenticate);
+ return;
+ }
+ ASSERT_NOT_REACHED();
}
#endif
@@ -162,13 +167,17 @@
#endif
}
-void DownloadManager::resumeDownload(PAL::SessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, const SandboxExtension::Handle& sandboxExtensionHandle)
+void DownloadManager::resumeDownload(PAL::SessionID sessionID, DownloadID downloadID, const IPC::DataReference& resumeData, const String& path, const SandboxExtension::Handle& sandboxExtensionHandle)
{
-#if USE(NETWORK_SESSION)
+#if USE(NETWORK_SESSION) && !PLATFORM(COCOA)
notImplemented();
#else
+#if USE(NETWORK_SESSION)
+ auto download = std::make_unique<Download>(*this, downloadID, nullptr, sessionID);
+#else
// Download::resume() is responsible for setting the Download's resource request.
auto download = std::make_unique<Download>(*this, downloadID, ResourceRequest());
+#endif
download->resume(resumeData, path, sandboxExtensionHandle);
ASSERT(!m_downloads.contains(downloadID));
Modified: trunk/Source/WebKit/NetworkProcess/Downloads/cocoa/DownloadCocoa.mm (223430 => 223431)
--- trunk/Source/WebKit/NetworkProcess/Downloads/cocoa/DownloadCocoa.mm 2017-10-16 20:28:53 UTC (rev 223430)
+++ trunk/Source/WebKit/NetworkProcess/Downloads/cocoa/DownloadCocoa.mm 2017-10-16 20:29:35 UTC (rev 223431)
@@ -29,13 +29,36 @@
#if USE(NETWORK_SESSION)
#import "DataReference.h"
-#import <WebCore/NotImplemented.h>
+#import "NetworkSessionCocoa.h"
+#import "SessionTracker.h"
+#import <pal/spi/cf/CFNetworkSPI.h>
namespace WebKit {
void Download::resume(const IPC::DataReference& resumeData, const String& path, const SandboxExtension::Handle& sandboxExtensionHandle)
{
- notImplemented();
+ m_sandboxExtension = SandboxExtension::create(sandboxExtensionHandle);
+ if (m_sandboxExtension)
+ m_sandboxExtension->consume();
+
+ auto* networkSession = SessionTracker::networkSession(m_sessionID);
+ if (!networkSession) {
+ WTFLogAlways("Could not find network session with given session ID");
+ return;
+ }
+ auto& cocoaSession = static_cast<NetworkSessionCocoa&>(*networkSession);
+ auto nsData = adoptNS([[NSData alloc] initWithBytes:resumeData.data() length:resumeData.size()]);
+
+ // FIXME: This is a temporary workaround for <rdar://problem/34745171>.
+ NSMutableDictionary *dictionary = [NSPropertyListSerialization propertyListWithData:nsData.get() options:NSPropertyListImmutable format:0 error:nullptr];
+ [dictionary setObject:static_cast<NSString*>(path) forKey:@"NSURLSessionResumeInfoLocalPath"];
+ NSData *updatedData = [NSPropertyListSerialization dataWithPropertyList:dictionary format:NSPropertyListXMLFormat_v1_0 options:0 error:nullptr];
+
+ m_downloadTask = cocoaSession.downloadTaskWithResumeData(updatedData);
+ cocoaSession.addDownloadID(m_downloadTask.get().taskIdentifier, m_downloadID);
+ m_downloadTask.get()._pathToDownloadTaskFile = path;
+
+ [m_downloadTask resume];
}
void Download::platformCancelNetworkLoad()
Modified: trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h (223430 => 223431)
--- trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h 2017-10-16 20:28:53 UTC (rev 223430)
+++ trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.h 2017-10-16 20:29:35 UTC (rev 223431)
@@ -27,7 +27,9 @@
#if USE(NETWORK_SESSION)
+OBJC_CLASS NSData;
OBJC_CLASS NSURLSession;
+OBJC_CLASS NSURLSessionDownloadTask;
OBJC_CLASS NSOperationQueue;
OBJC_CLASS WKNetworkSessionDelegate;
@@ -58,6 +60,7 @@
#endif
NetworkDataTaskCocoa* dataTaskForIdentifier(NetworkDataTaskCocoa::TaskIdentifier, WebCore::StoredCredentialsPolicy);
+ NSURLSessionDownloadTask* downloadTaskWithResumeData(NSData*);
void addDownloadID(NetworkDataTaskCocoa::TaskIdentifier, DownloadID);
DownloadID downloadID(NetworkDataTaskCocoa::TaskIdentifier);
Modified: trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm (223430 => 223431)
--- trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm 2017-10-16 20:28:53 UTC (rev 223430)
+++ trunk/Source/WebKit/NetworkProcess/cocoa/NetworkSessionCocoa.mm 2017-10-16 20:29:35 UTC (rev 223431)
@@ -278,6 +278,21 @@
};
networkDataTask->didReceiveChallenge(challenge, WTFMove(challengeCompletionHandler));
} else {
+ auto downloadID = _session->downloadID(task.taskIdentifier);
+ if (downloadID.downloadID()) {
+ if (auto* download = WebKit::NetworkProcess::singleton().downloadManager().download(downloadID)) {
+ // Received an authentication challenge for a download being resumed.
+ WebCore::AuthenticationChallenge authenticationChallenge { challenge };
+ auto completionHandlerCopy = Block_copy(completionHandler);
+ auto sessionID = _session->sessionID();
+ auto challengeCompletionHandler = [completionHandlerCopy, sessionID, authenticationChallenge](WebKit::AuthenticationChallengeDisposition disposition, const WebCore::Credential& credential) {
+ completionHandlerCopy(toNSURLSessionAuthChallengeDisposition(disposition), credential.nsCredential());
+ Block_release(completionHandlerCopy);
+ };
+ download->didReceiveChallenge(challenge, WTFMove(challengeCompletionHandler));
+ return;
+ }
+ }
LOG(NetworkSession, "%llu didReceiveChallenge completionHandler (cancel)", taskIdentifier);
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
}
@@ -671,6 +686,11 @@
return m_dataTaskMapWithoutState.get(taskIdentifier);
}
+NSURLSessionDownloadTask* NetworkSessionCocoa::downloadTaskWithResumeData(NSData* resumeData)
+{
+ return [m_sessionWithCredentialStorage downloadTaskWithResumeData:resumeData];
+}
+
void NetworkSessionCocoa::addDownloadID(NetworkDataTaskCocoa::TaskIdentifier taskIdentifier, DownloadID downloadID)
{
#ifndef NDEBUG
Modified: trunk/Source/WebKit/Shared/Authentication/AuthenticationManager.cpp (223430 => 223431)
--- trunk/Source/WebKit/Shared/Authentication/AuthenticationManager.cpp 2017-10-16 20:28:53 UTC (rev 223430)
+++ trunk/Source/WebKit/Shared/Authentication/AuthenticationManager.cpp 2017-10-16 20:29:35 UTC (rev 223431)
@@ -144,7 +144,7 @@
m_process.send(Messages::NetworkProcessProxy::DidReceiveAuthenticationChallenge(pageID, frameID, authenticationChallenge, challengeID));
}
-void AuthenticationManager::didReceiveAuthenticationChallenge(PendingDownload& pendingDownload, const WebCore::AuthenticationChallenge& authenticationChallenge, ChallengeCompletionHandler&& completionHandler)
+void AuthenticationManager::didReceiveAuthenticationChallenge(IPC::MessageSender& download, const WebCore::AuthenticationChallenge& authenticationChallenge, ChallengeCompletionHandler&& completionHandler)
{
uint64_t dummyPageID = 0;
uint64_t challengeID = addChallengeToChallengeMap({ dummyPageID, authenticationChallenge, WTFMove(completionHandler) });
@@ -153,7 +153,7 @@
if (shouldCoalesceChallenge(dummyPageID, challengeID, authenticationChallenge))
return;
- pendingDownload.send(Messages::DownloadProxy::DidReceiveAuthenticationChallenge(authenticationChallenge, challengeID));
+ download.send(Messages::DownloadProxy::DidReceiveAuthenticationChallenge(authenticationChallenge, challengeID));
}
#endif
Modified: trunk/Source/WebKit/Shared/Authentication/AuthenticationManager.h (223430 => 223431)
--- trunk/Source/WebKit/Shared/Authentication/AuthenticationManager.h 2017-10-16 20:28:53 UTC (rev 223430)
+++ trunk/Source/WebKit/Shared/Authentication/AuthenticationManager.h 2017-10-16 20:29:35 UTC (rev 223431)
@@ -34,6 +34,10 @@
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
+namespace IPC {
+class MessageSender;
+}
+
namespace WebCore {
class AuthenticationChallenge;
class CertificateInfo;
@@ -45,7 +49,6 @@
class ChildProcess;
class Download;
class DownloadID;
-class PendingDownload;
class WebFrame;
enum class AuthenticationChallengeDisposition {
@@ -65,7 +68,7 @@
#if USE(NETWORK_SESSION)
void didReceiveAuthenticationChallenge(uint64_t pageID, uint64_t frameID, const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler&&);
- void didReceiveAuthenticationChallenge(PendingDownload&, const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler&&);
+ void didReceiveAuthenticationChallenge(IPC::MessageSender& download, const WebCore::AuthenticationChallenge&, ChallengeCompletionHandler&&);
#if USE(PROTECTION_SPACE_AUTH_CALLBACK)
void continueCanAuthenticateAgainstProtectionSpace(DownloadID, bool canAuthenticate);
#endif