<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[196984] trunk/Source/WebKit2</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/196984">196984</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2016-02-23 11:13:18 -0800 (Tue, 23 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement downloads with NetworkSession
https://bugs.webkit.org/show_bug.cgi?id=154473

Reviewed by Brady Eidson.

* NetworkProcess/Downloads/Download.cpp:
(WebKit::Download::~Download):
(WebKit::Download::didStart):
(WebKit::Download::shouldDecodeSourceDataOfMIMEType):
(WebKit::Download::decideDestinationWithSuggestedFilename):
(WebKit::Download::didCreateDestination):
* NetworkProcess/Downloads/Download.h:
(WebKit::Download::downloadID):
(WebKit::Download::setSandboxExtension):
* NetworkProcess/Downloads/DownloadManager.cpp:
(WebKit::DownloadManager::startDownload):
(WebKit::DownloadManager::dataTaskBecameDownloadTask):
(WebKit::DownloadManager::continueCanAuthenticateAgainstProtectionSpace):
(WebKit::DownloadManager::continueWillSendRequest):
(WebKit::DownloadManager::willDecidePendingDownloadDestination):
(WebKit::DownloadManager::continueDecidePendingDownloadDestination):
(WebKit::DownloadManager::convertHandleToDownload):
* NetworkProcess/Downloads/DownloadManager.h:
* NetworkProcess/NetworkDataTask.h:
(WebKit::NetworkDataTask::clearClient):

NetworkDataTasks can now outlive their client, so we need to make client a pointer
with the ability to be nulled from the client's destructor.

(WebKit::NetworkDataTask::pendingDownloadID):
(WebKit::NetworkDataTask::pendingDownload):
(WebKit::NetworkDataTask::setPendingDownload):
(WebKit::NetworkDataTask::pendingDownloadLocation):
(WebKit::NetworkDataTask::client): Deleted.
* NetworkProcess/NetworkLoad.cpp:
(WebKit::NetworkLoad::~NetworkLoad):
(WebKit::NetworkLoad::convertTaskToDownload):
(WebKit::NetworkLoad::setPendingDownloadID):
(WebKit::NetworkLoad::didReceiveResponseNetworkSession):

Don't call the didReceiveResponse completion handler immediately when we know we are
going to turn the load into a download.  Instead, save the completion handler until
after we have determined the download destination and set it in the NetworkDataTask.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::continueWillSendRequest):
(WebKit::NetworkProcess::findPendingDownloadLocation):
(WebKit::NetworkProcess::continueDecidePendingDownloadDestination):
(WebKit::NetworkProcess::setCacheModel):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTask::NetworkDataTask):
(WebKit::NetworkDataTask::~NetworkDataTask):
(WebKit::NetworkDataTask::didSendData):
(WebKit::NetworkDataTask::didReceiveChallenge):
(WebKit::NetworkDataTask::didCompleteWithError):
(WebKit::NetworkDataTask::didReceiveResponse):
(WebKit::NetworkDataTask::didReceiveData):
(WebKit::NetworkDataTask::didBecomeDownload):
(WebKit::NetworkDataTask::willPerformHTTPRedirection):
(WebKit::NetworkDataTask::scheduleFailure):
(WebKit::NetworkDataTask::failureTimerFired):
(WebKit::NetworkDataTask::findPendingDownloadLocation):
(WebKit::NetworkDataTask::setPendingDownloadLocation):
(WebKit::NetworkDataTask::tryPasswordBasedAuthentication):
(WebKit::NetworkDataTask::transferSandboxExtensionToDownload):
(WebKit::NetworkDataTask::currentRequest):
(WebKit::NetworkDataTask::cancel):
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:]):
(-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:task:didCompleteWithError:]):
        
This delegate callback is used for downloads, too.

(-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveResponse:completionHandler:]):
(-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveData:]):
(-[WKNetworkSessionDelegate URLSession:downloadTask:didFinishDownloadingToURL:]):
(-[WKNetworkSessionDelegate URLSession:dataTask:didBecomeDownloadTask:]):
        
Call didCreateDestination now, which is after the file has been opened on the disk.
A DownloadProxy::DidStart message is now sent from NetworkProcess::findPendingDownloadLocation before
we ask the UIProcess where the download should end up on disk.
Null check the NetworkDataTask's client before using it because it is now a pointer that could be null. 
        
* UIProcess/Downloads/DownloadProxy.cpp:
(WebKit::DownloadProxy::shouldDecodeSourceDataOfMIMEType):
(WebKit::DownloadProxy::decideDestinationWithSuggestedFilenameAsync):
(WebKit::DownloadProxy::decideDestinationWithSuggestedFilename):
(WebKit::DownloadProxy::didCreateDestination):
* UIProcess/Downloads/DownloadProxy.h:
* UIProcess/Downloads/DownloadProxy.messages.in:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessDownloadsDownloadcpp">trunk/Source/WebKit2/NetworkProcess/Downloads/Download.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessDownloadsDownloadh">trunk/Source/WebKit2/NetworkProcess/Downloads/Download.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessDownloadsDownloadManagercpp">trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessDownloadsDownloadManagerh">trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkDataTaskh">trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkLoadcpp">trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkProcesscpp">trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkProcessh">trunk/Source/WebKit2/NetworkProcess/NetworkProcess.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkProcessmessagesin">trunk/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscocoaNetworkDataTaskCocoamm">trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscocoaNetworkSessionCocoamm">trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessDownloadsDownloadProxycpp">trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessDownloadsDownloadProxyh">trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessDownloadsDownloadProxymessagesin">trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.messages.in</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/ChangeLog        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -1,3 +1,100 @@
</span><ins>+2016-02-23  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        Implement downloads with NetworkSession
+        https://bugs.webkit.org/show_bug.cgi?id=154473
+
+        Reviewed by Brady Eidson.
+
+        * NetworkProcess/Downloads/Download.cpp:
+        (WebKit::Download::~Download):
+        (WebKit::Download::didStart):
+        (WebKit::Download::shouldDecodeSourceDataOfMIMEType):
+        (WebKit::Download::decideDestinationWithSuggestedFilename):
+        (WebKit::Download::didCreateDestination):
+        * NetworkProcess/Downloads/Download.h:
+        (WebKit::Download::downloadID):
+        (WebKit::Download::setSandboxExtension):
+        * NetworkProcess/Downloads/DownloadManager.cpp:
+        (WebKit::DownloadManager::startDownload):
+        (WebKit::DownloadManager::dataTaskBecameDownloadTask):
+        (WebKit::DownloadManager::continueCanAuthenticateAgainstProtectionSpace):
+        (WebKit::DownloadManager::continueWillSendRequest):
+        (WebKit::DownloadManager::willDecidePendingDownloadDestination):
+        (WebKit::DownloadManager::continueDecidePendingDownloadDestination):
+        (WebKit::DownloadManager::convertHandleToDownload):
+        * NetworkProcess/Downloads/DownloadManager.h:
+        * NetworkProcess/NetworkDataTask.h:
+        (WebKit::NetworkDataTask::clearClient):
+
+        NetworkDataTasks can now outlive their client, so we need to make client a pointer
+        with the ability to be nulled from the client's destructor.
+
+        (WebKit::NetworkDataTask::pendingDownloadID):
+        (WebKit::NetworkDataTask::pendingDownload):
+        (WebKit::NetworkDataTask::setPendingDownload):
+        (WebKit::NetworkDataTask::pendingDownloadLocation):
+        (WebKit::NetworkDataTask::client): Deleted.
+        * NetworkProcess/NetworkLoad.cpp:
+        (WebKit::NetworkLoad::~NetworkLoad):
+        (WebKit::NetworkLoad::convertTaskToDownload):
+        (WebKit::NetworkLoad::setPendingDownloadID):
+        (WebKit::NetworkLoad::didReceiveResponseNetworkSession):
+
+        Don't call the didReceiveResponse completion handler immediately when we know we are
+        going to turn the load into a download.  Instead, save the completion handler until
+        after we have determined the download destination and set it in the NetworkDataTask.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::continueWillSendRequest):
+        (WebKit::NetworkProcess::findPendingDownloadLocation):
+        (WebKit::NetworkProcess::continueDecidePendingDownloadDestination):
+        (WebKit::NetworkProcess::setCacheModel):
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
+        (WebKit::NetworkDataTask::NetworkDataTask):
+        (WebKit::NetworkDataTask::~NetworkDataTask):
+        (WebKit::NetworkDataTask::didSendData):
+        (WebKit::NetworkDataTask::didReceiveChallenge):
+        (WebKit::NetworkDataTask::didCompleteWithError):
+        (WebKit::NetworkDataTask::didReceiveResponse):
+        (WebKit::NetworkDataTask::didReceiveData):
+        (WebKit::NetworkDataTask::didBecomeDownload):
+        (WebKit::NetworkDataTask::willPerformHTTPRedirection):
+        (WebKit::NetworkDataTask::scheduleFailure):
+        (WebKit::NetworkDataTask::failureTimerFired):
+        (WebKit::NetworkDataTask::findPendingDownloadLocation):
+        (WebKit::NetworkDataTask::setPendingDownloadLocation):
+        (WebKit::NetworkDataTask::tryPasswordBasedAuthentication):
+        (WebKit::NetworkDataTask::transferSandboxExtensionToDownload):
+        (WebKit::NetworkDataTask::currentRequest):
+        (WebKit::NetworkDataTask::cancel):
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (-[WKNetworkSessionDelegate URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:]):
+        (-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):
+        (-[WKNetworkSessionDelegate URLSession:task:didReceiveChallenge:completionHandler:]):
+        (-[WKNetworkSessionDelegate URLSession:task:didCompleteWithError:]):
+        
+        This delegate callback is used for downloads, too.
+
+        (-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveResponse:completionHandler:]):
+        (-[WKNetworkSessionDelegate URLSession:dataTask:didReceiveData:]):
+        (-[WKNetworkSessionDelegate URLSession:downloadTask:didFinishDownloadingToURL:]):
+        (-[WKNetworkSessionDelegate URLSession:dataTask:didBecomeDownloadTask:]):
+        
+        Call didCreateDestination now, which is after the file has been opened on the disk.
+        A DownloadProxy::DidStart message is now sent from NetworkProcess::findPendingDownloadLocation before
+        we ask the UIProcess where the download should end up on disk.
+        Null check the NetworkDataTask's client before using it because it is now a pointer that could be null. 
+        
+        * UIProcess/Downloads/DownloadProxy.cpp:
+        (WebKit::DownloadProxy::shouldDecodeSourceDataOfMIMEType):
+        (WebKit::DownloadProxy::decideDestinationWithSuggestedFilenameAsync):
+        (WebKit::DownloadProxy::decideDestinationWithSuggestedFilename):
+        (WebKit::DownloadProxy::didCreateDestination):
+        * UIProcess/Downloads/DownloadProxy.h:
+        * UIProcess/Downloads/DownloadProxy.messages.in:
+
</ins><span class="cx"> 2016-02-23  Brian Burg  &lt;bburg@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Connect WebAutomationSession to its backend dispatcher as if it were an agent and add stub implementations
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessDownloadsDownloadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/Downloads/Download.cpp (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/Downloads/Download.cpp        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/Downloads/Download.cpp        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -66,12 +66,7 @@
</span><span class="cx">     m_downloadManager.didDestroyDownload();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if USE(NETWORK_SESSION)
-void Download::didStart(const ResourceRequest&amp; request)
-{
-    send(Messages::DownloadProxy::DidStart(request));
-}
-#else
</del><ins>+#if !USE(NETWORK_SESSION)
</ins><span class="cx"> void Download::didStart()
</span><span class="cx"> {
</span><span class="cx">     send(Messages::DownloadProxy::DidStart(m_request));
</span><span class="lines">@@ -104,6 +99,7 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if !USE(NETWORK_SESSION)
</ins><span class="cx"> String Download::decideDestinationWithSuggestedFilename(const String&amp; filename, bool&amp; allowOverwrite)
</span><span class="cx"> {
</span><span class="cx">     String destination;
</span><span class="lines">@@ -117,6 +113,7 @@
</span><span class="cx"> 
</span><span class="cx">     return destination;
</span><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx"> 
</span><span class="cx"> void Download::didCreateDestination(const String&amp; path)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessDownloadsDownloadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/Downloads/Download.h (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/Downloads/Download.h        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/Downloads/Download.h        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -82,9 +82,7 @@
</span><span class="cx"> #endif
</span><span class="cx">     ~Download();
</span><span class="cx"> 
</span><del>-#if USE(NETWORK_SESSION) &amp;&amp; PLATFORM(COCOA)
-    void dataTaskDidBecomeDownloadTask(const NetworkSession&amp;, RetainPtr&lt;NSURLSessionDownloadTask&gt;&amp;&amp;);
-#else
</del><ins>+#if !USE(NETWORK_SESSION)
</ins><span class="cx">     void start();
</span><span class="cx">     void startWithHandle(WebCore::ResourceHandle*, const WebCore::ResourceResponse&amp;);
</span><span class="cx"> #endif
</span><span class="lines">@@ -94,7 +92,7 @@
</span><span class="cx">     DownloadID downloadID() const { return m_downloadID; }
</span><span class="cx"> 
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><del>-    void didStart(const WebCore::ResourceRequest&amp;);
</del><ins>+    void setSandboxExtension(RefPtr&lt;SandboxExtension&gt;&amp;&amp; sandboxExtension) { m_sandboxExtension = WTFMove(sandboxExtension); }
</ins><span class="cx"> #else
</span><span class="cx">     void didStart();
</span><span class="cx">     void didReceiveAuthenticationChallenge(const WebCore::AuthenticationChallenge&amp;);
</span><span class="lines">@@ -102,7 +100,9 @@
</span><span class="cx">     void didReceiveResponse(const WebCore::ResourceResponse&amp;);
</span><span class="cx">     void didReceiveData(uint64_t length);
</span><span class="cx">     bool shouldDecodeSourceDataOfMIMEType(const String&amp; mimeType);
</span><ins>+#if !USE(NETWORK_SESSION)
</ins><span class="cx">     String decideDestinationWithSuggestedFilename(const String&amp; filename, bool&amp; allowOverwrite);
</span><ins>+#endif
</ins><span class="cx">     void didCreateDestination(const String&amp; path);
</span><span class="cx">     void didFinish();
</span><span class="cx">     void platformDidFinish();
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessDownloadsDownloadManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -65,13 +65,18 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><del>-std::unique_ptr&lt;PendingDownload&gt; DownloadManager::dataTaskBecameDownloadTask(DownloadID downloadID, std::unique_ptr&lt;Download&gt;&amp;&amp; download)
</del><ins>+std::pair&lt;RefPtr&lt;NetworkDataTask&gt;, std::unique_ptr&lt;PendingDownload&gt;&gt; DownloadManager::dataTaskBecameDownloadTask(DownloadID downloadID, std::unique_ptr&lt;Download&gt;&amp;&amp; download)
</ins><span class="cx"> {
</span><span class="cx">     // This is needed for downloads started with startDownload, otherwise it will return nullptr.
</span><span class="cx">     auto pendingDownload = m_pendingDownloads.take(downloadID);
</span><span class="cx"> 
</span><ins>+    // This is needed for downloads started with convertTaskToDownload, otherwise it will return nullptr.
+    auto downloadAfterLocationDecided = m_downloadsAfterDestinationDecided.take(downloadID);
+    
+    ASSERT(!!pendingDownload != !!downloadAfterLocationDecided);
+    
</ins><span class="cx">     m_downloads.add(downloadID, WTFMove(download));
</span><del>-    return pendingDownload;
</del><ins>+    return std::make_pair(WTFMove(downloadAfterLocationDecided), WTFMove(pendingDownload));
</ins><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> void DownloadManager::continueCanAuthenticateAgainstProtectionSpace(DownloadID downloadID, bool canAuthenticate)
</span><span class="lines">@@ -89,6 +94,28 @@
</span><span class="cx">     if (pendingDownload)
</span><span class="cx">         pendingDownload-&gt;continueWillSendRequest(request);
</span><span class="cx"> }
</span><ins>+
+void DownloadManager::willDecidePendingDownloadDestination(NetworkDataTask&amp; networkDataTask, ResponseCompletionHandler completionHandler)
+{
+    auto addResult = m_downloadsWaitingForDestination.set(networkDataTask.pendingDownloadID(), std::make_pair&lt;RefPtr&lt;NetworkDataTask&gt;, ResponseCompletionHandler&gt;(&amp;networkDataTask, WTFMove(completionHandler)));
+    ASSERT_UNUSED(addResult, addResult.isNewEntry);
+}
+
+void DownloadManager::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, const SandboxExtension::Handle&amp; sandboxExtensionHandle)
+{
+    auto pair = m_downloadsWaitingForDestination.take(downloadID);
+    auto networkDataTask = pair.first;
+    auto completionHandler = pair.second;
+    if (!networkDataTask || !completionHandler) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+    networkDataTask-&gt;setPendingDownloadLocation(destination, sandboxExtensionHandle);
+    completionHandler(PolicyDownload);
+    
+    ASSERT(!m_downloadsAfterDestinationDecided.contains(downloadID));
+    m_downloadsAfterDestinationDecided.set(downloadID, networkDataTask);
+}
</ins><span class="cx"> #else
</span><span class="cx"> void DownloadManager::convertHandleToDownload(DownloadID downloadID, ResourceHandle* handle, const ResourceRequest&amp; request, const ResourceResponse&amp; response)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessDownloadsDownloadManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #define DownloadManager_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;DownloadID.h&quot;
</span><ins>+#include &quot;NetworkDataTask.h&quot;
</ins><span class="cx"> #include &quot;PendingDownload.h&quot;
</span><span class="cx"> #include &quot;SandboxExtension.h&quot;
</span><span class="cx"> #include &lt;WebCore/NotImplemented.h&gt;
</span><span class="lines">@@ -72,9 +73,11 @@
</span><span class="cx"> 
</span><span class="cx">     void startDownload(WebCore::SessionID, DownloadID, const WebCore::ResourceRequest&amp;);
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><del>-    std::unique_ptr&lt;PendingDownload&gt; dataTaskBecameDownloadTask(DownloadID, std::unique_ptr&lt;Download&gt;&amp;&amp;);
</del><ins>+    std::pair&lt;RefPtr&lt;NetworkDataTask&gt;, std::unique_ptr&lt;PendingDownload&gt;&gt; dataTaskBecameDownloadTask(DownloadID, std::unique_ptr&lt;Download&gt;&amp;&amp;);
</ins><span class="cx">     void continueCanAuthenticateAgainstProtectionSpace(DownloadID, bool canAuthenticate);
</span><span class="cx">     void continueWillSendRequest(DownloadID, const WebCore::ResourceRequest&amp;);
</span><ins>+    void willDecidePendingDownloadDestination(NetworkDataTask&amp;, ResponseCompletionHandler);
+    void continueDecidePendingDownloadDestination(DownloadID, String destination, const SandboxExtension::Handle&amp;);
</ins><span class="cx"> #else
</span><span class="cx">     void convertHandleToDownload(DownloadID, WebCore::ResourceHandle*, const WebCore::ResourceRequest&amp;, const WebCore::ResourceResponse&amp;);
</span><span class="cx"> #endif
</span><span class="lines">@@ -99,6 +102,8 @@
</span><span class="cx">     Client&amp; m_client;
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx">     HashMap&lt;DownloadID, std::unique_ptr&lt;PendingDownload&gt;&gt; m_pendingDownloads;
</span><ins>+    HashMap&lt;DownloadID, std::pair&lt;RefPtr&lt;NetworkDataTask&gt;, ResponseCompletionHandler&gt;&gt; m_downloadsWaitingForDestination;
+    HashMap&lt;DownloadID, RefPtr&lt;NetworkDataTask&gt;&gt; m_downloadsAfterDestinationDecided;
</ins><span class="cx"> #endif
</span><span class="cx">     HashMap&lt;DownloadID, std::unique_ptr&lt;Download&gt;&gt; m_downloads;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkDataTaskh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef NetworkDataTask_h
</span><span class="cx"> #define NetworkDataTask_h
</span><span class="cx"> 
</span><ins>+#include &quot;SandboxExtension.h&quot;
</ins><span class="cx"> #include &lt;WebCore/FrameLoaderTypes.h&gt;
</span><span class="cx"> #include &lt;WebCore/ResourceHandleTypes.h&gt;
</span><span class="cx"> #include &lt;WebCore/ResourceLoaderOptions.h&gt;
</span><span class="lines">@@ -49,6 +50,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><ins>+class Download;
</ins><span class="cx"> class NetworkSession;
</span><span class="cx"> class PendingDownload;
</span><span class="cx"> 
</span><span class="lines">@@ -95,8 +97,15 @@
</span><span class="cx">     
</span><span class="cx">     ~NetworkDataTask();
</span><span class="cx">     
</span><del>-    NetworkDataTaskClient&amp; client() { return m_client; }
</del><ins>+    void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend);
+    void didReceiveChallenge(const WebCore::AuthenticationChallenge&amp;, ChallengeCompletionHandler);
+    void didCompleteWithError(const WebCore::ResourceError&amp;);
+    void didReceiveResponse(const WebCore::ResourceResponse&amp;, ResponseCompletionHandler);
+    void didReceiveData(RefPtr&lt;WebCore::SharedBuffer&gt;&amp;&amp;);
+    void didBecomeDownload();
</ins><span class="cx">     
</span><ins>+    void clearClient() { m_client = nullptr; }
+    
</ins><span class="cx">     DownloadID pendingDownloadID() { return m_pendingDownloadID; }
</span><span class="cx">     PendingDownload* pendingDownload() { return m_pendingDownload; }
</span><span class="cx">     void setPendingDownloadID(DownloadID downloadID)
</span><span class="lines">@@ -110,8 +119,13 @@
</span><span class="cx">         ASSERT(!m_pendingDownload);
</span><span class="cx">         m_pendingDownload = &amp;pendingDownload;
</span><span class="cx">     }
</span><ins>+    void findPendingDownloadLocation(ResponseCompletionHandler);
+    void setPendingDownloadLocation(const String&amp; filename, const SandboxExtension::Handle&amp;);
+    const String&amp; pendingDownloadLocation() { return m_pendingDownloadLocation; }
+    WebCore::ResourceRequest currentRequest();
</ins><span class="cx">     bool tryPasswordBasedAuthentication(const WebCore::AuthenticationChallenge&amp;, ChallengeCompletionHandler);
</span><span class="cx">     void willPerformHTTPRedirection(const WebCore::ResourceResponse&amp;, WebCore::ResourceRequest&amp;&amp;, RedirectCompletionHandler);
</span><ins>+    void transferSandboxExtensionToDownload(Download&amp;);
</ins><span class="cx">     
</span><span class="cx"> private:
</span><span class="cx">     NetworkDataTask(NetworkSession&amp;, NetworkDataTaskClient&amp;, const WebCore::ResourceRequest&amp;, WebCore::StoredCredentials, WebCore::ContentSniffingPolicy, bool shouldClearReferrerOnHTTPSToHTTPRedirect);
</span><span class="lines">@@ -127,14 +141,16 @@
</span><span class="cx">     void scheduleFailure(FailureType);
</span><span class="cx">     
</span><span class="cx">     NetworkSession&amp; m_session;
</span><del>-    NetworkDataTaskClient&amp; m_client;
</del><ins>+    NetworkDataTaskClient* m_client;
</ins><span class="cx">     PendingDownload* m_pendingDownload { nullptr };
</span><span class="cx">     DownloadID m_pendingDownloadID;
</span><span class="cx">     String m_user;
</span><span class="cx">     String m_password;
</span><span class="cx">     String m_lastHTTPMethod;
</span><ins>+    String m_pendingDownloadLocation;
</ins><span class="cx">     WebCore::ResourceRequest m_firstRequest;
</span><span class="cx">     bool m_shouldClearReferrerOnHTTPSToHTTPRedirect;
</span><ins>+    RefPtr&lt;SandboxExtension&gt; m_sandboxExtension;
</ins><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx">     RetainPtr&lt;NSURLSessionDataTask&gt; m_task;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkLoadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -71,6 +71,8 @@
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx">     if (m_responseCompletionHandler)
</span><span class="cx">         m_responseCompletionHandler(PolicyIgnore);
</span><ins>+    if (m_task)
+        m_task-&gt;clearClient();
</ins><span class="cx"> #endif
</span><span class="cx">     if (m_handle)
</span><span class="cx">         m_handle-&gt;clearClient();
</span><span class="lines">@@ -163,13 +165,14 @@
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::convertTaskToDownload(DownloadID downloadID)
</span><span class="cx"> {
</span><ins>+    if (!m_task)
+        return;
+
</ins><span class="cx">     m_task-&gt;setPendingDownloadID(downloadID);
</span><span class="cx">     
</span><span class="cx">     ASSERT(m_responseCompletionHandler);
</span><del>-    if (m_responseCompletionHandler) {
-        m_responseCompletionHandler(PolicyDownload);
-        m_responseCompletionHandler = nullptr;
-    }
</del><ins>+    if (m_responseCompletionHandler)
+        m_task-&gt;findPendingDownloadLocation(WTFMove(m_responseCompletionHandler));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::setPendingDownloadID(DownloadID downloadID)
</span><span class="lines">@@ -218,7 +221,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     if (m_task &amp;&amp; m_task-&gt;pendingDownloadID().downloadID())
</span><del>-        completionHandler(PolicyDownload);
</del><ins>+        m_task-&gt;findPendingDownloadLocation(completionHandler);
</ins><span class="cx">     else if (sharedDidReceiveResponse(response) == NetworkLoadClient::ShouldContinueDidReceiveResponse::Yes)
</span><span class="cx">         completionHandler(PolicyUse);
</span><span class="cx">     else
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &quot;AuthenticationManager.h&quot;
</span><span class="cx"> #include &quot;ChildProcessMessages.h&quot;
</span><span class="cx"> #include &quot;CustomProtocolManager.h&quot;
</span><ins>+#include &quot;DownloadProxyMessages.h&quot;
</ins><span class="cx"> #include &quot;Logging.h&quot;
</span><span class="cx"> #include &quot;NetworkConnectionToWebProcess.h&quot;
</span><span class="cx"> #include &quot;NetworkProcessCreationParameters.h&quot;
</span><span class="lines">@@ -41,6 +42,7 @@
</span><span class="cx"> #include &quot;SessionTracker.h&quot;
</span><span class="cx"> #include &quot;StatisticsData.h&quot;
</span><span class="cx"> #include &quot;WebCookieManager.h&quot;
</span><ins>+#include &quot;WebCoreArgumentCoders.h&quot;
</ins><span class="cx"> #include &quot;WebProcessPoolMessages.h&quot;
</span><span class="cx"> #include &quot;WebsiteData.h&quot;
</span><span class="cx"> #include &lt;WebCore/DNS.h&gt;
</span><span class="lines">@@ -468,6 +470,20 @@
</span><span class="cx"> {
</span><span class="cx">     downloadManager().continueWillSendRequest(downloadID, request);
</span><span class="cx"> }
</span><ins>+
+void NetworkProcess::findPendingDownloadLocation(NetworkDataTask&amp; networkDataTask, String suggestedFilename, ResponseCompletionHandler completionHandler)
+{
+    uint64_t destinationID = networkDataTask.pendingDownloadID().downloadID();
+    downloadProxyConnection()-&gt;send(Messages::DownloadProxy::DidStart(networkDataTask.currentRequest()), destinationID);
+    
+    downloadManager().willDecidePendingDownloadDestination(networkDataTask, completionHandler);
+    downloadProxyConnection()-&gt;send(Messages::DownloadProxy::DecideDestinationWithSuggestedFilenameAsync(networkDataTask.pendingDownloadID(), suggestedFilename), destinationID);
+}
+    
+void NetworkProcess::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, const SandboxExtension::Handle&amp; sandboxExtensionHandle)
+{
+    downloadManager().continueDecidePendingDownloadDestination(downloadID, destination, sandboxExtensionHandle);
+}
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> void NetworkProcess::setCacheModel(uint32_t cm)
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkProcessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcess.h (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkProcess.h        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkProcess.h        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><ins>+class DownloadID;
</ins><span class="cx"> class CertificateInfo;
</span><span class="cx"> class NetworkStorageSession;
</span><span class="cx"> class SecurityOrigin;
</span><span class="lines">@@ -99,6 +100,10 @@
</span><span class="cx">     void clearHSTSCache(WebCore::NetworkStorageSession&amp;, std::chrono::system_clock::time_point modifiedSince);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if USE(NETWORK_SESSION)
+    void findPendingDownloadLocation(NetworkDataTask&amp;, String suggestedFilename, ResponseCompletionHandler);
+#endif
+    
</ins><span class="cx">     void prefetchDNS(const String&amp;);
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -157,6 +162,7 @@
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx">     void continueCanAuthenticateAgainstProtectionSpace(DownloadID, bool canAuthenticate);
</span><span class="cx">     void continueWillSendRequest(DownloadID, const WebCore::ResourceRequest&amp;);
</span><ins>+    void continueDecidePendingDownloadDestination(DownloadID, String destination, const SandboxExtension::Handle&amp; sandboxExtensionHandle);
</ins><span class="cx"> #endif
</span><span class="cx">     void setCacheModel(uint32_t);
</span><span class="cx">     void allowSpecificHTTPSCertificateForHost(const WebCore::CertificateInfo&amp;, const String&amp; host);
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkProcessmessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkProcess.messages.in        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx">     ContinueCanAuthenticateAgainstProtectionSpace(WebKit::DownloadID downloadID, bool canAuthenticate)
</span><span class="cx">     ContinueWillSendRequest(WebKit::DownloadID downloadID, WebCore::ResourceRequest request)
</span><ins>+    ContinueDecidePendingDownloadDestination(WebKit::DownloadID downloadID, String destination, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     SetProcessSuppressionEnabled(bool flag)
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscocoaNetworkDataTaskCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -28,17 +28,25 @@
</span><span class="cx"> 
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx"> 
</span><ins>+#import &quot;Download.h&quot;
+#import &quot;DownloadProxyMessages.h&quot;
+#import &quot;NetworkProcess.h&quot;
+#import &quot;WebCoreArgumentCoders.h&quot;
</ins><span class="cx"> #import &lt;WebCore/AuthenticationChallenge.h&gt;
</span><span class="cx"> #import &lt;WebCore/CFNetworkSPI.h&gt;
</span><span class="cx"> #import &lt;WebCore/ResourceRequest.h&gt;
</span><span class="cx"> #import &lt;wtf/MainThread.h&gt;
</span><span class="cx"> 
</span><ins>+@interface NSURLSessionTask ()
+@property (readwrite, copy) NSString *_pathToDownloadTaskFile;
+@end
+
</ins><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><span class="cx"> NetworkDataTask::NetworkDataTask(NetworkSession&amp; session, NetworkDataTaskClient&amp; client, const WebCore::ResourceRequest&amp; requestWithCredentials, WebCore::StoredCredentials storedCredentials, WebCore::ContentSniffingPolicy shouldContentSniff, bool shouldClearReferrerOnHTTPSToHTTPRedirect)
</span><span class="cx">     : m_failureTimer(*this, &amp;NetworkDataTask::failureTimerFired)
</span><span class="cx">     , m_session(session)
</span><del>-    , m_client(client)
</del><ins>+    , m_client(&amp;client)
</ins><span class="cx">     , m_lastHTTPMethod(requestWithCredentials.httpMethod())
</span><span class="cx">     , m_firstRequest(requestWithCredentials)
</span><span class="cx">     , m_shouldClearReferrerOnHTTPSToHTTPRedirect(shouldClearReferrerOnHTTPSToHTTPRedirect)
</span><span class="lines">@@ -86,6 +94,42 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void NetworkDataTask::didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend)
+{
+    if (m_client)
+        m_client-&gt;didSendData(totalBytesSent, totalBytesExpectedToSend);
+}
+
+void NetworkDataTask::didReceiveChallenge(const WebCore::AuthenticationChallenge&amp; challenge, ChallengeCompletionHandler completionHandler)
+{
+    if (m_client)
+        m_client-&gt;didReceiveChallenge(challenge, completionHandler);
+}
+
+void NetworkDataTask::didCompleteWithError(const WebCore::ResourceError&amp; error)
+{
+    if (m_client)
+        m_client-&gt;didCompleteWithError(error);
+}
+
+void NetworkDataTask::didReceiveResponse(const WebCore::ResourceResponse&amp; response, ResponseCompletionHandler completionHandler)
+{
+    if (m_client)
+        m_client-&gt;didReceiveResponseNetworkSession(response, completionHandler);
+}
+
+void NetworkDataTask::didReceiveData(RefPtr&lt;WebCore::SharedBuffer&gt;&amp;&amp; data)
+{
+    if (m_client)
+        m_client-&gt;didReceiveData(WTFMove(data));
+}
+
+void NetworkDataTask::didBecomeDownload()
+{
+    if (m_client)
+        m_client-&gt;didBecomeDownload();
+}
+
</ins><span class="cx"> void NetworkDataTask::willPerformHTTPRedirection(const WebCore::ResourceResponse&amp; redirectResponse, WebCore::ResourceRequest&amp;&amp; request, RedirectCompletionHandler completionHandler)
</span><span class="cx"> {
</span><span class="cx">     if (redirectResponse.httpStatusCode() == 307 || redirectResponse.httpStatusCode() == 308) {
</span><span class="lines">@@ -116,7 +160,8 @@
</span><span class="cx">         request.clearHTTPOrigin();
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    client().willPerformHTTPRedirection(redirectResponse, request, completionHandler);
</del><ins>+    if (m_client)
+        m_client-&gt;willPerformHTTPRedirection(redirectResponse, request, completionHandler);
</ins><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> void NetworkDataTask::scheduleFailure(FailureType type)
</span><span class="lines">@@ -133,11 +178,13 @@
</span><span class="cx">     switch (m_scheduledFailureType) {
</span><span class="cx">     case BlockedFailure:
</span><span class="cx">         m_scheduledFailureType = NoFailure;
</span><del>-        client().wasBlocked();
</del><ins>+        if (m_client)
+            m_client-&gt;wasBlocked();
</ins><span class="cx">         return;
</span><span class="cx">     case InvalidURLFailure:
</span><span class="cx">         m_scheduledFailureType = NoFailure;
</span><del>-        client().cannotShowURL();
</del><ins>+        if (m_client)
+            m_client-&gt;cannotShowURL();
</ins><span class="cx">         return;
</span><span class="cx">     case NoFailure:
</span><span class="cx">         ASSERT_NOT_REACHED();
</span><span class="lines">@@ -146,6 +193,22 @@
</span><span class="cx">     ASSERT_NOT_REACHED();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void NetworkDataTask::findPendingDownloadLocation(ResponseCompletionHandler completionHandler)
+{
+    NetworkProcess::singleton().findPendingDownloadLocation(*this, m_task.get().response.suggestedFilename, completionHandler);
+}
+
+void NetworkDataTask::setPendingDownloadLocation(const WTF::String&amp; filename, const SandboxExtension::Handle&amp; sandboxExtensionHandle)
+{
+    ASSERT(!m_sandboxExtension);
+    m_sandboxExtension = SandboxExtension::create(sandboxExtensionHandle);
+    if (m_sandboxExtension)
+        m_sandboxExtension-&gt;consume();
+
+    m_pendingDownloadLocation = filename;
+    m_task.get()._pathToDownloadTaskFile = filename;
+}
+
</ins><span class="cx"> bool NetworkDataTask::tryPasswordBasedAuthentication(const WebCore::AuthenticationChallenge&amp; challenge, ChallengeCompletionHandler completionHandler)
</span><span class="cx"> {
</span><span class="cx">     if (!challenge.protectionSpace().isPasswordBased())
</span><span class="lines">@@ -166,6 +229,16 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void NetworkDataTask::transferSandboxExtensionToDownload(Download&amp; download)
+{
+    download.setSandboxExtension(WTFMove(m_sandboxExtension));
+}
+
+WebCore::ResourceRequest NetworkDataTask::currentRequest()
+{
+    return [m_task currentRequest];
+}
+
</ins><span class="cx"> void NetworkDataTask::cancel()
</span><span class="cx"> {
</span><span class="cx">     [m_task cancel];
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscocoaNetworkSessionCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx"> 
</span><span class="cx"> #import &quot;CustomProtocolManager.h&quot;
</span><ins>+#import &quot;DataReference.h&quot;
</ins><span class="cx"> #import &quot;Download.h&quot;
</span><span class="cx"> #import &quot;NetworkLoad.h&quot;
</span><span class="cx"> #import &quot;NetworkProcess.h&quot;
</span><span class="lines">@@ -98,7 +99,7 @@
</span><span class="cx"> - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
</span><span class="cx"> {
</span><span class="cx">     if (auto* networkDataTask = _session-&gt;dataTaskForIdentifier(task.taskIdentifier))
</span><del>-        networkDataTask-&gt;client().didSendData(totalBytesSent, totalBytesExpectedToSend);
</del><ins>+        networkDataTask-&gt;didSendData(totalBytesSent, totalBytesExpectedToSend);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest *))completionHandler
</span><span class="lines">@@ -125,14 +126,18 @@
</span><span class="cx">         if (networkDataTask-&gt;tryPasswordBasedAuthentication(challenge, challengeCompletionHandler))
</span><span class="cx">             return;
</span><span class="cx">         
</span><del>-        networkDataTask-&gt;client().didReceiveChallenge(challenge, challengeCompletionHandler);
</del><ins>+        networkDataTask-&gt;didReceiveChallenge(challenge, challengeCompletionHandler);
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
</span><span class="cx"> {
</span><span class="cx">     if (auto* networkDataTask = _session-&gt;dataTaskForIdentifier(task.taskIdentifier))
</span><del>-        networkDataTask-&gt;client().didCompleteWithError(error);
</del><ins>+        networkDataTask-&gt;didCompleteWithError(error);
+    else if (auto* download = WebKit::NetworkProcess::singleton().downloadManager().download(_session-&gt;downloadID(task.taskIdentifier))) {
+        if (error)
+            download-&gt;didFail(error, { }); // FIXME: Give some actual data here for resuming.
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
</span><span class="lines">@@ -142,7 +147,7 @@
</span><span class="cx">         WebCore::ResourceResponse resourceResponse(response);
</span><span class="cx">         copyTimingData([dataTask _timingData], resourceResponse.resourceLoadTiming());
</span><span class="cx">         auto completionHandlerCopy = Block_copy(completionHandler);
</span><del>-        networkDataTask-&gt;client().didReceiveResponseNetworkSession(resourceResponse, [completionHandlerCopy](WebCore::PolicyAction policyAction) {
</del><ins>+        networkDataTask-&gt;didReceiveResponse(resourceResponse, [completionHandlerCopy, resourceResponse](WebCore::PolicyAction policyAction) {
</ins><span class="cx">             completionHandlerCopy(toNSURLSessionResponseDisposition(policyAction));
</span><span class="cx">             Block_release(completionHandlerCopy);
</span><span class="cx">         });
</span><span class="lines">@@ -152,13 +157,12 @@
</span><span class="cx"> - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
</span><span class="cx"> {
</span><span class="cx">     if (auto* networkDataTask = _session-&gt;dataTaskForIdentifier(dataTask.taskIdentifier))
</span><del>-        networkDataTask-&gt;client().didReceiveData(WebCore::SharedBuffer::wrapNSData(data));
</del><ins>+        networkDataTask-&gt;didReceiveData(WebCore::SharedBuffer::wrapNSData(data));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
</span><span class="cx"> {
</span><span class="cx">     auto downloadID = _session-&gt;takeDownloadID([downloadTask taskIdentifier]);
</span><del>-    notImplemented();
</del><span class="cx">     if (auto* download = WebKit::NetworkProcess::singleton().downloadManager().download(downloadID))
</span><span class="cx">         download-&gt;didFinish();
</span><span class="cx"> }
</span><span class="lines">@@ -183,11 +187,13 @@
</span><span class="cx">         auto downloadID = networkDataTask-&gt;pendingDownloadID();
</span><span class="cx">         auto&amp; downloadManager = WebKit::NetworkProcess::singleton().downloadManager();
</span><span class="cx">         auto download = std::make_unique&lt;WebKit::Download&gt;(downloadManager, downloadID);
</span><del>-        download-&gt;didStart([downloadTask currentRequest]);
</del><ins>+        networkDataTask-&gt;transferSandboxExtensionToDownload(*download);
+        ASSERT(WebCore::fileExists(networkDataTask-&gt;pendingDownloadLocation()));
+        download-&gt;didCreateDestination(networkDataTask-&gt;pendingDownloadLocation());
</ins><span class="cx">         download-&gt;didReceiveResponse([downloadTask response]);
</span><span class="cx">         auto pendingDownload = downloadManager.dataTaskBecameDownloadTask(downloadID, WTFMove(download));
</span><span class="cx"> 
</span><del>-        networkDataTask-&gt;client().didBecomeDownload();
</del><ins>+        networkDataTask-&gt;didBecomeDownload();
</ins><span class="cx"> 
</span><span class="cx">         _session-&gt;addDownloadID([downloadTask taskIdentifier], downloadID);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessDownloadsDownloadProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.cpp        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> #include &quot;WebProcessMessages.h&quot;
</span><span class="cx"> #include &quot;WebProcessPool.h&quot;
</span><span class="cx"> #include &quot;WebProtectionSpace.h&quot;
</span><ins>+#include &lt;WebCore/FileSystem.h&gt;
</ins><span class="cx"> #include &lt;wtf/text/CString.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -170,6 +171,24 @@
</span><span class="cx">     result = m_processPool-&gt;downloadClient().shouldDecodeSourceDataOfMIMEType(m_processPool.get(), this, mimeType);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if USE(NETWORK_SESSION)
+void DownloadProxy::decideDestinationWithSuggestedFilenameAsync(DownloadID downloadID, const String&amp; suggestedFilename)
+{
+    bool allowOverwrite = false;
+    
+    if (!m_processPool)
+        return;
+    
+    String destination = m_processPool-&gt;downloadClient().decideDestinationWithSuggestedFilename(m_processPool.get(), this, suggestedFilename, allowOverwrite);
+    
+    SandboxExtension::Handle sandboxExtensionHandle;
+    if (!destination.isNull())
+        SandboxExtension::createHandle(destination, SandboxExtension::ReadWrite, sandboxExtensionHandle);
+    
+    if (NetworkProcessProxy* networkProcess = m_processPool-&gt;networkProcess())
+        networkProcess-&gt;connection()-&gt;send(Messages::NetworkProcess::ContinueDecidePendingDownloadDestination(downloadID, destination, sandboxExtensionHandle), 0);
+}
+#else
</ins><span class="cx"> void DownloadProxy::decideDestinationWithSuggestedFilename(const String&amp; filename, String&amp; destination, bool&amp; allowOverwrite, SandboxExtension::Handle&amp; sandboxExtensionHandle)
</span><span class="cx"> {
</span><span class="cx">     allowOverwrite = false;
</span><span class="lines">@@ -182,6 +201,7 @@
</span><span class="cx">     if (!destination.isNull())
</span><span class="cx">         SandboxExtension::createHandle(destination, SandboxExtension::ReadWrite, sandboxExtensionHandle);
</span><span class="cx"> }
</span><ins>+#endif
</ins><span class="cx"> 
</span><span class="cx"> void DownloadProxy::didCreateDestination(const String&amp; path)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessDownloadsDownloadProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.h (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.h        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.h        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -47,6 +47,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><ins>+class DownloadID;
</ins><span class="cx"> class DownloadProxyMap;
</span><span class="cx"> class WebPageProxy;
</span><span class="cx"> class WebProcessPool;
</span><span class="lines">@@ -81,7 +82,9 @@
</span><span class="cx">     void didReceiveResponse(const WebCore::ResourceResponse&amp;);
</span><span class="cx">     void didReceiveData(uint64_t length);
</span><span class="cx">     void shouldDecodeSourceDataOfMIMEType(const String&amp; mimeType, bool&amp; result);
</span><ins>+#if !USE(NETWORK_SESSION)
</ins><span class="cx">     void decideDestinationWithSuggestedFilename(const String&amp; filename, String&amp; destination, bool&amp; allowOverwrite, SandboxExtension::Handle&amp; sandboxExtensionHandle);
</span><ins>+#endif
</ins><span class="cx">     void didCreateDestination(const String&amp; path);
</span><span class="cx">     void didFinish();
</span><span class="cx">     void didFail(const WebCore::ResourceError&amp;, const IPC::DataReference&amp; resumeData);
</span><span class="lines">@@ -89,6 +92,7 @@
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx">     void canAuthenticateAgainstProtectionSpace(const WebCore::ProtectionSpace&amp;);
</span><span class="cx">     void willSendRequest(const WebCore::ResourceRequest&amp; redirectRequest, const WebCore::ResourceResponse&amp; redirectResponse);
</span><ins>+    void decideDestinationWithSuggestedFilenameAsync(DownloadID, const String&amp; suggestedFilename);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     DownloadProxyMap&amp; m_downloadProxyMap;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessDownloadsDownloadProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.messages.in (196983 => 196984)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.messages.in        2016-02-23 18:17:17 UTC (rev 196983)
+++ trunk/Source/WebKit2/UIProcess/Downloads/DownloadProxy.messages.in        2016-02-23 19:13:18 UTC (rev 196984)
</span><span class="lines">@@ -26,12 +26,15 @@
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx">     WillSendRequest(WebCore::ResourceRequest redirectRequest, WebCore::ResourceResponse redirectResponse));
</span><span class="cx">     CanAuthenticateAgainstProtectionSpace(WebCore::ProtectionSpace protectionSpace)
</span><ins>+    DecideDestinationWithSuggestedFilenameAsync(WebKit::DownloadID downloadID, String suggestedFilename)
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     DidReceiveResponse(WebCore::ResourceResponse response)
</span><span class="cx">     DidReceiveData(uint64_t length)
</span><span class="cx">     ShouldDecodeSourceDataOfMIMEType(String mimeType) -&gt; (bool result)
</span><ins>+#if !USE(NETWORK_SESSION)
</ins><span class="cx">     DecideDestinationWithSuggestedFilename(String filename) -&gt; (String destination, bool allowOverwrite, WebKit::SandboxExtension::Handle sandboxExtensionHandle)
</span><ins>+#endif
</ins><span class="cx">     DidCreateDestination(String path)
</span><span class="cx">     DidFinish()
</span><span class="cx">     DidFail(WebCore::ResourceError error, IPC::DataReference resumeData)
</span></span></pre>
</div>
</div>

</body>
</html>