summaryrefslogtreecommitdiff
path: root/chromium/components/download
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-07-31 15:50:41 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:35:23 +0000
commit7b2ffa587235a47d4094787d72f38102089f402a (patch)
tree30e82af9cbab08a7fa028bb18f4f2987a3f74dfa /chromium/components/download
parentd94af01c90575348c4e81a418257f254b6f8d225 (diff)
downloadqtwebengine-chromium-7b2ffa587235a47d4094787d72f38102089f402a.tar.gz
BASELINE: Update Chromium to 76.0.3809.94
Change-Id: I321c3f5f929c105aec0f98c5091ef6108822e647 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/download')
-rw-r--r--chromium/components/download/BUILD.gn1
-rw-r--r--chromium/components/download/content/DEPS1
-rw-r--r--chromium/components/download/content/factory/download_service_factory_helper.cc24
-rw-r--r--chromium/components/download/content/factory/download_service_factory_helper.h15
-rw-r--r--chromium/components/download/content/internal/download_driver_impl.cc100
-rw-r--r--chromium/components/download/content/internal/download_driver_impl.h33
-rw-r--r--chromium/components/download/content/internal/download_driver_impl_unittest.cc63
-rw-r--r--chromium/components/download/internal/background_service/controller_impl.cc17
-rw-r--r--chromium/components/download/internal/background_service/controller_impl_unittest.cc29
-rw-r--r--chromium/components/download/internal/background_service/debugging_client.cc6
-rw-r--r--chromium/components/download/internal/background_service/debugging_client.h2
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download.cc29
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download.h25
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver.cc19
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver.h11
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc17
-rw-r--r--chromium/components/download/internal/background_service/in_memory_download_unittest.cc33
-rw-r--r--chromium/components/download/internal/background_service/proto/request.proto1
-rw-r--r--chromium/components/download/internal/background_service/proto_conversions.cc4
-rw-r--r--chromium/components/download/internal/background_service/proto_conversions_unittest.cc2
-rw-r--r--chromium/components/download/internal/background_service/stats.cc19
-rw-r--r--chromium/components/download/internal/background_service/stats.h8
-rw-r--r--chromium/components/download/internal/common/BUILD.gn3
-rw-r--r--chromium/components/download/internal/common/DEPS2
-rw-r--r--chromium/components/download/internal/common/all_download_event_notifier_unittest.cc149
-rw-r--r--chromium/components/download/internal/common/android/download_collection_bridge.cc20
-rw-r--r--chromium/components/download/internal/common/android/download_collection_bridge.h4
-rw-r--r--chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java19
-rw-r--r--chromium/components/download/internal/common/base_file.cc24
-rw-r--r--chromium/components/download/internal/common/base_file_unittest.cc21
-rw-r--r--chromium/components/download/internal/common/download_file_impl.cc218
-rw-r--r--chromium/components/download/internal/common/download_file_unittest.cc120
-rw-r--r--chromium/components/download/internal/common/download_item_impl.cc70
-rw-r--r--chromium/components/download/internal/common/download_item_impl_delegate.cc5
-rw-r--r--chromium/components/download/internal/common/download_item_impl_unittest.cc11
-rw-r--r--chromium/components/download/internal/common/download_job_factory.cc6
-rw-r--r--chromium/components/download/internal/common/download_path_reservation_tracker.cc32
-rw-r--r--chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc46
-rw-r--r--chromium/components/download/internal/common/download_response_handler.cc17
-rw-r--r--chromium/components/download/internal/common/download_stats.cc58
-rw-r--r--chromium/components/download/internal/common/download_utils.cc32
-rw-r--r--chromium/components/download/internal/common/download_worker.cc9
-rw-r--r--chromium/components/download/internal/common/download_worker.h9
-rw-r--r--chromium/components/download/internal/common/in_progress_download_manager.cc119
-rw-r--r--chromium/components/download/internal/common/parallel_download_job.cc8
-rw-r--r--chromium/components/download/internal/common/parallel_download_job.h12
-rw-r--r--chromium/components/download/internal/common/parallel_download_job_unittest.cc7
-rw-r--r--chromium/components/download/internal/common/parallel_download_utils.cc2
-rw-r--r--chromium/components/download/internal/common/parallel_download_utils_unittest.cc29
-rw-r--r--chromium/components/download/internal/common/resource_downloader.cc37
-rw-r--r--chromium/components/download/internal/common/resource_downloader.h18
-rw-r--r--chromium/components/download/internal/common/simple_download_manager.cc20
-rw-r--r--chromium/components/download/internal/common/simple_download_manager_coordinator.cc47
-rw-r--r--chromium/components/download/internal/common/url_download_handler_factory.cc7
-rw-r--r--chromium/components/download/public/background_service/BUILD.gn2
-rw-r--r--chromium/components/download/public/background_service/blob_context_getter_factory.h41
-rw-r--r--chromium/components/download/public/background_service/client.cc22
-rw-r--r--chromium/components/download/public/background_service/client.h26
-rw-r--r--chromium/components/download/public/background_service/download_params.cc3
-rw-r--r--chromium/components/download/public/background_service/download_params.h3
-rw-r--r--chromium/components/download/public/common/BUILD.gn2
-rw-r--r--chromium/components/download/public/common/all_download_event_notifier.h3
-rw-r--r--chromium/components/download/public/common/base_file.h4
-rw-r--r--chromium/components/download/public/common/download_create_info.h4
-rw-r--r--chromium/components/download/public/common/download_features.cc11
-rw-r--r--chromium/components/download/public/common/download_features.h12
-rw-r--r--chromium/components/download/public/common/download_file.h3
-rw-r--r--chromium/components/download/public/common/download_file_impl.h65
-rw-r--r--chromium/components/download/public/common/download_item.h5
-rw-r--r--chromium/components/download/public/common/download_item_factory.h3
-rw-r--r--chromium/components/download/public/common/download_item_impl.h14
-rw-r--r--chromium/components/download/public/common/download_item_impl_delegate.h7
-rw-r--r--chromium/components/download/public/common/download_job_factory.h9
-rw-r--r--chromium/components/download/public/common/download_path_reservation_tracker.h8
-rw-r--r--chromium/components/download/public/common/download_response_handler.h6
-rw-r--r--chromium/components/download/public/common/download_save_info.cc4
-rw-r--r--chromium/components/download/public/common/download_save_info.h13
-rw-r--r--chromium/components/download/public/common/download_stats.h44
-rw-r--r--chromium/components/download/public/common/download_url_parameters.h6
-rw-r--r--chromium/components/download/public/common/download_utils.h9
-rw-r--r--chromium/components/download/public/common/in_progress_download_manager.h48
-rw-r--r--chromium/components/download/public/common/mock_download_file.h1
-rw-r--r--chromium/components/download/public/common/mock_download_item.h3
-rw-r--r--chromium/components/download/public/common/mock_download_item_impl.cc1
-rw-r--r--chromium/components/download/public/common/mock_download_item_impl.h3
-rw-r--r--chromium/components/download/public/common/mock_simple_download_manager.cc22
-rw-r--r--chromium/components/download/public/common/mock_simple_download_manager.h44
-rw-r--r--chromium/components/download/public/common/simple_download_manager.h16
-rw-r--r--chromium/components/download/public/common/simple_download_manager_coordinator.h22
-rw-r--r--chromium/components/download/public/common/url_download_handler_factory.h8
-rw-r--r--chromium/components/download/quarantine/BUILD.gn102
-rw-r--r--chromium/components/download/quarantine/DEPS2
-rw-r--r--chromium/components/download/quarantine/common_mac.h24
-rw-r--r--chromium/components/download/quarantine/common_mac.mm56
-rw-r--r--chromium/components/download/quarantine/common_win.cc13
-rw-r--r--chromium/components/download/quarantine/common_win.h16
-rw-r--r--chromium/components/download/quarantine/quarantine.cc9
-rw-r--r--chromium/components/download/quarantine/quarantine.h61
-rw-r--r--chromium/components/download/quarantine/quarantine_features_win.cc15
-rw-r--r--chromium/components/download/quarantine/quarantine_features_win.h16
-rw-r--r--chromium/components/download/quarantine/quarantine_mac.mm211
-rw-r--r--chromium/components/download/quarantine/quarantine_mac_unittest.mm129
-rw-r--r--chromium/components/download/quarantine/quarantine_unittest.cc58
-rw-r--r--chromium/components/download/quarantine/quarantine_win.cc279
-rw-r--r--chromium/components/download/quarantine/quarantine_win_unittest.cc407
-rw-r--r--chromium/components/download/quarantine/test_support.cc21
-rw-r--r--chromium/components/download/quarantine/test_support.h44
-rw-r--r--chromium/components/download/quarantine/test_support_mac.mm52
-rw-r--r--chromium/components/download/quarantine/test_support_win.cc61
109 files changed, 1636 insertions, 2077 deletions
diff --git a/chromium/components/download/BUILD.gn b/chromium/components/download/BUILD.gn
index 5e81255abf2..a9b5439e99d 100644
--- a/chromium/components/download/BUILD.gn
+++ b/chromium/components/download/BUILD.gn
@@ -14,7 +14,6 @@ group("unit_tests") {
"//components/download/internal/common:unit_tests",
"//components/download/public/common:unit_tests",
"//components/download/public/task:unit_tests",
- "//components/download/quarantine:unit_tests",
]
}
diff --git a/chromium/components/download/content/DEPS b/chromium/components/download/content/DEPS
index 98f5933ddb9..aea8a9407dc 100644
--- a/chromium/components/download/content/DEPS
+++ b/chromium/components/download/content/DEPS
@@ -5,4 +5,5 @@ include_rules = [
"+content/public/test",
"+base",
"+net",
+ "+services/network/public/cpp/shared_url_loader_factory.h",
]
diff --git a/chromium/components/download/content/factory/download_service_factory_helper.cc b/chromium/components/download/content/factory/download_service_factory_helper.cc
index 720653b3d2c..3bd089b9563 100644
--- a/chromium/components/download/content/factory/download_service_factory_helper.cc
+++ b/chromium/components/download/content/factory/download_service_factory_helper.cc
@@ -4,6 +4,8 @@
#include "components/download/content/factory/download_service_factory_helper.h"
+#include <utility>
+
#include "base/files/file_path.h"
#include "build/build_config.h"
#include "components/download/content/factory/navigation_monitor_factory.h"
@@ -25,6 +27,7 @@
#include "components/download/public/task/empty_task_scheduler.h"
#include "components/leveldb_proto/content/proto_database_provider_factory.h"
#include "components/leveldb_proto/public/proto_database_provider.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#if defined(OS_ANDROID)
#include "components/download/internal/background_service/android/battery_status_listener_android.h"
@@ -46,7 +49,7 @@ const base::FilePath::CharType kFilesStorageDir[] = FILE_PATH_LITERAL("Files");
// Helper function to create download service with different implementation
// details.
-DownloadService* CreateDownloadServiceInternal(
+std::unique_ptr<DownloadService> CreateDownloadServiceInternal(
SimpleFactoryKey* simple_factory_key,
std::unique_ptr<DownloadClientMap> clients,
std::unique_ptr<Configuration> config,
@@ -89,15 +92,13 @@ DownloadService* CreateDownloadServiceInternal(
files_storage_dir);
logger->SetLogSource(controller.get());
- return new DownloadServiceImpl(std::move(config), std::move(logger),
- std::move(controller));
+ return std::make_unique<DownloadServiceImpl>(
+ std::move(config), std::move(logger), std::move(controller));
}
// Create download service for normal profile.
-DownloadService* BuildDownloadService(
- content::BrowserContext* browser_context,
+std::unique_ptr<DownloadService> BuildDownloadService(
SimpleFactoryKey* simple_factory_key,
- PrefService* prefs,
std::unique_ptr<DownloadClientMap> clients,
network::NetworkConnectionTracker* network_connection_tracker,
const base::FilePath& storage_dir,
@@ -107,7 +108,6 @@ DownloadService* BuildDownloadService(
auto config = Configuration::CreateFromFinch();
auto driver = std::make_unique<DownloadDriverImpl>(
- content::BrowserContext::GetDownloadManager(browser_context),
download_manager_coordinator);
auto entry_db_storage_dir = storage_dir.Append(kEntryDBStorageDir);
@@ -131,19 +131,19 @@ DownloadService* BuildDownloadService(
}
// Create download service for incognito mode without any database or file IO.
-DownloadService* BuildInMemoryDownloadService(
+std::unique_ptr<DownloadService> BuildInMemoryDownloadService(
SimpleFactoryKey* simple_factory_key,
std::unique_ptr<DownloadClientMap> clients,
network::NetworkConnectionTracker* network_connection_tracker,
const base::FilePath& storage_dir,
- BlobTaskProxy::BlobContextGetter blob_context_getter,
+ BlobContextGetterFactoryPtr blob_context_getter_factory,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
auto config = Configuration::CreateFromFinch();
auto download_factory = std::make_unique<InMemoryDownloadFactory>(
- url_loader_factory.get(), blob_context_getter, io_task_runner);
- auto driver =
- std::make_unique<InMemoryDownloadDriver>(std::move(download_factory));
+ url_loader_factory.get(), io_task_runner);
+ auto driver = std::make_unique<InMemoryDownloadDriver>(
+ std::move(download_factory), std::move(blob_context_getter_factory));
auto store = std::make_unique<NoopStore>();
auto task_scheduler = std::make_unique<EmptyTaskScheduler>();
diff --git a/chromium/components/download/content/factory/download_service_factory_helper.h b/chromium/components/download/content/factory/download_service_factory_helper.h
index f683e03c44b..4d4d4e24f90 100644
--- a/chromium/components/download/content/factory/download_service_factory_helper.h
+++ b/chromium/components/download/content/factory/download_service_factory_helper.h
@@ -11,15 +11,10 @@
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
-#include "components/download/internal/background_service/blob_task_proxy.h"
+#include "components/download/public/background_service/blob_context_getter_factory.h"
#include "components/download/public/background_service/clients.h"
class SimpleFactoryKey;
-class PrefService;
-
-namespace content {
-class BrowserContext;
-} // namespace content
namespace network {
class NetworkConnectionTracker;
@@ -42,10 +37,8 @@ class TaskScheduler;
// will act as an in-memory only service (this means no auto-retries after
// restarts, no files written on completion, etc.).
// |background_task_runner| will be used for all disk reads and writes.
-DownloadService* BuildDownloadService(
- content::BrowserContext* browser_context,
+std::unique_ptr<DownloadService> BuildDownloadService(
SimpleFactoryKey* simple_factory_key,
- PrefService* prefs,
std::unique_ptr<DownloadClientMap> clients,
network::NetworkConnectionTracker* network_connection_tracker,
const base::FilePath& storage_dir,
@@ -55,12 +48,12 @@ DownloadService* BuildDownloadService(
// Create download service used in incognito mode, without any database or
// download file IO.
-DownloadService* BuildInMemoryDownloadService(
+std::unique_ptr<DownloadService> BuildInMemoryDownloadService(
SimpleFactoryKey* simple_factory_key,
std::unique_ptr<DownloadClientMap> clients,
network::NetworkConnectionTracker* network_connection_tracker,
const base::FilePath& storage_dir,
- BlobTaskProxy::BlobContextGetter blob_context_getter,
+ BlobContextGetterFactoryPtr blob_context_getter_factory,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
diff --git a/chromium/components/download/content/internal/download_driver_impl.cc b/chromium/components/download/content/internal/download_driver_impl.cc
index deff1ab8f2b..ea7b4d55ad6 100644
--- a/chromium/components/download/content/internal/download_driver_impl.cc
+++ b/chromium/components/download/content/internal/download_driver_impl.cc
@@ -10,15 +10,16 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/memory_usage_estimator.h"
#include "components/download/internal/background_service/driver_entry.h"
+#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/simple_download_manager_coordinator.h"
-#include "content/public/browser/browser_thread.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
@@ -113,18 +114,19 @@ DriverEntry DownloadDriverImpl::CreateDriverEntry(
}
DownloadDriverImpl::DownloadDriverImpl(
- content::DownloadManager* manager,
SimpleDownloadManagerCoordinator* download_manager_coordinator)
- : download_manager_(manager),
- client_(nullptr),
+ : client_(nullptr),
download_manager_coordinator_(download_manager_coordinator),
+ is_ready_(false),
weak_ptr_factory_(this) {
- DCHECK(download_manager_);
- DCHECK(!download_manager_coordinator_ ||
- !download_manager_coordinator_->HasSetDownloadManager());
+ DCHECK(download_manager_coordinator_);
+ DETACH_FROM_SEQUENCE(sequence_checker_);
}
-DownloadDriverImpl::~DownloadDriverImpl() = default;
+DownloadDriverImpl::~DownloadDriverImpl() {
+ if (download_manager_coordinator_)
+ download_manager_coordinator_->GetNotifier()->RemoveObserver(this);
+}
void DownloadDriverImpl::Initialize(DownloadDriver::Client* client) {
DCHECK(!client_);
@@ -132,13 +134,12 @@ void DownloadDriverImpl::Initialize(DownloadDriver::Client* client) {
DCHECK(client_);
// |download_manager_| may be shut down. Informs the client.
- if (!download_manager_) {
+ if (!download_manager_coordinator_) {
client_->OnDriverReady(false);
return;
}
- notifier_ =
- std::make_unique<AllDownloadItemNotifier>(download_manager_, this);
+ download_manager_coordinator_->GetNotifier()->AddObserver(this);
}
void DownloadDriverImpl::HardRecover() {
@@ -149,8 +150,8 @@ void DownloadDriverImpl::HardRecover() {
}
bool DownloadDriverImpl::IsReady() const {
- return client_ && download_manager_ &&
- download_manager_->IsManagerInitialized();
+ return client_ && download_manager_coordinator_ &&
+ download_manager_coordinator_->initialized();
}
void DownloadDriverImpl::Start(
@@ -161,7 +162,7 @@ void DownloadDriverImpl::Start(
const net::NetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK(!request_params.url.is_empty());
DCHECK(!guid.empty());
- if (!download_manager_)
+ if (!download_manager_coordinator_)
return;
std::unique_ptr<DownloadUrlParameters> download_url_params(
@@ -187,9 +188,9 @@ void DownloadDriverImpl::Start(
download_url_params->set_upload_progress_callback(
base::BindRepeating(&DownloadDriverImpl::OnUploadProgress,
weak_ptr_factory_.GetWeakPtr(), guid));
- download_manager_->DownloadUrl(std::move(download_url_params),
- nullptr /* blob_data_handle */,
- nullptr /* blob_url_loader_factory */);
+ download_url_params->set_require_safety_checks(
+ request_params.require_safety_checks);
+ download_manager_coordinator_->DownloadUrl(std::move(download_url_params));
}
void DownloadDriverImpl::Remove(const std::string& guid, bool remove_file) {
@@ -205,9 +206,9 @@ void DownloadDriverImpl::Remove(const std::string& guid, bool remove_file) {
void DownloadDriverImpl::DoRemoveDownload(const std::string& guid,
bool remove_file) {
- if (!download_manager_)
+ if (!download_manager_coordinator_)
return;
- DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+ DownloadItem* item = download_manager_coordinator_->GetDownloadByGuid(guid);
// Cancels the download and removes the persisted records in content layer.
if (item) {
// Remove the download file for completed download.
@@ -218,25 +219,25 @@ void DownloadDriverImpl::DoRemoveDownload(const std::string& guid,
}
void DownloadDriverImpl::Pause(const std::string& guid) {
- if (!download_manager_)
+ if (!download_manager_coordinator_)
return;
- DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+ DownloadItem* item = download_manager_coordinator_->GetDownloadByGuid(guid);
if (item)
item->Pause();
}
void DownloadDriverImpl::Resume(const std::string& guid) {
- if (!download_manager_)
+ if (!download_manager_coordinator_)
return;
- DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+ DownloadItem* item = download_manager_coordinator_->GetDownloadByGuid(guid);
if (item)
item->Resume(true);
}
base::Optional<DriverEntry> DownloadDriverImpl::Find(const std::string& guid) {
- if (!download_manager_)
+ if (!download_manager_coordinator_)
return base::nullopt;
- DownloadItem* item = download_manager_->GetDownloadByGuid(guid);
+ DownloadItem* item = download_manager_coordinator_->GetDownloadByGuid(guid);
if (item)
return CreateDriverEntry(item);
return base::nullopt;
@@ -244,11 +245,11 @@ base::Optional<DriverEntry> DownloadDriverImpl::Find(const std::string& guid) {
std::set<std::string> DownloadDriverImpl::GetActiveDownloads() {
std::set<std::string> guids;
- if (!download_manager_)
+ if (!download_manager_coordinator_)
return guids;
std::vector<DownloadItem*> items;
- download_manager_->GetAllDownloads(&items);
+ download_manager_coordinator_->GetAllDownloads(&items);
for (auto* item : items) {
DriverEntry::State state = ToDriverEntryState(item->GetState());
@@ -260,12 +261,12 @@ std::set<std::string> DownloadDriverImpl::GetActiveDownloads() {
}
size_t DownloadDriverImpl::EstimateMemoryUsage() const {
- return base::trace_event::EstimateMemoryUsage(guid_to_remove_) +
- notifier_->EstimateMemoryUsage();
+ return base::trace_event::EstimateMemoryUsage(guid_to_remove_);
}
-void DownloadDriverImpl::OnDownloadUpdated(content::DownloadManager* manager,
- DownloadItem* item) {
+void DownloadDriverImpl::OnDownloadUpdated(
+ SimpleDownloadManagerCoordinator* coordinator,
+ DownloadItem* item) {
DCHECK(client_);
// Blocks the observer call if we asked to remove the download.
if (guid_to_remove_.find(item->GetGuid()) != guid_to_remove_.end())
@@ -287,14 +288,16 @@ void DownloadDriverImpl::OnDownloadUpdated(content::DownloadManager* manager,
}
}
-void DownloadDriverImpl::OnDownloadRemoved(content::DownloadManager* manager,
- DownloadItem* download) {
+void DownloadDriverImpl::OnDownloadRemoved(
+ SimpleDownloadManagerCoordinator* coordinator,
+ DownloadItem* download) {
guid_to_remove_.erase(download->GetGuid());
// |download| is about to be deleted.
}
-void DownloadDriverImpl::OnDownloadCreated(content::DownloadManager* manager,
- DownloadItem* item) {
+void DownloadDriverImpl::OnDownloadCreated(
+ SimpleDownloadManagerCoordinator* coordinator,
+ DownloadItem* item) {
if (guid_to_remove_.find(item->GetGuid()) != guid_to_remove_.end()) {
// Client has removed the download before content persistence layer created
// the record, remove the download immediately.
@@ -317,21 +320,30 @@ void DownloadDriverImpl::OnDownloadCreated(content::DownloadManager* manager,
void DownloadDriverImpl::OnUploadProgress(const std::string& guid,
uint64_t bytes_uploaded) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
client_->OnUploadProgress(guid, bytes_uploaded);
}
-void DownloadDriverImpl::OnManagerInitialized(
- content::DownloadManager* manager) {
- DCHECK_EQ(download_manager_, manager);
- DCHECK(client_);
- DCHECK(download_manager_);
+void DownloadDriverImpl::OnDownloadsInitialized(
+ SimpleDownloadManagerCoordinator* coordinator,
+ bool active_downloads_only) {
+ DCHECK_EQ(download_manager_coordinator_, coordinator);
+ DCHECK(download_manager_coordinator_);
+
+ if (!client_)
+ return;
+
+ if (is_ready_)
+ return;
+
client_->OnDriverReady(true);
+ is_ready_ = true;
}
-void DownloadDriverImpl::OnManagerGoingDown(content::DownloadManager* manager) {
- DCHECK_EQ(download_manager_, manager);
- download_manager_ = nullptr;
+void DownloadDriverImpl::OnManagerGoingDown(
+ SimpleDownloadManagerCoordinator* coordinator) {
+ DCHECK_EQ(download_manager_coordinator_, coordinator);
+ download_manager_coordinator_ = nullptr;
}
void DownloadDriverImpl::OnHardRecoverComplete(bool success) {
diff --git a/chromium/components/download/content/internal/download_driver_impl.h b/chromium/components/download/content/internal/download_driver_impl.h
index 67702bfa160..1fca209d5e6 100644
--- a/chromium/components/download/content/internal/download_driver_impl.h
+++ b/chromium/components/download/content/internal/download_driver_impl.h
@@ -11,11 +11,10 @@
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
-#include "components/download/content/public/all_download_item_notifier.h"
+#include "base/sequence_checker.h"
#include "components/download/internal/background_service/download_driver.h"
#include "components/download/public/background_service/download_params.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/download_manager.h"
+#include "components/download/public/common/all_download_event_notifier.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
namespace download {
@@ -27,14 +26,13 @@ struct DriverEntry;
// Aggregates and handles all interaction between download service and content
// download logic.
class DownloadDriverImpl : public DownloadDriver,
- public AllDownloadItemNotifier::Observer {
+ public AllDownloadEventNotifier::Observer {
public:
// Creates a driver entry based on a download item.
static DriverEntry CreateDriverEntry(const download::DownloadItem* item);
// Create the driver.
DownloadDriverImpl(
- content::DownloadManager* manager,
SimpleDownloadManagerCoordinator* download_manager_coordinator);
~DownloadDriverImpl() override;
@@ -56,14 +54,16 @@ class DownloadDriverImpl : public DownloadDriver,
size_t EstimateMemoryUsage() const override;
private:
- // content::AllDownloadItemNotifier::Observer implementation.
- void OnManagerInitialized(content::DownloadManager* manager) override;
- void OnManagerGoingDown(content::DownloadManager* manager) override;
- void OnDownloadCreated(content::DownloadManager* manager,
+ // content::AllDownloadEventNotifier::Observer implementation.
+ void OnDownloadsInitialized(SimpleDownloadManagerCoordinator* coordinator,
+ bool active_downloads_only) override;
+ void OnManagerGoingDown(
+ SimpleDownloadManagerCoordinator* coordinator) override;
+ void OnDownloadCreated(SimpleDownloadManagerCoordinator* coordinator,
download::DownloadItem* item) override;
- void OnDownloadUpdated(content::DownloadManager* manager,
+ void OnDownloadUpdated(SimpleDownloadManagerCoordinator* coordinator,
download::DownloadItem* item) override;
- void OnDownloadRemoved(content::DownloadManager* manager,
+ void OnDownloadRemoved(SimpleDownloadManagerCoordinator* coordinator,
download::DownloadItem* item) override;
void OnUploadProgress(const std::string& guid, uint64_t bytes_uploaded);
@@ -73,15 +73,9 @@ class DownloadDriverImpl : public DownloadDriver,
// Remove the download, used to be posted to the task queue.
void DoRemoveDownload(const std::string& guid, bool remove_file);
- // Low level download handle.
- content::DownloadManager* download_manager_;
-
// The client that receives updates from low level download logic.
DownloadDriver::Client* client_;
- // Built lazily on initialize and destroyed when/if the manager is torn down.
- std::unique_ptr<AllDownloadItemNotifier> notifier_;
-
// Pending guid set of downloads that will be removed soon.
std::set<std::string> guid_to_remove_;
@@ -89,6 +83,11 @@ class DownloadDriverImpl : public DownloadDriver,
// no longer used.
SimpleDownloadManagerCoordinator* download_manager_coordinator_;
+ // Whether this object is ready to handle download requests.
+ bool is_ready_;
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
// Only used to post tasks on the same thread.
base::WeakPtrFactory<DownloadDriverImpl> weak_ptr_factory_;
diff --git a/chromium/components/download/content/internal/download_driver_impl_unittest.cc b/chromium/components/download/content/internal/download_driver_impl_unittest.cc
index 28628fda993..a4bdcca950f 100644
--- a/chromium/components/download/content/internal/download_driver_impl_unittest.cc
+++ b/chromium/components/download/content/internal/download_driver_impl_unittest.cc
@@ -7,13 +7,14 @@
#include <memory>
#include <string>
+#include "base/bind_helpers.h"
#include "base/guid.h"
#include "base/test/test_simple_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/download/content/public/all_download_item_notifier.h"
#include "components/download/internal/background_service/test/mock_download_driver_client.h"
+#include "components/download/public/common//mock_simple_download_manager.h"
#include "content/public/test/fake_download_item.h"
-#include "content/public/test/mock_download_manager.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -52,18 +53,22 @@ MATCHER_P(DriverEntryEqual, entry, "") {
class DownloadDriverImplTest : public testing::Test {
public:
DownloadDriverImplTest()
- : task_runner_(new base::TestSimpleTaskRunner), handle_(task_runner_) {}
+ : coordinator_(base::NullCallback()),
+ task_runner_(new base::TestSimpleTaskRunner),
+ handle_(task_runner_) {}
~DownloadDriverImplTest() override = default;
void SetUp() override {
EXPECT_CALL(mock_client_, IsTrackingDownload(_))
.WillRepeatedly(Return(true));
- driver_ = std::make_unique<DownloadDriverImpl>(&mock_manager_, nullptr);
+ driver_ = std::make_unique<DownloadDriverImpl>(&coordinator_);
+ coordinator_.SetSimpleDownloadManager(&mock_manager_, true);
}
// TODO(xingliu): implements test download manager for embedders to test.
- NiceMock<content::MockDownloadManager> mock_manager_;
+ SimpleDownloadManagerCoordinator coordinator_;
+ NiceMock<MockSimpleDownloadManager> mock_manager_;
MockDriverClient mock_client_;
std::unique_ptr<DownloadDriverImpl> driver_;
@@ -77,20 +82,18 @@ class DownloadDriverImplTest : public testing::Test {
// Ensure the download manager can be initialized after the download driver.
TEST_F(DownloadDriverImplTest, ManagerLateInitialization) {
- EXPECT_CALL(mock_manager_, IsManagerInitialized())
- .Times(1)
- .WillOnce(Return(false));
driver_->Initialize(&mock_client_);
- EXPECT_CALL(mock_client_, OnDriverReady(true));
- static_cast<AllDownloadItemNotifier::Observer*>(driver_.get())
- ->OnManagerInitialized(&mock_manager_);
+ EXPECT_CALL(mock_client_, OnDriverReady(true)).Times(1);
+ static_cast<AllDownloadEventNotifier::Observer*>(driver_.get())
+ ->OnDownloadsInitialized(&coordinator_, true);
+
+ EXPECT_CALL(mock_client_, OnDriverReady(true)).Times(0);
+ static_cast<AllDownloadEventNotifier::Observer*>(driver_.get())
+ ->OnDownloadsInitialized(&coordinator_, false);
}
TEST_F(DownloadDriverImplTest, TestHardRecover) {
- EXPECT_CALL(mock_manager_, IsManagerInitialized())
- .Times(1)
- .WillOnce(Return(false));
driver_->Initialize(&mock_client_);
EXPECT_CALL(mock_client_, OnDriverHardRecoverComplete(true)).Times(1);
@@ -102,14 +105,10 @@ TEST_F(DownloadDriverImplTest, TestHardRecover) {
TEST_F(DownloadDriverImplTest, RemoveBeforeCreated) {
using DownloadState = download::DownloadItem::DownloadState;
- EXPECT_CALL(mock_manager_, IsManagerInitialized())
- .Times(1)
- .WillOnce(Return(false));
driver_->Initialize(&mock_client_);
EXPECT_CALL(mock_client_, OnDriverReady(true));
- static_cast<AllDownloadItemNotifier::Observer*>(driver_.get())
- ->OnManagerInitialized(&mock_manager_);
+ mock_manager_.NotifyOnDownloadInitialized();
const std::string kTestGuid = "abc";
content::FakeDownloadItem fake_item;
@@ -126,8 +125,8 @@ TEST_F(DownloadDriverImplTest, RemoveBeforeCreated) {
ON_CALL(mock_manager_, GetDownloadByGuid(kTestGuid))
.WillByDefault(Return(&fake_item));
EXPECT_CALL(mock_client_, OnDownloadCreated(_)).Times(0);
- static_cast<AllDownloadItemNotifier::Observer*>(driver_.get())
- ->OnDownloadCreated(&mock_manager_, &fake_item);
+ static_cast<AllDownloadEventNotifier::Observer*>(driver_.get())
+ ->OnDownloadCreated(&coordinator_, &fake_item);
task_runner_->RunUntilIdle();
// Expect a remove call down to content layer download item.
@@ -139,9 +138,7 @@ TEST_F(DownloadDriverImplTest, DownloadItemUpdateEvents) {
using DownloadState = download::DownloadItem::DownloadState;
using DownloadInterruptReason = download::DownloadInterruptReason;
- EXPECT_CALL(mock_manager_, IsManagerInitialized())
- .Times(1)
- .WillOnce(Return(true));
+ mock_manager_.NotifyOnDownloadInitialized();
EXPECT_CALL(mock_client_, OnDriverReady(true)).Times(1);
driver_->Initialize(&mock_client_);
@@ -155,13 +152,13 @@ TEST_F(DownloadDriverImplTest, DownloadItemUpdateEvents) {
EXPECT_CALL(mock_client_, OnDownloadUpdated(DriverEntryEqual(entry)))
.Times(1)
.RetiresOnSaturation();
- static_cast<AllDownloadItemNotifier::Observer*>(driver_.get())
- ->OnDownloadUpdated(&mock_manager_, &fake_item);
+ static_cast<AllDownloadEventNotifier::Observer*>(driver_.get())
+ ->OnDownloadUpdated(&coordinator_, &fake_item);
// Nothing happens for cancelled state.
fake_item.SetState(DownloadState::CANCELLED);
- static_cast<AllDownloadItemNotifier::Observer*>(driver_.get())
- ->OnDownloadUpdated(&mock_manager_, &fake_item);
+ static_cast<AllDownloadEventNotifier::Observer*>(driver_.get())
+ ->OnDownloadUpdated(&coordinator_, &fake_item);
fake_item.SetReceivedBytes(1024);
fake_item.SetState(DownloadState::COMPLETE);
@@ -170,8 +167,8 @@ TEST_F(DownloadDriverImplTest, DownloadItemUpdateEvents) {
EXPECT_CALL(mock_client_, OnDownloadSucceeded(DriverEntryEqual(entry)))
.Times(1)
.RetiresOnSaturation();
- static_cast<AllDownloadItemNotifier::Observer*>(driver_.get())
- ->OnDownloadUpdated(&mock_manager_, &fake_item);
+ static_cast<AllDownloadEventNotifier::Observer*>(driver_.get())
+ ->OnDownloadUpdated(&coordinator_, &fake_item);
fake_item.SetState(DownloadState::INTERRUPTED);
fake_item.SetLastReason(
@@ -181,8 +178,8 @@ TEST_F(DownloadDriverImplTest, DownloadItemUpdateEvents) {
FailureType::RECOVERABLE))
.Times(1)
.RetiresOnSaturation();
- static_cast<AllDownloadItemNotifier::Observer*>(driver_.get())
- ->OnDownloadUpdated(&mock_manager_, &fake_item);
+ static_cast<AllDownloadEventNotifier::Observer*>(driver_.get())
+ ->OnDownloadUpdated(&coordinator_, &fake_item);
}
TEST_F(DownloadDriverImplTest, TestGetActiveDownloadsCall) {
@@ -208,9 +205,7 @@ TEST_F(DownloadDriverImplTest, TestGetActiveDownloadsCall) {
ON_CALL(mock_manager_, GetAllDownloads(_))
.WillByDefault(PopulateVector(items));
- EXPECT_CALL(mock_manager_, IsManagerInitialized())
- .Times(1)
- .WillOnce(Return(true));
+ mock_manager_.NotifyOnDownloadInitialized();
EXPECT_CALL(mock_client_, OnDriverReady(true)).Times(1);
driver_->Initialize(&mock_client_);
diff --git a/chromium/components/download/internal/background_service/controller_impl.cc b/chromium/components/download/internal/background_service/controller_impl.cc
index 2177e6a8253..c16357d94b4 100644
--- a/chromium/components/download/internal/background_service/controller_impl.cc
+++ b/chromium/components/download/internal/background_service/controller_impl.cc
@@ -9,7 +9,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/callback_helpers.h"
#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -388,8 +387,7 @@ void ControllerImpl::HandleTaskFinished(DownloadTaskType task_type,
return;
if (status != stats::ScheduledTaskStatus::CANCELLED_ON_STOP) {
- base::ResetAndReturn(&task_finished_callbacks_[task_type])
- .Run(needs_reschedule);
+ std::move(task_finished_callbacks_[task_type]).Run(needs_reschedule);
}
// TODO(dtrainor): It might be useful to log how many downloads we have
// running when we're asked to stop processing.
@@ -438,13 +436,8 @@ void ControllerImpl::OnDownloadCreated(const DriverEntry& download) {
download::Client* client = clients_->GetClient(entry->client);
DCHECK(client);
- using ShouldDownload = download::Client::ShouldDownload;
- ShouldDownload should_download = client->OnDownloadStarted(
- download.guid, download.url_chain, download.response_headers);
- stats::LogStartDownloadResponse(entry->client, should_download);
- if (should_download == ShouldDownload::ABORT) {
- HandleCompleteDownload(CompletionType::ABORT, entry->guid);
- }
+ client->OnDownloadStarted(download.guid, download.url_chain,
+ download.response_headers);
}
void ControllerImpl::OnDownloadFailed(const DriverEntry& download,
@@ -1098,8 +1091,8 @@ void ControllerImpl::NotifyServiceOfStartup() {
if (init_callback_.is_null())
return;
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::ResetAndReturn(&init_callback_));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ std::move(init_callback_));
}
void ControllerImpl::HandleStartDownloadResponse(
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 0cd66071ce7..f1524e58f69 100644
--- a/chromium/components/download/internal/background_service/controller_impl_unittest.cc
+++ b/chromium/components/download/internal/background_service/controller_impl_unittest.cc
@@ -1221,23 +1221,20 @@ TEST_F(DownloadServiceControllerImplTest, DownloadCompletionTest) {
Entry entry1 = test::BuildBasicEntry(Entry::State::ACTIVE);
Entry entry2 = test::BuildBasicEntry(Entry::State::ACTIVE);
Entry entry3 = test::BuildBasicEntry(Entry::State::ACTIVE);
- Entry entry4 = test::BuildBasicEntry(Entry::State::ACTIVE);
- entry4.scheduling_params.cancel_time = base::Time::Now();
- std::vector<Entry> entries = {entry1, entry2, entry3, entry4};
+ entry3.scheduling_params.cancel_time = base::Time::Now();
+ std::vector<Entry> entries = {entry1, entry2, entry3};
DriverEntry dentry1 =
BuildDriverEntry(entry1, DriverEntry::State::IN_PROGRESS);
- // dentry2 will effectively be created by the test to simulate a start
- // download.
- DriverEntry dentry3 =
- BuildDriverEntry(entry3, DriverEntry::State::IN_PROGRESS);
- driver_->AddTestData(std::vector<DriverEntry>{dentry1, dentry3});
+ DriverEntry dentry2 =
+ BuildDriverEntry(entry2, DriverEntry::State::IN_PROGRESS);
+ driver_->AddTestData(std::vector<DriverEntry>{dentry1, dentry2});
EXPECT_CALL(*client_, OnServiceInitialized(false, _)).Times(1);
// Test FailureReason::TIMEDOUT.
EXPECT_CALL(*client_,
- OnDownloadFailed(entry4.guid, _, Client::FailureReason::TIMEDOUT))
+ OnDownloadFailed(entry3.guid, _, Client::FailureReason::TIMEDOUT))
.Times(1);
// Set up the Controller.
@@ -1254,21 +1251,11 @@ TEST_F(DownloadServiceControllerImplTest, DownloadCompletionTest) {
.Times(1);
controller_->CancelDownload(entry1.guid);
- // Test FailureReason::ABORTED.
- EXPECT_CALL(*client_, OnDownloadStarted(entry2.guid, _, _))
- .Times(1)
- .WillOnce(Return(Client::ShouldDownload::ABORT));
- EXPECT_CALL(*client_,
- OnDownloadFailed(entry2.guid, _, Client::FailureReason::ABORTED))
- .Times(1);
- driver_->Start(RequestParams(), entry2.guid, entry2.target_file_path, nullptr,
- TRAFFIC_ANNOTATION_FOR_TESTS);
-
// Test FailureReason::NETWORK.
EXPECT_CALL(*client_,
- OnDownloadFailed(entry3.guid, _, Client::FailureReason::NETWORK))
+ OnDownloadFailed(entry2.guid, _, Client::FailureReason::NETWORK))
.Times(1);
- driver_->NotifyDownloadFailed(dentry3, FailureType::NOT_RECOVERABLE);
+ driver_->NotifyDownloadFailed(dentry2, FailureType::NOT_RECOVERABLE);
task_runner_->RunUntilIdle();
}
diff --git a/chromium/components/download/internal/background_service/debugging_client.cc b/chromium/components/download/internal/background_service/debugging_client.cc
index 9bc4298b639..4c1879c0b82 100644
--- a/chromium/components/download/internal/background_service/debugging_client.cc
+++ b/chromium/components/download/internal/background_service/debugging_client.cc
@@ -17,12 +17,10 @@ void DebuggingClient::OnServiceInitialized(
void DebuggingClient::OnServiceUnavailable() {}
-Client::ShouldDownload DebuggingClient::OnDownloadStarted(
+void DebuggingClient::OnDownloadStarted(
const std::string& guid,
const std::vector<GURL>& url_chain,
- const scoped_refptr<const net::HttpResponseHeaders>& headers) {
- return Client::ShouldDownload::CONTINUE;
-}
+ const scoped_refptr<const net::HttpResponseHeaders>& headers) {}
void DebuggingClient::OnDownloadUpdated(const std::string& guid,
uint64_t bytes_uploaded,
diff --git a/chromium/components/download/internal/background_service/debugging_client.h b/chromium/components/download/internal/background_service/debugging_client.h
index 74db9bf55ee..252c81141f4 100644
--- a/chromium/components/download/internal/background_service/debugging_client.h
+++ b/chromium/components/download/internal/background_service/debugging_client.h
@@ -23,7 +23,7 @@ class DebuggingClient : public Client {
bool state_lost,
const std::vector<DownloadMetaData>& downloads) override;
void OnServiceUnavailable() override;
- ShouldDownload OnDownloadStarted(
+ void OnDownloadStarted(
const std::string& guid,
const std::vector<GURL>& url_chain,
const scoped_refptr<const net::HttpResponseHeaders>& headers) override;
diff --git a/chromium/components/download/internal/background_service/in_memory_download.cc b/chromium/components/download/internal/background_service/in_memory_download.cc
index 15ab8286017..6b3ac7d5abd 100644
--- a/chromium/components/download/internal/background_service/in_memory_download.cc
+++ b/chromium/components/download/internal/background_service/in_memory_download.cc
@@ -32,21 +32,19 @@ InMemoryDownloadImpl::InMemoryDownloadImpl(
const net::NetworkTrafficAnnotationTag& traffic_annotation,
Delegate* delegate,
network::mojom::URLLoaderFactory* url_loader_factory,
- BlobTaskProxy::BlobContextGetter blob_context_getter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: InMemoryDownload(guid),
request_params_(request_params),
request_body_(std::move(request_body)),
traffic_annotation_(traffic_annotation),
url_loader_factory_(url_loader_factory),
- blob_task_proxy_(
- BlobTaskProxy::Create(blob_context_getter, io_task_runner)),
io_task_runner_(io_task_runner),
delegate_(delegate),
completion_notified_(false),
started_(false),
weak_ptr_factory_(this) {
DCHECK(!guid_.empty());
+ DCHECK(delegate_);
}
InMemoryDownloadImpl::~InMemoryDownloadImpl() {
@@ -55,6 +53,17 @@ InMemoryDownloadImpl::~InMemoryDownloadImpl() {
void InMemoryDownloadImpl::Start() {
DCHECK(state_ == State::INITIAL) << "Only call Start() for new download.";
+ state_ = State::RETRIEVE_BLOB_CONTEXT;
+ delegate_->RetrieveBlobContextGetter(
+ base::BindOnce(&InMemoryDownloadImpl::OnRetrievedBlobContextGetter,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void InMemoryDownloadImpl::OnRetrievedBlobContextGetter(
+ BlobContextGetter blob_context_getter) {
+ DCHECK(state_ == State::RETRIEVE_BLOB_CONTEXT);
+ blob_task_proxy_ =
+ BlobTaskProxy::Create(blob_context_getter, io_task_runner_);
SendRequest();
state_ = State::IN_PROGRESS;
}
@@ -69,7 +78,7 @@ void InMemoryDownloadImpl::Resume() {
switch (state_) {
case State::INITIAL:
- NOTREACHED();
+ case State::RETRIEVE_BLOB_CONTEXT:
return;
case State::IN_PROGRESS:
// Let the network pipe continue to read data.
@@ -115,8 +124,7 @@ void InMemoryDownloadImpl::OnDataReceived(base::StringPiece string_piece,
std::move(resume).Run();
// TODO(xingliu): Throttle the update frequency. See https://crbug.com/809674.
- if (delegate_)
- delegate_->OnDownloadProgress(this);
+ delegate_->OnDownloadProgress(this);
}
void InMemoryDownloadImpl::OnComplete(bool success) {
@@ -183,8 +191,7 @@ void InMemoryDownloadImpl::NotifyDelegateDownloadComplete() {
return;
completion_notified_ = true;
- if (delegate_)
- delegate_->OnDownloadComplete(this);
+ delegate_->OnDownloadComplete(this);
}
void InMemoryDownloadImpl::SendRequest() {
@@ -228,14 +235,12 @@ void InMemoryDownloadImpl::OnResponseStarted(
started_ = true;
response_headers_ = response_head.headers;
- if (delegate_)
- delegate_->OnDownloadStarted(this);
+ delegate_->OnDownloadStarted(this);
}
void InMemoryDownloadImpl::OnUploadProgress(uint64_t position, uint64_t total) {
bytes_uploaded_ = position;
- if (delegate_)
- delegate_->OnUploadProgress(this);
+ delegate_->OnUploadProgress(this);
}
void InMemoryDownloadImpl::Reset() {
diff --git a/chromium/components/download/internal/background_service/in_memory_download.h b/chromium/components/download/internal/background_service/in_memory_download.h
index 4b0baa7e14f..950d38f9ab8 100644
--- a/chromium/components/download/internal/background_service/in_memory_download.h
+++ b/chromium/components/download/internal/background_service/in_memory_download.h
@@ -15,6 +15,7 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "components/download/internal/background_service/blob_task_proxy.h"
+#include "components/download/public/background_service/blob_context_getter_factory.h"
#include "components/download/public/background_service/download_params.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
@@ -38,18 +39,23 @@ struct RequestParams;
// Used by download service in Incognito mode, where download files shouldn't
// be persisted to disk.
//
-// Life cycle: The object is created before creating the network request.
-// Call Start() to send the network request.
+// Life cycle: The object is created before sending the network request.
+// Call Start() to retrieve the blob storage context and send the network
+// request.
class InMemoryDownload {
public:
- // Report download progress with in-memory download backend.
class Delegate {
public:
+ // Report download progress with in-memory download backend.
virtual void OnDownloadStarted(InMemoryDownload* download) = 0;
virtual void OnDownloadProgress(InMemoryDownload* download) = 0;
virtual void OnDownloadComplete(InMemoryDownload* download) = 0;
virtual void OnUploadProgress(InMemoryDownload* download) = 0;
+ // Retrieves the blob storage context getter.
+ virtual void RetrieveBlobContextGetter(
+ BlobContextGetterCallback callback) = 0;
+
protected:
virtual ~Delegate() = default;
};
@@ -69,12 +75,15 @@ class InMemoryDownload {
// States of the download.
enum class State {
- // The object is created but network request has not been sent.
+ // The object is just created.
INITIAL,
+ // Waiting to retrieve BlobStorageContextGetter.
+ RETRIEVE_BLOB_CONTEXT,
+
// Download is in progress, including the following procedures.
- // 1. Transfer network data.
- // 2. Save to blob storage.
+ // 1. Send the network request and transfer data from network.
+ // 2. Save the data to blob storage.
IN_PROGRESS,
// The download can fail due to:
@@ -161,7 +170,6 @@ class InMemoryDownloadImpl : public network::SimpleURLLoaderStreamConsumer,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
Delegate* delegate,
network::mojom::URLLoaderFactory* url_loader_factory,
- BlobTaskProxy::BlobContextGetter blob_context_getter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~InMemoryDownloadImpl() override;
@@ -172,6 +180,9 @@ class InMemoryDownloadImpl : public network::SimpleURLLoaderStreamConsumer,
void Pause() override;
void Resume() override;
+ // Called when the BlobStorageContextGetter is ready to use.
+ void OnRetrievedBlobContextGetter(BlobContextGetter blob_context_getter);
+
std::unique_ptr<storage::BlobDataHandle> ResultAsBlob() const override;
size_t EstimateMemoryUsage() const override;
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 7cc50015adf..69fed665443 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
@@ -14,7 +14,7 @@ namespace {
DriverEntry::State ToDriverEntryState(InMemoryDownload::State state) {
switch (state) {
case InMemoryDownload::State::INITIAL:
- return DriverEntry::State::IN_PROGRESS;
+ case InMemoryDownload::State::RETRIEVE_BLOB_CONTEXT:
case InMemoryDownload::State::IN_PROGRESS:
return DriverEntry::State::IN_PROGRESS;
case InMemoryDownload::State::FAILED:
@@ -55,10 +55,8 @@ DriverEntry CreateDriverEntry(const InMemoryDownload& download) {
InMemoryDownloadFactory::InMemoryDownloadFactory(
network::mojom::URLLoaderFactory* url_loader_factory,
- BlobTaskProxy::BlobContextGetter blob_context_getter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: url_loader_factory_(url_loader_factory),
- blob_context_getter_(blob_context_getter),
io_task_runner_(io_task_runner) {}
InMemoryDownloadFactory::~InMemoryDownloadFactory() = default;
@@ -72,12 +70,15 @@ std::unique_ptr<InMemoryDownload> InMemoryDownloadFactory::Create(
DCHECK(url_loader_factory_);
return std::make_unique<InMemoryDownloadImpl>(
guid, request_params, std::move(request_body), traffic_annotation,
- delegate, url_loader_factory_, blob_context_getter_, io_task_runner_);
+ delegate, url_loader_factory_, io_task_runner_);
}
InMemoryDownloadDriver::InMemoryDownloadDriver(
- std::unique_ptr<InMemoryDownload::Factory> download_factory)
- : client_(nullptr), download_factory_(std::move(download_factory)) {}
+ std::unique_ptr<InMemoryDownload::Factory> download_factory,
+ BlobContextGetterFactoryPtr blob_context_getter_factory)
+ : client_(nullptr),
+ download_factory_(std::move(download_factory)),
+ blob_context_getter_factory_(std::move(blob_context_getter_factory)) {}
InMemoryDownloadDriver::~InMemoryDownloadDriver() = default;
@@ -182,6 +183,7 @@ void InMemoryDownloadDriver::OnDownloadComplete(InMemoryDownload* download) {
// OnDownloadSucceeded.
return;
case InMemoryDownload::State::INITIAL:
+ case InMemoryDownload::State::RETRIEVE_BLOB_CONTEXT:
case InMemoryDownload::State::IN_PROGRESS:
NOTREACHED();
return;
@@ -194,4 +196,9 @@ void InMemoryDownloadDriver::OnUploadProgress(InMemoryDownload* download) {
client_->OnUploadProgress(download->guid(), download->bytes_uploaded());
}
+void InMemoryDownloadDriver::RetrieveBlobContextGetter(
+ BlobContextGetterCallback callback) {
+ blob_context_getter_factory_->RetrieveBlobContextGetter(std::move(callback));
+}
+
} // namespace download
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 a50daddb699..4d2bbcabb4f 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
@@ -24,7 +24,6 @@ class InMemoryDownloadFactory : public InMemoryDownload::Factory {
public:
InMemoryDownloadFactory(
network::mojom::URLLoaderFactory* url_loader_factory,
- BlobTaskProxy::BlobContextGetter blob_context_getter,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
~InMemoryDownloadFactory() override;
@@ -39,7 +38,6 @@ class InMemoryDownloadFactory : public InMemoryDownload::Factory {
network::mojom::URLLoaderFactory* url_loader_factory_;
- BlobTaskProxy::BlobContextGetter blob_context_getter_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
DISALLOW_COPY_AND_ASSIGN(InMemoryDownloadFactory);
@@ -50,8 +48,9 @@ class InMemoryDownloadFactory : public InMemoryDownload::Factory {
class InMemoryDownloadDriver : public DownloadDriver,
public InMemoryDownload::Delegate {
public:
- explicit InMemoryDownloadDriver(
- std::unique_ptr<InMemoryDownload::Factory> download_factory);
+ InMemoryDownloadDriver(
+ std::unique_ptr<InMemoryDownload::Factory> download_factory,
+ BlobContextGetterFactoryPtr blob_context_getter_factory);
~InMemoryDownloadDriver() override;
private:
@@ -77,6 +76,7 @@ class InMemoryDownloadDriver : public DownloadDriver,
void OnDownloadProgress(InMemoryDownload* download) override;
void OnDownloadComplete(InMemoryDownload* download) override;
void OnUploadProgress(InMemoryDownload* download) override;
+ void RetrieveBlobContextGetter(BlobContextGetterCallback callback) override;
// The client that receives updates from low level download logic.
DownloadDriver::Client* client_;
@@ -84,6 +84,9 @@ class InMemoryDownloadDriver : public DownloadDriver,
// The factory used to create in memory download objects.
std::unique_ptr<InMemoryDownload::Factory> download_factory_;
+ // Used to retrieve BlobStorageContextGetter.
+ BlobContextGetterFactoryPtr blob_context_getter_factory_;
+
// A map of GUID and in memory download, which holds download data.
std::map<std::string, std::unique_ptr<InMemoryDownload>> downloads_;
diff --git a/chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc b/chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc
index 65de0d0a2ee..432884237bc 100644
--- a/chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc
+++ b/chromium/components/download/internal/background_service/in_memory_download_driver_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "components/download/internal/background_service/test/mock_download_driver_client.h"
+#include "components/download/public/background_service/blob_context_getter_factory.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "storage/browser/blob/blob_data_handle.h"
@@ -23,6 +24,17 @@ MATCHER_P(DriverEntryEqual, entry, "") {
entry.bytes_downloaded == arg.bytes_downloaded;
}
+// BlobContextGetterFactory implementation that does nothing.
+class NoopBlobContextGetterFactory : public BlobContextGetterFactory {
+ public:
+ NoopBlobContextGetterFactory() = default;
+ ~NoopBlobContextGetterFactory() override = default;
+
+ private:
+ void RetrieveBlobContextGetter(BlobContextGetterCallback callback) override {}
+ DISALLOW_COPY_AND_ASSIGN(NoopBlobContextGetterFactory);
+};
+
// Test in memory download that doesn't do complex IO.
class TestInMemoryDownload : public InMemoryDownload {
public:
@@ -106,7 +118,10 @@ class InMemoryDownloadDriverTest : public testing::Test {
void SetUp() override {
auto factory = std::make_unique<TestInMemoryDownloadFactory>();
factory_ = factory.get();
- driver_ = std::make_unique<InMemoryDownloadDriver>(std::move(factory));
+ auto blob_context_getter_factory =
+ std::make_unique<NoopBlobContextGetterFactory>();
+ driver_ = std::make_unique<InMemoryDownloadDriver>(
+ std::move(factory), std::move(blob_context_getter_factory));
driver()->Initialize(&driver_client_);
}
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 532d31c06e4..19a7e6d353f 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
@@ -45,9 +45,17 @@ void SetValue(T* address, T value) {
*address = value;
}
+// Must run on IO thread task runner.
+base::WeakPtr<storage::BlobStorageContext> BlobStorageContextGetter(
+ storage::BlobStorageContext* blob_context) {
+ DCHECK(blob_context);
+ return blob_context->AsWeakPtr();
+}
+
class MockDelegate : public InMemoryDownload::Delegate {
public:
- MockDelegate() = default;
+ MockDelegate(BlobContextGetter blob_context_getter)
+ : blob_context_getter_(blob_context_getter) {}
void WaitForCompletion() {
DCHECK(!run_loop_.running());
@@ -62,20 +70,18 @@ class MockDelegate : public InMemoryDownload::Delegate {
run_loop_.Quit();
}
MOCK_METHOD1(OnUploadProgress, void(InMemoryDownload*));
+ void RetrieveBlobContextGetter(
+ base::OnceCallback<void(BlobContextGetter)> callback) override {
+ std::move(callback).Run(blob_context_getter_);
+ }
private:
base::RunLoop run_loop_;
+ BlobContextGetter blob_context_getter_;
DISALLOW_COPY_AND_ASSIGN(MockDelegate);
};
-// Must run on IO thread task runner.
-base::WeakPtr<storage::BlobStorageContext> BlobStorageContextGetter(
- storage::BlobStorageContext* blob_context) {
- DCHECK(blob_context);
- return blob_context->AsWeakPtr();
-}
-
class InMemoryDownloadTest : public testing::Test {
public:
InMemoryDownloadTest() = default;
@@ -94,6 +100,11 @@ class InMemoryDownloadTest : public testing::Test {
loop.Quit();
}));
loop.Run();
+
+ auto blob_storage_context_getter = base::BindRepeating(
+ &BlobStorageContextGetter, blob_storage_context_.get());
+ mock_delegate_ =
+ std::make_unique<NiceMock<MockDelegate>>(blob_storage_context_getter);
}
void TearDown() override {
@@ -108,13 +119,11 @@ class InMemoryDownloadTest : public testing::Test {
download_ = std::make_unique<InMemoryDownloadImpl>(
base::GenerateGUID(), request_params, /* request_body= */ nullptr,
TRAFFIC_ANNOTATION_FOR_TESTS, delegate(), &url_loader_factory_,
- base::BindRepeating(&BlobStorageContextGetter,
- blob_storage_context_.get()),
io_thread_->task_runner());
}
InMemoryDownload* download() { return download_.get(); }
- MockDelegate* delegate() { return &mock_delegate_; }
+ MockDelegate* delegate() { return mock_delegate_.get(); }
network::TestURLLoaderFactory* url_loader_factory() {
return &url_loader_factory_;
}
@@ -166,7 +175,7 @@ class InMemoryDownloadTest : public testing::Test {
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<InMemoryDownloadImpl> download_;
- NiceMock<MockDelegate> mock_delegate_;
+ std::unique_ptr<NiceMock<MockDelegate>> mock_delegate_;
// Used by SimpleURLLoader network backend.
network::TestURLLoaderFactory url_loader_factory_;
diff --git a/chromium/components/download/internal/background_service/proto/request.proto b/chromium/components/download/internal/background_service/proto/request.proto
index ae2b7bed13d..485bf6b6ae9 100644
--- a/chromium/components/download/internal/background_service/proto/request.proto
+++ b/chromium/components/download/internal/background_service/proto/request.proto
@@ -19,4 +19,5 @@ message RequestParams {
optional string method = 2;
repeated RequestHeader headers = 3;
optional bool fetch_error_body = 4;
+ optional bool require_safety_checks = 5 [default = true];
}
diff --git a/chromium/components/download/internal/background_service/proto_conversions.cc b/chromium/components/download/internal/background_service/proto_conversions.cc
index 4e074ef9085..630abdf5691 100644
--- a/chromium/components/download/internal/background_service/proto_conversions.cc
+++ b/chromium/components/download/internal/background_service/proto_conversions.cc
@@ -245,6 +245,7 @@ RequestParams ProtoConversions::RequestParamsFromProto(
request_params.url = GURL(proto.url());
request_params.method = proto.method();
request_params.fetch_error_body = proto.fetch_error_body();
+ request_params.require_safety_checks = proto.require_safety_checks();
for (int i = 0; i < proto.headers_size(); i++) {
protodb::RequestHeader header = proto.headers(i);
@@ -259,6 +260,7 @@ void ProtoConversions::RequestParamsToProto(const RequestParams& request_params,
proto->set_url(request_params.url.spec());
proto->set_method(request_params.method);
proto->set_fetch_error_body(request_params.fetch_error_body);
+ proto->set_require_safety_checks(request_params.require_safety_checks);
int i = 0;
net::HttpRequestHeaders::Iterator iter(request_params.request_headers);
@@ -291,7 +293,7 @@ Entry ProtoConversions::EntryFromProto(const protodb::Entry& proto) {
entry.cleanup_attempt_count = proto.cleanup_attempt_count();
entry.has_upload_data = proto.has_upload_data();
entry.traffic_annotation =
- net::MutableNetworkTrafficAnnotationTag({proto.traffic_annotation()});
+ net::CreateMutableNetworkTrafficAnnotationTag(proto.traffic_annotation());
entry.bytes_downloaded = proto.bytes_downloaded();
for (const auto& url : proto.url_chain())
entry.url_chain.emplace_back(url);
diff --git a/chromium/components/download/internal/background_service/proto_conversions_unittest.cc b/chromium/components/download/internal/background_service/proto_conversions_unittest.cc
index 46e9bdc5c92..692389ce813 100644
--- a/chromium/components/download/internal/background_service/proto_conversions_unittest.cc
+++ b/chromium/components/download/internal/background_service/proto_conversions_unittest.cc
@@ -98,6 +98,7 @@ TEST_F(ProtoConversionsTest, RequestParamsWithHeadersConversion) {
expected.url = GURL(TEST_URL);
expected.method = "GET";
expected.fetch_error_body = true;
+ expected.require_safety_checks = false;
expected.request_headers.SetHeader("key1", "value1");
expected.request_headers.SetHeader("key2", "value2");
@@ -108,6 +109,7 @@ TEST_F(ProtoConversionsTest, RequestParamsWithHeadersConversion) {
EXPECT_EQ(expected.url, actual.url);
EXPECT_EQ(expected.method, actual.method);
EXPECT_EQ(expected.fetch_error_body, actual.fetch_error_body);
+ EXPECT_EQ(expected.require_safety_checks, actual.require_safety_checks);
std::string out;
actual.request_headers.GetHeader("key1", &out);
diff --git a/chromium/components/download/internal/background_service/stats.cc b/chromium/components/download/internal/background_service/stats.cc
index a5062f36555..dc627fd7a2f 100644
--- a/chromium/components/download/internal/background_service/stats.cc
+++ b/chromium/components/download/internal/background_service/stats.cc
@@ -221,19 +221,6 @@ void LogStartDownloadResult(DownloadClient client,
DownloadParams::StartResult::COUNT);
}
-void LogStartDownloadResponse(DownloadClient client,
- Client::ShouldDownload should_download) {
- // Total count for each start response.
- std::string name("Download.Service.Request.StartResponse");
- base::UmaHistogramEnumeration(name, should_download,
- Client::ShouldDownload::COUNT);
-
- // Total count for each client response with client suffix.
- name.append(".").append(ClientToHistogramSuffix(client));
- base::UmaHistogramEnumeration(name, should_download,
- Client::ShouldDownload::COUNT);
-}
-
void LogDownloadParams(const DownloadParams& params) {
UMA_HISTOGRAM_ENUMERATION("Download.Service.Request.BatteryRequirement",
params.scheduling_params.battery_requirements,
@@ -400,5 +387,11 @@ void LogHashPresence(bool hash_exists) {
UMA_HISTOGRAM_BOOLEAN("Download.Service.Finish.ReportedHash", hash_exists);
}
+void LogDownloadClientInflatedFullBrowser(DownloadClient client) {
+ std::string client_name(ClientToHistogramSuffix(client));
+ base::UmaHistogramBoolean(
+ "Download.Service.Clients.InflatedFullBrowser." + client_name, true);
+}
+
} // namespace stats
} // namespace download
diff --git a/chromium/components/download/internal/background_service/stats.h b/chromium/components/download/internal/background_service/stats.h
index 49de816c97f..d92385aa429 100644
--- a/chromium/components/download/internal/background_service/stats.h
+++ b/chromium/components/download/internal/background_service/stats.h
@@ -159,10 +159,6 @@ void LogServiceApiAction(DownloadClient client, ServiceApiAction action);
void LogStartDownloadResult(DownloadClient client,
DownloadParams::StartResult result);
-// Logs the client response to StartDownload() attempt on the service.
-void LogStartDownloadResponse(DownloadClient client,
- download::Client::ShouldDownload should_download);
-
// Logs the download parameters when StartDownload() is called.
void LogDownloadParams(const DownloadParams& params);
@@ -230,6 +226,10 @@ void LogHasUploadData(DownloadClient client, bool has_upload_data);
// Records whether or not a completed entry has a hash value.
void LogHashPresence(bool hash_exists);
+// Records count of reduced mode to full browser transitions requested by each
+// client.
+void LogDownloadClientInflatedFullBrowser(DownloadClient client);
+
} // namespace stats
} // namespace download
diff --git a/chromium/components/download/internal/common/BUILD.gn b/chromium/components/download/internal/common/BUILD.gn
index e0b03cffe6a..419ee87c0c6 100644
--- a/chromium/components/download/internal/common/BUILD.gn
+++ b/chromium/components/download/internal/common/BUILD.gn
@@ -74,8 +74,10 @@ source_set("internal") {
"//components/leveldb_proto",
"//mojo/public/c/system",
"//net",
+ "//services/device/public/mojom:mojom",
"//services/metrics/public/cpp:ukm_builders",
"//services/network/public/cpp",
+ "//services/service_manager/public/cpp:cpp",
]
if (is_android) {
@@ -130,6 +132,7 @@ source_set("unit_tests") {
}
sources = [
+ "all_download_event_notifier_unittest.cc",
"base_file_unittest.cc",
"base_file_win_unittest.cc",
"download_db_cache_unittest.cc",
diff --git a/chromium/components/download/internal/common/DEPS b/chromium/components/download/internal/common/DEPS
index 713aa400ea7..015703b0a6f 100644
--- a/chromium/components/download/internal/common/DEPS
+++ b/chromium/components/download/internal/common/DEPS
@@ -22,7 +22,9 @@ include_rules = [
"+net/http/http_util.h",
"+net/traffic_annotation/network_traffic_annotation.h",
"+net/url_request/url_request_context_getter.h",
+ "+services/device/public/mojom",
"+services/metrics/public/cpp",
"+services/network/public/cpp",
"+services/network/public/mojom",
+ "+services/service_manager/public/cpp",
]
diff --git a/chromium/components/download/internal/common/all_download_event_notifier_unittest.cc b/chromium/components/download/internal/common/all_download_event_notifier_unittest.cc
new file mode 100644
index 00000000000..5d63d4da46b
--- /dev/null
+++ b/chromium/components/download/internal/common/all_download_event_notifier_unittest.cc
@@ -0,0 +1,149 @@
+// Copyright 2019 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/all_download_event_notifier.h"
+
+#include "base/bind_helpers.h"
+#include "base/macros.h"
+#include "components/download/public/common/mock_download_item.h"
+#include "components/download/public/common/mock_simple_download_manager.h"
+#include "components/download/public/common/simple_download_manager_coordinator.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::_;
+using testing::NiceMock;
+
+namespace download {
+namespace {
+
+class MockNotifierObserver : public AllDownloadEventNotifier::Observer {
+ public:
+ MockNotifierObserver() = default;
+ ~MockNotifierObserver() override = default;
+
+ MOCK_METHOD2(OnDownloadsInitialized,
+ void(SimpleDownloadManagerCoordinator* manager,
+ bool active_downloads_only));
+ MOCK_METHOD2(OnDownloadCreated,
+ void(SimpleDownloadManagerCoordinator* manager,
+ DownloadItem* item));
+ MOCK_METHOD2(OnDownloadUpdated,
+ void(SimpleDownloadManagerCoordinator* manager,
+ DownloadItem* item));
+ MOCK_METHOD2(OnDownloadOpened,
+ void(SimpleDownloadManagerCoordinator* manager,
+ DownloadItem* item));
+ MOCK_METHOD2(OnDownloadRemoved,
+ void(SimpleDownloadManagerCoordinator* manager,
+ DownloadItem* item));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockNotifierObserver);
+};
+
+class AllDownloadEventNotifierTest : public testing::Test {
+ public:
+ AllDownloadEventNotifierTest() : coordinator_(base::NullCallback()) {}
+
+ ~AllDownloadEventNotifierTest() override = default;
+
+ SimpleDownloadManagerCoordinator* coordinator() { return &coordinator_; }
+
+ MockDownloadItem& item() { return item_; }
+
+ MockNotifierObserver& observer() { return observer_; }
+
+ private:
+ NiceMock<MockDownloadItem> item_;
+ SimpleDownloadManagerCoordinator coordinator_;
+ NiceMock<MockNotifierObserver> observer_;
+ DISALLOW_COPY_AND_ASSIGN(AllDownloadEventNotifierTest);
+};
+
+} // namespace
+
+// Tests that OnDownloadCreated() will be propagated correctly.
+TEST_F(AllDownloadEventNotifierTest, OnDownloadCreated) {
+ NiceMock<MockSimpleDownloadManager> manager;
+ coordinator()->SetSimpleDownloadManager(&manager, true);
+ coordinator()->GetNotifier()->AddObserver(&observer());
+ EXPECT_CALL(observer(), OnDownloadCreated(coordinator(), &item()));
+ manager.NotifyOnNewDownloadCreated(&item());
+}
+
+// Tests that OnDownloadsInitialized() will be propated correctly.
+TEST_F(AllDownloadEventNotifierTest, OnDownloadsInitialized) {
+ NiceMock<MockSimpleDownloadManager> manager;
+ coordinator()->SetSimpleDownloadManager(&manager, false);
+ coordinator()->GetNotifier()->AddObserver(&observer());
+ EXPECT_CALL(observer(), OnDownloadsInitialized(coordinator(), true));
+ manager.NotifyOnDownloadInitialized();
+
+ NiceMock<MockSimpleDownloadManager> manager2;
+ coordinator()->SetSimpleDownloadManager(&manager2, true);
+ EXPECT_CALL(observer(), OnDownloadsInitialized(coordinator(), false));
+ manager2.NotifyOnDownloadInitialized();
+}
+
+// Tests that the full manaager is set before the in progress manager
+// initializes.
+TEST_F(AllDownloadEventNotifierTest,
+ SetFullManagerBeforeInProgressManagerInitializes) {
+ NiceMock<MockSimpleDownloadManager> manager;
+ coordinator()->SetSimpleDownloadManager(&manager, false);
+ coordinator()->GetNotifier()->AddObserver(&observer());
+
+ // Sets the full manager before the first one is initialized.
+ NiceMock<MockSimpleDownloadManager> manager2;
+ coordinator()->SetSimpleDownloadManager(&manager2, true);
+
+ EXPECT_CALL(observer(), OnDownloadsInitialized(coordinator(), _)).Times(0);
+ // Initializing the first manager shouldn't impact the coordinator now.
+ manager.NotifyOnDownloadInitialized();
+ EXPECT_CALL(observer(), OnDownloadsInitialized(coordinator(), false));
+ manager2.NotifyOnDownloadInitialized();
+}
+
+// Tests that OnDownloadUpdated() will be propagated correctly.
+TEST_F(AllDownloadEventNotifierTest, OnDownloadUpdated) {
+ NiceMock<MockSimpleDownloadManager> manager;
+ coordinator()->SetSimpleDownloadManager(&manager, true);
+ coordinator()->GetNotifier()->AddObserver(&observer());
+ EXPECT_CALL(observer(), OnDownloadCreated(coordinator(), &item()));
+ manager.NotifyOnNewDownloadCreated(&item());
+
+ EXPECT_CALL(observer(), OnDownloadUpdated(coordinator(), &item()));
+ item().NotifyObserversDownloadUpdated();
+}
+
+// Tests that observer will be notified if it is added after manager
+// initialization.
+TEST_F(AllDownloadEventNotifierTest, AddObserverAfterManagerInitialization) {
+ NiceMock<MockSimpleDownloadManager> manager;
+ coordinator()->SetSimpleDownloadManager(&manager, true);
+ manager.NotifyOnDownloadInitialized();
+ EXPECT_CALL(observer(), OnDownloadsInitialized(coordinator(), false));
+ coordinator()->GetNotifier()->AddObserver(&observer());
+}
+
+// Tests that observer will only be notified once if multiple manager calls
+// OnDownloadCreated() on the same download.
+TEST_F(AllDownloadEventNotifierTest, MultipleOnDownloadCreatedOnSameDownload) {
+ NiceMock<MockSimpleDownloadManager> manager;
+ coordinator()->GetNotifier()->AddObserver(&observer());
+ coordinator()->SetSimpleDownloadManager(&manager, false);
+ EXPECT_CALL(observer(), OnDownloadCreated(coordinator(), &item())).Times(1);
+ manager.NotifyOnNewDownloadCreated(&item());
+
+ // Sets the full manager and call OnDownloadCreated() again.
+ NiceMock<MockSimpleDownloadManager> manager2;
+ coordinator()->SetSimpleDownloadManager(&manager2, true);
+ manager2.NotifyOnNewDownloadCreated(&item());
+
+ EXPECT_CALL(observer(), OnDownloadUpdated(coordinator(), &item()));
+ item().NotifyObserversDownloadUpdated();
+}
+
+} // namespace download
diff --git a/chromium/components/download/internal/common/android/download_collection_bridge.cc b/chromium/components/download/internal/common/android/download_collection_bridge.cc
index 6dfc75e3fa2..ae075552619 100644
--- a/chromium/components/download/internal/common/android/download_collection_bridge.cc
+++ b/chromium/components/download/internal/common/android/download_collection_bridge.cc
@@ -154,10 +154,7 @@ void DownloadCollectionBridge::GetDisplayNamesForDownloads(
std::move(cb).Run(std::move(result));
return;
}
- jsize count = env->GetArrayLength(jdisplay_infos.obj());
- for (jsize i = 0; i < count; ++i) {
- base::android::ScopedJavaLocalRef<jobject> jdisplay_info(
- env, env->GetObjectArrayElement(jdisplay_infos.obj(), i));
+ for (auto jdisplay_info : jdisplay_infos.ReadElements<jobject>()) {
ScopedJavaLocalRef<jstring> juri =
Java_DisplayNameInfo_getDownloadUri(env, jdisplay_info);
ScopedJavaLocalRef<jstring> jdisplay_name =
@@ -177,6 +174,21 @@ bool DownloadCollectionBridge::NeedToRetrieveDisplayNames() {
return Java_DownloadCollectionBridge_needToRetrieveDisplayNames(env);
}
+// static
+base::FilePath DownloadCollectionBridge::GetDisplayName(
+ const base::FilePath& download_uri) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> jdownload_uri =
+ ConvertUTF8ToJavaString(env, download_uri.value());
+ ScopedJavaLocalRef<jstring> jdisplay_name =
+ Java_DownloadCollectionBridge_getDisplayName(env, jdownload_uri);
+ if (jdisplay_name) {
+ std::string display_name = ConvertJavaStringToUTF8(env, jdisplay_name);
+ return base::FilePath(display_name);
+ }
+ return base::FilePath();
+}
+
jint JNI_DownloadCollectionBridge_GetExpirationDurationInDays(JNIEnv* env) {
std::string finch_value = base::GetFieldTrialParamValueByFeature(
features::kRefreshExpirationDate, kDownloadExpirationDurationFinchKey);
diff --git a/chromium/components/download/internal/common/android/download_collection_bridge.h b/chromium/components/download/internal/common/android/download_collection_bridge.h
index 17cb1a500a5..c3afaae41fe 100644
--- a/chromium/components/download/internal/common/android/download_collection_bridge.h
+++ b/chromium/components/download/internal/common/android/download_collection_bridge.h
@@ -72,6 +72,10 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadCollectionBridge {
// Gets the display name for all downloads.
// Called on non UI thread.
static void GetDisplayNamesForDownloads(GetDisplayNamesCallback cb);
+
+ // Gets the display name for a download.
+ static base::FilePath GetDisplayName(const base::FilePath& download_uri);
+
private:
DISALLOW_COPY_AND_ASSIGN(DownloadCollectionBridge);
};
diff --git a/chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java b/chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
index e45a5b67fa3..29c2a74c9a7 100644
--- a/chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
+++ b/chromium/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
@@ -161,6 +161,15 @@ public class DownloadCollectionBridge {
protected void refreshExpirationDate(final String intermediateUri) {}
/**
+ * Gets the display name for a download.
+ * @param downloadUri Uri of the download.
+ * @return the display name of the download.
+ */
+ protected String getDisplayNameForUri(final String downloadUri) {
+ return null;
+ }
+
+ /**
* Creates an intermediate URI for download to be written into. On completion, call
* nativeOnCreateIntermediateUriResult() with |callbackId|.
* @param fileName Name of the file.
@@ -287,5 +296,15 @@ public class DownloadCollectionBridge {
return nativeGetExpirationDurationInDays();
}
+ /**
+ * Gets the display name for a download.
+ * @param downloadUri Uri of the download.
+ * @return the display name of the download.
+ */
+ @CalledByNative
+ private static String getDisplayName(final String downloadUri) {
+ return getDownloadCollectionBridge().getDisplayNameForUri(downloadUri);
+ }
+
private static native int nativeGetExpirationDurationInDays();
}
diff --git a/chromium/components/download/internal/common/base_file.cc b/chromium/components/download/internal/common/base_file.cc
index d2b4aca398e..d220a7bc132 100644
--- a/chromium/components/download/internal/common/base_file.cc
+++ b/chromium/components/download/internal/common/base_file.cc
@@ -154,9 +154,10 @@ DownloadInterruptReason BaseFile::WriteDataToFile(int64_t offset,
if (detached_)
RecordDownloadCount(APPEND_TO_DETACHED_FILE_COUNT);
- if (!file_.IsValid())
+ if (!file_.IsValid()) {
return LogInterruptReason("No file stream on append", 0,
DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
+ }
// TODO(phajdan.jr): get rid of this check.
if (data_len == 0)
@@ -204,6 +205,27 @@ DownloadInterruptReason BaseFile::WriteDataToFile(int64_t offset,
return DOWNLOAD_INTERRUPT_REASON_NONE;
}
+bool BaseFile::ValidateDataInFile(int64_t offset,
+ const char* data,
+ size_t data_len) {
+ if (!file_.IsValid())
+ return false;
+
+ // Only validate the first chunk of the file. So |offset| cannot be
+ // larger than bytes received.
+ if (offset > bytes_so_far_)
+ return false;
+
+ if (data_len <= 0)
+ return true;
+
+ std::unique_ptr<char[]> buffer(new char[data_len]);
+ if (file_.Read(offset, buffer.get(), data_len) <= 0)
+ return false;
+
+ return memcmp(data, buffer.get(), data_len) == 0;
+}
+
DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE;
diff --git a/chromium/components/download/internal/common/base_file_unittest.cc b/chromium/components/download/internal/common/base_file_unittest.cc
index f86edf1bcc0..921ad87a2fe 100644
--- a/chromium/components/download/internal/common/base_file_unittest.cc
+++ b/chromium/components/download/internal/common/base_file_unittest.cc
@@ -757,4 +757,25 @@ TEST_F(BaseFileTest, WriteDataToSparseFile) {
ExpectHashValue(kHashOfTestData1To3, base_file_->Finish());
}
+// Test that validating data in a file works.
+TEST_F(BaseFileTest, ValidateDataInFile) {
+ ASSERT_TRUE(InitializeFile());
+ ASSERT_TRUE(AppendDataToFile(kTestData1));
+
+ ASSERT_TRUE(base_file_->ValidateDataInFile(0, "Let's", 5));
+ ASSERT_TRUE(base_file_->ValidateDataInFile(1, "et's ", 5));
+ ASSERT_TRUE(base_file_->ValidateDataInFile(
+ 0, "Let's write some data to the file!\n", kTestDataLength1));
+ ASSERT_TRUE(base_file_->ValidateDataInFile(kTestDataLength1 - 1, "\n", 1));
+ ASSERT_FALSE(base_file_->ValidateDataInFile(kTestDataLength1, "\n", 1));
+ ASSERT_FALSE(base_file_->ValidateDataInFile(kTestDataLength1 - 1, "y\n", 2));
+ ASSERT_FALSE(base_file_->ValidateDataInFile(0, "et's ", 5));
+ ASSERT_FALSE(base_file_->ValidateDataInFile(
+ 0, "Let's write some data to the file1\n", kTestDataLength1));
+ ASSERT_FALSE(base_file_->ValidateDataInFile(
+ 0, "Let's write some data to the file1!\n", kTestDataLength1 + 1));
+
+ base_file_->Finish();
+}
+
} // namespace download
diff --git a/chromium/components/download/internal/common/download_file_impl.cc b/chromium/components/download/internal/common/download_file_impl.cc
index e433cb0822c..13f52e034d4 100644
--- a/chromium/components/download/internal/common/download_file_impl.cc
+++ b/chromium/components/download/internal/common/download_file_impl.cc
@@ -4,6 +4,7 @@
#include "components/download/public/common/download_file_impl.h"
+#include <algorithm>
#include <string>
#include <utility>
@@ -58,13 +59,24 @@ const int kUnknownContentLength = -1;
DownloadFileImpl::SourceStream::SourceStream(
int64_t offset,
int64_t length,
+ int64_t starting_file_write_offset,
std::unique_ptr<InputStream> stream)
: offset_(offset),
length_(length),
+ starting_file_write_offset_(starting_file_write_offset),
+ bytes_read_(0),
bytes_written_(0),
finished_(false),
index_(0u),
- input_stream_(std::move(stream)) {}
+ input_stream_(std::move(stream)) {
+ CHECK_LE(offset_, starting_file_write_offset_);
+ CHECK_GE(offset_, 0);
+ DCHECK(length <= 0 || length >= starting_file_write_offset - offset)
+ << "Not enough for content validation. offset = " << offset
+ << ", length = " << length
+ << " , starting_file_write_offset = " << starting_file_write_offset
+ << ".";
+}
DownloadFileImpl::SourceStream::~SourceStream() = default;
@@ -72,19 +84,25 @@ void DownloadFileImpl::SourceStream::Initialize() {
input_stream_->Initialize();
}
-void DownloadFileImpl::SourceStream::OnWriteBytesToDisk(int64_t bytes_write) {
- bytes_written_ += bytes_write;
+void DownloadFileImpl::SourceStream::OnBytesConsumed(int64_t bytes_read,
+ int64_t bytes_written) {
+ CHECK_GE(bytes_read, bytes_written);
+ bytes_read_ += bytes_read;
+ bytes_written_ += bytes_written;
}
void DownloadFileImpl::SourceStream::TruncateLengthWithWrittenDataBlock(
- int64_t offset,
+ int64_t received_slice_offset,
int64_t bytes_written) {
DCHECK_GT(bytes_written, 0);
if (length_ == kNoBytesToWrite)
return;
- if (offset <= offset_) {
- if (offset + bytes_written > offset_) {
+ if (received_slice_offset <= starting_file_write_offset_) {
+ // If validation has completed, mark the stream as finished if the file
+ // write position already has data.
+ if (received_slice_offset + bytes_written > starting_file_write_offset_ &&
+ GetRemainingBytesToValidate() == 0) {
length_ = kNoBytesToWrite;
finished_ = true;
}
@@ -92,8 +110,12 @@ void DownloadFileImpl::SourceStream::TruncateLengthWithWrittenDataBlock(
}
if (length_ == DownloadSaveInfo::kLengthFullContent ||
- length_ > offset - offset_) {
- length_ = offset - offset_;
+ (length_ > received_slice_offset - offset_ &&
+ length_ > starting_file_write_offset_ - offset_)) {
+ // Stream length should always include the validation data, unless the
+ // response is too short.
+ length_ =
+ std::max(received_slice_offset, starting_file_write_offset_) - offset_;
}
}
@@ -123,23 +145,15 @@ InputStream::StreamState DownloadFileImpl::SourceStream::Read(
return input_stream_->Read(data, length);
}
-DownloadFileImpl::DownloadFileImpl(
- std::unique_ptr<DownloadSaveInfo> save_info,
- const base::FilePath& default_download_directory,
- std::unique_ptr<InputStream> stream,
- uint32_t download_id,
- base::WeakPtr<DownloadDestinationObserver> observer)
- : DownloadFileImpl(std::move(save_info),
- default_download_directory,
- download_id,
- observer) {
- source_streams_[save_info_->offset] = std::make_unique<SourceStream>(
- save_info_->offset, save_info_->length, std::move(stream));
+size_t DownloadFileImpl::SourceStream::GetRemainingBytesToValidate() {
+ int64_t bytes_remaining = starting_file_write_offset_ - offset_ - bytes_read_;
+ return bytes_remaining < 0 ? 0 : bytes_remaining;
}
DownloadFileImpl::DownloadFileImpl(
std::unique_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_download_directory,
+ std::unique_ptr<InputStream> stream,
uint32_t download_id,
base::WeakPtr<DownloadDestinationObserver> observer)
: file_(download_id),
@@ -161,6 +175,10 @@ DownloadFileImpl::DownloadFileImpl(
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("download", "DownloadFileActive",
download_id);
+ source_streams_[save_info_->offset] = std::make_unique<SourceStream>(
+ save_info_->offset, save_info_->length,
+ save_info_->GetStartingFileWriteOffset(), std::move(stream));
+
DETACH_FROM_SEQUENCE(sequence_checker_);
}
@@ -194,7 +212,7 @@ void DownloadFileImpl::Initialize(
bytes_so_far += received_slice.received_bytes;
}
} else {
- bytes_so_far = save_info_->offset;
+ bytes_so_far = save_info_->GetStartingFileWriteOffset();
}
int64_t bytes_wasted = 0;
DownloadInterruptReason reason = file_.Initialize(
@@ -237,7 +255,7 @@ void DownloadFileImpl::AddInputStream(std::unique_ptr<InputStream> stream,
}
DCHECK(source_streams_.find(offset) == source_streams_.end());
source_streams_[offset] =
- std::make_unique<SourceStream>(offset, length, std::move(stream));
+ std::make_unique<SourceStream>(offset, length, offset, std::move(stream));
OnSourceStreamAdded(source_streams_[offset].get());
}
@@ -254,46 +272,73 @@ void DownloadFileImpl::OnSourceStreamAdded(SourceStream* source_stream) {
RegisterAndActivateStream(source_stream);
}
-DownloadInterruptReason DownloadFileImpl::WriteDataToFile(int64_t offset,
- const char* data,
- size_t data_len) {
+DownloadInterruptReason DownloadFileImpl::ValidateAndWriteDataToFile(
+ int64_t offset,
+ const char* data,
+ size_t bytes_to_validate,
+ size_t bytes_to_write) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- WillWriteToDisk(data_len);
- return file_.WriteDataToFile(offset, data, data_len);
+ // Check if some of the data is for validation purpose.
+ if (bytes_to_validate > 0 &&
+ !file_.ValidateDataInFile(offset, data, bytes_to_validate)) {
+ return DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH;
+ }
+ // If there is no data to write, just return DOWNLOAD_INTERRUPT_REASON_NONE
+ // and read the next chunk.
+ if (bytes_to_write <= 0)
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
+ // Write the remaining data to disk.
+ WillWriteToDisk(bytes_to_write);
+ return file_.WriteDataToFile(offset + bytes_to_validate,
+ data + bytes_to_validate, bytes_to_write);
}
bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream,
size_t bytes_available_to_write,
+ size_t* bytes_to_validate,
size_t* bytes_to_write) {
+ *bytes_to_validate = 0;
if (source_stream->length() == kNoBytesToWrite) {
*bytes_to_write = 0;
return true;
}
+ // First calculate the number of bytes to validate.
+ *bytes_to_write = bytes_available_to_write;
+ size_t remaining_bytes_to_validate =
+ source_stream->GetRemainingBytesToValidate();
+ if (remaining_bytes_to_validate > 0) {
+ *bytes_to_validate =
+ std::min(remaining_bytes_to_validate, bytes_available_to_write);
+ *bytes_to_write -= *bytes_to_validate;
+ }
+ if (source_stream->length() != DownloadSaveInfo::kLengthFullContent &&
+ source_stream->bytes_read() +
+ static_cast<int64_t>(bytes_available_to_write) >
+ source_stream->length()) {
+ // Total bytes to consume is capped by the length of the stream.
+ int64_t bytes_to_consume =
+ source_stream->length() - source_stream->bytes_read();
+ // The validation data should always be streamed.
+ DCHECK_GE(bytes_to_consume, static_cast<int64_t>(*bytes_to_validate));
+ *bytes_to_write = bytes_to_consume - *bytes_to_validate;
+ return true;
+ }
+
// If a new slice finds that its target position has already been written,
- // terminate the stream.
- if (source_stream->bytes_written() == 0) {
+ // terminate the stream if there are no bytes to validate.
+ if (source_stream->bytes_written() == 0 && *bytes_to_write > 0) {
for (const auto& received_slice : received_slices_) {
- if (received_slice.offset <= source_stream->offset() &&
+ if (received_slice.offset <=
+ source_stream->starting_file_write_offset() &&
received_slice.offset + received_slice.received_bytes >
- source_stream->offset()) {
+ source_stream->starting_file_write_offset()) {
*bytes_to_write = 0;
return true;
}
}
}
- if (source_stream->length() != DownloadSaveInfo::kLengthFullContent &&
- source_stream->bytes_written() +
- static_cast<int64_t>(bytes_available_to_write) >
- source_stream->length()) {
- // Write a partial buffer as the incoming data exceeds the length limit.
- *bytes_to_write = source_stream->length() - source_stream->bytes_written();
- return true;
- }
-
- *bytes_to_write = bytes_available_to_write;
return false;
}
@@ -331,8 +376,12 @@ void DownloadFileImpl::CreateIntermediateUriForPublish(
DownloadCollectionBridge::CreateIntermediateUriForPublish(
original_url, referrer_url, file_name, mime_type);
DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
- if (!content_path.empty())
+ if (!content_path.empty()) {
reason = file_.Rename(content_path);
+ display_name_ = DownloadCollectionBridge::GetDisplayName(content_path);
+ }
+ if (display_name_.empty())
+ display_name_ = file_name;
OnRenameComplete(reason, content_path, callback);
}
@@ -341,6 +390,10 @@ void DownloadFileImpl::PublishDownload(
DownloadInterruptReason reason = file_.PublishDownload();
OnRenameComplete(reason, file_.full_path(), callback);
}
+
+base::FilePath DownloadFileImpl::GetDisplayName() {
+ return display_name_;
+}
#endif // defined(OS_ANDROID)
base::TimeDelta DownloadFileImpl::GetRetryDelayForFailedRename(
@@ -363,8 +416,9 @@ DownloadInterruptReason DownloadFileImpl::HandleStreamCompletionStatus(
DownloadInterruptReason reason = source_stream->GetCompletionStatus();
if (source_stream->length() == DownloadSaveInfo::kLengthFullContent &&
!received_slices_.empty() &&
- (source_stream->offset() == received_slices_.back().offset +
- received_slices_.back().received_bytes) &&
+ (source_stream->starting_file_write_offset() ==
+ received_slices_.back().offset +
+ received_slices_.back().received_bytes) &&
reason == DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE) {
// We are probably reaching the end of the stream, don't treat this
// as an error.
@@ -510,6 +564,7 @@ void DownloadFileImpl::StreamActive(SourceStream* source_stream,
size_t incoming_data_size = 0;
size_t total_incoming_data_size = 0;
size_t num_buffers = 0;
+ size_t bytes_to_validate = 0;
size_t bytes_to_write = 0;
bool should_terminate = false;
InputStream::StreamState state(InputStream::EMPTY);
@@ -526,24 +581,26 @@ void DownloadFileImpl::StreamActive(SourceStream* source_stream,
break;
case InputStream::HAS_DATA: {
++num_buffers;
- should_terminate = CalculateBytesToWrite(
- source_stream, incoming_data_size, &bytes_to_write);
+ should_terminate =
+ CalculateBytesToWrite(source_stream, incoming_data_size,
+ &bytes_to_validate, &bytes_to_write);
DCHECK_GE(incoming_data_size, bytes_to_write);
- reason = WriteDataToFile(
- source_stream->offset() + source_stream->bytes_written(),
- incoming_data->data(), bytes_to_write);
+ reason = ValidateAndWriteDataToFile(
+ source_stream->offset() + source_stream->bytes_read(),
+ incoming_data->data(), bytes_to_validate, bytes_to_write);
bytes_seen_ += bytes_to_write;
- total_incoming_data_size += bytes_to_write;
+ total_incoming_data_size += incoming_data_size;
if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) {
int64_t prev_bytes_written = source_stream->bytes_written();
- source_stream->OnWriteBytesToDisk(bytes_to_write);
+ source_stream->OnBytesConsumed(incoming_data_size, bytes_to_write);
if (!IsSparseFile())
break;
// If the write operation creates a new slice, add it to the
// |received_slices_| and update all the entries in
// |source_streams_|.
if (bytes_to_write > 0 && prev_bytes_written == 0) {
- AddNewSlice(source_stream->offset(), bytes_to_write);
+ AddNewSlice(source_stream->starting_file_write_offset(),
+ bytes_to_write);
} else {
received_slices_[source_stream->index()].received_bytes +=
bytes_to_write;
@@ -613,7 +670,7 @@ void DownloadFileImpl::NotifyObserver(SourceStream* source_stream,
}
SetPotentialFileLength(source_stream->offset() +
- source_stream->bytes_written());
+ source_stream->bytes_read());
}
num_active_streams_--;
@@ -700,10 +757,10 @@ void DownloadFileImpl::AddNewSlice(int64_t offset, int64_t length) {
// Update the index of exising SourceStreams.
for (auto& stream : source_streams_) {
SourceStream* source_stream = stream.second.get();
- if (source_stream->offset() > offset) {
+ if (source_stream->starting_file_write_offset() > offset) {
if (slice_added && source_stream->bytes_written() > 0)
source_stream->set_index(source_stream->index() + 1);
- } else if (source_stream->offset() == offset) {
+ } else if (source_stream->starting_file_write_offset() == offset) {
source_stream->set_index(index);
} else {
source_stream->TruncateLengthWithWrittenDataBlock(offset, length);
@@ -738,26 +795,29 @@ void DownloadFileImpl::HandleStreamError(SourceStream* source_stream,
source_stream->set_finished(true);
num_active_streams_--;
- // If previous stream has already written data at the starting offset of
- // the error stream. The download can complete.
- bool can_recover_from_error = (source_stream->length() == kNoBytesToWrite);
-
- // See if the previous stream can download the full content.
- // If the current stream has written some data, length of all preceding
- // streams will be truncated.
- if (IsSparseFile() && !can_recover_from_error) {
- SourceStream* preceding_neighbor = FindPrecedingNeighbor(source_stream);
- while (preceding_neighbor) {
- if (CanRecoverFromError(source_stream, preceding_neighbor)) {
- can_recover_from_error = true;
- break;
- }
+ bool can_recover_from_error = false;
+ if (reason != DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH) {
+ // If previous stream has already written data at the starting offset of
+ // the error stream. The download can complete.
+ can_recover_from_error = (source_stream->length() == kNoBytesToWrite);
+
+ // See if the previous stream can download the full content.
+ // If the current stream has written some data, length of all preceding
+ // streams will be truncated.
+ if (IsSparseFile() && !can_recover_from_error) {
+ SourceStream* preceding_neighbor = FindPrecedingNeighbor(source_stream);
+ while (preceding_neighbor) {
+ if (CanRecoverFromError(source_stream, preceding_neighbor)) {
+ can_recover_from_error = true;
+ break;
+ }
- // If the neighbor cannot recover the error and it has already created
- // a slice, just interrupt the download.
- if (preceding_neighbor->bytes_written() > 0)
- break;
- preceding_neighbor = FindPrecedingNeighbor(preceding_neighbor);
+ // If the neighbor cannot recover the error and it has already created
+ // a slice, just interrupt the download.
+ if (preceding_neighbor->bytes_written() > 0)
+ break;
+ preceding_neighbor = FindPrecedingNeighbor(preceding_neighbor);
+ }
}
}
@@ -786,8 +846,9 @@ DownloadFileImpl::SourceStream* DownloadFileImpl::FindPrecedingNeighbor(
int64_t max_preceding_offset = 0;
SourceStream* ret = nullptr;
for (auto& stream : source_streams_) {
- int64_t offset = stream.second->offset();
- if (offset < source_stream->offset() && offset >= max_preceding_offset) {
+ int64_t offset = stream.second->starting_file_write_offset();
+ if (offset < source_stream->starting_file_write_offset() &&
+ offset >= max_preceding_offset) {
ret = stream.second.get();
max_preceding_offset = offset;
}
@@ -807,6 +868,9 @@ void DownloadFileImpl::DebugStates() const {
DVLOG(1) << "Total source stream count = " << source_streams_.size();
for (const auto& stream : source_streams_) {
DVLOG(1) << "Source stream, offset = " << stream.second->offset()
+ << " , bytes_read = " << stream.second->bytes_read()
+ << " , starting_file_write_offset = "
+ << stream.second->starting_file_write_offset()
<< " , bytes_written = " << stream.second->bytes_written()
<< " , is_finished = " << stream.second->is_finished()
<< " , length = " << stream.second->length()
diff --git a/chromium/components/download/internal/common/download_file_unittest.cc b/chromium/components/download/internal/common/download_file_unittest.cc
index fb89b4c5797..a3d72dc2be9 100644
--- a/chromium/components/download/internal/common/download_file_unittest.cc
+++ b/chromium/components/download/internal/common/download_file_unittest.cc
@@ -192,15 +192,22 @@ class DownloadFileTest : public testing::Test {
closure.Run();
}
- bool CreateDownloadFile(int offset, bool calculate_hash) {
- return CreateDownloadFile(offset, 0, calculate_hash,
- DownloadItem::ReceivedSlices());
+ bool CreateDownloadFile(bool calculate_hash) {
+ return CreateDownloadFile(0, calculate_hash, DownloadItem::ReceivedSlices(),
+ -1);
}
- bool CreateDownloadFile(int offset,
- int length,
+ bool CreateDownloadFile(int length,
bool calculate_hash,
const DownloadItem::ReceivedSlices& received_slices) {
+ return CreateDownloadFile(length, calculate_hash,
+ DownloadItem::ReceivedSlices(), -1);
+ }
+
+ bool CreateDownloadFile(int length,
+ bool calculate_hash,
+ const DownloadItem::ReceivedSlices& received_slices,
+ int file_offset) {
// There can be only one.
DCHECK(!download_file_);
@@ -213,8 +220,23 @@ class DownloadFileTest : public testing::Test {
.RetiresOnSaturation();
std::unique_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
- save_info->offset = offset;
+ // Fill the file by repeatedly copying |kTestData1| if |file_offset| is
+ // positive.
+ if (file_offset > 0) {
+ base::CreateTemporaryFileInDir(download_dir_.GetPath(),
+ &save_info->file_path);
+ int len = file_offset;
+ int data_len = strlen(kTestData1);
+ while (len > 0) {
+ int bytes_to_write = len > data_len ? data_len : len;
+ base::AppendToFile(save_info->file_path, kTestData1, bytes_to_write);
+ len -= bytes_to_write;
+ }
+ }
+
+ save_info->offset = 0;
save_info->length = length;
+ save_info->file_offset = file_offset;
download_file_.reset(new TestDownloadFileImpl(
std::move(save_info), download_dir_.GetPath(),
@@ -462,6 +484,9 @@ class DownloadFileTest : public testing::Test {
int64_t bytes_;
int64_t bytes_per_sec_;
+ // Keep track of what data should be saved to the disk file.
+ std::string expected_data_;
+
private:
void SetRenameResult(const base::Closure& closure,
DownloadInterruptReason* reason_p,
@@ -476,9 +501,6 @@ class DownloadFileTest : public testing::Test {
}
base::test::ScopedTaskEnvironment scoped_task_environment_;
-
- // Keep track of what data should be saved to the disk file.
- std::string expected_data_;
};
// DownloadFile::RenameAndAnnotate and DownloadFile::RenameAndUniquify have a
@@ -531,7 +553,7 @@ const int DownloadFileTest::kDummyRequestId = 67;
// Rename the file before any data is downloaded, after some has, after it all
// has, and after it's closed.
TEST_P(DownloadFileTestWithRename, RenameFileFinal) {
- ASSERT_TRUE(CreateDownloadFile(0, true));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
EXPECT_TRUE(base::PathExists(initial_path));
base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
@@ -601,7 +623,7 @@ TEST_P(DownloadFileTestWithRename, RenameFileFinal) {
// the above test because it only applies to RenameAndAnnotate().
// RenameAndUniquify() doesn't overwrite by design.
TEST_F(DownloadFileTest, RenameOverwrites) {
- ASSERT_TRUE(CreateDownloadFile(0, true));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
EXPECT_TRUE(base::PathExists(initial_path));
base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
@@ -631,7 +653,7 @@ TEST_F(DownloadFileTest, RenameOverwrites) {
// DownloadFileTestWithRename test because this only applies to
// RenameAndUniquify().
TEST_F(DownloadFileTest, RenameUniquifies) {
- ASSERT_TRUE(CreateDownloadFile(0, true));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
EXPECT_TRUE(base::PathExists(initial_path));
base::FilePath path_1(initial_path.InsertBeforeExtensionASCII("_1"));
@@ -654,7 +676,7 @@ TEST_F(DownloadFileTest, RenameUniquifies) {
// Test that RenameAndUniquify doesn't try to uniquify in the case where the
// target filename is the same as the current filename.
TEST_F(DownloadFileTest, RenameRecognizesSelfConflict) {
- ASSERT_TRUE(CreateDownloadFile(0, true));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
EXPECT_TRUE(base::PathExists(initial_path));
@@ -671,7 +693,7 @@ TEST_F(DownloadFileTest, RenameRecognizesSelfConflict) {
// Test to make sure we get the proper error on failure.
TEST_P(DownloadFileTestWithRename, RenameError) {
- ASSERT_TRUE(CreateDownloadFile(0, true));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
// Create a subdirectory.
@@ -726,7 +748,7 @@ void TestRenameCompletionCallback(const base::Closure& closure,
// 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));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
// Create a subdirectory.
@@ -797,7 +819,7 @@ TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) {
// Various tests of the StreamActive method.
TEST_F(DownloadFileTest, StreamEmptySuccess) {
- ASSERT_TRUE(CreateDownloadFile(0, true));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
EXPECT_TRUE(base::PathExists(initial_path));
@@ -813,7 +835,7 @@ TEST_F(DownloadFileTest, StreamEmptySuccess) {
}
TEST_F(DownloadFileTest, StreamEmptyError) {
- ASSERT_TRUE(CreateDownloadFile(0, true));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
EXPECT_TRUE(base::PathExists(initial_path));
@@ -842,7 +864,7 @@ TEST_F(DownloadFileTest, StreamEmptyError) {
}
TEST_F(DownloadFileTest, StreamNonEmptySuccess) {
- ASSERT_TRUE(CreateDownloadFile(0, true));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
EXPECT_TRUE(base::PathExists(initial_path));
@@ -858,7 +880,7 @@ TEST_F(DownloadFileTest, StreamNonEmptySuccess) {
}
TEST_F(DownloadFileTest, StreamNonEmptyError) {
- ASSERT_TRUE(CreateDownloadFile(0, true));
+ ASSERT_TRUE(CreateDownloadFile(true));
base::FilePath initial_path(download_file_->FullPath());
EXPECT_TRUE(base::PathExists(initial_path));
@@ -888,6 +910,58 @@ TEST_F(DownloadFileTest, StreamNonEmptyError) {
DestroyDownloadFile(0);
}
+// Tests that if file content validation succeeds, all the remaining data will
+// be writing to the file.
+TEST_F(DownloadFileTest, FileContentValidationSuccess) {
+ int stream_length = strlen(kTestData1) * 2;
+
+ ASSERT_TRUE(CreateDownloadFile(
+ stream_length /* length */, true /* calculate_hash */,
+ DownloadItem::ReceivedSlices(), strlen(kTestData1) - 1));
+ base::FilePath initial_path(download_file_->FullPath());
+ EXPECT_TRUE(base::PathExists(initial_path));
+
+ const char* chunks1[] = {kTestData1, kTestData1};
+ ::testing::Sequence s1;
+ SetupDataAppend(chunks1, 2 /* num_chunks */, input_stream_, s1);
+ SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_, s1);
+ EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
+ sink_callback_.Run(MOJO_RESULT_OK);
+ VerifyStreamAndSize();
+ base::RunLoop().RunUntilIdle();
+ DestroyDownloadFile(0);
+}
+
+// Tests that if file content validation fails, an error will occur and no data
+// will be written.
+TEST_F(DownloadFileTest, FileContentValidationFail) {
+ int file_length = strlen(kTestData2) - 1;
+ int stream_length = strlen(kTestData1) + strlen(kTestData2);
+
+ ASSERT_TRUE(CreateDownloadFile(stream_length /* length */,
+ true /* calculate_hash */,
+ DownloadItem::ReceivedSlices(), file_length));
+ base::FilePath initial_path(download_file_->FullPath());
+ EXPECT_TRUE(base::PathExists(initial_path));
+ std::string file_content = std::string(kTestData1, 0, file_length);
+ expected_data_ = file_content;
+ VerifyStreamAndSize();
+
+ const char* chunks1[] = {kTestData2, kTestData1};
+ ::testing::Sequence s1;
+ // Only 1 chunk will be read, and it will generate an error after
+ // failing the validation.
+ SetupDataAppend(chunks1, 1 /* num_chunks */, input_stream_, s1);
+ EXPECT_CALL(*input_stream_, ClearDataReadyCallback());
+ EXPECT_CALL(*(observer_.get()),
+ MockDestinationError(DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH,
+ file_length, _));
+ sink_callback_.Run(MOJO_RESULT_OK);
+ base::RunLoop().RunUntilIdle();
+ expected_data_ = file_content;
+ DestroyDownloadFile(0);
+}
+
// Tests for concurrent streams handling, used for parallel download.
//
// Activate both streams at the same time.
@@ -895,7 +969,7 @@ TEST_F(DownloadFileTest, MultipleStreamsWrite) {
int64_t stream_0_length = GetBuffersLength(kTestData6, 2);
int64_t stream_1_length = GetBuffersLength(kTestData7, 2);
- ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true,
+ ASSERT_TRUE(CreateDownloadFile(stream_0_length, true,
DownloadItem::ReceivedSlices()));
PrepareStream(&input_stream_, 0, false, true, kTestData6, 2);
@@ -934,7 +1008,7 @@ TEST_F(DownloadFileTest, MutipleStreamsLimitedLength) {
// "Range:50-".
int64_t stream_2_length = GetBuffersLength(kTestData6, 2);
- ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true,
+ ASSERT_TRUE(CreateDownloadFile(stream_0_length, true,
DownloadItem::ReceivedSlices()));
PrepareStream(&input_stream_, 0, false, true, kTestData6, 2);
@@ -986,7 +1060,7 @@ TEST_F(DownloadFileTest, MutipleStreamsLimitedLength) {
TEST_F(DownloadFileTest, MultipleStreamsFirstStreamWriteAllData) {
int64_t stream_0_length = GetBuffersLength(kTestData8, 4);
- ASSERT_TRUE(CreateDownloadFile(0, DownloadSaveInfo::kLengthFullContent, true,
+ ASSERT_TRUE(CreateDownloadFile(DownloadSaveInfo::kLengthFullContent, true,
DownloadItem::ReceivedSlices()));
PrepareStream(&input_stream_, 0, false, true, kTestData8, 4);
@@ -1019,7 +1093,7 @@ TEST_F(DownloadFileTest, MultipleStreamsFirstStreamWriteAllData) {
TEST_F(DownloadFileTest, SecondStreamStartingOffsetAlreadyWritten) {
int64_t stream_0_length = GetBuffersLength(kTestData6, 2);
- ASSERT_TRUE(CreateDownloadFile(0, stream_0_length, true,
+ ASSERT_TRUE(CreateDownloadFile(stream_0_length, true,
DownloadItem::ReceivedSlices()));
Sequence seq;
diff --git a/chromium/components/download/internal/common/download_item_impl.cc b/chromium/components/download/internal/common/download_item_impl.cc
index b1bc7b7d249..bd90ec09ce9 100644
--- a/chromium/components/download/internal/common/download_item_impl.cc
+++ b/chromium/components/download/internal/common/download_item_impl.cc
@@ -46,6 +46,7 @@
#include "components/download/internal/common/download_job_impl.h"
#include "components/download/internal/common/parallel_download_utils.h"
#include "components/download/public/common/download_danger_type.h"
+#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_file.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item_impl_delegate.h"
@@ -225,6 +226,7 @@ DownloadItemImpl::RequestInfo::RequestInfo(
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& suggested_filename,
const base::FilePath& forced_file_path,
ui::PageTransition transition_type,
@@ -236,6 +238,7 @@ DownloadItemImpl::RequestInfo::RequestInfo(
site_url(site_url),
tab_url(tab_url),
tab_referrer_url(tab_referrer_url),
+ request_initiator(request_initiator),
suggested_filename(suggested_filename),
forced_file_path(forced_file_path),
transition_type(transition_type),
@@ -290,6 +293,7 @@ DownloadItemImpl::DownloadItemImpl(
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_refererr_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -314,6 +318,7 @@ DownloadItemImpl::DownloadItemImpl(
site_url,
tab_url,
tab_refererr_url,
+ request_initiator,
std::string(),
base::FilePath(),
ui::PAGE_TRANSITION_LINK,
@@ -363,6 +368,7 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
info.site_url,
info.tab_url,
info.tab_referrer_url,
+ info.request_initiator,
base::UTF16ToUTF8(info.save_info->suggested_name),
info.save_info->file_path,
info.transition_type ? info.transition_type.value()
@@ -421,7 +427,7 @@ DownloadItemImpl::DownloadItemImpl(
weak_ptr_factory_(this) {
job_ = DownloadJobFactory::CreateJob(this, std::move(request_handle),
DownloadCreateInfo(), true, nullptr,
- nullptr);
+ nullptr, nullptr);
delegate_->Attach();
Init(true /* actively downloading */, TYPE_SAVE_PAGE_AS);
}
@@ -796,6 +802,11 @@ const GURL& DownloadItemImpl::GetTabReferrerUrl() const {
return request_info_.tab_referrer_url;
}
+const base::Optional<url::Origin>& DownloadItemImpl::GetRequestInitiator()
+ const {
+ return request_info_.request_initiator;
+}
+
std::string DownloadItemImpl::GetSuggestedFilename() const {
return request_info_.suggested_filename;
}
@@ -986,8 +997,7 @@ bool DownloadItemImpl::CanOpenDownload() {
// they aren't owned by the download system.
const bool is_complete = GetState() == DownloadItem::COMPLETE;
return (!IsDone() || is_complete) && !IsTemporary() &&
- !file_externally_removed_ &&
- delegate_->IsMostRecentDownloadItemAtFilePath(this);
+ !file_externally_removed_;
}
bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() {
@@ -1133,8 +1143,10 @@ ResumeMode DownloadItemImpl::GetResumeMode() const {
// We also can't continue if we don't have some verifier to make sure
// we're getting the same file.
bool restart_required =
- (GetFullPath().empty() || (etag_.empty() && last_modified_time_.empty()));
-
+ (GetFullPath().empty() ||
+ (!HasStrongValidators() &&
+ !base::FeatureList::IsEnabled(
+ features::kAllowDownloadResumptionWithoutStrongValidators)));
// We won't auto-restart if we've used up our attempts or the
// download has been paused by user action.
bool user_action_required =
@@ -1144,6 +1156,10 @@ ResumeMode DownloadItemImpl::GetResumeMode() const {
user_action_required);
}
+bool DownloadItemImpl::HasStrongValidators() const {
+ return !etag_.empty() || !last_modified_time_.empty();
+}
+
void DownloadItemImpl::UpdateValidatorsOnResumption(
const DownloadCreateInfo& new_create_info) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -1167,10 +1183,24 @@ void DownloadItemImpl::UpdateValidatorsOnResumption(
// a full request rather than a partial. Full restarts clobber validators.
if (etag_ != new_create_info.etag ||
last_modified_time_ != new_create_info.last_modified) {
+ if (destination_info_.received_bytes > 0) {
+ RecordResumptionRestartCount(
+ ResumptionRestartCountTypes::kStrongValidatorChangesCount);
+ }
received_slices_.clear();
destination_info_.received_bytes = 0;
}
+ if (destination_info_.received_bytes > 0 && new_create_info.offset == 0) {
+ if (!base::FeatureList::IsEnabled(
+ features::kAllowDownloadResumptionWithoutStrongValidators) ||
+ GetDownloadValidationLengthConfig() >
+ destination_info_.received_bytes) {
+ RecordResumptionRestartCount(
+ ResumptionRestartCountTypes::kRequestedByServerCount);
+ }
+ }
+
request_info_.url_chain.insert(request_info_.url_chain.end(), chain_iter,
new_create_info.url_chain.end());
etag_ = new_create_info.etag;
@@ -1398,7 +1428,8 @@ void DownloadItemImpl::Start(
download_file_ = std::move(file);
job_ = DownloadJobFactory::CreateJob(
this, std::move(req_handle), new_create_info, false,
- std::move(url_loader_factory_getter), url_request_context_getter);
+ std::move(url_loader_factory_getter), url_request_context_getter,
+ delegate_ ? delegate_->GetServiceManagerConnector() : nullptr);
if (job_->IsParallelizable()) {
RecordParallelizableDownloadCount(START_COUNT, IsParallelDownloadEnabled());
}
@@ -1644,9 +1675,9 @@ void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
#if defined(OS_ANDROID)
// For content URIs, target file path is the same as the current path.
if (full_path.IsContentUri()) {
- if (display_name_.empty())
- SetDisplayName(GetTargetFilePath().BaseName());
destination_info_.target_path = full_path;
+ if (display_name_.empty())
+ SetDisplayName(download_file_->GetDisplayName());
}
#endif // defined(OS_ANDROID)
} else {
@@ -1833,7 +1864,8 @@ void DownloadItemImpl::Completed() {
bool is_parallelizable = job_ && job_->IsParallelizable();
RecordDownloadCompleted(GetReceivedBytes(), is_parallelizable,
- download_source_);
+ download_source_, has_resumed_,
+ HasStrongValidators());
if (!delegate_->IsOffTheRecord()) {
RecordDownloadCountWithSource(COMPLETED_COUNT_NORMAL_PROFILE,
download_source_);
@@ -2312,6 +2344,13 @@ void DownloadItemImpl::ResumeInterruptedDownload(
mode == ResumeMode::USER_RESTART) {
LOG_IF(ERROR, !GetFullPath().empty())
<< "Download full path should be empty before resumption";
+ if (destination_info_.received_bytes > 0) {
+ if (!HasStrongValidators()) {
+ RecordResumptionRestartCount(
+ ResumptionRestartCountTypes::kMissingStrongValidatorsCount);
+ }
+ RecordResumptionRestartReason(last_reason_);
+ }
destination_info_.received_bytes = 0;
last_modified_time_.clear();
etag_.clear();
@@ -2363,6 +2402,17 @@ void DownloadItemImpl::ResumeInterruptedDownload(
download_params->set_hash_of_partial_file(GetHash());
download_params->set_hash_state(std::move(hash_state_));
download_params->set_guid(guid_);
+ if (!HasStrongValidators() && download_params->offset() > 0 &&
+ base::FeatureList::IsEnabled(
+ features::kAllowDownloadResumptionWithoutStrongValidators)) {
+ download_params->set_use_if_range(false);
+ download_params->set_file_offset(download_params->offset());
+ int64_t validation_length = GetDownloadValidationLengthConfig();
+ download_params->set_offset(download_params->offset() > validation_length
+ ? download_params->offset() -
+ validation_length
+ : 0);
+ }
// TODO(xingliu): Read |fetch_error_body| and |request_headers_| from the
// cache, and don't copy them into DownloadItemImpl.
@@ -2391,10 +2441,12 @@ void DownloadItemImpl::ResumeInterruptedDownload(
DownloadUkmHelper::RecordDownloadResumed(ukm_download_id_, GetResumeMode(),
time_since_start);
+ RecordDownloadResumed(HasStrongValidators());
delegate_->ResumeInterruptedDownload(std::move(download_params),
request_info_.site_url);
+ has_resumed_ = true;
if (job_)
job_->Resume(false);
}
diff --git a/chromium/components/download/internal/common/download_item_impl_delegate.cc b/chromium/components/download/internal/common/download_item_impl_delegate.cc
index cc3fb6af5dd..f5dff20abdc 100644
--- a/chromium/components/download/internal/common/download_item_impl_delegate.cc
+++ b/chromium/components/download/internal/common/download_item_impl_delegate.cc
@@ -103,4 +103,9 @@ bool DownloadItemImplDelegate::IsActiveNetworkMetered() const {
void DownloadItemImplDelegate::ReportBytesWasted(DownloadItemImpl* download) {}
+service_manager::Connector*
+DownloadItemImplDelegate::GetServiceManagerConnector() {
+ return nullptr;
+}
+
} // namespace download
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 02488f1ed77..f202fda37a0 100644
--- a/chromium/components/download/internal/common/download_item_impl_unittest.cc
+++ b/chromium/components/download/internal/common/download_item_impl_unittest.cc
@@ -14,7 +14,6 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/callback_helpers.h"
#include "base/containers/circular_deque.h"
#include "base/containers/queue.h"
#include "base/files/file_util.h"
@@ -242,7 +241,7 @@ class DownloadItemTest : public testing::Test {
DownloadItemTest()
: task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::UI,
- base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
+ base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
next_download_id_(DownloadItem::kInvalidId + 1) {
create_info_.reset(new DownloadCreateInfo());
create_info_->save_info =
@@ -849,10 +848,10 @@ TEST_F(DownloadItemTest, AutomaticResumption_AttemptLimit) {
EXPECT_CALL(*mock_download_file_ref, RenameAndUniquify(_, _)).Times(i == 0);
ASSERT_FALSE(callback.is_null());
- base::ResetAndReturn(&callback).Run(
- target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
- DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path,
- DOWNLOAD_INTERRUPT_REASON_NONE);
+ std::move(callback).Run(target_path,
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ intermediate_path, DOWNLOAD_INTERRUPT_REASON_NONE);
task_environment_.RunUntilIdle();
// Use a continuable interrupt.
diff --git a/chromium/components/download/internal/common/download_job_factory.cc b/chromium/components/download/internal/common/download_job_factory.cc
index f3cea3aef72..0c351882c8f 100644
--- a/chromium/components/download/internal/common/download_job_factory.cc
+++ b/chromium/components/download/internal/common/download_job_factory.cc
@@ -98,7 +98,8 @@ std::unique_ptr<DownloadJob> DownloadJobFactory::CreateJob(
bool is_save_package_download,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter) {
+ net::URLRequestContextGetter* url_request_context_getter,
+ service_manager::Connector* connector) {
if (is_save_package_download) {
return std::make_unique<SavePackageDownloadJob>(download_item,
std::move(req_handle));
@@ -109,7 +110,8 @@ 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(url_loader_factory_getter), url_request_context_getter);
+ std::move(url_loader_factory_getter), url_request_context_getter,
+ connector);
}
// An ordinary download job.
diff --git a/chromium/components/download/internal/common/download_path_reservation_tracker.cc b/chromium/components/download/internal/common/download_path_reservation_tracker.cc
index 5c02e27b657..8a4004127f7 100644
--- a/chromium/components/download/internal/common/download_path_reservation_tracker.cc
+++ b/chromium/components/download/internal/common/download_path_reservation_tracker.cc
@@ -26,6 +26,7 @@
#include "base/third_party/icu/icu_utf.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_item.h"
#include "components/filename_generation/filename_generation.h"
#include "net/base/filename_util.h"
@@ -57,10 +58,6 @@ const size_t kZoneIdentifierLength = sizeof(":Zone.Identifier") - 1;
// Map of download path reservations. Each reserved path is associated with a
// ReservationKey=DownloadItem*. This object is destroyed in |Revoke()| when
// there are no more reservations.
-//
-// It is not an error, although undesirable, to have multiple DownloadItem*s
-// that are mapped to the same path. This can happen if a reservation is created
-// that is supposed to overwrite an existing reservation.
ReservationMap* g_reservation_map = NULL;
base::LazySequencedTaskRunner g_sequenced_task_runner =
@@ -122,6 +119,21 @@ bool IsFileNameInUse(const base::FilePath& path) {
return false;
}
+// Returns true if the given path is in use by a path reservation,
+// and has a different key then the item arg.
+bool IsAdditionalPathReserved(const base::FilePath& path, DownloadItem* item) {
+ if (!g_reservation_map)
+ return false;
+
+ for (ReservationMap::const_iterator iter = g_reservation_map->begin();
+ iter != g_reservation_map->end(); ++iter) {
+ if (iter->first != item && base::FilePath::CompareEqualIgnoreCase(
+ iter->second.value(), path.value()))
+ return true;
+ }
+ return false;
+}
+
// Returns true if the given path is in use by any path reservation or the
// file system. Called on the task runner returned by
// DownloadPathReservationTracker::GetTaskRunner().
@@ -238,6 +250,11 @@ PathValidationResult ResolveReservationConflicts(
: PathValidationResult::CONFLICT;
case DownloadPathReservationTracker::OVERWRITE:
+ if (base::FeatureList::IsEnabled(
+ features::kPreventDownloadsWithSamePath) &&
+ IsPathReserved(*target_path)) {
+ return PathValidationResult::CONFLICT;
+ }
return PathValidationResult::SUCCESS;
case DownloadPathReservationTracker::PROMPT:
@@ -520,4 +537,11 @@ DownloadPathReservationTracker::GetTaskRunner() {
return g_sequenced_task_runner.Get();
}
+// static
+bool DownloadPathReservationTracker::CheckDownloadPathForExistingDownload(
+ const base::FilePath& target_path,
+ DownloadItem* download_item) {
+ return IsAdditionalPathReserved(target_path, download_item);
+}
+
} // namespace download
diff --git a/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc b/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc
index acdffd42f45..1b6ccde7434 100644
--- a/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc
+++ b/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc
@@ -15,10 +15,12 @@
#include "base/observer_list.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/test_file_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_path_reservation_tracker.h"
#include "components/download/public/common/mock_download_item.h"
#include "net/base/filename_util.h"
@@ -352,6 +354,12 @@ TEST_F(DownloadPathReservationTrackerTest, ConflictWithSource) {
// Multiple reservations for the same path should uniquify around each other.
TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) {
+ // When kPreventDownloadsWithSamePath is disabled,
+ // an OVERWRITE reservation with a conflicting path should return success
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndDisableFeature(
+ features::kPreventDownloadsWithSamePath);
+
std::unique_ptr<MockDownloadItem> item1 = CreateDownloadItem(1);
base::FilePath path(
GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
@@ -411,6 +419,8 @@ TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) {
EXPECT_TRUE(IsPathInUse(path));
EXPECT_FALSE(IsPathInUse(uniquified_path));
+ EXPECT_EQ(PathValidationResult::SUCCESS, result);
+
EXPECT_EQ(path.value(), reserved_path1.value());
EXPECT_EQ(path.value(), reserved_path3.value());
@@ -418,6 +428,42 @@ TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) {
SetDownloadItemState(item3.get(), DownloadItem::COMPLETE);
}
+// When kPreventDownloadsWithSamePath flag is enabled, an OVERWRITE reservation
+// with the same path as an active reservation should return a CONFLICT result.
+TEST_F(DownloadPathReservationTrackerTest, ConflictingReservation_Prevented) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kPreventDownloadsWithSamePath);
+
+ std::unique_ptr<MockDownloadItem> item1 = CreateDownloadItem(1);
+ base::FilePath path(
+ GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
+ ASSERT_FALSE(IsPathInUse(path));
+
+ base::FilePath reserved_path;
+ PathValidationResult result = PathValidationResult::NAME_TOO_LONG;
+ DownloadPathReservationTracker::FilenameConflictAction conflict_action =
+ DownloadPathReservationTracker::OVERWRITE;
+ bool create_directory = false;
+ CallGetReservedPath(item1.get(), path, create_directory, conflict_action,
+ &reserved_path, &result);
+ EXPECT_TRUE(IsPathInUse(path));
+ EXPECT_EQ(PathValidationResult::SUCCESS, result);
+ EXPECT_EQ(path.value(), reserved_path.value());
+
+ std::unique_ptr<MockDownloadItem> item2 = CreateDownloadItem(2);
+ base::FilePath reserved_path2;
+ CallGetReservedPath(item2.get(), path, create_directory, conflict_action,
+ &reserved_path2, &result);
+
+ EXPECT_TRUE(IsPathInUse(path));
+ EXPECT_EQ(PathValidationResult::CONFLICT, result);
+ EXPECT_EQ(path.value(), reserved_path2.value());
+
+ SetDownloadItemState(item1.get(), DownloadItem::COMPLETE);
+ SetDownloadItemState(item2.get(), DownloadItem::COMPLETE);
+}
+
// Two active downloads shouldn't be able to reserve paths that only differ by
// case.
TEST_F(DownloadPathReservationTrackerTest, ConflictingCaseReservations) {
diff --git a/chromium/components/download/internal/common/download_response_handler.cc b/chromium/components/download/internal/common/download_response_handler.cc
index 7ab6994b362..d203a3cf163 100644
--- a/chromium/components/download/internal/common/download_response_handler.cc
+++ b/chromium/components/download/internal/common/download_response_handler.cc
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/metrics/histogram_functions.h"
#include "components/download/public/common/download_stats.h"
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/download_utils.h"
@@ -80,7 +81,7 @@ DownloadResponseHandler::DownloadResponseHandler(
RecordDownloadCountWithSource(UNTHROTTLED_COUNT, download_source);
}
if (resource_request->request_initiator.has_value())
- origin_ = resource_request->request_initiator.value().GetURL();
+ request_initiator_ = resource_request->request_initiator;
}
DownloadResponseHandler::~DownloadResponseHandler() = default;
@@ -103,10 +104,12 @@ void DownloadResponseHandler::OnReceiveResponse(
// suggested name for the security origin of the downlaod URL. However, this
// assumption doesn't hold if there were cross origin redirects. Therefore,
// clear the suggested_name for such requests.
- if (origin_.is_valid() && !create_info_->url_chain.back().SchemeIsBlob() &&
+ if (request_initiator_.has_value() &&
+ !create_info_->url_chain.back().SchemeIsBlob() &&
!create_info_->url_chain.back().SchemeIs(url::kAboutScheme) &&
!create_info_->url_chain.back().SchemeIs(url::kDataScheme) &&
- origin_ != create_info_->url_chain.back().GetOrigin()) {
+ request_initiator_.value() !=
+ url::Origin::Create(create_info_->url_chain.back())) {
create_info_->save_info->suggested_name.clear();
}
@@ -143,6 +146,7 @@ DownloadResponseHandler::CreateDownloadCreateInfo(
create_info->request_headers = request_headers_;
create_info->request_origin = request_origin_;
create_info->download_source = download_source_;
+ create_info->request_initiator = request_initiator_;
HandleResponseHeaders(head.headers.get(), create_info.get());
return create_info;
@@ -194,7 +198,7 @@ void DownloadResponseHandler::OnUploadProgress(
}
void DownloadResponseHandler::OnReceiveCachedMetadata(
- const std::vector<uint8_t>& data) {}
+ mojo_base::BigBuffer data) {}
void DownloadResponseHandler::OnTransferSizeUpdated(
int32_t transfer_size_diff) {}
@@ -226,6 +230,11 @@ void DownloadResponseHandler::OnComplete(
ConvertInterruptReasonToMojoNetworkRequestStatus(reason));
}
+ if (reason == DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED) {
+ base::UmaHistogramSparse("Download.MapErrorNetworkFailed.NetworkService",
+ std::abs(status.error_code));
+ }
+
if (started_) {
delegate_->OnResponseCompleted();
return;
diff --git a/chromium/components/download/internal/common/download_stats.cc b/chromium/components/download/internal/common/download_stats.cc
index b7367a029ad..a46e7db8f5c 100644
--- a/chromium/components/download/internal/common/download_stats.cc
+++ b/chromium/components/download/internal/common/download_stats.cc
@@ -12,6 +12,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
+#include "build/build_config.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "net/http/http_content_disposition.h"
#include "net/http/http_util.h"
@@ -447,6 +448,29 @@ constexpr const base::FilePath::CharType* kDangerousFileTypes[] = {
FILE_PATH_LITERAL(".configprofile"), // 362
FILE_PATH_LITERAL(".internetconnect"), // 363
FILE_PATH_LITERAL(".networkconnect"), // 364
+ FILE_PATH_LITERAL(".bmp"), // 365
+ FILE_PATH_LITERAL(".css"), // 366
+ FILE_PATH_LITERAL(".ehtml"), // 367
+ FILE_PATH_LITERAL(".flac"), // 368
+ FILE_PATH_LITERAL(".ico"), // 369
+ FILE_PATH_LITERAL(".jfif"), // 370
+ FILE_PATH_LITERAL(".m4a"), // 371
+ FILE_PATH_LITERAL(".m4v"), // 372
+ FILE_PATH_LITERAL(".mpeg"), // 373
+ FILE_PATH_LITERAL(".mpg"), // 374
+ FILE_PATH_LITERAL(".oga"), // 375
+ FILE_PATH_LITERAL(".ogg"), // 376
+ FILE_PATH_LITERAL(".ogm"), // 377
+ FILE_PATH_LITERAL(".ogv"), // 378
+ FILE_PATH_LITERAL(".opus"), // 379
+ FILE_PATH_LITERAL(".pjp"), // 380
+ FILE_PATH_LITERAL(".pjpeg"), // 381
+ FILE_PATH_LITERAL(".svgz"), // 382
+ FILE_PATH_LITERAL(".text"), // 383
+ FILE_PATH_LITERAL(".tiff"), // 384
+ FILE_PATH_LITERAL(".weba"), // 385
+ FILE_PATH_LITERAL(".webm"), // 386
+ FILE_PATH_LITERAL(".xbm"), // 387
// NOTE! When you add a type here, please add the UMA value as a comment.
// These must all match DownloadItem.DangerousFileType in
// enums.xml. From 263 onward, they should also match
@@ -543,7 +567,9 @@ void RecordDownloadCountWithSource(DownloadCountTypes type,
void RecordDownloadCompleted(int64_t download_len,
bool is_parallelizable,
- DownloadSource download_source) {
+ DownloadSource download_source,
+ bool has_resumed,
+ bool has_strong_validators) {
RecordDownloadCountWithSource(COMPLETED_COUNT, download_source);
int64_t max = 1024 * 1024 * 1024; // One Terabyte.
download_len /= 1024; // In Kilobytes
@@ -553,6 +579,11 @@ void RecordDownloadCompleted(int64_t download_len,
UMA_HISTOGRAM_CUSTOM_COUNTS("Download.DownloadSize.Parallelizable",
download_len, 1, max, 256);
}
+
+ if (has_resumed) {
+ base::UmaHistogramBoolean("Download.ResumptionComplete.HasStrongValidators",
+ has_strong_validators);
+ }
}
void RecordDownloadDeletion(base::Time completion_time,
@@ -1223,4 +1254,29 @@ void RecordDuplicateInProgressDownloadIdCount(int count) {
count, 1, 10, 11);
}
+void RecordResumptionRestartReason(DownloadInterruptReason reason) {
+ base::UmaHistogramSparse("Download.ResumptionRestart.Reason", reason);
+}
+
+void RecordResumptionRestartCount(ResumptionRestartCountTypes type) {
+ base::UmaHistogramEnumeration("Download.ResumptionRestart.Counts", type);
+}
+
+void RecordDownloadResumed(bool has_strong_validators) {
+ base::UmaHistogramBoolean("Download.ResumptionStart.HasStrongValidators",
+ has_strong_validators);
+}
+
+#if defined(OS_ANDROID)
+void RecordFirstBackgroundDownloadInterruptReason(
+ DownloadInterruptReason reason,
+ bool download_started) {
+ if (download_started)
+ base::UmaHistogramSparse("MobileDownload.FirstBackground.StartedReason",
+ reason);
+ else
+ base::UmaHistogramSparse("MobileDownload.FirstBackground.Reason", reason);
+}
+#endif // defined(OS_ANDROID)
+
} // namespace download
diff --git a/chromium/components/download/internal/common/download_utils.cc b/chromium/components/download/internal/common/download_utils.cc
index 5478f941f2b..43c571344a1 100644
--- a/chromium/components/download/internal/common/download_utils.cc
+++ b/chromium/components/download/internal/common/download_utils.cc
@@ -7,11 +7,14 @@
#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/i18n/file_util_icu.h"
+#include "base/metrics/field_trial_params.h"
#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/download/public/common/download_create_info.h"
+#include "components/download/public/common/download_features.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_stats.h"
@@ -29,6 +32,14 @@
namespace download {
namespace {
+// Default value for |kDownloadContentValidationLengthFinchKey|, when no
+// parameter is specified.
+const int64_t kDefaultContentValidationLength = 1024;
+
+// If the file_offset value from SaveInfo is equal to this, no content
+// validation will be performed and download stream will be written to
+// file starting at the offset from the response.
+const int64_t kInvalidFileWriteOffset = -1;
void AppendExtraHeaders(net::HttpRequestHeaders* headers,
DownloadUrlParameters* params) {
@@ -162,6 +173,7 @@ DownloadInterruptReason HandleSuccessfulServerResponse(
// The response can be HTTP 200 or other error code when
// |fetch_error_body| is true.
save_info->offset = 0;
+ save_info->file_offset = kInvalidFileWriteOffset;
save_info->hash_of_partial_file.clear();
save_info->hash_state.reset();
return DOWNLOAD_INTERRUPT_REASON_NONE;
@@ -312,9 +324,13 @@ std::unique_ptr<net::HttpRequestHeaders> GetAdditionalRequestHeaders(
bool has_etag = !params->etag().empty();
// Strong validator(i.e. etag or last modified) is required in range requests
- // for download resumption and parallel download.
- DCHECK(has_etag || has_last_modified);
- if (!has_etag && !has_last_modified) {
+ // for download resumption and parallel download, unless
+ // |kAllowDownloadResumptionWithoutStrongValidators| is enabled.
+ bool allow_resumption =
+ has_etag || has_last_modified ||
+ base::FeatureList::IsEnabled(
+ features::kAllowDownloadResumptionWithoutStrongValidators);
+ if (!allow_resumption) {
DVLOG(1) << "Creating partial request without strong validators.";
AppendExtraHeaders(headers.get(), params);
return headers;
@@ -590,4 +606,14 @@ download::DownloadItem::DownloadRenameResult RenameDownloadedFile(
: download::DownloadItem::DownloadRenameResult::
FAILURE_NAME_INVALID;
}
+
+int64_t GetDownloadValidationLengthConfig() {
+ std::string finch_value = base::GetFieldTrialParamValueByFeature(
+ features::kAllowDownloadResumptionWithoutStrongValidators,
+ kDownloadContentValidationLengthFinchKey);
+ int64_t result;
+ return base::StringToInt64(finch_value, &result)
+ ? result
+ : kDefaultContentValidationLength;
+}
} // namespace download
diff --git a/chromium/components/download/internal/common/download_worker.cc b/chromium/components/download/internal/common/download_worker.cc
index 05f82616ecd..ad5bec88089 100644
--- a/chromium/components/download/internal/common/download_worker.cc
+++ b/chromium/components/download/internal/common/download_worker.cc
@@ -16,6 +16,7 @@
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace download {
namespace {
@@ -55,10 +56,12 @@ void CreateUrlDownloadHandler(
url_loader_factory_getter,
const URLSecurityPolicy& url_security_policy,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
auto downloader = UrlDownloadHandlerFactory::Create(
std::move(params), delegate, std::move(url_loader_factory_getter),
- url_security_policy, std::move(url_request_context_getter), task_runner);
+ url_security_policy, std::move(url_request_context_getter),
+ std::move(connector), task_runner);
task_runner->PostTask(
FROM_HERE,
base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadHandlerCreated,
@@ -87,13 +90,15 @@ void DownloadWorker::SendRequest(
std::unique_ptr<DownloadUrlParameters> params,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ service_manager::Connector* connector) {
GetIOTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&CreateUrlDownloadHandler, std::move(params),
weak_factory_.GetWeakPtr(),
std::move(url_loader_factory_getter),
base::BindRepeating(&IsURLSafe),
std::move(url_request_context_getter),
+ connector ? connector->Clone() : nullptr,
base::ThreadTaskRunnerHandle::Get()));
}
diff --git a/chromium/components/download/internal/common/download_worker.h b/chromium/components/download/internal/common/download_worker.h
index ec8147106bb..6021c0603af 100644
--- a/chromium/components/download/internal/common/download_worker.h
+++ b/chromium/components/download/internal/common/download_worker.h
@@ -17,7 +17,11 @@
namespace net {
class URLRequestContextGetter;
-}
+} // namespace net
+
+namespace service_manager {
+class Connector;
+} // namespace service_manager
namespace download {
class DownloadURLLoaderFactoryGetter;
@@ -53,7 +57,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker
std::unique_ptr<DownloadUrlParameters> params,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
- scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
+ scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ service_manager::Connector* connector);
// Download operations.
void Pause();
diff --git a/chromium/components/download/internal/common/in_progress_download_manager.cc b/chromium/components/download/internal/common/in_progress_download_manager.cc
index 2b3b61ce504..1c05b2fc4ce 100644
--- a/chromium/components/download/internal/common/in_progress_download_manager.cc
+++ b/chromium/components/download/internal/common/in_progress_download_manager.cc
@@ -27,6 +27,7 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/resource_response.h"
+#include "services/service_manager/public/cpp/connector.h"
#if defined(OS_ANDROID)
#include "components/download/internal/common/android/download_collection_bridge.h"
@@ -55,14 +56,15 @@ std::unique_ptr<DownloadItemImpl> CreateDownloadItemImpl(
in_progress_info->current_path, in_progress_info->target_path,
in_progress_info->url_chain, in_progress_info->referrer_url,
in_progress_info->site_url, in_progress_info->tab_url,
- in_progress_info->tab_referrer_url, in_progress_info->mime_type,
- in_progress_info->original_mime_type, in_progress_info->start_time,
- in_progress_info->end_time, in_progress_info->etag,
- in_progress_info->last_modified, in_progress_info->received_bytes,
- in_progress_info->total_bytes, in_progress_info->auto_resume_count,
- in_progress_info->hash, in_progress_info->state,
- in_progress_info->danger_type, in_progress_info->interrupt_reason,
- in_progress_info->paused, in_progress_info->metered, false, base::Time(),
+ in_progress_info->tab_referrer_url, base::nullopt,
+ in_progress_info->mime_type, in_progress_info->original_mime_type,
+ in_progress_info->start_time, in_progress_info->end_time,
+ in_progress_info->etag, in_progress_info->last_modified,
+ in_progress_info->received_bytes, in_progress_info->total_bytes,
+ in_progress_info->auto_resume_count, in_progress_info->hash,
+ in_progress_info->state, in_progress_info->danger_type,
+ in_progress_info->interrupt_reason, in_progress_info->paused,
+ in_progress_info->metered, false, base::Time(),
in_progress_info->transient, in_progress_info->received_slices);
}
@@ -86,13 +88,15 @@ void BeginResourceDownload(
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
+ std::unique_ptr<service_manager::Connector> connector,
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), url_security_policy, site_url,
- tab_url, tab_referrer_url, is_new_download, false, main_task_runner)
+ tab_url, tab_referrer_url, is_new_download, false,
+ std::move(connector), main_task_runner)
.release(),
base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
@@ -114,6 +118,7 @@ void CreateDownloadHandlerForNavigation(
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter,
const URLSecurityPolicy& url_security_policy,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) {
DCHECK(GetIOTaskRunner()->BelongsToCurrentThread());
UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader(
@@ -123,7 +128,7 @@ void CreateDownloadHandlerForNavigation(
std::move(url_chain), std::move(response), std::move(cert_status),
std::move(url_loader_client_endpoints),
std::move(url_loader_factory_getter), url_security_policy,
- main_task_runner)
+ std::move(connector), main_task_runner)
.release(),
base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
@@ -143,17 +148,35 @@ void OnDownloadDisplayNamesReturned(
#endif
} // namespace
+bool InProgressDownloadManager::Delegate::InterceptDownload(
+ const DownloadCreateInfo& download_create_info) {
+ return false;
+}
+
+base::FilePath
+InProgressDownloadManager::Delegate::GetDefaultDownloadDirectory() {
+ return base::FilePath();
+}
+
+net::URLRequestContextGetter*
+InProgressDownloadManager::Delegate::GetURLRequestContextGetter(
+ const DownloadCreateInfo& download_create_info) {
+ return nullptr;
+}
+
InProgressDownloadManager::InProgressDownloadManager(
Delegate* delegate,
const base::FilePath& in_progress_db_dir,
const IsOriginSecureCallback& is_origin_secure_cb,
- const URLSecurityPolicy& url_security_policy)
+ const URLSecurityPolicy& url_security_policy,
+ service_manager::Connector* connector)
: delegate_(delegate),
file_factory_(new DownloadFileFactory()),
download_start_observer_(nullptr),
is_origin_secure_cb_(is_origin_secure_cb),
url_security_policy_(url_security_policy),
use_empty_db_(in_progress_db_dir.empty()),
+ connector_(connector),
weak_factory_(this) {
Initialize(in_progress_db_dir);
}
@@ -186,10 +209,21 @@ void InProgressDownloadManager::OnUrlDownloadHandlerCreated(
url_download_handlers_.push_back(std::move(downloader));
}
-bool InProgressDownloadManager::DownloadUrl(
+void InProgressDownloadManager::DownloadUrl(
std::unique_ptr<DownloadUrlParameters> params) {
- DCHECK(!delegate_);
- DCHECK(params->is_transient());
+ if (!CanDownload(params.get()))
+ return;
+
+ // Start the new download, the download should be saved to the file path
+ // specifcied in the |params|.
+ BeginDownload(std::move(params), url_loader_factory_getter_,
+ true /* is_new_download */, GURL() /* site_url */,
+ GURL() /* tab_url */, GURL() /* tab_referral_url */);
+}
+
+bool InProgressDownloadManager::CanDownload(DownloadUrlParameters* params) {
+ if (!params->is_transient())
+ return false;
if (!url_loader_factory_getter_)
return false;
@@ -200,11 +234,6 @@ bool InProgressDownloadManager::DownloadUrl(
if (params->file_path().empty())
return false;
- // Start the new download, the download should be saved to the file path
- // specifcied in the |params|.
- BeginDownload(std::move(params), url_loader_factory_getter_,
- true /* is_new_download */, GURL() /* site_url */,
- GURL() /* tab_url */, GURL() /* tab_referral_url */);
return true;
}
@@ -234,11 +263,12 @@ void InProgressDownloadManager::BeginDownload(
CreateResourceRequest(params.get());
GetIOTaskRunner()->PostTask(
FROM_HERE,
- base::BindOnce(&BeginResourceDownload, std::move(params),
- std::move(request), std::move(url_loader_factory_getter),
- url_security_policy_, is_new_download,
- weak_factory_.GetWeakPtr(), site_url, tab_url,
- tab_referrer_url, base::ThreadTaskRunnerHandle::Get()));
+ base::BindOnce(
+ &BeginResourceDownload, std::move(params), std::move(request),
+ std::move(url_loader_factory_getter), url_security_policy_,
+ is_new_download, weak_factory_.GetWeakPtr(), site_url, tab_url,
+ tab_referrer_url, connector_ ? connector_->Clone() : nullptr,
+ base::ThreadTaskRunnerHandle::Get()));
}
void InProgressDownloadManager::InterceptDownloadFromNavigation(
@@ -262,6 +292,7 @@ void InProgressDownloadManager::InterceptDownloadFromNavigation(
std::move(response), std::move(cert_status),
std::move(url_loader_client_endpoints),
std::move(url_loader_factory_getter), url_security_policy_,
+ connector_ ? connector_->Clone() : nullptr,
base::ThreadTaskRunnerHandle::Get()));
}
@@ -284,17 +315,26 @@ void InProgressDownloadManager::ShutDown() {
void InProgressDownloadManager::DetermineDownloadTarget(
DownloadItemImpl* download,
const DownloadTargetCallback& callback) {
- // TODO(http://crbug.com/851581): handle the case that |target_path| and
- // |intermediate_path| are empty.
base::FilePath target_path = download->GetTargetFilePath().empty()
? download->GetForcedFilePath()
: download->GetTargetFilePath();
base::FilePath intermediate_path = download->GetFullPath().empty()
? download->GetForcedFilePath()
: download->GetFullPath();
+#if defined(OS_ANDROID)
+ // If final target is a content URI, the intermediate path should
+ // be identical to it.
+ if (target_path.IsContentUri())
+ intermediate_path = target_path;
+#endif
+ if (!target_path.empty() && intermediate_path.empty()) {
+ if (intermediate_path_cb_)
+ intermediate_path = intermediate_path_cb_.Run(target_path);
+ }
callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
download->GetDangerType(), intermediate_path,
- DOWNLOAD_INTERRUPT_REASON_NONE);
+ intermediate_path.empty() ? DOWNLOAD_INTERRUPT_REASON_FILE_FAILED
+ : DOWNLOAD_INTERRUPT_REASON_NONE);
}
void InProgressDownloadManager::ResumeInterruptedDownload(
@@ -366,7 +406,9 @@ void InProgressDownloadManager::StartDownload(
info->mime_type, is_origin_secure_cb_);
}
- if (delegate_) {
+ // If the download cannot be found locally, ask |delegate_| to provide the
+ // DownloadItem.
+ if (delegate_ && !GetDownloadByGuid(info->guid)) {
delegate_->StartDownloadItem(
std::move(info), on_started,
base::BindOnce(&InProgressDownloadManager::StartDownloadWithItem,
@@ -511,6 +553,7 @@ void InProgressDownloadManager::OnDownloadNamesRetrieved(
if (num_duplicates > 0)
RecordDuplicateInProgressDownloadIdCount(num_duplicates);
OnInitialized();
+ OnDownloadsInitialized();
}
std::vector<std::unique_ptr<download::DownloadItemImpl>>
@@ -535,6 +578,26 @@ void InProgressDownloadManager::OnAllInprogressDownloadsLoaded() {
display_names_.reset();
}
+void InProgressDownloadManager::SetDelegate(Delegate* delegate) {
+ delegate_ = delegate;
+ if (initialized_)
+ OnDownloadsInitialized();
+}
+
+void InProgressDownloadManager::OnDownloadsInitialized() {
+ if (delegate_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&InProgressDownloadManager::NotifyDownloadsInitialized,
+ weak_factory_.GetWeakPtr()));
+ }
+}
+
+void InProgressDownloadManager::NotifyDownloadsInitialized() {
+ if (delegate_)
+ delegate_->OnDownloadsInitialized();
+}
+
void InProgressDownloadManager::AddInProgressDownloadForTest(
std::unique_ptr<download::DownloadItemImpl> download) {
in_progress_downloads_.push_back(std::move(download));
diff --git a/chromium/components/download/internal/common/parallel_download_job.cc b/chromium/components/download/internal/common/parallel_download_job.cc
index 376700af397..1ac7dbbb753 100644
--- a/chromium/components/download/internal/common/parallel_download_job.cc
+++ b/chromium/components/download/internal/common/parallel_download_job.cc
@@ -27,7 +27,8 @@ ParallelDownloadJob::ParallelDownloadJob(
const DownloadCreateInfo& create_info,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter)
+ net::URLRequestContextGetter* url_request_context_getter,
+ service_manager::Connector* connector)
: DownloadJobImpl(download_item, std::move(request_handle), true),
initial_request_offset_(create_info.offset),
initial_received_slices_(download_item->GetReceivedSlices()),
@@ -35,7 +36,8 @@ ParallelDownloadJob::ParallelDownloadJob(
requests_sent_(false),
is_canceled_(false),
url_loader_factory_getter_(std::move(url_loader_factory_getter)),
- url_request_context_getter_(url_request_context_getter) {}
+ url_request_context_getter_(url_request_context_getter),
+ connector_(connector) {}
ParallelDownloadJob::~ParallelDownloadJob() = default;
@@ -298,7 +300,7 @@ void ParallelDownloadJob::CreateRequest(int64_t offset, int64_t length) {
// Send the request.
worker->SendRequest(std::move(download_params), url_loader_factory_getter_,
- url_request_context_getter_);
+ url_request_context_getter_, connector_);
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 1c791294b61..71c45c861f6 100644
--- a/chromium/components/download/internal/common/parallel_download_job.h
+++ b/chromium/components/download/internal/common/parallel_download_job.h
@@ -19,7 +19,11 @@
namespace net {
class URLRequestContextGetter;
-}
+} // namespace net
+
+namespace service_manager {
+class Connector;
+} // namespace service_manager
namespace download {
@@ -38,7 +42,8 @@ class COMPONENTS_DOWNLOAD_EXPORT ParallelDownloadJob
const DownloadCreateInfo& create_info,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter);
+ net::URLRequestContextGetter* url_request_context_getter,
+ service_manager::Connector* connector);
~ParallelDownloadJob() override;
// DownloadJobImpl implementation.
@@ -122,6 +127,9 @@ class COMPONENTS_DOWNLOAD_EXPORT ParallelDownloadJob
// is disabled.
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+ // Connector used for establishing the connection to the ServiceManager.
+ service_manager::Connector* connector_;
+
DISALLOW_COPY_AND_ASSIGN(ParallelDownloadJob);
};
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 3a46e76c054..d227cf4232e 100644
--- a/chromium/components/download/internal/common/parallel_download_job_unittest.cc
+++ b/chromium/components/download/internal/common/parallel_download_job_unittest.cc
@@ -69,6 +69,7 @@ class ParallelDownloadJobForTest : public ParallelDownloadJob {
std::move(request_handle),
create_info,
nullptr,
+ nullptr,
nullptr),
request_count_(request_count),
min_slice_size_(min_slice_size),
@@ -114,9 +115,9 @@ class ParallelDownloadJobForTest : public ParallelDownloadJob {
class ParallelDownloadJobTest : public testing::Test {
public:
ParallelDownloadJobTest()
- : task_environment_(
- base::test::ScopedTaskEnvironment::MainThreadType::UI,
- base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {}
+ : task_environment_(base::test::ScopedTaskEnvironment::MainThreadType::UI,
+ base::test::ScopedTaskEnvironment::
+ ThreadPoolExecutionMode::QUEUED) {}
void CreateParallelJob(int64_t initial_request_offset,
int64_t content_length,
diff --git a/chromium/components/download/internal/common/parallel_download_utils.cc b/chromium/components/download/internal/common/parallel_download_utils.cc
index bc7266fea61..5aa3ad60325 100644
--- a/chromium/components/download/internal/common/parallel_download_utils.cc
+++ b/chromium/components/download/internal/common/parallel_download_utils.cc
@@ -102,7 +102,7 @@ bool CanRecoverFromError(
// the error stream.
if (error_stream->length() > 0) {
return error_stream->offset() + error_stream->length() <=
- preceding_neighbor->offset() + preceding_neighbor->bytes_written();
+ preceding_neighbor->offset() + preceding_neighbor->bytes_read();
}
return false;
diff --git a/chromium/components/download/internal/common/parallel_download_utils_unittest.cc b/chromium/components/download/internal/common/parallel_download_utils_unittest.cc
index af8aab73d76..b0c8462d916 100644
--- a/chromium/components/download/internal/common/parallel_download_utils_unittest.cc
+++ b/chromium/components/download/internal/common/parallel_download_utils_unittest.cc
@@ -43,7 +43,8 @@ class ParallelDownloadUtilsRecoverErrorTest
EXPECT_CALL(*input_stream_, GetCompletionStatus())
.WillRepeatedly(Return(DOWNLOAD_INTERRUPT_REASON_NONE));
return std::make_unique<DownloadFileImpl::SourceStream>(
- offset, length, std::unique_ptr<MockInputStream>(input_stream_));
+ offset, length, offset,
+ std::unique_ptr<MockInputStream>(input_stream_));
}
protected:
@@ -166,7 +167,7 @@ TEST_P(ParallelDownloadUtilsRecoverErrorTest,
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
// Even if it has written some data.
- preceding_stream->OnWriteBytesToDisk(1000u);
+ preceding_stream->OnBytesConsumed(1000u, 1000u);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
// Now capped the length of preceding stream with different values.
@@ -177,14 +178,15 @@ TEST_P(ParallelDownloadUtilsRecoverErrorTest,
preceding_stream->set_finished(false);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
preceding_stream->set_finished(true);
- preceding_stream->OnWriteBytesToDisk(kErrorStreamOffset - preceding_offset);
+ int64_t bytes_consumed = kErrorStreamOffset - preceding_offset;
+ preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
// Inject an error results in failure, even if data written exceeds the first
// byte of error stream.
EXPECT_CALL(*input_stream_, GetCompletionStatus())
.WillRepeatedly(Return(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE));
- preceding_stream->OnWriteBytesToDisk(1000u);
+ preceding_stream->OnBytesConsumed(1000u, 1000u);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
// Make preceding stream can reach the first byte of error stream.
@@ -194,9 +196,9 @@ TEST_P(ParallelDownloadUtilsRecoverErrorTest,
preceding_stream->set_finished(false);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
preceding_stream->set_finished(true);
- preceding_stream->OnWriteBytesToDisk(kErrorStreamOffset - preceding_offset);
+ preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
- preceding_stream->OnWriteBytesToDisk(1);
+ preceding_stream->OnBytesConsumed(1, 1);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
// Preceding stream that never download data won't recover the error stream.
@@ -229,11 +231,13 @@ TEST_P(ParallelDownloadUtilsRecoverErrorTest,
// Since the preceding stream can never reach the starting offset, for an
// unfinished stream, we rely on length instead of bytes written.
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
- preceding_stream->OnWriteBytesToDisk(kErrorStreamOffset - preceding_offset);
+ int64_t bytes_consumed = kErrorStreamOffset - preceding_offset;
+ preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
- preceding_stream->OnWriteBytesToDisk(kErrorStreamLength - 1);
+ preceding_stream->OnBytesConsumed(kErrorStreamLength - 1,
+ kErrorStreamLength - 1);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
- preceding_stream->OnWriteBytesToDisk(1);
+ preceding_stream->OnBytesConsumed(1, 1);
// Create preceding stream that can reach the upper bound of error stream.
// Since it's unfinished, it potentially can take over error stream's work
@@ -248,11 +252,12 @@ TEST_P(ParallelDownloadUtilsRecoverErrorTest,
// Finished preceding stream only checks data written.
preceding_stream = CreateSourceStream(preceding_offset, 1);
preceding_stream->set_finished(true);
- preceding_stream->OnWriteBytesToDisk(kErrorStreamOffset - preceding_offset);
+ preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
- preceding_stream->OnWriteBytesToDisk(kErrorStreamLength - 1);
+ preceding_stream->OnBytesConsumed(kErrorStreamLength - 1,
+ kErrorStreamLength - 1);
EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
- preceding_stream->OnWriteBytesToDisk(1);
+ preceding_stream->OnBytesConsumed(1, 1);
EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get()));
// Even if inject an error, since data written has cover the upper bound of
diff --git a/chromium/components/download/internal/common/resource_downloader.cc b/chromium/components/download/internal/common/resource_downloader.cc
index b5b86b05098..5ddb3408e76 100644
--- a/chromium/components/download/internal/common/resource_downloader.cc
+++ b/chromium/components/download/internal/common/resource_downloader.cc
@@ -10,7 +10,10 @@
#include "components/download/public/common/download_url_loader_factory_getter.h"
#include "components/download/public/common/stream_handle_input_stream.h"
#include "components/download/public/common/url_download_request_handle.h"
+#include "services/device/public/mojom/constants.mojom.h"
+#include "services/device/public/mojom/wake_lock_provider.mojom.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace network {
struct ResourceResponseHead;
@@ -34,7 +37,7 @@ class URLLoaderStatusMonitor : public network::mojom::URLLoaderClient {
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override {}
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override {}
void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override {}
@@ -67,12 +70,14 @@ std::unique_ptr<ResourceDownloader> ResourceDownloader::BeginDownload(
const GURL& tab_referrer_url,
bool is_new_download,
bool is_parallel_request,
+ std::unique_ptr<service_manager::Connector> connector,
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, is_new_download, task_runner,
- std::move(url_loader_factory_getter), url_security_policy);
+ std::move(url_loader_factory_getter), url_security_policy,
+ std::move(connector));
downloader->Start(std::move(params), is_parallel_request);
return downloader;
@@ -95,11 +100,13 @@ ResourceDownloader::InterceptNavigationResponse(
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
const URLSecurityPolicy& url_security_policy,
+ std::unique_ptr<service_manager::Connector> connector,
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, true, task_runner,
- std::move(url_loader_factory_getter), url_security_policy);
+ std::move(url_loader_factory_getter), url_security_policy,
+ std::move(connector));
downloader->InterceptResponse(std::move(response), std::move(url_chain),
cert_status,
std::move(url_loader_client_endpoints));
@@ -118,7 +125,8 @@ ResourceDownloader::ResourceDownloader(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
- const URLSecurityPolicy& url_security_policy)
+ const URLSecurityPolicy& url_security_policy,
+ std::unique_ptr<service_manager::Connector> connector)
: delegate_(delegate),
resource_request_(std::move(resource_request)),
is_new_download_(is_new_download),
@@ -130,7 +138,9 @@ ResourceDownloader::ResourceDownloader(
delegate_task_runner_(task_runner),
url_loader_factory_getter_(std::move(url_loader_factory_getter)),
url_security_policy_(url_security_policy),
- weak_ptr_factory_(this) {}
+ weak_ptr_factory_(this) {
+ RequestWakeLock(connector.get());
+}
ResourceDownloader::~ResourceDownloader() = default;
@@ -254,10 +264,27 @@ void ResourceDownloader::CancelRequest() {
}
void ResourceDownloader::Destroy() {
+ if (wake_lock_)
+ wake_lock_->CancelWakeLock();
delegate_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&UrlDownloadHandler::Delegate::OnUrlDownloadStopped,
delegate_, this));
}
+void ResourceDownloader::RequestWakeLock(
+ service_manager::Connector* connector) {
+ if (!connector)
+ return;
+ device::mojom::WakeLockProviderPtr wake_lock_provider;
+ connector->BindInterface(device::mojom::kServiceName,
+ mojo::MakeRequest(&wake_lock_provider));
+ wake_lock_provider->GetWakeLockWithoutContext(
+ device::mojom::WakeLockType::kPreventAppSuspension,
+ device::mojom::WakeLockReason::kOther, "Download in progress",
+ mojo::MakeRequest(&wake_lock_));
+
+ wake_lock_->RequestWakeLock();
+}
+
} // namespace download
diff --git a/chromium/components/download/internal/common/resource_downloader.h b/chromium/components/download/internal/common/resource_downloader.h
index 63664cfbe8f..b2f8ec766fe 100644
--- a/chromium/components/download/internal/common/resource_downloader.h
+++ b/chromium/components/download/internal/common/resource_downloader.h
@@ -12,9 +12,14 @@
#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/device/public/mojom/wake_lock.mojom.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+namespace service_manager {
+class Connector;
+} // namespace service_manager
+
namespace download {
class DownloadURLLoaderFactoryGetter;
@@ -36,6 +41,7 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
const GURL& tab_referrer_url,
bool is_new_download,
bool is_parallel_request,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
// Create a ResourceDownloader from a navigation that turns to be a download.
@@ -56,6 +62,7 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
const URLSecurityPolicy& url_security_policy,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
ResourceDownloader(
@@ -70,7 +77,8 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
- const URLSecurityPolicy& url_security_policy);
+ const URLSecurityPolicy& url_security_policy,
+ std::unique_ptr<service_manager::Connector> connector);
~ResourceDownloader() override;
// download::DownloadResponseHandler::Delegate
@@ -101,6 +109,9 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
// Ask the |delegate_| to destroy this object.
void Destroy();
+ // Requests the wake lock using |connector|.
+ void RequestWakeLock(service_manager::Connector* connector);
+
base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate_;
// The ResourceRequest for this object.
@@ -154,6 +165,11 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader
// Used to check if the URL is safe to request.
URLSecurityPolicy url_security_policy_;
+ // Used to keep the system from sleeping while a download is ongoing. If the
+ // system enters power saving mode while a download is alive, it can cause
+ // download to be interrupted.
+ device::mojom::WakeLockPtr wake_lock_;
+
base::WeakPtrFactory<ResourceDownloader> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ResourceDownloader);
diff --git a/chromium/components/download/internal/common/simple_download_manager.cc b/chromium/components/download/internal/common/simple_download_manager.cc
index 9cac3131863..5401b468bca 100644
--- a/chromium/components/download/internal/common/simple_download_manager.cc
+++ b/chromium/components/download/internal/common/simple_download_manager.cc
@@ -15,6 +15,8 @@ SimpleDownloadManager::~SimpleDownloadManager() {
void SimpleDownloadManager::AddObserver(Observer* observer) {
simple_download_manager_observers_.AddObserver(observer);
+ if (initialized_)
+ NotifyInitialized();
}
void SimpleDownloadManager::RemoveObserver(Observer* observer) {
@@ -23,18 +25,7 @@ void SimpleDownloadManager::RemoveObserver(Observer* observer) {
void SimpleDownloadManager::OnInitialized() {
initialized_ = true;
- for (auto& callback : std::move(on_initialized_callbacks_))
- std::move(callback).Run();
-}
-
-void SimpleDownloadManager::NotifyWhenInitialized(
- base::OnceClosure on_initialized_cb) {
- if (initialized_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- std::move(on_initialized_cb));
- return;
- }
- on_initialized_callbacks_.emplace_back(std::move(on_initialized_cb));
+ NotifyInitialized();
}
void SimpleDownloadManager::OnNewDownloadCreated(DownloadItem* download) {
@@ -42,4 +33,9 @@ void SimpleDownloadManager::OnNewDownloadCreated(DownloadItem* download) {
observer.OnDownloadCreated(download);
}
+void SimpleDownloadManager::NotifyInitialized() {
+ for (auto& observer : simple_download_manager_observers_)
+ observer.OnDownloadsInitialized();
+}
+
} // namespace download
diff --git a/chromium/components/download/internal/common/simple_download_manager_coordinator.cc b/chromium/components/download/internal/common/simple_download_manager_coordinator.cc
index ca14a7f40b0..bf1a4f42df9 100644
--- a/chromium/components/download/internal/common/simple_download_manager_coordinator.cc
+++ b/chromium/components/download/internal/common/simple_download_manager_coordinator.cc
@@ -12,13 +12,20 @@
namespace download {
-SimpleDownloadManagerCoordinator::SimpleDownloadManagerCoordinator()
+SimpleDownloadManagerCoordinator::SimpleDownloadManagerCoordinator(
+ const DownloadWhenFullManagerStartsCallBack&
+ download_when_full_manager_starts_cb)
: simple_download_manager_(nullptr),
has_all_history_downloads_(false),
+ current_manager_has_all_history_downloads_(false),
initialized_(false),
+ download_when_full_manager_starts_cb_(
+ download_when_full_manager_starts_cb),
weak_factory_(this) {}
SimpleDownloadManagerCoordinator::~SimpleDownloadManagerCoordinator() {
+ if (simple_download_manager_)
+ simple_download_manager_->RemoveObserver(this);
for (auto& observer : observers_)
observer.OnManagerGoingDown();
}
@@ -26,18 +33,24 @@ SimpleDownloadManagerCoordinator::~SimpleDownloadManagerCoordinator() {
void SimpleDownloadManagerCoordinator::SetSimpleDownloadManager(
SimpleDownloadManager* simple_download_manager,
bool manages_all_history_downloads) {
- DCHECK(simple_download_manager_);
+ DCHECK(simple_download_manager);
+ // Make sure we won't transition from a full manager to a in-progress manager,
+ DCHECK(!current_manager_has_all_history_downloads_ ||
+ manages_all_history_downloads);
+
if (simple_download_manager_)
simple_download_manager_->RemoveObserver(this);
+ current_manager_has_all_history_downloads_ = manages_all_history_downloads;
simple_download_manager_ = simple_download_manager;
simple_download_manager_->AddObserver(this);
- simple_download_manager_->NotifyWhenInitialized(base::BindOnce(
- &SimpleDownloadManagerCoordinator::OnManagerInitialized,
- weak_factory_.GetWeakPtr(), manages_all_history_downloads));
}
void SimpleDownloadManagerCoordinator::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
+ if (initialized_) {
+ for (auto& observer : observers_)
+ observer.OnDownloadsInitialized(!has_all_history_downloads_);
+ }
}
void SimpleDownloadManagerCoordinator::RemoveObserver(Observer* observer) {
@@ -46,13 +59,22 @@ void SimpleDownloadManagerCoordinator::RemoveObserver(Observer* observer) {
void SimpleDownloadManagerCoordinator::DownloadUrl(
std::unique_ptr<DownloadUrlParameters> parameters) {
- if (simple_download_manager_)
+ bool result = simple_download_manager_
+ ? simple_download_manager_->CanDownload(parameters.get())
+ : false;
+ if (result) {
simple_download_manager_->DownloadUrl(std::move(parameters));
+ return;
+ }
+
+ if (!current_manager_has_all_history_downloads_)
+ download_when_full_manager_starts_cb_.Run(std::move(parameters));
}
void SimpleDownloadManagerCoordinator::GetAllDownloads(
std::vector<DownloadItem*>* downloads) {
- simple_download_manager_->GetAllDownloads(downloads);
+ if (simple_download_manager_)
+ simple_download_manager_->GetAllDownloads(downloads);
}
DownloadItem* SimpleDownloadManagerCoordinator::GetDownloadByGuid(
@@ -62,16 +84,11 @@ DownloadItem* SimpleDownloadManagerCoordinator::GetDownloadByGuid(
return nullptr;
}
-bool SimpleDownloadManagerCoordinator::HasSetDownloadManager() {
- return simple_download_manager_;
-}
-
-void SimpleDownloadManagerCoordinator::OnManagerInitialized(
- bool has_all_history_downloads) {
+void SimpleDownloadManagerCoordinator::OnDownloadsInitialized() {
initialized_ = true;
- has_all_history_downloads_ = has_all_history_downloads;
+ has_all_history_downloads_ = current_manager_has_all_history_downloads_;
for (auto& observer : observers_)
- observer.OnDownloadsInitialized(!has_all_history_downloads);
+ observer.OnDownloadsInitialized(!has_all_history_downloads_);
}
void SimpleDownloadManagerCoordinator::OnManagerGoingDown() {
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 b88c1ff4385..c295bc9dfaa 100644
--- a/chromium/components/download/internal/common/url_download_handler_factory.cc
+++ b/chromium/components/download/internal/common/url_download_handler_factory.cc
@@ -12,6 +12,7 @@
#include "components/download/public/common/download_utils.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/service_manager/public/cpp/connector.h"
namespace download {
@@ -31,6 +32,7 @@ class DefaultUrlDownloadHandlerFactory : public UrlDownloadHandlerFactory {
url_loader_factory_getter,
const URLSecurityPolicy& url_security_policy,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override {
std::unique_ptr<network::ResourceRequest> request =
CreateResourceRequest(params.get());
@@ -38,7 +40,7 @@ class DefaultUrlDownloadHandlerFactory : public UrlDownloadHandlerFactory {
download::ResourceDownloader::BeginDownload(
delegate, std::move(params), std::move(request),
std::move(url_loader_factory_getter), url_security_policy, GURL(),
- GURL(), GURL(), true, true, task_runner)
+ GURL(), GURL(), true, true, std::move(connector), task_runner)
.release(),
base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get()));
}
@@ -66,6 +68,7 @@ UrlDownloadHandlerFactory::Create(
url_loader_factory_getter,
const URLSecurityPolicy& url_security_policy,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
base::AutoLock auto_lock(GetURLDownloadHandlerFactoryLock());
if (!g_url_download_handler_factory)
@@ -73,7 +76,7 @@ UrlDownloadHandlerFactory::Create(
return g_url_download_handler_factory->CreateUrlDownloadHandler(
std::move(params), delegate, std::move(url_loader_factory_getter),
std::move(url_security_policy), std::move(url_request_context_getter),
- task_runner);
+ std::move(connector), task_runner);
}
// static
diff --git a/chromium/components/download/public/background_service/BUILD.gn b/chromium/components/download/public/background_service/BUILD.gn
index 424ed0bf9f0..d309ca9488b 100644
--- a/chromium/components/download/public/background_service/BUILD.gn
+++ b/chromium/components/download/public/background_service/BUILD.gn
@@ -9,6 +9,8 @@ if (is_android) {
source_set("public") {
sources = [
+ "blob_context_getter_factory.h",
+ "client.cc",
"client.h",
"clients.h",
"download_metadata.cc",
diff --git a/chromium/components/download/public/background_service/blob_context_getter_factory.h b/chromium/components/download/public/background_service/blob_context_getter_factory.h
new file mode 100644
index 00000000000..d9cf66ad547
--- /dev/null
+++ b/chromium/components/download/public/background_service/blob_context_getter_factory.h
@@ -0,0 +1,41 @@
+// Copyright 2019 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_PUBLIC_BACKGROUND_SERVICE_BLOB_CONTEXT_GETTER_FACTORY_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_BLOB_CONTEXT_GETTER_FACTORY_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+
+namespace storage {
+class BlobStorageContext;
+} // namespace storage
+
+namespace download {
+
+using BlobContextGetter =
+ base::RepeatingCallback<base::WeakPtr<storage::BlobStorageContext>()>;
+using BlobContextGetterCallback = base::OnceCallback<void(BlobContextGetter)>;
+
+// Retrieves a blob storage context getter on main thread.
+class BlobContextGetterFactory {
+ public:
+ virtual void RetrieveBlobContextGetter(
+ BlobContextGetterCallback callback) = 0;
+
+ virtual ~BlobContextGetterFactory() = default;
+
+ protected:
+ BlobContextGetterFactory() = default;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BlobContextGetterFactory);
+};
+
+using BlobContextGetterFactoryPtr = std::unique_ptr<BlobContextGetterFactory>;
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_BACKGROUND_SERVICE_BLOB_CONTEXT_GETTER_FACTORY_H_
diff --git a/chromium/components/download/public/background_service/client.cc b/chromium/components/download/public/background_service/client.cc
new file mode 100644
index 00000000000..68f9120a69b
--- /dev/null
+++ b/chromium/components/download/public/background_service/client.cc
@@ -0,0 +1,22 @@
+// Copyright 2019 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/background_service/client.h"
+
+namespace download {
+
+void Client::OnDownloadStarted(
+ const std::string& guid,
+ const std::vector<GURL>& url_chain,
+ const scoped_refptr<const net::HttpResponseHeaders>& headers) {}
+
+void Client::OnDownloadUpdated(const std::string& guid,
+ uint64_t bytes_uploaded,
+ uint64_t bytes_downloaded) {}
+
+void Client::OnDownloadFailed(const std::string& guid,
+ const download::CompletionInfo& completion_info,
+ download::Client::FailureReason reason) {}
+
+} // namespace download
diff --git a/chromium/components/download/public/background_service/client.h b/chromium/components/download/public/background_service/client.h
index da5956cab18..1374d0d83eb 100644
--- a/chromium/components/download/public/background_service/client.h
+++ b/chromium/components/download/public/background_service/client.h
@@ -30,19 +30,6 @@ using GetUploadDataCallback =
// when the DownloadService is created (see the factory).
class Client {
public:
- // Used by OnDownloadStarted to determine whether or not the DownloadService
- // should continue downloading the file or abort the attempt.
- enum class ShouldDownload {
- // Continue to download the file.
- CONTINUE,
-
- // Abort the download.
- ABORT,
-
- // The count of entries for the enum.
- COUNT,
- };
-
// Used by OnDownloadFailed to determine the reason of the abort.
enum class FailureReason {
// Used when the download has been aborted after reaching a threshold where
@@ -88,13 +75,12 @@ class Client {
// Called when the DownloadService fails to initialize and should not be used.
virtual void OnServiceUnavailable() = 0;
- // Return whether or not the download should be aborted (potentially in
- // response to |headers|). The download will be downloading at the time this
- // call is made.
- virtual ShouldDownload OnDownloadStarted(
+ // Will be called when a download has been started and the headers have been
+ // retrieved. The download will be downloading at the time this call is made.
+ virtual void OnDownloadStarted(
const std::string& guid,
const std::vector<GURL>& url_chain,
- const scoped_refptr<const net::HttpResponseHeaders>& headers) = 0;
+ const scoped_refptr<const net::HttpResponseHeaders>& headers);
// Will be called when there is an update to the current progress state of the
// underlying download. Note that |bytes_downloaded| may go backwards if the
@@ -104,7 +90,7 @@ class Client {
// driver.
virtual void OnDownloadUpdated(const std::string& guid,
uint64_t bytes_uploaded,
- uint64_t bytes_downloaded) = 0;
+ uint64_t bytes_downloaded);
// Called when a download failed. Check FailureReason for a list of possible
// reasons why this failure occurred. Note that this will also be called for
@@ -112,7 +98,7 @@ class Client {
// and response headers filled in if available.
virtual void OnDownloadFailed(const std::string& guid,
const download::CompletionInfo& info,
- FailureReason reason) = 0;
+ FailureReason reason);
// Called when a download has been successfully completed.
// The file and the database record will be automatically removed if it is not
diff --git a/chromium/components/download/public/background_service/download_params.cc b/chromium/components/download/public/background_service/download_params.cc
index d5c123846c1..00a3ccbd9c8 100644
--- a/chromium/components/download/public/background_service/download_params.cc
+++ b/chromium/components/download/public/background_service/download_params.cc
@@ -20,7 +20,8 @@ bool SchedulingParams::operator==(const SchedulingParams& rhs) const {
priority == rhs.priority && cancel_time == rhs.cancel_time;
}
-RequestParams::RequestParams() : method("GET"), fetch_error_body(false) {}
+RequestParams::RequestParams()
+ : method("GET"), fetch_error_body(false), require_safety_checks(true) {}
RequestParams::RequestParams(const RequestParams& other) = default;
diff --git a/chromium/components/download/public/background_service/download_params.h b/chromium/components/download/public/background_service/download_params.h
index aadde2f4b4b..4445bbbbcfd 100644
--- a/chromium/components/download/public/background_service/download_params.h
+++ b/chromium/components/download/public/background_service/download_params.h
@@ -107,6 +107,9 @@ struct RequestParams {
// If the request will fetch HTTP error response body and treat them as
// a successful download.
bool fetch_error_body;
+
+ // Whether the download is not trustworthy and requires safe browsing checks.
+ bool require_safety_checks;
};
// The parameters that describe a download request made to the DownloadService.
diff --git a/chromium/components/download/public/common/BUILD.gn b/chromium/components/download/public/common/BUILD.gn
index 71b8180719d..5937c55370e 100644
--- a/chromium/components/download/public/common/BUILD.gn
+++ b/chromium/components/download/public/common/BUILD.gn
@@ -134,6 +134,8 @@ source_set("test_support") {
"mock_download_item_impl.h",
"mock_input_stream.cc",
"mock_input_stream.h",
+ "mock_simple_download_manager.cc",
+ "mock_simple_download_manager.h",
]
public_deps = [
diff --git a/chromium/components/download/public/common/all_download_event_notifier.h b/chromium/components/download/public/common/all_download_event_notifier.h
index 90275c18e07..d9a8989b5d1 100644
--- a/chromium/components/download/public/common/all_download_event_notifier.h
+++ b/chromium/components/download/public/common/all_download_event_notifier.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/observer_list.h"
+#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/simple_download_manager_coordinator.h"
@@ -16,7 +17,7 @@ namespace download {
// Observes all the download events from a single
// SimpleDownloadManagerCoordinator.
-class AllDownloadEventNotifier
+class COMPONENTS_DOWNLOAD_EXPORT AllDownloadEventNotifier
: public SimpleDownloadManagerCoordinator::Observer,
public DownloadItem::Observer {
public:
diff --git a/chromium/components/download/public/common/base_file.h b/chromium/components/download/public/common/base_file.h
index d6716233e0a..dd8ed1b1993 100644
--- a/chromium/components/download/public/common/base_file.h
+++ b/chromium/components/download/public/common/base_file.h
@@ -114,6 +114,10 @@ class COMPONENTS_DOWNLOAD_EXPORT BaseFile {
const char* data,
size_t data_len);
+ // Validates that the content starting from |offset| matches that of |data|
+ // with the given length.
+ bool ValidateDataInFile(int64_t offset, const char* data, size_t data_len);
+
// Rename the download file. Returns a DownloadInterruptReason indicating the
// result of the operation. A return code of NONE indicates that the rename
// was successful. After a failure, the full_path() and in_progress() can be
diff --git a/chromium/components/download/public/common/download_create_info.h b/chromium/components/download/public/common/download_create_info.h
index 7c82695416b..19552ad5b07 100644
--- a/chromium/components/download/public/common/download_create_info.h
+++ b/chromium/components/download/public/common/download_create_info.h
@@ -27,6 +27,7 @@
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace net {
class HttpResponseHeaders;
@@ -67,6 +68,9 @@ struct COMPONENTS_DOWNLOAD_EXPORT DownloadCreateInfo {
// The referrer URL of the tab that started us.
GURL tab_referrer_url;
+ // The origin of the requester that originally initiated the download.
+ base::Optional<url::Origin> request_initiator;
+
// The time when the download started.
base::Time start_time;
diff --git a/chromium/components/download/public/common/download_features.cc b/chromium/components/download/public/common/download_features.cc
index 6929f5a798b..7e945dd4815 100644
--- a/chromium/components/download/public/common/download_features.cc
+++ b/chromium/components/download/public/common/download_features.cc
@@ -38,5 +38,16 @@ const base::Feature kRefreshExpirationDate{"RefreshExpirationDate",
base::FEATURE_ENABLED_BY_DEFAULT};
#endif
+const base::Feature kPreventDownloadsWithSamePath{
+ "PreventDownloadsWithSamePath", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kUseInProgressDownloadManagerForDownloadService{
+ "UseInProgressDownloadManagerForDownloadService",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kAllowDownloadResumptionWithoutStrongValidators{
+ "AllowDownloadResumptionWithoutStrongValidators",
+ base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features
+
} // namespace download
diff --git a/chromium/components/download/public/common/download_features.h b/chromium/components/download/public/common/download_features.h
index b802cbf2840..a3d7fda74f6 100644
--- a/chromium/components/download/public/common/download_features.h
+++ b/chromium/components/download/public/common/download_features.h
@@ -33,6 +33,18 @@ COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature
COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature kRefreshExpirationDate;
#endif
+// Whether concurrent downloads to the same target path should be allowed.
+COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature
+ kPreventDownloadsWithSamePath;
+
+// Whether in-progress download manager will be used to initialize download
+// service.
+COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature
+ kUseInProgressDownloadManagerForDownloadService;
+
+// Whether download resumption is allowed when there are no strong validators.
+COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature
+ kAllowDownloadResumptionWithoutStrongValidators;
} // namespace features
} // namespace download
diff --git a/chromium/components/download/public/common/download_file.h b/chromium/components/download/public/common/download_file.h
index 50561a801aa..545b4d186aa 100644
--- a/chromium/components/download/public/common/download_file.h
+++ b/chromium/components/download/public/common/download_file.h
@@ -121,6 +121,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFile {
// Publishes the download to public. Once completes, |callback| is called with
// the final content URI.
virtual void PublishDownload(const RenameCompletionCallback& callback) = 0;
+
+ // Returns the suggested file path from the system.
+ virtual base::FilePath GetDisplayName() = 0;
#endif // defined(OS_ANDROID)
};
diff --git a/chromium/components/download/public/common/download_file_impl.h b/chromium/components/download/public/common/download_file_impl.h
index 1f82b9d92d4..c3dee68fc39 100644
--- a/chromium/components/download/public/common/download_file_impl.h
+++ b/chromium/components/download/public/common/download_file_impl.h
@@ -84,6 +84,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
const std::string& mime_type,
const RenameCompletionCallback& callback) override;
void PublishDownload(const RenameCompletionCallback& callback) override;
+ base::FilePath GetDisplayName() override;
#endif // defined(OS_ANDROID)
// Wrapper of a ByteStreamReader or ScopedDataPipeConsumerHandle, and the meta
@@ -98,17 +99,19 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
public:
SourceStream(int64_t offset,
int64_t length,
+ int64_t starting_file_write_offset,
std::unique_ptr<InputStream> stream);
~SourceStream();
void Initialize();
- // Called after successfully writing a buffer to disk.
- void OnWriteBytesToDisk(int64_t bytes_write);
+ // Called after successfully reading and writing a buffer from stream.
+ void OnBytesConsumed(int64_t bytes_read, int64_t bytes_written);
// Given a data block that is already written, truncate the length of this
- // object to avoid overwriting that block.
- void TruncateLengthWithWrittenDataBlock(int64_t offset,
+ // object to avoid overwriting that block. Data used for validation purpose
+ // will not be truncated.
+ void TruncateLengthWithWrittenDataBlock(int64_t received_slice_offset,
int64_t bytes_written);
// Registers the callback that will be called when data is ready.
@@ -135,8 +138,15 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
InputStream::StreamState Read(scoped_refptr<net::IOBuffer>* data,
size_t* length);
+ // Returning the remaining bytes to validate.
+ size_t GetRemainingBytesToValidate();
+
int64_t offset() const { return offset_; }
int64_t length() const { return length_; }
+ int64_t starting_file_write_offset() const {
+ return starting_file_write_offset_;
+ }
+ int64_t bytes_read() const { return bytes_read_; }
int64_t bytes_written() const { return bytes_written_; }
bool is_finished() const { return finished_; }
void set_finished(bool finish) { finished_ = finish; }
@@ -144,15 +154,24 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
void set_index(size_t index) { index_ = index; }
private:
- // Starting position for the stream to write to disk.
+ // Starting position of the stream, this is from the network response.
int64_t offset_;
// The maximum length to write to the disk. If set to 0, keep writing until
// the stream depletes.
int64_t length_;
- // Number of bytes written to disk from the stream.
- // Next write position is (|offset_| + |bytes_written_|).
+ // All the data received before this offset are used for validation purpose
+ // and will not be written to disk. This value should always be no less than
+ // |offset_|.
+ int64_t starting_file_write_offset_;
+
+ // Number of bytes read from the stream.
+ // Next read position is (|offset_| + |bytes_read_|).
+ int64_t bytes_read_;
+
+ // Number of bytes written to the disk. This does not include the bytes used
+ // for validation.
int64_t bytes_written_;
// If all the data read from the stream has been successfully written to
@@ -171,11 +190,13 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
protected:
// For test class overrides.
- // Write data from the offset to the file.
- // On OS level, it will seek to the |offset| and write from there.
- virtual DownloadInterruptReason WriteDataToFile(int64_t offset,
- const char* data,
- size_t data_len);
+ // Validate the first |bytes_to_validate| bytes and write the next
+ // |bytes_to_write| bytes of data from the offset to the file.
+ virtual DownloadInterruptReason ValidateAndWriteDataToFile(
+ int64_t offset,
+ const char* data,
+ size_t bytes_to_validate,
+ size_t bytes_to_write);
virtual base::TimeDelta GetRetryDelayForFailedRename(int attempt_number);
@@ -187,11 +208,6 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
private:
friend class DownloadFileTest;
- DownloadFileImpl(std::unique_ptr<DownloadSaveInfo> save_info,
- const base::FilePath& default_downloads_directory,
- uint32_t download_id,
- base::WeakPtr<DownloadDestinationObserver> observer);
-
// Options for RenameWithRetryInternal.
enum RenameOption {
UNIQUIFY = 1 << 0, // If there's already a file on disk that conflicts with
@@ -236,13 +252,14 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
void WillWriteToDisk(size_t data_len);
// For a given SourceStream object and the bytes available to write, determine
- // the actual number of bytes it can write to the disk. For parallel
- // downloading, if the first disk IO writes to a location that is already
- // written by another stream, the current stream should stop writing. Returns
- // true if the stream can write no more data and should be finished, returns
- // false otherwise.
+ // the number of bytes to validate and the number of bytes it can write to the
+ // disk. For parallel downloading, if the first disk IO writes to a location
+ // that is already written by another stream, the current stream should stop
+ // writing. Returns true if the stream can write no more data and should be
+ // finished, returns false otherwise.
bool CalculateBytesToWrite(SourceStream* source_stream,
size_t bytes_available_to_write,
+ size_t* bytes_to_validate,
size_t* bytes_to_write);
// Called when a new SourceStream object is added.
@@ -346,6 +363,10 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile {
// TaskRunner to post updates to the |observer_|.
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+#if defined(OS_ANDROID)
+ base::FilePath display_name_;
+#endif // defined(OS_ANDROID)
+
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtr<DownloadDestinationObserver> observer_;
diff --git a/chromium/components/download/public/common/download_item.h b/chromium/components/download/public/common/download_item.h
index cfd9d19c3cc..df473cfe887 100644
--- a/chromium/components/download/public/common/download_item.h
+++ b/chromium/components/download/public/common/download_item.h
@@ -26,12 +26,14 @@
#include "base/callback_forward.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
+#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/supports_user_data.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "ui/base/page_transition_types.h"
+#include "url/origin.h"
class GURL;
@@ -282,6 +284,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItem : public base::SupportsUserData {
// Referrer URL for top level frame.
virtual const GURL& GetTabReferrerUrl() const = 0;
+ // Origin of the original originator of this download, before redirects, etc.
+ virtual const base::Optional<url::Origin>& GetRequestInitiator() const = 0;
+
// For downloads initiated via <a download>, this is the suggested download
// filename from the download attribute.
virtual std::string GetSuggestedFilename() const = 0;
diff --git a/chromium/components/download/public/common/download_item_factory.h b/chromium/components/download/public/common/download_item_factory.h
index 0ceeea52ad6..8453cd85349 100644
--- a/chromium/components/download/public/common/download_item_factory.h
+++ b/chromium/components/download/public/common/download_item_factory.h
@@ -15,8 +15,10 @@
#include <string>
#include <vector>
+#include "base/optional.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_item.h"
+#include "url/origin.h"
class GURL;
@@ -46,6 +48,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemFactory {
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_refererr_url,
+ const base::Optional<url::Origin>& initiator_origin,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
diff --git a/chromium/components/download/public/common/download_item_impl.h b/chromium/components/download/public/common/download_item_impl.h
index 85f45a5e654..0da7255e41a 100644
--- a/chromium/components/download/public/common/download_item_impl.h
+++ b/chromium/components/download/public/common/download_item_impl.h
@@ -16,6 +16,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "base/optional.h"
#include "base/threading/thread_checker_impl.h"
#include "base/time/time.h"
#include "components/download/public/common/download_create_info.h"
@@ -27,6 +28,7 @@
#include "components/download/public/common/download_url_parameters.h"
#include "components/download/public/common/resume_mode.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace net {
class URLRequestContextGetter;
@@ -53,6 +55,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& suggested_filename,
const base::FilePath& forced_file_path,
ui::PageTransition transition_type,
@@ -79,6 +82,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
// The URL of the referrer of the tab that initiated the download.
GURL tab_referrer_url;
+ // The origin of the requester that originally initiated the download.
+ base::Optional<url::Origin> request_initiator;
+
// Filename suggestion from DownloadSaveInfo. It could, among others, be the
// suggested filename in 'download' attribute of an anchor. Details:
// http://www.whatwg.org/specs/web-apps/current-work/#downloading-hyperlinks
@@ -171,6 +177,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
const GURL& site_url,
const GURL& tab_url,
const GURL& tab_referrer_url,
+ const base::Optional<url::Origin>& request_initiator,
const std::string& mime_type,
const std::string& original_mime_type,
base::Time start_time,
@@ -242,6 +249,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
const GURL& GetSiteUrl() const override;
const GURL& GetTabUrl() const override;
const GURL& GetTabReferrerUrl() const override;
+ const base::Optional<url::Origin>& GetRequestInitiator() const override;
std::string GetSuggestedFilename() const override;
const scoped_refptr<const net::HttpResponseHeaders>& GetResponseHeaders()
const override;
@@ -637,6 +645,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
// INTERRUPTED state.
ResumeMode GetResumeMode() const;
+ // Whether strong validators are present.
+ bool HasStrongValidators() const;
+
DownloadItem::DownloadRenameResult RenameDownloadedFile(
const std::string& name);
void RenameDownloadedFileDone(RenameDownloadCallback callback,
@@ -815,6 +826,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
// UKM ID for reporting, default to 0 if uninitialized.
uint64_t ukm_download_id_ = 0;
+ // Whether download has been resumed.
+ bool has_resumed_ = false;
+
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<DownloadItemImpl> weak_ptr_factory_;
diff --git a/chromium/components/download/public/common/download_item_impl_delegate.h b/chromium/components/download/public/common/download_item_impl_delegate.h
index a6eb542950c..e67be44238b 100644
--- a/chromium/components/download/public/common/download_item_impl_delegate.h
+++ b/chromium/components/download/public/common/download_item_impl_delegate.h
@@ -15,6 +15,10 @@
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/download_url_parameters.h"
+namespace service_manager {
+class Connector;
+} // namespace service_manager
+
namespace download {
struct DownloadEntry;
class DownloadItemImpl;
@@ -113,6 +117,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImplDelegate {
// Report extra bytes wasted during resumption.
virtual void ReportBytesWasted(DownloadItemImpl* download);
+ // Gets the ServiceManager connector that can be used on UI thread.
+ virtual service_manager::Connector* GetServiceManagerConnector();
+
private:
// For "Outlives attached DownloadItemImpl" invariant assertion.
int count_;
diff --git a/chromium/components/download/public/common/download_job_factory.h b/chromium/components/download/public/common/download_job_factory.h
index cd44f441cad..d6660c1073c 100644
--- a/chromium/components/download/public/common/download_job_factory.h
+++ b/chromium/components/download/public/common/download_job_factory.h
@@ -13,7 +13,11 @@
namespace net {
class URLRequestContextGetter;
-}
+} // namespace net
+
+namespace service_manager {
+class Connector;
+} // namespace service_manager
namespace download {
@@ -32,7 +36,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadJobFactory {
bool is_save_package_download,
scoped_refptr<download::DownloadURLLoaderFactoryGetter>
url_loader_factory_getter,
- net::URLRequestContextGetter* url_request_context_getter);
+ net::URLRequestContextGetter* url_request_context_getter,
+ service_manager::Connector* connector);
private:
DISALLOW_COPY_AND_ASSIGN(DownloadJobFactory);
diff --git a/chromium/components/download/public/common/download_path_reservation_tracker.h b/chromium/components/download/public/common/download_path_reservation_tracker.h
index 446a2de057c..6c0b83a12cb 100644
--- a/chromium/components/download/public/common/download_path_reservation_tracker.h
+++ b/chromium/components/download/public/common/download_path_reservation_tracker.h
@@ -111,6 +111,14 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadPathReservationTracker {
// tests.
static bool IsPathInUseForTesting(const base::FilePath& path);
+ // Returns true if there is an existing path reservation, separate from the
+ // download_item. Called by
+ // ChromeDownloadManagerDelegate::OnDownloadTargetDetermined to see if there
+ // is a target collision.
+ static bool CheckDownloadPathForExistingDownload(
+ const base::FilePath& target_path,
+ DownloadItem* download_item);
+
static scoped_refptr<base::SequencedTaskRunner> GetTaskRunner();
};
diff --git a/chromium/components/download/public/common/download_response_handler.h b/chromium/components/download/public/common/download_response_handler.h
index b0967deba49..ce94c9a0560 100644
--- a/chromium/components/download/public/common/download_response_handler.h
+++ b/chromium/components/download/public/common/download_response_handler.h
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "base/optional.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_export.h"
#include "components/download/public/common/download_source.h"
@@ -17,6 +18,7 @@
#include "net/cert/cert_status_flags.h"
#include "services/network/public/cpp/resource_response.h"
#include "services/network/public/mojom/url_loader.mojom.h"
+#include "url/origin.h"
namespace download {
@@ -60,7 +62,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler
void OnUploadProgress(int64_t current_position,
int64_t total_size,
OnUploadProgressCallback callback) override;
- void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override;
+ void OnReceiveCachedMetadata(mojo_base::BigBuffer data) override;
void OnTransferSizeUpdated(int32_t transfer_size_diff) override;
void OnStartLoadingResponseBody(
mojo::ScopedDataPipeConsumerHandle body) override;
@@ -94,7 +96,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler
DownloadSource download_source_;
net::CertStatus cert_status_;
bool has_strong_validators_;
- GURL origin_;
+ base::Optional<url::Origin> request_initiator_;
bool is_partial_request_;
bool completed_;
diff --git a/chromium/components/download/public/common/download_save_info.cc b/chromium/components/download/public/common/download_save_info.cc
index 2b25b628c44..c66a6003f03 100644
--- a/chromium/components/download/public/common/download_save_info.cc
+++ b/chromium/components/download/public/common/download_save_info.cc
@@ -15,4 +15,8 @@ DownloadSaveInfo::~DownloadSaveInfo() = default;
DownloadSaveInfo::DownloadSaveInfo(DownloadSaveInfo&& that) = default;
+int64_t DownloadSaveInfo::GetStartingFileWriteOffset() {
+ return file_offset >= 0 ? file_offset : offset;
+}
+
} // namespace download
diff --git a/chromium/components/download/public/common/download_save_info.h b/chromium/components/download/public/common/download_save_info.h
index a1e00c8755a..9f249c7bda6 100644
--- a/chromium/components/download/public/common/download_save_info.h
+++ b/chromium/components/download/public/common/download_save_info.h
@@ -30,6 +30,8 @@ struct COMPONENTS_DOWNLOAD_EXPORT DownloadSaveInfo {
~DownloadSaveInfo();
DownloadSaveInfo(DownloadSaveInfo&& that);
+ int64_t GetStartingFileWriteOffset();
+
// If non-empty, contains the full target path of the download that has been
// determined prior to download initiation. This is considered to be a trusted
// path.
@@ -42,9 +44,18 @@ struct COMPONENTS_DOWNLOAD_EXPORT DownloadSaveInfo {
// If valid, contains the source data stream for the file contents.
base::File file;
- // The file offset at which to start the download.
+ // The offset sent to the server when requesting the download. During
+ // resumption, |offset| could be smaller than the downloaded content length.
+ // This is because download may request some data to validate whether the
+ // content has changed.
int64_t offset = 0;
+ // The file offset to start writing to disk. If this value is negative,
+ // download stream will be writing to the disk starting at |offset|.
+ // Otherwise, this value will be used. Data received before |file_offset| are
+ // used for validation purpose.
+ int64_t file_offset = -1;
+
// The number of the bytes to download from |offset|.
// Ask to retrieve segment of the download file when length is greater than 0.
// Request the rest of the file starting from |offset|, when length is
diff --git a/chromium/components/download/public/common/download_stats.h b/chromium/components/download/public/common/download_stats.h
index b01123d1a91..7e10804bac4 100644
--- a/chromium/components/download/public/common/download_stats.h
+++ b/chromium/components/download/public/common/download_stats.h
@@ -15,6 +15,7 @@
#include "base/callback.h"
#include "base/optional.h"
+#include "build/build_config.h"
#include "components/download/public/common/download_content.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_export.h"
@@ -219,6 +220,21 @@ enum class ParallelDownloadCreationEvent {
COUNT,
};
+// Reason for download to restart during resumption. These enum values are
+// persisted to logs, and should therefore never be renumbered nor removed.
+enum class ResumptionRestartCountTypes {
+ // The download is restarted due to server response.
+ kRequestedByServerCount = 0,
+
+ // Strong validator changes.
+ kStrongValidatorChangesCount = 1,
+
+ // No strong validators are present.
+ kMissingStrongValidatorsCount = 2,
+
+ kMaxValue = kMissingStrongValidatorsCount
+};
+
// Increment one of the above counts.
COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadCount(DownloadCountTypes type);
@@ -231,7 +247,9 @@ COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadCountWithSource(
COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadCompleted(
int64_t download_len,
bool is_parallelizable,
- DownloadSource download_source);
+ DownloadSource download_source,
+ bool has_resumed,
+ bool has_strong_validators);
// Record download deletion event.
COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadDeletion(
@@ -410,6 +428,30 @@ COMPONENTS_DOWNLOAD_EXPORT void RecordInProgressDBCount(
COMPONENTS_DOWNLOAD_EXPORT void RecordDuplicateInProgressDownloadIdCount(
int count);
+
+// Records the interrupt reason that causes download to restart.
+COMPONENTS_DOWNLOAD_EXPORT void RecordResumptionRestartReason(
+ DownloadInterruptReason reason);
+
+// Records the interrupt reason that causes download to restart.
+COMPONENTS_DOWNLOAD_EXPORT void RecordResumptionStrongValidators(
+ DownloadInterruptReason reason);
+
+COMPONENTS_DOWNLOAD_EXPORT void RecordResumptionRestartCount(
+ ResumptionRestartCountTypes type);
+
+// Records that download was resumed.
+COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadResumed(
+ bool has_strong_validators);
+
+#if defined(OS_ANDROID)
+// Records the download interrupt reason for the first background download.
+// If |download_started| is true, this records the last interrupt reason
+// before download is started manually or by the task scheduler.
+COMPONENTS_DOWNLOAD_EXPORT void RecordFirstBackgroundDownloadInterruptReason(
+ DownloadInterruptReason reason,
+ bool download_started);
+#endif // defined(OS_ANDROID)
} // namespace download
#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_STATS_H_
diff --git a/chromium/components/download/public/common/download_url_parameters.h b/chromium/components/download/public/common/download_url_parameters.h
index eb9422c7947..f276eddce7a 100644
--- a/chromium/components/download/public/common/download_url_parameters.h
+++ b/chromium/components/download/public/common/download_url_parameters.h
@@ -180,6 +180,12 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
// See |DownloadSaveInfo.length|.
void set_length(int64_t length) { save_info_.length = length; }
+ // Sets the offset to start writing to the file. If set, The data received
+ // before |file_offset| are discarded or are used for validation purpose.
+ void set_file_offset(int64_t file_offset) {
+ save_info_.file_offset = file_offset;
+ }
+
// If |offset| is non-zero, then |hash_of_partial_file| contains the raw
// SHA-256 hash of the first |offset| bytes of the target file. Only
// meaningful if a partial file exists and is identified by either the
diff --git a/chromium/components/download/public/common/download_utils.h b/chromium/components/download/public/common/download_utils.h
index dfeb282af22..9e609fee9f1 100644
--- a/chromium/components/download/public/common/download_utils.h
+++ b/chromium/components/download/public/common/download_utils.h
@@ -101,6 +101,15 @@ COMPONENTS_DOWNLOAD_EXPORT bool DeleteDownloadedFile(
COMPONENTS_DOWNLOAD_EXPORT download::DownloadItem::DownloadRenameResult
RenameDownloadedFile(const base::FilePath& from_path,
const base::FilePath& to_path);
+
+// Finch parameter key value for number of bytes used for content validation
+// during resumption.
+constexpr char kDownloadContentValidationLengthFinchKey[] =
+ "download_validation_length";
+
+// Get the number of bytes to validate from finch configuration.
+int64_t GetDownloadValidationLengthConfig();
+
} // namespace download
#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_UTILS_H_
diff --git a/chromium/components/download/public/common/in_progress_download_manager.h b/chromium/components/download/public/common/in_progress_download_manager.h
index 08aa242dd8a..aaa886466d5 100644
--- a/chromium/components/download/public/common/in_progress_download_manager.h
+++ b/chromium/components/download/public/common/in_progress_download_manager.h
@@ -24,11 +24,15 @@
namespace net {
class URLRequestContextGetter;
-}
+} // namespace net
namespace network {
struct ResourceResponse;
-}
+} // namespace network
+
+namespace service_manager {
+class Connector;
+} // namespace service_manager
namespace download {
@@ -54,13 +58,16 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
// Class to be notified when download starts/stops.
class COMPONENTS_DOWNLOAD_EXPORT Delegate {
public:
+ // Called when in-progress downloads are initialized.
+ virtual void OnDownloadsInitialized() {}
+
// Intercepts the download to another system if applicable. Returns true if
// the download was intercepted.
virtual bool InterceptDownload(
- const DownloadCreateInfo& download_create_info) = 0;
+ const DownloadCreateInfo& download_create_info);
// Gets the default download directory.
- virtual base::FilePath GetDefaultDownloadDirectory() = 0;
+ virtual base::FilePath GetDefaultDownloadDirectory();
// Gets the download item for the given |download_create_info|.
// TODO(qinmin): remove this method and let InProgressDownloadManager
@@ -68,23 +75,25 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
virtual void StartDownloadItem(
std::unique_ptr<DownloadCreateInfo> info,
const DownloadUrlParameters::OnStartedCallback& on_started,
- StartDownloadItemCallback callback) = 0;
+ StartDownloadItemCallback callback) {}
// Gets the URLRequestContextGetter for sending requests.
// TODO(qinmin): remove this once network service is fully enabled.
virtual net::URLRequestContextGetter* GetURLRequestContextGetter(
- const DownloadCreateInfo& download_create_info) = 0;
+ const DownloadCreateInfo& download_create_info);
};
using IsOriginSecureCallback = base::RepeatingCallback<bool(const GURL&)>;
InProgressDownloadManager(Delegate* delegate,
const base::FilePath& in_progress_db_dir,
const IsOriginSecureCallback& is_origin_secure_cb,
- const URLSecurityPolicy& url_security_policy);
+ const URLSecurityPolicy& url_security_policy,
+ service_manager::Connector* connector);
~InProgressDownloadManager() override;
// SimpleDownloadManager implementation.
- bool DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override;
+ void DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override;
+ bool CanDownload(DownloadUrlParameters* params) override;
void GetAllDownloads(
SimpleDownloadManager::DownloadVector* downloads) override;
DownloadItem* GetDownloadByGuid(const std::string& guid) override;
@@ -139,6 +148,15 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
download_start_observer_ = observer;
}
+ // Callback to generate an intermediate file path from the given target file
+ // path;
+ using IntermediatePathCallback =
+ base::RepeatingCallback<base::FilePath(const base::FilePath&)>;
+ void set_intermediate_path_cb(
+ const IntermediatePathCallback& intermediate_path_cb) {
+ intermediate_path_cb_ = intermediate_path_cb;
+ }
+
// Called to get all in-progress DownloadItemImpl.
// TODO(qinmin): remove this method once InProgressDownloadManager owns
// all in-progress downloads.
@@ -164,7 +182,7 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
url_loader_factory_getter_ = std::move(url_loader_factory_getter);
}
- void set_delegate(Delegate* delegate) { delegate_ = delegate; }
+ void SetDelegate(Delegate* delegate);
void set_is_origin_secure_cb(
const IsOriginSecureCallback& is_origin_secure_cb) {
@@ -205,6 +223,12 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
DownloadItemImpl* download,
bool should_persist_new_download);
+ // Called when downloads are initialized.
+ void OnDownloadsInitialized();
+
+ // Called to notify |delegate_| that downloads are initialized.
+ void NotifyDownloadsInitialized();
+
// Active download handlers.
std::vector<UrlDownloadHandler::UniqueUrlDownloadHandlerPtr>
url_download_handlers_;
@@ -234,6 +258,9 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
// callback to check if an origin is secure.
IsOriginSecureCallback is_origin_secure_cb_;
+ // callback to generate the intermediate file path.
+ IntermediatePathCallback intermediate_path_cb_;
+
// A list of in-progress download items, could be null if DownloadManagerImpl
// is managing all downloads.
std::vector<std::unique_ptr<DownloadItemImpl>> in_progress_downloads_;
@@ -255,6 +282,9 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager
// Whether this object uses an empty database and no history will be saved.
bool use_empty_db_;
+ // Connector to the service manager.
+ service_manager::Connector* connector_;
+
base::WeakPtrFactory<InProgressDownloadManager> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(InProgressDownloadManager);
diff --git a/chromium/components/download/public/common/mock_download_file.h b/chromium/components/download/public/common/mock_download_file.h
index 53f016cb4ac..b30b1672c35 100644
--- a/chromium/components/download/public/common/mock_download_file.h
+++ b/chromium/components/download/public/common/mock_download_file.h
@@ -75,6 +75,7 @@ class MockDownloadFile : public DownloadFile {
const std::string& mime_type,
const RenameCompletionCallback& callback));
MOCK_METHOD1(PublishDownload, void(const RenameCompletionCallback& callback));
+ MOCK_METHOD0(GetDisplayName, base::FilePath());
#endif // defined(OS_ANDROID)
};
diff --git a/chromium/components/download/public/common/mock_download_item.h b/chromium/components/download/public/common/mock_download_item.h
index 98420c1f6aa..09ea72f712a 100644
--- a/chromium/components/download/public/common/mock_download_item.h
+++ b/chromium/components/download/public/common/mock_download_item.h
@@ -12,11 +12,13 @@
#include "base/callback.h"
#include "base/observer_list.h"
+#include "base/optional.h"
#include "base/time/time.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace download {
@@ -65,6 +67,7 @@ class MockDownloadItem : public DownloadItem {
MOCK_CONST_METHOD0(GetSiteUrl, const GURL&());
MOCK_CONST_METHOD0(GetTabUrl, const GURL&());
MOCK_CONST_METHOD0(GetTabReferrerUrl, const GURL&());
+ MOCK_CONST_METHOD0(GetRequestInitiator, const base::Optional<url::Origin>&());
MOCK_CONST_METHOD0(GetSuggestedFilename, std::string());
MOCK_CONST_METHOD0(GetContentDisposition, std::string());
MOCK_CONST_METHOD0(GetResponseHeaders,
diff --git a/chromium/components/download/public/common/mock_download_item_impl.cc b/chromium/components/download/public/common/mock_download_item_impl.cc
index 5282defc5f2..05b6a9117fc 100644
--- a/chromium/components/download/public/common/mock_download_item_impl.cc
+++ b/chromium/components/download/public/common/mock_download_item_impl.cc
@@ -17,6 +17,7 @@ MockDownloadItemImpl::MockDownloadItemImpl(DownloadItemImplDelegate* delegate)
GURL(),
GURL(),
GURL(),
+ url::Origin(),
"application/octet-stream",
"application/octet-stream",
base::Time(),
diff --git a/chromium/components/download/public/common/mock_download_item_impl.h b/chromium/components/download/public/common/mock_download_item_impl.h
index 7bbb9589d24..612485d1f7b 100644
--- a/chromium/components/download/public/common/mock_download_item_impl.h
+++ b/chromium/components/download/public/common/mock_download_item_impl.h
@@ -10,11 +10,13 @@
#include <vector>
#include "base/macros.h"
+#include "base/optional.h"
#include "components/download/public/common/download_create_info.h"
#include "components/download/public/common/download_file.h"
#include "components/download/public/common/download_item_impl.h"
#include "components/download/public/common/download_request_handle_interface.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "url/origin.h"
namespace download {
@@ -81,6 +83,7 @@ class MockDownloadItemImpl : public DownloadItemImpl {
MOCK_CONST_METHOD0(GetReferrerUrl, const GURL&());
MOCK_CONST_METHOD0(GetTabUrl, const GURL&());
MOCK_CONST_METHOD0(GetTabReferrerUrl, const GURL&());
+ MOCK_CONST_METHOD0(GetRequestInitiator, const base::Optional<url::Origin>&());
MOCK_CONST_METHOD0(GetSuggestedFilename, std::string());
MOCK_CONST_METHOD0(GetContentDisposition, std::string());
MOCK_CONST_METHOD0(GetMimeType, std::string());
diff --git a/chromium/components/download/public/common/mock_simple_download_manager.cc b/chromium/components/download/public/common/mock_simple_download_manager.cc
new file mode 100644
index 00000000000..0189b58078c
--- /dev/null
+++ b/chromium/components/download/public/common/mock_simple_download_manager.cc
@@ -0,0 +1,22 @@
+// Copyright 2019 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/mock_simple_download_manager.h"
+
+namespace download {
+
+MockSimpleDownloadManager::MockSimpleDownloadManager() = default;
+
+MockSimpleDownloadManager::~MockSimpleDownloadManager() = default;
+
+void MockSimpleDownloadManager::NotifyOnDownloadInitialized() {
+ OnInitialized();
+}
+
+void MockSimpleDownloadManager::NotifyOnNewDownloadCreated(DownloadItem* item) {
+ for (auto& observer : simple_download_manager_observers_)
+ observer.OnDownloadCreated(item);
+}
+
+} // namespace download
diff --git a/chromium/components/download/public/common/mock_simple_download_manager.h b/chromium/components/download/public/common/mock_simple_download_manager.h
new file mode 100644
index 00000000000..9a878f7cef7
--- /dev/null
+++ b/chromium/components/download/public/common/mock_simple_download_manager.h
@@ -0,0 +1,44 @@
+// Copyright 2019 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_PUBLIC_COMMON_MOCK_SIMPLE_DOWNLOAD_MANAGER_H_
+#define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_MOCK_SIMPLE_DOWNLOAD_MANAGER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/observer_list.h"
+#include "components/download/public/common/simple_download_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace download {
+
+class MockSimpleDownloadManager : public SimpleDownloadManager {
+ public:
+ MockSimpleDownloadManager();
+ ~MockSimpleDownloadManager() override;
+
+ // Dispatches an OnNewDownloadCreated() notification to observers.
+ void NotifyOnNewDownloadCreated(DownloadItem* item);
+
+ // Notifies observers that downloads is initialized.
+ void NotifyOnDownloadInitialized();
+
+ void DownloadUrl(std::unique_ptr<DownloadUrlParameters> params) override {
+ DownloadUrlMock(params.get());
+ }
+
+ MOCK_METHOD1(CanDownload, bool(DownloadUrlParameters*));
+ MOCK_METHOD1(DownloadUrlMock, void(DownloadUrlParameters*));
+ MOCK_METHOD1(GetDownloadByGuid, DownloadItem*(const std::string&));
+ MOCK_METHOD1(GetAllDownloads, void(DownloadVector* downloads));
+
+ private:
+ base::ObserverList<Observer>::Unchecked observers_;
+};
+
+} // namespace download
+
+#endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_MOCK_SIMPLE_DOWNLOAD_MANAGER_H_
diff --git a/chromium/components/download/public/common/simple_download_manager.h b/chromium/components/download/public/common/simple_download_manager.h
index 234138e47f5..8a3bd82d5a4 100644
--- a/chromium/components/download/public/common/simple_download_manager.h
+++ b/chromium/components/download/public/common/simple_download_manager.h
@@ -26,6 +26,7 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManager {
Observer() = default;
virtual ~Observer() = default;
+ virtual void OnDownloadsInitialized() {}
virtual void OnManagerGoingDown() {}
virtual void OnDownloadCreated(DownloadItem* item) {}
@@ -39,14 +40,14 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManager {
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
- // Calls the callback if this object becomes initialized.
- void NotifyWhenInitialized(base::OnceClosure callback);
-
// Download a URL given by the |params|. Returns true if the download could
// take place, or false otherwise.
- virtual bool DownloadUrl(
+ virtual void DownloadUrl(
std::unique_ptr<DownloadUrlParameters> parameters) = 0;
+ // Returns whether the manager can handle this download.
+ virtual bool CanDownload(DownloadUrlParameters* parameters) = 0;
+
using DownloadVector = std::vector<DownloadItem*>;
// Add all download items to |downloads|, no matter the type or state, without
// clearing |downloads| first.
@@ -62,15 +63,14 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManager {
// Called when a new download is created.
void OnNewDownloadCreated(DownloadItem* download);
+ // Notify observers that this object is initialized.
+ void NotifyInitialized();
+
// Whether this object is initialized.
bool initialized_ = false;
// Observers that want to be notified of changes to the set of downloads.
base::ObserverList<Observer>::Unchecked simple_download_manager_observers_;
-
- private:
- // Callbacks to call once this object is initialized.
- std::vector<base::OnceClosure> on_initialized_callbacks_;
};
} // namespace download
diff --git a/chromium/components/download/public/common/simple_download_manager_coordinator.h b/chromium/components/download/public/common/simple_download_manager_coordinator.h
index 03ebf4e643c..c610486ed2a 100644
--- a/chromium/components/download/public/common/simple_download_manager_coordinator.h
+++ b/chromium/components/download/public/common/simple_download_manager_coordinator.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "components/download/public/common/download_export.h"
@@ -42,7 +43,10 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManagerCoordinator
DISALLOW_COPY_AND_ASSIGN(Observer);
};
- SimpleDownloadManagerCoordinator();
+ using DownloadWhenFullManagerStartsCallBack =
+ base::RepeatingCallback<void(std::unique_ptr<DownloadUrlParameters>)>;
+ SimpleDownloadManagerCoordinator(const DownloadWhenFullManagerStartsCallBack&
+ download_when_full_manager_starts_cb);
~SimpleDownloadManagerCoordinator() override;
void AddObserver(Observer* observer);
@@ -63,22 +67,20 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManagerCoordinator
// Get the download item for |guid|.
DownloadItem* GetDownloadByGuid(const std::string& guid);
- // Return whether this object has download manager set.
- bool HasSetDownloadManager();
-
// Returns a non-empty notifier to be used for observing download events.
AllDownloadEventNotifier* GetNotifier();
+ // Whether this object is initialized.
+ bool initialized() const { return initialized_; }
+
bool has_all_history_downloads() const { return has_all_history_downloads_; }
private:
// SimpleDownloadManager::Observer implementation.
+ void OnDownloadsInitialized() override;
void OnManagerGoingDown() override;
void OnDownloadCreated(DownloadItem* item) override;
- // Called when |simple_download_manager_| is initialized.
- void OnManagerInitialized(bool has_all_history_downloads);
-
SimpleDownloadManager* simple_download_manager_;
// Object for notifying others about various download events.
@@ -87,10 +89,16 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManagerCoordinator
// Whether all the history downloads are ready.
bool has_all_history_downloads_;
+ // Whether current SimpleDownloadManager has all history downloads.
+ bool current_manager_has_all_history_downloads_;
+
// Whether this object is initialized and active downloads are ready to be
// retrieved.
bool initialized_;
+ // Callback to download the url when full manager becomes ready.
+ DownloadWhenFullManagerStartsCallBack download_when_full_manager_starts_cb_;
+
// Observers that want to be notified of changes to the set of downloads.
base::ObserverList<Observer>::Unchecked observers_;
diff --git a/chromium/components/download/public/common/url_download_handler_factory.h b/chromium/components/download/public/common/url_download_handler_factory.h
index bbe7195e199..8b30691e11d 100644
--- a/chromium/components/download/public/common/url_download_handler_factory.h
+++ b/chromium/components/download/public/common/url_download_handler_factory.h
@@ -11,7 +11,11 @@
namespace net {
class URLRequestContextGetter;
-}
+} // namespace net
+
+namespace service_manager {
+class Connector;
+} // namespace service_manager
namespace download {
class DownloadURLLoaderFactoryGetter;
@@ -35,6 +39,7 @@ class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadHandlerFactory {
url_loader_factory_getter,
const URLSecurityPolicy& url_security_policy,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
virtual ~UrlDownloadHandlerFactory();
@@ -52,6 +57,7 @@ class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadHandlerFactory {
url_loader_factory_getter,
const URLSecurityPolicy& url_security_policy,
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
+ std::unique_ptr<service_manager::Connector> connector,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) = 0;
};
diff --git a/chromium/components/download/quarantine/BUILD.gn b/chromium/components/download/quarantine/BUILD.gn
index 4ce7b5bdc11..395de65b0b6 100644
--- a/chromium/components/download/quarantine/BUILD.gn
+++ b/chromium/components/download/quarantine/BUILD.gn
@@ -2,113 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build/config/chromecast_build.gni")
-
-if (is_android) {
- import("//build/config/android/rules.gni")
-}
-
static_library("quarantine") {
sources = [
"quarantine.cc",
"quarantine.h",
- "quarantine_features_win.cc",
- "quarantine_features_win.h",
- "quarantine_mac.mm",
- "quarantine_win.cc",
- ]
-
- deps = [
- ":common",
- "//base",
- "//net",
- "//url",
- ]
-
- if (is_mac) {
- libs = [
- "Carbon.framework",
- "Foundation.framework",
- ]
- }
-}
-
-source_set("common") {
- sources = [
- "common_mac.h",
- "common_mac.mm",
- "common_win.cc",
- "common_win.h",
]
deps = [
- "//base",
+ "//components/services/quarantine",
]
-
- if (is_mac) {
- libs = [
- "Carbon.framework",
- "Foundation.framework",
- ]
- }
-}
-
-source_set("test_support") {
- testonly = true
-
- sources = [
- "test_support.cc",
- "test_support.h",
- "test_support_mac.mm",
- "test_support_win.cc",
- ]
-
- deps = [
- ":common",
- ":quarantine",
- "//base",
- "//url",
- ]
-
- if (is_mac) {
- libs = [
- "Carbon.framework",
- "Foundation.framework",
- ]
- }
-}
-
-source_set("unit_tests") {
- testonly = true
-
- sources = [
- "quarantine_mac_unittest.mm",
- "quarantine_win_unittest.cc",
- ]
-
- # Chromecasts do not have extended attributes enabled; even if it were
- # enabled, the devices use tmpfs which restricts the extended attributes that
- # can be set such that quarantining still would not work. (The platform
- # specific tests include a runtime guard to skip tests that need xattr.)
- if (!is_chromecast) {
- sources += [ "quarantine_unittest.cc" ]
- }
-
- deps = [
- ":common",
- ":quarantine",
- ":test_support",
- "//base",
- "//base/test:test_support",
- "//net",
- "//testing/gtest",
- "//url",
- ]
-
- if (is_mac) {
- libs = [
- "Carbon.framework",
- "Foundation.framework",
- ]
- }
}
diff --git a/chromium/components/download/quarantine/DEPS b/chromium/components/download/quarantine/DEPS
index 9d3031f8980..ad6fcad01aa 100644
--- a/chromium/components/download/quarantine/DEPS
+++ b/chromium/components/download/quarantine/DEPS
@@ -1,3 +1,3 @@
include_rules = [
- "+net/base/filename_util.h",
+ "+components/services/quarantine/quarantine.h",
]
diff --git a/chromium/components/download/quarantine/common_mac.h b/chromium/components/download/quarantine/common_mac.h
deleted file mode 100644
index 179bb137ce0..00000000000
--- a/chromium/components/download/quarantine/common_mac.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// 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.
-
-#ifndef COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_MAC_H_
-#define COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_MAC_H_
-
-#import <Foundation/Foundation.h>
-
-#include "base/mac/scoped_nsobject.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace download {
-
-bool GetQuarantineProperties(
- const base::FilePath& file,
- base::scoped_nsobject<NSMutableDictionary>* properties);
-
-} // namespace download
-
-#endif // COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_MAC_H_
diff --git a/chromium/components/download/quarantine/common_mac.mm b/chromium/components/download/quarantine/common_mac.mm
deleted file mode 100644
index a8ccaeba2b3..00000000000
--- a/chromium/components/download/quarantine/common_mac.mm
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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/quarantine/common_mac.h"
-
-#import <ApplicationServices/ApplicationServices.h>
-
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/mac/availability.h"
-#include "base/mac/foundation_util.h"
-#include "base/mac/mac_logging.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/strings/sys_string_conversions.h"
-
-namespace download {
-
-bool GetQuarantineProperties(
- const base::FilePath& file,
- base::scoped_nsobject<NSMutableDictionary>* properties) {
- base::scoped_nsobject<NSURL> file_url([[NSURL alloc]
- initFileURLWithPath:base::SysUTF8ToNSString(file.value())]);
- if (!file_url)
- return false;
-
- NSError* error = nil;
- id quarantine_properties = nil;
- BOOL success = [file_url getResourceValue:&quarantine_properties
- forKey:NSURLQuarantinePropertiesKey
- error:&error];
- if (!success) {
- std::string error_message(error ? error.description.UTF8String : "");
- LOG(WARNING) << "Unable to get quarantine attributes for file "
- << file.value() << ". Error: " << error_message;
- return false;
- }
-
- if (!quarantine_properties)
- return true;
-
- NSDictionary* quarantine_properties_dict =
- base::mac::ObjCCast<NSDictionary>(quarantine_properties);
- if (!quarantine_properties_dict) {
- LOG(WARNING) << "Quarantine properties have wrong class: "
- << base::SysNSStringToUTF8(
- [[quarantine_properties class] description]);
- return false;
- }
-
- properties->reset([quarantine_properties_dict mutableCopy]);
- return true;
-}
-
-} // namespace download
diff --git a/chromium/components/download/quarantine/common_win.cc b/chromium/components/download/quarantine/common_win.cc
deleted file mode 100644
index f9d5cd9de6f..00000000000
--- a/chromium/components/download/quarantine/common_win.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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/quarantine/common_win.h"
-
-namespace download {
-
-// [MS-FSCC] Section 5.6.1
-const base::FilePath::CharType kZoneIdentifierStreamSuffix[] =
- FILE_PATH_LITERAL(":Zone.Identifier");
-
-} // namespace download
diff --git a/chromium/components/download/quarantine/common_win.h b/chromium/components/download/quarantine/common_win.h
deleted file mode 100644
index b75de7b811a..00000000000
--- a/chromium/components/download/quarantine/common_win.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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.
-
-#ifndef COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_WIN_H_
-#define COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_WIN_H_
-
-#include "base/files/file_path.h"
-
-namespace download {
-
-extern const base::FilePath::CharType kZoneIdentifierStreamSuffix[];
-
-} // namespace download
-
-#endif // COMPONENTS_DOWNLOAD_QUARANTINE_COMMON_WIN_H_
diff --git a/chromium/components/download/quarantine/quarantine.cc b/chromium/components/download/quarantine/quarantine.cc
index ac5b109edd0..b576c4de1f7 100644
--- a/chromium/components/download/quarantine/quarantine.cc
+++ b/chromium/components/download/quarantine/quarantine.cc
@@ -4,19 +4,14 @@
#include "components/download/quarantine/quarantine.h"
-#include "build/build_config.h"
-
-#if !defined(OS_WIN) && !defined(OS_MACOSX)
-
namespace download {
QuarantineFileResult QuarantineFile(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url,
const std::string& client_guid) {
- return QuarantineFileResult::OK;
+ return quarantine::QuarantineFile(file, source_url, referrer_url,
+ client_guid);
}
} // namespace download
-
-#endif // !WIN && !MAC
diff --git a/chromium/components/download/quarantine/quarantine.h b/chromium/components/download/quarantine/quarantine.h
index 8393e4a707a..eb6e94691f3 100644
--- a/chromium/components/download/quarantine/quarantine.h
+++ b/chromium/components/download/quarantine/quarantine.h
@@ -7,6 +7,8 @@
#include <string>
+#include "components/services/quarantine/quarantine.h"
+
class GURL;
namespace base {
@@ -15,62 +17,17 @@ class FilePath;
namespace download {
-// Return value for QuarantineFile.
-enum class QuarantineFileResult {
- OK, // Success.
- ACCESS_DENIED, // Access to the file was denied. The safety of the file could
- // not be determined.
- BLOCKED_BY_POLICY, // Downloads from |source_url| are not allowed by policy.
- // The file has been deleted.
- ANNOTATION_FAILED, // Unable to write the mark-of-the-web or otherwise
- // annotate the file as being downloaded from
- // |source_url|.
- FILE_MISSING, // |file| does not name a valid file.
- SECURITY_CHECK_FAILED, // An unknown error occurred while checking |file|.
- // The file may have been deleted.
- VIRUS_INFECTED // |file| was found to be infected by a virus and was deleted.
-};
+using quarantine::QuarantineFileResult;
// Quarantine a file that was downloaded from the internet.
+// See components/services/quarantine/quarantine.h for a full explanation.
//
-// Ensures that |file| is handled as safely as possible given that it was
-// downloaded from |source_url|. The details of how a downloaded file is handled
-// are platform dependent. Please refer to the individual quarantine_<os>
-// implementation.
-//
-// This function should be called for all files downloaded from the internet and
-// placed in a manner discoverable by the user, or exposed to an external
-// application. Furthermore, it should be called:
-//
-// * **AFTER** all the data has been written to the file. On Windows, registered
-// anti-virus products will be invoked for scanning the contents of the file.
-// Hence it's important to have the final contents of the file be available at
-// the point at which this function is called.
-//
-// Exception: Zero-length files will be handled solely on the basis of the
-// |source_url| and the file type. This exception accommodates situations
-// where the file contents cannot be determined before it is made visible to
-// an external application.
-//
-// * **AFTER** the file has been renamed to its final name. The file type is
-// significant and is derived from the filename.
-//
-// * **BEFORE** the file is made visible to an external application or the user.
-// Security checks and mark-of-the-web annotations must be made prior to
-// exposing the file externally.
-//
-// Note that it is possible for this method to take a long time to complete
-// (several seconds or more). In addition to blocking during this time, this
-// delay also introduces a window during which a browser shutdown may leave the
-// downloaded file unannotated.
+// Forwards to the definition in components/services/quarantine.
+// This is a temporary state before the quarantine service is fully implemented,
+// when the call sites will be updated to use the service directly.
//
-// Parameters:
-// |file| : Final name of the file.
-// |source_url|: URL from which the file content was downloaded. This is empty
-// for off-the-record download.
-// |referrer_url|: Referring URL. This is empty for off-the-record download.
-// |client_guid|: Only used on Windows. Identifies the client application
-// that downloaded the file.
+// TODO: Delete this file (and all of components/download/quarantine)
+// when the quarantine service is implemented.
QuarantineFileResult QuarantineFile(const base::FilePath& file,
const GURL& source_url,
const GURL& referrer_url,
diff --git a/chromium/components/download/quarantine/quarantine_features_win.cc b/chromium/components/download/quarantine/quarantine_features_win.cc
deleted file mode 100644
index 6c67f2e1e17..00000000000
--- a/chromium/components/download/quarantine/quarantine_features_win.cc
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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/quarantine/quarantine_features_win.h"
-
-namespace download {
-
-// This feature controls whether the InvokeAttachmentServices function will be
-// called. Has no effect on machines that are domain-joined, where the function
-// is always called.
-const base::Feature kInvokeAttachmentServices{"InvokeAttachmentServices",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
-} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_features_win.h b/chromium/components/download/quarantine/quarantine_features_win.h
deleted file mode 100644
index 7363a0f4f88..00000000000
--- a/chromium/components/download/quarantine/quarantine_features_win.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// 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.
-
-#ifndef COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_FEATURES_WIN_H_
-#define COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_FEATURES_WIN_H_
-
-#include "base/feature_list.h"
-
-namespace download {
-
-extern const base::Feature kInvokeAttachmentServices;
-
-} // namespace download
-
-#endif // COMPONENTS_DOWNLOAD_QUARANTINE_QUARANTINE_FEATURES_WIN_H_
diff --git a/chromium/components/download/quarantine/quarantine_mac.mm b/chromium/components/download/quarantine/quarantine_mac.mm
deleted file mode 100644
index 26b783a0ec5..00000000000
--- a/chromium/components/download/quarantine/quarantine_mac.mm
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2016 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/quarantine/quarantine.h"
-
-#import <ApplicationServices/ApplicationServices.h>
-#import <Foundation/Foundation.h>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/mac/foundation_util.h"
-#include "base/mac/mac_logging.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/threading/scoped_blocking_call.h"
-#include "components/download/quarantine/common_mac.h"
-#include "url/gurl.h"
-
-namespace {
-
-bool SetQuarantineProperties(const base::FilePath& file,
- NSDictionary* properties) {
- base::scoped_nsobject<NSURL> file_url([[NSURL alloc]
- initFileURLWithPath:base::SysUTF8ToNSString(file.value())]);
- if (!file_url)
- return false;
-
- NSError* error = nil;
- bool success = [file_url setResourceValue:properties
- forKey:NSURLQuarantinePropertiesKey
- error:&error];
- if (!success) {
- std::string error_message(error ? error.description.UTF8String : "");
- LOG(WARNING) << "Unable to set quarantine attributes on file "
- << file.value() << ". Error: " << error_message;
- return false;
- }
- return true;
-}
-
-} // namespace
-
-namespace download {
-
-namespace {
-
-// As of Mac OS X 10.4 ("Tiger"), files can be tagged with metadata describing
-// various attributes. Metadata is integrated with the system's Spotlight
-// feature and is searchable. Ordinarily, metadata can only be set by
-// Spotlight importers, which requires that the importer own the target file.
-// However, there's an attribute intended to describe the origin of a
-// file, that can store the source URL and referrer of a downloaded file.
-// It's stored as a "com.apple.metadata:kMDItemWhereFroms" extended attribute,
-// structured as a binary1-format plist containing a list of sources. This
-// attribute can only be populated by the downloader, not a Spotlight importer.
-// Safari on 10.4 and later populates this attribute.
-//
-// With this metadata set, you can locate downloads by performing a Spotlight
-// search for their source or referrer URLs, either from within the Spotlight
-// UI or from the command line:
-// mdfind 'kMDItemWhereFroms == "http://releases.mozilla.org/*"'
-//
-// There is no documented API to set metadata on a file directly as of the
-// 10.5 SDK. The MDSetItemAttribute function does exist to perform this task,
-// but it's undocumented.
-//
-// Note that the Metadata.framework in CoreServices has been superseded by the
-// NSMetadata API (e.g. kMDItemWhereFroms -> NSMetadataItemWhereFromsKey, etc).
-// The NSMetadata API still is a query-only interface, with no way to set
-// attributes, so we continue to use the original API.
-bool AddOriginMetadataToFile(const base::FilePath& file,
- const GURL& source,
- const GURL& referrer) {
- base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
- base::BlockingType::MAY_BLOCK);
-
- // There's no declaration for MDItemSetAttribute in any known public SDK.
- // It exists in the 10.4 and 10.5 runtimes. To play it safe, do the lookup
- // at runtime instead of declaring it ourselves and linking against what's
- // provided. This has two benefits:
- // - If Apple relents and declares the function in a future SDK (it's
- // happened before), our build won't break.
- // - If Apple removes or renames the function in a future runtime, the
- // loader won't refuse to let the application launch. Instead, we'll
- // silently fail to set any metadata.
- using MDItemSetAttribute_type =
- OSStatus (*)(MDItemRef, CFStringRef, CFTypeRef);
- static MDItemSetAttribute_type md_item_set_attribute_func =
- []() -> MDItemSetAttribute_type {
- CFBundleRef metadata_bundle =
- CFBundleGetBundleWithIdentifier(CFSTR("com.apple.Metadata"));
- if (!metadata_bundle)
- return nullptr;
-
- return reinterpret_cast<MDItemSetAttribute_type>(
- CFBundleGetFunctionPointerForName(metadata_bundle,
- CFSTR("MDItemSetAttribute")));
- }();
- if (!md_item_set_attribute_func)
- return false;
-
- NSString* file_path = base::mac::FilePathToNSString(file);
- if (!file_path)
- return false;
-
- base::ScopedCFTypeRef<MDItemRef> md_item(
- MDItemCreate(kCFAllocatorDefault, base::mac::NSToCFCast(file_path)));
- if (!md_item) {
- LOG(WARNING) << "MDItemCreate failed for path " << file.value();
- return false;
- }
-
- // We won't put any more than 2 items into the attribute.
- NSMutableArray* list = [NSMutableArray arrayWithCapacity:2];
-
- // Follow Safari's lead: the first item in the list is the source URL of the
- // downloaded file. If the referrer is known, store that, too. The URLs may be
- // empty (e.g. files downloaded in Incognito mode); don't add empty URLs.
- NSString* origin_url = base::SysUTF8ToNSString(source.spec());
- if (origin_url && [origin_url length])
- [list addObject:origin_url];
- NSString* referrer_url = base::SysUTF8ToNSString(referrer.spec());
- if (referrer_url && [referrer_url length])
- [list addObject:referrer_url];
-
- if ([list count]) {
- md_item_set_attribute_func(md_item, kMDItemWhereFroms,
- base::mac::NSToCFCast(list));
- }
-
- return true;
-}
-
-// Adds quarantine metadata to the file, assuming it has already been
-// quarantined by the OS.
-// |source| should be the source URL for the download, and |referrer| should be
-// the URL the user initiated the download from.
-
-// The OS will automatically quarantine files due to the
-// LSFileQuarantineEnabled entry in our Info.plist, but it knows relatively
-// little about the files. We add more information about the download to
-// improve the UI shown by the OS when the users tries to open the file.
-bool AddQuarantineMetadataToFile(const base::FilePath& file,
- const GURL& source,
- const GURL& referrer) {
- base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
- base::BlockingType::MAY_BLOCK);
- base::scoped_nsobject<NSMutableDictionary> properties;
- bool success = GetQuarantineProperties(file, &properties);
-
- if (!success)
- return false;
-
- if (!properties) {
- // If there are no quarantine properties, then the file isn't quarantined
- // (e.g., because the user has set up exclusions for certain file types).
- // We don't want to add any metadata, because that will cause the file to
- // be quarantined against the user's wishes.
- return true;
- }
-
- // kLSQuarantineAgentNameKey, kLSQuarantineAgentBundleIdentifierKey, and
- // kLSQuarantineTimeStampKey are set for us (see LSQuarantine.h), so we only
- // need to set the values that the OS can't infer.
-
- if (![properties valueForKey:(NSString*)kLSQuarantineTypeKey]) {
- CFStringRef type = source.SchemeIsHTTPOrHTTPS()
- ? kLSQuarantineTypeWebDownload
- : kLSQuarantineTypeOtherDownload;
- [properties setValue:(NSString*)type
- forKey:(NSString*)kLSQuarantineTypeKey];
- }
-
- if (![properties valueForKey:(NSString*)kLSQuarantineOriginURLKey] &&
- referrer.is_valid()) {
- NSString* referrer_url = base::SysUTF8ToNSString(referrer.spec());
- [properties setValue:referrer_url
- forKey:(NSString*)kLSQuarantineOriginURLKey];
- }
-
- if (![properties valueForKey:(NSString*)kLSQuarantineDataURLKey] &&
- source.is_valid()) {
- NSString* origin_url = base::SysUTF8ToNSString(source.spec());
- [properties setValue:origin_url forKey:(NSString*)kLSQuarantineDataURLKey];
- }
-
- return SetQuarantineProperties(file, properties);
-}
-
-} // namespace
-
-QuarantineFileResult QuarantineFile(const base::FilePath& file,
- const GURL& source_url,
- const GURL& referrer_url,
- const std::string& client_guid) {
- if (!base::PathExists(file))
- return QuarantineFileResult::FILE_MISSING;
-
- // Don't consider it an error if we fail to add origin metadata.
- AddOriginMetadataToFile(file, source_url, referrer_url);
- bool quarantine_succeeded =
- AddQuarantineMetadataToFile(file, source_url, referrer_url);
- return quarantine_succeeded ? QuarantineFileResult::OK
- : QuarantineFileResult::ANNOTATION_FAILED;
-}
-
-} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_mac_unittest.mm b/chromium/components/download/quarantine/quarantine_mac_unittest.mm
deleted file mode 100644
index d37d5eefa9e..00000000000
--- a/chromium/components/download/quarantine/quarantine_mac_unittest.mm
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2016 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/quarantine/quarantine.h"
-
-#include <sys/xattr.h>
-
-#import <ApplicationServices/ApplicationServices.h>
-#import <Foundation/Foundation.h>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/mac/foundation_util.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/strings/sys_string_conversions.h"
-#include "components/download/quarantine/test_support.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/gtest_mac.h"
-#include "url/gurl.h"
-
-namespace download {
-namespace {
-
-class QuarantineMacTest : public testing::Test {
- public:
- QuarantineMacTest()
- : source_url_("http://www.source.example.com"),
- referrer_url_("http://www.referrer.example.com") {}
-
- protected:
- void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- ASSERT_TRUE(
- base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &test_file_));
- file_url_.reset([[NSURL alloc]
- initFileURLWithPath:base::SysUTF8ToNSString(test_file_.value())]);
-
- base::scoped_nsobject<NSMutableDictionary> properties(
- [[NSMutableDictionary alloc] init]);
- [properties
- setValue:@"com.google.Chrome"
- forKey:static_cast<NSString*>(kLSQuarantineAgentBundleIdentifierKey)];
- [properties setValue:@"Google Chrome.app"
- forKey:static_cast<NSString*>(kLSQuarantineAgentNameKey)];
- [properties setValue:@(1) forKey:@"kLSQuarantineIsOwnedByCurrentUserKey"];
- bool success = [file_url_ setResourceValue:properties
- forKey:NSURLQuarantinePropertiesKey
- error:nullptr];
- ASSERT_TRUE(success);
- }
-
- base::ScopedTempDir temp_dir_;
- base::FilePath test_file_;
- GURL source_url_;
- GURL referrer_url_;
- base::scoped_nsobject<NSURL> file_url_;
-};
-
-TEST_F(QuarantineMacTest, CheckMetadataSetCorrectly) {
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, source_url_, referrer_url_, ""));
- EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, referrer_url_));
-}
-
-TEST_F(QuarantineMacTest, SetMetadataMultipleTimes) {
- GURL dummy_url("http://www.dummy.example.com");
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, source_url_, referrer_url_, ""));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, dummy_url, dummy_url, ""));
- EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, referrer_url_));
-}
-
-TEST_F(QuarantineMacTest, IsFileQuarantined_NoFile) {
- base::FilePath does_not_exist = temp_dir_.GetPath().AppendASCII("a.jar");
- EXPECT_FALSE(IsFileQuarantined(does_not_exist, GURL(), GURL()));
-}
-
-TEST_F(QuarantineMacTest, IsFileQuarantined_NoAnnotationsOnFile) {
- EXPECT_FALSE(IsFileQuarantined(test_file_, GURL(), GURL()));
-}
-
-TEST_F(QuarantineMacTest, IsFileQuarantined_SourceUrlOnly) {
- ASSERT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, source_url_, GURL(), std::string()));
- EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, GURL()));
- EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), GURL()));
- EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), referrer_url_));
- EXPECT_FALSE(IsFileQuarantined(test_file_, referrer_url_, GURL()));
-}
-
-TEST_F(QuarantineMacTest, IsFileQuarantined_FullMetadata) {
- ASSERT_EQ(
- QuarantineFileResult::OK,
- QuarantineFile(test_file_, source_url_, referrer_url_, std::string()));
- EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), GURL()));
- EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, GURL()));
- EXPECT_TRUE(IsFileQuarantined(test_file_, source_url_, referrer_url_));
- EXPECT_TRUE(IsFileQuarantined(test_file_, GURL(), referrer_url_));
- EXPECT_FALSE(IsFileQuarantined(test_file_, source_url_, source_url_));
- EXPECT_FALSE(IsFileQuarantined(test_file_, referrer_url_, referrer_url_));
-}
-
-TEST_F(QuarantineMacTest, NoWhereFromsKeyIfNoURLs) {
- ASSERT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file_, GURL(), GURL(), std::string()));
-
- NSString* file_path = base::mac::FilePathToNSString(test_file_);
- ASSERT_NE(nullptr, file_path);
- base::ScopedCFTypeRef<MDItemRef> md_item(
- MDItemCreate(kCFAllocatorDefault, base::mac::NSToCFCast(file_path)));
- if (!md_item) {
- // The quarantine code ignores it if adding origin metadata fails. If for
- // some reason MDItemCreate fails (which it seems to do on the bots, not
- // sure why) just stop on the test.
- return;
- }
-
- base::ScopedCFTypeRef<CFTypeRef> attr(
- MDItemCopyAttribute(md_item, kMDItemWhereFroms));
- EXPECT_FALSE(attr);
-}
-
-} // namespace
-} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_unittest.cc b/chromium/components/download/quarantine/quarantine_unittest.cc
deleted file mode 100644
index a70fd27eb41..00000000000
--- a/chromium/components/download/quarantine/quarantine_unittest.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2016 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/quarantine/quarantine.h"
-
-#include <iterator>
-#include <string>
-
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/stl_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace download {
-
-namespace {
-
-const char kTestData[] = "It's okay to have a trailing nul.";
-const char kInternetURL[] = "http://example.com/some-url";
-const char kInternetReferrerURL[] = "http://example.com/some-other-url";
-const char kTestGUID[] = "69f8621d-c46a-4e88-b915-1ce5415cb008";
-
-} // namespace
-
-TEST(QuarantineTest, FileCanBeOpenedForReadAfterAnnotation) {
- base::ScopedTempDir test_dir;
- ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-
- base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.class");
- ASSERT_EQ(static_cast<int>(base::size(kTestData)),
- base::WriteFile(test_file, kTestData, base::size(kTestData)));
-
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(kInternetURL),
- GURL(kInternetReferrerURL), kTestGUID));
-
- std::string contents;
- EXPECT_TRUE(base::ReadFileToString(test_file, &contents));
- EXPECT_EQ(std::string(std::begin(kTestData), std::end(kTestData)), contents);
-}
-
-TEST(QuarantineTest, FileCanBeAnnotatedWithNoGUID) {
- base::ScopedTempDir test_dir;
- ASSERT_TRUE(test_dir.CreateUniqueTempDir());
-
- base::FilePath test_file = test_dir.GetPath().AppendASCII("foo.class");
- ASSERT_EQ(static_cast<int>(base::size(kTestData)),
- base::WriteFile(test_file, kTestData, base::size(kTestData)));
-
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(kInternetURL),
- GURL(kInternetReferrerURL), std::string()));
-}
-
-} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_win.cc b/chromium/components/download/quarantine/quarantine_win.cc
deleted file mode 100644
index eaf6370d144..00000000000
--- a/chromium/components/download/quarantine/quarantine_win.cc
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright 2016 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/quarantine/quarantine.h"
-
-#include <windows.h>
-#include <wrl/client.h>
-
-#include <cguid.h>
-#include <objbase.h>
-#include <shellapi.h>
-#include <shlobj.h>
-#include <shobjidl.h>
-#include <wininet.h>
-
-#include <vector>
-
-#include "base/enterprise_util.h"
-#include "base/feature_list.h"
-#include "base/files/file_util.h"
-#include "base/guid.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/threading/scoped_blocking_call.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/win_util.h"
-#include "base/win/windows_version.h"
-#include "components/download/quarantine/common_win.h"
-#include "components/download/quarantine/quarantine_features_win.h"
-#include "url/gurl.h"
-
-namespace download {
-namespace {
-
-// Returns true for a valid |url| whose length does not exceed
-// INTERNET_MAX_URL_LENGTH.
-bool IsValidUrlForAttachmentServices(const GURL& url) {
- return url.is_valid() && url.spec().size() <= INTERNET_MAX_URL_LENGTH;
-}
-
-// Sets the Zone Identifier on the file to "Internet" (3). Returns true if the
-// function succeeds, false otherwise. A failure is expected if alternate
-// streams are not supported, like a file on a FAT32 filesystem. This function
-// does not invoke Windows Attachment Execution Services.
-//
-// On Windows 10 or higher, the ReferrerUrl and HostUrl values are set according
-// to the behavior of the IAttachmentExecute interface.
-//
-// |full_path| is the path to the downloaded file.
-QuarantineFileResult SetInternetZoneIdentifierDirectly(
- const base::FilePath& full_path,
- const GURL& source_url,
- const GURL& referrer_url) {
- const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- std::wstring path = full_path.value() + kZoneIdentifierStreamSuffix;
- base::win::ScopedHandle file(::CreateFile(path.c_str(), GENERIC_WRITE, kShare,
- nullptr, OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL, nullptr));
- if (!file.IsValid())
- return QuarantineFileResult::ANNOTATION_FAILED;
-
- static const char kReferrerUrlFormat[] = "ReferrerUrl=%s\r\n";
- static const char kHostUrlFormat[] = "HostUrl=%s\r\n";
-
- std::string identifier = "[ZoneTransfer]\r\nZoneId=3\r\n";
- if (base::win::GetVersion() >= base::win::VERSION_WIN10) {
- // Match what the InvokeAttachmentServices() function will output, including
- // the order of the values.
- if (IsValidUrlForAttachmentServices(referrer_url)) {
- identifier.append(
- base::StringPrintf(kReferrerUrlFormat, referrer_url.spec().c_str()));
- }
- identifier.append(base::StringPrintf(
- kHostUrlFormat, IsValidUrlForAttachmentServices(source_url)
- ? source_url.spec().c_str()
- : "about:internet"));
- }
-
- // Don't include trailing null in data written.
- DWORD written = 0;
- BOOL write_result = ::WriteFile(file.Get(), identifier.c_str(),
- identifier.length(), &written, nullptr);
- BOOL flush_result = FlushFileBuffers(file.Get());
-
- return write_result && flush_result && written == identifier.length()
- ? QuarantineFileResult::OK
- : QuarantineFileResult::ANNOTATION_FAILED;
-}
-
-// Maps a return code from an unsuccessful IAttachmentExecute::Save() call to a
-// QuarantineFileResult.
-//
-// Typical return codes from IAttachmentExecute::Save():
-// S_OK : The file was okay. If any viruses were found, they were cleaned.
-// E_FAIL : Virus infected.
-// INET_E_SECURITY_PROBLEM : The file was blocked due to security policy.
-//
-// Any other return value indicates an unexpected error during the scan.
-QuarantineFileResult FailedSaveResultToQuarantineResult(HRESULT result) {
- switch (result) {
- case INET_E_SECURITY_PROBLEM: // 0x800c000e
- // This is returned if the download was blocked due to security
- // restrictions. E.g. if the source URL was in the Restricted Sites zone
- // and downloads are blocked on that zone, then the download would be
- // deleted and this error code is returned.
- return QuarantineFileResult::BLOCKED_BY_POLICY;
-
- case E_FAIL: // 0x80004005
- // Returned if an anti-virus product reports an infection in the
- // downloaded file during IAE::Save().
- return QuarantineFileResult::VIRUS_INFECTED;
-
- default:
- // Any other error that occurs during IAttachmentExecute::Save() likely
- // indicates a problem with the security check, but not necessarily the
- // download. This also includes cases where SUCCEEDED(result) is true. In
- // the latter case we are likely dealing with a situation where the file
- // is missing after a successful scan. See http://crbug.com/153212.
- return QuarantineFileResult::SECURITY_CHECK_FAILED;
- }
-}
-
-// Invokes IAttachmentExecute::Save on CLSID_AttachmentServices to validate the
-// downloaded file. The call may scan the file for viruses and if necessary,
-// annotate it with evidence. As a result of the validation, the file may be
-// deleted. See: http://msdn.microsoft.com/en-us/bb776299
-//
-// IAE::Save() will delete the file if it was found to be blocked by local
-// security policy or if it was found to be infected. The call may also delete
-// the file due to other failures (http://crbug.com/153212). In these cases,
-// |result| will contain the failure code.
-//
-// The return value is |false| iff the function fails to invoke
-// IAttachmentExecute::Save(). If the function returns |true|, then the result
-// of invoking IAttachmentExecute::Save() is stored in |result|.
-//
-// |full_path| : is the path to the downloaded file. This should be the final
-// path of the download. Must be present.
-// |source_url|: the source URL for the download. If empty, the source will
-// be set to 'about:internet'.
-// |referrer_url|: the referrer URL for the download. If empty, the referrer
-// will not be set.
-// |client_guid|: the GUID to be set in the IAttachmentExecute client slot.
-// Used to identify the app to the system AV function.
-// |result|: Receives the result of invoking IAttachmentExecute::Save().
-bool InvokeAttachmentServices(const base::FilePath& full_path,
- const GURL& source_url,
- const GURL& referrer_url,
- const GUID& client_guid,
- QuarantineFileResult* result) {
- Microsoft::WRL::ComPtr<IAttachmentExecute> attachment_services;
- HRESULT hr = ::CoCreateInstance(CLSID_AttachmentServices, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&attachment_services));
-
- if (FAILED(hr)) {
- // The thread must have COM initialized.
- DCHECK_NE(CO_E_NOTINITIALIZED, hr);
- return false;
- }
-
- // Note that it is mandatory to check the return values from here on out. If
- // setting one of the parameters fails, it could leave the object in a state
- // where the final Save() call will also fail.
-
- hr = attachment_services->SetClientGuid(client_guid);
- if (FAILED(hr))
- return false;
-
- hr = attachment_services->SetLocalPath(full_path.value().c_str());
- if (FAILED(hr))
- return false;
-
- // The source URL could be empty if it was not a valid URL, or was not HTTP/S,
- // or the download was off-the-record. If so, use "about:internet" as a
- // fallback URL. The latter is known to reliably map to the Internet zone.
- //
- // In addition, URLs that are longer than INTERNET_MAX_URL_LENGTH are also
- // known to cause problems for URLMon. Hence also use "about:internet" in
- // these cases. See http://crbug.com/601538.
- hr = attachment_services->SetSource(
- IsValidUrlForAttachmentServices(source_url)
- ? base::UTF8ToWide(source_url.spec()).c_str()
- : L"about:internet");
- if (FAILED(hr))
- return false;
-
- // Only set referrer if one is present and shorter than
- // INTERNET_MAX_URL_LENGTH. Also, the source_url is authoritative for
- // determining the relative danger of |full_path| so we don't consider it an
- // error if we have to skip the |referrer_url|.
- if (IsValidUrlForAttachmentServices(referrer_url)) {
- hr = attachment_services->SetReferrer(
- base::UTF8ToWide(referrer_url.spec()).c_str());
- if (FAILED(hr))
- return false;
- }
-
- HRESULT save_result = S_OK;
- {
- // This method has been known to take longer than 10 seconds in some
- // instances.
- SCOPED_UMA_HISTOGRAM_LONG_TIMER("Download.AttachmentServices.Duration");
- save_result = attachment_services->Save();
- }
-
- // If the download file is missing after the call, then treat this as an
- // interrupted download.
- //
- // If IAttachmentExecute::Save() failed, but the downloaded file is still
- // around, then don't interrupt the download. Attachment Execution Services
- // deletes the submitted file if the downloaded file is blocked by policy or
- // if it was found to be infected.
- //
- // If the file is still there, then the error could be due to Windows
- // Attachment Services not being available or some other error during the AES
- // invocation. In either case, we don't surface the error to the user.
- *result = base::PathExists(full_path)
- ? QuarantineFileResult::OK
- : FailedSaveResultToQuarantineResult(save_result);
-
- return true;
-}
-
-} // namespace
-
-QuarantineFileResult QuarantineFile(const base::FilePath& file,
- const GURL& source_url,
- const GURL& referrer_url,
- const std::string& client_guid) {
- base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
- base::BlockingType::MAY_BLOCK);
-
- int64_t file_size = 0;
- if (!base::PathExists(file) || !base::GetFileSize(file, &file_size))
- return QuarantineFileResult::FILE_MISSING;
-
- std::string braces_guid = "{" + client_guid + "}";
- GUID guid = GUID_NULL;
- if (base::IsValidGUID(client_guid)) {
- HRESULT hr = CLSIDFromString(base::UTF8ToUTF16(braces_guid).c_str(), &guid);
- if (FAILED(hr))
- guid = GUID_NULL;
- }
-
- if (file_size == 0 || IsEqualGUID(guid, GUID_NULL)) {
- // Calling InvokeAttachmentServices on an empty file can result in the file
- // being deleted. Also an anti-virus scan doesn't make a lot of sense to
- // perform on an empty file.
- return SetInternetZoneIdentifierDirectly(file, source_url, referrer_url);
- }
-
- // Check if the attachment services should be invoked based on the experiment
- // state. Not invoking the attachment services means that the Zone Identifier
- // will always be set to 3 (Internet), regardless of URL zones configurations.
- //
- // Note: The attachment services must always be invoked on domain-joined
- // machines.
- // TODO(pmonette): Move the InvokeAttachmentServices() call to a utility
- // process and remove the feature.
- bool should_invoke_attachment_services =
- base::IsMachineExternallyManaged() ||
- base::FeatureList::IsEnabled(kInvokeAttachmentServices);
-
- QuarantineFileResult attachment_services_result = QuarantineFileResult::OK;
- if (should_invoke_attachment_services &&
- InvokeAttachmentServices(file, source_url, referrer_url, guid,
- &attachment_services_result)) {
- return attachment_services_result;
- }
-
- return SetInternetZoneIdentifierDirectly(file, source_url, referrer_url);
-}
-
-} // namespace download
diff --git a/chromium/components/download/quarantine/quarantine_win_unittest.cc b/chromium/components/download/quarantine/quarantine_win_unittest.cc
deleted file mode 100644
index 0c663a947c1..00000000000
--- a/chromium/components/download/quarantine/quarantine_win_unittest.cc
+++ /dev/null
@@ -1,407 +0,0 @@
-// Copyright 2016 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 <windows.h>
-
-#include <wininet.h>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/test_file_util.h"
-#include "base/test/test_reg_util_win.h"
-#include "base/win/win_util.h"
-#include "base/win/windows_version.h"
-#include "components/download/quarantine/quarantine.h"
-#include "components/download/quarantine/quarantine_features_win.h"
-#include "net/base/filename_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-namespace download {
-
-namespace {
-
-const char kDummySourceUrl[] = "https://example.com/foo";
-const char kDummyReferrerUrl[] = "https://example.com/referrer";
-const char kDummyClientGuid[] = "A1B69307-8FA2-4B6F-9181-EA06051A48A7";
-
-const char* const kUntrustedURLs[] = {
- "http://example.com/foo",
- "https://example.com/foo",
- "ftp://example.com/foo",
- "ftp://example.com:2121/foo",
- "data:text/plain,Hello%20world",
- "blob://example.com/126278b3-58f3-4b4a-a914-1d1185d634f6",
- "about:internet",
- ""};
-
-// Creates a non-empty file at |file_path|.
-bool CreateFile(const base::FilePath& file_path) {
- constexpr char kTestData[] = "Hello world!";
-
- return base::WriteFile(file_path, kTestData, base::size(kTestData)) ==
- static_cast<int>(base::size(kTestData));
-}
-
-base::FilePath GetZoneIdentifierStreamPath(const base::FilePath& file_path) {
- const base::FilePath::CharType kMotwStreamSuffix[] =
- FILE_PATH_LITERAL(":Zone.Identifier");
-
- return base::FilePath(file_path.value() + kMotwStreamSuffix);
-}
-
-// Reads the Zone.Identifier alternate data stream from |file_path| into
-// |contents|.
-bool GetZoneIdentifierStreamContents(const base::FilePath& file_path,
- std::string* contents) {
- DCHECK(contents);
- return base::ReadFileToString(GetZoneIdentifierStreamPath(file_path),
- contents);
-}
-
-// Maps a domain and protocol to a zone.
-class ScopedZoneForSite {
- public:
- enum ZoneIdentifierType : DWORD {
- kMyComputer = 0,
- kLocalIntranetZone = 1,
- kTrustedSitesZone = 2,
- kInternetZone = 3,
- kRestrictedSitesZone = 4,
- };
-
- ScopedZoneForSite(const base::string16& domain,
- const base::string16& protocol,
- ZoneIdentifierType zone_identifier_type);
- ~ScopedZoneForSite();
-
- private:
- base::string16 domain_;
- base::string16 protocol_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedZoneForSite);
-};
-
-ScopedZoneForSite::ScopedZoneForSite(const base::string16& domain,
- const base::string16& protocol,
- ZoneIdentifierType zone_identifier_type)
- : domain_(domain), protocol_(protocol) {
- base::string16 registry_path = base::StringPrintf(
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet "
- L"Settings\\ZoneMap\\Domains\\%ls",
- domain_.c_str());
- base::win::RegKey registry_key(HKEY_CURRENT_USER, registry_path.c_str(),
- KEY_SET_VALUE);
-
- EXPECT_EQ(registry_key.WriteValue(protocol_.c_str(), zone_identifier_type),
- ERROR_SUCCESS);
-}
-
-ScopedZoneForSite::~ScopedZoneForSite() {
- base::string16 registry_path = base::StringPrintf(
- L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet "
- L"Settings\\ZoneMap\\Domains\\%ls",
- domain_.c_str());
- base::win::RegKey registry_key(HKEY_CURRENT_USER, registry_path.c_str(),
- KEY_SET_VALUE);
- registry_key.DeleteValue(protocol_.c_str());
-}
-
-// Sets the internet Zone.Identifier alternate data stream for |file_path|.
-bool AddInternetZoneIdentifierDirectly(const base::FilePath& file_path) {
- static const char kMotwForInternetZone[] = "[ZoneTransfer]\r\nZoneId=3\r\n";
- return base::WriteFile(GetZoneIdentifierStreamPath(file_path),
- kMotwForInternetZone,
- base::size(kMotwForInternetZone)) ==
- static_cast<int>(base::size(kMotwForInternetZone));
-}
-
-} // namespace
-
-class QuarantineWinTest : public ::testing::Test {
- public:
- QuarantineWinTest() = default;
- ~QuarantineWinTest() override = default;
-
- void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(
- registry_override_.OverrideRegistry(HKEY_CURRENT_USER));
- ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
-
- scoped_zone_for_trusted_site_ = std::make_unique<ScopedZoneForSite>(
- GetTrustedSite(), L"https",
- ScopedZoneForSite::ZoneIdentifierType::kTrustedSitesZone);
- scoped_zone_for_restricted_site_ = std::make_unique<ScopedZoneForSite>(
- GetRestrictedSite(), L"https",
- ScopedZoneForSite::ZoneIdentifierType::kRestrictedSitesZone);
- }
-
- base::FilePath GetTempDir() { return scoped_temp_dir_.GetPath(); }
-
- const wchar_t* GetTrustedSite() { return L"thisisatrustedsite.com"; }
-
- const wchar_t* GetRestrictedSite() { return L"thisisarestrictedsite.com"; }
-
- private:
- registry_util::RegistryOverrideManager registry_override_;
-
- base::ScopedTempDir scoped_temp_dir_;
-
- // Due to caching, these sites zone must be set for all tests, so that the
- // order the tests are run does not matter.
- std::unique_ptr<ScopedZoneForSite> scoped_zone_for_trusted_site_;
- std::unique_ptr<ScopedZoneForSite> scoped_zone_for_restricted_site_;
-
- DISALLOW_COPY_AND_ASSIGN(QuarantineWinTest);
-};
-
-// If the file is missing, the QuarantineFile() call should return FILE_MISSING.
-TEST_F(QuarantineWinTest, MissingFile) {
- EXPECT_EQ(QuarantineFileResult::FILE_MISSING,
- QuarantineFile(GetTempDir().AppendASCII("does-not-exist.exe"),
- GURL(kDummySourceUrl), GURL(kDummyReferrerUrl),
- kDummyClientGuid));
-}
-
-// On Windows systems, files downloaded from a local source are considered
-// trustworthy. Hence they aren't annotated with source information. This test
-// verifies this behavior since the other tests in this suite would pass with a
-// false positive if local files are being annotated with the MOTW for the
-// internet zone.
-TEST_F(QuarantineWinTest, LocalFile_DependsOnLocalConfig) {
- base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
-
- const char* const kLocalSourceURLs[] = {"http://localhost/foo",
- "file:///C:/some-local-dir/foo.exe"};
-
- for (const char* source_url : kLocalSourceURLs) {
- SCOPED_TRACE(::testing::Message() << "Trying URL " << source_url);
-
- ASSERT_TRUE(CreateFile(test_file));
-
- EXPECT_EQ(
- QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(source_url), GURL(), kDummyClientGuid));
-
- std::string zone_identifier;
- GetZoneIdentifierStreamContents(test_file, &zone_identifier);
-
- // No zone identifier for local source.
- EXPECT_TRUE(zone_identifier.empty());
-
- ASSERT_TRUE(base::DeleteFile(test_file, false));
- }
-}
-
-// A file downloaded from the internet should be annotated with .. something.
-// The specific zone assigned to our dummy source URL depends on the local
-// configuration. But no sane configuration should be treating the dummy URL as
-// a trusted source for anything.
-TEST_F(QuarantineWinTest, DownloadedFile_DependsOnLocalConfig) {
- base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
-
- for (const char* source_url : kUntrustedURLs) {
- SCOPED_TRACE(::testing::Message() << "Trying URL " << source_url);
-
- ASSERT_TRUE(CreateFile(test_file));
- EXPECT_EQ(
- QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(source_url), GURL(), kDummyClientGuid));
-
- std::string zone_identifier;
- ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-
- // The actual assigned zone could be anything and the contents of the zone
- // identifier depends on the version of Windows. So only testing that there
- // is a zone annotation.
- EXPECT_FALSE(zone_identifier.empty());
-
- ASSERT_TRUE(base::DeleteFile(test_file, false));
- }
-}
-
-TEST_F(QuarantineWinTest, UnsafeReferrer_DependsOnLocalConfig) {
- base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
-
- std::vector<std::string> unsafe_referrers(std::begin(kUntrustedURLs),
- std::end(kUntrustedURLs));
-
- // Add one more test case.
- std::string huge_referrer = "http://example.com/";
- huge_referrer.append(INTERNET_MAX_URL_LENGTH * 2, 'a');
- unsafe_referrers.push_back(huge_referrer);
-
- for (const auto referrer_url : unsafe_referrers) {
- SCOPED_TRACE(::testing::Message() << "Trying URL " << referrer_url);
-
- ASSERT_TRUE(CreateFile(test_file));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL("http://example.com/good"),
- GURL(referrer_url), kDummyClientGuid));
-
- std::string zone_identifier;
- ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-
- // The actual assigned zone could be anything and the contents of the zone
- // identifier depends on the version of Windows. So only testing that there
- // is a zone annotation.
- EXPECT_FALSE(zone_identifier.empty());
-
- ASSERT_TRUE(base::DeleteFile(test_file, false));
- }
-}
-
-// An empty source URL should result in a file that's treated the same as one
-// downloaded from the internet.
-TEST_F(QuarantineWinTest, EmptySource_DependsOnLocalConfig) {
- base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
- ASSERT_TRUE(CreateFile(test_file));
-
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(), GURL(), kDummyClientGuid));
-
- std::string zone_identifier;
- ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-
- // The actual assigned zone could be anything and the contents of the zone
- // identifier depends on the version of Windows. So only testing that there is
- // a zone annotation.
- EXPECT_FALSE(zone_identifier.empty());
-}
-
-// Empty files aren't passed to AVScanFile. They are instead marked manually. If
-// the file is passed to AVScanFile, then there wouldn't be a MOTW attached to
-// it and the test would fail.
-TEST_F(QuarantineWinTest, EmptyFile) {
- base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
- ASSERT_EQ(0, base::WriteFile(test_file, "", 0u));
-
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, net::FilePathToFileURL(test_file), GURL(),
- kDummyClientGuid));
-
- std::string zone_identifier;
- ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-
- // The actual assigned zone could be anything and the contents of the zone
- // identifier depends on the version of Windows. So only testing that there is
- // a zone annotation.
- EXPECT_FALSE(zone_identifier.empty());
-}
-
-// If there is no client GUID supplied to the QuarantineFile() call, then rather
-// than invoking AVScanFile, the MOTW will be applied manually. If the file is
-// passed to AVScanFile, then there wouldn't be a MOTW attached to it and the
-// test would fail.
-TEST_F(QuarantineWinTest, NoClientGuid) {
- base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
- ASSERT_TRUE(CreateFile(test_file));
-
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, net::FilePathToFileURL(test_file), GURL(),
- std::string()));
-
- std::string zone_identifier;
- ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-
- // The actual assigned zone could be anything and the contents of the zone
- // identifier depends on the version of Windows. So only testing that there is
- // a zone annotation.
- EXPECT_FALSE(zone_identifier.empty());
-}
-
-// URLs longer than INTERNET_MAX_URL_LENGTH are known to break URLMon. Such a
-// URL, when used as a source URL shouldn't break QuarantineFile() which should
-// mark the file as being from the internet zone as a safe fallback.
-TEST_F(QuarantineWinTest, SuperLongURL) {
- base::FilePath test_file = GetTempDir().AppendASCII("foo.exe");
- ASSERT_TRUE(CreateFile(test_file));
-
- std::string source_url("http://example.com/");
- source_url.append(INTERNET_MAX_URL_LENGTH * 2, 'a');
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, GURL(source_url), GURL(), std::string()));
-
- std::string zone_identifier;
- ASSERT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-
- // The actual assigned zone could be anything and the contents of the zone
- // identifier depends on the version of Windows. So only testing that there is
- // a zone annotation.
- EXPECT_FALSE(zone_identifier.empty());
-}
-
-TEST_F(QuarantineWinTest, TrustedSite) {
- // Test file path and source URL.
- base::FilePath test_file = GetTempDir().AppendASCII("good.exe");
- GURL source_url = GURL(
- base::StringPrintf(L"https://%ls/folder/good.exe", GetTrustedSite()));
-
- ASSERT_TRUE(CreateFile(test_file));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid));
-
- // No zone identifier.
- std::string zone_identifier;
- EXPECT_FALSE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-}
-
-TEST_F(QuarantineWinTest, RestrictedSite) {
- // Test file path and source URL.
- base::FilePath test_file = GetTempDir().AppendASCII("bad.exe");
- GURL source_url = GURL(
- base::StringPrintf(L"https://%ls/folder/bad.exe", GetRestrictedSite()));
-
- ASSERT_TRUE(CreateFile(test_file));
-
- // Files from a restricted site are deleted.
- EXPECT_EQ(QuarantineFileResult::BLOCKED_BY_POLICY,
- QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid));
-
- std::string zone_identifier;
- EXPECT_FALSE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-}
-
-TEST_F(QuarantineWinTest, TrustedSite_AlreadyQuarantined) {
- // Test file path and source URL.
- base::FilePath test_file = GetTempDir().AppendASCII("good.exe");
- GURL source_url = GURL(
- base::StringPrintf(L"https://%ls/folder/good.exe", GetTrustedSite()));
-
- ASSERT_TRUE(CreateFile(test_file));
- // Ensure the file already contains a zone identifier.
- ASSERT_TRUE(AddInternetZoneIdentifierDirectly(test_file));
- EXPECT_EQ(QuarantineFileResult::OK,
- QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid));
-
- // The existing zone identifier was not removed.
- std::string zone_identifier;
- EXPECT_TRUE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-
- EXPECT_FALSE(zone_identifier.empty());
-}
-
-TEST_F(QuarantineWinTest, RestrictedSite_AlreadyQuarantined) {
- // Test file path and source URL.
- base::FilePath test_file = GetTempDir().AppendASCII("bad.exe");
- GURL source_url = GURL(
- base::StringPrintf(L"https://%ls/folder/bad.exe", GetRestrictedSite()));
-
- ASSERT_TRUE(CreateFile(test_file));
- // Ensure the file already contains a zone identifier.
- ASSERT_TRUE(AddInternetZoneIdentifierDirectly(test_file));
-
- // Files from a restricted site are deleted.
- EXPECT_EQ(QuarantineFileResult::BLOCKED_BY_POLICY,
- QuarantineFile(test_file, source_url, GURL(), kDummyClientGuid));
-
- std::string zone_identifier;
- EXPECT_FALSE(GetZoneIdentifierStreamContents(test_file, &zone_identifier));
-}
-
-} // namespace download
diff --git a/chromium/components/download/quarantine/test_support.cc b/chromium/components/download/quarantine/test_support.cc
deleted file mode 100644
index 55ef0628d00..00000000000
--- a/chromium/components/download/quarantine/test_support.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// 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/quarantine/test_support.h"
-
-#include "build/build_config.h"
-
-#if !defined(OS_WIN) && !defined(OS_MACOSX)
-
-namespace download {
-
-bool IsFileQuarantined(const base::FilePath& file,
- const GURL& source_url,
- const GURL& referrer_url) {
- return false;
-}
-
-} // namespace download
-
-#endif // !WIN && !MAC
diff --git a/chromium/components/download/quarantine/test_support.h b/chromium/components/download/quarantine/test_support.h
deleted file mode 100644
index 38e601cdd27..00000000000
--- a/chromium/components/download/quarantine/test_support.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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.
-
-#ifndef COMPONENTS_DOWNLOAD_QUARANTINE_TEST_SUPPORT_H_
-#define COMPONENTS_DOWNLOAD_QUARANTINE_TEST_SUPPORT_H_
-
-#include <string>
-
-class GURL;
-
-namespace base {
-class FilePath;
-}
-
-namespace download {
-
-// Determine if a file has quarantine metadata attached to it.
-//
-// If |source_url| is non-empty, then the download source URL in
-// quarantine metadata should match |source_url| exactly. The function returns
-// |false| if there is a mismatch. If |source_url| is empty, then this function
-// only checks for the existence of a download source URL in quarantine
-// metadata.
-//
-// If |referrer_url| is valid, then the download referrer URL in quarantine
-// metadata must match |referrer_url| exactly. The function returns |false| if
-// there is a mismatch in the |referrer_url| even if the |source_url| matches.
-// No referrer URL checks are performed if |referrer_url| is empty.
-//
-// If both |source_url| and |referrer_url| are empty, then the function returns
-// true if any quarantine metadata is present for the file.
-//
-// **Note**: On Windows 8 or lower, this function only checks if the
-// |ZoneIdentifier| metadata is present. |source_url| and |referrer_url| are
-// ignored. Individual URLs are only stored as part of the mark-of-the-web since
-// Windows 10.
-bool IsFileQuarantined(const base::FilePath& file,
- const GURL& source_url,
- const GURL& referrer_url);
-
-} // namespace download
-
-#endif // COMPONENTS_DOWNLOAD_QUARANTINE_TEST_SUPPORT_H_
diff --git a/chromium/components/download/quarantine/test_support_mac.mm b/chromium/components/download/quarantine/test_support_mac.mm
deleted file mode 100644
index 54369105c91..00000000000
--- a/chromium/components/download/quarantine/test_support_mac.mm
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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/quarantine/test_support.h"
-
-#import <ApplicationServices/ApplicationServices.h>
-#import <Foundation/Foundation.h>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/threading/scoped_blocking_call.h"
-#include "components/download/quarantine/common_mac.h"
-#include "url/gurl.h"
-
-namespace download {
-
-bool IsFileQuarantined(const base::FilePath& file,
- const GURL& expected_source_url,
- const GURL& referrer_url) {
- base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
- base::BlockingType::MAY_BLOCK);
-
- if (!base::PathExists(file))
- return false;
-
- base::scoped_nsobject<NSMutableDictionary> properties;
- bool success = GetQuarantineProperties(file, &properties);
-
- if (!success || !properties)
- return false;
-
- NSString* source_url =
- [[properties valueForKey:(NSString*)kLSQuarantineDataURLKey] description];
-
- if (!expected_source_url.is_valid())
- return [source_url length] > 0;
-
- if (![source_url isEqualToString:base::SysUTF8ToNSString(
- expected_source_url.spec())]) {
- return false;
- }
-
- return !referrer_url.is_valid() ||
- [[[properties valueForKey:(NSString*)kLSQuarantineOriginURLKey]
- description]
- isEqualToString:base::SysUTF8ToNSString(referrer_url.spec())];
-}
-
-} // namespace download
diff --git a/chromium/components/download/quarantine/test_support_win.cc b/chromium/components/download/quarantine/test_support_win.cc
deleted file mode 100644
index 4220849c126..00000000000
--- a/chromium/components/download/quarantine/test_support_win.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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/quarantine/test_support.h"
-
-#include <windows.h>
-
-#include <string>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/win/scoped_handle.h"
-#include "components/download/quarantine/common_win.h"
-
-namespace download {
-
-namespace {
-
-bool ZoneIdentifierPresentForFile(const base::FilePath& path) {
- const DWORD kShare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
- base::FilePath::StringType zone_identifier_path =
- path.value() + kZoneIdentifierStreamSuffix;
- base::win::ScopedHandle file(
- ::CreateFile(zone_identifier_path.c_str(), GENERIC_READ, kShare, nullptr,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
- if (!file.IsValid())
- return false;
-
- // The zone identifier contents is expected to be:
- // "[ZoneTransfer]\r\nZoneId=3\r\n". The actual ZoneId can be different. A
- // buffer of 32 bytes is sufficient for verifying the contents.
- std::vector<char> zone_identifier_contents_buffer(32);
- DWORD actual_length = 0;
- if (!::ReadFile(file.Get(), &zone_identifier_contents_buffer.front(),
- zone_identifier_contents_buffer.size(), &actual_length,
- nullptr))
- return false;
- zone_identifier_contents_buffer.resize(actual_length);
-
- std::string zone_identifier_contents(zone_identifier_contents_buffer.begin(),
- zone_identifier_contents_buffer.end());
-
- std::vector<base::StringPiece> lines =
- base::SplitStringPiece(zone_identifier_contents, "\n",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- return lines.size() > 1 && lines[0] == "[ZoneTransfer]" &&
- lines[1].find("ZoneId=") == 0;
-}
-
-} // namespace
-
-bool IsFileQuarantined(const base::FilePath& file,
- const GURL& source_url,
- const GURL& referrer_url) {
- return ZoneIdentifierPresentForFile(file);
-}
-
-} // namespace download