summaryrefslogtreecommitdiff
path: root/chromium/components/download/internal/common/resource_downloader.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/download/internal/common/resource_downloader.cc')
-rw-r--r--chromium/components/download/internal/common/resource_downloader.cc226
1 files changed, 226 insertions, 0 deletions
diff --git a/chromium/components/download/internal/common/resource_downloader.cc b/chromium/components/download/internal/common/resource_downloader.cc
new file mode 100644
index 00000000000..ab961f310e3
--- /dev/null
+++ b/chromium/components/download/internal/common/resource_downloader.cc
@@ -0,0 +1,226 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/download/public/common/resource_downloader.h"
+
+#include <memory>
+
+#include "base/strings/utf_string_conversions.h"
+#include "components/download/public/common/stream_handle_input_stream.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+
+namespace network {
+struct ResourceResponseHead;
+}
+
+namespace download {
+
+// This object monitors the URLLoaderCompletionStatus change when
+// ResourceDownloader is asking |delegate_| whether download can proceed.
+class URLLoaderStatusMonitor : public network::mojom::URLLoaderClient {
+ public:
+ using URLLoaderStatusChangeCallback =
+ base::OnceCallback<void(const network::URLLoaderCompletionStatus&)>;
+ explicit URLLoaderStatusMonitor(URLLoaderStatusChangeCallback callback);
+ ~URLLoaderStatusMonitor() override = default;
+
+ // network::mojom::URLLoaderClient
+ void OnReceiveResponse(
+ const network::ResourceResponseHead& head,
+ network::mojom::DownloadedTempFilePtr downloaded_file) override {}
+ void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
+ const network::ResourceResponseHead& head) override {}
+ void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
+ void OnUploadProgress(int64_t current_position,
+ int64_t total_size,
+ OnUploadProgressCallback callback) override {}
+ void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
+ void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
+ void OnStartLoadingResponseBody(
+ mojo::ScopedDataPipeConsumerHandle body) override {}
+ void OnComplete(const network::URLLoaderCompletionStatus& status) override;
+
+ private:
+ URLLoaderStatusChangeCallback callback_;
+ DISALLOW_COPY_AND_ASSIGN(URLLoaderStatusMonitor);
+};
+
+URLLoaderStatusMonitor::URLLoaderStatusMonitor(
+ URLLoaderStatusChangeCallback callback)
+ : callback_(std::move(callback)) {}
+
+void URLLoaderStatusMonitor::OnComplete(
+ const network::URLLoaderCompletionStatus& status) {
+ std::move(callback_).Run(status);
+}
+
+// static
+std::unique_ptr<ResourceDownloader> ResourceDownloader::BeginDownload(
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+ std::unique_ptr<DownloadUrlParameters> params,
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ const GURL& site_url,
+ const GURL& tab_url,
+ const GURL& tab_referrer_url,
+ uint32_t download_id,
+ bool is_parallel_request,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
+ auto downloader = std::make_unique<ResourceDownloader>(
+ delegate, std::move(request), params->render_process_host_id(),
+ params->render_frame_host_routing_id(), site_url, tab_url,
+ tab_referrer_url, download_id, task_runner,
+ std::move(shared_url_loader_factory));
+
+ downloader->Start(std::move(params), is_parallel_request);
+ return downloader;
+}
+
+// static
+std::unique_ptr<ResourceDownloader>
+ResourceDownloader::InterceptNavigationResponse(
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+ std::unique_ptr<network::ResourceRequest> resource_request,
+ int render_process_id,
+ int render_frame_id,
+ const GURL& site_url,
+ const GURL& tab_url,
+ const GURL& tab_referrer_url,
+ std::vector<GURL> url_chain,
+ const base::Optional<std::string>& suggested_filename,
+ const scoped_refptr<network::ResourceResponse>& response,
+ net::CertStatus cert_status,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
+ auto downloader = std::make_unique<ResourceDownloader>(
+ delegate, std::move(resource_request), render_process_id, render_frame_id,
+ site_url, tab_url, tab_referrer_url, download::DownloadItem::kInvalidId,
+ task_runner, std::move(shared_url_loader_factory));
+ downloader->InterceptResponse(std::move(response), std::move(url_chain),
+ suggested_filename, cert_status,
+ std::move(url_loader_client_endpoints));
+ return downloader;
+}
+
+ResourceDownloader::ResourceDownloader(
+ base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
+ std::unique_ptr<network::ResourceRequest> resource_request,
+ int render_process_id,
+ int render_frame_id,
+ const GURL& site_url,
+ const GURL& tab_url,
+ const GURL& tab_referrer_url,
+ uint32_t download_id,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory)
+ : delegate_(delegate),
+ resource_request_(std::move(resource_request)),
+ download_id_(download_id),
+ render_process_id_(render_process_id),
+ render_frame_id_(render_frame_id),
+ site_url_(site_url),
+ tab_url_(tab_url),
+ tab_referrer_url_(tab_referrer_url),
+ delegate_task_runner_(task_runner),
+ shared_url_loader_factory_(std::move(shared_url_loader_factory)),
+ weak_ptr_factory_(this) {}
+
+ResourceDownloader::~ResourceDownloader() = default;
+
+void ResourceDownloader::Start(
+ std::unique_ptr<DownloadUrlParameters> download_url_parameters,
+ bool is_parallel_request) {
+ callback_ = download_url_parameters->callback();
+ guid_ = download_url_parameters->guid();
+
+ // Set up the URLLoaderClient.
+ url_loader_client_ = std::make_unique<DownloadResponseHandler>(
+ resource_request_.get(), this,
+ std::make_unique<DownloadSaveInfo>(
+ download_url_parameters->GetSaveInfo()),
+ is_parallel_request, download_url_parameters->is_transient(),
+ download_url_parameters->fetch_error_body(),
+ download_url_parameters->request_headers(),
+ download_url_parameters->request_origin(),
+ download_url_parameters->download_source(),
+ std::vector<GURL>(1, resource_request_->url));
+ network::mojom::URLLoaderClientPtr url_loader_client_ptr;
+ url_loader_client_binding_ =
+ std::make_unique<mojo::Binding<network::mojom::URLLoaderClient>>(
+ url_loader_client_.get(), mojo::MakeRequest(&url_loader_client_ptr));
+
+ // Set up the URLLoader
+ network::mojom::URLLoaderRequest url_loader_request =
+ mojo::MakeRequest(&url_loader_);
+ shared_url_loader_factory_->CreateLoaderAndStart(
+ std::move(url_loader_request),
+ 0, // routing_id
+ 0, // request_id
+ network::mojom::kURLLoadOptionSendSSLInfoWithResponse,
+ *(resource_request_.get()), std::move(url_loader_client_ptr),
+ net::MutableNetworkTrafficAnnotationTag(
+ download_url_parameters->GetNetworkTrafficAnnotation()));
+ url_loader_->SetPriority(net::RequestPriority::IDLE,
+ 0 /* intra_priority_value */);
+}
+
+void ResourceDownloader::InterceptResponse(
+ const scoped_refptr<network::ResourceResponse>& response,
+ std::vector<GURL> url_chain,
+ const base::Optional<std::string>& suggested_filename,
+ net::CertStatus cert_status,
+ network::mojom::URLLoaderClientEndpointsPtr endpoints) {
+ // Set the URLLoader.
+ url_loader_.Bind(std::move(endpoints->url_loader));
+
+ // Create the new URLLoaderClient that will intercept the navigation.
+ auto save_info = std::make_unique<DownloadSaveInfo>();
+ if (suggested_filename.has_value())
+ save_info->suggested_name = base::UTF8ToUTF16(suggested_filename.value());
+ url_loader_client_ = std::make_unique<DownloadResponseHandler>(
+ resource_request_.get(), this, std::move(save_info),
+ false, /* is_parallel_request */
+ false, /* is_transient */
+ false, /* fetch_error_body */
+ download::DownloadUrlParameters::RequestHeadersType(),
+ std::string(), /* request_origin */
+ download::DownloadSource::NAVIGATION, std::move(url_chain));
+
+ // Simulate on the new URLLoaderClient calls that happened on the old client.
+ response->head.cert_status = cert_status;
+ url_loader_client_->OnReceiveResponse(
+ response->head, network::mojom::DownloadedTempFilePtr());
+
+ // Bind the new client.
+ url_loader_client_binding_ =
+ std::make_unique<mojo::Binding<network::mojom::URLLoaderClient>>(
+ url_loader_client_.get(), std::move(endpoints->url_loader_client));
+}
+
+void ResourceDownloader::OnResponseStarted(
+ std::unique_ptr<DownloadCreateInfo> download_create_info,
+ mojom::DownloadStreamHandlePtr stream_handle) {
+ download_create_info->download_id = download_id_;
+ download_create_info->guid = guid_;
+ download_create_info->site_url = site_url_;
+ download_create_info->tab_url = tab_url_;
+ download_create_info->tab_referrer_url = tab_referrer_url_;
+ download_create_info->render_process_id = render_process_id_;
+ download_create_info->render_frame_id = render_frame_id_;
+
+ delegate_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &UrlDownloadHandler::Delegate::OnUrlDownloadStarted, delegate_,
+ std::move(download_create_info),
+ std::make_unique<StreamHandleInputStream>(std::move(stream_handle)),
+ std::move(shared_url_loader_factory_), callback_));
+}
+
+void ResourceDownloader::OnReceiveRedirect() {
+ url_loader_->FollowRedirect();
+}
+
+} // namespace download