diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 10:22:43 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-08-30 12:36:28 +0000 |
commit | 271a6c3487a14599023a9106329505597638d793 (patch) | |
tree | e040d58ffc86c1480b79ca8528020ca9ec919bf8 /chromium/components/download | |
parent | 7b2ffa587235a47d4094787d72f38102089f402a (diff) | |
download | qtwebengine-chromium-271a6c3487a14599023a9106329505597638d793.tar.gz |
BASELINE: Update Chromium to 77.0.3865.59
Change-Id: I1e89a5f3b009a9519a6705102ad65c92fe736f21
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/components/download')
88 files changed, 961 insertions, 409 deletions
diff --git a/chromium/components/download/content/internal/download_driver_impl.cc b/chromium/components/download/content/internal/download_driver_impl.cc index ea7b4d55ad6..6b81a071d13 100644 --- a/chromium/components/download/content/internal/download_driver_impl.cc +++ b/chromium/components/download/content/internal/download_driver_impl.cc @@ -117,8 +117,7 @@ DownloadDriverImpl::DownloadDriverImpl( SimpleDownloadManagerCoordinator* download_manager_coordinator) : client_(nullptr), download_manager_coordinator_(download_manager_coordinator), - is_ready_(false), - weak_ptr_factory_(this) { + is_ready_(false) { DCHECK(download_manager_coordinator_); DETACH_FROM_SEQUENCE(sequence_checker_); } diff --git a/chromium/components/download/content/internal/download_driver_impl.h b/chromium/components/download/content/internal/download_driver_impl.h index 1fca209d5e6..97e9a0c5f86 100644 --- a/chromium/components/download/content/internal/download_driver_impl.h +++ b/chromium/components/download/content/internal/download_driver_impl.h @@ -89,7 +89,7 @@ class DownloadDriverImpl : public DownloadDriver, SEQUENCE_CHECKER(sequence_checker_); // Only used to post tasks on the same thread. - base::WeakPtrFactory<DownloadDriverImpl> weak_ptr_factory_; + base::WeakPtrFactory<DownloadDriverImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DownloadDriverImpl); }; diff --git a/chromium/components/download/database/download_db_impl.cc b/chromium/components/download/database/download_db_impl.cc index 06f74774083..b1a5ca60889 100644 --- a/chromium/components/download/database/download_db_impl.cc +++ b/chromium/components/download/database/download_db_impl.cc @@ -54,7 +54,10 @@ DownloadDBImpl::DownloadDBImpl(DownloadNamespace download_namespace, leveldb_proto::ProtoDatabaseProvider::CreateUniqueDB< download_pb::DownloadDBEntry>( base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::BEST_EFFORT, + {base::MayBlock(), + // USER_VISIBLE because it is required to display + // chrome://downloads. https://crbug.com/976223 + base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}))) {} DownloadDBImpl::DownloadDBImpl( @@ -66,8 +69,7 @@ DownloadDBImpl::DownloadDBImpl( db_(std::move(db)), is_initialized_(false), download_namespace_(download_namespace), - num_initialize_attempts_(0), - weak_factory_(this) {} + num_initialize_attempts_(0) {} DownloadDBImpl::~DownloadDBImpl() = default; diff --git a/chromium/components/download/database/download_db_impl.h b/chromium/components/download/database/download_db_impl.h index 9dac9f58dae..a1a6b65b781 100644 --- a/chromium/components/download/database/download_db_impl.h +++ b/chromium/components/download/database/download_db_impl.h @@ -81,7 +81,7 @@ class DownloadDBImpl : public DownloadDB { // Number of initialize attempts. int num_initialize_attempts_; - base::WeakPtrFactory<DownloadDBImpl> weak_factory_; + base::WeakPtrFactory<DownloadDBImpl> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DownloadDBImpl); }; diff --git a/chromium/components/download/internal/background_service/BUILD.gn b/chromium/components/download/internal/background_service/BUILD.gn index 83b9120ca9e..6c1ade7240b 100644 --- a/chromium/components/download/internal/background_service/BUILD.gn +++ b/chromium/components/download/internal/background_service/BUILD.gn @@ -125,7 +125,6 @@ if (is_android) { sources = [ "android/java/src/org/chromium/components/download/internal/BatteryStatusListenerAndroid.java", ] - jni_package = "components/download/internal/background_service" } } diff --git a/chromium/components/download/internal/background_service/DEPS b/chromium/components/download/internal/background_service/DEPS index 9500a4e33eb..6cce2194ddb 100644 --- a/chromium/components/download/internal/background_service/DEPS +++ b/chromium/components/download/internal/background_service/DEPS @@ -1,9 +1,9 @@ include_rules = [ "-components/download/content", "-content", + "+components/download/internal/background_service/jni_headers", "+components/leveldb_proto", "+base", - "+jni", "+net", "+services/network/public", "+services/network/test", diff --git a/chromium/components/download/internal/background_service/android/battery_status_listener_android.cc b/chromium/components/download/internal/background_service/android/battery_status_listener_android.cc index 33e6641353e..25778aa9f6d 100644 --- a/chromium/components/download/internal/background_service/android/battery_status_listener_android.cc +++ b/chromium/components/download/internal/background_service/android/battery_status_listener_android.cc @@ -6,7 +6,7 @@ #include "base/android/jni_android.h" #include "base/trace_event/trace_event.h" -#include "jni/BatteryStatusListenerAndroid_jni.h" +#include "components/download/internal/background_service/jni_headers/BatteryStatusListenerAndroid_jni.h" namespace download { diff --git a/chromium/components/download/internal/background_service/blob_task_proxy.cc b/chromium/components/download/internal/background_service/blob_task_proxy.cc index b7afc1cedbe..0e12a6cd9c3 100644 --- a/chromium/components/download/internal/background_service/blob_task_proxy.cc +++ b/chromium/components/download/internal/background_service/blob_task_proxy.cc @@ -27,8 +27,7 @@ BlobTaskProxy::BlobTaskProxy( BlobContextGetter blob_context_getter, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), - io_task_runner_(io_task_runner), - weak_ptr_factory_(this) { + io_task_runner_(io_task_runner) { // Unretained the raw pointer because owner on UI thread should destroy this // object on IO thread. io_task_runner_->PostTask( diff --git a/chromium/components/download/internal/background_service/blob_task_proxy.h b/chromium/components/download/internal/background_service/blob_task_proxy.h index d7fc6113441..2714fb74b4b 100644 --- a/chromium/components/download/internal/background_service/blob_task_proxy.h +++ b/chromium/components/download/internal/background_service/blob_task_proxy.h @@ -65,7 +65,7 @@ class BlobTaskProxy { std::unique_ptr<storage::BlobDataHandle> blob_data_handle_; // Bounded to IO thread task runner. - base::WeakPtrFactory<BlobTaskProxy> weak_ptr_factory_; + base::WeakPtrFactory<BlobTaskProxy> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(BlobTaskProxy); }; diff --git a/chromium/components/download/internal/background_service/controller_impl.cc b/chromium/components/download/internal/background_service/controller_impl.cc index c16357d94b4..2469409cbfc 100644 --- a/chromium/components/download/internal/background_service/controller_impl.cc +++ b/chromium/components/download/internal/background_service/controller_impl.cc @@ -126,8 +126,7 @@ ControllerImpl::ControllerImpl( scheduler_(std::move(scheduler)), task_scheduler_(std::move(task_scheduler)), file_monitor_(std::move(file_monitor)), - controller_state_(State::CREATED), - weak_ptr_factory_(this) { + controller_state_(State::CREATED) { DCHECK(config_); DCHECK(log_sink_); } diff --git a/chromium/components/download/internal/background_service/controller_impl.h b/chromium/components/download/internal/background_service/controller_impl.h index 7105d00d910..cc9d469ecef 100644 --- a/chromium/components/download/internal/background_service/controller_impl.h +++ b/chromium/components/download/internal/background_service/controller_impl.h @@ -277,7 +277,7 @@ class ControllerImpl : public Controller, base::CancelableClosure cancel_uploads_callback_; // Only used to post tasks on the same thread. - base::WeakPtrFactory<ControllerImpl> weak_ptr_factory_; + base::WeakPtrFactory<ControllerImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ControllerImpl); }; diff --git a/chromium/components/download/internal/background_service/download_service_impl.cc b/chromium/components/download/internal/background_service/download_service_impl.cc index 8ba75350bee..6a30111d255 100644 --- a/chromium/components/download/internal/background_service/download_service_impl.cc +++ b/chromium/components/download/internal/background_service/download_service_impl.cc @@ -22,8 +22,7 @@ DownloadServiceImpl::DownloadServiceImpl(std::unique_ptr<Configuration> config, logger_(std::move(logger)), controller_(std::move(controller)), service_config_(config_.get()), - startup_completed_(false), - weak_ptr_factory_(this) { + startup_completed_(false) { controller_->Initialize( base::BindRepeating(&DownloadServiceImpl::OnControllerInitialized, weak_ptr_factory_.GetWeakPtr())); @@ -80,7 +79,6 @@ DownloadService::ServiceStatus DownloadServiceImpl::GetStatus() { void DownloadServiceImpl::StartDownload(const DownloadParams& download_params) { stats::LogServiceApiAction(download_params.client, stats::ServiceApiAction::START_DOWNLOAD); - stats::LogDownloadParams(download_params); if (startup_completed_) { controller_->StartDownload(download_params); } else { diff --git a/chromium/components/download/internal/background_service/download_service_impl.h b/chromium/components/download/internal/background_service/download_service_impl.h index 3c69213b8ff..e604ab2d432 100644 --- a/chromium/components/download/internal/background_service/download_service_impl.h +++ b/chromium/components/download/internal/background_service/download_service_impl.h @@ -61,7 +61,7 @@ class DownloadServiceImpl : public DownloadService { std::map<DownloadTaskType, base::OnceClosure> pending_tasks_; bool startup_completed_; - base::WeakPtrFactory<DownloadServiceImpl> weak_ptr_factory_; + base::WeakPtrFactory<DownloadServiceImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DownloadServiceImpl); }; diff --git a/chromium/components/download/internal/background_service/download_service_impl_unittest.cc b/chromium/components/download/internal/background_service/download_service_impl_unittest.cc index 9a41b3955b4..9792b067a85 100644 --- a/chromium/components/download/internal/background_service/download_service_impl_unittest.cc +++ b/chromium/components/download/internal/background_service/download_service_impl_unittest.cc @@ -94,12 +94,6 @@ TEST_F(DownloadServiceImplTest, TestApiPassThrough) { static_cast<base::HistogramBase::Sample>( stats::ServiceApiAction::START_DOWNLOAD), 1); - histogram_tester.ExpectBucketCount( - "Download.Service.Request.BatteryRequirement", - static_cast<base::HistogramBase::Sample>( - params.scheduling_params.battery_requirements), - 1); - histogram_tester.ExpectTotalCount("Download.Service.Request.ClientAction", 1); histogram_tester.ExpectTotalCount( diff --git a/chromium/components/download/internal/background_service/download_store.cc b/chromium/components/download/internal/background_service/download_store.cc index 87a16b6c363..fa10e0dc400 100644 --- a/chromium/components/download/internal/background_service/download_store.cc +++ b/chromium/components/download/internal/background_service/download_store.cc @@ -33,9 +33,7 @@ leveldb_env::Options GetDownloadDBOptions() { DownloadStore::DownloadStore( std::unique_ptr<leveldb_proto::ProtoDatabase<protodb::Entry>> db) - : db_(std::move(db)), - is_initialized_(false), - weak_factory_(this) {} + : db_(std::move(db)), is_initialized_(false) {} DownloadStore::~DownloadStore() = default; diff --git a/chromium/components/download/internal/background_service/download_store.h b/chromium/components/download/internal/background_service/download_store.h index a6ff03d8601..9914b6af1da 100644 --- a/chromium/components/download/internal/background_service/download_store.h +++ b/chromium/components/download/internal/background_service/download_store.h @@ -49,7 +49,7 @@ class DownloadStore : public Store { std::unique_ptr<leveldb_proto::ProtoDatabase<protodb::Entry>> db_; bool is_initialized_; - base::WeakPtrFactory<DownloadStore> weak_factory_; + base::WeakPtrFactory<DownloadStore> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DownloadStore); }; diff --git a/chromium/components/download/internal/background_service/empty_file_monitor.cc b/chromium/components/download/internal/background_service/empty_file_monitor.cc index 6605eee262d..36ee4431830 100644 --- a/chromium/components/download/internal/background_service/empty_file_monitor.cc +++ b/chromium/components/download/internal/background_service/empty_file_monitor.cc @@ -9,7 +9,7 @@ namespace download { -EmptyFileMonitor::EmptyFileMonitor() : weak_ptr_factory_(this) {} +EmptyFileMonitor::EmptyFileMonitor() {} EmptyFileMonitor::~EmptyFileMonitor() = default; diff --git a/chromium/components/download/internal/background_service/empty_file_monitor.h b/chromium/components/download/internal/background_service/empty_file_monitor.h index 715fb1b5479..e4b9b80905e 100644 --- a/chromium/components/download/internal/background_service/empty_file_monitor.h +++ b/chromium/components/download/internal/background_service/empty_file_monitor.h @@ -32,7 +32,7 @@ class EmptyFileMonitor : public FileMonitor { stats::FileCleanupReason reason) override; void HardRecover(const InitCallback& callback) override; - base::WeakPtrFactory<EmptyFileMonitor> weak_ptr_factory_; + base::WeakPtrFactory<EmptyFileMonitor> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(EmptyFileMonitor); }; diff --git a/chromium/components/download/internal/background_service/file_monitor_impl.cc b/chromium/components/download/internal/background_service/file_monitor_impl.cc index 99cdf48a862..7d976e1fdce 100644 --- a/chromium/components/download/internal/background_service/file_monitor_impl.cc +++ b/chromium/components/download/internal/background_service/file_monitor_impl.cc @@ -148,8 +148,7 @@ FileMonitorImpl::FileMonitorImpl( base::TimeDelta file_keep_alive_time) : download_file_dir_(download_file_dir), file_keep_alive_time_(file_keep_alive_time), - file_thread_task_runner_(file_thread_task_runner), - weak_factory_(this) {} + file_thread_task_runner_(file_thread_task_runner) {} FileMonitorImpl::~FileMonitorImpl() = default; diff --git a/chromium/components/download/internal/background_service/file_monitor_impl.h b/chromium/components/download/internal/background_service/file_monitor_impl.h index 723843f3785..8717561f00d 100644 --- a/chromium/components/download/internal/background_service/file_monitor_impl.h +++ b/chromium/components/download/internal/background_service/file_monitor_impl.h @@ -49,7 +49,7 @@ class FileMonitorImpl : public FileMonitor { const base::TimeDelta file_keep_alive_time_; scoped_refptr<base::SequencedTaskRunner> file_thread_task_runner_; - base::WeakPtrFactory<FileMonitorImpl> weak_factory_; + base::WeakPtrFactory<FileMonitorImpl> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(FileMonitorImpl); }; 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 6b3ac7d5abd..c9926226bc4 100644 --- a/chromium/components/download/internal/background_service/in_memory_download.cc +++ b/chromium/components/download/internal/background_service/in_memory_download.cc @@ -41,8 +41,7 @@ InMemoryDownloadImpl::InMemoryDownloadImpl( io_task_runner_(io_task_runner), delegate_(delegate), completion_notified_(false), - started_(false), - weak_ptr_factory_(this) { + started_(false) { DCHECK(!guid_.empty()); DCHECK(delegate_); } 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 950d38f9ab8..ec7ea9d356f 100644 --- a/chromium/components/download/internal/background_service/in_memory_download.h +++ b/chromium/components/download/internal/background_service/in_memory_download.h @@ -259,7 +259,7 @@ class InMemoryDownloadImpl : public network::SimpleURLLoaderStreamConsumer, bool started_; // Bounded to main thread task runner. - base::WeakPtrFactory<InMemoryDownloadImpl> weak_ptr_factory_; + base::WeakPtrFactory<InMemoryDownloadImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(InMemoryDownloadImpl); }; diff --git a/chromium/components/download/internal/background_service/model_impl.cc b/chromium/components/download/internal/background_service/model_impl.cc index 3beabb3e136..2f46ddd0860 100644 --- a/chromium/components/download/internal/background_service/model_impl.cc +++ b/chromium/components/download/internal/background_service/model_impl.cc @@ -15,7 +15,7 @@ namespace download { ModelImpl::ModelImpl(std::unique_ptr<Store> store) - : client_(nullptr), store_(std::move(store)), weak_ptr_factory_(this) { + : client_(nullptr), store_(std::move(store)) { DCHECK(store_); } diff --git a/chromium/components/download/internal/background_service/model_impl.h b/chromium/components/download/internal/background_service/model_impl.h index 8ec5f0acd0a..c94675cd8c5 100644 --- a/chromium/components/download/internal/background_service/model_impl.h +++ b/chromium/components/download/internal/background_service/model_impl.h @@ -64,7 +64,7 @@ class ModelImpl : public Model { // entries saved in Store. OwnedEntryMap entries_; - base::WeakPtrFactory<ModelImpl> weak_ptr_factory_; + base::WeakPtrFactory<ModelImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ModelImpl); }; diff --git a/chromium/components/download/internal/background_service/navigation_monitor_impl.cc b/chromium/components/download/internal/background_service/navigation_monitor_impl.cc index 52cf9c82284..62d3c3f850b 100644 --- a/chromium/components/download/internal/background_service/navigation_monitor_impl.cc +++ b/chromium/components/download/internal/background_service/navigation_monitor_impl.cc @@ -11,9 +11,7 @@ namespace download { NavigationMonitorImpl::NavigationMonitorImpl() - : observer_(nullptr), - current_navigation_count_(0), - weak_ptr_factory_(this) {} + : observer_(nullptr), current_navigation_count_(0) {} NavigationMonitorImpl::~NavigationMonitorImpl() = default; diff --git a/chromium/components/download/internal/background_service/navigation_monitor_impl.h b/chromium/components/download/internal/background_service/navigation_monitor_impl.h index a972de39493..076d4c618e3 100644 --- a/chromium/components/download/internal/background_service/navigation_monitor_impl.h +++ b/chromium/components/download/internal/background_service/navigation_monitor_impl.h @@ -40,7 +40,7 @@ class NavigationMonitorImpl : public NavigationMonitor { base::TimeDelta navigation_completion_delay_; base::TimeDelta navigation_timeout_delay_; - base::WeakPtrFactory<NavigationMonitorImpl> weak_ptr_factory_; + base::WeakPtrFactory<NavigationMonitorImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(NavigationMonitorImpl); }; diff --git a/chromium/components/download/internal/background_service/navigation_monitor_impl_unittests.cc b/chromium/components/download/internal/background_service/navigation_monitor_impl_unittests.cc index 19fb4dd2ced..c3b0fa47a51 100644 --- a/chromium/components/download/internal/background_service/navigation_monitor_impl_unittests.cc +++ b/chromium/components/download/internal/background_service/navigation_monitor_impl_unittests.cc @@ -22,8 +22,7 @@ class TestNavigationMonitorObserver : public NavigationMonitor::Observer { NavigationMonitor* monitor) : task_runner_(task_runner), monitor_(monitor), - navigation_in_progress_(false), - weak_ptr_factory_(this) {} + navigation_in_progress_(false) {} ~TestNavigationMonitorObserver() override = default; void OnNavigationEvent() override { @@ -46,7 +45,7 @@ class TestNavigationMonitorObserver : public NavigationMonitor::Observer { scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; NavigationMonitor* monitor_; bool navigation_in_progress_; - base::WeakPtrFactory<TestNavigationMonitorObserver> weak_ptr_factory_; + base::WeakPtrFactory<TestNavigationMonitorObserver> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(TestNavigationMonitorObserver); }; @@ -54,9 +53,7 @@ class TestNavigationMonitorObserver : public NavigationMonitor::Observer { class NavigationMonitorImplTest : public testing::Test { public: NavigationMonitorImplTest() - : task_runner_(new base::TestMockTimeTaskRunner), - handle_(task_runner_), - weak_ptr_factory_(this) {} + : task_runner_(new base::TestMockTimeTaskRunner), handle_(task_runner_) {} ~NavigationMonitorImplTest() override = default; void SetUp() override { @@ -91,7 +88,7 @@ class NavigationMonitorImplTest : public testing::Test { base::ThreadTaskRunnerHandle handle_; std::unique_ptr<NavigationMonitorImpl> navigation_monitor_; std::unique_ptr<TestNavigationMonitorObserver> observer_; - base::WeakPtrFactory<NavigationMonitorImplTest> weak_ptr_factory_; + base::WeakPtrFactory<NavigationMonitorImplTest> weak_ptr_factory_{this}; private: DISALLOW_COPY_AND_ASSIGN(NavigationMonitorImplTest); diff --git a/chromium/components/download/internal/background_service/noop_store.cc b/chromium/components/download/internal/background_service/noop_store.cc index 7eeab1d60b0..d4c1624a3ff 100644 --- a/chromium/components/download/internal/background_service/noop_store.cc +++ b/chromium/components/download/internal/background_service/noop_store.cc @@ -12,7 +12,7 @@ namespace download { -NoopStore::NoopStore() : initialized_(false), weak_ptr_factory_(this) {} +NoopStore::NoopStore() : initialized_(false) {} NoopStore::~NoopStore() = default; diff --git a/chromium/components/download/internal/background_service/noop_store.h b/chromium/components/download/internal/background_service/noop_store.h index 643dfc119f1..46a6a62c117 100644 --- a/chromium/components/download/internal/background_service/noop_store.h +++ b/chromium/components/download/internal/background_service/noop_store.h @@ -34,7 +34,7 @@ class NoopStore : public Store { // Initialize() is called. bool initialized_; - base::WeakPtrFactory<NoopStore> weak_ptr_factory_; + base::WeakPtrFactory<NoopStore> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(NoopStore); }; diff --git a/chromium/components/download/internal/background_service/scheduler/battery_status_listener_impl.cc b/chromium/components/download/internal/background_service/scheduler/battery_status_listener_impl.cc index 62fd8bc95ef..e74bf55405d 100644 --- a/chromium/components/download/internal/background_service/scheduler/battery_status_listener_impl.cc +++ b/chromium/components/download/internal/background_service/scheduler/battery_status_listener_impl.cc @@ -23,21 +23,20 @@ int BatteryStatusListenerImpl::GetBatteryPercentage() { } bool BatteryStatusListenerImpl::IsOnBatteryPower() { - return base::PowerMonitor::Get()->IsOnBatteryPower(); + return base::PowerMonitor::IsOnBatteryPower(); } void BatteryStatusListenerImpl::Start(Observer* observer) { observer_ = observer; - base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); - DCHECK(power_monitor); - power_monitor->AddObserver(this); + DCHECK(base::PowerMonitor::IsInitialized()); + base::PowerMonitor::AddObserver(this); UpdateBatteryPercentage(true); } void BatteryStatusListenerImpl::Stop() { - base::PowerMonitor::Get()->RemoveObserver(this); + base::PowerMonitor::RemoveObserver(this); } int BatteryStatusListenerImpl::GetBatteryPercentageInternal() { diff --git a/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc b/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc index d5e6bda0033..e3da016383e 100644 --- a/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc +++ b/chromium/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc @@ -86,8 +86,7 @@ class DeviceStatusListenerTest : public testing::Test { void SetUp() override { auto power_source = std::make_unique<base::PowerMonitorTestSource>(); power_source_ = power_source.get(); - power_monitor_ = - std::make_unique<base::PowerMonitor>(std::move(power_source)); + base::PowerMonitor::Initialize(std::move(power_source)); auto battery_listener = std::make_unique<TestBatteryStatusListener>(); test_battery_listener_ = battery_listener.get(); @@ -100,7 +99,10 @@ class DeviceStatusListenerTest : public testing::Test { listener_->SetObserver(&mock_observer_); } - void TearDown() override { listener_.reset(); } + void TearDown() override { + listener_.reset(); + base::PowerMonitor::ShutdownForTesting(); + } protected: // Start the listener with certain network and battery state. @@ -145,7 +147,6 @@ class DeviceStatusListenerTest : public testing::Test { // Needed for network change notifier and power monitor. base::test::ScopedTaskEnvironment task_environment_; - std::unique_ptr<base::PowerMonitor> power_monitor_; base::PowerMonitorTestSource* power_source_; TestBatteryStatusListener* test_battery_listener_; }; diff --git a/chromium/components/download/internal/background_service/stats.cc b/chromium/components/download/internal/background_service/stats.cc index dc627fd7a2f..282cf52abfd 100644 --- a/chromium/components/download/internal/background_service/stats.cc +++ b/chromium/components/download/internal/background_service/stats.cc @@ -221,18 +221,6 @@ void LogStartDownloadResult(DownloadClient client, DownloadParams::StartResult::COUNT); } -void LogDownloadParams(const DownloadParams& params) { - UMA_HISTOGRAM_ENUMERATION("Download.Service.Request.BatteryRequirement", - params.scheduling_params.battery_requirements, - SchedulingParams::BatteryRequirements::COUNT); - UMA_HISTOGRAM_ENUMERATION("Download.Service.Request.NetworkRequirement", - params.scheduling_params.network_requirements, - SchedulingParams::NetworkRequirements::COUNT); - UMA_HISTOGRAM_ENUMERATION("Download.Service.Request.Priority", - params.scheduling_params.priority, - SchedulingParams::Priority::COUNT); -} - void LogRecoveryOperation(Entry::State to_state) { UMA_HISTOGRAM_ENUMERATION("Download.Service.Recovery", to_state, Entry::State::COUNT); diff --git a/chromium/components/download/internal/background_service/stats.h b/chromium/components/download/internal/background_service/stats.h index d92385aa429..4c4353775a7 100644 --- a/chromium/components/download/internal/background_service/stats.h +++ b/chromium/components/download/internal/background_service/stats.h @@ -159,9 +159,6 @@ void LogServiceApiAction(DownloadClient client, ServiceApiAction action); void LogStartDownloadResult(DownloadClient client, DownloadParams::StartResult result); -// Logs the download parameters when StartDownload() is called. -void LogDownloadParams(const DownloadParams& params); - // Logs recovery operations that happened when we had to move from one state // to another on startup. void LogRecoveryOperation(Entry::State to_state); diff --git a/chromium/components/download/internal/common/BUILD.gn b/chromium/components/download/internal/common/BUILD.gn index 419ee87c0c6..63db61acc4b 100644 --- a/chromium/components/download/internal/common/BUILD.gn +++ b/chromium/components/download/internal/common/BUILD.gn @@ -80,6 +80,10 @@ source_set("internal") { "//services/service_manager/public/cpp:cpp", ] + if (is_win) { + deps += [ "//components/services/quarantine/public/cpp:features" ] + } + if (is_android) { sources += [ "android/download_collection_bridge.cc", @@ -108,7 +112,6 @@ if (is_android) { sources = [ "android/java/src/org/chromium/components/download/DownloadCollectionBridge.java", ] - jni_package = "components/download/internal/common" } } diff --git a/chromium/components/download/internal/common/DEPS b/chromium/components/download/internal/common/DEPS index 015703b0a6f..6ad5fdf295c 100644 --- a/chromium/components/download/internal/common/DEPS +++ b/chromium/components/download/internal/common/DEPS @@ -1,13 +1,14 @@ include_rules = [ "-content", "+components/download/downloader/in_progress", + "+components/download/internal/common/jni_headers", "+components/download/public/common", "+components/download/quarantine", "+components/filename_generation/filename_generation.h", "+components/leveldb_proto", + "+components/services/quarantine/public/cpp/quarantine_features_win.h", "+components/ukm/test_ukm_recorder.h", "+crypto", - "+jni", "+mojo/public/c/system", "+mojo/public/cpp/bindings", "+net/base/filename_util.h", 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 ae075552619..1b4c1e9239e 100644 --- a/chromium/components/download/internal/common/android/download_collection_bridge.cc +++ b/chromium/components/download/internal/common/android/download_collection_bridge.cc @@ -11,9 +11,9 @@ #include "base/files/file_util.h" #include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" +#include "components/download/internal/common/jni_headers/DownloadCollectionBridge_jni.h" #include "components/download/public/common/download_features.h" #include "components/download/public/common/download_interrupt_reasons.h" -#include "jni/DownloadCollectionBridge_jni.h" using base::android::ConvertJavaStringToUTF8; using base::android::ConvertUTF16ToJavaString; 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 29c2a74c9a7..cdf3e44e5bc 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 @@ -178,7 +178,7 @@ public class DownloadCollectionBridge { * @param referrer Referrer of the download. */ @CalledByNative - private static String createIntermediateUriForPublish(final String fileName, + public static String createIntermediateUriForPublish(final String fileName, final String mimeType, final String originalUrl, final String referrer) { Uri uri = getDownloadCollectionBridge().createPendingSession( fileName, mimeType, originalUrl, referrer); @@ -202,7 +202,7 @@ public class DownloadCollectionBridge { * @return True on success, or false otherwise. */ @CalledByNative - private static boolean copyFileToIntermediateUri( + public static boolean copyFileToIntermediateUri( final String sourcePath, final String destinationUri) { return getDownloadCollectionBridge().copyFileToPendingUri(sourcePath, destinationUri); } @@ -212,7 +212,7 @@ public class DownloadCollectionBridge { * @param uri Intermediate Uri that is going to be deleted. */ @CalledByNative - private static void deleteIntermediateUri(final String uri) { + public static void deleteIntermediateUri(final String uri) { getDownloadCollectionBridge().abandonPendingUri(uri); } @@ -222,7 +222,7 @@ public class DownloadCollectionBridge { * @return Uri of the published file. */ @CalledByNative - private static String publishDownload(final String intermediateUri) { + public static String publishDownload(final String intermediateUri) { Uri uri = getDownloadCollectionBridge().publishCompletedDownload(intermediateUri); return uri == null ? null : uri.toString(); } diff --git a/chromium/components/download/internal/common/base_file.cc b/chromium/components/download/internal/common/base_file.cc index d220a7bc132..9497a10ae44 100644 --- a/chromium/components/download/internal/common/base_file.cc +++ b/chromium/components/download/internal/common/base_file.cc @@ -13,6 +13,7 @@ #include "base/format_macros.h" #include "base/logging.h" #include "base/macros.h" +#include "base/metrics/histogram_functions.h" #include "base/numerics/safe_conversions.h" #include "base/pickle.h" #include "base/strings/stringprintf.h" @@ -24,6 +25,11 @@ #include "components/download/public/common/download_stats.h" #include "components/download/quarantine/quarantine.h" #include "crypto/secure_hash.h" +#include "services/service_manager/public/cpp/connector.h" + +#if defined(OS_WIN) +#include "components/services/quarantine/public/cpp/quarantine_features_win.h" +#endif // defined(OS_WIN) #if defined(OS_ANDROID) #include "base/android/content_uri_utils.h" @@ -278,6 +284,7 @@ DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { } void BaseFile::Detach() { + weak_factory_.InvalidateWeakPtrs(); detached_ = true; CONDITIONAL_TRACE( INSTANT0("download", "DownloadFileDetached", TRACE_EVENT_SCOPE_THREAD)); @@ -516,10 +523,46 @@ DownloadInterruptReason BaseFile::PublishDownload() { } #endif // defined(OS_ANDROID) -#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) - namespace { +DownloadInterruptReason QuarantineFileResultToReason( + quarantine::mojom::QuarantineFileResult result) { + switch (result) { + case quarantine::mojom::QuarantineFileResult::OK: + return DOWNLOAD_INTERRUPT_REASON_NONE; + case quarantine::mojom::QuarantineFileResult::VIRUS_INFECTED: + return DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED; + case quarantine::mojom::QuarantineFileResult::SECURITY_CHECK_FAILED: + return DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED; + case quarantine::mojom::QuarantineFileResult::BLOCKED_BY_POLICY: + return DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED; + case quarantine::mojom::QuarantineFileResult::ACCESS_DENIED: + return DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; + + case quarantine::mojom::QuarantineFileResult::FILE_MISSING: + // Don't have a good interrupt reason here. This return code means that + // the file at |full_path_| went missing before QuarantineFile got to + // look at it. Not expected to happen, but we've seen instances where a + // file goes missing immediately after BaseFile closes the handle. + // + // Intentionally using a different error message than + // SECURITY_CHECK_FAILED in order to distinguish the two. + return DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; + + case quarantine::mojom::QuarantineFileResult::ANNOTATION_FAILED: + // This means that the mark-of-the-web couldn't be applied. The file is + // already on the file system under its final target name. + // + // Causes of failed annotations typically aren't transient. E.g. the + // target file system may not support extended attributes or alternate + // streams. We are going to allow these downloads to progress on the + // assumption that failures to apply MOTW can't reliably be introduced + // remotely. + return DOWNLOAD_INTERRUPT_REASON_NONE; + } + return DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; +} + // Given a source and a referrer, determines the "safest" URL that can be used // to determine the authority of the download source. Returns an empty URL if no // HTTP/S URL can be determined for the <|source_url|, |referrer_url|> pair. @@ -551,7 +594,9 @@ GURL GetEffectiveAuthorityURL(const GURL& source_url, } // namespace -DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( +#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) + +DownloadInterruptReason BaseFile::AnnotateWithSourceInformationSync( const std::string& client_guid, const GURL& source_url, const GURL& referrer_url) { @@ -565,43 +610,10 @@ DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( referrer_url, client_guid); CONDITIONAL_TRACE(END0("download", "DownloadFileAnnotate")); - switch (result) { - case QuarantineFileResult::OK: - return DOWNLOAD_INTERRUPT_REASON_NONE; - case QuarantineFileResult::VIRUS_INFECTED: - return DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED; - case QuarantineFileResult::SECURITY_CHECK_FAILED: - return DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED; - case QuarantineFileResult::BLOCKED_BY_POLICY: - return DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED; - case QuarantineFileResult::ACCESS_DENIED: - return DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; - - case QuarantineFileResult::FILE_MISSING: - // Don't have a good interrupt reason here. This return code means that - // the file at |full_path_| went missing before QuarantineFile got to look - // at it. Not expected to happen, but we've seen instances where a file - // goes missing immediately after BaseFile closes the handle. - // - // Intentionally using a different error message than - // SECURITY_CHECK_FAILED in order to distinguish the two. - return DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; - - case QuarantineFileResult::ANNOTATION_FAILED: - // This means that the mark-of-the-web couldn't be applied. The file is - // already on the file system under its final target name. - // - // Causes of failed annotations typically aren't transient. E.g. the - // target file system may not support extended attributes or alternate - // streams. We are going to allow these downloads to progress on the - // assumption that failures to apply MOTW can't reliably be introduced - // remotely. - return DOWNLOAD_INTERRUPT_REASON_NONE; - } - return DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; + return QuarantineFileResultToReason(result); } #else // !OS_WIN && !OS_MACOSX && !OS_LINUX -DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( +DownloadInterruptReason BaseFile::AnnotateWithSourceInformationSync( const std::string& client_guid, const GURL& source_url, const GURL& referrer_url) { @@ -609,4 +621,63 @@ DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( } #endif +void BaseFile::OnFileQuarantined( + bool connection_error, + quarantine::mojom::QuarantineFileResult result) { + base::UmaHistogramBoolean("Download.QuarantineService.ConnectionError", + connection_error); + + DCHECK(on_annotation_done_callback_); + quarantine_service_.reset(); + std::move(on_annotation_done_callback_) + .Run(QuarantineFileResultToReason(result)); +} + +void BaseFile::OnQuarantineServiceError(const GURL& source_url, + const GURL& referrer_url) { +#if defined(OS_WIN) + if (base::FeatureList::IsEnabled(quarantine::kOutOfProcessQuarantine)) { + OnFileQuarantined(/*connection_error=*/true, + quarantine::SetInternetZoneIdentifierDirectly( + full_path_, source_url, referrer_url)); + return; + } +#endif // defined(OS_WIN) + + CHECK(false) << "In-process quarantine service should not have failed."; +} + +void BaseFile::AnnotateWithSourceInformation( + const std::string& client_guid, + const GURL& source_url, + const GURL& referrer_url, + std::unique_ptr<service_manager::Connector> connector, + OnAnnotationDoneCallback on_annotation_done_callback) { + GURL authority_url = GetEffectiveAuthorityURL(source_url, referrer_url); + if (!connector) { +#if defined(OS_WIN) + QuarantineFileResult result = quarantine::SetInternetZoneIdentifierDirectly( + full_path_, authority_url, referrer_url); +#else + QuarantineFileResult result = QuarantineFileResult::ANNOTATION_FAILED; +#endif + std::move(on_annotation_done_callback) + .Run(QuarantineFileResultToReason(result)); + } else { + connector->BindInterface(quarantine::mojom::kServiceName, + mojo::MakeRequest(&quarantine_service_)); + + on_annotation_done_callback_ = std::move(on_annotation_done_callback); + + quarantine_service_.set_connection_error_handler(base::BindOnce( + &BaseFile::OnQuarantineServiceError, weak_factory_.GetWeakPtr(), + authority_url, referrer_url)); + + quarantine_service_->QuarantineFile( + full_path_, authority_url, referrer_url, client_guid, + base::BindOnce(&BaseFile::OnFileQuarantined, weak_factory_.GetWeakPtr(), + false)); + } +} + } // namespace download diff --git a/chromium/components/download/internal/common/base_file_win.cc b/chromium/components/download/internal/common/base_file_win.cc index cdaf9d49be9..322636626a5 100644 --- a/chromium/components/download/internal/common/base_file_win.cc +++ b/chromium/components/download/internal/common/base_file_win.cc @@ -15,6 +15,7 @@ #include "base/win/com_init_util.h" #include "base/win/iunknown_impl.h" #include "components/download/public/common/download_interrupt_reasons_utils.h" +#include "components/download/public/common/download_stats.h" namespace download { namespace { @@ -26,6 +27,7 @@ DownloadInterruptReason HRESULTToDownloadInterruptReason(HRESULT hr) { if (SUCCEEDED(hr) && HRESULT_FACILITY(hr) != FACILITY_SHELL) return DOWNLOAD_INTERRUPT_REASON_NONE; + DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE; // All of the remaining HRESULTs to be considered are either from the copy // engine, or are unknown; we've got handling for all the copy engine errors, // and otherwise we'll just return the generic error reason. @@ -51,7 +53,8 @@ DownloadInterruptReason HRESULTToDownloadInterruptReason(HRESULT hr) { // open; often it's antivirus scanning, and this error can be treated as // transient, as we assume eventually the other process will close its // handle. - return DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; + reason = DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR; + break; case COPYENGINE_E_PATH_TOO_DEEP_DEST: case COPYENGINE_E_PATH_TOO_DEEP_SRC: @@ -59,7 +62,8 @@ DownloadInterruptReason HRESULTToDownloadInterruptReason(HRESULT hr) { case COPYENGINE_E_NEWFOLDER_NAME_TOO_LONG: // Any of these errors can be encountered if MAXPATH is hit while writing // out a filename. This can happen really just about anywhere. - return DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG; + reason = DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG; + break; case COPYENGINE_S_USER_IGNORED: // On Windows 7, inability to access a file may return "user ignored" @@ -81,14 +85,16 @@ DownloadInterruptReason HRESULTToDownloadInterruptReason(HRESULT hr) { case COPYENGINE_E_SRC_IS_R_DVD: // When the source is actually a disk, and a Move is attempted, it can't // delete the source. This is unlikely to be encountered in our scenario. - return DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; + reason = DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED; + break; case COPYENGINE_E_FILE_TOO_LARGE: case COPYENGINE_E_DISK_FULL: case COPYENGINE_E_REMOVABLE_FULL: case COPYENGINE_E_DISK_FULL_CLEAN: // No room for the file in the destination location. - return DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE; + reason = DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE; + break; case COPYENGINE_E_ALREADY_EXISTS_NORMAL: case COPYENGINE_E_ALREADY_EXISTS_READONLY: @@ -119,7 +125,13 @@ DownloadInterruptReason HRESULTToDownloadInterruptReason(HRESULT hr) { case COPYENGINE_E_USER_CANCELLED: case COPYENGINE_E_CANCELLED: case COPYENGINE_E_REQUIRES_ELEVATION: - return DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; + reason = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; + break; + } + + if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { + RecordWinFileMoveError(HRESULT_CODE(hr)); + return reason; } // Copy operations may still return Win32 error codes, so handle those here. @@ -302,10 +314,9 @@ DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions( file_operation->GetAnyOperationsAborted(&any_operations_aborted); if (any_operations_aborted) interrupt_reason = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; - } - - if (interrupt_reason != DOWNLOAD_INTERRUPT_REASON_NONE) + } else { return LogInterruptReason("IFileOperation::MoveItem", hr, interrupt_reason); + } return interrupt_reason; } diff --git a/chromium/components/download/internal/common/base_file_win_unittest.cc b/chromium/components/download/internal/common/base_file_win_unittest.cc index 43d98e9a8e4..759eb16f152 100644 --- a/chromium/components/download/internal/common/base_file_win_unittest.cc +++ b/chromium/components/download/internal/common/base_file_win_unittest.cc @@ -78,7 +78,7 @@ TEST(BaseFileWin, AnnotateWithSourceInformation) { base_file.AppendDataToFile(kTestFileContents, base::size(kTestFileContents))); ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, - base_file.AnnotateWithSourceInformation( + base_file.AnnotateWithSourceInformationSync( "7B2CEE7C-DC81-4160-86F1-9C968597118F", url, referrer)); base_file.Detach(); base_file.Finish(); diff --git a/chromium/components/download/internal/common/download_create_info.cc b/chromium/components/download/internal/common/download_create_info.cc index ebc8df19a11..b875d995273 100644 --- a/chromium/components/download/internal/common/download_create_info.cc +++ b/chromium/components/download/internal/common/download_create_info.cc @@ -28,7 +28,7 @@ DownloadCreateInfo::DownloadCreateInfo( save_info(std::move(save_info)), render_process_id(-1), render_frame_id(-1), - accept_range(false), + accept_range(RangeRequestSupportType::kNoSupport), connection_info(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN), method("GET"), ukm_source_id(ukm::kInvalidSourceId) {} diff --git a/chromium/components/download/internal/common/download_db_cache.cc b/chromium/components/download/internal/common/download_db_cache.cc index 7e81fd7ef99..e9f8afffb41 100644 --- a/chromium/components/download/internal/common/download_db_cache.cc +++ b/chromium/components/download/internal/common/download_db_cache.cc @@ -37,6 +37,7 @@ ShouldUpdateDownloadDBResult ShouldUpdateDownloadDB( previous_info = previous->download_info->in_progress_info; base::FilePath previous_path = previous_info ? previous_info->current_path : base::FilePath(); + bool previous_paused = previous_info ? previous_info->paused : false; base::Optional<InProgressInfo> current_info; if (current.download_info) @@ -45,10 +46,12 @@ ShouldUpdateDownloadDBResult ShouldUpdateDownloadDB( base::FilePath current_path = current_info ? current_info->current_path : base::FilePath(); + bool paused = current_info ? current_info->paused : false; + // When download path is determined, Chrome should commit the history // immediately. Otherwise the file will be left permanently on the external // storage if Chrome crashes right away. - if (current_path != previous_path) + if (current_path != previous_path || paused != previous_paused) return ShouldUpdateDownloadDBResult::UPDATE_IMMEDIATELY; if (previous.value() == current) @@ -92,9 +95,7 @@ bool IsInProgressEntry(base::Optional<DownloadDBEntry> entry) { } // namespace DownloadDBCache::DownloadDBCache(std::unique_ptr<DownloadDB> download_db) - : initialized_(false), - download_db_(std::move(download_db)), - weak_factory_(this) { + : initialized_(false), download_db_(std::move(download_db)) { DCHECK(download_db_); } diff --git a/chromium/components/download/internal/common/download_db_cache.h b/chromium/components/download/internal/common/download_db_cache.h index cb9989a741f..bd61630fcc4 100644 --- a/chromium/components/download/internal/common/download_db_cache.h +++ b/chromium/components/download/internal/common/download_db_cache.h @@ -80,7 +80,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadDBCache // Used to trigger db updates. base::OneShotTimer update_timer_; - base::WeakPtrFactory<DownloadDBCache> weak_factory_; + base::WeakPtrFactory<DownloadDBCache> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DownloadDBCache); }; diff --git a/chromium/components/download/internal/common/download_file_impl.cc b/chromium/components/download/internal/common/download_file_impl.cc index 13f52e034d4..f0ebeb52667 100644 --- a/chromium/components/download/internal/common/download_file_impl.cc +++ b/chromium/components/download/internal/common/download_file_impl.cc @@ -10,9 +10,9 @@ #include "base/bind.h" #include "base/files/file_util.h" -#include "base/message_loop/message_loop_current.h" #include "base/strings/stringprintf.h" #include "base/threading/sequenced_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "base/values.h" @@ -20,6 +20,7 @@ #include "components/download/internal/common/parallel_download_utils.h" #include "components/download/public/common/download_create_info.h" #include "components/download/public/common/download_destination_observer.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_stats.h" #include "crypto/secure_hash.h" @@ -27,8 +28,10 @@ #include "mojo/public/c/system/types.h" #include "net/base/io_buffer.h" #include "services/network/public/cpp/features.h" +#include "services/service_manager/public/cpp/connector.h" #if defined(OS_ANDROID) +#include "base/android/content_uri_utils.h" #include "components/download/internal/common/android/download_collection_bridge.h" #endif // defined(OS_ANDROID) @@ -167,9 +170,8 @@ DownloadFileImpl::DownloadFileImpl( bytes_seen_without_parallel_streams_(0), is_paused_(false), download_id_(download_id), - main_task_runner_(base::MessageLoopCurrent::Get()->task_runner()), - observer_(observer), - weak_factory_(this) { + main_task_runner_(base::ThreadTaskRunnerHandle::Get()), + observer_(observer) { TRACE_EVENT_INSTANT0("download", "DownloadFileCreated", TRACE_EVENT_SCOPE_THREAD); TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("download", "DownloadFileActive", @@ -355,26 +357,33 @@ void DownloadFileImpl::RenameAndAnnotate( const std::string& client_guid, const GURL& source_url, const GURL& referrer_url, + std::unique_ptr<service_manager::Connector> connector, const RenameCompletionCallback& callback) { std::unique_ptr<RenameParameters> parameters(new RenameParameters( ANNOTATE_WITH_SOURCE_INFORMATION, full_path, callback)); parameters->client_guid = client_guid; parameters->source_url = source_url; parameters->referrer_url = referrer_url; + parameters->connector = std::move(connector); RenameWithRetryInternal(std::move(parameters)); } #if defined(OS_ANDROID) -void DownloadFileImpl::CreateIntermediateUriForPublish( +void DownloadFileImpl::RenameToIntermediateUri( const GURL& original_url, const GURL& referrer_url, const base::FilePath& file_name, const std::string& mime_type, + const base::FilePath& current_path, const RenameCompletionCallback& callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Create new content URI if |current_path| is not content URI + // or if it is already deleted. base::FilePath content_path = - DownloadCollectionBridge::CreateIntermediateUriForPublish( - original_url, referrer_url, file_name, mime_type); + current_path.IsContentUri() && base::ContentUriExists(current_path) + ? current_path + : DownloadCollectionBridge::CreateIntermediateUriForPublish( + original_url, referrer_url, file_name, mime_type); DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; if (!content_path.empty()) { reason = file_.Rename(content_path); @@ -382,13 +391,13 @@ void DownloadFileImpl::CreateIntermediateUriForPublish( } if (display_name_.empty()) display_name_ = file_name; - OnRenameComplete(reason, content_path, callback); + OnRenameComplete(content_path, callback, reason); } void DownloadFileImpl::PublishDownload( const RenameCompletionCallback& callback) { DownloadInterruptReason reason = file_.PublishDownload(); - OnRenameComplete(reason, file_.full_path(), callback); + OnRenameComplete(file_.full_path(), callback, reason); } base::FilePath DownloadFileImpl::GetDisplayName() { @@ -466,18 +475,33 @@ void DownloadFileImpl::RenameWithRetryInternal( // anti-virus scanners on Windows to actually see the data // (http://crbug.com/127999) under the correct name (which is information // it uses). - reason = file_.AnnotateWithSourceInformation(parameters->client_guid, - parameters->source_url, - parameters->referrer_url); + // + // If concurrent downloads with the same target path are allowed, an + // asynchronous quarantine file may cause a file to be stamped with + // incorrect mark-of-the-web data. Therefore, fall back to non-service + // QuarantineFile when kPreventDownloadsWithSamePath is disabled. + if (base::FeatureList::IsEnabled( + download::features::kPreventDownloadsWithSamePath)) { + file_.AnnotateWithSourceInformation( + parameters->client_guid, parameters->source_url, + parameters->referrer_url, std::move(parameters->connector), + base::BindOnce(&DownloadFileImpl::OnRenameComplete, + weak_factory_.GetWeakPtr(), new_path, + parameters->completion_callback)); + return; + } + reason = file_.AnnotateWithSourceInformationSync(parameters->client_guid, + parameters->source_url, + parameters->referrer_url); } - OnRenameComplete(reason, new_path, parameters->completion_callback); + OnRenameComplete(new_path, parameters->completion_callback, reason); } void DownloadFileImpl::OnRenameComplete( - DownloadInterruptReason reason, const base::FilePath& new_path, - const RenameCompletionCallback& callback) { + const RenameCompletionCallback& callback, + DownloadInterruptReason reason) { if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { // Make sure our information is updated, since we're about to // error out. diff --git a/chromium/components/download/internal/common/download_file_unittest.cc b/chromium/components/download/internal/common/download_file_unittest.cc index a3d72dc2be9..41fd65fe478 100644 --- a/chromium/components/download/internal/common/download_file_unittest.cc +++ b/chromium/components/download/internal/common/download_file_unittest.cc @@ -26,6 +26,7 @@ #include "components/download/public/common/download_interrupt_reasons.h" #include "components/download/public/common/mock_input_stream.h" #include "net/base/net_errors.h" +#include "services/service_manager/public/cpp/connector.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -396,7 +397,7 @@ class DownloadFileTest : public testing::Test { case RENAME_AND_ANNOTATE: download_file_->RenameAndAnnotate( full_path, "12345678-ABCD-1234-DCBA-123456789ABC", GURL(), GURL(), - completion_callback); + nullptr, completion_callback); break; } } diff --git a/chromium/components/download/internal/common/download_item_impl.cc b/chromium/components/download/internal/common/download_item_impl.cc index bd90ec09ce9..386660c5ee9 100644 --- a/chromium/components/download/internal/common/download_item_impl.cc +++ b/chromium/components/download/internal/common/download_item_impl.cc @@ -59,6 +59,7 @@ #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/service_manager/public/cpp/connector.h" #if defined(OS_ANDROID) #include "components/download/internal/common/android/download_collection_bridge.h" @@ -350,8 +351,7 @@ DownloadItemImpl::DownloadItemImpl( last_modified_time_(last_modified), etag_(etag), received_slices_(received_slices), - is_updating_observers_(false), - weak_ptr_factory_(this) { + is_updating_observers_(false) { delegate_->Attach(); DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL || state_ == CANCELLED_INTERNAL); @@ -397,8 +397,7 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, is_updating_observers_(false), fetch_error_body_(info.fetch_error_body), request_headers_(info.request_headers), - download_source_(info.download_source), - weak_ptr_factory_(this) { + download_source_(info.download_source) { delegate_->Attach(); Init(true /* actively downloading */, TYPE_ACTIVE_DOWNLOAD); allow_metered_ |= delegate_->IsActiveNetworkMetered(); @@ -423,8 +422,7 @@ DownloadItemImpl::DownloadItemImpl( state_(IN_PROGRESS_INTERNAL), delegate_(delegate), destination_info_(path, path, 0, false, std::string(), base::Time()), - is_updating_observers_(false), - weak_ptr_factory_(this) { + is_updating_observers_(false) { job_ = DownloadJobFactory::CreateJob(this, std::move(request_handle), DownloadCreateInfo(), true, nullptr, nullptr, nullptr); @@ -588,7 +586,9 @@ void DownloadItemImpl::Resume(bool user_resume) { if (auto_resume_count_ >= kMaxAutoResumeAttempts) return; - ResumeInterruptedDownload(ResumptionRequestSource::USER); + ResumeInterruptedDownload(user_resume + ? ResumptionRequestSource::USER + : ResumptionRequestSource::AUTOMATIC); UpdateObservers(); return; @@ -1493,6 +1493,8 @@ void DownloadItemImpl::Start( DownloadUkmHelper::RecordDownloadStarted( ukm_download_id_, new_create_info.ukm_source_id, file_type, download_source_, state, is_same_host_download); + RecordDownloadValidationMetrics(DownloadMetricsCallsite::kDownloadItem, + state, file_type); if (!delegate_->IsOffTheRecord()) { RecordDownloadCountWithSource(NEW_DOWNLOAD_COUNT_NORMAL_PROFILE, @@ -1640,15 +1642,17 @@ void DownloadItemImpl::OnDownloadTargetDetermined( base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, weak_ptr_factory_.GetWeakPtr()); #if defined(OS_ANDROID) - if (download_type_ == TYPE_ACTIVE_DOWNLOAD && - DownloadCollectionBridge::ShouldPublishDownload(GetTargetFilePath())) { + if ((download_type_ == TYPE_ACTIVE_DOWNLOAD && + DownloadCollectionBridge::ShouldPublishDownload(GetTargetFilePath())) || + GetTargetFilePath().IsContentUri()) { GetDownloadTaskRunner()->PostTask( FROM_HERE, - base::BindOnce(&DownloadFile::CreateIntermediateUriForPublish, + base::BindOnce(&DownloadFile::RenameToIntermediateUri, // Safe because we control download file lifetime. base::Unretained(download_file_.get()), GetOriginalUrl(), - GetReferrerUrl(), GetTargetFilePath().BaseName(), - GetMimeType(), std::move(callback))); + GetReferrerUrl(), GetFileNameToReportUser(), + GetMimeType(), GetTargetFilePath(), + std::move(callback))); return; } #endif // defined(OS_ANDROID) @@ -1783,6 +1787,13 @@ void DownloadItemImpl::OnDownloadCompleting() { return; } #endif // defined(OS_ANDROID) + + std::unique_ptr<service_manager::Connector> new_connector; + service_manager::Connector* connector = + delegate_->GetServiceManagerConnector(); + if (connector) + new_connector = connector->Clone(); + GetDownloadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&DownloadFile::RenameAndAnnotate, @@ -1791,7 +1802,7 @@ void DownloadItemImpl::OnDownloadCompleting() { delegate_->GetApplicationClientIdForFileScanning(), delegate_->IsOffTheRecord() ? GURL() : GetURL(), delegate_->IsOffTheRecord() ? GURL() : GetReferrerUrl(), - std::move(callback))); + std::move(new_connector), std::move(callback))); } void DownloadItemImpl::OnDownloadRenamedToFinalName( @@ -1975,16 +1986,14 @@ void DownloadItemImpl::InterruptWithPartialState( FALLTHROUGH; case IN_PROGRESS_INTERNAL: - case TARGET_RESOLVED_INTERNAL: + case TARGET_RESOLVED_INTERNAL: { // last_reason_ needs to be set for GetResumeMode() to work. last_reason_ = reason; - if (download_file_) { - ResumeMode resume_mode = GetResumeMode(); - ReleaseDownloadFile(resume_mode != ResumeMode::IMMEDIATE_CONTINUE && - resume_mode != ResumeMode::USER_CONTINUE); - } - break; + ResumeMode resume_mode = GetResumeMode(); + ReleaseDownloadFile(resume_mode != ResumeMode::IMMEDIATE_CONTINUE && + resume_mode != ResumeMode::USER_CONTINUE); + } break; case RESUMING_INTERNAL: case INTERRUPTED_INTERNAL: @@ -1995,15 +2004,10 @@ void DownloadItemImpl::InterruptWithPartialState( return; last_reason_ = reason; - if (!GetFullPath().empty()) { - // There is no download file and this is transitioning from INTERRUPTED - // to CANCELLED. The intermediate file is no longer usable, and should - // be deleted. - GetDownloadTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(base::IgnoreResult(&DeleteDownloadedFile), - GetFullPath())); - destination_info_.current_path.clear(); - } + // There is no download file and this is transitioning from INTERRUPTED + // to CANCELLED. The intermediate file is no longer usable, and should + // be deleted. + DeleteDownloadFile(); break; } @@ -2052,7 +2056,8 @@ void DownloadItemImpl::InterruptWithPartialState( RecordDownloadInterrupted(reason, GetReceivedBytes(), total_bytes_, job_ && job_->IsParallelizable(), - IsParallelDownloadEnabled(), download_source_); + IsParallelDownloadEnabled(), download_source_, + received_bytes_at_length_mismatch_ > 0); base::TimeDelta time_since_start = base::Time::Now() - GetStartTime(); int resulting_file_size = GetReceivedBytes(); @@ -2107,15 +2112,19 @@ void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) { DVLOG(20) << __func__ << "() destroy_file:" << destroy_file; if (destroy_file) { - GetDownloadTaskRunner()->PostTask( - FROM_HERE, - // Will be deleted at end of task execution. - base::BindOnce(&DownloadFileCancel, std::move(download_file_))); + if (download_file_) { + GetDownloadTaskRunner()->PostTask( + FROM_HERE, + // Will be deleted at end of task execution. + base::BindOnce(&DownloadFileCancel, std::move(download_file_))); + } else { + DeleteDownloadFile(); + } // Avoid attempting to reuse the intermediate file by clearing out // current_path_ and received slices. destination_info_.current_path.clear(); received_slices_.clear(); - } else { + } else if (download_file_) { GetDownloadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(base::IgnoreResult(&DownloadFileDetach), // Will be deleted at end of task execution. @@ -2127,6 +2136,15 @@ void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) { weak_ptr_factory_.InvalidateWeakPtrs(); } +void DownloadItemImpl::DeleteDownloadFile() { + if (GetFullPath().empty()) + return; + GetDownloadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(base::IgnoreResult(&DeleteDownloadedFile), GetFullPath())); + destination_info_.current_path.clear(); +} + bool DownloadItemImpl::IsDownloadReadyForCompletion( const base::Closure& state_change_notification) { // If the download hasn't progressed to the IN_PROGRESS state, then it's not @@ -2431,6 +2449,13 @@ void DownloadItemImpl::ResumeInterruptedDownload( download_params->set_referrer_policy(net::URLRequest::NEVER_CLEAR_REFERRER); download_params->set_follow_cross_origin_redirects(false); + // If the interruption was caused by content length mismatch, ignore it during + // resumption. + if (last_reason_ == + DOWNLOAD_INTERRUPT_REASON_SERVER_CONTENT_LENGTH_MISMATCH) { + download_params->set_ignore_content_length_mismatch(true); + } + TransitionTo(RESUMING_INTERNAL); RecordDownloadCountWithSource(source == ResumptionRequestSource::USER ? MANUAL_RESUMPTION_COUNT 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 f202fda37a0..93a09d6a13e 100644 --- a/chromium/components/download/internal/common/download_item_impl_unittest.cc +++ b/chromium/components/download/internal/common/download_item_impl_unittest.cc @@ -200,7 +200,7 @@ ACTION_P3(ScheduleRenameAndUniquifyCallback, // Schedules a task to invoke the RenameCompletionCallback with |new_path| on // the |task_runner|. Should only be used as the action for // MockDownloadFile::RenameAndAnnotate as follows: -// EXPECT_CALL(download_file, RenameAndAnnotate(_,_,_,_,_)) +// EXPECT_CALL(download_file, RenameAndAnnotate(_,_,_,_,_,_)) // .WillOnce(ScheduleRenameAndAnnotateCallback( // DOWNLOAD_INTERRUPT_REASON_NONE, new_path, task_runner)); ACTION_P3(ScheduleRenameAndAnnotateCallback, @@ -208,7 +208,7 @@ ACTION_P3(ScheduleRenameAndAnnotateCallback, new_path, task_runner) { task_runner->PostTask(FROM_HERE, - base::BindOnce(arg4, interrupt_reason, new_path)); + base::BindOnce(arg5, interrupt_reason, new_path)); } // Schedules a task to invoke a callback that's bound to the specified @@ -341,7 +341,7 @@ class DownloadItemTest : public testing::Test { EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _)) .WillOnce(Return(true)); base::FilePath final_path(kDummyTargetPath); - EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _)) + EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, final_path, base::ThreadTaskRunnerHandle::Get())); @@ -516,7 +516,7 @@ TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) { EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _)) .WillOnce(Return(true)); - EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _)); + EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _, _)); unsafeurl_item->ValidateDangerousDownload(); EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated()); CleanupItem(unsafeurl_item, download_file, DownloadItem::IN_PROGRESS); @@ -534,7 +534,7 @@ TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) { EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _)) .WillOnce(Return(true)); - EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _)); + EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _, _)); unsafefile_item->ValidateDangerousDownload(); EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated()); CleanupItem(unsafefile_item, download_file, DownloadItem::IN_PROGRESS); @@ -769,8 +769,9 @@ TEST_F(DownloadItemTest, UnresumableInterrupt) { // Fail final rename with unresumable reason. EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _)) .WillOnce(Return(true)); - EXPECT_CALL(*download_file, - RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _)) + EXPECT_CALL( + *download_file, + RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED, base::FilePath(), base::ThreadTaskRunnerHandle::Get())); @@ -1278,7 +1279,7 @@ TEST_F(DownloadItemTest, CallbackAfterRename) { EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _)) .WillOnce(Return(true)); - EXPECT_CALL(*download_file, RenameAndAnnotate(final_path, _, _, _, _)) + EXPECT_CALL(*download_file, RenameAndAnnotate(final_path, _, _, _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, final_path, base::ThreadTaskRunnerHandle::Get())); @@ -1697,7 +1698,7 @@ TEST_F(DownloadItemTest, EnabledActionsForNormalDownload) { EXPECT_TRUE(item->CanOpenDownload()); // Complete - EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _)) + EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath), base::ThreadTaskRunnerHandle::Get())); @@ -1733,7 +1734,7 @@ TEST_F(DownloadItemTest, EnabledActionsForTemporaryDownload) { // Complete Temporary EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _)) .WillOnce(Return(true)); - EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _)) + EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath), base::ThreadTaskRunnerHandle::Get())); @@ -1799,8 +1800,9 @@ TEST_F(DownloadItemTest, CompleteDelegate_ReturnTrue) { EXPECT_FALSE(item->IsDangerous()); // Make sure the download can complete. - EXPECT_CALL(*download_file, - RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _)) + EXPECT_CALL( + *download_file, + RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath), base::ThreadTaskRunnerHandle::Get())); @@ -1839,8 +1841,9 @@ TEST_F(DownloadItemTest, CompleteDelegate_BlockOnce) { EXPECT_FALSE(item->IsDangerous()); // Make sure the download can complete. - EXPECT_CALL(*download_file, - RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _)) + EXPECT_CALL( + *download_file, + RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath), base::ThreadTaskRunnerHandle::Get())); @@ -1882,8 +1885,9 @@ TEST_F(DownloadItemTest, CompleteDelegate_SetDanger) { EXPECT_TRUE(item->IsDangerous()); // Make sure the download doesn't complete until we've validated it. - EXPECT_CALL(*download_file, - RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _)) + EXPECT_CALL( + *download_file, + RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath), base::ThreadTaskRunnerHandle::Get())); @@ -1934,8 +1938,9 @@ TEST_F(DownloadItemTest, CompleteDelegate_BlockTwice) { EXPECT_FALSE(item->IsDangerous()); // Make sure the download can complete. - EXPECT_CALL(*download_file, - RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _)) + EXPECT_CALL( + *download_file, + RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath), base::ThreadTaskRunnerHandle::Get())); @@ -2046,7 +2051,7 @@ TEST_F(DownloadItemTest, AnnotationWithEmptyURLInIncognito) { DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); // Target file should be annotated with the source URL. EXPECT_CALL(*download_file, - RenameAndAnnotate(_, _, create_info()->url(), _, _)) + RenameAndAnnotate(_, _, create_info()->url(), _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath), base::ThreadTaskRunnerHandle::Get())); @@ -2064,7 +2069,7 @@ TEST_F(DownloadItemTest, AnnotationWithEmptyURLInIncognito) { download_file = DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); // Target file should be annotated with an empty URL. - EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, GURL(), _, _)) + EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, GURL(), _, _, _)) .WillOnce(ScheduleRenameAndAnnotateCallback( DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath), base::ThreadTaskRunnerHandle::Get())); diff --git a/chromium/components/download/internal/common/download_job.cc b/chromium/components/download/internal/common/download_job.cc index d65b3348c41..f69b10805a7 100644 --- a/chromium/components/download/internal/common/download_job.cc +++ b/chromium/components/download/internal/common/download_job.cc @@ -16,8 +16,7 @@ DownloadJob::DownloadJob( std::unique_ptr<DownloadRequestHandleInterface> request_handle) : download_item_(download_item), request_handle_(std::move(request_handle)), - is_paused_(false), - weak_ptr_factory_(this) {} + is_paused_(false) {} DownloadJob::~DownloadJob() = default; diff --git a/chromium/components/download/internal/common/download_job_factory.cc b/chromium/components/download/internal/common/download_job_factory.cc index 0c351882c8f..db41162941f 100644 --- a/chromium/components/download/internal/common/download_job_factory.cc +++ b/chromium/components/download/internal/common/download_job_factory.cc @@ -10,6 +10,7 @@ #include "components/download/internal/common/parallel_download_job.h" #include "components/download/internal/common/parallel_download_utils.h" #include "components/download/internal/common/save_package_download_job.h" +#include "components/download/public/common/download_features.h" #include "components/download/public/common/download_item.h" #include "components/download/public/common/download_stats.h" #include "components/download/public/common/download_url_loader_factory_getter.h" @@ -18,6 +19,57 @@ namespace download { namespace { +// Connection type of the download. +enum class ConnectionType { + kHTTP = 0, + kHTTP2, + kQUIC, + kUnknown, +}; + +ConnectionType GetConnectionType( + net::HttpResponseInfo::ConnectionInfo connection_info) { + switch (connection_info) { + case net::HttpResponseInfo::CONNECTION_INFO_HTTP0_9: + case net::HttpResponseInfo::CONNECTION_INFO_HTTP1_0: + case net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1: + return ConnectionType::kHTTP; + case net::HttpResponseInfo::CONNECTION_INFO_DEPRECATED_SPDY2: + case net::HttpResponseInfo::CONNECTION_INFO_DEPRECATED_SPDY3: + case net::HttpResponseInfo::CONNECTION_INFO_DEPRECATED_HTTP2_14: + case net::HttpResponseInfo::CONNECTION_INFO_DEPRECATED_HTTP2_15: + case net::HttpResponseInfo::CONNECTION_INFO_HTTP2: + return ConnectionType::kHTTP2; + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_32: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_33: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_34: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_35: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_36: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_37: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_38: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_39: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_40: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_41: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_42: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_43: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_44: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_45: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_46: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_47: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_48: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_99: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_999: + return ConnectionType::kQUIC; + case net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN: + return ConnectionType::kUnknown; + case net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS: + NOTREACHED(); + return ConnectionType::kUnknown; + } + NOTREACHED(); + return ConnectionType::kUnknown; +} // Returns if the download can be parallelized. bool IsParallelizableDownload(const DownloadCreateInfo& create_info, @@ -41,16 +93,28 @@ bool IsParallelizableDownload(const DownloadCreateInfo& create_info, bool satisfy_min_file_size = !download_item->GetReceivedSlices().empty() || create_info.total_bytes >= GetMinSliceSizeConfig(); - bool satisfy_connection_type = create_info.connection_info == - net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1; + ConnectionType type = GetConnectionType(create_info.connection_info); + bool satisfy_connection_type = + (create_info.connection_info == + net::HttpResponseInfo::CONNECTION_INFO_HTTP1_1) || + (type == ConnectionType::kHTTP2 && + base::FeatureList::IsEnabled(features::kUseParallelRequestsForHTTP2)) || + (type == ConnectionType::kQUIC && + base::FeatureList::IsEnabled(features::kUseParallelRequestsForQUIC)); bool http_get_method = create_info.method == "GET" && create_info.url().SchemeIsHTTPOrHTTPS(); bool partial_response_success = download_item->GetReceivedSlices().empty() || create_info.offset != 0; - bool is_parallelizable = has_strong_validator && create_info.accept_range && + bool range_support_allowed = + create_info.accept_range == RangeRequestSupportType::kSupport || + (base::FeatureList::IsEnabled( + features::kUseParallelRequestsForUnknwonRangeSupport) && + create_info.accept_range == RangeRequestSupportType::kUnknown); + bool is_parallelizable = has_strong_validator && range_support_allowed && has_content_length && satisfy_min_file_size && satisfy_connection_type && http_get_method && partial_response_success; + RecordDownloadConnectionInfo(create_info.connection_info); if (!IsParallelDownloadEnabled()) return is_parallelizable; @@ -59,14 +123,17 @@ bool IsParallelizableDownload(const DownloadCreateInfo& create_info, is_parallelizable ? ParallelDownloadCreationEvent::STARTED_PARALLEL_DOWNLOAD : ParallelDownloadCreationEvent::FELL_BACK_TO_NORMAL_DOWNLOAD); - if (!has_strong_validator) { RecordParallelDownloadCreationEvent( ParallelDownloadCreationEvent::FALLBACK_REASON_STRONG_VALIDATORS); } - if (!create_info.accept_range) { + if (!range_support_allowed) { RecordParallelDownloadCreationEvent( ParallelDownloadCreationEvent::FALLBACK_REASON_ACCEPT_RANGE_HEADER); + if (create_info.accept_range == RangeRequestSupportType::kUnknown) { + RecordParallelDownloadCreationEvent( + ParallelDownloadCreationEvent::FALLBACK_REASON_UNKNOWN_RANGE_SUPPORT); + } } if (!has_content_length) { RecordParallelDownloadCreationEvent( 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 8a4004127f7..d35d7862c89 100644 --- a/chromium/components/download/internal/common/download_path_reservation_tracker.cc +++ b/chromium/components/download/internal/common/download_path_reservation_tracker.cc @@ -61,7 +61,8 @@ const size_t kZoneIdentifierLength = sizeof(":Zone.Identifier") - 1; ReservationMap* g_reservation_map = NULL; base::LazySequencedTaskRunner g_sequenced_task_runner = - LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({base::MayBlock()}); + LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER( + base::TaskTraits(base::ThreadPool(), base::MayBlock())); // Observes a DownloadItem for changes to its target path and state. Updates or // revokes associated download path reservations as necessary. Created, invoked @@ -400,7 +401,7 @@ void UpdateReservation(ReservationKey key, const base::FilePath& new_path) { // |key|. void RevokeReservation(ReservationKey key) { DCHECK(g_reservation_map != NULL); - DCHECK(base::ContainsKey(*g_reservation_map, key)); + DCHECK(base::Contains(*g_reservation_map, key)); g_reservation_map->erase(key); if (g_reservation_map->size() == 0) { // No more reservations. Delete map. diff --git a/chromium/components/download/internal/common/download_response_handler.cc b/chromium/components/download/internal/common/download_response_handler.cc index d203a3cf163..1d5e3942653 100644 --- a/chromium/components/download/internal/common/download_response_handler.cc +++ b/chromium/components/download/internal/common/download_response_handler.cc @@ -58,7 +58,9 @@ DownloadResponseHandler::DownloadResponseHandler( const DownloadUrlParameters::RequestHeadersType& request_headers, const std::string& request_origin, DownloadSource download_source, - std::vector<GURL> url_chain) + bool ignore_content_length_mismatch, + std::vector<GURL> url_chain, + bool is_background_mode) : delegate_(delegate), started_(false), save_info_(std::move(save_info)), @@ -73,10 +75,11 @@ DownloadResponseHandler::DownloadResponseHandler( request_headers_(request_headers), request_origin_(request_origin), download_source_(download_source), - has_strong_validators_(false), + ignore_content_length_mismatch_(ignore_content_length_mismatch), is_partial_request_(save_info_->offset > 0), completed_(false), - abort_reason_(DOWNLOAD_INTERRUPT_REASON_NONE) { + abort_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), + is_background_mode_(is_background_mode) { if (!is_parallel_request) { RecordDownloadCountWithSource(UNTHROTTLED_COUNT, download_source); } @@ -95,8 +98,17 @@ void DownloadResponseHandler::OnReceiveResponse( // Sets page transition type correctly and call // |RecordDownloadSourcePageTransitionType| here. if (head.headers) { - has_strong_validators_ = head.headers->HasStrongValidators(); - RecordDownloadHttpResponseCode(head.headers->response_code()); + // ERR_CONTENT_LENGTH_MISMATCH can be caused by 1 of the following reasons: + // 1. Server or proxy closes the connection too early. + // 2. The content-length header is wrong. + // If the download has strong validators, we can interrupt the download + // and let it resume automatically. Otherwise, resuming the download will + // cause it to restart and the download may never complete if the error was + // caused by reason 2. As a result, downloads without strong validators are + // treated as completed here. + ignore_content_length_mismatch_ |= !head.headers->HasStrongValidators(); + RecordDownloadHttpResponseCode(head.headers->response_code(), + is_background_mode_); RecordDownloadContentDisposition(create_info_->content_disposition); } @@ -222,8 +234,9 @@ void DownloadResponseHandler::OnComplete( completed_ = true; DownloadInterruptReason reason = HandleRequestCompletionStatus( - static_cast<net::Error>(status.error_code), has_strong_validators_, - cert_status_, abort_reason_); + static_cast<net::Error>(status.error_code), + ignore_content_length_mismatch_, cert_status_, is_partial_request_, + abort_reason_); if (client_ptr_) { client_ptr_->OnStreamCompleted( @@ -233,6 +246,11 @@ void DownloadResponseHandler::OnComplete( if (reason == DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED) { base::UmaHistogramSparse("Download.MapErrorNetworkFailed.NetworkService", std::abs(status.error_code)); + if (is_background_mode_) { + base::UmaHistogramSparse( + "Download.MapErrorNetworkFailed.NetworkService.BackgroundDownload", + std::abs(status.error_code)); + } } if (started_) { diff --git a/chromium/components/download/internal/common/download_stats.cc b/chromium/components/download/internal/common/download_stats.cc index a46e7db8f5c..1060096e1d8 100644 --- a/chromium/components/download/internal/common/download_stats.cc +++ b/chromium/components/download/internal/common/download_stats.cc @@ -613,13 +613,19 @@ void RecordDownloadInterrupted(DownloadInterruptReason reason, int64_t total, bool is_parallelizable, bool is_parallel_download_enabled, - DownloadSource download_source) { + DownloadSource download_source, + bool post_content_length_mismatch) { RecordDownloadCountWithSource(INTERRUPTED_COUNT, download_source); if (is_parallelizable) { RecordParallelizableDownloadCount(INTERRUPTED_COUNT, is_parallel_download_enabled); } + if (post_content_length_mismatch) { + base::UmaHistogramSparse( + "Download.ResumptionAfterContentLengthMismatch.Reason", reason); + } + std::vector<base::HistogramBase::Sample> samples = base::CustomHistogram::ArrayToCustomEnumRanges(kAllInterruptReasonCodes); UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.InterruptedReason", reason, @@ -644,8 +650,6 @@ void RecordDownloadInterrupted(DownloadInterruptReason reason, bool unknown_size = total <= 0; int64_t received_kb = received / 1024; int64_t total_kb = total / 1024; - UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedReceivedSizeK", received_kb, - 1, kMaxKb, kBuckets); if (is_parallel_download_enabled) { UMA_HISTOGRAM_CUSTOM_COUNTS( "Download.InterruptedReceivedSizeK.ParallelDownload", received_kb, 1, @@ -662,31 +666,9 @@ void RecordDownloadInterrupted(DownloadInterruptReason reason, } if (delta_bytes == 0) { RecordDownloadCountWithSource(INTERRUPTED_AT_END_COUNT, download_source); - UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.InterruptedAtEndReason", - reason, samples); - if (is_parallelizable) { RecordParallelizableDownloadCount(INTERRUPTED_AT_END_COUNT, is_parallel_download_enabled); - UMA_HISTOGRAM_CUSTOM_ENUMERATION( - "Download.InterruptedAtEndReason.ParallelDownload", reason, - samples); - } - } else if (delta_bytes > 0) { - UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedOverrunBytes", - delta_bytes, 1, kMaxKb, kBuckets); - if (is_parallel_download_enabled) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Download.InterruptedOverrunBytes.ParallelDownload", delta_bytes, 1, - kMaxKb, kBuckets); - } - } else { - UMA_HISTOGRAM_CUSTOM_COUNTS("Download.InterruptedUnderrunBytes", - -delta_bytes, 1, kMaxKb, kBuckets); - if (is_parallel_download_enabled) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Download.InterruptedUnderrunBytes.ParallelDownload", -delta_bytes, - 1, kMaxKb, kBuckets); } } } @@ -929,6 +911,54 @@ void RecordDownloadVideoType(const std::string& mime_type_string) { DOWNLOAD_VIDEO_MAX); } +// These histograms summarize download mime-types. The same data is recorded in +// a few places, as they exist to sanity-check and understand other metrics. +const char* const kDownloadMetricsVerificationNameItemSecure = + "Download.InsecureBlocking.Verification.Item.Secure"; +const char* const kDownloadMetricsVerificationNameItemInsecure = + "Download.InsecureBlocking.Verification.Item.Insecure"; +const char* const kDownloadMetricsVerificationNameItemOther = + "Download.InsecureBlocking.Verification.Item.Other"; +const char* const kDownloadMetricsVerificationNameManagerSecure = + "Download.InsecureBlocking.Verification.Manager.Secure"; +const char* const kDownloadMetricsVerificationNameManagerInsecure = + "Download.InsecureBlocking.Verification.Manager.Insecure"; +const char* const kDownloadMetricsVerificationNameManagerOther = + "Download.InsecureBlocking.Verification.Manager.Other"; + +const char* GetDownloadValidationMetricName( + const DownloadMetricsCallsite& callsite, + const DownloadConnectionSecurity& state) { + DCHECK(callsite == DownloadMetricsCallsite::kDownloadItem || + callsite == DownloadMetricsCallsite::kMixContentDownloadBlocking); + + switch (state) { + case DOWNLOAD_SECURE: + case DOWNLOAD_TARGET_BLOB: + case DOWNLOAD_TARGET_DATA: + case DOWNLOAD_TARGET_FILE: + if (callsite == DownloadMetricsCallsite::kDownloadItem) + return kDownloadMetricsVerificationNameItemSecure; + return kDownloadMetricsVerificationNameManagerSecure; + case DOWNLOAD_TARGET_INSECURE: + case DOWNLOAD_REDIRECT_INSECURE: + case DOWNLOAD_REDIRECT_TARGET_INSECURE: + if (callsite == DownloadMetricsCallsite::kDownloadItem) + return kDownloadMetricsVerificationNameItemInsecure; + return kDownloadMetricsVerificationNameManagerInsecure; + case DOWNLOAD_TARGET_OTHER: + case DOWNLOAD_TARGET_FILESYSTEM: + case DOWNLOAD_TARGET_FTP: + if (callsite == DownloadMetricsCallsite::kDownloadItem) + return kDownloadMetricsVerificationNameItemOther; + return kDownloadMetricsVerificationNameManagerOther; + case DOWNLOAD_CONNECTION_SECURITY_MAX: + NOTREACHED(); + } + NOTREACHED(); + return nullptr; +} + } // namespace DownloadContent DownloadContentFromMimeType(const std::string& mime_type_string, @@ -1055,8 +1085,16 @@ void RecordParallelDownloadRequestCount(int request_count) { request_count, 1, 10, 11); } -void RecordParallelDownloadAddStreamSuccess(bool success) { - UMA_HISTOGRAM_BOOLEAN("Download.ParallelDownloadAddStreamSuccess", success); +void RecordParallelDownloadAddStreamSuccess(bool success, + bool support_range_request) { + if (support_range_request) { + base::UmaHistogramBoolean("Download.ParallelDownloadAddStreamSuccess", + success); + } else { + base::UmaHistogramBoolean( + "Download.ParallelDownloadAddStreamSuccess.NoAcceptRangesHeader", + success); + } } void RecordParallelizableContentLength(int64_t content_length) { @@ -1118,10 +1156,6 @@ void RecordParallelizableDownloadStats( UMA_HISTOGRAM_CUSTOM_COUNTS( "Download.EstimatedTimeSavedWithParallelDownload", time_saved.InMilliseconds(), 0, kMillisecondsPerHour, 50); - } else { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Download.EstimatedTimeWastedWithParallelDownload", - -time_saved.InMilliseconds(), 0, kMillisecondsPerHour, 50); } } @@ -1193,6 +1227,14 @@ DownloadConnectionSecurity CheckDownloadConnectionSecurity( return state; } +void RecordDownloadValidationMetrics(DownloadMetricsCallsite callsite, + DownloadConnectionSecurity state, + DownloadContent file_type) { + base::UmaHistogramEnumeration( + GetDownloadValidationMetricName(callsite, state), file_type, + DownloadContent::MAX); +} + void RecordDownloadConnectionSecurity(const GURL& download_url, const std::vector<GURL>& url_chain) { UMA_HISTOGRAM_ENUMERATION( @@ -1238,11 +1280,17 @@ void RecordDownloadSourcePageTransitionType( ui::PAGE_TRANSITION_LAST_CORE + 1); } -void RecordDownloadHttpResponseCode(int response_code) { - UMA_HISTOGRAM_CUSTOM_ENUMERATION( - "Download.HttpResponseCode", - net::HttpUtil::MapStatusCodeForHistogram(response_code), - net::HttpUtil::GetStatusCodesForHistogram()); +void RecordDownloadHttpResponseCode(int response_code, + bool is_background_mode) { + int status_code = net::HttpUtil::MapStatusCodeForHistogram(response_code); + std::vector<int> status_codes = net::HttpUtil::GetStatusCodesForHistogram(); + UMA_HISTOGRAM_CUSTOM_ENUMERATION("Download.HttpResponseCode", status_code, + status_codes); + if (is_background_mode) { + UMA_HISTOGRAM_CUSTOM_ENUMERATION( + "Download.HttpResponseCode.BackgroundDownload", status_code, + status_codes); + } } void RecordInProgressDBCount(InProgressDBCountTypes type) { @@ -1267,6 +1315,13 @@ void RecordDownloadResumed(bool has_strong_validators) { has_strong_validators); } +void RecordDownloadConnectionInfo( + net::HttpResponseInfo::ConnectionInfo connection_info) { + base::UmaHistogramEnumeration( + "Download.ConnectionInfo", connection_info, + net::HttpResponseInfo::ConnectionInfo::NUM_OF_CONNECTION_INFOS); +} + #if defined(OS_ANDROID) void RecordFirstBackgroundDownloadInterruptReason( DownloadInterruptReason reason, @@ -1277,6 +1332,17 @@ void RecordFirstBackgroundDownloadInterruptReason( else base::UmaHistogramSparse("MobileDownload.FirstBackground.Reason", reason); } + +void RecordBackgroundTargetDeterminationResult( + BackgroudTargetDeterminationResultTypes type) { + base::UmaHistogramEnumeration( + "MobileDownload.Background.TargetDeterminationResult", type); +} #endif // defined(OS_ANDROID) +#if defined(OS_WIN) +void RecordWinFileMoveError(int os_error) { + base::UmaHistogramSparse("Download.WinFileMoveError", os_error); +} +#endif // defined(OS_WIN) } // namespace download diff --git a/chromium/components/download/internal/common/download_task_runner.cc b/chromium/components/download/internal/common/download_task_runner.cc index 27bfc6f3860..cb198e7eff9 100644 --- a/chromium/components/download/internal/common/download_task_runner.cc +++ b/chromium/components/download/internal/common/download_task_runner.cc @@ -20,12 +20,16 @@ namespace { // necessitating the use of a COM single-threaded apartment sequence. base::LazyCOMSTATaskRunner g_download_task_runner = LAZY_COM_STA_TASK_RUNNER_INITIALIZER( - base::TaskTraits(base::MayBlock(), base::TaskPriority::USER_VISIBLE), + base::TaskTraits(base::ThreadPool(), + base::MayBlock(), + base::TaskPriority::USER_VISIBLE), base::SingleThreadTaskRunnerThreadMode::SHARED); #else base::LazySequencedTaskRunner g_download_task_runner = LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER( - base::TaskTraits(base::MayBlock(), base::TaskPriority::USER_VISIBLE)); + base::TaskTraits(base::ThreadPool(), + base::MayBlock(), + base::TaskPriority::USER_VISIBLE)); #endif base::LazyInstance<scoped_refptr<base::SingleThreadTaskRunner>>:: diff --git a/chromium/components/download/internal/common/download_utils.cc b/chromium/components/download/internal/common/download_utils.cc index 43c571344a1..b1c816f2dee 100644 --- a/chromium/components/download/internal/common/download_utils.cc +++ b/chromium/components/download/internal/common/download_utils.cc @@ -53,22 +53,12 @@ const uint32_t DownloadItem::kInvalidId = 0; DownloadInterruptReason HandleRequestCompletionStatus( net::Error error_code, - bool has_strong_validators, + bool ignore_content_length_mismatch, net::CertStatus cert_status, + bool is_partial_request, DownloadInterruptReason abort_reason) { - // ERR_CONTENT_LENGTH_MISMATCH can be caused by 1 of the following reasons: - // 1. Server or proxy closes the connection too early. - // 2. The content-length header is wrong. - // If the download has strong validators, we can interrupt the download - // and let it resume automatically. Otherwise, resuming the download will - // cause it to restart and the download may never complete if the error was - // caused by reason 2. As a result, downloads without strong validators are - // treated as completed here. - // TODO(qinmin): check the metrics from downloads with strong validators, - // and decide whether we should interrupt downloads without strong validators - // rather than complete them. if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH && - !has_strong_validators) { + ignore_content_length_mismatch) { error_code = net::OK; RecordDownloadCount(COMPLETED_WITH_CONTENT_LENGTH_MISMATCH_COUNT); } @@ -93,6 +83,12 @@ DownloadInterruptReason HandleRequestCompletionStatus( return abort_reason; } + // For some servers, a range request could cause the server to send + // wrongly encoded content and cause decoding failures. Restart the download + // in that case. + if (is_partial_request && error_code == net::ERR_CONTENT_DECODING_FAILED) + return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE; + return ConvertNetErrorToInterruptReason(error_code, DOWNLOAD_INTERRUPT_FROM_NETWORK); } @@ -190,12 +186,8 @@ DownloadInterruptReason HandleSuccessfulServerResponse( (save_info->length > 0 && last_byte != save_info->offset + save_info->length - 1)) { // The server returned a different range than the one we requested. Assume - // the response is bad. - // - // In the future we should consider allowing offsets that are less than - // the offset we've requested, since in theory we can truncate the partial - // file at the offset and continue. - return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; + // the server doesn't support range request. + return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE; } return DOWNLOAD_INTERRUPT_REASON_NONE; @@ -237,10 +229,15 @@ void HandleResponseHeaders(const net::HttpResponseHeaders* headers, // In RFC 7233, a single part 206 partial response must generate // Content-Range. Accept-Range may be sent in 200 response to indicate the // server can handle range request, but optional in 206 response. - create_info->accept_range = - headers->HasHeaderValue("Accept-Ranges", "bytes") || + if (headers->HasHeaderValue("Accept-Ranges", "bytes") || (headers->HasHeader("Content-Range") && - headers->response_code() == net::HTTP_PARTIAL_CONTENT); + headers->response_code() == net::HTTP_PARTIAL_CONTENT)) { + create_info->accept_range = RangeRequestSupportType::kSupport; + } else if (headers->HasHeaderValue("Accept-Ranges", "none")) { + create_info->accept_range = RangeRequestSupportType::kNoSupport; + } else { + create_info->accept_range = RangeRequestSupportType::kUnknown; + } } std::unique_ptr<network::ResourceRequest> CreateResourceRequest( @@ -263,7 +260,7 @@ std::unique_ptr<network::ResourceRequest> CreateResourceRequest( // See also: // - https://crbug.com/952834 // - https://github.com/whatwg/fetch/issues/896#issuecomment-484423278 - request->fetch_request_mode = network::mojom::FetchRequestMode::kNavigate; + request->mode = network::mojom::RequestMode::kNavigate; bool has_upload_data = false; if (params->post_body()) { diff --git a/chromium/components/download/internal/common/download_worker.cc b/chromium/components/download/internal/common/download_worker.cc index ad5bec88089..cd55965b6a7 100644 --- a/chromium/components/download/internal/common/download_worker.cc +++ b/chromium/components/download/internal/common/download_worker.cc @@ -79,8 +79,7 @@ DownloadWorker::DownloadWorker(DownloadWorker::Delegate* delegate, is_paused_(false), is_canceled_(false), is_user_cancel_(false), - url_download_handler_(nullptr, base::OnTaskRunnerDeleter(nullptr)), - weak_factory_(this) { + url_download_handler_(nullptr, base::OnTaskRunnerDeleter(nullptr)) { DCHECK(delegate_); } diff --git a/chromium/components/download/internal/common/download_worker.h b/chromium/components/download/internal/common/download_worker.h index 6021c0603af..26b57219725 100644 --- a/chromium/components/download/internal/common/download_worker.h +++ b/chromium/components/download/internal/common/download_worker.h @@ -96,7 +96,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker // Used to handle the url request. Live and die on IO thread. UrlDownloadHandler::UniqueUrlDownloadHandlerPtr url_download_handler_; - base::WeakPtrFactory<DownloadWorker> weak_factory_; + base::WeakPtrFactory<DownloadWorker> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DownloadWorker); }; 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 1c05b2fc4ce..de9122bcedc 100644 --- a/chromium/components/download/internal/common/in_progress_download_manager.cc +++ b/chromium/components/download/internal/common/in_progress_download_manager.cc @@ -31,6 +31,7 @@ #if defined(OS_ANDROID) #include "components/download/internal/common/android/download_collection_bridge.h" +#include "components/download/public/common/download_path_reservation_tracker.h" #endif namespace download { @@ -89,6 +90,7 @@ void BeginResourceDownload( const GURL& tab_url, const GURL& tab_referrer_url, std::unique_ptr<service_manager::Connector> connector, + bool is_background_mode, const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) { DCHECK(GetIOTaskRunner()->BelongsToCurrentThread()); UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader( @@ -96,7 +98,7 @@ void BeginResourceDownload( 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, - std::move(connector), main_task_runner) + std::move(connector), is_background_mode, main_task_runner) .release(), base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())); @@ -113,8 +115,9 @@ void CreateDownloadHandlerForNavigation( const GURL& tab_url, const GURL& tab_referrer_url, std::vector<GURL> url_chain, - scoped_refptr<network::ResourceResponse> response, net::CertStatus cert_status, + scoped_refptr<network::ResourceResponse> response_head, + mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter, const URLSecurityPolicy& url_security_policy, @@ -125,7 +128,8 @@ void CreateDownloadHandlerForNavigation( ResourceDownloader::InterceptNavigationResponse( download_manager, std::move(resource_request), render_process_id, render_frame_id, site_url, tab_url, tab_referrer_url, - std::move(url_chain), std::move(response), std::move(cert_status), + std::move(url_chain), std::move(cert_status), + std::move(response_head), std::move(response_body), std::move(url_loader_client_endpoints), std::move(url_loader_factory_getter), url_security_policy, std::move(connector), main_task_runner) @@ -145,7 +149,38 @@ void OnDownloadDisplayNamesReturned( FROM_HERE, base::BindOnce(std::move(callback), std::move(download_names))); } + +void OnPathReserved( + const DownloadItemImplDelegate::DownloadTargetCallback& callback, + DownloadDangerType danger_type, + const InProgressDownloadManager::IntermediatePathCallback& + intermediate_path_cb, + const base::FilePath& forced_file_path, + PathValidationResult result, + const base::FilePath& target_path) { + base::FilePath intermediate_path; + if (!target_path.empty() && + (result == PathValidationResult::SUCCESS || + result == download::PathValidationResult::SAME_AS_SOURCE)) { + if (!forced_file_path.empty()) { + DCHECK_EQ(target_path, forced_file_path); + intermediate_path = target_path; + } else if (intermediate_path_cb) { + intermediate_path = intermediate_path_cb.Run(target_path); + } + } + + RecordBackgroundTargetDeterminationResult( + intermediate_path.empty() + ? BackgroudTargetDeterminationResultTypes::kPathReservationFailed + : BackgroudTargetDeterminationResultTypes::kSuccess); + callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE, + danger_type, intermediate_path, + intermediate_path.empty() ? DOWNLOAD_INTERRUPT_REASON_FILE_FAILED + : DOWNLOAD_INTERRUPT_REASON_NONE); +} #endif + } // namespace bool InProgressDownloadManager::Delegate::InterceptDownload( @@ -176,8 +211,7 @@ InProgressDownloadManager::InProgressDownloadManager( 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) { + connector_(connector) { Initialize(in_progress_db_dir); } @@ -268,6 +302,7 @@ void InProgressDownloadManager::BeginDownload( 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, + !delegate_ /* is_background_mode */, base::ThreadTaskRunnerHandle::Get())); } @@ -279,21 +314,22 @@ void InProgressDownloadManager::InterceptDownloadFromNavigation( const GURL& tab_url, const GURL& tab_referrer_url, std::vector<GURL> url_chain, - scoped_refptr<network::ResourceResponse> response, net::CertStatus cert_status, + scoped_refptr<network::ResourceResponse> response_head, + mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter) { GetIOTaskRunner()->PostTask( FROM_HERE, - base::BindOnce(&CreateDownloadHandlerForNavigation, - weak_factory_.GetWeakPtr(), std::move(resource_request), - render_process_id, render_frame_id, site_url, tab_url, - tab_referrer_url, std::move(url_chain), - std::move(response), std::move(cert_status), - std::move(url_loader_client_endpoints), - std::move(url_loader_factory_getter), url_security_policy_, - connector_ ? connector_->Clone() : nullptr, - base::ThreadTaskRunnerHandle::Get())); + base::BindOnce( + &CreateDownloadHandlerForNavigation, weak_factory_.GetWeakPtr(), + std::move(resource_request), render_process_id, render_frame_id, + site_url, tab_url, tab_referrer_url, std::move(url_chain), + std::move(cert_status), std::move(response_head), + std::move(response_body), std::move(url_loader_client_endpoints), + std::move(url_loader_factory_getter), url_security_policy_, + connector_ ? connector_->Clone() : nullptr, + base::ThreadTaskRunnerHandle::Get())); } void InProgressDownloadManager::Initialize( @@ -315,26 +351,40 @@ void InProgressDownloadManager::ShutDown() { void InProgressDownloadManager::DetermineDownloadTarget( DownloadItemImpl* download, const DownloadTargetCallback& callback) { - 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) + base::FilePath target_path = download->GetForcedFilePath().empty() + ? download->GetTargetFilePath() + : download->GetForcedFilePath(); + + if (target_path.empty()) { + callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE, + download->GetDangerType(), target_path, + DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); + RecordBackgroundTargetDeterminationResult( + BackgroudTargetDeterminationResultTypes::kTargetPathMissing); + return; + } + // 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); + if (target_path.IsContentUri()) { + callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE, + download->GetDangerType(), target_path, + DOWNLOAD_INTERRUPT_REASON_NONE); + RecordBackgroundTargetDeterminationResult( + BackgroudTargetDeterminationResultTypes::kSuccess); + return; } - callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE, - download->GetDangerType(), intermediate_path, - intermediate_path.empty() ? DOWNLOAD_INTERRUPT_REASON_FILE_FAILED - : DOWNLOAD_INTERRUPT_REASON_NONE); + + DownloadPathReservationTracker::GetReservedPath( + download, target_path, target_path.DirName(), default_download_dir_, + true /* create_directory */, + download->GetForcedFilePath().empty() + ? DownloadPathReservationTracker::UNIQUIFY + : DownloadPathReservationTracker::OVERWRITE, + base::Bind(&OnPathReserved, callback, download->GetDangerType(), + intermediate_path_cb_, download->GetForcedFilePath())); +#endif } void InProgressDownloadManager::ResumeInterruptedDownload( @@ -357,7 +407,7 @@ base::Optional<DownloadEntry> InProgressDownloadManager::GetInProgressEntry( DownloadItemImpl* download) { if (!download) return base::Optional<DownloadEntry>(); - if (base::ContainsKey(download_entries_, download->GetGuid())) + if (base::Contains(download_entries_, download->GetGuid())) return download_entries_[download->GetGuid()]; return base::Optional<DownloadEntry>(); @@ -454,7 +504,7 @@ void InProgressDownloadManager::StartDownloadWithItem( if (info->is_new_download && !should_persist_new_download) non_persistent_download_guids_.insert(download->GetGuid()); // If the download is not persisted, don't notify |download_db_cache_|. - if (!base::ContainsKey(non_persistent_download_guids_, download->GetGuid())) { + if (!base::Contains(non_persistent_download_guids_, download->GetGuid())) { download_db_cache_->AddOrReplaceEntry( CreateDownloadDBEntryFromItem(*download)); download->RemoveObserver(download_db_cache_.get()); @@ -526,7 +576,7 @@ void InProgressDownloadManager::OnDownloadNamesRetrieved( uint32_t download_id = item->GetId(); // Remove entries with duplicate ids. if (download_id != DownloadItem::kInvalidId && - base::ContainsKey(download_ids, download_id)) { + base::Contains(download_ids, download_id)) { RemoveInProgressDownload(item->GetGuid()); num_duplicates++; continue; diff --git a/chromium/components/download/internal/common/parallel_download_job.cc b/chromium/components/download/internal/common/parallel_download_job.cc index 1ac7dbbb753..45600c7054f 100644 --- a/chromium/components/download/internal/common/parallel_download_job.cc +++ b/chromium/components/download/internal/common/parallel_download_job.cc @@ -35,6 +35,7 @@ ParallelDownloadJob::ParallelDownloadJob( content_length_(create_info.total_bytes), requests_sent_(false), is_canceled_(false), + range_support_(create_info.accept_range), url_loader_factory_getter_(std::move(url_loader_factory_getter)), url_request_context_getter_(url_request_context_getter), connector_(connector) {} @@ -134,7 +135,9 @@ void ParallelDownloadJob::OnInputStreamReady( success = DownloadJob::AddInputStream(std::move(input_stream), worker->offset(), worker->length()); } - RecordParallelDownloadAddStreamSuccess(success); + + RecordParallelDownloadAddStreamSuccess( + success, range_support_ == RangeRequestSupportType::kSupport); // Destroy the request if the sink is gone. if (!success) { @@ -184,10 +187,6 @@ void ParallelDownloadJob::BuildParallelRequests() { int64_t remaining_bytes = download_item_->GetTotalBytes() - download_item_->GetReceivedBytes(); - int64_t remaining_time = remaining_bytes / current_bytes_per_second; - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Download.ParallelDownload.RemainingTimeWhenBuildingRequests", - remaining_time, 0, base::TimeDelta::FromDays(1).InSeconds(), 50); if (remaining_bytes / current_bytes_per_second > GetMinRemainingTimeInSeconds()) { // Fork more requests to accelerate, only if one slice is left to download diff --git a/chromium/components/download/internal/common/parallel_download_job.h b/chromium/components/download/internal/common/parallel_download_job.h index 71c45c861f6..ca410838e13 100644 --- a/chromium/components/download/internal/common/parallel_download_job.h +++ b/chromium/components/download/internal/common/parallel_download_job.h @@ -14,6 +14,7 @@ #include "base/timer/timer.h" #include "components/download/internal/common/download_job_impl.h" #include "components/download/internal/common/download_worker.h" +#include "components/download/public/common/download_create_info.h" #include "components/download/public/common/download_export.h" #include "components/download/public/common/parallel_download_configs.h" @@ -119,6 +120,9 @@ class COMPONENTS_DOWNLOAD_EXPORT ParallelDownloadJob // If the download progress is canceled. bool is_canceled_; + // Whether the server accepts range requests. + RangeRequestSupportType range_support_; + // URLLoaderFactory getter to issue network requests with network service scoped_refptr<download::DownloadURLLoaderFactoryGetter> url_loader_factory_getter_; diff --git a/chromium/components/download/internal/common/resource_downloader.cc b/chromium/components/download/internal/common/resource_downloader.cc index 5ddb3408e76..aaeef1a691f 100644 --- a/chromium/components/download/internal/common/resource_downloader.cc +++ b/chromium/components/download/internal/common/resource_downloader.cc @@ -71,6 +71,7 @@ std::unique_ptr<ResourceDownloader> ResourceDownloader::BeginDownload( bool is_new_download, bool is_parallel_request, std::unique_ptr<service_manager::Connector> connector, + bool is_background_mode, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { auto downloader = std::make_unique<ResourceDownloader>( delegate, std::move(request), params->render_process_host_id(), @@ -79,7 +80,7 @@ std::unique_ptr<ResourceDownloader> ResourceDownloader::BeginDownload( std::move(url_loader_factory_getter), url_security_policy, std::move(connector)); - downloader->Start(std::move(params), is_parallel_request); + downloader->Start(std::move(params), is_parallel_request, is_background_mode); return downloader; } @@ -94,8 +95,9 @@ ResourceDownloader::InterceptNavigationResponse( const GURL& tab_url, const GURL& tab_referrer_url, std::vector<GURL> url_chain, - const scoped_refptr<network::ResourceResponse>& response, net::CertStatus cert_status, + const scoped_refptr<network::ResourceResponse>& response_head, + mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, scoped_refptr<download::DownloadURLLoaderFactoryGetter> url_loader_factory_getter, @@ -107,9 +109,9 @@ ResourceDownloader::InterceptNavigationResponse( site_url, tab_url, tab_referrer_url, true, task_runner, 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)); + downloader->InterceptResponse( + std::move(url_chain), cert_status, std::move(response_head), + std::move(response_body), std::move(url_loader_client_endpoints)); return downloader; } @@ -137,8 +139,7 @@ ResourceDownloader::ResourceDownloader( tab_referrer_url_(tab_referrer_url), 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) { + url_security_policy_(url_security_policy) { RequestWakeLock(connector.get()); } @@ -146,7 +147,8 @@ ResourceDownloader::~ResourceDownloader() = default; void ResourceDownloader::Start( std::unique_ptr<DownloadUrlParameters> download_url_parameters, - bool is_parallel_request) { + bool is_parallel_request, + bool is_background_mode) { callback_ = download_url_parameters->callback(); upload_callback_ = download_url_parameters->upload_callback(); guid_ = download_url_parameters->guid(); @@ -162,7 +164,8 @@ void ResourceDownloader::Start( download_url_parameters->request_headers(), download_url_parameters->request_origin(), download_url_parameters->download_source(), - std::vector<GURL>(1, resource_request_->url)); + download_url_parameters->ignore_content_length_mismatch(), + std::vector<GURL>(1, resource_request_->url), is_background_mode); network::mojom::URLLoaderClientPtr url_loader_client_ptr; url_loader_client_binding_ = std::make_unique<mojo::Binding<network::mojom::URLLoaderClient>>( @@ -184,9 +187,10 @@ void ResourceDownloader::Start( } void ResourceDownloader::InterceptResponse( - const scoped_refptr<network::ResourceResponse>& response, std::vector<GURL> url_chain, net::CertStatus cert_status, + const scoped_refptr<network::ResourceResponse>& response_head, + mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr endpoints) { // Set the URLLoader. url_loader_.Bind(std::move(endpoints->url_loader)); @@ -200,11 +204,17 @@ void ResourceDownloader::InterceptResponse( true, /* follow_cross_origin_redirects */ download::DownloadUrlParameters::RequestHeadersType(), std::string(), /* request_origin */ - download::DownloadSource::NAVIGATION, std::move(url_chain)); + download::DownloadSource::NAVIGATION, + false /* ignore_content_length_mismatch */, std::move(url_chain), + false /* is_background_mode */); // Simulate on the new URLLoaderClient calls that happened on the old client. - response->head.cert_status = cert_status; - url_loader_client_->OnReceiveResponse(response->head); + response_head->head.cert_status = cert_status; + url_loader_client_->OnReceiveResponse(response_head->head); + + // Available when NavigationImmediateResponse is enabled. + if (response_body) + url_loader_client_->OnStartLoadingResponseBody(std::move(response_body)); // Bind the new client. url_loader_client_binding_ = diff --git a/chromium/components/download/internal/common/resource_downloader.h b/chromium/components/download/internal/common/resource_downloader.h index b2f8ec766fe..ed355ee35be 100644 --- a/chromium/components/download/internal/common/resource_downloader.h +++ b/chromium/components/download/internal/common/resource_downloader.h @@ -42,6 +42,7 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader bool is_new_download, bool is_parallel_request, std::unique_ptr<service_manager::Connector> connector, + bool is_background_mode, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner); // Create a ResourceDownloader from a navigation that turns to be a download. @@ -56,8 +57,9 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader const GURL& tab_url, const GURL& tab_referrer_url, std::vector<GURL> url_chain, - const scoped_refptr<network::ResourceResponse>& response, net::CertStatus cert_status, + const scoped_refptr<network::ResourceResponse>& response_head, + mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, scoped_refptr<download::DownloadURLLoaderFactoryGetter> url_loader_factory_getter, @@ -94,13 +96,15 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader // Helper method to start the network request. void Start( std::unique_ptr<download::DownloadUrlParameters> download_url_parameters, - bool is_parallel_request); + bool is_parallel_request, + bool is_background_mode); // Intercepts the navigation response. void InterceptResponse( - const scoped_refptr<network::ResourceResponse>& response, std::vector<GURL> url_chain, net::CertStatus cert_status, + const scoped_refptr<network::ResourceResponse>& response_head, + mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints); // UrlDownloadHandler implementations. @@ -170,7 +174,7 @@ class COMPONENTS_DOWNLOAD_EXPORT ResourceDownloader // download to be interrupted. device::mojom::WakeLockPtr wake_lock_; - base::WeakPtrFactory<ResourceDownloader> weak_ptr_factory_; + base::WeakPtrFactory<ResourceDownloader> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(ResourceDownloader); }; 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 bf1a4f42df9..9cf5796b068 100644 --- a/chromium/components/download/internal/common/simple_download_manager_coordinator.cc +++ b/chromium/components/download/internal/common/simple_download_manager_coordinator.cc @@ -20,8 +20,7 @@ SimpleDownloadManagerCoordinator::SimpleDownloadManagerCoordinator( current_manager_has_all_history_downloads_(false), initialized_(false), download_when_full_manager_starts_cb_( - download_when_full_manager_starts_cb), - weak_factory_(this) {} + download_when_full_manager_starts_cb) {} SimpleDownloadManagerCoordinator::~SimpleDownloadManagerCoordinator() { if (simple_download_manager_) @@ -73,8 +72,10 @@ void SimpleDownloadManagerCoordinator::DownloadUrl( void SimpleDownloadManagerCoordinator::GetAllDownloads( std::vector<DownloadItem*>* downloads) { - if (simple_download_manager_) + if (simple_download_manager_) { simple_download_manager_->GetAllDownloads(downloads); + simple_download_manager_->GetUninitializedActiveDownloadsIfAny(downloads); + } } DownloadItem* SimpleDownloadManagerCoordinator::GetDownloadByGuid( @@ -106,4 +107,8 @@ AllDownloadEventNotifier* SimpleDownloadManagerCoordinator::GetNotifier() { return notifier_.get(); } +void SimpleDownloadManagerCoordinator::CheckForExternallyRemovedDownloads() { + simple_download_manager_->CheckForHistoryFilesRemoval(); +} + } // namespace download 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 c295bc9dfaa..d0634a03292 100644 --- a/chromium/components/download/internal/common/url_download_handler_factory.cc +++ b/chromium/components/download/internal/common/url_download_handler_factory.cc @@ -40,7 +40,8 @@ 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, std::move(connector), task_runner) + GURL(), GURL(), true, true, std::move(connector), + false /* is_background_mode */, task_runner) .release(), base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())); } diff --git a/chromium/components/download/network/BUILD.gn b/chromium/components/download/network/BUILD.gn index c3719e8e2bf..9b3e61bcfd4 100644 --- a/chromium/components/download/network/BUILD.gn +++ b/chromium/components/download/network/BUILD.gn @@ -53,6 +53,5 @@ if (is_android) { sources = [ "android/java/src/org/chromium/components/download/NetworkStatusListenerAndroid.java", ] - jni_package = "components/download/network" } } diff --git a/chromium/components/download/network/DEPS b/chromium/components/download/network/DEPS index b0597c63381..e0d62f0fa88 100644 --- a/chromium/components/download/network/DEPS +++ b/chromium/components/download/network/DEPS @@ -1,6 +1,6 @@ include_rules = [ "-content", - "+jni", + "+components/download/network/jni_headers", "+net", "+services/network/public", ] diff --git a/chromium/components/download/network/android/network_status_listener_android.cc b/chromium/components/download/network/android/network_status_listener_android.cc index 505d81b01b5..7d13f0728cc 100644 --- a/chromium/components/download/network/android/network_status_listener_android.cc +++ b/chromium/components/download/network/android/network_status_listener_android.cc @@ -6,7 +6,7 @@ #include "base/android/jni_android.h" #include "base/trace_event/trace_event.h" -#include "jni/NetworkStatusListenerAndroid_jni.h" +#include "components/download/network/jni_headers/NetworkStatusListenerAndroid_jni.h" namespace download { diff --git a/chromium/components/download/public/common/BUILD.gn b/chromium/components/download/public/common/BUILD.gn index 5937c55370e..5883cbbcb11 100644 --- a/chromium/components/download/public/common/BUILD.gn +++ b/chromium/components/download/public/common/BUILD.gn @@ -80,6 +80,7 @@ component("public") { "//base", "//components/download/database", "//components/download/internal/common:internal", + "//components/services/quarantine:quarantine", "//crypto", "//net", "//services/metrics/public/cpp:metrics_cpp", @@ -142,6 +143,7 @@ source_set("test_support") { ":public", "//base", "//net", + "//services/service_manager/public/cpp:cpp", "//testing/gmock", "//url", ] diff --git a/chromium/components/download/public/common/DEPS b/chromium/components/download/public/common/DEPS index 8de183633e6..cf72027ee02 100644 --- a/chromium/components/download/public/common/DEPS +++ b/chromium/components/download/public/common/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+crypto", "+components/keyed_service/core", + "+components/services/quarantine/public/mojom/quarantine.mojom.h", "+mojo/public/cpp/bindings", "+mojo/public/cpp/system", "+net/base/io_buffer.h", @@ -16,6 +17,7 @@ include_rules = [ "+services/network/public/cpp", "+services/network/public/mojom", "+services/network/test", + "+services/service_manager/public/cpp/connector.h", "+storage/browser", "+ui/base", ] diff --git a/chromium/components/download/public/common/auto_resumption_handler.cc b/chromium/components/download/public/common/auto_resumption_handler.cc index eca40b4bfb1..9cfdb609737 100644 --- a/chromium/components/download/public/common/auto_resumption_handler.cc +++ b/chromium/components/download/public/common/auto_resumption_handler.cc @@ -70,25 +70,6 @@ bool IsConnected(network::mojom::ConnectionType type) { } } -bool IsInterruptedDownloadAutoResumable(download::DownloadItem* download_item, - int auto_resumption_size_limit) { - if (!download_item->GetURL().SchemeIsHTTPOrHTTPS()) - return false; - - if (download_item->GetBytesWasted() > auto_resumption_size_limit) - return false; - - int interrupt_reason = download_item->GetLastReason(); - DCHECK_NE(interrupt_reason, download::DOWNLOAD_INTERRUPT_REASON_NONE); - return interrupt_reason == - download::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT || - interrupt_reason == - download::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED || - interrupt_reason == - download::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED || - interrupt_reason == download::DOWNLOAD_INTERRUPT_REASON_CRASH; -} - } // namespace namespace download { @@ -118,8 +99,7 @@ AutoResumptionHandler::AutoResumptionHandler( std::unique_ptr<Config> config) : network_listener_(std::move(network_listener)), task_manager_(std::move(task_manager)), - config_(std::move(config)), - weak_factory_(this) { + config_(std::move(config)) { network_listener_->Start(this); } @@ -189,6 +169,7 @@ void AutoResumptionHandler::OnDownloadRemoved(download::DownloadItem* item) { } void AutoResumptionHandler::OnDownloadDestroyed(download::DownloadItem* item) { + resumable_downloads_.erase(item->GetGuid()); downloads_to_retry_.erase(item); } @@ -288,7 +269,7 @@ bool AutoResumptionHandler::SatisfiesNetworkRequirements( bool AutoResumptionHandler::IsAutoResumableDownload( download::DownloadItem* item) { - if (item->IsDangerous()) + if (!item || item->IsDangerous()) return false; switch (item->GetState()) { @@ -308,4 +289,29 @@ bool AutoResumptionHandler::IsAutoResumableDownload( return false; } +// static +bool AutoResumptionHandler::IsInterruptedDownloadAutoResumable( + download::DownloadItem* download_item, + int auto_resumption_size_limit) { + DCHECK_EQ(download::DownloadItem::INTERRUPTED, download_item->GetState()); + if (download_item->IsDangerous()) + return false; + + if (!download_item->GetURL().SchemeIsHTTPOrHTTPS()) + return false; + + if (download_item->GetBytesWasted() > auto_resumption_size_limit) + return false; + + int interrupt_reason = download_item->GetLastReason(); + DCHECK_NE(interrupt_reason, download::DOWNLOAD_INTERRUPT_REASON_NONE); + return interrupt_reason == + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT || + interrupt_reason == + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED || + interrupt_reason == + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED || + interrupt_reason == download::DOWNLOAD_INTERRUPT_REASON_CRASH; +} + } // namespace download diff --git a/chromium/components/download/public/common/auto_resumption_handler.h b/chromium/components/download/public/common/auto_resumption_handler.h index 14982236837..955f8aa8d6d 100644 --- a/chromium/components/download/public/common/auto_resumption_handler.h +++ b/chromium/components/download/public/common/auto_resumption_handler.h @@ -44,6 +44,12 @@ class COMPONENTS_DOWNLOAD_EXPORT AutoResumptionHandler // initialization is not yet complete. static AutoResumptionHandler* Get(); + // Utility function to determine whether an interrupted download should be + // auto-resumable. + static bool IsInterruptedDownloadAutoResumable( + download::DownloadItem* download_item, + int auto_resumption_size_limit); + AutoResumptionHandler( std::unique_ptr<download::NetworkStatusListener> network_listener, std::unique_ptr<download::TaskManager> task_manager, @@ -89,7 +95,7 @@ class COMPONENTS_DOWNLOAD_EXPORT AutoResumptionHandler bool recompute_task_params_scheduled_ = false; - base::WeakPtrFactory<AutoResumptionHandler> weak_factory_; + base::WeakPtrFactory<AutoResumptionHandler> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(AutoResumptionHandler); }; diff --git a/chromium/components/download/public/common/base_file.h b/chromium/components/download/public/common/base_file.h index dd8ed1b1993..4a01d7b7d0e 100644 --- a/chromium/components/download/public/common/base_file.h +++ b/chromium/components/download/public/common/base_file.h @@ -18,16 +18,22 @@ #include "base/gtest_prod_util.h" #include "base/logging.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/sequence_checker.h" #include "base/time/time.h" #include "build/build_config.h" #include "components/download/public/common/download_export.h" #include "components/download/public/common/download_interrupt_reasons.h" +#include "components/services/quarantine/public/mojom/quarantine.mojom.h" #include "crypto/secure_hash.h" #include "net/base/net_errors.h" #include "url/gurl.h" +namespace service_manager { +class Connector; +} + namespace download { // File being downloaded and saved to disk. This is a base class @@ -152,11 +158,29 @@ class COMPONENTS_DOWNLOAD_EXPORT BaseFile { // that originated this download. Will be used to annotate source // information and also to determine the relative danger level of the // file. - DownloadInterruptReason AnnotateWithSourceInformation( + DownloadInterruptReason AnnotateWithSourceInformationSync( const std::string& client_guid, const GURL& source_url, const GURL& referrer_url); + // Callback used with AnnotateWithSourceInformation. + // Created by DownloadFileImpl::RenameWithRetryInternal + // to bind DownloadFileImpl::OnRenameComplete. + using OnAnnotationDoneCallback = + base::OnceCallback<void(DownloadInterruptReason)>; + + // Called when a quarantine service is used, + // connector is used to populate a quarantine::mojom::QuarantinePtr, + // and the callback will be called from the service. + // TODO (crbug.com/973497): Remove non-service version when + // kPreventDownloadsWithSamePath feature is removed. + void AnnotateWithSourceInformation( + const std::string& client_guid, + const GURL& source_url, + const GURL& referrer_url, + std::unique_ptr<service_manager::Connector> connector, + OnAnnotationDoneCallback on_annotation_done_callback); + #if defined(OS_ANDROID) // Publishes the intermediate download to public download collection. DownloadInterruptReason PublishDownload(); @@ -244,6 +268,15 @@ class COMPONENTS_DOWNLOAD_EXPORT BaseFile { int os_error, DownloadInterruptReason reason); + // Callback invoked when quarantine service has an error. + void OnQuarantineServiceError(const GURL& source_url, + const GURL& referrer_url); + + // Callback invoked by quarantine service. Also called by + // OnQuarantineServiceError after manually applying mark-of-the-web. + void OnFileQuarantined(bool connection_error, + quarantine::mojom::QuarantineFileResult result); + // Full path to the file including the file name. base::FilePath full_path_; @@ -271,8 +304,16 @@ class COMPONENTS_DOWNLOAD_EXPORT BaseFile { // ID of the download, used for trace events. uint32_t download_id_; + // Mojo pointer for quarantine service. + quarantine::mojom::QuarantinePtr quarantine_service_; + + // Callback invoked after quarantine service finishes. + OnAnnotationDoneCallback on_annotation_done_callback_; + SEQUENCE_CHECKER(sequence_checker_); + base::WeakPtrFactory<BaseFile> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(BaseFile); }; diff --git a/chromium/components/download/public/common/download_create_info.h b/chromium/components/download/public/common/download_create_info.h index 19552ad5b07..0e97e309a85 100644 --- a/chromium/components/download/public/common/download_create_info.h +++ b/chromium/components/download/public/common/download_create_info.h @@ -35,6 +35,16 @@ class HttpResponseHeaders; namespace download { +// Server support for range request inferred from the response headers. +// |kSupport| value means the server supports range requests. |kNoSupport| +// means no range request is accepted by server. and |kUnknown| is used if +// range request support cannot be inferred from response headers. +enum class RangeRequestSupportType { + kSupport = 0, + kUnknown, + kNoSupport, +}; + // Used for informing the download manager of a new download, since we don't // want to pass |DownloadItem|s between threads. struct COMPONENTS_DOWNLOAD_EXPORT DownloadCreateInfo { @@ -142,10 +152,8 @@ struct COMPONENTS_DOWNLOAD_EXPORT DownloadCreateInfo { // For continuing a download, the ETag of the file. std::string etag; - // If the download response can be partial content. - // Either "Accept-Ranges" or "Content-Range" header presents in the - // response header. - bool accept_range; + // Whether the server supports range requests. + RangeRequestSupportType accept_range; // The HTTP connection type. net::HttpResponseInfo::ConnectionInfo connection_info; diff --git a/chromium/components/download/public/common/download_danger_type.h b/chromium/components/download/public/common/download_danger_type.h index e9e8952413b..e93fbb52efd 100644 --- a/chromium/components/download/public/common/download_danger_type.h +++ b/chromium/components/download/public/common/download_danger_type.h @@ -47,6 +47,12 @@ enum DownloadDangerType { // Download URL whitelisted by enterprise policy. DOWNLOAD_DANGER_TYPE_WHITELISTED_BY_POLICY = 9, + // Download is pending a more detailed verdict. + DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING = 10, + + // Download is password protected, and should be blocked according to policy. + DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED = 11, + // Memory space for histograms is determined by the max. // ALWAYS ADD NEW VALUES BEFORE THIS ONE. DOWNLOAD_DANGER_TYPE_MAX diff --git a/chromium/components/download/public/common/download_features.cc b/chromium/components/download/public/common/download_features.cc index 7e945dd4815..3d27465f635 100644 --- a/chromium/components/download/public/common/download_features.cc +++ b/chromium/components/download/public/common/download_features.cc @@ -48,6 +48,16 @@ const base::Feature kUseInProgressDownloadManagerForDownloadService{ const base::Feature kAllowDownloadResumptionWithoutStrongValidators{ "AllowDownloadResumptionWithoutStrongValidators", base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::Feature kUseParallelRequestsForUnknwonRangeSupport{ + "UseParallelRequestForUnknownRangeSupport", + base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::Feature kUseParallelRequestsForHTTP2{ + "kUseParallelRequestsForHTTP2", base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::Feature kUseParallelRequestsForQUIC{ + "kUseParallelRequestsForQUIC", 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 a3d7fda74f6..345844aafa9 100644 --- a/chromium/components/download/public/common/download_features.h +++ b/chromium/components/download/public/common/download_features.h @@ -45,7 +45,21 @@ COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature // Whether download resumption is allowed when there are no strong validators. COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature kAllowDownloadResumptionWithoutStrongValidators; + +// Whether parallel requests are used if server response doesn't reveal range +// support. +COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature + kUseParallelRequestsForUnknwonRangeSupport; + +// Whether parallel download is used for HTTP2 connections. +COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature + kUseParallelRequestsForHTTP2; + +// Whether parallel download is used for QUIC connections. +COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature + kUseParallelRequestsForQUIC; } // namespace features + } // namespace download #endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_FEATURES_H_ diff --git a/chromium/components/download/public/common/download_file.h b/chromium/components/download/public/common/download_file.h index 545b4d186aa..6cfd902a6d4 100644 --- a/chromium/components/download/public/common/download_file.h +++ b/chromium/components/download/public/common/download_file.h @@ -22,6 +22,10 @@ class GURL; +namespace service_manager { +class Connector; +} + namespace download { // These objects live exclusively on the download sequence and handle the @@ -82,11 +86,17 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFile { // Rename the download file to |full_path| and annotate it with // "Mark of the Web" information about its source. No uniquification // will be performed. - virtual void RenameAndAnnotate(const base::FilePath& full_path, - const std::string& client_guid, - const GURL& source_url, - const GURL& referrer_url, - const RenameCompletionCallback& callback) = 0; + // connector is a clone of the service manager connector from + // DownloadItemImpl's delegate. It used to create the quarantine service. + // In the unexpected case that connector is null, or the service otherwise + // fails, mark-of-the-web is manually applied as a fallback. + virtual void RenameAndAnnotate( + const base::FilePath& full_path, + const std::string& client_guid, + const GURL& source_url, + const GURL& referrer_url, + std::unique_ptr<service_manager::Connector> connector, + const RenameCompletionCallback& callback) = 0; // Detach the file so it is not deleted on destruction. virtual void Detach() = 0; @@ -109,13 +119,16 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFile { virtual void Resume() = 0; #if defined(OS_ANDROID) - // Create an intermediate URI to write the download file. Once completes, - // |callback| is called with a content URI to be written into. - virtual void CreateIntermediateUriForPublish( + // Renames the download file to an intermediate URI. If current_path is a + // content URI, it will be used for the renaming. Otherwise, A new + // intermediate URI will be created to write the download file. Once + // completes, |callback| is called with a content URI to be written into. + virtual void RenameToIntermediateUri( const GURL& original_url, const GURL& referrer_url, const base::FilePath& file_name, const std::string& mime_type, + const base::FilePath& current_path, const RenameCompletionCallback& callback) = 0; // Publishes the download to public. Once completes, |callback| is called with diff --git a/chromium/components/download/public/common/download_file_impl.h b/chromium/components/download/public/common/download_file_impl.h index c3dee68fc39..1b33f39da91 100644 --- a/chromium/components/download/public/common/download_file_impl.h +++ b/chromium/components/download/public/common/download_file_impl.h @@ -28,9 +28,14 @@ #include "components/download/public/common/download_item.h" #include "components/download/public/common/download_save_info.h" #include "components/download/public/common/rate_estimator.h" +#include "components/services/quarantine/public/mojom/quarantine.mojom.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/system/simple_watcher.h" +namespace service_manager { +class Connector; +} + namespace download { class DownloadDestinationObserver; @@ -67,6 +72,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { const std::string& client_guid, const GURL& source_url, const GURL& referrer_url, + std::unique_ptr<service_manager::Connector> connector, const RenameCompletionCallback& callback) override; void Detach() override; void Cancel() override; @@ -77,11 +83,12 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { void Resume() override; #if defined(OS_ANDROID) - void CreateIntermediateUriForPublish( + void RenameToIntermediateUri( const GURL& original_url, const GURL& referrer_url, const base::FilePath& file_name, const std::string& mime_type, + const base::FilePath& current_path, const RenameCompletionCallback& callback) override; void PublishDownload(const RenameCompletionCallback& callback) override; base::FilePath GetDisplayName() override; @@ -227,6 +234,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { std::string client_guid; // See BaseFile::AnnotateWithSourceInformation() GURL source_url; // See BaseFile::AnnotateWithSourceInformation() GURL referrer_url; // See BaseFile::AnnotateWithSourceInformation() + std::unique_ptr<service_manager::Connector> connector; int retries_left; // RenameWithRetryInternal() will // automatically retry until this // count reaches 0. Each attempt @@ -241,9 +249,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { void RenameWithRetryInternal(std::unique_ptr<RenameParameters> parameters); // Called after |file_| was renamed. - void OnRenameComplete(DownloadInterruptReason reason, - const base::FilePath& content_path, - const RenameCompletionCallback& callback); + void OnRenameComplete(const base::FilePath& content_path, + const RenameCompletionCallback& callback, + DownloadInterruptReason reason); // Send an update on our progress. void SendUpdate(); @@ -370,7 +378,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { SEQUENCE_CHECKER(sequence_checker_); base::WeakPtr<DownloadDestinationObserver> observer_; - base::WeakPtrFactory<DownloadFileImpl> weak_factory_; + base::WeakPtrFactory<DownloadFileImpl> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DownloadFileImpl); }; diff --git a/chromium/components/download/public/common/download_item_impl.h b/chromium/components/download/public/common/download_item_impl.h index 0da7255e41a..72e52e201a7 100644 --- a/chromium/components/download/public/common/download_item_impl.h +++ b/chromium/components/download/public/common/download_item_impl.h @@ -612,6 +612,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl // resets |current_path_|. void ReleaseDownloadFile(bool destroy_file); + // Deletes the download file at |current_path_|. + void DeleteDownloadFile(); + // Check if a download is ready for completion. The callback provided // may be called at some point in the future if an external entity // state has change s.t. this routine should be checked again. @@ -831,7 +834,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl THREAD_CHECKER(thread_checker_); - base::WeakPtrFactory<DownloadItemImpl> weak_ptr_factory_; + base::WeakPtrFactory<DownloadItemImpl> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DownloadItemImpl); }; diff --git a/chromium/components/download/public/common/download_job.h b/chromium/components/download/public/common/download_job.h index 82ab597fc50..0831b93fc4f 100644 --- a/chromium/components/download/public/common/download_job.h +++ b/chromium/components/download/public/common/download_job.h @@ -74,7 +74,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadJob { // If the download progress is paused by the user. bool is_paused_; - base::WeakPtrFactory<DownloadJob> weak_ptr_factory_; + base::WeakPtrFactory<DownloadJob> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DownloadJob); }; diff --git a/chromium/components/download/public/common/download_response_handler.h b/chromium/components/download/public/common/download_response_handler.h index ce94c9a0560..9b67e71af4b 100644 --- a/chromium/components/download/public/common/download_response_handler.h +++ b/chromium/components/download/public/common/download_response_handler.h @@ -52,7 +52,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler const DownloadUrlParameters::RequestHeadersType& request_headers, const std::string& request_origin, DownloadSource download_source, - std::vector<GURL> url_chain); + bool ignore_content_length_mismatch, + std::vector<GURL> url_chain, + bool is_background_mode); ~DownloadResponseHandler() override; // network::mojom::URLLoaderClient @@ -95,7 +97,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler std::string request_origin_; DownloadSource download_source_; net::CertStatus cert_status_; - bool has_strong_validators_; + bool ignore_content_length_mismatch_; base::Optional<url::Origin> request_initiator_; bool is_partial_request_; bool completed_; @@ -106,6 +108,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler // Mojo interface ptr to send the completion status to the download sink. mojom::DownloadStreamClientPtr client_ptr_; + // Whether the download is running in background mode. + bool is_background_mode_; DISALLOW_COPY_AND_ASSIGN(DownloadResponseHandler); }; diff --git a/chromium/components/download/public/common/download_stats.h b/chromium/components/download/public/common/download_stats.h index 7e10804bac4..9e72887e191 100644 --- a/chromium/components/download/public/common/download_stats.h +++ b/chromium/components/download/public/common/download_stats.h @@ -21,6 +21,7 @@ #include "components/download/public/common/download_export.h" #include "components/download/public/common/download_interrupt_reasons.h" #include "components/download/public/common/download_source.h" +#include "net/http/http_response_info.h" #include "ui/base/page_transition_types.h" #include "url/gurl.h" @@ -216,6 +217,9 @@ enum class ParallelDownloadCreationEvent { // The http method or url scheme does not meet the requirement. FALLBACK_REASON_HTTP_METHOD, + // Range support is unknown from the response. + FALLBACK_REASON_UNKNOWN_RANGE_SUPPORT, + // Last entry of the enum. COUNT, }; @@ -263,7 +267,8 @@ COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadInterrupted( int64_t total, bool is_parallelizable, bool is_parallel_download_enabled, - DownloadSource download_source); + DownloadSource download_source, + bool post_content_length_mismatch); // Record that a download has been classified as malicious. COMPONENTS_DOWNLOAD_EXPORT void RecordMaliciousDownloadClassified( @@ -324,8 +329,11 @@ COMPONENTS_DOWNLOAD_EXPORT void RecordParallelDownloadRequestCount( int request_count); // Records if each byte stream is successfully added to download sink. +// |support_range_request| indicates whether the server strongly supports range +// requests. COMPONENTS_DOWNLOAD_EXPORT void RecordParallelDownloadAddStreamSuccess( - bool success); + bool success, + bool support_range_request); // Records the bandwidth for parallelizable download and estimates the saved // time at the file end. Does not count in any hash computation or file @@ -402,10 +410,27 @@ enum DownloadConnectionSecurity { DOWNLOAD_CONNECTION_SECURITY_MAX }; +enum class DownloadMetricsCallsite { + // Called from within DownloadItem initialization. + kDownloadItem = 0, + + // Called from within MixedContentDownloadBlocking (as part of + // ChromeDownloadManagerDelegate). + kMixContentDownloadBlocking, +}; + COMPONENTS_DOWNLOAD_EXPORT DownloadConnectionSecurity CheckDownloadConnectionSecurity(const GURL& download_url, const std::vector<GURL>& url_chain); +// Records a download's mime-type and security state. This is a short-lived +// metric recorded in multiple callsites to investigate discrepancies in other +// metrics. +COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadValidationMetrics( + DownloadMetricsCallsite callsite, + DownloadConnectionSecurity state, + DownloadContent file_type); + COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadConnectionSecurity( const GURL& download_url, const std::vector<GURL>& url_chain); @@ -421,7 +446,8 @@ COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadSourcePageTransitionType( const base::Optional<ui::PageTransition>& transition); COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadHttpResponseCode( - int response_code); + int response_code, + bool is_background_mode); COMPONENTS_DOWNLOAD_EXPORT void RecordInProgressDBCount( InProgressDBCountTypes type); @@ -444,6 +470,10 @@ COMPONENTS_DOWNLOAD_EXPORT void RecordResumptionRestartCount( COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadResumed( bool has_strong_validators); +// Records connection info of the download. +COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadConnectionInfo( + net::HttpResponseInfo::ConnectionInfo connection_info); + #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 @@ -451,7 +481,30 @@ COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadResumed( COMPONENTS_DOWNLOAD_EXPORT void RecordFirstBackgroundDownloadInterruptReason( DownloadInterruptReason reason, bool download_started); + +enum class BackgroudTargetDeterminationResultTypes { + // Target determination succeeded. + kSuccess = 0, + + // Target path doesn't exist. + kTargetPathMissing = 1, + + // Path reservation failed. + kPathReservationFailed = 2, + + kMaxValue = kPathReservationFailed +}; + +// Records whether download target determination is successfully completed in +// reduced mode. +COMPONENTS_DOWNLOAD_EXPORT void RecordBackgroundTargetDeterminationResult( + BackgroudTargetDeterminationResultTypes type); #endif // defined(OS_ANDROID) + +#if defined(OS_WIN) +// Records the OS error code when moving a file on Windows. +COMPONENTS_DOWNLOAD_EXPORT void RecordWinFileMoveError(int os_error); +#endif // defined(OS_WIN) } // namespace download #endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_STATS_H_ diff --git a/chromium/components/download/public/common/download_url_parameters.cc b/chromium/components/download/public/common/download_url_parameters.cc index fd465914dc1..0c85c8f6a9a 100644 --- a/chromium/components/download/public/common/download_url_parameters.cc +++ b/chromium/components/download/public/common/download_url_parameters.cc @@ -40,7 +40,8 @@ DownloadUrlParameters::DownloadUrlParameters( transient_(false), traffic_annotation_(traffic_annotation), download_source_(DownloadSource::UNKNOWN), - require_safety_checks_(true) {} + require_safety_checks_(true), + ignore_content_length_mismatch_(false) {} DownloadUrlParameters::~DownloadUrlParameters() = default; diff --git a/chromium/components/download/public/common/download_url_parameters.h b/chromium/components/download/public/common/download_url_parameters.h index f276eddce7a..ecbc0aff525 100644 --- a/chromium/components/download/public/common/download_url_parameters.h +++ b/chromium/components/download/public/common/download_url_parameters.h @@ -257,6 +257,11 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { require_safety_checks_ = require_safety_checks; } + // Sets whether to ignore content length mismatch errors. + void set_ignore_content_length_mismatch(bool ignore_content_length_mismatch) { + ignore_content_length_mismatch_ = ignore_content_length_mismatch; + } + const OnStartedCallback& callback() const { return callback_; } bool content_initiated() const { return content_initiated_; } const std::string& last_modified() const { return last_modified_; } @@ -310,6 +315,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { bool is_transient() const { return transient_; } std::string guid() const { return guid_; } bool require_safety_checks() const { return require_safety_checks_; } + bool ignore_content_length_mismatch() const { + return ignore_content_length_mismatch_; + } // STATE CHANGING: All save_info_ sub-objects will be in an indeterminate // state following this call. @@ -357,6 +365,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { DownloadSource download_source_; UploadProgressCallback upload_callback_; bool require_safety_checks_; + bool ignore_content_length_mismatch_; DISALLOW_COPY_AND_ASSIGN(DownloadUrlParameters); }; diff --git a/chromium/components/download/public/common/download_utils.h b/chromium/components/download/public/common/download_utils.h index 9e609fee9f1..69f4824e5f7 100644 --- a/chromium/components/download/public/common/download_utils.h +++ b/chromium/components/download/public/common/download_utils.h @@ -39,8 +39,9 @@ using URLSecurityPolicy = // |cert_status| is ignored if error_code is not net::ERR_ABORTED. COMPONENTS_DOWNLOAD_EXPORT DownloadInterruptReason HandleRequestCompletionStatus(net::Error error_code, - bool has_strong_validators, + bool ignore_content_length_mismatch, net::CertStatus cert_status, + bool is_partial_request, DownloadInterruptReason abort_reason); // Parse the HTTP server response code. 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 aaa886466d5..4feb5060ceb 100644 --- a/chromium/components/download/public/common/in_progress_download_manager.h +++ b/chromium/components/download/public/common/in_progress_download_manager.h @@ -14,12 +14,14 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "build/build_config.h" #include "components/download/public/common/download_export.h" #include "components/download/public/common/download_file_factory.h" #include "components/download/public/common/download_item_impl_delegate.h" #include "components/download/public/common/download_utils.h" #include "components/download/public/common/simple_download_manager.h" #include "components/download/public/common/url_download_handler.h" +#include "mojo/public/cpp/system/data_pipe.h" #include "url/gurl.h" namespace net { @@ -116,8 +118,9 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager const GURL& tab_url, const GURL& tab_referrer_url, std::vector<GURL> url_chain, - scoped_refptr<network::ResourceResponse> response, net::CertStatus cert_status, + scoped_refptr<network::ResourceResponse> response_head, + mojo::ScopedDataPipeConsumerHandle response_body, network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, scoped_refptr<DownloadURLLoaderFactoryGetter> url_loader_factory_getter); @@ -148,6 +151,7 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager download_start_observer_ = observer; } +#if defined(OS_ANDROID) // Callback to generate an intermediate file path from the given target file // path; using IntermediatePathCallback = @@ -157,6 +161,11 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager intermediate_path_cb_ = intermediate_path_cb; } + void set_default_download_dir(base::FilePath default_download_dir) { + default_download_dir_ = default_download_dir; + } +#endif + // Called to get all in-progress DownloadItemImpl. // TODO(qinmin): remove this method once InProgressDownloadManager owns // all in-progress downloads. @@ -258,9 +267,14 @@ 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. +#if defined(OS_ANDROID) + // Callback to generate the intermediate file path. IntermediatePathCallback intermediate_path_cb_; + // Default download directory. + base::FilePath default_download_dir_; +#endif + // 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_; @@ -285,7 +299,7 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager // Connector to the service manager. service_manager::Connector* connector_; - base::WeakPtrFactory<InProgressDownloadManager> weak_factory_; + base::WeakPtrFactory<InProgressDownloadManager> weak_factory_{this}; 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 b30b1672c35..b0a7d25a3aa 100644 --- a/chromium/components/download/public/common/mock_download_file.h +++ b/chromium/components/download/public/common/mock_download_file.h @@ -17,6 +17,7 @@ #include "build/build_config.h" #include "components/download/public/common/download_file.h" #include "components/download/public/common/input_stream.h" +#include "services/service_manager/public/cpp/connector.h" #include "testing/gmock/include/gmock/gmock.h" namespace download { @@ -47,11 +48,12 @@ class MockDownloadFile : public DownloadFile { MOCK_METHOD2(RenameAndUniquify, void(const base::FilePath& full_path, const RenameCompletionCallback& callback)); - MOCK_METHOD5(RenameAndAnnotate, + MOCK_METHOD6(RenameAndAnnotate, void(const base::FilePath& full_path, const std::string& client_guid, const GURL& source_url, const GURL& referrer_url, + std::unique_ptr<service_manager::Connector> connector, const RenameCompletionCallback& callback)); MOCK_METHOD0(Detach, void()); MOCK_METHOD0(Cancel, void()); @@ -68,11 +70,12 @@ class MockDownloadFile : public DownloadFile { MOCK_METHOD0(Pause, void()); MOCK_METHOD0(Resume, void()); #if defined(OS_ANDROID) - MOCK_METHOD5(CreateIntermediateUriForPublish, + MOCK_METHOD6(RenameToIntermediateUri, void(const GURL& original_url, const GURL& referrer_url, const base::FilePath& file_name, const std::string& mime_type, + const base::FilePath& current_path, const RenameCompletionCallback& callback)); MOCK_METHOD1(PublishDownload, void(const RenameCompletionCallback& callback)); MOCK_METHOD0(GetDisplayName, base::FilePath()); diff --git a/chromium/components/download/public/common/simple_download_manager.h b/chromium/components/download/public/common/simple_download_manager.h index 8a3bd82d5a4..271b38ec9f6 100644 --- a/chromium/components/download/public/common/simple_download_manager.h +++ b/chromium/components/download/public/common/simple_download_manager.h @@ -49,13 +49,25 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManager { 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. + // Add all initialized download items to |downloads|, no matter the type or + // state, without clearing |downloads| first. If active downloads are not + // initialized, this call will not return them. Caller should call + // GetUninitializedActiveDownloadsIfAny() below to retrieve uninitialized + // active downloads. virtual void GetAllDownloads(DownloadVector* downloads) = 0; + // Gets all the active downloads that are initialized yet. + virtual void GetUninitializedActiveDownloadsIfAny(DownloadVector* downloads) { + } + // Get the download item for |guid|. virtual DownloadItem* GetDownloadByGuid(const std::string& guid) = 0; + // Checks whether downloaded files still exist. Updates state of downloads + // that refer to removed files. The check runs in the background and may + // finish asynchronously after this method returns. + virtual void CheckForHistoryFilesRemoval() {} + protected: // Called when the manager is initailized. void OnInitialized(); 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 c610486ed2a..a69e556e449 100644 --- a/chromium/components/download/public/common/simple_download_manager_coordinator.h +++ b/chromium/components/download/public/common/simple_download_manager_coordinator.h @@ -75,6 +75,11 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManagerCoordinator bool has_all_history_downloads() const { return has_all_history_downloads_; } + // Checks whether downloaded files still exist. Updates state of downloads + // that refer to removed files. The check runs in the background and may + // finish asynchronously after this method returns. + void CheckForExternallyRemovedDownloads(); + private: // SimpleDownloadManager::Observer implementation. void OnDownloadsInitialized() override; @@ -102,7 +107,7 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManagerCoordinator // Observers that want to be notified of changes to the set of downloads. base::ObserverList<Observer>::Unchecked observers_; - base::WeakPtrFactory<SimpleDownloadManagerCoordinator> weak_factory_; + base::WeakPtrFactory<SimpleDownloadManagerCoordinator> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(SimpleDownloadManagerCoordinator); }; |