| // 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 "content/browser/download/download_utils.h" |
| |
| #include "base/format_macros.h" |
| #include "base/process/process_handle.h" |
| #include "base/rand_util.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/task_scheduler/post_task.h" |
| #include "components/download/downloader/in_progress/download_entry.h" |
| #include "components/download/downloader/in_progress/in_progress_cache.h" |
| #include "components/download/public/common/download_create_info.h" |
| #include "components/download/public/common/download_interrupt_reasons_utils.h" |
| #include "components/download/public/common/download_save_info.h" |
| #include "components/download/public/common/download_url_parameters.h" |
| #include "components/download/public/common/download_utils.h" |
| #include "content/browser/blob_storage/chrome_blob_storage_context.h" |
| #include "content/browser/loader/upload_data_stream_builder.h" |
| #include "content/browser/resource_context_impl.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/download_manager_delegate.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "net/base/elements_upload_data_stream.h" |
| #include "net/base/upload_bytes_element_reader.h" |
| #include "net/http/http_request_headers.h" |
| #include "net/url_request/url_request_context.h" |
| |
| namespace content { |
| |
| storage::BlobStorageContext* BlobStorageContextGetter( |
| ResourceContext* resource_context) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| ChromeBlobStorageContext* blob_context = |
| GetChromeBlobStorageContextForResourceContext(resource_context); |
| return blob_context->context(); |
| } |
| |
| std::unique_ptr<net::URLRequest> CreateURLRequestOnIOThread( |
| download::DownloadUrlParameters* params) { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| DCHECK(params->offset() >= 0); |
| |
| // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and |
| // download::DownloadUrlParameters can-not include |
| // resource_dispatcher_host_impl.h, so we must down cast. RDHI is the only |
| // subclass of RDH as of 2012 May 4. |
| std::unique_ptr<net::URLRequest> request( |
| params->url_request_context_getter() |
| ->GetURLRequestContext() |
| ->CreateRequest(params->url(), net::DEFAULT_PRIORITY, nullptr, |
| params->GetNetworkTrafficAnnotation())); |
| request->set_method(params->method()); |
| |
| if (params->post_body()) { |
| storage::BlobStorageContext* blob_context = |
| params->get_blob_storage_context_getter().Run(); |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner = |
| base::CreateSingleThreadTaskRunnerWithTraits( |
| {base::MayBlock(), base::TaskPriority::USER_VISIBLE}); |
| std::unique_ptr<net::UploadDataStream> upload_data_stream = |
| UploadDataStreamBuilder::Build(params->post_body().get(), blob_context, |
| nullptr /*FileSystemContext*/, |
| task_runner.get()); |
| request->set_upload(std::move(upload_data_stream)); |
| } |
| |
| if (params->post_id() >= 0) { |
| // The POST in this case does not have an actual body, and only works |
| // when retrieving data from cache. This is done because we don't want |
| // to do a re-POST without user consent, and currently don't have a good |
| // plan on how to display the UI for that. |
| DCHECK(params->prefer_cache()); |
| DCHECK_EQ("POST", params->method()); |
| std::vector<std::unique_ptr<net::UploadElementReader>> element_readers; |
| request->set_upload(std::make_unique<net::ElementsUploadDataStream>( |
| std::move(element_readers), params->post_id())); |
| } |
| |
| request->SetLoadFlags(download::GetLoadFlags(params, request->get_upload())); |
| |
| // Add additional request headers. |
| std::unique_ptr<net::HttpRequestHeaders> headers = |
| download::GetAdditionalRequestHeaders(params); |
| if (!headers->IsEmpty()) |
| request->SetExtraRequestHeaders(*headers); |
| |
| // Downloads are treated as top level navigations. Hence the first-party |
| // origin for cookies is always based on the target URL and is updated on |
| // redirects. |
| request->set_site_for_cookies(params->url()); |
| request->set_first_party_url_policy( |
| net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT); |
| request->set_initiator(params->initiator()); |
| |
| return request; |
| } |
| |
| // Gets the unique download id for ukm reporting. |
| uint64_t GetUniqueDownloadId() { |
| // Get a new UKM download_id that is not 0. |
| uint64_t download_id = 0; |
| do { |
| download_id = base::RandUint64(); |
| } while (download_id == 0); |
| return download_id; |
| } |
| |
| } // namespace content |