Reland: Introduce ResourceDownloader for url downloading with network service

The previous CL: https://chromium-review.googlesource.com/c/chromium/src/+/621772 was reverted,
due to broken test on network service bot.
However, those test shouldn't pass in the first place.
The test passes because they are not using network service.
Instead, they are using the UrlRequest codepath.
This CL is clone of the original CL, but it removed the if statement to create ResourceDownloader
in DownloadManagerImpl. I added a TODO instead.
Will enable the ResourceDownload creation when the new code path fully works,
so network service bot will be happy.

Both the ResourceDownloader and the UrlDownloader now inherits UrlDownloadHandler,
so DownloadManagerImpl/DownloadWorker can reuse most of the current code for both implementations.
The ResourceDownloader returns a data pipe when download starts,
DownloadManagerImpl/DownloadWorker can use the data pipe to initialize DownloadFile.

Bug=715630

Change-Id: Ia4cdfee066e0c8236b941437b58393bdeaaaa5fc
Reviewed-on: https://chromium-review.googlesource.com/631636
Commit-Queue: Min Qin <[email protected]>
Reviewed-by: Bo <[email protected]>
Cr-Commit-Position: refs/heads/master@{#497336}
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index b87f694..0abd4a0f 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -30,9 +30,13 @@
 #include "content/browser/download/download_item_impl.h"
 #include "content/browser/download/download_stats.h"
 #include "content/browser/download/download_task_runner.h"
+#include "content/browser/download/download_utils.h"
+#include "content/browser/download/resource_downloader.h"
+#include "content/browser/download/url_downloader.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/loader/resource_request_info_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/storage_partition_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/content_browser_client.h"
@@ -44,6 +48,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/resource_context.h"
 #include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/content_features.h"
 #include "content/public/common/previews_state.h"
 #include "content/public/common/referrer.h"
 #include "net/base/elements_upload_data_stream.h"
@@ -63,6 +68,24 @@
 namespace content {
 namespace {
 
+scoped_refptr<URLLoaderFactoryGetter> GetURLLoaderFactoryGetter(
+    BrowserContext* context,
+    int render_process_id,
+    int render_frame_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  SiteInstance* site_instance = nullptr;
+  if (render_process_id >= 0) {
+    RenderFrameHost* render_frame_host_ =
+        RenderFrameHost::FromID(render_process_id, render_frame_id);
+    if (render_frame_host_)
+      site_instance = render_frame_host_->GetSiteInstance();
+  }
+  StoragePartitionImpl* partition = static_cast<StoragePartitionImpl*>(
+      BrowserContext::GetStoragePartition(context, site_instance));
+  return partition->url_loader_factory_getter();
+}
+
 std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread> BeginDownload(
     std::unique_ptr<DownloadUrlParameters> params,
     content::ResourceContext* resource_context,
@@ -117,6 +140,23 @@
           .release());
 }
 
+std::unique_ptr<ResourceDownloader, BrowserThread::DeleteOnIOThread>
+BeginResourceDownload(
+    std::unique_ptr<DownloadUrlParameters> params,
+    std::unique_ptr<ResourceRequest> request,
+    scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter,
+    uint32_t download_id,
+    base::WeakPtr<DownloadManagerImpl> download_manager) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  return std::unique_ptr<ResourceDownloader, BrowserThread::DeleteOnIOThread>(
+      ResourceDownloader::BeginDownload(download_manager, std::move(params),
+                                        std::move(request),
+                                        url_loader_factory_getter, download_id,
+                                        false)
+          .release());
+}
+
 class DownloadItemFactoryImpl : public DownloadItemFactory {
  public:
   DownloadItemFactoryImpl() {}
@@ -304,7 +344,7 @@
   }
   downloads_.clear();
   downloads_by_guid_.clear();
-  url_downloaders_.clear();
+  url_download_handlers_.clear();
 
   // We'll have nothing more to report to the observers after this point.
   observers_.Clear();
@@ -502,7 +542,7 @@
       base::Bind(&BeginDownload, base::Passed(&params),
                  browser_context_->GetResourceContext(), id,
                  weak_factory_.GetWeakPtr()),
-      base::Bind(&DownloadManagerImpl::AddUrlDownloader,
+      base::Bind(&DownloadManagerImpl::AddUrlDownloadHandler,
                  weak_factory_.GetWeakPtr()));
 }
 
@@ -528,11 +568,11 @@
   downloads_.erase(download->GetId());
 }
 
-void DownloadManagerImpl::AddUrlDownloader(
-    std::unique_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>
+void DownloadManagerImpl::AddUrlDownloadHandler(
+    std::unique_ptr<UrlDownloadHandler, BrowserThread::DeleteOnIOThread>
         downloader) {
   if (downloader)
-    url_downloaders_.push_back(std::move(downloader));
+    url_download_handlers_.push_back(std::move(downloader));
 }
 
 // static
@@ -625,13 +665,34 @@
     DCHECK(params->prefer_cache());
     DCHECK_EQ("POST", params->method());
   }
-  BrowserThread::PostTaskAndReplyWithResult(
-      BrowserThread::IO, FROM_HERE,
-      base::Bind(&BeginDownload, base::Passed(&params),
-                 browser_context_->GetResourceContext(),
-                 content::DownloadItem::kInvalidId, weak_factory_.GetWeakPtr()),
-      base::Bind(&DownloadManagerImpl::AddUrlDownloader,
-                 weak_factory_.GetWeakPtr()));
+
+  // TODO(qinmin): remove false from the if statement once download works when
+  // network service is enabled, or once we disable the tests that are currently
+  // passing with the URLRequest code path.
+  if (base::FeatureList::IsEnabled(features::kNetworkService) && false) {
+    std::unique_ptr<ResourceRequest> request = CreateResourceRequest(
+        params.get());
+    BrowserThread::PostTaskAndReplyWithResult(
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&BeginResourceDownload, std::move(params),
+                       std::move(request),
+                       GetURLLoaderFactoryGetter(
+                           browser_context_, params->render_process_host_id(),
+                           params->render_frame_host_routing_id()),
+                       content::DownloadItem::kInvalidId,
+                       weak_factory_.GetWeakPtr()),
+        base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler,
+                       weak_factory_.GetWeakPtr()));
+  } else {
+    BrowserThread::PostTaskAndReplyWithResult(
+        BrowserThread::IO, FROM_HERE,
+        base::BindOnce(&BeginDownload, std::move(params),
+                       browser_context_->GetResourceContext(),
+                       content::DownloadItem::kInvalidId,
+                       weak_factory_.GetWeakPtr()),
+        base::BindOnce(&DownloadManagerImpl::AddUrlDownloadHandler,
+                       weak_factory_.GetWeakPtr()));
+  }
 }
 
 void DownloadManagerImpl::AddObserver(Observer* observer) {
@@ -734,19 +795,21 @@
                                                      : nullptr;
 }
 
-void DownloadManagerImpl::OnUrlDownloaderStarted(
+void DownloadManagerImpl::OnUrlDownloadStarted(
     std::unique_ptr<DownloadCreateInfo> download_create_info,
-    std::unique_ptr<ByteStreamReader> stream_reader,
+    std::unique_ptr<UrlDownloadHandler::InputStream> input_stream,
     const DownloadUrlParameters::OnStartedCallback& callback) {
-  StartDownload(std::move(download_create_info), std::move(stream_reader),
-                callback);
+  if (!base::FeatureList::IsEnabled(features::kNetworkService)) {
+    StartDownload(std::move(download_create_info),
+                  std::move(input_stream->stream_reader_), callback);
+  }
 }
 
-void DownloadManagerImpl::OnUrlDownloaderStopped(UrlDownloader* downloader) {
-  for (auto ptr = url_downloaders_.begin(); ptr != url_downloaders_.end();
-       ++ptr) {
+void DownloadManagerImpl::OnUrlDownloadStopped(UrlDownloadHandler* downloader) {
+  for (auto ptr = url_download_handlers_.begin();
+       ptr != url_download_handlers_.end(); ++ptr) {
     if (ptr->get() == downloader) {
-      url_downloaders_.erase(ptr);
+      url_download_handlers_.erase(ptr);
       return;
     }
   }