<!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>[208521] trunk</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/208521">208521</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2016-11-09 20:49:09 -0800 (Wed, 09 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>NetworkSession: Network process crash when converting main resource to download
https://bugs.webkit.org/show_bug.cgi?id=164220

Patch by Carlos Garcia Campos &lt;cgarcia@igalia.com&gt; on 2016-11-09
Reviewed by Alex Christensen.

Source/WebKit2:

Right after the main resource load is converted to a download, the web process deletes the ResourceLoader which
sends the RemoveLoadIdentifier to the network process and the load is aborted. Sometimes it happens that
NetworkResourceLoader::abort() is called while the NetworkLoad is still deciding the destination of the
download. In such case, NetworkResourceLoader::didConvertToDownload() has already been called, but not
NetworkResourceLoader::didBecomeDownload(). In NetworkResourceLoader::abort() we already handle the case of
having a NetworkLoad after NetworkResourceLoader::didConvertToDownload() has been called, to avoid canceling the
load in such case, however cleanup() is always called unconditionally and the NetworkLoad is deleted before
NetworkResourceLoader::didBecomeDownload() is called. When the NetworkLoad is destroyed the NetworkDataTask
client becomes nullptr, leaving it in a state where both the client is nullptr and the download hasn't been
created yet. That's not expected to happen and when the response completion handler is called in the
NetworkDataTask it tries to use either the client or the download and it crashes.
We need to cleanup and destroy the ResourceLoader as soon as it becomes a download, because that's the expected
behavior, but at the same time we need to keep the NetworkLoad alive until the NetworkDataTask finishes to become
a download. This patch creates a PendingDownload to take the ownership of the NetworkLoad, so that
ResourceLoader can be cleaned up and destroyed. The DownloadManager now will handle the PendingDownload as if it
was created by startDownload(), but ensuring it's deleted right before the final Download object is added to the
downloads map. That way NetworkDataTask will always have a valid client until the final Download is created,
first the ResourceLoader and then the PendingDownload. Since the DownloadManager is the owner of the
PendingDownload we no longer need the didBecomeDownload() callback to delete the NetworkLoad, because the
NetworkLoad will always be owned by the PendingDownload now that will be deleted by the DownloadManager.

* NetworkProcess/Downloads/DownloadManager.cpp:
(WebKit::DownloadManager::dataTaskBecameDownloadTask): Change the ASSERT because at this point we should always
have a PendingDownload, and then remove it from the map here before adding the final Download to the map.
(WebKit::DownloadManager::convertNetworkLoadToDownload): This replaces convertHandleToDownload, but it also now
used for the NetworkSession. It creates a PendingDownload for the given NetworkLoad.
(WebKit::DownloadManager::continueDecidePendingDownloadDestination): Do not take the PendingDownload from the
map here, just check it's present, because it will be removed from dataTaskBecameDownloadTask().
(WebKit::DownloadManager::convertHandleToDownload): Deleted.
* NetworkProcess/Downloads/DownloadManager.h:
* NetworkProcess/Downloads/PendingDownload.cpp:
(WebKit::PendingDownload::PendingDownload): Add a constructor that receives a NetworkLoad.
* NetworkProcess/Downloads/PendingDownload.h:
* NetworkProcess/NetworkConnectionToWebProcess.cpp:
(WebKit::NetworkConnectionToWebProcess::convertMainResourceLoadToDownload): Just ask the ResourceLoader to be
converted to a download.
* NetworkProcess/NetworkDataTask.h:
* NetworkProcess/NetworkDataTaskBlob.cpp:
(WebKit::NetworkDataTaskBlob::download): Do not call didBecomeDownload() and add an assert to ensure the client
has already been removed right after the final Download object is created.
* NetworkProcess/NetworkLoad.cpp:
(WebKit::NetworkLoad::NetworkLoad): Use a pointer for the client instead of a reference because now we need to
change the client when the load is converted to a download. We don't need to null check the client in any case
because the member is only updated internally and always from a passed reference.
(WebKit::NetworkLoad::sharedDidReceiveResponse):
(WebKit::NetworkLoad::sharedWillSendRedirectedRequest):
(WebKit::NetworkLoad::convertTaskToDownload): This now receives a PendingDownload. It updates the client and no
longer sends DidStart, because the PendingDownload sends it now.
(WebKit::NetworkLoad::didReceiveChallenge):
(WebKit::NetworkLoad::didReceiveData):
(WebKit::NetworkLoad::didCompleteWithError):
(WebKit::NetworkLoad::didSendData):
(WebKit::NetworkLoad::wasBlocked):
(WebKit::NetworkLoad::cannotShowURL):
(WebKit::NetworkLoad::didReceiveBuffer):
(WebKit::NetworkLoad::didFinishLoading):
(WebKit::NetworkLoad::didFail):
(WebKit::NetworkLoad::canAuthenticateAgainstProtectionSpaceAsync):
(WebKit::NetworkLoad::didBecomeDownload): Deleted.
* NetworkProcess/NetworkLoad.h:
* NetworkProcess/NetworkLoadClient.h: Remove didBecomeDownload().
* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::convertToDownload): This replaces didBecomeDownload() and
didConvertToDownload(). It transfers the NetworkLoad to the DownloadManager.
(WebKit::NetworkResourceLoader::abort): We don't need to check if the load was converted to a download here,
because m_networkLoad will always be null here in such case.
(WebKit::NetworkResourceLoader::didBecomeDownload): Deleted
(WebKit::NetworkResourceLoader::didConvertToDownload): Deleted
* NetworkProcess/NetworkResourceLoader.h:
* NetworkProcess/PingLoad.h: Remove didBecomeDownload().
* NetworkProcess/cache/NetworkCacheSpeculativeLoad.h: Ditto.
* NetworkProcess/cocoa/NetworkDataTaskCocoa.h: Ditto.
* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm: Ditto.
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate URLSession:dataTask:didBecomeDownloadTask:]): Do not call didBecomeDownload().
* NetworkProcess/soup/NetworkDataTaskSoup.cpp:
(WebKit::NetworkDataTaskSoup::download): Do not call didBecomeDownload() and add an assert to ensure the client
has already been removed right after the final Download object is created.

Tools:

Split /webkit2/Downloads/policy-decision-download in two, one to test the full load when main resource is
converted to a download and another one to test the cancellation as the test was doing before. When doing the
full load, delay a bit the decide destination to ensure the load is aborted before the data task has became a
download.

* TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp:
(testPolicyResponseDownload):
(testPolicyResponseDownloadCancel):
(beforeAll):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</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="#trunkSourceWebKit2NetworkProcessDownloadsPendingDownloadcpp">trunk/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessDownloadsPendingDownloadh">trunk/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkConnectionToWebProcesscpp">trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkDataTaskh">trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkDataTaskBlobcpp">trunk/Source/WebKit2/NetworkProcess/NetworkDataTaskBlob.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkLoadcpp">trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkLoadh">trunk/Source/WebKit2/NetworkProcess/NetworkLoad.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkLoadClienth">trunk/Source/WebKit2/NetworkProcess/NetworkLoadClient.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkResourceLoadercpp">trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkResourceLoaderh">trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessPingLoadh">trunk/Source/WebKit2/NetworkProcess/PingLoad.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheSpeculativeLoadh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscocoaNetworkDataTaskCocoah">trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.h</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="#trunkSourceWebKit2NetworkProcesssoupNetworkDataTaskSoupcpp">trunk/Source/WebKit2/NetworkProcess/soup/NetworkDataTaskSoup.cpp</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2GtkTestDownloadscpp">trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/ChangeLog        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -1,3 +1,89 @@
</span><ins>+2016-11-09  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        NetworkSession: Network process crash when converting main resource to download
+        https://bugs.webkit.org/show_bug.cgi?id=164220
+
+        Reviewed by Alex Christensen.
+
+        Right after the main resource load is converted to a download, the web process deletes the ResourceLoader which
+        sends the RemoveLoadIdentifier to the network process and the load is aborted. Sometimes it happens that
+        NetworkResourceLoader::abort() is called while the NetworkLoad is still deciding the destination of the
+        download. In such case, NetworkResourceLoader::didConvertToDownload() has already been called, but not
+        NetworkResourceLoader::didBecomeDownload(). In NetworkResourceLoader::abort() we already handle the case of
+        having a NetworkLoad after NetworkResourceLoader::didConvertToDownload() has been called, to avoid canceling the
+        load in such case, however cleanup() is always called unconditionally and the NetworkLoad is deleted before
+        NetworkResourceLoader::didBecomeDownload() is called. When the NetworkLoad is destroyed the NetworkDataTask
+        client becomes nullptr, leaving it in a state where both the client is nullptr and the download hasn't been
+        created yet. That's not expected to happen and when the response completion handler is called in the
+        NetworkDataTask it tries to use either the client or the download and it crashes.
+        We need to cleanup and destroy the ResourceLoader as soon as it becomes a download, because that's the expected
+        behavior, but at the same time we need to keep the NetworkLoad alive until the NetworkDataTask finishes to become
+        a download. This patch creates a PendingDownload to take the ownership of the NetworkLoad, so that
+        ResourceLoader can be cleaned up and destroyed. The DownloadManager now will handle the PendingDownload as if it
+        was created by startDownload(), but ensuring it's deleted right before the final Download object is added to the
+        downloads map. That way NetworkDataTask will always have a valid client until the final Download is created,
+        first the ResourceLoader and then the PendingDownload. Since the DownloadManager is the owner of the
+        PendingDownload we no longer need the didBecomeDownload() callback to delete the NetworkLoad, because the
+        NetworkLoad will always be owned by the PendingDownload now that will be deleted by the DownloadManager.
+
+        * NetworkProcess/Downloads/DownloadManager.cpp:
+        (WebKit::DownloadManager::dataTaskBecameDownloadTask): Change the ASSERT because at this point we should always
+        have a PendingDownload, and then remove it from the map here before adding the final Download to the map.
+        (WebKit::DownloadManager::convertNetworkLoadToDownload): This replaces convertHandleToDownload, but it also now
+        used for the NetworkSession. It creates a PendingDownload for the given NetworkLoad.
+        (WebKit::DownloadManager::continueDecidePendingDownloadDestination): Do not take the PendingDownload from the
+        map here, just check it's present, because it will be removed from dataTaskBecameDownloadTask().
+        (WebKit::DownloadManager::convertHandleToDownload): Deleted.
+        * NetworkProcess/Downloads/DownloadManager.h:
+        * NetworkProcess/Downloads/PendingDownload.cpp:
+        (WebKit::PendingDownload::PendingDownload): Add a constructor that receives a NetworkLoad.
+        * NetworkProcess/Downloads/PendingDownload.h:
+        * NetworkProcess/NetworkConnectionToWebProcess.cpp:
+        (WebKit::NetworkConnectionToWebProcess::convertMainResourceLoadToDownload): Just ask the ResourceLoader to be
+        converted to a download.
+        * NetworkProcess/NetworkDataTask.h:
+        * NetworkProcess/NetworkDataTaskBlob.cpp:
+        (WebKit::NetworkDataTaskBlob::download): Do not call didBecomeDownload() and add an assert to ensure the client
+        has already been removed right after the final Download object is created.
+        * NetworkProcess/NetworkLoad.cpp:
+        (WebKit::NetworkLoad::NetworkLoad): Use a pointer for the client instead of a reference because now we need to
+        change the client when the load is converted to a download. We don't need to null check the client in any case
+        because the member is only updated internally and always from a passed reference.
+        (WebKit::NetworkLoad::sharedDidReceiveResponse):
+        (WebKit::NetworkLoad::sharedWillSendRedirectedRequest):
+        (WebKit::NetworkLoad::convertTaskToDownload): This now receives a PendingDownload. It updates the client and no
+        longer sends DidStart, because the PendingDownload sends it now.
+        (WebKit::NetworkLoad::didReceiveChallenge):
+        (WebKit::NetworkLoad::didReceiveData):
+        (WebKit::NetworkLoad::didCompleteWithError):
+        (WebKit::NetworkLoad::didSendData):
+        (WebKit::NetworkLoad::wasBlocked):
+        (WebKit::NetworkLoad::cannotShowURL):
+        (WebKit::NetworkLoad::didReceiveBuffer):
+        (WebKit::NetworkLoad::didFinishLoading):
+        (WebKit::NetworkLoad::didFail):
+        (WebKit::NetworkLoad::canAuthenticateAgainstProtectionSpaceAsync):
+        (WebKit::NetworkLoad::didBecomeDownload): Deleted.
+        * NetworkProcess/NetworkLoad.h:
+        * NetworkProcess/NetworkLoadClient.h: Remove didBecomeDownload().
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::convertToDownload): This replaces didBecomeDownload() and
+        didConvertToDownload(). It transfers the NetworkLoad to the DownloadManager.
+        (WebKit::NetworkResourceLoader::abort): We don't need to check if the load was converted to a download here,
+        because m_networkLoad will always be null here in such case.
+        (WebKit::NetworkResourceLoader::didBecomeDownload): Deleted
+        (WebKit::NetworkResourceLoader::didConvertToDownload): Deleted
+        * NetworkProcess/NetworkResourceLoader.h:
+        * NetworkProcess/PingLoad.h: Remove didBecomeDownload().
+        * NetworkProcess/cache/NetworkCacheSpeculativeLoad.h: Ditto.
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.h: Ditto.
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm: Ditto.
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (-[WKNetworkSessionDelegate URLSession:dataTask:didBecomeDownloadTask:]): Do not call didBecomeDownload().
+        * NetworkProcess/soup/NetworkDataTaskSoup.cpp:
+        (WebKit::NetworkDataTaskSoup::download): Do not call didBecomeDownload() and add an assert to ensure the client
+        has already been removed right after the final Download object is created.
+
</ins><span class="cx"> 2016-11-09  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r208438.
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessDownloadsDownloadManagercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.cpp        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -67,7 +67,8 @@
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx"> void DownloadManager::dataTaskBecameDownloadTask(DownloadID downloadID, std::unique_ptr&lt;Download&gt;&amp;&amp; download)
</span><span class="cx"> {
</span><del>-    ASSERT(!m_pendingDownloads.contains(downloadID));
</del><ins>+    ASSERT(m_pendingDownloads.contains(downloadID));
+    m_pendingDownloads.remove(downloadID);
</ins><span class="cx">     ASSERT(!m_downloads.contains(downloadID));
</span><span class="cx">     m_downloadsAfterDestinationDecided.remove(downloadID);
</span><span class="cx">     m_downloads.add(downloadID, WTFMove(download));
</span><span class="lines">@@ -97,28 +98,37 @@
</span><span class="cx">     auto addResult = m_downloadsWaitingForDestination.set(downloadID, std::make_pair&lt;RefPtr&lt;NetworkDataTask&gt;, ResponseCompletionHandler&gt;(&amp;networkDataTask, WTFMove(completionHandler)));
</span><span class="cx">     ASSERT_UNUSED(addResult, addResult.isNewEntry);
</span><span class="cx"> }
</span><ins>+#endif // USE(NETWORK_SESSION)
+
+void DownloadManager::convertNetworkLoadToDownload(DownloadID downloadID, std::unique_ptr&lt;NetworkLoad&gt;&amp;&amp; networkLoad, const ResourceRequest&amp; request, const ResourceResponse&amp; response)
+{
+#if USE(NETWORK_SESSION)
+    ASSERT(!m_pendingDownloads.contains(downloadID));
+    m_pendingDownloads.add(downloadID, std::make_unique&lt;PendingDownload&gt;(WTFMove(networkLoad), downloadID, request, response));
</ins><span class="cx"> #else
</span><del>-void DownloadManager::convertHandleToDownload(DownloadID downloadID, ResourceHandle* handle, const ResourceRequest&amp; request, const ResourceResponse&amp; response)
-{
</del><span class="cx">     auto download = std::make_unique&lt;Download&gt;(*this, downloadID, request);
</span><span class="cx"> 
</span><ins>+    auto* handle = networkLoad-&gt;handle();
+    ASSERT(handle);
</ins><span class="cx">     download-&gt;startWithHandle(handle, response);
</span><span class="cx">     ASSERT(!m_downloads.contains(downloadID));
</span><span class="cx">     m_downloads.add(downloadID, WTFMove(download));
</span><ins>+
+    // Unblock the URL connection operation queue.
+    handle-&gt;continueDidReceiveResponse();
+#endif
</ins><span class="cx"> }
</span><del>-#endif // USE(NETWORK_SESSION)
</del><span class="cx"> 
</span><span class="cx"> void DownloadManager::continueDecidePendingDownloadDestination(DownloadID downloadID, String destination, const SandboxExtension::Handle&amp; sandboxExtensionHandle, bool allowOverwrite)
</span><span class="cx"> {
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx">     if (m_downloadsWaitingForDestination.contains(downloadID)) {
</span><del>-        auto pendingDownload = m_pendingDownloads.take(downloadID);
</del><span class="cx">         auto pair = m_downloadsWaitingForDestination.take(downloadID);
</span><span class="cx">         auto networkDataTask = WTFMove(pair.first);
</span><span class="cx">         auto completionHandler = WTFMove(pair.second);
</span><span class="cx">         ASSERT(networkDataTask);
</span><span class="cx">         ASSERT(completionHandler);
</span><del>-        ASSERT(!pendingDownload || pendingDownload.get() == networkDataTask-&gt;pendingDownload());
</del><ins>+        ASSERT(m_pendingDownloads.contains(downloadID));
</ins><span class="cx"> 
</span><span class="cx">         networkDataTask-&gt;setPendingDownloadLocation(destination, sandboxExtensionHandle, allowOverwrite);
</span><span class="cx">         completionHandler(PolicyDownload);
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessDownloadsDownloadManagerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/Downloads/DownloadManager.h        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx"> 
</span><span class="cx"> class AuthenticationManager;
</span><span class="cx"> class Download;
</span><ins>+class NetworkLoad;
</ins><span class="cx"> class PendingDownload;
</span><span class="cx"> 
</span><span class="cx"> class DownloadManager {
</span><span class="lines">@@ -80,9 +81,8 @@
</span><span class="cx"> #endif
</span><span class="cx">     void continueWillSendRequest(DownloadID, WebCore::ResourceRequest&amp;&amp;);
</span><span class="cx">     void willDecidePendingDownloadDestination(NetworkDataTask&amp;, ResponseCompletionHandler&amp;&amp;);
</span><del>-#else
-    void convertHandleToDownload(DownloadID, WebCore::ResourceHandle*, const WebCore::ResourceRequest&amp;, const WebCore::ResourceResponse&amp;);
</del><span class="cx"> #endif
</span><ins>+    void convertNetworkLoadToDownload(DownloadID, std::unique_ptr&lt;NetworkLoad&gt;&amp;&amp;, const WebCore::ResourceRequest&amp;, const WebCore::ResourceResponse&amp;);
</ins><span class="cx">     void continueDecidePendingDownloadDestination(DownloadID, String destination, const SandboxExtension::Handle&amp;, bool allowOverwrite);
</span><span class="cx"> 
</span><span class="cx">     void resumeDownload(WebCore::SessionID, DownloadID, const IPC::DataReference&amp; resumeData, const String&amp; path, const SandboxExtension::Handle&amp;);
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessDownloadsPendingDownloadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.cpp (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.cpp        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.cpp        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -48,6 +48,15 @@
</span><span class="cx">     send(Messages::DownloadProxy::DidStart(m_networkLoad-&gt;currentRequest(), suggestedName));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+PendingDownload::PendingDownload(std::unique_ptr&lt;NetworkLoad&gt;&amp;&amp; networkLoad, DownloadID downloadID, const ResourceRequest&amp; request, const ResourceResponse&amp; response)
+    : m_networkLoad(WTFMove(networkLoad))
+{
+    m_networkLoad-&gt;setPendingDownloadID(downloadID);
+    send(Messages::DownloadProxy::DidStart(request, String()));
+
+    m_networkLoad-&gt;convertTaskToDownload(*this, request, response);
+}
+
</ins><span class="cx"> void PendingDownload::willSendRedirectedRequest(WebCore::ResourceRequest&amp;&amp;, WebCore::ResourceRequest&amp;&amp; redirectRequest, WebCore::ResourceResponse&amp;&amp; redirectResponse)
</span><span class="cx"> {
</span><span class="cx">     send(Messages::DownloadProxy::WillSendRequest(WTFMove(redirectRequest), WTFMove(redirectResponse)));
</span><span class="lines">@@ -77,11 +86,6 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-void PendingDownload::didBecomeDownload()
-{
-    m_networkLoad = nullptr;
-}
-    
</del><span class="cx"> void PendingDownload::didFailLoading(const WebCore::ResourceError&amp; error)
</span><span class="cx"> {
</span><span class="cx">     send(Messages::DownloadProxy::DidFail(error, { }));
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessDownloadsPendingDownloadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.h (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.h        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/Downloads/PendingDownload.h        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -46,6 +46,7 @@
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><span class="cx">     PendingDownload(NetworkLoadParameters&amp;&amp;, DownloadID, NetworkSession&amp;, const String&amp; suggestedName);
</span><ins>+    PendingDownload(std::unique_ptr&lt;NetworkLoad&gt;&amp;&amp;, DownloadID, const WebCore::ResourceRequest&amp;, const WebCore::ResourceResponse&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void continueWillSendRequest(WebCore::ResourceRequest&amp;&amp;);
</span><span class="cx"> #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
</span><span class="lines">@@ -65,8 +66,7 @@
</span><span class="cx">     void didReceiveBuffer(Ref&lt;WebCore::SharedBuffer&gt;&amp;&amp;, int reportedEncodedDataLength) override { };
</span><span class="cx">     void didFinishLoading(double finishTime) override { };
</span><span class="cx">     void didFailLoading(const WebCore::ResourceError&amp;) override;
</span><del>-    void didBecomeDownload() override;
-    
</del><ins>+
</ins><span class="cx">     // MessageSender.
</span><span class="cx">     IPC::Connection* messageSenderConnection() override;
</span><span class="cx">     uint64_t messageSenderDestinationID() override;
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkConnectionToWebProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkConnectionToWebProcess.cpp        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -206,17 +206,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-#if USE(NETWORK_SESSION)
-    loader-&gt;networkLoad()-&gt;convertTaskToDownload(downloadID, request, response);
-    loader-&gt;didConvertToDownload();
-#else
-    networkProcess.downloadManager().convertHandleToDownload(downloadID, loader-&gt;networkLoad()-&gt;handle(), request, response);
-
-    // Unblock the URL connection operation queue.
-    loader-&gt;networkLoad()-&gt;handle()-&gt;continueDidReceiveResponse();
-
-    loader-&gt;didConvertToDownload();
-#endif
</del><ins>+    loader-&gt;convertToDownload(downloadID, request, response);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkConnectionToWebProcess::cookiesForDOM(SessionID sessionID, const URL&amp; firstParty, const URL&amp; url, String&amp; result)
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkDataTaskh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -63,7 +63,6 @@
</span><span class="cx">     virtual void didReceiveResponseNetworkSession(WebCore::ResourceResponse&amp;&amp;, ResponseCompletionHandler&amp;&amp;) = 0;
</span><span class="cx">     virtual void didReceiveData(Ref&lt;WebCore::SharedBuffer&gt;&amp;&amp;) = 0;
</span><span class="cx">     virtual void didCompleteWithError(const WebCore::ResourceError&amp;) = 0;
</span><del>-    virtual void didBecomeDownload() = 0;
</del><span class="cx">     virtual void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) = 0;
</span><span class="cx">     virtual void wasBlocked() = 0;
</span><span class="cx">     virtual void cannotShowURL() = 0;
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkDataTaskBlobcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkDataTaskBlob.cpp (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkDataTaskBlob.cpp        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkDataTaskBlob.cpp        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -472,9 +472,7 @@
</span><span class="cx">     downloadManager.dataTaskBecameDownloadTask(m_pendingDownloadID, WTFMove(download));
</span><span class="cx">     downloadPtr-&gt;didCreateDestination(m_pendingDownloadLocation);
</span><span class="cx"> 
</span><del>-    ASSERT(m_client);
-    m_client-&gt;didBecomeDownload();
-
</del><ins>+    ASSERT(!m_client);
</ins><span class="cx">     m_buffer.resize(bufferSize);
</span><span class="cx">     read();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkLoadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -185,7 +185,7 @@
</span><span class="cx">     if (m_parameters.needsCertificateInfo)
</span><span class="cx">         response.includeCertificateInfo();
</span><span class="cx"> 
</span><del>-    return m_client.didReceiveResponse(WTFMove(response));
</del><ins>+    return m_client.get().didReceiveResponse(WTFMove(response));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::sharedWillSendRedirectedRequest(ResourceRequest&amp;&amp; request, ResourceResponse&amp;&amp; redirectResponse)
</span><span class="lines">@@ -196,21 +196,20 @@
</span><span class="cx"> 
</span><span class="cx">     auto oldRequest = WTFMove(m_currentRequest);
</span><span class="cx">     m_currentRequest = request;
</span><del>-    m_client.willSendRedirectedRequest(WTFMove(oldRequest), WTFMove(request), WTFMove(redirectResponse));
</del><ins>+    m_client.get().willSendRedirectedRequest(WTFMove(oldRequest), WTFMove(request), WTFMove(redirectResponse));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx"> 
</span><del>-void NetworkLoad::convertTaskToDownload(DownloadID downloadID, const ResourceRequest&amp; updatedRequest, const ResourceResponse&amp; response)
</del><ins>+void NetworkLoad::convertTaskToDownload(PendingDownload&amp; pendingDownload, const ResourceRequest&amp; updatedRequest, const ResourceResponse&amp; response)
</ins><span class="cx"> {
</span><span class="cx">     if (!m_task)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    m_client = pendingDownload;
</ins><span class="cx">     m_currentRequest = updatedRequest;
</span><del>-    NetworkProcess::singleton().downloadManager().downloadProxyConnection()-&gt;send(Messages::DownloadProxy::DidStart(m_currentRequest, String()), downloadID.downloadID());
-    m_task-&gt;setPendingDownloadID(downloadID);
-    
-    ASSERT(m_responseCompletionHandler);
</del><ins>+    m_task-&gt;setPendingDownload(pendingDownload);
+
</ins><span class="cx">     if (m_responseCompletionHandler)
</span><span class="cx">         NetworkProcess::singleton().findPendingDownloadLocation(*m_task.get(), std::exchange(m_responseCompletionHandler, nullptr), response);
</span><span class="cx"> }
</span><span class="lines">@@ -263,7 +262,7 @@
</span><span class="cx">     m_challenge = challenge;
</span><span class="cx"> #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
</span><span class="cx">     m_challengeCompletionHandler = WTFMove(completionHandler);
</span><del>-    m_client.canAuthenticateAgainstProtectionSpaceAsync(challenge.protectionSpace());
</del><ins>+    m_client.get().canAuthenticateAgainstProtectionSpaceAsync(challenge.protectionSpace());
</ins><span class="cx"> #else
</span><span class="cx">     completeAuthenticationChallenge(WTFMove(completionHandler));
</span><span class="cx"> #endif
</span><span class="lines">@@ -338,7 +337,7 @@
</span><span class="cx"> 
</span><span class="cx">     // FIXME: This should be the encoded data length, not the decoded data length.
</span><span class="cx">     auto size = buffer-&gt;size();
</span><del>-    m_client.didReceiveBuffer(WTFMove(buffer), size);
</del><ins>+    m_client.get().didReceiveBuffer(WTFMove(buffer), size);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::didCompleteWithError(const ResourceError&amp; error)
</span><span class="lines">@@ -346,9 +345,9 @@
</span><span class="cx">     ASSERT(!m_throttle);
</span><span class="cx"> 
</span><span class="cx">     if (error.isNull())
</span><del>-        m_client.didFinishLoading(WTF::monotonicallyIncreasingTime());
</del><ins>+        m_client.get().didFinishLoading(WTF::monotonicallyIncreasingTime());
</ins><span class="cx">     else
</span><del>-        m_client.didFailLoading(error);
</del><ins>+        m_client.get().didFailLoading(error);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::throttleDelayCompleted()
</span><span class="lines">@@ -360,24 +359,19 @@
</span><span class="cx">     notifyDidReceiveResponse(WTFMove(throttle-&gt;response), WTFMove(throttle-&gt;responseCompletionHandler));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void NetworkLoad::didBecomeDownload()
-{
-    m_client.didBecomeDownload();
-}
-
</del><span class="cx"> void NetworkLoad::didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend)
</span><span class="cx"> {
</span><del>-    m_client.didSendData(totalBytesSent, totalBytesExpectedToSend);
</del><ins>+    m_client.get().didSendData(totalBytesSent, totalBytesExpectedToSend);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::wasBlocked()
</span><span class="cx"> {
</span><del>-    m_client.didFailLoading(blockedError(m_currentRequest));
</del><ins>+    m_client.get().didFailLoading(blockedError(m_currentRequest));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::cannotShowURL()
</span><span class="cx"> {
</span><del>-    m_client.didFailLoading(cannotShowURLError(m_currentRequest));
</del><ins>+    m_client.get().didFailLoading(cannotShowURLError(m_currentRequest));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #else
</span><span class="lines">@@ -399,13 +393,13 @@
</span><span class="cx"> void NetworkLoad::didReceiveBuffer(ResourceHandle* handle, Ref&lt;SharedBuffer&gt;&amp;&amp; buffer, int reportedEncodedDataLength)
</span><span class="cx"> {
</span><span class="cx">     ASSERT_UNUSED(handle, handle == m_handle);
</span><del>-    m_client.didReceiveBuffer(WTFMove(buffer), reportedEncodedDataLength);
</del><ins>+    m_client.get().didReceiveBuffer(WTFMove(buffer), reportedEncodedDataLength);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::didFinishLoading(ResourceHandle* handle, double finishTime)
</span><span class="cx"> {
</span><span class="cx">     ASSERT_UNUSED(handle, handle == m_handle);
</span><del>-    m_client.didFinishLoading(finishTime);
</del><ins>+    m_client.get().didFinishLoading(finishTime);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::didFail(ResourceHandle* handle, const ResourceError&amp; error)
</span><span class="lines">@@ -413,7 +407,7 @@
</span><span class="cx">     ASSERT_UNUSED(handle, !handle || handle == m_handle);
</span><span class="cx">     ASSERT(!error.isNull());
</span><span class="cx"> 
</span><del>-    m_client.didFailLoading(error);
</del><ins>+    m_client.get().didFailLoading(error);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::willSendRequestAsync(ResourceHandle* handle, ResourceRequest&amp;&amp; request, ResourceResponse&amp;&amp; redirectResponse)
</span><span class="lines">@@ -436,7 +430,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_waitingForContinueCanAuthenticateAgainstProtectionSpace = true;
</span><del>-    m_client.canAuthenticateAgainstProtectionSpaceAsync(protectionSpace);
</del><ins>+    m_client.get().canAuthenticateAgainstProtectionSpaceAsync(protectionSpace);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::continueCanAuthenticateAgainstProtectionSpace(bool result)
</span><span class="lines">@@ -465,7 +459,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT_UNUSED(handle, handle == m_handle);
</span><span class="cx"> 
</span><del>-    m_client.didSendData(bytesSent, totalBytesToBeSent);
</del><ins>+    m_client.get().didSendData(bytesSent, totalBytesToBeSent);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void NetworkLoad::wasBlocked(ResourceHandle* handle)
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkLoadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkLoad.h (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkLoad.h        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkLoad.h        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx">     void continueDidReceiveResponse();
</span><span class="cx"> 
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><del>-    void convertTaskToDownload(DownloadID, const WebCore::ResourceRequest&amp;, const WebCore::ResourceResponse&amp;);
</del><ins>+    void convertTaskToDownload(PendingDownload&amp;, const WebCore::ResourceRequest&amp;, const WebCore::ResourceResponse&amp;);
</ins><span class="cx">     void setPendingDownloadID(DownloadID);
</span><span class="cx">     void setSuggestedFilename(const String&amp;);
</span><span class="cx">     void setPendingDownload(PendingDownload&amp;);
</span><span class="lines">@@ -113,7 +113,7 @@
</span><span class="cx">     void didReceiveAuthenticationChallenge(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&amp;) final;
</span><span class="cx">     void receivedCancellation(WebCore::ResourceHandle*, const WebCore::AuthenticationChallenge&amp;) final;
</span><span class="cx">     bool usesAsyncCallbacks() final { return true; }
</span><del>-    bool loadingSynchronousXHR() final { return m_client.isSynchronous(); }
</del><ins>+    bool loadingSynchronousXHR() final { return m_client.get().isSynchronous(); }
</ins><span class="cx"> #else
</span><span class="cx">     // NetworkDataTaskClient
</span><span class="cx">     void willPerformHTTPRedirection(WebCore::ResourceResponse&amp;&amp;, WebCore::ResourceRequest&amp;&amp;, RedirectCompletionHandler&amp;&amp;) final;
</span><span class="lines">@@ -121,7 +121,6 @@
</span><span class="cx">     void didReceiveResponseNetworkSession(WebCore::ResourceResponse&amp;&amp;, ResponseCompletionHandler&amp;&amp;) final;
</span><span class="cx">     void didReceiveData(Ref&lt;WebCore::SharedBuffer&gt;&amp;&amp;) final;
</span><span class="cx">     void didCompleteWithError(const WebCore::ResourceError&amp;) final;
</span><del>-    void didBecomeDownload() final;
</del><span class="cx">     void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) final;
</span><span class="cx">     void wasBlocked() final;
</span><span class="cx">     void cannotShowURL() final;
</span><span class="lines">@@ -132,7 +131,7 @@
</span><span class="cx">     void completeAuthenticationChallenge(ChallengeCompletionHandler&amp;&amp;);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    NetworkLoadClient&amp; m_client;
</del><ins>+    std::reference_wrapper&lt;NetworkLoadClient&gt; m_client;
</ins><span class="cx">     const NetworkLoadParameters m_parameters;
</span><span class="cx"> #if USE(NETWORK_SESSION)
</span><span class="cx">     RefPtr&lt;NetworkDataTask&gt; m_task;
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkLoadClienth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkLoadClient.h (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkLoadClient.h        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkLoadClient.h        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -57,9 +57,6 @@
</span><span class="cx">     virtual void didReceiveBuffer(Ref&lt;WebCore::SharedBuffer&gt;&amp;&amp;, int reportedEncodedDataLength) = 0;
</span><span class="cx">     virtual void didFinishLoading(double finishTime) = 0;
</span><span class="cx">     virtual void didFailLoading(const WebCore::ResourceError&amp;) = 0;
</span><del>-#if USE(NETWORK_SESSION)
-    virtual void didBecomeDownload() = 0;
-#endif
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkResourceLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -274,21 +274,11 @@
</span><span class="cx">     m_connection-&gt;didCleanupResourceLoader(*this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void NetworkResourceLoader::didConvertToDownload()
</del><ins>+void NetworkResourceLoader::convertToDownload(DownloadID downloadID, const ResourceRequest&amp; request, const ResourceResponse&amp; response)
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_didConvertToDownload);
</del><span class="cx">     ASSERT(m_networkLoad);
</span><del>-    m_didConvertToDownload = true;
</del><ins>+    NetworkProcess::singleton().downloadManager().convertNetworkLoadToDownload(downloadID, WTFMove(m_networkLoad), request, response);
</ins><span class="cx"> }
</span><del>-    
-#if USE(NETWORK_SESSION)
-void NetworkResourceLoader::didBecomeDownload()
-{
-    ASSERT(m_didConvertToDownload);
-    ASSERT(m_networkLoad);
-    m_networkLoad = nullptr;
-}
-#endif
</del><span class="cx"> 
</span><span class="cx"> void NetworkResourceLoader::abort()
</span><span class="cx"> {
</span><span class="lines">@@ -297,7 +287,7 @@
</span><span class="cx">     RELEASE_LOG_IF_ALLOWED(&quot;abort: Canceling resource load (pageID = %&quot; PRIu64 &quot;, frameID = %&quot; PRIu64 &quot;, resourceID = %&quot; PRIu64 &quot;)&quot;,
</span><span class="cx">         m_parameters.webPageID, m_parameters.webFrameID, m_parameters.identifier);
</span><span class="cx"> 
</span><del>-    if (m_networkLoad &amp;&amp; !m_didConvertToDownload) {
</del><ins>+    if (m_networkLoad) {
</ins><span class="cx"> #if ENABLE(NETWORK_CACHE)
</span><span class="cx">         if (canUseCache(m_networkLoad-&gt;currentRequest())) {
</span><span class="cx">             // We might already have used data from this incomplete load. Ensure older versions don't remain in the cache after cancel.
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkResourceLoaderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef NetworkResourceLoader_h
</span><span class="cx"> #define NetworkResourceLoader_h
</span><span class="cx"> 
</span><ins>+#include &quot;DownloadID.h&quot;
</ins><span class="cx"> #include &quot;MessageSender.h&quot;
</span><span class="cx"> #include &quot;NetworkConnectionToWebProcessMessages.h&quot;
</span><span class="cx"> #include &quot;NetworkLoadClient.h&quot;
</span><span class="lines">@@ -95,12 +96,9 @@
</span><span class="cx">     void didReceiveBuffer(Ref&lt;WebCore::SharedBuffer&gt;&amp;&amp;, int reportedEncodedDataLength) override;
</span><span class="cx">     void didFinishLoading(double finishTime) override;
</span><span class="cx">     void didFailLoading(const WebCore::ResourceError&amp;) override;
</span><del>-#if USE(NETWORK_SESSION)
-    void didBecomeDownload() override;
-#endif
-    
-    void didConvertToDownload();
</del><span class="cx"> 
</span><ins>+    void convertToDownload(DownloadID, const WebCore::ResourceRequest&amp;, const WebCore::ResourceResponse&amp;);
+
</ins><span class="cx">     bool isMainResource() const { return m_parameters.request.requester() == WebCore::ResourceRequest::Requester::Main; }
</span><span class="cx">     bool isAlwaysOnLoggingAllowed() const;
</span><span class="cx"> 
</span><span class="lines">@@ -152,7 +150,6 @@
</span><span class="cx">     std::unique_ptr&lt;SynchronousLoadData&gt; m_synchronousLoadData;
</span><span class="cx">     Vector&lt;RefPtr&lt;WebCore::BlobDataFileReference&gt;&gt; m_fileReferences;
</span><span class="cx"> 
</span><del>-    bool m_didConvertToDownload { false };
</del><span class="cx">     bool m_didConsumeSandboxExtensions { false };
</span><span class="cx">     bool m_defersLoading { false };
</span><span class="cx">     bool m_hasReceivedData { false };
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessPingLoadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/PingLoad.h (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/PingLoad.h        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/PingLoad.h        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -66,7 +66,6 @@
</span><span class="cx">     }
</span><span class="cx">     void didReceiveData(Ref&lt;WebCore::SharedBuffer&gt;&amp;&amp;) final { ASSERT_NOT_REACHED(); }
</span><span class="cx">     void didCompleteWithError(const WebCore::ResourceError&amp;) final { delete this; }
</span><del>-    void didBecomeDownload() final { ASSERT_NOT_REACHED(); }
</del><span class="cx">     void didSendData(uint64_t totalBytesSent, uint64_t totalBytesExpectedToSend) final { }
</span><span class="cx">     void wasBlocked() final { delete this; }
</span><span class="cx">     void cannotShowURL() final { delete this; }
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheSpeculativeLoadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheSpeculativeLoad.h        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -63,9 +63,6 @@
</span><span class="cx">     void didReceiveBuffer(Ref&lt;WebCore::SharedBuffer&gt;&amp;&amp;, int reportedEncodedDataLength) override;
</span><span class="cx">     void didFinishLoading(double finishTime) override;
</span><span class="cx">     void didFailLoading(const WebCore::ResourceError&amp;) override;
</span><del>-#if USE(NETWORK_SESSION)
-    void didBecomeDownload() override { ASSERT_NOT_REACHED(); }
-#endif
</del><span class="cx"> 
</span><span class="cx">     void abort();
</span><span class="cx">     void didComplete();
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscocoaNetworkDataTaskCocoah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.h (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.h        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.h        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -53,7 +53,6 @@
</span><span class="cx">     void didCompleteWithError(const WebCore::ResourceError&amp;);
</span><span class="cx">     void didReceiveResponse(WebCore::ResourceResponse&amp;&amp;, ResponseCompletionHandler&amp;&amp;);
</span><span class="cx">     void didReceiveData(Ref&lt;WebCore::SharedBuffer&gt;&amp;&amp;);
</span><del>-    void didBecomeDownload();
</del><span class="cx"> 
</span><span class="cx">     void willPerformHTTPRedirection(WebCore::ResourceResponse&amp;&amp;, WebCore::ResourceRequest&amp;&amp;, RedirectCompletionHandler&amp;&amp;);
</span><span class="cx">     void transferSandboxExtensionToDownload(Download&amp;);
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscocoaNetworkDataTaskCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -171,12 +171,6 @@
</span><span class="cx">         m_client-&gt;didReceiveData(WTFMove(data));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void NetworkDataTaskCocoa::didBecomeDownload()
-{
-    if (m_client)
-        m_client-&gt;didBecomeDownload();
-}
-
</del><span class="cx"> void NetworkDataTaskCocoa::willPerformHTTPRedirection(WebCore::ResourceResponse&amp;&amp; redirectResponse, WebCore::ResourceRequest&amp;&amp; request, RedirectCompletionHandler&amp;&amp; completionHandler)
</span><span class="cx"> {
</span><span class="cx">     if (redirectResponse.httpStatusCode() == 307 || redirectResponse.httpStatusCode() == 308) {
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscocoaNetworkSessionCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -304,7 +304,6 @@
</span><span class="cx">         ASSERT(WebCore::fileExists(networkDataTask-&gt;pendingDownloadLocation()));
</span><span class="cx">         download-&gt;didCreateDestination(networkDataTask-&gt;pendingDownloadLocation());
</span><span class="cx">         downloadManager.dataTaskBecameDownloadTask(downloadID, WTFMove(download));
</span><del>-        networkDataTask-&gt;didBecomeDownload();
</del><span class="cx"> 
</span><span class="cx">         _session-&gt;addDownloadID([downloadTask taskIdentifier], downloadID);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesssoupNetworkDataTaskSoupcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/soup/NetworkDataTaskSoup.cpp (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/soup/NetworkDataTaskSoup.cpp        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Source/WebKit2/NetworkProcess/soup/NetworkDataTaskSoup.cpp        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -862,9 +862,7 @@
</span><span class="cx">     downloadManager.dataTaskBecameDownloadTask(m_pendingDownloadID, WTFMove(download));
</span><span class="cx">     downloadPtr-&gt;didCreateDestination(m_pendingDownloadLocation);
</span><span class="cx"> 
</span><del>-    ASSERT(m_client);
-    m_client-&gt;didBecomeDownload();
-
</del><ins>+    ASSERT(!m_client);
</ins><span class="cx">     read();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Tools/ChangeLog        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -1,3 +1,20 @@
</span><ins>+2016-11-09  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        NetworkSession: Network process crash when converting main resource to download
+        https://bugs.webkit.org/show_bug.cgi?id=164220
+
+        Reviewed by Alex Christensen.
+
+        Split /webkit2/Downloads/policy-decision-download in two, one to test the full load when main resource is
+        converted to a download and another one to test the cancellation as the test was doing before. When doing the
+        full load, delay a bit the decide destination to ensure the load is aborted before the data task has became a
+        download.
+
+        * TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp:
+        (testPolicyResponseDownload):
+        (testPolicyResponseDownloadCancel):
+        (beforeAll):
+
</ins><span class="cx"> 2016-11-09  KwangHyuk Kim  &lt;hyuki.kim@samsung.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [EFL] fix error message caused by eina log
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2GtkTestDownloadscpp"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp (208520 => 208521)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp        2016-11-10 03:54:06 UTC (rev 208520)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp        2016-11-10 04:49:09 UTC (rev 208521)
</span><span class="lines">@@ -515,6 +515,8 @@
</span><span class="cx">     {
</span><span class="cx">         test-&gt;m_download = download;
</span><span class="cx">         test-&gt;assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download));
</span><ins>+        g_signal_connect(download, &quot;decide-destination&quot;, G_CALLBACK(downloadDecideDestinationCallback), test);
+        g_signal_connect(download, &quot;finished&quot;, G_CALLBACK(downloadFinishedCallback), test);
</ins><span class="cx">         test-&gt;quitMainLoop();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -539,6 +541,8 @@
</span><span class="cx">     {
</span><span class="cx">         GUniquePtr&lt;char&gt; destination(g_build_filename(Test::dataDirectory(), suggestedFilename, nullptr));
</span><span class="cx">         GUniquePtr&lt;char&gt; destinationURI(g_filename_to_uri(destination.get(), 0, 0));
</span><ins>+        if (test-&gt;m_shouldDelayDecideDestination)
+            g_usleep(0.2 * G_USEC_PER_SEC);
</ins><span class="cx">         webkit_download_set_destination(download, destinationURI.get());
</span><span class="cx">         return TRUE;
</span><span class="cx">     }
</span><span class="lines">@@ -550,12 +554,11 @@
</span><span class="cx"> 
</span><span class="cx">     void waitUntilDownloadFinished()
</span><span class="cx">     {
</span><del>-        g_signal_connect(m_download.get(), &quot;decide-destination&quot;, G_CALLBACK(downloadDecideDestinationCallback), this);
-        g_signal_connect(m_download.get(), &quot;finished&quot;, G_CALLBACK(downloadFinishedCallback), this);
</del><span class="cx">         g_main_loop_run(m_mainLoop);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     GRefPtr&lt;WebKitDownload&gt; m_download;
</span><ins>+    bool m_shouldDelayDecideDestination { false };
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static void testWebViewDownloadURI(WebViewDownloadTest* test, gconstpointer)
</span><span class="lines">@@ -604,8 +607,10 @@
</span><span class="cx"> 
</span><span class="cx"> static void testPolicyResponseDownload(PolicyResponseDownloadTest* test, gconstpointer)
</span><span class="cx"> {
</span><del>-    // Test that a download started by the the policy checker contains the web view.
</del><span class="cx">     CString requestURI = kServer-&gt;getURIForPath(&quot;/test.pdf&quot;).data();
</span><ins>+    // Delay the DecideDestination to ensure that the load is aborted before the network task has became a download.
+    // See https://bugs.webkit.org/show_bug.cgi?id=164220.
+    test-&gt;m_shouldDelayDecideDestination = true;
</ins><span class="cx">     test-&gt;loadURI(requestURI.data());
</span><span class="cx">     test-&gt;waitUntilDownloadStarted();
</span><span class="cx"> 
</span><span class="lines">@@ -614,6 +619,25 @@
</span><span class="cx">     ASSERT_CMP_CSTRING(webkit_uri_request_get_uri(request), ==, requestURI);
</span><span class="cx"> 
</span><span class="cx">     g_assert(test-&gt;m_webView == webkit_download_get_web_view(test-&gt;m_download.get()));
</span><ins>+    test-&gt;waitUntilDownloadFinished();
+
+    GRefPtr&lt;GFile&gt; downloadFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(test-&gt;m_download.get())));
+    GRefPtr&lt;GFileInfo&gt; downloadFileInfo = adoptGRef(g_file_query_info(downloadFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast&lt;GFileQueryInfoFlags&gt;(0), nullptr, nullptr));
+    g_assert_cmpint(g_file_info_get_size(downloadFileInfo.get()), &gt;, 0);
+    g_file_delete(downloadFile.get(), nullptr, nullptr);
+}
+
+static void testPolicyResponseDownloadCancel(PolicyResponseDownloadTest* test, gconstpointer)
+{
+    CString requestURI = kServer-&gt;getURIForPath(&quot;/test.pdf&quot;).data();
+    test-&gt;loadURI(requestURI.data());
+    test-&gt;waitUntilDownloadStarted();
+
+    WebKitURIRequest* request = webkit_download_get_request(test-&gt;m_download.get());
+    g_assert(request);
+    ASSERT_CMP_CSTRING(webkit_uri_request_get_uri(request), ==, requestURI);
+
+    g_assert(test-&gt;m_webView == webkit_download_get_web_view(test-&gt;m_download.get()));
</ins><span class="cx">     test-&gt;cancelDownloadAndWaitUntilFinished();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -657,6 +681,7 @@
</span><span class="cx">     DownloadErrorTest::add(&quot;Downloads&quot;, &quot;remote-file-error&quot;, testDownloadRemoteFileError);
</span><span class="cx">     WebViewDownloadTest::add(&quot;WebKitWebView&quot;, &quot;download-uri&quot;, testWebViewDownloadURI);
</span><span class="cx">     PolicyResponseDownloadTest::add(&quot;Downloads&quot;, &quot;policy-decision-download&quot;, testPolicyResponseDownload);
</span><ins>+    PolicyResponseDownloadTest::add(&quot;Downloads&quot;, &quot;policy-decision-download-cancel&quot;, testPolicyResponseDownloadCancel);
</ins><span class="cx">     DownloadTest::add(&quot;Downloads&quot;, &quot;mime-type&quot;, testDownloadMIMEType);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>