summaryrefslogtreecommitdiff
path: root/chromium/components/download/internal
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/download/internal')
-rw-r--r--chromium/components/download/internal/background_service/blob_task_proxy.cc2
-rw-r--r--chromium/components/download/internal/background_service/controller_impl.cc2
-rw-r--r--chromium/components/download/internal/background_service/controller_impl_unittest.cc4
-rw-r--r--chromium/components/download/internal/background_service/entry_utils.cc16
-rw-r--r--chromium/components/download/internal/background_service/entry_utils.h9
-rw-r--r--chromium/components/download/internal/background_service/entry_utils_unittest.cc56
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver.cc2
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver.h1
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_unittest.cc2
-rw-r--r--chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc5
-rw-r--r--chromium/components/download/internal/common/BUILD.gn7
-rw-r--r--chromium/components/download/internal/common/DEPS3
-rw-r--r--chromium/components/download/internal/common/base_file.cc32
-rw-r--r--chromium/components/download/internal/common/base_file_win.cc17
-rw-r--r--chromium/components/download/internal/common/download_file_impl.cc8
-rw-r--r--chromium/components/download/internal/common/download_file_unittest.cc10
-rw-r--r--chromium/components/download/internal/common/download_item_impl.cc40
-rw-r--r--chromium/components/download/internal/common/download_item_impl_unittest.cc49
-rw-r--r--chromium/components/download/internal/common/download_job_factory.cc13
-rw-r--r--chromium/components/download/internal/common/download_stats.cc3
-rw-r--r--chromium/components/download/internal/common/download_task_runner.cc1
-rw-r--r--chromium/components/download/internal/common/download_utils.cc21
-rw-r--r--chromium/components/download/internal/common/download_worker.cc20
-rw-r--r--chromium/components/download/internal/common/download_worker.h17
-rw-r--r--chromium/components/download/internal/common/in_progress_download_manager.cc402
-rw-r--r--chromium/components/download/internal/common/parallel_download_job.cc19
-rw-r--r--chromium/components/download/internal/common/parallel_download_job.h14
-rw-r--r--chromium/components/download/internal/common/parallel_download_job_unittest.cc14
-rw-r--r--chromium/components/download/internal/common/resource_downloader.cc34
-rw-r--r--chromium/components/download/internal/common/resource_downloader.h145
-rw-r--r--chromium/components/download/internal/common/url_download_handler_factory.cc13
31 files changed, 841 insertions, 140 deletions
diff --git a/chromium/components/download/internal/background_service/blob_task_proxy.cc b/chromium/components/download/internal/background_service/blob_task_proxy.cc
index ab525937720..4c0813902d0 100644
--- a/chromium/components/download/internal/background_service/blob_task_proxy.cc
+++ b/chromium/components/download/internal/background_service/blob_task_proxy.cc
@@ -61,7 +61,7 @@ void BlobTaskProxy::SaveAsBlobOnIO(std::unique_ptr<std::string> data,
// Build blob data. This has to do a copy into blob's internal storage.
std::string blob_uuid = base::GenerateGUID();
auto builder = std::make_unique<storage::BlobDataBuilder>(blob_uuid);
- builder->AppendData(*data.get());
+ builder->AppendData(*data);
blob_data_handle_ =
blob_storage_context_->AddFinishedBlob(std::move(builder));
diff --git a/chromium/components/download/internal/background_service/controller_impl.cc b/chromium/components/download/internal/background_service/controller_impl.cc
index 5b602187936..2150eca0b17 100644
--- a/chromium/components/download/internal/background_service/controller_impl.cc
+++ b/chromium/components/download/internal/background_service/controller_impl.cc
@@ -1051,7 +1051,7 @@ void ControllerImpl::KillTimedOutUploads() {
void ControllerImpl::NotifyClientsOfStartup(bool state_lost) {
auto categorized = util::MapEntriesToMetadataForClients(
- clients_->GetRegisteredClients(), model_->PeekEntries());
+ clients_->GetRegisteredClients(), model_->PeekEntries(), driver_.get());
for (auto client_id : clients_->GetRegisteredClients()) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chromium/components/download/internal/background_service/controller_impl_unittest.cc b/chromium/components/download/internal/background_service/controller_impl_unittest.cc
index 66d8ff523da..1e4f96bab34 100644
--- a/chromium/components/download/internal/background_service/controller_impl_unittest.cc
+++ b/chromium/components/download/internal/background_service/controller_impl_unittest.cc
@@ -437,8 +437,8 @@ TEST_F(DownloadServiceControllerImplTest, SuccessfulInitWithExistingDownload) {
std::vector<Entry> entries = {entry1, entry2, entry3};
std::vector<DownloadMetaData> expected_downloads = {
- util::BuildDownloadMetaData(&entry1),
- util::BuildDownloadMetaData(&entry2)};
+ util::BuildDownloadMetaData(&entry1, driver_),
+ util::BuildDownloadMetaData(&entry2, driver_)};
EXPECT_CALL(*client_,
OnServiceInitialized(false, testing::UnorderedElementsAreArray(
diff --git a/chromium/components/download/internal/background_service/entry_utils.cc b/chromium/components/download/internal/background_service/entry_utils.cc
index 8738cb02350..4402d4c9647 100644
--- a/chromium/components/download/internal/background_service/entry_utils.cc
+++ b/chromium/components/download/internal/background_service/entry_utils.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "components/download/internal/background_service/download_driver.h"
#include "components/download/internal/background_service/entry.h"
#include "components/download/public/background_service/download_metadata.h"
@@ -24,7 +25,8 @@ uint32_t GetNumberOfLiveEntriesForClient(DownloadClient client,
std::map<DownloadClient, std::vector<DownloadMetaData>>
MapEntriesToMetadataForClients(const std::set<DownloadClient>& clients,
- const std::vector<Entry*>& entries) {
+ const std::vector<Entry*>& entries,
+ DownloadDriver* driver) {
std::map<DownloadClient, std::vector<DownloadMetaData>> categorized;
for (auto* entry : entries) {
@@ -32,7 +34,7 @@ MapEntriesToMetadataForClients(const std::set<DownloadClient>& clients,
if (clients.find(client) == clients.end())
client = DownloadClient::INVALID;
- categorized[client].push_back(BuildDownloadMetaData(entry));
+ categorized[client].push_back(BuildDownloadMetaData(entry, driver));
}
return categorized;
@@ -86,14 +88,22 @@ bool EntryBetterThan(const Entry& lhs, const Entry& rhs) {
return lhs.create_time < rhs.create_time;
}
-DownloadMetaData BuildDownloadMetaData(Entry* entry) {
+DownloadMetaData BuildDownloadMetaData(Entry* entry, DownloadDriver* driver) {
DCHECK(entry);
DownloadMetaData meta_data;
meta_data.guid = entry->guid;
if (entry->state == Entry::State::COMPLETE) {
meta_data.completion_info =
CompletionInfo(entry->target_file_path, entry->bytes_downloaded);
+ // If the download is completed, the |current_size| needs to pull from entry
+ // since the history db record has been deleted.
+ meta_data.current_size = entry->bytes_downloaded;
+ return meta_data;
}
+
+ auto driver_entry = driver->Find(entry->guid);
+ if (driver_entry)
+ meta_data.current_size = driver_entry->bytes_downloaded;
return meta_data;
}
diff --git a/chromium/components/download/internal/background_service/entry_utils.h b/chromium/components/download/internal/background_service/entry_utils.h
index 410383c50b6..a519d759e24 100644
--- a/chromium/components/download/internal/background_service/entry_utils.h
+++ b/chromium/components/download/internal/background_service/entry_utils.h
@@ -17,6 +17,7 @@
namespace download {
+class DownloadDriver;
struct DownloadMetaData;
struct Entry;
@@ -35,7 +36,8 @@ uint32_t GetNumberOfLiveEntriesForClient(DownloadClient client,
// not be included.
std::map<DownloadClient, std::vector<DownloadMetaData>>
MapEntriesToMetadataForClients(const std::set<DownloadClient>& clients,
- const std::vector<Entry*>& entries);
+ const std::vector<Entry*>& entries,
+ DownloadDriver* driver);
// Gets the least strict scheduling criteria from |entries|, the criteria is
// used to schedule platform background tasks.
@@ -46,8 +48,9 @@ Criteria GetSchedulingCriteria(const Model::EntryList& entries,
// |rhs| based on their priority and cancel time.
bool EntryBetterThan(const Entry& lhs, const Entry& rhs);
-// Builds a download meta data based on |entry|.
-DownloadMetaData BuildDownloadMetaData(Entry* entry);
+// Builds a download meta data based on |entry| and the states from |driver| in
+// the history db.
+DownloadMetaData BuildDownloadMetaData(Entry* entry, DownloadDriver* driver);
} // namespace util
} // namespace download
diff --git a/chromium/components/download/internal/background_service/entry_utils_unittest.cc b/chromium/components/download/internal/background_service/entry_utils_unittest.cc
index fda16a7f2a8..75f36afc8be 100644
--- a/chromium/components/download/internal/background_service/entry_utils_unittest.cc
+++ b/chromium/components/download/internal/background_service/entry_utils_unittest.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "components/download/internal/background_service/test/entry_utils.h"
+#include "components/download/internal/background_service/test/test_download_driver.h"
#include "components/download/public/background_service/clients.h"
#include "components/download/public/background_service/download_metadata.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -35,21 +36,23 @@ TEST(DownloadServiceEntryUtilsTest, MapEntriesToClients) {
Entry entry5 = test::BuildBasicEntry(Entry::State::AVAILABLE);
std::vector<Entry*> entries = {&entry1, &entry2, &entry3, &entry4, &entry5};
+ test::TestDownloadDriver driver;
std::vector<DownloadMetaData> expected_list = {
- util::BuildDownloadMetaData(&entry1),
- util::BuildDownloadMetaData(&entry2),
- util::BuildDownloadMetaData(&entry3),
- util::BuildDownloadMetaData(&entry4),
- util::BuildDownloadMetaData(&entry5)};
+ util::BuildDownloadMetaData(&entry1, &driver),
+ util::BuildDownloadMetaData(&entry2, &driver),
+ util::BuildDownloadMetaData(&entry3, &driver),
+ util::BuildDownloadMetaData(&entry4, &driver),
+ util::BuildDownloadMetaData(&entry5, &driver)};
std::vector<DownloadMetaData> expected_pruned_list = {
- util::BuildDownloadMetaData(&entry1),
- util::BuildDownloadMetaData(&entry2),
- util::BuildDownloadMetaData(&entry3),
- util::BuildDownloadMetaData(&entry5)};
+ util::BuildDownloadMetaData(&entry1, &driver),
+ util::BuildDownloadMetaData(&entry2, &driver),
+ util::BuildDownloadMetaData(&entry3, &driver),
+ util::BuildDownloadMetaData(&entry5, &driver)};
+
// If DownloadClient::TEST isn't a valid Client, all of the associated entries
// should move to the DownloadClient::INVALID bucket.
- auto mapped1 =
- util::MapEntriesToMetadataForClients(std::set<DownloadClient>(), entries);
+ auto mapped1 = util::MapEntriesToMetadataForClients(
+ std::set<DownloadClient>(), entries, &driver);
EXPECT_EQ(1U, mapped1.size());
EXPECT_NE(mapped1.end(), mapped1.find(DownloadClient::INVALID));
EXPECT_EQ(mapped1.end(), mapped1.find(DownloadClient::TEST));
@@ -62,7 +65,8 @@ TEST(DownloadServiceEntryUtilsTest, MapEntriesToClients) {
// If DownloadClient::TEST is a valid Client, it should have the associated
// entries.
std::set<DownloadClient> clients = {DownloadClient::TEST};
- auto mapped2 = util::MapEntriesToMetadataForClients(clients, entries);
+ auto mapped2 =
+ util::MapEntriesToMetadataForClients(clients, entries, &driver);
EXPECT_EQ(1U, mapped2.size());
EXPECT_NE(mapped2.end(), mapped2.find(DownloadClient::TEST));
EXPECT_EQ(mapped2.end(), mapped2.find(DownloadClient::INVALID));
@@ -136,15 +140,22 @@ TEST(DownloadServiceEntryUtilsTest, BuildDownloadMetaData) {
Entry entry = test::BuildBasicEntry(Entry::State::PAUSED);
entry.target_file_path = base::FilePath::FromUTF8Unsafe("123");
entry.bytes_downloaded = 200u;
- auto meta_data = util::BuildDownloadMetaData(&entry);
+ test::TestDownloadDriver driver;
+
+ auto meta_data = util::BuildDownloadMetaData(&entry, &driver);
EXPECT_EQ(entry.guid, meta_data.guid);
+
// Incomplete downloads don't copy the following data.
EXPECT_FALSE(meta_data.completion_info.has_value());
+ // Current size is always pulled from driver, and we don't persist the current
+ // size in each OnDownloadUpdated call in DownloadDriver.
+ EXPECT_EQ(0u, meta_data.current_size);
+
entry = test::BuildBasicEntry(Entry::State::COMPLETE);
entry.target_file_path = base::FilePath::FromUTF8Unsafe("123");
entry.bytes_downloaded = 100u;
- meta_data = util::BuildDownloadMetaData(&entry);
+ meta_data = util::BuildDownloadMetaData(&entry, &driver);
EXPECT_EQ(entry.guid, meta_data.guid);
EXPECT_TRUE(meta_data.completion_info.has_value());
EXPECT_EQ(entry.target_file_path, meta_data.completion_info->path);
@@ -152,4 +163,21 @@ TEST(DownloadServiceEntryUtilsTest, BuildDownloadMetaData) {
meta_data.completion_info->bytes_downloaded);
}
+// Test to verify the current size is correctly built into the meta data.
+TEST(DownloadServiceEntryUtilsTest, BuildDownloadMetaDataCurrentSize) {
+ Entry entry = test::BuildBasicEntry(Entry::State::PAUSED);
+ entry.target_file_path = base::FilePath::FromUTF8Unsafe("123");
+ entry.bytes_downloaded = 0u;
+
+ test::TestDownloadDriver driver;
+ DriverEntry driver_entry;
+ driver_entry.guid = entry.guid;
+ driver_entry.bytes_downloaded = 100u;
+ driver.AddTestData({driver_entry});
+
+ auto meta_data = util::BuildDownloadMetaData(&entry, &driver);
+ meta_data = util::BuildDownloadMetaData(&entry, &driver);
+ EXPECT_EQ(driver_entry.bytes_downloaded, meta_data.current_size);
+}
+
} // namespace download
diff --git a/chromium/components/download/internal/background_service/in_memory_download_driver.cc b/chromium/components/download/internal/background_service/in_memory_download_driver.cc
index 99ba0970550..50eeda0460c 100644
--- a/chromium/components/download/internal/background_service/in_memory_download_driver.cc
+++ b/chromium/components/download/internal/background_service/in_memory_download_driver.cc
@@ -131,7 +131,7 @@ base::Optional<DriverEntry> InMemoryDownloadDriver::Find(
base::Optional<DriverEntry> entry;
auto it = downloads_.find(guid);
if (it != downloads_.end())
- entry = CreateDriverEntry(*it->second.get());
+ entry = CreateDriverEntry(*it->second);
return entry;
}
diff --git a/chromium/components/download/internal/background_service/in_memory_download_driver.h b/chromium/components/download/internal/background_service/in_memory_download_driver.h
index b1594999c72..c28df4c386e 100644
--- a/chromium/components/download/internal/background_service/in_memory_download_driver.h
+++ b/chromium/components/download/internal/background_service/in_memory_download_driver.h
@@ -11,6 +11,7 @@
#include <memory>
#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
#include "components/download/internal/background_service/in_memory_download.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
diff --git a/chromium/components/download/internal/background_service/in_memory_download_unittest.cc b/chromium/components/download/internal/background_service/in_memory_download_unittest.cc
index c89ae3a0cdc..e04ec21317e 100644
--- a/chromium/components/download/internal/background_service/in_memory_download_unittest.cc
+++ b/chromium/components/download/internal/background_service/in_memory_download_unittest.cc
@@ -44,7 +44,7 @@ class MockDelegate : public InMemoryDownload::Delegate {
// InMemoryDownload::Delegate implementation.
MOCK_METHOD1(OnDownloadProgress, void(InMemoryDownload*));
- void OnDownloadComplete(InMemoryDownload* download) {
+ void OnDownloadComplete(InMemoryDownload* download) override {
if (run_loop_.running())
run_loop_.Quit();
}
diff --git a/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc b/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
index 18ab129af56..74ceabe5538 100644
--- a/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
+++ b/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
@@ -34,8 +34,7 @@ MATCHER_P(BatteryStatusEqual, value, "") {
class TestNetworkChangeNotifier : public net::NetworkChangeNotifier {
public:
TestNetworkChangeNotifier()
- : net::NetworkChangeNotifier(),
- conn_type_(ConnectionType::CONNECTION_UNKNOWN) {}
+ : conn_type_(ConnectionType::CONNECTION_UNKNOWN) {}
// net::NetworkChangeNotifier implementation.
ConnectionType GetCurrentConnectionType() const override {
@@ -129,7 +128,7 @@ class DeviceStatusListenerTest : public testing::Test {
// Simulates a network change call, the event will be sent to client
// immediately.
void ChangeNetworkTypeImmediately(ConnectionType type) {
- DCHECK(listener_.get());
+ DCHECK(listener_);
static_cast<NetworkStatusListener::Observer*>(listener_.get())
->OnNetworkChanged(type);
}
diff --git a/chromium/components/download/internal/common/BUILD.gn b/chromium/components/download/internal/common/BUILD.gn
index bb3a9299559..42ed3007fc8 100644
--- a/chromium/components/download/internal/common/BUILD.gn
+++ b/chromium/components/download/internal/common/BUILD.gn
@@ -14,7 +14,6 @@ source_set("internal") {
sources = [
"base_file.cc",
- "base_file_posix.cc",
"base_file_win.cc",
"download_create_info.cc",
"download_file_factory.cc",
@@ -35,12 +34,14 @@ source_set("internal") {
"download_utils.cc",
"download_worker.cc",
"download_worker.h",
+ "in_progress_download_manager.cc",
"parallel_download_job.cc",
"parallel_download_job.h",
"parallel_download_utils.cc",
"parallel_download_utils.h",
"rate_estimator.cc",
"resource_downloader.cc",
+ "resource_downloader.h",
"save_package_download_job.cc",
"save_package_download_job.h",
"stream_handle_input_stream.cc",
@@ -61,6 +62,10 @@ source_set("internal") {
"//services/metrics/public/cpp:ukm_builders",
"//services/network/public/cpp",
]
+
+ if (is_posix || is_fuchsia) {
+ sources += [ "base_file_posix.cc" ]
+ }
}
# tests need to access both public and internal sources. So in the component
diff --git a/chromium/components/download/internal/common/DEPS b/chromium/components/download/internal/common/DEPS
index 65c70055f64..a5df1addd5a 100644
--- a/chromium/components/download/internal/common/DEPS
+++ b/chromium/components/download/internal/common/DEPS
@@ -6,10 +6,12 @@ include_rules = [
"+components/ukm/test_ukm_recorder.h",
"+crypto",
"+mojo/public/c/system",
+ "+mojo/public/cpp/bindings",
"+net/base/filename_util.h",
"+net/base/load_flags.h",
"+net/base/io_buffer.h",
"+net/base/net_errors.h",
+ "+net/cert/cert_status_flags.h",
"+net/http/http_content_disposition.h",
"+net/http/http_request_headers.h",
"+net/http/http_response_headers.h",
@@ -18,4 +20,5 @@ include_rules = [
"+net/traffic_annotation/network_traffic_annotation.h",
"+services/metrics/public/cpp",
"+services/network/public/cpp",
+ "+services/network/public/mojom",
]
diff --git a/chromium/components/download/internal/common/base_file.cc b/chromium/components/download/internal/common/base_file.cc
index fce4f343809..03416fb14a8 100644
--- a/chromium/components/download/internal/common/base_file.cc
+++ b/chromium/components/download/internal/common/base_file.cc
@@ -13,6 +13,7 @@
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
#include "base/pickle.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
@@ -137,14 +138,6 @@ DownloadInterruptReason BaseFile::WriteDataToFile(int64_t offset,
// belong to the same download will be grouped together.
CONDITIONAL_TRACE(
NESTABLE_ASYNC_BEGIN0("download", "DownloadFileWrite", download_id_));
- int write_result = file_.Write(offset, data, data_len);
- DCHECK_NE(0, write_result);
-
- // Report errors on file writes.
- if (write_result < 0)
- return LogSystemError("Write", logging::GetLastSystemErrorCode());
-
- DCHECK_EQ(static_cast<size_t>(write_result), data_len);
if (bytes_so_far_ != offset) {
// A hole is created in the file.
@@ -152,7 +145,28 @@ DownloadInterruptReason BaseFile::WriteDataToFile(int64_t offset,
secure_hash_.reset();
}
- bytes_so_far_ += data_len;
+ // Writes to the file.
+ int64_t len = base::saturated_cast<int64_t>(data_len);
+ const char* current_data = data;
+ int64_t current_offset = offset;
+ while (len > 0) {
+ // |write_result| may be less than |len|, and return an error on the next
+ // write call when the disk is unavaliable.
+ int write_result = file_.Write(current_offset, current_data, len);
+ DCHECK_NE(0, write_result);
+
+ // Report errors on file writes.
+ if (write_result < 0)
+ return LogSystemError("Write", logging::GetLastSystemErrorCode());
+
+ // Update status.
+ DCHECK_LE(write_result, len);
+ len -= write_result;
+ current_data += write_result;
+ current_offset += write_result;
+ bytes_so_far_ += write_result;
+ }
+
CONDITIONAL_TRACE(NESTABLE_ASYNC_END1("download", "DownloadFileWrite",
download_id_, "bytes", data_len));
diff --git a/chromium/components/download/internal/common/base_file_win.cc b/chromium/components/download/internal/common/base_file_win.cc
index df78b6956d5..11796902e9a 100644
--- a/chromium/components/download/internal/common/base_file_win.cc
+++ b/chromium/components/download/internal/common/base_file_win.cc
@@ -257,25 +257,22 @@ DownloadInterruptReason MapShFileOperationCodes(int code) {
if (result == DOWNLOAD_INTERRUPT_REASON_FILE_FAILED) {
UMA_HISTOGRAM_CUSTOM_ENUMERATION(
"Download.MapWinShErrorFileFailed", code,
- base::CustomHistogram::ArrayToCustomRanges(
- kAllSpecialShFileOperationCodes,
- arraysize(kAllSpecialShFileOperationCodes)));
+ base::CustomHistogram::ArrayToCustomEnumRanges(
+ kAllSpecialShFileOperationCodes));
}
if (result == DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED) {
UMA_HISTOGRAM_CUSTOM_ENUMERATION(
"Download.MapWinShErrorAccessDenied", code,
- base::CustomHistogram::ArrayToCustomRanges(
- kAllSpecialShFileOperationCodes,
- arraysize(kAllSpecialShFileOperationCodes)));
+ base::CustomHistogram::ArrayToCustomEnumRanges(
+ kAllSpecialShFileOperationCodes));
}
if (result == DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR) {
UMA_HISTOGRAM_CUSTOM_ENUMERATION(
"Download.MapWinShErrorTransientError", code,
- base::CustomHistogram::ArrayToCustomRanges(
- kAllSpecialShFileOperationCodes,
- arraysize(kAllSpecialShFileOperationCodes)));
+ base::CustomHistogram::ArrayToCustomEnumRanges(
+ kAllSpecialShFileOperationCodes));
}
if (result != DOWNLOAD_INTERRUPT_REASON_NONE)
@@ -302,7 +299,7 @@ DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions(
source.append(1, L'\0');
target.append(1, L'\0');
- SHFILEOPSTRUCT move_info = {0};
+ SHFILEOPSTRUCT move_info = {nullptr};
move_info.wFunc = FO_MOVE;
move_info.pFrom = source.c_str();
move_info.pTo = target.c_str();
diff --git a/chromium/components/download/internal/common/download_file_impl.cc b/chromium/components/download/internal/common/download_file_impl.cc
index 7acae0764dd..05d8f7c5c19 100644
--- a/chromium/components/download/internal/common/download_file_impl.cc
+++ b/chromium/components/download/internal/common/download_file_impl.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_current.h"
#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
@@ -147,7 +147,7 @@ DownloadFileImpl::DownloadFileImpl(
bytes_seen_without_parallel_streams_(0),
is_paused_(false),
download_id_(download_id),
- main_task_runner_(base::MessageLoop::current()->task_runner()),
+ main_task_runner_(base::MessageLoopCurrent::Get()->task_runner()),
observer_(observer),
weak_factory_(this) {
TRACE_EVENT_INSTANT0("download", "DownloadFileCreated",
@@ -229,7 +229,7 @@ void DownloadFileImpl::AddInputStream(std::unique_ptr<InputStream> stream,
CancelRequest(offset);
return;
}
-
+ DCHECK(source_streams_.find(offset) == source_streams_.end());
source_streams_[offset] =
std::make_unique<SourceStream>(offset, length, std::move(stream));
OnSourceStreamAdded(source_streams_[offset].get());
@@ -504,7 +504,7 @@ void DownloadFileImpl::StreamActive(SourceStream* source_stream,
DCHECK_GE(incoming_data_size, bytes_to_write);
reason = WriteDataToFile(
source_stream->offset() + source_stream->bytes_written(),
- incoming_data.get()->data(), bytes_to_write);
+ incoming_data->data(), bytes_to_write);
disk_writes_time_ += (base::TimeTicks::Now() - write_start);
bytes_seen_ += bytes_to_write;
total_incoming_data_size += bytes_to_write;
diff --git a/chromium/components/download/internal/common/download_file_unittest.cc b/chromium/components/download/internal/common/download_file_unittest.cc
index 91c9d212691..f0f2204d6a5 100644
--- a/chromium/components/download/internal/common/download_file_unittest.cc
+++ b/chromium/components/download/internal/common/download_file_unittest.cc
@@ -201,7 +201,7 @@ class DownloadFileTest : public testing::Test {
bool calculate_hash,
const DownloadItem::ReceivedSlices& received_slices) {
// There can be only one.
- DCHECK(!download_file_.get());
+ DCHECK(!download_file_);
input_stream_ = new StrictMock<MockInputStream>();
@@ -721,8 +721,8 @@ void TestRenameCompletionCallback(const base::Closure& closure,
// succeed.
//
// Note that there is only one queue of tasks to run, and that is in the tests'
-// base::MessageLoop::current(). Each RunLoop processes that queue until it sees
-// a QuitClosure() targeted at itself, at which point it stops processing.
+// base::MessageLoopCurrent::Get(). Each RunLoop processes that queue until it
+// sees a QuitClosure() targeted at itself, at which point it stops processing.
TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) {
ASSERT_TRUE(CreateDownloadFile(0, true));
base::FilePath initial_path(download_file_->FullPath());
@@ -1042,8 +1042,8 @@ TEST_F(DownloadFileTest, SecondStreamStartingOffsetAlreadyWritten) {
.RetiresOnSaturation();
download_file_->AddInputStream(
- std::unique_ptr<MockInputStream>(additional_streams_[0]), 0,
- DownloadSaveInfo::kLengthFullContent);
+ std::unique_ptr<MockInputStream>(additional_streams_[0]),
+ strlen(kTestData1), DownloadSaveInfo::kLengthFullContent);
// The stream should get terminated and reset the callback.
EXPECT_TRUE(sink_callback_.is_null());
diff --git a/chromium/components/download/internal/common/download_item_impl.cc b/chromium/components/download/internal/common/download_item_impl.cc
index 7181a2ca5c8..817deacd108 100644
--- a/chromium/components/download/internal/common/download_item_impl.cc
+++ b/chromium/components/download/internal/common/download_item_impl.cc
@@ -147,6 +147,8 @@ std::string GetDownloadDangerNames(DownloadDangerType type) {
return "DANGEROUS_HOST";
case DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED:
return "POTENTIALLY_UNWANTED";
+ case DOWNLOAD_DANGER_TYPE_WHITELISTED_BY_POLICY:
+ return "WHITELISTED_BY_POLICY";
default:
NOTREACHED();
return "UNKNOWN_DANGER_TYPE";
@@ -418,7 +420,7 @@ DownloadItemImpl::~DownloadItemImpl() {
// Should always have been nuked before now, at worst in
// DownloadManager shutdown.
- DCHECK(!download_file_.get());
+ DCHECK(!download_file_);
CHECK(!is_updating_observers_);
for (auto& observer : observers_)
@@ -957,6 +959,11 @@ bool DownloadItemImpl::IsTransient() const {
return transient_;
}
+bool DownloadItemImpl::IsParallelDownload() const {
+ bool is_parallelizable = job_ ? job_->IsParallelizable() : false;
+ return is_parallelizable && download::IsParallelDownloadEnabled();
+}
+
void DownloadItemImpl::OnContentCheckCompleted(DownloadDangerType danger_type,
DownloadInterruptReason reason) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -1040,7 +1047,7 @@ std::string DownloadItemImpl::DebugString(bool verbose) const {
IsPaused() ? 'T' : 'F', DebugResumeModeString(GetResumeMode()),
auto_resume_count_, GetDangerType(), AllDataSaved() ? 'T' : 'F',
GetLastModifiedTime().c_str(), GetETag().c_str(),
- download_file_.get() ? "true" : "false", url_list.c_str(),
+ download_file_ ? "true" : "false", url_list.c_str(),
GetFullPath().value().c_str(), GetTargetFilePath().value().c_str(),
GetReferrerUrl().spec().c_str(), GetSiteUrl().spec().c_str());
} else {
@@ -1383,17 +1390,18 @@ void DownloadItemImpl::Start(
std::unique_ptr<DownloadFile> file,
std::unique_ptr<DownloadRequestHandleInterface> req_handle,
const DownloadCreateInfo& new_create_info,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
net::URLRequestContextGetter* url_request_context_getter) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(!download_file_.get());
+ DCHECK(!download_file_);
DVLOG(20) << __func__ << "() this=" << DebugString(true);
RecordDownloadCountWithSource(START_COUNT, download_source_);
download_file_ = std::move(file);
job_ = DownloadJobFactory::CreateJob(
this, std::move(req_handle), new_create_info, false,
- std::move(shared_url_loader_factory), url_request_context_getter);
+ std::move(url_loader_factory_getter), url_request_context_getter);
if (job_->IsParallelizable()) {
RecordParallelizableDownloadCount(START_COUNT, IsParallelDownloadEnabled());
}
@@ -1422,23 +1430,20 @@ void DownloadItemImpl::Start(
// If a resumption attempted failed, or if the download was DOA, then the
// download should go back to being interrupted.
if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) {
- DCHECK(!download_file_.get());
+ DCHECK(!download_file_);
// Download requests that are interrupted by Start() should result in a
// DownloadCreateInfo with an intact DownloadSaveInfo.
DCHECK(new_create_info.save_info);
- int64_t offset = new_create_info.save_info->offset;
std::unique_ptr<crypto::SecureHash> hash_state =
new_create_info.save_info->hash_state
? new_create_info.save_info->hash_state->Clone()
: nullptr;
- destination_info_.received_bytes = offset;
hash_state_ = std::move(hash_state);
destination_info_.hash.clear();
deferred_interrupt_reason_ = new_create_info.result;
- received_slices_.clear();
TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
DetermineDownloadTarget();
return;
@@ -1473,9 +1478,8 @@ void DownloadItemImpl::Start(
if (state_ == RESUMING_INTERNAL)
UpdateValidatorsOnResumption(new_create_info);
- // If the download is not parallel download during resumption, clear the
- // |received_slices_|.
- if (!job_->IsParallelizable() && !received_slices_.empty()) {
+ // If the download is not parallel, clear the |received_slices_|.
+ if (!received_slices_.empty() && !job_->IsParallelizable()) {
destination_info_.received_bytes =
GetMaxContiguousDataBlockSizeFromBeginning(received_slices_);
received_slices_.clear();
@@ -1715,7 +1719,7 @@ void DownloadItemImpl::OnDownloadCompleting() {
DCHECK(!GetTargetFilePath().empty());
DCHECK(!IsDangerous());
- DCHECK(download_file_.get());
+ DCHECK(download_file_);
// Unilaterally rename; even if it already has the right name,
// we need theannotation.
DownloadFile::RenameCompletionCallback callback =
@@ -1727,7 +1731,9 @@ void DownloadItemImpl::OnDownloadCompleting() {
base::Unretained(download_file_.get()),
GetTargetFilePath(),
delegate_->GetApplicationClientIdForFileScanning(),
- GetURL(), GetReferrerUrl(), std::move(callback)));
+ delegate_->IsOffTheRecord() ? GURL() : GetURL(),
+ delegate_->IsOffTheRecord() ? GURL() : GetReferrerUrl(),
+ std::move(callback)));
}
void DownloadItemImpl::OnDownloadRenamedToFinalName(
@@ -2229,7 +2235,8 @@ void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) {
if ((danger_type_ == DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
danger_type_ == DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT ||
- danger_type_ == DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT) &&
+ danger_type_ == DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT ||
+ danger_type_ == DOWNLOAD_DANGER_TYPE_WHITELISTED_BY_POLICY) &&
(danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST ||
danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
danger_type == DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
@@ -2341,6 +2348,9 @@ void DownloadItemImpl::ResumeInterruptedDownload(
for (const auto& header : request_headers_) {
download_params->add_request_header(header.first, header.second);
}
+ // The offset is calculated after decompression, so the range request cannot
+ // involve any compression,
+ download_params->add_request_header("Accept-Encoding", "identity");
auto entry = delegate_->GetInProgressEntry(this);
if (entry)
diff --git a/chromium/components/download/internal/common/download_item_impl_unittest.cc b/chromium/components/download/internal/common/download_item_impl_unittest.cc
index 8515eb822f6..1503ec33b07 100644
--- a/chromium/components/download/internal/common/download_item_impl_unittest.cc
+++ b/chromium/components/download/internal/common/download_item_impl_unittest.cc
@@ -66,7 +66,7 @@ base::HistogramBase::Sample ToHistogramSample(T t) {
class MockDelegate : public DownloadItemImplDelegate {
public:
- MockDelegate() : DownloadItemImplDelegate() { SetDefaultExpectations(); }
+ MockDelegate() { SetDefaultExpectations(); }
MOCK_METHOD2(DetermineDownloadTarget,
void(DownloadItemImpl*,
@@ -89,6 +89,7 @@ class MockDelegate : public DownloadItemImplDelegate {
MOCK_METHOD1(DownloadOpened, void(DownloadItemImpl*));
MOCK_METHOD1(DownloadRemoved, void(DownloadItemImpl*));
MOCK_CONST_METHOD1(AssertStateConsistent, void(DownloadItemImpl*));
+ MOCK_CONST_METHOD0(IsOffTheRecord, bool());
void VerifyAndClearExpectations() {
::testing::Mock::VerifyAndClearExpectations(this);
@@ -101,6 +102,7 @@ class MockDelegate : public DownloadItemImplDelegate {
EXPECT_CALL(*this, ShouldOpenFileBasedOnExtension(_))
.WillRepeatedly(Return(false));
EXPECT_CALL(*this, ShouldOpenDownload(_, _)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*this, IsOffTheRecord()).WillRepeatedly(Return(false));
}
};
@@ -2010,6 +2012,48 @@ TEST_F(DownloadItemTest, StealInterruptedNonContinuableDangerousDownload) {
EXPECT_TRUE(returned_path.empty());
}
+// Tests that for an incognito download, the target file is annotated with an
+// empty source URL.
+TEST_F(DownloadItemTest, AnnotationWithEmptyURLInIncognito) {
+ // Non-incognito case
+ DownloadItemImpl* item = CreateDownloadItem();
+ MockDownloadFile* download_file =
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ // Target file should be annotated with the source URL.
+ EXPECT_CALL(*download_file,
+ RenameAndAnnotate(_, _, create_info()->url(), _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath),
+ base::ThreadTaskRunnerHandle::Get()));
+ EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*download_file, FullPath())
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
+ EXPECT_CALL(*download_file, Detach());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, std::unique_ptr<crypto::SecureHash>());
+ task_environment_.RunUntilIdle();
+
+ // Incognito case
+ item = CreateDownloadItem();
+ download_file =
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ // Target file should be annotated with an empty URL.
+ EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, GURL(), _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath),
+ base::ThreadTaskRunnerHandle::Get()));
+ EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*mock_delegate(), IsOffTheRecord()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*download_file, FullPath())
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
+ EXPECT_CALL(*download_file, Detach());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, std::unique_ptr<crypto::SecureHash>());
+ task_environment_.RunUntilIdle();
+}
+
namespace {
// The DownloadItemDestinationUpdateRaceTest fixture (defined below) is used to
@@ -2191,8 +2235,7 @@ class DownloadItemDestinationUpdateRaceTest
public ::testing::WithParamInterface<EventList> {
public:
DownloadItemDestinationUpdateRaceTest()
- : DownloadItemTest(),
- item_(CreateDownloadItem()),
+ : item_(CreateDownloadItem()),
file_(new ::testing::StrictMock<MockDownloadFile>()),
request_handle_(new ::testing::StrictMock<MockRequestHandle>()) {
DCHECK_EQ(GetParam().size(), static_cast<unsigned>(kEventCount));
diff --git a/chromium/components/download/internal/common/download_job_factory.cc b/chromium/components/download/internal/common/download_job_factory.cc
index b2fda04191a..c9cffbebc1b 100644
--- a/chromium/components/download/internal/common/download_job_factory.cc
+++ b/chromium/components/download/internal/common/download_job_factory.cc
@@ -12,7 +12,7 @@
#include "components/download/internal/common/save_package_download_job.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_stats.h"
-#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
namespace download {
@@ -44,10 +44,12 @@ bool IsParallelizableDownload(const DownloadCreateInfo& create_info,
net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1;
bool http_get_method =
create_info.method == "GET" && create_info.url().SchemeIsHTTPOrHTTPS();
-
+ bool partial_response_success =
+ download_item->GetReceivedSlices().empty() || create_info.offset != 0;
bool is_parallelizable = has_strong_validator && create_info.accept_range &&
has_content_length && satisfy_min_file_size &&
- satisfy_connection_type && http_get_method;
+ satisfy_connection_type && http_get_method &&
+ partial_response_success;
if (!IsParallelDownloadEnabled())
return is_parallelizable;
@@ -93,7 +95,8 @@ std::unique_ptr<DownloadJob> DownloadJobFactory::CreateJob(
std::unique_ptr<DownloadRequestHandleInterface> req_handle,
const DownloadCreateInfo& create_info,
bool is_save_package_download,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
net::URLRequestContextGetter* url_request_context_getter) {
if (is_save_package_download) {
return std::make_unique<SavePackageDownloadJob>(download_item,
@@ -105,7 +108,7 @@ std::unique_ptr<DownloadJob> DownloadJobFactory::CreateJob(
if (IsParallelDownloadEnabled() && is_parallelizable) {
return std::make_unique<ParallelDownloadJob>(
download_item, std::move(req_handle), create_info,
- std::move(shared_url_loader_factory), url_request_context_getter);
+ std::move(url_loader_factory_getter), url_request_context_getter);
}
// An ordinary download job.
diff --git a/chromium/components/download/internal/common/download_stats.cc b/chromium/components/download/internal/common/download_stats.cc
index 829b99ed9d6..fb06e932988 100644
--- a/chromium/components/download/internal/common/download_stats.cc
+++ b/chromium/components/download/internal/common/download_stats.cc
@@ -377,8 +377,7 @@ void RecordDownloadInterrupted(DownloadInterruptReason reason,
}
std::vector<base::HistogramBase::Sample> samples =
- base::CustomHistogram::ArrayToCustomRanges(
- kAllInterruptReasonCodes, arraysize(kAllInterruptReasonCodes));
+ base::CustomHistogram::ArrayToCustomEnumRanges(kAllInterruptReasonCodes);
UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.InterruptedReason", reason,
samples);
diff --git a/chromium/components/download/internal/common/download_task_runner.cc b/chromium/components/download/internal/common/download_task_runner.cc
index 0cc99355e32..55db38f64b6 100644
--- a/chromium/components/download/internal/common/download_task_runner.cc
+++ b/chromium/components/download/internal/common/download_task_runner.cc
@@ -6,6 +6,7 @@
#include "base/lazy_instance.h"
#include "base/no_destructor.h"
+#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "base/task_scheduler/lazy_task_runner.h"
#include "build/build_config.h"
diff --git a/chromium/components/download/internal/common/download_utils.cc b/chromium/components/download/internal/common/download_utils.cc
index 224894906f4..cc9f500041b 100644
--- a/chromium/components/download/internal/common/download_utils.cc
+++ b/chromium/components/download/internal/common/download_utils.cc
@@ -5,6 +5,7 @@
#include "components/download/public/common/download_utils.h"
#include "base/format_macros.h"
+#include "base/rand_util.h"
#include "base/strings/stringprintf.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_interrupt_reasons_utils.h"
@@ -347,4 +348,24 @@ std::unique_ptr<net::HttpRequestHeaders> GetAdditionalRequestHeaders(
return headers;
}
+DownloadEntry CreateDownloadEntryFromItem(
+ const DownloadItem& item,
+ const std::string& request_origin,
+ DownloadSource download_source,
+ bool fetch_error_body,
+ const DownloadUrlParameters::RequestHeadersType& request_headers) {
+ return DownloadEntry(item.GetGuid(), request_origin, download_source,
+ fetch_error_body, request_headers,
+ GetUniqueDownloadId());
+}
+
+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 download
diff --git a/chromium/components/download/internal/common/download_worker.cc b/chromium/components/download/internal/common/download_worker.cc
index c05b1f8a0c2..b6f3aa58879 100644
--- a/chromium/components/download/internal/common/download_worker.cc
+++ b/chromium/components/download/internal/common/download_worker.cc
@@ -4,13 +4,13 @@
#include "components/download/internal/common/download_worker.h"
-#include "base/message_loop/message_loop.h"
+#include "components/download/internal/common/resource_downloader.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_task_runner.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/download_utils.h"
#include "components/download/public/common/input_stream.h"
-#include "components/download/public/common/resource_downloader.h"
#include "components/download/public/common/url_download_handler_factory.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -43,10 +43,11 @@ class CompletedInputStream : public InputStream {
void CreateUrlDownloadHandler(
std::unique_ptr<DownloadUrlParameters> params,
base::WeakPtr<UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
auto downloader = UrlDownloadHandlerFactory::Create(
- std::move(params), delegate, std::move(shared_url_loader_factory),
+ std::move(params), delegate, std::move(url_loader_factory_getter),
task_runner);
task_runner->PostTask(
FROM_HERE,
@@ -74,11 +75,12 @@ DownloadWorker::~DownloadWorker() = default;
void DownloadWorker::SendRequest(
std::unique_ptr<DownloadUrlParameters> params,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory) {
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter) {
GetIOTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&CreateUrlDownloadHandler, std::move(params),
weak_factory_.GetWeakPtr(),
- std::move(shared_url_loader_factory),
+ std::move(url_loader_factory_getter),
base::ThreadTaskRunnerHandle::Get()));
}
@@ -104,7 +106,8 @@ void DownloadWorker::Cancel(bool user_cancel) {
void DownloadWorker::OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> create_info,
std::unique_ptr<InputStream> input_stream,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const DownloadUrlParameters::OnStartedCallback& callback) {
// |callback| is not used in subsequent requests.
DCHECK(callback.is_null());
@@ -134,7 +137,8 @@ void DownloadWorker::OnUrlDownloadStarted(
Pause();
}
- delegate_->OnInputStreamReady(this, std::move(input_stream));
+ delegate_->OnInputStreamReady(this, std::move(input_stream),
+ std::move(create_info));
}
void DownloadWorker::OnUrlDownloadStopped(UrlDownloadHandler* downloader) {
diff --git a/chromium/components/download/internal/common/download_worker.h b/chromium/components/download/internal/common/download_worker.h
index 8996f082d12..8c712607093 100644
--- a/chromium/components/download/internal/common/download_worker.h
+++ b/chromium/components/download/internal/common/download_worker.h
@@ -14,11 +14,8 @@
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/url_download_handler.h"
-namespace network {
-class SharedURLLoaderFactory;
-}
-
namespace download {
+class DownloadURLLoaderFactoryGetter;
// Helper class used to send subsequent range requests to fetch slices of the
// file after handling response of the original non-range request.
@@ -34,7 +31,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker
// destination file.
virtual void OnInputStreamReady(
DownloadWorker* worker,
- std::unique_ptr<InputStream> input_stream) = 0;
+ std::unique_ptr<InputStream> input_stream,
+ std::unique_ptr<DownloadCreateInfo> download_create_info) = 0;
};
DownloadWorker(DownloadWorker::Delegate* delegate,
@@ -46,9 +44,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker
int64_t length() const { return length_; }
// Send network request to ask for a download.
- void SendRequest(
- std::unique_ptr<DownloadUrlParameters> params,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
+ void SendRequest(std::unique_ptr<DownloadUrlParameters> params,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter);
// Download operations.
void Pause();
@@ -60,7 +58,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker
void OnUrlDownloadStarted(
std::unique_ptr<DownloadCreateInfo> create_info,
std::unique_ptr<InputStream> input_stream,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const DownloadUrlParameters::OnStartedCallback& callback) override;
void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override;
void OnUrlDownloadHandlerCreated(
diff --git a/chromium/components/download/internal/common/in_progress_download_manager.cc b/chromium/components/download/internal/common/in_progress_download_manager.cc
new file mode 100644
index 00000000000..9ed647a5b05
--- /dev/null
+++ b/chromium/components/download/internal/common/in_progress_download_manager.cc
@@ -0,0 +1,402 @@
+// Copyright 2018 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/in_progress_download_manager.h"
+
+#include "base/optional.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/download/downloader/in_progress/in_progress_cache_impl.h"
+#include "components/download/internal/common/resource_downloader.h"
+#include "components/download/public/common/download_file.h"
+#include "components/download/public/common/download_item_impl.h"
+#include "components/download/public/common/download_stats.h"
+#include "components/download/public/common/download_task_runner.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
+#include "components/download/public/common/download_url_parameters.h"
+#include "components/download/public/common/download_utils.h"
+#include "components/download/public/common/input_stream.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/resource_response.h"
+
+namespace download {
+
+namespace {
+
+void OnUrlDownloadHandlerCreated(
+ UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader,
+ base::WeakPtr<InProgressDownloadManager> download_manager,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) {
+ main_task_runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated,
+ download_manager, std::move(downloader)));
+}
+
+void BeginResourceDownload(
+ std::unique_ptr<DownloadUrlParameters> params,
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ uint32_t download_id,
+ base::WeakPtr<InProgressDownloadManager> download_manager,
+ const GURL& site_url,
+ const GURL& tab_url,
+ const GURL& tab_referrer_url,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) {
+ DCHECK(GetIOTaskRunner()->BelongsToCurrentThread());
+ UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader(
+ ResourceDownloader::BeginDownload(
+ download_manager, std::move(params), std::move(request),
+ std::move(url_loader_factory_getter), site_url, tab_url,
+ tab_referrer_url, download_id, false, main_task_runner)
+ .release(),
+ base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
+
+ OnUrlDownloadHandlerCreated(std::move(downloader), download_manager,
+ main_task_runner);
+}
+
+void CreateDownloadHandlerForNavigation(
+ base::WeakPtr<InProgressDownloadManager> download_manager,
+ 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,
+ scoped_refptr<network::ResourceResponse> response,
+ net::CertStatus cert_status,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) {
+ DCHECK(GetIOTaskRunner()->BelongsToCurrentThread());
+ UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader(
+ ResourceDownloader::InterceptNavigationResponse(
+ download_manager, std::move(resource_request), render_process_id,
+ render_frame_id, site_url, tab_url, tab_referrer_url,
+ std::move(url_chain), std::move(response), std::move(cert_status),
+ std::move(url_loader_client_endpoints),
+ std::move(url_loader_factory_getter), main_task_runner)
+ .release(),
+ base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
+
+ OnUrlDownloadHandlerCreated(std::move(downloader), download_manager,
+ main_task_runner);
+}
+
+// Responsible for persisting the in-progress metadata associated with a
+// download.
+class InProgressDownloadObserver : public DownloadItem::Observer {
+ public:
+ explicit InProgressDownloadObserver(InProgressCache* in_progress_cache);
+ ~InProgressDownloadObserver() override;
+
+ private:
+ // DownloadItem::Observer
+ void OnDownloadUpdated(DownloadItem* download) override;
+ void OnDownloadRemoved(DownloadItem* download) override;
+
+ // The persistent cache to store in-progress metadata.
+ InProgressCache* in_progress_cache_;
+
+ DISALLOW_COPY_AND_ASSIGN(InProgressDownloadObserver);
+};
+
+InProgressDownloadObserver::InProgressDownloadObserver(
+ InProgressCache* in_progress_cache)
+ : in_progress_cache_(in_progress_cache) {}
+
+InProgressDownloadObserver::~InProgressDownloadObserver() = default;
+
+void InProgressDownloadObserver::OnDownloadUpdated(DownloadItem* download) {
+ // TODO(crbug.com/778425): Properly handle fail/resume/retry for downloads
+ // that are in the INTERRUPTED state for a long time.
+ if (!in_progress_cache_)
+ return;
+
+ switch (download->GetState()) {
+ case DownloadItem::DownloadState::COMPLETE:
+ // Intentional fallthrough.
+ case DownloadItem::DownloadState::CANCELLED:
+ if (in_progress_cache_)
+ in_progress_cache_->RemoveEntry(download->GetGuid());
+ break;
+
+ case DownloadItem::DownloadState::INTERRUPTED:
+ // Intentional fallthrough.
+ case DownloadItem::DownloadState::IN_PROGRESS: {
+ // Make sure the entry exists in the cache.
+ base::Optional<DownloadEntry> entry_opt =
+ in_progress_cache_->RetrieveEntry(download->GetGuid());
+ DownloadEntry entry;
+ if (!entry_opt.has_value()) {
+ entry = CreateDownloadEntryFromItem(
+ *download, std::string(), /* request_origin */
+ DownloadSource::UNKNOWN, false, /* fetch_error_body */
+ DownloadUrlParameters::RequestHeadersType());
+ in_progress_cache_->AddOrReplaceEntry(entry);
+ break;
+ }
+ entry = entry_opt.value();
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+void InProgressDownloadObserver::OnDownloadRemoved(DownloadItem* download) {
+ if (!in_progress_cache_)
+ return;
+
+ in_progress_cache_->RemoveEntry(download->GetGuid());
+}
+
+} // namespace
+
+InProgressDownloadManager::InProgressDownloadManager(
+ Delegate* delegate,
+ const IsOriginSecureCallback& is_origin_secure_cb)
+ : delegate_(delegate),
+ file_factory_(new DownloadFileFactory()),
+ is_origin_secure_cb_(is_origin_secure_cb),
+ weak_factory_(this) {}
+
+InProgressDownloadManager::~InProgressDownloadManager() = default;
+
+void InProgressDownloadManager::OnUrlDownloadStarted(
+ std::unique_ptr<DownloadCreateInfo> download_create_info,
+ std::unique_ptr<InputStream> input_stream,
+ scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ const DownloadUrlParameters::OnStartedCallback& callback) {
+ StartDownload(std::move(download_create_info), std::move(input_stream),
+ std::move(url_loader_factory_getter), callback);
+}
+
+void InProgressDownloadManager::OnUrlDownloadStopped(
+ UrlDownloadHandler* downloader) {
+ for (auto ptr = url_download_handlers_.begin();
+ ptr != url_download_handlers_.end(); ++ptr) {
+ if (ptr->get() == downloader) {
+ url_download_handlers_.erase(ptr);
+ return;
+ }
+ }
+}
+
+void InProgressDownloadManager::OnUrlDownloadHandlerCreated(
+ UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) {
+ if (downloader)
+ url_download_handlers_.push_back(std::move(downloader));
+}
+
+void InProgressDownloadManager::BeginDownload(
+ std::unique_ptr<DownloadUrlParameters> params,
+ scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ uint32_t download_id,
+ const GURL& site_url,
+ const GURL& tab_url,
+ const GURL& tab_referrer_url) {
+ std::unique_ptr<network::ResourceRequest> request =
+ CreateResourceRequest(params.get());
+ GetIOTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&BeginResourceDownload, std::move(params),
+ std::move(request), std::move(url_loader_factory_getter),
+ download_id, weak_factory_.GetWeakPtr(), site_url, tab_url,
+ tab_referrer_url, base::ThreadTaskRunnerHandle::Get()));
+}
+
+void InProgressDownloadManager::InterceptDownloadFromNavigation(
+ 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,
+ scoped_refptr<network::ResourceResponse> response,
+ net::CertStatus cert_status,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter) {
+ GetIOTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&CreateDownloadHandlerForNavigation,
+ weak_factory_.GetWeakPtr(), std::move(resource_request),
+ render_process_id, render_frame_id, site_url, tab_url,
+ tab_referrer_url, std::move(url_chain),
+ std::move(response), std::move(cert_status),
+ std::move(url_loader_client_endpoints),
+ std::move(url_loader_factory_getter),
+ base::ThreadTaskRunnerHandle::Get()));
+}
+
+void InProgressDownloadManager::Initialize(
+ const base::FilePath& metadata_cache_dir,
+ base::OnceClosure callback) {
+ download_metadata_cache_ = std::make_unique<InProgressCacheImpl>(
+ metadata_cache_dir.empty() ? base::FilePath() :
+ metadata_cache_dir.Append(kDownloadMetadataStoreFilename),
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}));
+
+ download_metadata_cache_->Initialize(std::move(callback));
+}
+
+void InProgressDownloadManager::ShutDown() {
+ url_download_handlers_.clear();
+}
+
+void InProgressDownloadManager::ResumeInterruptedDownload(
+ std::unique_ptr<DownloadUrlParameters> params,
+ uint32_t id,
+ const GURL& site_url) {}
+
+base::Optional<DownloadEntry> InProgressDownloadManager::GetInProgressEntry(
+ DownloadItemImpl* download) {
+ if (!download || !download_metadata_cache_)
+ return base::Optional<DownloadEntry>();
+
+ return download_metadata_cache_->RetrieveEntry(download->GetGuid());
+}
+
+void InProgressDownloadManager::ReportBytesWasted(DownloadItemImpl* download) {
+ if (!download_metadata_cache_)
+ return;
+ base::Optional<DownloadEntry> entry_opt =
+ download_metadata_cache_->RetrieveEntry(download->GetGuid());
+ if (entry_opt.has_value()) {
+ DownloadEntry entry = entry_opt.value();
+ entry.bytes_wasted = download->GetBytesWasted();
+ download_metadata_cache_->AddOrReplaceEntry(entry);
+ }
+}
+
+void InProgressDownloadManager::StartDownload(
+ std::unique_ptr<DownloadCreateInfo> info,
+ std::unique_ptr<InputStream> stream,
+ scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ const DownloadUrlParameters::OnStartedCallback& on_started) {
+ DCHECK(info);
+
+ uint32_t download_id = info->download_id;
+ bool new_download = (download_id == DownloadItem::kInvalidId);
+ if (new_download && info->result == DOWNLOAD_INTERRUPT_REASON_NONE) {
+ if (delegate_ && delegate_->InterceptDownload(*info)) {
+ GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, stream.release());
+ return;
+ }
+ }
+
+ // |stream| is only non-null if the download request was successful.
+ DCHECK(
+ (info->result == DOWNLOAD_INTERRUPT_REASON_NONE && !stream->IsEmpty()) ||
+ (info->result != DOWNLOAD_INTERRUPT_REASON_NONE && stream->IsEmpty()));
+ DVLOG(20) << __func__
+ << "() result=" << DownloadInterruptReasonToString(info->result);
+
+ GURL url = info->url();
+ std::vector<GURL> url_chain = info->url_chain;
+ std::string mime_type = info->mime_type;
+
+ if (new_download) {
+ RecordDownloadConnectionSecurity(info->url(), info->url_chain);
+ RecordDownloadContentTypeSecurity(info->url(), info->url_chain,
+ info->mime_type, is_origin_secure_cb_);
+ }
+
+ base::RepeatingCallback<void(uint32_t)> got_id(base::BindRepeating(
+ &InProgressDownloadManager::StartDownloadWithId,
+ weak_factory_.GetWeakPtr(), base::Passed(&info), base::Passed(&stream),
+ std::move(url_loader_factory_getter), on_started, new_download));
+ if (new_download) {
+ // TODO(qinmin): use GUID as the key for downloads history table so we don't
+ // rely on the delegate to provide the next download ID.
+ if (delegate_)
+ delegate_->GetNextId(std::move(got_id));
+ } else {
+ std::move(got_id).Run(download_id);
+ }
+}
+
+void InProgressDownloadManager::StartDownloadWithId(
+ std::unique_ptr<DownloadCreateInfo> info,
+ std::unique_ptr<InputStream> stream,
+ scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
+ const DownloadUrlParameters::OnStartedCallback& on_started,
+ bool new_download,
+ uint32_t id) {
+ DCHECK_NE(DownloadItem::kInvalidId, id);
+ DownloadItemImpl* download =
+ delegate_ ? delegate_->GetDownloadItem(id, new_download, *info) : nullptr;
+
+ if (!download) {
+ // If the download is no longer known to the DownloadManager, then it was
+ // removed after it was resumed. Ignore. If the download is cancelled
+ // while resuming, then also ignore the request.
+ if (info->request_handle)
+ info->request_handle->CancelRequest(true);
+ if (!on_started.is_null())
+ on_started.Run(nullptr, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
+ // The ByteStreamReader lives and dies on the download sequence.
+ if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE)
+ GetDownloadTaskRunner()->DeleteSoon(FROM_HERE, stream.release());
+ return;
+ }
+
+ base::FilePath default_download_directory;
+ if (delegate_)
+ default_download_directory = delegate_->GetDefaultDownloadDirectory();
+
+ if (download_metadata_cache_) {
+ base::Optional<DownloadEntry> entry_opt =
+ download_metadata_cache_->RetrieveEntry(download->GetGuid());
+ if (!entry_opt.has_value()) {
+ download_metadata_cache_->AddOrReplaceEntry(CreateDownloadEntryFromItem(
+ *download, info->request_origin, info->download_source,
+ info->fetch_error_body, info->request_headers));
+ }
+ }
+
+ if (!in_progress_download_observer_) {
+ in_progress_download_observer_ =
+ std::make_unique<InProgressDownloadObserver>(
+ download_metadata_cache_.get());
+ }
+ // May already observe this item, remove observer first.
+ download->RemoveObserver(in_progress_download_observer_.get());
+ download->AddObserver(in_progress_download_observer_.get());
+
+ std::unique_ptr<DownloadFile> download_file;
+ if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE) {
+ DCHECK(stream);
+ download_file.reset(file_factory_->CreateFile(
+ std::move(info->save_info), default_download_directory,
+ std::move(stream), id, download->DestinationObserverAsWeakPtr()));
+ }
+ // It is important to leave info->save_info intact in the case of an interrupt
+ // so that the DownloadItem can salvage what it can out of a failed
+ // resumption attempt.
+
+ download->Start(
+ std::move(download_file), std::move(info->request_handle), *info,
+ std::move(url_loader_factory_getter),
+ delegate_ ? delegate_->GetURLRequestContextGetter(*info) : nullptr);
+
+ // For interrupted downloads, Start() will transition the state to
+ // IN_PROGRESS and consumers will be notified via OnDownloadUpdated().
+ // For new downloads, we notify here, rather than earlier, so that
+ // the download_file is bound to download and all the usual
+ // setters (e.g. Cancel) work.
+ if (new_download && delegate_)
+ delegate_->OnNewDownloadStarted(download);
+
+ if (!on_started.is_null())
+ on_started.Run(download, DOWNLOAD_INTERRUPT_REASON_NONE);
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/parallel_download_job.cc b/chromium/components/download/internal/common/parallel_download_job.cc
index e139a42c314..e72f9af89c0 100644
--- a/chromium/components/download/internal/common/parallel_download_job.cc
+++ b/chromium/components/download/internal/common/parallel_download_job.cc
@@ -12,6 +12,7 @@
#include "components/download/internal/common/parallel_download_utils.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_stats.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
namespace download {
@@ -23,7 +24,8 @@ ParallelDownloadJob::ParallelDownloadJob(
DownloadItem* download_item,
std::unique_ptr<DownloadRequestHandleInterface> request_handle,
const DownloadCreateInfo& create_info,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
net::URLRequestContextGetter* url_request_context_getter)
: DownloadJobImpl(download_item, std::move(request_handle), true),
initial_request_offset_(create_info.offset),
@@ -31,7 +33,7 @@ ParallelDownloadJob::ParallelDownloadJob(
content_length_(create_info.total_bytes),
requests_sent_(false),
is_canceled_(false),
- shared_url_loader_factory_(std::move(shared_url_loader_factory)),
+ url_loader_factory_getter_(std::move(url_loader_factory_getter)),
url_request_context_getter_(url_request_context_getter) {}
ParallelDownloadJob::~ParallelDownloadJob() = default;
@@ -121,9 +123,14 @@ void ParallelDownloadJob::BuildParallelRequestAfterDelay() {
void ParallelDownloadJob::OnInputStreamReady(
DownloadWorker* worker,
- std::unique_ptr<InputStream> input_stream) {
- bool success = DownloadJob::AddInputStream(
- std::move(input_stream), worker->offset(), worker->length());
+ std::unique_ptr<InputStream> input_stream,
+ std::unique_ptr<DownloadCreateInfo> download_create_info) {
+ // If server returns a wrong range, abort the parallel request.
+ bool success = download_create_info->offset == worker->offset();
+ if (success) {
+ success = DownloadJob::AddInputStream(std::move(input_stream),
+ worker->offset(), worker->length());
+ }
RecordParallelDownloadAddStreamSuccess(success);
// Destroy the request if the sink is gone.
@@ -286,7 +293,7 @@ void ParallelDownloadJob::CreateRequest(int64_t offset, int64_t length) {
download_params->set_referrer_policy(net::URLRequest::NEVER_CLEAR_REFERRER);
// Send the request.
- worker->SendRequest(std::move(download_params), shared_url_loader_factory_);
+ worker->SendRequest(std::move(download_params), url_loader_factory_getter_);
DCHECK(workers_.find(offset) == workers_.end());
workers_[offset] = std::move(worker);
}
diff --git a/chromium/components/download/internal/common/parallel_download_job.h b/chromium/components/download/internal/common/parallel_download_job.h
index c37fb07eb96..a6803e22ee4 100644
--- a/chromium/components/download/internal/common/parallel_download_job.h
+++ b/chromium/components/download/internal/common/parallel_download_job.h
@@ -35,7 +35,8 @@ class COMPONENTS_DOWNLOAD_EXPORT ParallelDownloadJob
DownloadItem* download_item,
std::unique_ptr<DownloadRequestHandleInterface> request_handle,
const DownloadCreateInfo& create_info,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
net::URLRequestContextGetter* url_request_context_getter);
~ParallelDownloadJob() override;
@@ -67,8 +68,10 @@ class COMPONENTS_DOWNLOAD_EXPORT ParallelDownloadJob
friend class ParallelDownloadJobTest;
// DownloadWorker::Delegate implementation.
- void OnInputStreamReady(DownloadWorker* worker,
- std::unique_ptr<InputStream> input_stream) override;
+ void OnInputStreamReady(
+ DownloadWorker* worker,
+ std::unique_ptr<InputStream> input_stream,
+ std::unique_ptr<DownloadCreateInfo> download_create_info) override;
// Build parallel requests after a delay, to effectively measure the single
// stream bandwidth.
@@ -110,8 +113,9 @@ class COMPONENTS_DOWNLOAD_EXPORT ParallelDownloadJob
// If the download progress is canceled.
bool is_canceled_;
- // SharedURLLoaderFactory to issue network requests with network service
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
+ // URLLoaderFactory getter to issue network requests with network service
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter_;
// URLRequestContextGetter for issueing network requests when network service
// is disabled.
diff --git a/chromium/components/download/internal/common/parallel_download_job_unittest.cc b/chromium/components/download/internal/common/parallel_download_job_unittest.cc
index eb09f931707..61761c49fb4 100644
--- a/chromium/components/download/internal/common/parallel_download_job_unittest.cc
+++ b/chromium/components/download/internal/common/parallel_download_job_unittest.cc
@@ -94,8 +94,10 @@ class ParallelDownloadJobForTest : public ParallelDownloadJob {
return min_remaining_time_;
}
- void OnInputStreamReady(DownloadWorker* worker,
- std::unique_ptr<InputStream> input_stream) override {
+ void OnInputStreamReady(
+ DownloadWorker* worker,
+ std::unique_ptr<InputStream> input_stream,
+ std::unique_ptr<DownloadCreateInfo> download_create_info) override {
CountOnInputStreamReady();
}
@@ -429,7 +431,7 @@ TEST_F(ParallelDownloadJobTest, EarlyCancelBeforeByteStreamReady) {
for (auto& worker : job_->workers()) {
std::unique_ptr<MockDownloadRequestHandle> mock_handle =
std::make_unique<MockDownloadRequestHandle>();
- EXPECT_CALL(*mock_handle.get(), CancelRequest(_));
+ EXPECT_CALL(*mock_handle, CancelRequest(_));
MakeWorkerReady(worker.second.get(), std::move(mock_handle));
}
@@ -451,10 +453,10 @@ TEST_F(ParallelDownloadJobTest, EarlyPauseBeforeByteStreamReady) {
EXPECT_TRUE(job_->is_paused());
for (auto& worker : job_->workers()) {
- EXPECT_CALL(*job_.get(), CountOnInputStreamReady());
+ EXPECT_CALL(*job_, CountOnInputStreamReady());
std::unique_ptr<MockDownloadRequestHandle> mock_handle =
std::make_unique<MockDownloadRequestHandle>();
- EXPECT_CALL(*mock_handle.get(), PauseRequest());
+ EXPECT_CALL(*mock_handle, PauseRequest());
MakeWorkerReady(worker.second.get(), std::move(mock_handle));
}
@@ -517,7 +519,7 @@ TEST_F(ParallelDownloadJobTest, InterruptOnStartup) {
job_->MakeFileInitialized(callback.Get(), DOWNLOAD_INTERRUPT_REASON_NONE);
// Simulate and inject an error from IO thread after file initialized.
- EXPECT_CALL(*download_item_.get(), GetState())
+ EXPECT_CALL(*download_item_, GetState())
.WillRepeatedly(Return(DownloadItem::DownloadState::INTERRUPTED));
// Because of the error, no parallel requests are built.
diff --git a/chromium/components/download/internal/common/resource_downloader.cc b/chromium/components/download/internal/common/resource_downloader.cc
index ab961f310e3..988cf5cef88 100644
--- a/chromium/components/download/internal/common/resource_downloader.cc
+++ b/chromium/components/download/internal/common/resource_downloader.cc
@@ -2,11 +2,11 @@
// 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 "components/download/internal/common/resource_downloader.h"
#include <memory>
-#include "base/strings/utf_string_conversions.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/stream_handle_input_stream.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -60,7 +60,8 @@ 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,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
@@ -71,7 +72,7 @@ std::unique_ptr<ResourceDownloader> ResourceDownloader::BeginDownload(
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));
+ std::move(url_loader_factory_getter));
downloader->Start(std::move(params), is_parallel_request);
return downloader;
@@ -88,18 +89,18 @@ ResourceDownloader::InterceptNavigationResponse(
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,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
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));
+ task_runner, std::move(url_loader_factory_getter));
downloader->InterceptResponse(std::move(response), std::move(url_chain),
- suggested_filename, cert_status,
+ cert_status,
std::move(url_loader_client_endpoints));
return downloader;
}
@@ -114,7 +115,8 @@ ResourceDownloader::ResourceDownloader(
const GURL& tab_referrer_url,
uint32_t download_id,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory)
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter)
: delegate_(delegate),
resource_request_(std::move(resource_request)),
download_id_(download_id),
@@ -124,7 +126,7 @@ ResourceDownloader::ResourceDownloader(
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)),
+ url_loader_factory_getter_(std::move(url_loader_factory_getter)),
weak_ptr_factory_(this) {}
ResourceDownloader::~ResourceDownloader() = default;
@@ -154,7 +156,7 @@ void ResourceDownloader::Start(
// Set up the URLLoader
network::mojom::URLLoaderRequest url_loader_request =
mojo::MakeRequest(&url_loader_);
- shared_url_loader_factory_->CreateLoaderAndStart(
+ url_loader_factory_getter_->GetURLLoaderFactory()->CreateLoaderAndStart(
std::move(url_loader_request),
0, // routing_id
0, // request_id
@@ -169,18 +171,14 @@ void ResourceDownloader::Start(
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),
+ resource_request_.get(), this, std::make_unique<DownloadSaveInfo>(),
false, /* is_parallel_request */
false, /* is_transient */
false, /* fetch_error_body */
@@ -216,11 +214,11 @@ void ResourceDownloader::OnResponseStarted(
&UrlDownloadHandler::Delegate::OnUrlDownloadStarted, delegate_,
std::move(download_create_info),
std::make_unique<StreamHandleInputStream>(std::move(stream_handle)),
- std::move(shared_url_loader_factory_), callback_));
+ std::move(url_loader_factory_getter_), callback_));
}
void ResourceDownloader::OnReceiveRedirect() {
- url_loader_->FollowRedirect();
+ url_loader_->FollowRedirect(base::nullopt);
}
} // namespace download
diff --git a/chromium/components/download/internal/common/resource_downloader.h b/chromium/components/download/internal/common/resource_downloader.h
new file mode 100644
index 00000000000..ce6eef63834
--- /dev/null
+++ b/chromium/components/download/internal/common/resource_downloader.h
@@ -0,0 +1,145 @@
+// 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.
+
+#ifndef COMPONENTS_DOWNLOAD_INTERNAL_COMMON_RESOURCE_DOWNLOADER_H_
+#define COMPONENTS_DOWNLOAD_INTERNAL_COMMON_RESOURCE_DOWNLOADER_H_
+
+#include "components/download/public/common/download_export.h"
+#include "components/download/public/common/download_response_handler.h"
+#include "components/download/public/common/url_download_handler.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "net/cert/cert_status_flags.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+
+namespace download {
+class DownloadURLLoaderFactoryGetter;
+
+// Class for handing the download of a url.
+class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
+ : public download::UrlDownloadHandler,
+ public download::DownloadResponseHandler::Delegate {
+ public:
+ // Called to start a download, must be called on IO thread.
+ static std::unique_ptr<ResourceDownloader> BeginDownload(
+ base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
+ std::unique_ptr<download::DownloadUrlParameters> download_url_parameters,
+ std::unique_ptr<network::ResourceRequest> request,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
+ 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);
+
+ // Create a ResourceDownloader from a navigation that turns to be a download.
+ // No URLLoader is created, but the URLLoaderClient implementation is
+ // transferred.
+ static std::unique_ptr<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 scoped_refptr<network::ResourceResponse>& response,
+ net::CertStatus cert_status,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
+
+ 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<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter);
+ ~ResourceDownloader() override;
+
+ // download::DownloadResponseHandler::Delegate
+ void OnResponseStarted(
+ std::unique_ptr<download::DownloadCreateInfo> download_create_info,
+ download::mojom::DownloadStreamHandlePtr stream_handle) override;
+ void OnReceiveRedirect() override;
+
+ private:
+ // Helper method to start the network request.
+ void Start(
+ std::unique_ptr<download::DownloadUrlParameters> download_url_parameters,
+ bool is_parallel_request);
+
+ // Intercepts the navigation response.
+ void InterceptResponse(
+ const scoped_refptr<network::ResourceResponse>& response,
+ std::vector<GURL> url_chain,
+ net::CertStatus cert_status,
+ network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints);
+
+ base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate_;
+
+ // The ResourceRequest for this object.
+ std::unique_ptr<network::ResourceRequest> resource_request_;
+
+ // Object that will handle the response.
+ std::unique_ptr<network::mojom::URLLoaderClient> url_loader_client_;
+
+ // URLLoaderClient binding. It sends any requests to the |url_loader_client_|.
+ std::unique_ptr<mojo::Binding<network::mojom::URLLoaderClient>>
+ url_loader_client_binding_;
+
+ // URLLoader for sending out the request.
+ network::mojom::URLLoaderPtr url_loader_;
+
+ // ID of the download, or download::DownloadItem::kInvalidId if this is a new
+ // download.
+ uint32_t download_id_;
+
+ // GUID of the download, or empty if this is a new download.
+ std::string guid_;
+
+ // Callback to run after download starts.
+ download::DownloadUrlParameters::OnStartedCallback callback_;
+
+ // Frame and process id associated with the request.
+ int render_process_id_;
+ int render_frame_id_;
+
+ // Site URL for the site instance that initiated the download.
+ GURL site_url_;
+
+ // The URL of the tab that started us.
+ GURL tab_url_;
+
+ // The referrer URL of the tab that started us.
+ GURL tab_referrer_url_;
+
+ // URLLoader status when intercepting the navigation request.
+ base::Optional<network::URLLoaderCompletionStatus> url_loader_status_;
+
+ // TaskRunner to post callbacks to the |delegate_|
+ scoped_refptr<base::SingleThreadTaskRunner> delegate_task_runner_;
+
+ // URLLoaderFactory getter for issueing network requests.
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter_;
+
+ base::WeakPtrFactory<ResourceDownloader> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceDownloader);
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_INTERNAL_COMMON_RESOURCE_DOWNLOADER_H_
diff --git a/chromium/components/download/internal/common/url_download_handler_factory.cc b/chromium/components/download/internal/common/url_download_handler_factory.cc
index fec5bf41cd0..625f6da4ffd 100644
--- a/chromium/components/download/internal/common/url_download_handler_factory.cc
+++ b/chromium/components/download/internal/common/url_download_handler_factory.cc
@@ -6,9 +6,10 @@
#include "base/no_destructor.h"
#include "base/synchronization/lock.h"
+#include "components/download/internal/common/resource_downloader.h"
#include "components/download/public/common/download_item.h"
+#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/download_utils.h"
-#include "components/download/public/common/resource_downloader.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace download {
@@ -25,14 +26,15 @@ class DefaultUrlDownloadHandlerFactory : public UrlDownloadHandlerFactory {
UrlDownloadHandler::UniqueUrlDownloadHandlerPtr CreateUrlDownloadHandler(
std::unique_ptr<download::DownloadUrlParameters> params,
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override {
std::unique_ptr<network::ResourceRequest> request =
CreateResourceRequest(params.get());
return UrlDownloadHandler::UniqueUrlDownloadHandlerPtr(
download::ResourceDownloader::BeginDownload(
delegate, std::move(params), std::move(request),
- std::move(shared_url_loader_factory), GURL(), GURL(), GURL(),
+ std::move(url_loader_factory_getter), GURL(), GURL(), GURL(),
download::DownloadItem::kInvalidId, true, task_runner)
.release(),
base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
@@ -57,13 +59,14 @@ UrlDownloadHandler::UniqueUrlDownloadHandlerPtr
UrlDownloadHandlerFactory::Create(
std::unique_ptr<download::DownloadUrlParameters> params,
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate,
- scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
+ scoped_refptr<download::DownloadURLLoaderFactoryGetter>
+ url_loader_factory_getter,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
base::AutoLock auto_lock(GetURLDownloadHandlerFactoryLock());
if (!g_url_download_handler_factory)
g_url_download_handler_factory = new DefaultUrlDownloadHandlerFactory();
return g_url_download_handler_factory->CreateUrlDownloadHandler(
- std::move(params), delegate, std::move(shared_url_loader_factory),
+ std::move(params), delegate, std::move(url_loader_factory_getter),
task_runner);
}