Title: [223431] trunk/Source/WebKit
Revision
223431
Author
[email protected]
Date
2017-10-16 13:29:35 -0700 (Mon, 16 Oct 2017)

Log Message

[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:

Modified Paths

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
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to