diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-01-23 17:21:03 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-01-23 16:25:15 +0000 |
commit | c551f43206405019121bd2b2c93714319a0a3300 (patch) | |
tree | 1f48c30631c421fd4bbb3c36da20183c8a2ed7d7 /chromium/components/download | |
parent | 7961cea6d1041e3e454dae6a1da660b453efd238 (diff) | |
download | qtwebengine-chromium-c551f43206405019121bd2b2c93714319a0a3300.tar.gz |
BASELINE: Update Chromium to 79.0.3945.139
Change-Id: I336b7182fab9bca80b709682489c07db112eaca5
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/download')
73 files changed, 805 insertions, 603 deletions
diff --git a/chromium/components/download/content/internal/download_driver_impl.cc b/chromium/components/download/content/internal/download_driver_impl.cc index 6b81a071d13..6547ee07a57 100644 --- a/chromium/components/download/content/internal/download_driver_impl.cc +++ b/chromium/components/download/content/internal/download_driver_impl.cc @@ -183,7 +183,8 @@ void DownloadDriverImpl::Start( download_url_params->set_download_source( download::DownloadSource::INTERNAL_API); download_url_params->set_post_body(post_body); - download_url_params->set_follow_cross_origin_redirects(true); + download_url_params->set_cross_origin_redirects( + network::mojom::RedirectMode::kFollow); download_url_params->set_upload_progress_callback( base::BindRepeating(&DownloadDriverImpl::OnUploadProgress, weak_ptr_factory_.GetWeakPtr(), guid)); diff --git a/chromium/components/download/content/internal/download_driver_impl_unittest.cc b/chromium/components/download/content/internal/download_driver_impl_unittest.cc index a4bdcca950f..61f933116ce 100644 --- a/chromium/components/download/content/internal/download_driver_impl_unittest.cc +++ b/chromium/components/download/content/internal/download_driver_impl_unittest.cc @@ -53,7 +53,7 @@ MATCHER_P(DriverEntryEqual, entry, "") { class DownloadDriverImplTest : public testing::Test { public: DownloadDriverImplTest() - : coordinator_(base::NullCallback()), + : coordinator_(base::NullCallback(), false), task_runner_(new base::TestSimpleTaskRunner), handle_(task_runner_) {} diff --git a/chromium/components/download/database/download_db_impl.cc b/chromium/components/download/database/download_db_impl.cc index 2e728e8fe1c..6ae623f4f21 100644 --- a/chromium/components/download/database/download_db_impl.cc +++ b/chromium/components/download/database/download_db_impl.cc @@ -53,7 +53,7 @@ DownloadDBImpl::DownloadDBImpl( DCHECK(!database_dir.empty()); db_ = db_provider->GetDB<download_pb::DownloadDBEntry>( leveldb_proto::ProtoDbType::DOWNLOAD_DB, database_dir, - base::CreateSequencedTaskRunnerWithTraits( + base::CreateSequencedTaskRunner( {base::ThreadPool(), base::MayBlock(), // USER_VISIBLE because it is required to display chrome://downloads. // https://crbug.com/976223 diff --git a/chromium/components/download/internal/background_service/controller_impl.cc b/chromium/components/download/internal/background_service/controller_impl.cc index 3c02debb23e..d8106125942 100644 --- a/chromium/components/download/internal/background_service/controller_impl.cc +++ b/chromium/components/download/internal/background_service/controller_impl.cc @@ -1153,7 +1153,6 @@ void ControllerImpl::HandleCompleteDownload(CompletionType type, DCHECK(driver_entry.has_value()); stats::LogFilePathRenamed(driver_entry->current_file_path != entry->target_file_path); - stats::LogHashPresence(!driver_entry->hash256.empty()); entry->target_file_path = driver_entry->current_file_path; entry->completion_time = driver_entry->completion_time; entry->bytes_downloaded = driver_entry->bytes_downloaded; 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 c9926226bc4..f5e369ff666 100644 --- a/chromium/components/download/internal/background_service/in_memory_download.cc +++ b/chromium/components/download/internal/background_service/in_memory_download.cc @@ -11,6 +11,7 @@ #include "components/download/internal/background_service/blob_task_proxy.h" #include "net/base/load_flags.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/mojom/url_response_head.mojom.h" #include "storage/browser/blob/blob_data_handle.h" #include "storage/browser/blob/blob_storage_context.h" @@ -140,7 +141,7 @@ void InMemoryDownloadImpl::OnComplete(bool success) { // OnComplete() called without OnResponseStarted(). This will happen when the // request was aborted. if (!started_) - OnResponseStarted(GURL(), network::ResourceResponseHead()); + OnResponseStarted(GURL(), network::mojom::URLResponseHead()); NotifyDelegateDownloadComplete(); } @@ -223,14 +224,14 @@ void InMemoryDownloadImpl::SendRequest() { void InMemoryDownloadImpl::OnRedirect( const net::RedirectInfo& redirect_info, - const network::ResourceResponseHead& response_head, + const network::mojom::URLResponseHead& response_head, std::vector<std::string>* to_be_removed_headers) { url_chain_.push_back(redirect_info.new_url); } void InMemoryDownloadImpl::OnResponseStarted( const GURL& final_url, - const network::ResourceResponseHead& response_head) { + const network::mojom::URLResponseHead& response_head) { started_ = true; response_headers_ = response_head.headers; 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 ec7ea9d356f..cd1a9a37323 100644 --- a/chromium/components/download/internal/background_service/in_memory_download.h +++ b/chromium/components/download/internal/background_service/in_memory_download.h @@ -20,6 +20,7 @@ #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/cpp/simple_url_loader_stream_consumer.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" +#include "services/network/public/mojom/url_response_head.mojom-forward.h" class GURL; @@ -207,12 +208,12 @@ class InMemoryDownloadImpl : public network::SimpleURLLoaderStreamConsumer, // Called when the server redirects to another URL. void OnRedirect(const net::RedirectInfo& redirect_info, - const network::ResourceResponseHead& response_head, + const network::mojom::URLResponseHead& response_head, std::vector<std::string>* to_be_removed_headers); // Called when the response of the final URL is received. void OnResponseStarted(const GURL& final_url, - const network::ResourceResponseHead& response_head); + const network::mojom::URLResponseHead& response_head); void OnUploadProgress(uint64_t position, uint64_t total); diff --git a/chromium/components/download/internal/background_service/in_memory_download_unittest.cc b/chromium/components/download/internal/background_service/in_memory_download_unittest.cc index 5c4b9dfffc7..daeba85c5d3 100644 --- a/chromium/components/download/internal/background_service/in_memory_download_unittest.cc +++ b/chromium/components/download/internal/background_service/in_memory_download_unittest.cc @@ -210,27 +210,28 @@ TEST_F(InMemoryDownloadTest, RedirectResponseHeaders) { // Add a redirect. net::RedirectInfo redirect_info; redirect_info.new_url = GURL("https://example.com/redirect12345"); - network::TestURLLoaderFactory::Redirects redirects = { - {redirect_info, network::ResourceResponseHead()}}; + network::TestURLLoaderFactory::Redirects redirects; + redirects.push_back({redirect_info, network::mojom::URLResponseHead::New()}); // Add some random header. - network::ResourceResponseHead response_head; - response_head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); - response_head.headers->AddHeader("X-Random-Test-Header: 123"); + auto response_head = network::mojom::URLResponseHead::New(); + response_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(""); + response_head->headers->AddHeader("X-Random-Test-Header: 123"); // The size must match for download as stream from SimpleUrlLoader. network::URLLoaderCompletionStatus status; status.decoded_body_length = base::size(kTestDownloadData) - 1; - url_loader_factory()->AddResponse(request_params.url, response_head, - kTestDownloadData, status, redirects); + url_loader_factory()->AddResponse(request_params.url, response_head.Clone(), + kTestDownloadData, status, + std::move(redirects)); std::vector<GURL> expected_url_chain = {request_params.url, redirect_info.new_url}; EXPECT_CALL(*delegate(), OnDownloadStarted(InMemoryDownloadMatcher( - response_head.headers->raw_headers(), expected_url_chain))); + response_head->headers->raw_headers(), expected_url_chain))); download()->Start(); delegate()->WaitForCompletion(); @@ -240,7 +241,7 @@ TEST_F(InMemoryDownloadTest, RedirectResponseHeaders) { // the original URL and redirect URL, and should not contain the final URL. EXPECT_EQ(download()->url_chain(), expected_url_chain); EXPECT_EQ(download()->response_headers()->raw_headers(), - response_head.headers->raw_headers()); + response_head->headers->raw_headers()); // Verfiy the data persisted to disk after redirect chain. auto blob = download()->ResultAsBlob(); 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 d6ad0b4b9a7..f814936cdef 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 @@ -146,7 +146,7 @@ class DeviceStatusListenerTest : public testing::Test { MockObserver mock_observer_; // Needed for network change notifier and power monitor. - base::test::TaskEnvironment task_environment_; + base::test::SingleThreadTaskEnvironment task_environment_; 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 ac937aba898..3fd3716b254 100644 --- a/chromium/components/download/internal/background_service/stats.cc +++ b/chromium/components/download/internal/background_service/stats.cc @@ -330,10 +330,6 @@ void LogHasUploadData(DownloadClient client, bool has_upload_data) { base::UmaHistogramBoolean(name, has_upload_data); } -void LogHashPresence(bool hash_exists) { - UMA_HISTOGRAM_BOOLEAN("Download.Service.Finish.ReportedHash", hash_exists); -} - void LogDownloadClientInflatedFullBrowser(DownloadClient client) { std::string client_name(ClientToHistogramSuffix(client)); base::UmaHistogramBoolean( diff --git a/chromium/components/download/internal/background_service/stats.h b/chromium/components/download/internal/background_service/stats.h index 4c4353775a7..07cc041d74c 100644 --- a/chromium/components/download/internal/background_service/stats.h +++ b/chromium/components/download/internal/background_service/stats.h @@ -220,9 +220,6 @@ void LogEntryRetryCount(uint32_t retry_count); // Records whether the entry was an upload. void LogHasUploadData(DownloadClient client, bool has_upload_data); -// Records whether or not a completed entry has a hash value. -void LogHashPresence(bool hash_exists); - // Records count of reduced mode to full browser transitions requested by each // client. void LogDownloadClientInflatedFullBrowser(DownloadClient client); diff --git a/chromium/components/download/internal/common/BUILD.gn b/chromium/components/download/internal/common/BUILD.gn index 4959f0a026c..4c31aa2fc3c 100644 --- a/chromium/components/download/internal/common/BUILD.gn +++ b/chromium/components/download/internal/common/BUILD.gn @@ -105,7 +105,9 @@ if (is_android) { deps = [ "//base:base_java", + "//base:jni_java", ] + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] } generate_jni("jni_headers") { diff --git a/chromium/components/download/internal/common/all_download_event_notifier.cc b/chromium/components/download/internal/common/all_download_event_notifier.cc index e28d8b0d1f1..e4bed564d24 100644 --- a/chromium/components/download/internal/common/all_download_event_notifier.cc +++ b/chromium/components/download/internal/common/all_download_event_notifier.cc @@ -49,7 +49,9 @@ void AllDownloadEventNotifier::OnDownloadsInitialized( active_downloads_only); } -void AllDownloadEventNotifier::OnManagerGoingDown() { +void AllDownloadEventNotifier::OnManagerGoingDown( + SimpleDownloadManagerCoordinator* manager) { + DCHECK_EQ(manager, simple_download_manager_coordinator_); for (auto& observer : observers_) observer.OnManagerGoingDown(simple_download_manager_coordinator_); simple_download_manager_coordinator_->RemoveObserver(this); diff --git a/chromium/components/download/internal/common/all_download_event_notifier_unittest.cc b/chromium/components/download/internal/common/all_download_event_notifier_unittest.cc index 5d63d4da46b..b84fe2ad3b8 100644 --- a/chromium/components/download/internal/common/all_download_event_notifier_unittest.cc +++ b/chromium/components/download/internal/common/all_download_event_notifier_unittest.cc @@ -45,7 +45,7 @@ class MockNotifierObserver : public AllDownloadEventNotifier::Observer { class AllDownloadEventNotifierTest : public testing::Test { public: - AllDownloadEventNotifierTest() : coordinator_(base::NullCallback()) {} + AllDownloadEventNotifierTest() : coordinator_(base::NullCallback(), false) {} ~AllDownloadEventNotifierTest() override = default; 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 e710401f2f1..11bfaeb485e 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 @@ -12,6 +12,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; /** * Helper class for publishing download files to the public download collection. @@ -296,7 +297,7 @@ public class DownloadCollectionBridge { * @return number of days for an intermediate download to expire. */ public static int getExpirationDurationInDays() { - return nativeGetExpirationDurationInDays(); + return DownloadCollectionBridgeJni.get().getExpirationDurationInDays(); } /** @@ -309,5 +310,8 @@ public class DownloadCollectionBridge { return getDownloadCollectionBridge().getDisplayNameForUri(downloadUri); } - private static native int nativeGetExpirationDurationInDays(); + @NativeMethods + interface Natives { + int getExpirationDurationInDays(); + } } diff --git a/chromium/components/download/internal/common/base_file.cc b/chromium/components/download/internal/common/base_file.cc index 5f955ab6340..d5281d7f4d1 100644 --- a/chromium/components/download/internal/common/base_file.cc +++ b/chromium/components/download/internal/common/base_file.cc @@ -80,9 +80,19 @@ void InitializeFile(base::File* file, const base::FilePath& file_path) { return; } #endif // defined(OS_ANDROID) - file->Initialize(file_path, base::File::FLAG_OPEN_ALWAYS | - base::File::FLAG_WRITE | - base::File::FLAG_READ); + + // Use exclusive write to prevent another process from writing the file. + file->Initialize( + file_path, + base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE | + base::File::FLAG_READ +#if defined(OS_WIN) + // Don't allow other process to write to the file while Chrome is + // writing to it. On posix systems, use FLAG_EXCLUSIVE_WRITE will + // cause file creation to fail if the file already exists. + | base::File::FLAG_EXCLUSIVE_WRITE +#endif // defined(OS_WIN) + ); } void DeleteFile(const base::FilePath& file_path) { diff --git a/chromium/components/download/internal/common/base_file_unittest.cc b/chromium/components/download/internal/common/base_file_unittest.cc index 921ad87a2fe..0b32a96ac5d 100644 --- a/chromium/components/download/internal/common/base_file_unittest.cc +++ b/chromium/components/download/internal/common/base_file_unittest.cc @@ -140,13 +140,17 @@ class BaseFileTest : public testing::Test { void CreateFileWithName(const base::FilePath& file_name) { EXPECT_NE(base::FilePath::StringType(), file_name.value()); BaseFile duplicate_file(download::DownloadItem::kInvalidId); - EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, - duplicate_file.Initialize(file_name, temp_dir_.GetPath(), - base::File(), 0, std::string(), - std::unique_ptr<crypto::SecureHash>(), - false, &kTestDataBytesWasted)); + DownloadInterruptReason reason = duplicate_file.Initialize( + file_name, temp_dir_.GetPath(), base::File(), 0, std::string(), + std::unique_ptr<crypto::SecureHash>(), false, &kTestDataBytesWasted); +#if defined(OS_WIN) + EXPECT_EQ(reason, DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); +#else + EXPECT_EQ(reason, DOWNLOAD_INTERRUPT_REASON_NONE); // Write something into it. duplicate_file.AppendDataToFile(kTestData4, kTestDataLength4); +#endif // defined(OS_WIN) + // Detach the file so it isn't deleted on destruction of |duplicate_file|. duplicate_file.Detach(); } diff --git a/chromium/components/download/internal/common/base_file_win.cc b/chromium/components/download/internal/common/base_file_win.cc index 322636626a5..ac50ce55cee 100644 --- a/chromium/components/download/internal/common/base_file_win.cc +++ b/chromium/components/download/internal/common/base_file_win.cc @@ -10,10 +10,10 @@ #include <shellapi.h> #include <shobjidl.h> #include <wrl/client.h> +#include <wrl/implements.h> #include "base/threading/scoped_blocking_call.h" #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" @@ -143,29 +143,17 @@ DownloadInterruptReason HRESULTToDownloadInterruptReason(HRESULT hr) { return DOWNLOAD_INTERRUPT_REASON_FILE_FAILED; } -class FileOperationProgressSink : public base::win::IUnknownImpl, - public IFileOperationProgressSink { +class FileOperationProgressSink + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, + IFileOperationProgressSink> { public: FileOperationProgressSink() = default; HRESULT GetOperationResult() { return result_; } - // base::win::IUnknownImpl: - STDMETHODIMP QueryInterface(REFIID riid, PVOID* ppv) override { - if (riid == IID_IFileOperationProgressSink) { - *ppv = static_cast<IFileOperationProgressSink*>(this); - IUnknownImpl::AddRef(); - return S_OK; - } - - return IUnknownImpl::QueryInterface(riid, ppv); - } - - ULONG STDMETHODCALLTYPE AddRef() override { return IUnknownImpl::AddRef(); } - ULONG STDMETHODCALLTYPE Release() override { return IUnknownImpl::Release(); } - // IFileOperationProgressSink: - HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT hr) override { + IFACEMETHODIMP FinishOperations(HRESULT hr) override { // If a failure has already been captured, don't bother overriding it. That // way, the original failure can be propagated; in the event that the new // HRESULT is also a success, overwriting will not harm anything and @@ -175,27 +163,27 @@ class FileOperationProgressSink : public base::win::IUnknownImpl, return S_OK; } - HRESULT STDMETHODCALLTYPE PauseTimer() override { return S_OK; } - HRESULT STDMETHODCALLTYPE PostCopyItem(DWORD, - IShellItem*, - IShellItem*, - PCWSTR, - HRESULT, - IShellItem*) override { + IFACEMETHODIMP PauseTimer() override { return S_OK; } + IFACEMETHODIMP PostCopyItem(DWORD, + IShellItem*, + IShellItem*, + PCWSTR, + HRESULT, + IShellItem*) override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE PostDeleteItem(DWORD, - IShellItem*, - HRESULT, - IShellItem*) override { + IFACEMETHODIMP PostDeleteItem(DWORD, + IShellItem*, + HRESULT, + IShellItem*) override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE PostMoveItem(DWORD, - IShellItem*, - IShellItem*, - PCWSTR, - HRESULT hr, - IShellItem*) override { + IFACEMETHODIMP PostMoveItem(DWORD, + IShellItem*, + IShellItem*, + PCWSTR, + HRESULT hr, + IShellItem*) override { // Like in FinishOperations, overwriting with a different success value // does not have a negative impact, but replacing an existing failure will // cause issues. @@ -203,44 +191,38 @@ class FileOperationProgressSink : public base::win::IUnknownImpl, result_ = hr; return S_OK; } - HRESULT STDMETHODCALLTYPE PostNewItem(DWORD, - IShellItem*, - PCWSTR, - PCWSTR, - DWORD, - HRESULT, - IShellItem*) override { + IFACEMETHODIMP PostNewItem(DWORD, + IShellItem*, + PCWSTR, + PCWSTR, + DWORD, + HRESULT, + IShellItem*) override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE + IFACEMETHODIMP PostRenameItem(DWORD, IShellItem*, PCWSTR, HRESULT, IShellItem*) override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE PreCopyItem(DWORD, - IShellItem*, - IShellItem*, - PCWSTR) override { + IFACEMETHODIMP PreCopyItem(DWORD, IShellItem*, IShellItem*, PCWSTR) override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE PreDeleteItem(DWORD, IShellItem*) override { + IFACEMETHODIMP PreDeleteItem(DWORD, IShellItem*) override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE PreMoveItem(DWORD, - IShellItem*, - IShellItem*, - PCWSTR) override { + IFACEMETHODIMP PreMoveItem(DWORD, IShellItem*, IShellItem*, PCWSTR) override { return S_OK; } - HRESULT STDMETHODCALLTYPE PreNewItem(DWORD, IShellItem*, PCWSTR) override { + IFACEMETHODIMP PreNewItem(DWORD, IShellItem*, PCWSTR) override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE PreRenameItem(DWORD, IShellItem*, PCWSTR) override { + IFACEMETHODIMP PreRenameItem(DWORD, IShellItem*, PCWSTR) override { return E_NOTIMPL; } - HRESULT STDMETHODCALLTYPE ResetTimer() override { return S_OK; } - HRESULT STDMETHODCALLTYPE ResumeTimer() override { return S_OK; } - HRESULT STDMETHODCALLTYPE StartOperations() override { return S_OK; } - HRESULT STDMETHODCALLTYPE UpdateProgress(UINT, UINT) override { return S_OK; } + IFACEMETHODIMP ResetTimer() override { return S_OK; } + IFACEMETHODIMP ResumeTimer() override { return S_OK; } + IFACEMETHODIMP StartOperations() override { return S_OK; } + IFACEMETHODIMP UpdateProgress(UINT, UINT) override { return S_OK; } protected: ~FileOperationProgressSink() override = default; @@ -290,11 +272,12 @@ DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions( FOF_NO_UI | FOF_NOCOPYSECURITYATTRIBS | FOFX_EARLYFAILURE); } - scoped_refptr<FileOperationProgressSink> sink(new FileOperationProgressSink); + Microsoft::WRL::ComPtr<FileOperationProgressSink> sink = + Microsoft::WRL::Make<FileOperationProgressSink>(); if (SUCCEEDED(hr)) { hr = file_operation->MoveItem(original_path.Get(), destination_folder.Get(), new_path.BaseName().value().c_str(), - sink.get()); + sink.Get()); } if (SUCCEEDED(hr)) diff --git a/chromium/components/download/internal/common/download_create_info.cc b/chromium/components/download/internal/common/download_create_info.cc index 20881b0be7b..7d45b1819b4 100644 --- a/chromium/components/download/internal/common/download_create_info.cc +++ b/chromium/components/download/internal/common/download_create_info.cc @@ -4,10 +4,10 @@ #include "components/download/public/common/download_create_info.h" +#include <memory> #include <string> #include "base/format_macros.h" -#include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" #include "net/http/http_response_headers.h" @@ -35,8 +35,7 @@ DownloadCreateInfo::DownloadCreateInfo( is_content_initiated(false) {} DownloadCreateInfo::DownloadCreateInfo() - : DownloadCreateInfo(base::Time(), base::WrapUnique(new DownloadSaveInfo)) { -} + : DownloadCreateInfo(base::Time(), std::make_unique<DownloadSaveInfo>()) {} DownloadCreateInfo::~DownloadCreateInfo() {} diff --git a/chromium/components/download/internal/common/download_db_cache.cc b/chromium/components/download/internal/common/download_db_cache.cc index fc6c029813d..9ff1755ad45 100644 --- a/chromium/components/download/internal/common/download_db_cache.cc +++ b/chromium/components/download/internal/common/download_db_cache.cc @@ -43,10 +43,19 @@ ShouldUpdateDownloadDBResult ShouldUpdateDownloadDB( if (current.download_info) current_info = current.download_info->in_progress_info; - base::FilePath current_path = - current_info ? current_info->current_path : base::FilePath(); - - bool paused = current_info ? current_info->paused : false; + base::FilePath current_path; + bool paused = false; + GURL url; + DownloadItem::DownloadState state = DownloadItem::DownloadState::IN_PROGRESS; + DownloadInterruptReason interrupt_reason = DOWNLOAD_INTERRUPT_REASON_NONE; + if (current_info) { + base::FilePath current_path = current_info->current_path; + paused = current_info->paused; + if (!current_info->url_chain.empty()) + url = current_info->url_chain.back(); + state = current_info->state; + interrupt_reason = current_info->interrupt_reason; + } // When download path is determined, Chrome should commit the history // immediately. Otherwise the file will be left permanently on the external @@ -57,6 +66,9 @@ ShouldUpdateDownloadDBResult ShouldUpdateDownloadDB( if (previous.value() == current) return ShouldUpdateDownloadDBResult::NO_UPDATE; + if (IsDownloadDone(url, state, interrupt_reason)) + return ShouldUpdateDownloadDBResult::UPDATE_IMMEDIATELY; + return ShouldUpdateDownloadDBResult::UPDATE; } @@ -171,18 +183,6 @@ void DownloadDBCache::UpdateDownloadDB() { } void DownloadDBCache::OnDownloadUpdated(DownloadItem* download) { - // TODO(crbug.com/778425): Properly handle fail/resume/retry for downloads - // that are in the INTERRUPTED state for a long time. - if (!base::FeatureList::IsEnabled(features::kDownloadDBForNewDownloads)) { - // If history service is still managing in-progress download, we can safely - // remove a download from the in-progress DB whenever it is in the terminal - // state. Otherwise, we need to propagate the completed download to - // history service before we can remove it. - if (download->IsDone()) { - OnDownloadRemoved(download); - return; - } - } DownloadDBEntry entry = CreateDownloadDBEntryFromItem( *(static_cast<DownloadItemImpl*>(download))); AddOrReplaceEntry(entry); diff --git a/chromium/components/download/internal/common/download_file_impl.cc b/chromium/components/download/internal/common/download_file_impl.cc index ce58672bd20..d531a8e9c8d 100644 --- a/chromium/components/download/internal/common/download_file_impl.cc +++ b/chromium/components/download/internal/common/download_file_impl.cc @@ -59,11 +59,10 @@ const int kUnknownContentLength = -1; DownloadFileImpl::SourceStream::SourceStream( int64_t offset, - int64_t length, int64_t starting_file_write_offset, std::unique_ptr<InputStream> stream) : offset_(offset), - length_(length), + length_(DownloadSaveInfo::kLengthFullContent), starting_file_write_offset_(starting_file_write_offset), bytes_read_(0), bytes_written_(0), @@ -72,11 +71,6 @@ DownloadFileImpl::SourceStream::SourceStream( input_stream_(std::move(stream)) { CHECK_LE(offset_, starting_file_write_offset_); CHECK_GE(offset_, 0); - DCHECK(length <= 0 || length >= starting_file_write_offset - offset) - << "Not enough for content validation. offset = " << offset - << ", length = " << length - << " , starting_file_write_offset = " << starting_file_write_offset - << "."; } DownloadFileImpl::SourceStream::~SourceStream() = default; @@ -126,6 +120,7 @@ void DownloadFileImpl::SourceStream::RegisterDataReadyCallback( } void DownloadFileImpl::SourceStream::ClearDataReadyCallback() { + read_stream_callback_.Cancel(); input_stream_->ClearDataReadyCallback(); } @@ -176,8 +171,8 @@ DownloadFileImpl::DownloadFileImpl( download_id); source_streams_[save_info_->offset] = std::make_unique<SourceStream>( - save_info_->offset, save_info_->length, - save_info_->GetStartingFileWriteOffset(), std::move(stream)); + save_info_->offset, save_info_->GetStartingFileWriteOffset(), + std::move(stream)); DETACH_FROM_SEQUENCE(sequence_checker_); } @@ -208,9 +203,10 @@ void DownloadFileImpl::Initialize( } if (IsSparseFile()) { - for (const auto& received_slice : received_slices_) { + for (const auto& received_slice : received_slices_) bytes_so_far += received_slice.received_bytes; - } + slice_to_download_ = FindSlicesToDownload(received_slices_); + } else { bytes_so_far = save_info_->GetStartingFileWriteOffset(); } @@ -243,8 +239,7 @@ void DownloadFileImpl::Initialize( } void DownloadFileImpl::AddInputStream(std::unique_ptr<InputStream> stream, - int64_t offset, - int64_t length) { + int64_t offset) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // UI thread may not be notified about completion and detach download file, @@ -255,7 +250,7 @@ void DownloadFileImpl::AddInputStream(std::unique_ptr<InputStream> stream, } DCHECK(source_streams_.find(offset) == source_streams_.end()); source_streams_[offset] = - std::make_unique<SourceStream>(offset, length, offset, std::move(stream)); + std::make_unique<SourceStream>(offset, offset, std::move(stream)); OnSourceStreamAdded(source_streams_[offset].get()); } @@ -478,19 +473,13 @@ void DownloadFileImpl::RenameWithRetryInternal( // 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->remote_quarantine), - 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); + file_.AnnotateWithSourceInformation( + parameters->client_guid, parameters->source_url, + parameters->referrer_url, std::move(parameters->remote_quarantine), + base::BindOnce(&DownloadFileImpl::OnRenameComplete, + weak_factory_.GetWeakPtr(), new_path, + parameters->completion_callback)); + return; } OnRenameComplete(new_path, parameters->completion_callback, reason); @@ -566,9 +555,8 @@ void DownloadFileImpl::Resume() { for (auto& stream : source_streams_) { SourceStream* source_stream = stream.second.get(); - if (!source_stream->is_finished()) { - ActivateStream(source_stream); - } + if (!source_stream->is_finished()) + StreamActive(source_stream, MOJO_RESULT_OK); } } @@ -591,7 +579,6 @@ void DownloadFileImpl::StreamActive(SourceStream* source_stream, DownloadInterruptReason reason = DOWNLOAD_INTERRUPT_REASON_NONE; base::TimeDelta delta( base::TimeDelta::FromMilliseconds(kMaxTimeBlockingFileThreadMs)); - // Take care of any file local activity required. do { state = source_stream->Read(&incoming_data, &incoming_data_size); @@ -645,10 +632,15 @@ void DownloadFileImpl::StreamActive(SourceStream* source_stream, // If we're stopping to yield the thread, post a task so we come back. if (state == InputStream::HAS_DATA && now - start > delta && !should_terminate) { + source_stream->read_stream_callback()->Reset(base::BindOnce( + &DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(), + source_stream, MOJO_RESULT_OK)); base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&DownloadFileImpl::StreamActive, - weak_factory_.GetWeakPtr(), source_stream, - MOJO_RESULT_OK)); + FROM_HERE, source_stream->read_stream_callback()->callback()); + } else if (state == InputStream::EMPTY && !should_terminate) { + source_stream->RegisterDataReadyCallback( + base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(), + source_stream)); } if (state == InputStream::COMPLETE) @@ -688,9 +680,10 @@ void DownloadFileImpl::NotifyObserver(SourceStream* source_stream, << "Received slice index out of bound!"; received_slices_[source_stream->index()].finished = true; } - - SetPotentialFileLength(source_stream->offset() + - source_stream->bytes_read()); + if (!should_terminate) { + SetPotentialFileLength(source_stream->offset() + + source_stream->bytes_read()); + } } num_active_streams_--; @@ -716,6 +709,11 @@ void DownloadFileImpl::NotifyObserver(SourceStream* source_stream, base::BindOnce(&DownloadDestinationObserver::DestinationCompleted, observer_, TotalBytesReceived(), std::move(hash_state))); + } else { + // If all the stream completes and we still not able to complete, trigger + // a content length mismatch error so auto resumption will be performed. + SendErrorUpdateIfFinished( + DOWNLOAD_INTERRUPT_REASON_SERVER_CONTENT_LENGTH_MISMATCH); } } } @@ -730,13 +728,6 @@ void DownloadFileImpl::RegisterAndActivateStream(SourceStream* source_stream) { received_slice.offset, received_slice.received_bytes); } num_active_streams_++; - ActivateStream(source_stream); -} - -void DownloadFileImpl::ActivateStream(SourceStream* source_stream) { - source_stream->RegisterDataReadyCallback( - base::Bind(&DownloadFileImpl::StreamActive, weak_factory_.GetWeakPtr(), - source_stream)); StreamActive(source_stream, MOJO_RESULT_OK); } @@ -847,18 +838,36 @@ void DownloadFileImpl::HandleStreamError(SourceStream* source_stream, SendUpdate(); // Make info up to date before error. - if (!can_recover_from_error) { - // Error case for both upstream source and file write. - // Shut down processing and signal an error to our observer. - // Our observer will clean us up. - weak_factory_.InvalidateWeakPtrs(); - std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); - main_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&DownloadDestinationObserver::DestinationError, - observer_, reason, TotalBytesReceived(), - std::move(hash_state))); + if (!can_recover_from_error) + SendErrorUpdateIfFinished(reason); +} + +void DownloadFileImpl::SendErrorUpdateIfFinished( + DownloadInterruptReason reason) { + // If there are still active streams, let them finish before + // sending out the error to the observer. + if (num_active_streams_ > 0) + return; + + if (IsSparseFile()) { + for (const auto& slice : slice_to_download_) { + // Ignore last slice beyond file length. + if (slice.offset > 0 && slice.offset == potential_file_length_) + continue; + if (source_streams_.find(slice.offset) == source_streams_.end()) + return; + } } + + // Error case for both upstream source and file write. + // Shut down processing and signal an error to our observer. + // Our observer will clean us up. + weak_factory_.InvalidateWeakPtrs(); + std::unique_ptr<crypto::SecureHash> hash_state = file_.Finish(); + main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&DownloadDestinationObserver::DestinationError, observer_, + reason, TotalBytesReceived(), std::move(hash_state))); } bool DownloadFileImpl::IsSparseFile() const { diff --git a/chromium/components/download/internal/common/download_file_unittest.cc b/chromium/components/download/internal/common/download_file_unittest.cc index e36751b69f4..0dac1e18b29 100644 --- a/chromium/components/download/internal/common/download_file_unittest.cc +++ b/chromium/components/download/internal/common/download_file_unittest.cc @@ -184,6 +184,15 @@ class DownloadFileTest : public testing::Test { void ClearCallback() { sink_callback_.Reset(); } + void OnStreamActive(int64_t offset) { + DCHECK(download_file_->source_streams_.find(offset) != + download_file_->source_streams_.end()) + << "Can't find stream at offset : " << offset; + DownloadFileImpl::SourceStream* stream = + download_file_->source_streams_[offset].get(); + download_file_->StreamActive(stream, MOJO_RESULT_OK); + } + void SetInterruptReasonCallback(const base::Closure& closure, DownloadInterruptReason* reason_p, DownloadInterruptReason reason, @@ -235,7 +244,6 @@ class DownloadFileTest : public testing::Test { } save_info->offset = 0; - save_info->length = length; save_info->file_offset = file_offset; download_file_.reset(new TestDownloadFileImpl( @@ -430,7 +438,7 @@ class DownloadFileTest : public testing::Test { // 1. RegisterCallback: Must called twice. One to set the callback, the // other to release the stream. // 2. Read: If filled with N buffer, called (N+1) times, where the last Read - // call doesn't read any data but returns STRAM_COMPLETE. + // call doesn't read any data but returns STREAM_COMPLETE. // The stream may terminate in the middle and less Read calls are expected. // 3. GetStatus: Only called if the stream is completed and last Read call // returns STREAM_COMPLETE. @@ -573,6 +581,9 @@ TEST_P(DownloadFileTestWithRename, RenameFileFinal) { EXPECT_FALSE(base::PathExists(initial_path)); EXPECT_TRUE(base::PathExists(path_1)); + EXPECT_CALL(*input_stream_, RegisterDataReadyCallback(_)) + .Times(1) + .RetiresOnSaturation(); // Download the data. const char* chunks1[] = {kTestData1, kTestData2}; AppendDataToFile(chunks1, 2); @@ -588,6 +599,9 @@ TEST_P(DownloadFileTestWithRename, RenameFileFinal) { EXPECT_FALSE(base::PathExists(path_1)); EXPECT_TRUE(base::PathExists(path_2)); + EXPECT_CALL(*input_stream_, RegisterDataReadyCallback(_)) + .Times(1) + .RetiresOnSaturation(); const char* chunks2[] = {kTestData3}; AppendDataToFile(chunks2, 1); @@ -825,6 +839,9 @@ TEST_F(DownloadFileTest, StreamEmptySuccess) { // Test that calling the sink_callback_ on an empty stream shouldn't // do anything. + EXPECT_CALL(*input_stream_, RegisterDataReadyCallback(_)) + .Times(1) + .RetiresOnSaturation(); AppendDataToFile(nullptr, 0); // Finish the download this way and make sure we see it on the observer. @@ -976,14 +993,12 @@ TEST_F(DownloadFileTest, MultipleStreamsWrite) { PrepareStream(&additional_streams_[0], stream_0_length, true, true, kTestData7, 2); - EXPECT_CALL(*additional_streams_[0], RegisterDataReadyCallback(_)) - .RetiresOnSaturation(); EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); // Activate the streams. download_file_->AddInputStream( - std::unique_ptr<MockInputStream>(additional_streams_[0]), stream_0_length, - DownloadSaveInfo::kLengthFullContent); + std::unique_ptr<MockInputStream>(additional_streams_[0]), + stream_0_length); sink_callback_.Run(MOJO_RESULT_OK); base::RunLoop().RunUntilIdle(); @@ -997,7 +1012,7 @@ TEST_F(DownloadFileTest, MultipleStreamsWrite) { } // 3 streams write to one sink, the second stream has a limited length. -TEST_F(DownloadFileTest, MutipleStreamsLimitedLength) { +TEST_F(DownloadFileTest, MultipleStreamsLimitedLength) { int64_t stream_0_length = GetBuffersLength(kTestData6, 2); // The second stream has a limited length and should be partially written @@ -1017,26 +1032,19 @@ TEST_F(DownloadFileTest, MutipleStreamsLimitedLength) { PrepareStream(&additional_streams_[1], stream_0_length + stream_1_length, true, true, kTestData6, 2); - EXPECT_CALL(*additional_streams_[0], RegisterDataReadyCallback(_)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*additional_streams_[0], ClearDataReadyCallback()) .Times(1) .RetiresOnSaturation(); - EXPECT_CALL(*additional_streams_[1], RegisterDataReadyCallback(_)) - .RetiresOnSaturation(); - EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); // Activate all the streams. - download_file_->AddInputStream( - std::unique_ptr<MockInputStream>(additional_streams_[0]), stream_0_length, - stream_1_length); - download_file_->AddInputStream( + download_file_->AddInputStream( std::unique_ptr<MockInputStream>(additional_streams_[1]), - stream_0_length + stream_1_length, DownloadSaveInfo::kLengthFullContent); + stream_0_length + stream_1_length); + download_file_->AddInputStream( + std::unique_ptr<MockInputStream>(additional_streams_[0]), + stream_0_length); sink_callback_.Run(MOJO_RESULT_OK); base::RunLoop().RunUntilIdle(); @@ -1077,7 +1085,7 @@ TEST_F(DownloadFileTest, MultipleStreamsFirstStreamWriteAllData) { additional_streams_[0] = new StrictMock<MockInputStream>(); download_file_->AddInputStream( std::unique_ptr<MockInputStream>(additional_streams_[0]), - stream_0_length - 1, DownloadSaveInfo::kLengthFullContent); + stream_0_length - 1); base::RunLoop().RunUntilIdle(); SourceStreamTestData stream_data_0(0, stream_0_length, true); @@ -1103,13 +1111,13 @@ TEST_F(DownloadFileTest, SecondStreamStartingOffsetAlreadyWritten) { .InSequence(seq) .WillOnce(Return(InputStream::EMPTY)) .RetiresOnSaturation(); + EXPECT_CALL(*input_stream_, RegisterDataReadyCallback(_)) + .Times(1) + .RetiresOnSaturation(); sink_callback_.Run(MOJO_RESULT_OK); base::RunLoop().RunUntilIdle(); additional_streams_[0] = new StrictMock<MockInputStream>(); - EXPECT_CALL(*additional_streams_[0], RegisterDataReadyCallback(_)) - .WillRepeatedly(Invoke(this, &DownloadFileTest::RegisterCallback)) - .RetiresOnSaturation(); EXPECT_CALL(*additional_streams_[0], ClearDataReadyCallback()) .WillRepeatedly(Invoke(this, &DownloadFileTest::ClearCallback)) .RetiresOnSaturation(); @@ -1119,7 +1127,7 @@ TEST_F(DownloadFileTest, SecondStreamStartingOffsetAlreadyWritten) { download_file_->AddInputStream( std::unique_ptr<MockInputStream>(additional_streams_[0]), - strlen(kTestData1), DownloadSaveInfo::kLengthFullContent); + strlen(kTestData1)); // The stream should get terminated and reset the callback. EXPECT_TRUE(sink_callback_.is_null()); @@ -1127,4 +1135,68 @@ TEST_F(DownloadFileTest, SecondStreamStartingOffsetAlreadyWritten) { DestroyDownloadFile(0, false); } +// The second stream successfully reads the data from its offset. However, +// before it is able to write the data, the same block was written by +// the first stream. +TEST_F(DownloadFileTest, SecondStreamReadsOffsetWrittenByFirst) { + int64_t stream_0_length = GetBuffersLength(kTestData8, 4); + + ASSERT_TRUE(CreateDownloadFile(stream_0_length, true, + DownloadItem::ReceivedSlices())); + + // First stream writes the first 2 chunks. + Sequence seq; + SetupDataAppend(kTestData8, 2, input_stream_, seq, 0); + + EXPECT_CALL(*input_stream_, Read(_, _)) + .InSequence(seq) + .WillOnce(Return(InputStream::EMPTY)) + .RetiresOnSaturation(); + EXPECT_CALL(*input_stream_, RegisterDataReadyCallback(_)) + .Times(2) + .RetiresOnSaturation(); + sink_callback_.Run(MOJO_RESULT_OK); + base::RunLoop().RunUntilIdle(); + + // The second stream is created and waiting for data. + additional_streams_[0] = new StrictMock<MockInputStream>(); + EXPECT_CALL(*additional_streams_[0], RegisterDataReadyCallback(_)) + .RetiresOnSaturation(); + EXPECT_CALL(*additional_streams_[0], ClearDataReadyCallback()) + .RetiresOnSaturation(); + EXPECT_CALL(*additional_streams_[0], Read(_, _)) + .WillOnce(Return(InputStream::EMPTY)) + .RetiresOnSaturation(); + int64_t offset = strlen(kTestData1) + strlen(kTestData2); + download_file_->AddInputStream( + std::unique_ptr<MockInputStream>(additional_streams_[0]), offset); + base::RunLoop().RunUntilIdle(); + + // First stream reads the 3rd chunk and writes it to disk. + const char* chunk[] = {kTestData4}; + SetupDataAppend(chunk, 1, input_stream_, seq, offset); + EXPECT_CALL(*input_stream_, Read(_, _)) + .InSequence(seq) + .WillOnce(Return(InputStream::EMPTY)) + .RetiresOnSaturation(); + sink_callback_.Run(MOJO_RESULT_OK); + base::RunLoop().RunUntilIdle(); + + // Second stream also reads the 3rd chunk, but it will be terminated. + SetupDataAppend(chunk, 1, additional_streams_[0], seq, offset); + OnStreamActive(offset); + base::RunLoop().RunUntilIdle(); + + // First stream writes the last chunk, and completes the download. + chunk[0] = kTestData5; + SetupDataAppend(chunk, 1, input_stream_, seq, offset + strlen(kTestData4)); + SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, input_stream_, seq); + EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _)); + sink_callback_.Run(MOJO_RESULT_OK); + base::RunLoop().RunUntilIdle(); + + download_file_->Cancel(); + DestroyDownloadFile(0, false); +} + } // namespace download diff --git a/chromium/components/download/internal/common/download_item_impl.cc b/chromium/components/download/internal/common/download_item_impl.cc index f24ef713bf7..f19cfe9b6b7 100644 --- a/chromium/components/download/internal/common/download_item_impl.cc +++ b/chromium/components/download/internal/common/download_item_impl.cc @@ -41,8 +41,8 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/task_runner_util.h" +#include "base/trace_event/memory_usage_estimator.h" #include "build/build_config.h" -#include "components/download/database/in_progress/download_entry.h" #include "components/download/internal/common/download_job_impl.h" #include "components/download/internal/common/parallel_download_utils.h" #include "components/download/public/common/download_danger_type.h" @@ -313,7 +313,8 @@ DownloadItemImpl::DownloadItemImpl( bool opened, base::Time last_access_time, bool transient, - const std::vector<DownloadItem::ReceivedSlice>& received_slices) + const std::vector<DownloadItem::ReceivedSlice>& received_slices, + std::unique_ptr<DownloadEntry> download_entry) : request_info_(url_chain, referrer_url, site_url, @@ -356,6 +357,16 @@ DownloadItemImpl::DownloadItemImpl( DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL || state_ == CANCELLED_INTERNAL); DCHECK(base::IsValidGUID(guid_)); + + if (download_entry) { + download_source_ = download_entry->download_source; + fetch_error_body_ = download_entry->fetch_error_body; + request_headers_ = download_entry->request_headers; + ukm_download_id_ = download_entry->ukm_download_id; + bytes_wasted_ = download_entry->bytes_wasted; + } else { + ukm_download_id_ = GetUniqueDownloadId(); + } Init(false /* not actively downloading */, TYPE_HISTORY_IMPORT); } @@ -666,22 +677,33 @@ void DownloadItemImpl::ShowDownloadInShell() { delegate_->ShowDownloadInShell(this); } -void DownloadItemImpl::RenameDownloadedFileDone(RenameDownloadCallback callback, - const base::FilePath& new_path, - DownloadRenameResult result) { +void DownloadItemImpl::RenameDownloadedFileDone( + RenameDownloadCallback callback, + const base::FilePath& display_name, + DownloadRenameResult result) { if (result == DownloadRenameResult::SUCCESS) { - destination_info_.target_path = new_path; - destination_info_.current_path = new_path; + bool is_content_uri = false; +#if defined(OS_ANDROID) + is_content_uri = GetFullPath().IsContentUri(); +#endif // defined(OS_ANDROID) + if (is_content_uri) { + SetDisplayName(display_name); + } else { + auto new_full_path = + base::FilePath(GetFullPath().DirName()).Append(display_name); + destination_info_.target_path = new_full_path; + destination_info_.current_path = new_full_path; + } UpdateObservers(); } std::move(callback).Run(result); } -void DownloadItemImpl::Rename(const base::FilePath& name, +void DownloadItemImpl::Rename(const base::FilePath& display_name, DownloadItem::RenameDownloadCallback callback) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (name.IsAbsolute()) { + if (display_name.IsAbsolute()) { base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&DownloadItemImpl::RenameDownloadedFileDone, weak_ptr_factory_.GetWeakPtr(), @@ -690,14 +712,13 @@ void DownloadItemImpl::Rename(const base::FilePath& name, return; } - auto full_path = base::FilePath(GetFullPath().DirName()).Append(name); - base::PostTaskAndReplyWithResult( GetDownloadTaskRunner().get(), FROM_HERE, - base::BindOnce(&download::RenameDownloadedFile, GetFullPath(), full_path), + base::BindOnce(&download::RenameDownloadedFile, GetFullPath(), + display_name), base::BindOnce(&DownloadItemImpl::RenameDownloadedFileDone, weak_ptr_factory_.GetWeakPtr(), std::move(callback), - full_path)); + display_name)); } uint32_t DownloadItemImpl::GetId() const { @@ -867,7 +888,8 @@ const base::FilePath& DownloadItemImpl::GetForcedFilePath() const { } base::FilePath DownloadItemImpl::GetTemporaryFilePath() const { - if (state_ == TARGET_PENDING_INTERNAL || INTERRUPTED_TARGET_PENDING_INTERNAL) + if (state_ == TARGET_PENDING_INTERNAL || + state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) return download_file_ ? download_file_->FullPath() : base::FilePath(); return base::FilePath(); } @@ -925,7 +947,9 @@ bool DownloadItemImpl::IsDangerous() const { danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT || danger_type_ == DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT || danger_type_ == DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST || - danger_type_ == DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED); + danger_type_ == DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED || + danger_type_ == DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE || + danger_type_ == DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED); } DownloadDangerType DownloadItemImpl::GetDangerType() const { @@ -1056,6 +1080,17 @@ void DownloadItemImpl::OnContentCheckCompleted(DownloadDangerType danger_type, UpdateObservers(); } +void DownloadItemImpl::OnAsyncScanningCompleted( + DownloadDangerType danger_type) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(AllDataSaved()); + + DVLOG(20) << __func__ << "() danger_type=" << danger_type + << " download=" << DebugString(true); + SetDangerType(danger_type); + UpdateObservers(); +} + void DownloadItemImpl::SetOpenWhenComplete(bool open) { open_when_complete_ = open; } @@ -1393,20 +1428,6 @@ void DownloadItemImpl::Init(bool active, TRACE_EVENT_INSTANT1("download", "DownloadItemActive", TRACE_EVENT_SCOPE_THREAD, "download_item", std::move(active_data)); - - // Read data from in-progress cache. - // TODO(qinmin): Remove this once we initialize the data in DownloadItemImpl - // ctor. - auto in_progress_entry = delegate_->GetInProgressEntry(this); - if (in_progress_entry) { - download_source_ = in_progress_entry->download_source; - fetch_error_body_ = in_progress_entry->fetch_error_body; - request_headers_ = in_progress_entry->request_headers; - ukm_download_id_ = in_progress_entry->ukm_download_id; - bytes_wasted_ = in_progress_entry->bytes_wasted; - } else { - ukm_download_id_ = GetUniqueDownloadId(); - } } DVLOG(20) << __func__ << "() " << DebugString(true); @@ -1641,7 +1662,7 @@ void DownloadItemImpl::OnDownloadTargetDetermined( base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, weak_ptr_factory_.GetWeakPtr()); #if defined(OS_ANDROID) - if ((download_type_ == TYPE_ACTIVE_DOWNLOAD && + if ((download_type_ == TYPE_ACTIVE_DOWNLOAD && !transient_ && DownloadCollectionBridge::ShouldPublishDownload(GetTargetFilePath())) || GetTargetFilePath().IsContentUri()) { GetDownloadTaskRunner()->PostTask( @@ -2429,7 +2450,8 @@ void DownloadItemImpl::ResumeInterruptedDownload( // will only be sent to the URL returned by GetURL(). download_params->set_referrer(GetReferrerUrl()); download_params->set_referrer_policy(net::URLRequest::NEVER_CLEAR_REFERRER); - download_params->set_follow_cross_origin_redirects(false); + download_params->set_cross_origin_redirects( + network::mojom::RedirectMode::kError); TransitionTo(RESUMING_INTERNAL); RecordDownloadCountWithSource(source == ResumptionRequestSource::USER @@ -2626,4 +2648,28 @@ const char* DownloadItemImpl::DebugResumeModeString(ResumeMode mode) { return "unknown"; } +size_t DownloadItemImpl::GetApproximateMemoryUsage() const { + static size_t class_size = sizeof(DownloadItemImpl); + size_t size = class_size; + + for (const GURL& url : GetUrlChain()) + size += url.EstimateMemoryUsage(); + size += GetReferrerUrl().EstimateMemoryUsage(); + size += GetSiteUrl().EstimateMemoryUsage(); + size += GetTabUrl().EstimateMemoryUsage(); + size += GetTabReferrerUrl().EstimateMemoryUsage(); + size += base::trace_event::EstimateMemoryUsage(GetSuggestedFilename()); + size += base::trace_event::EstimateMemoryUsage(GetForcedFilePath().value()); + size += base::trace_event::EstimateMemoryUsage(GetRemoteAddress()); + size += base::trace_event::EstimateMemoryUsage(GetTargetFilePath().value()); + size += base::trace_event::EstimateMemoryUsage(GetFullPath().value()); + size += base::trace_event::EstimateMemoryUsage(GetHash()); + size += base::trace_event::EstimateMemoryUsage(GetMimeType()); + size += base::trace_event::EstimateMemoryUsage(GetOriginalMimeType()); + size += base::trace_event::EstimateMemoryUsage(GetLastModifiedTime()); + size += base::trace_event::EstimateMemoryUsage(GetETag()); + size += base::trace_event::EstimateMemoryUsage(GetGuid()); + return size; +} + } // namespace download diff --git a/chromium/components/download/internal/common/download_item_impl_delegate.cc b/chromium/components/download/internal/common/download_item_impl_delegate.cc index 11a8f2691cc..cba7a2dd4d3 100644 --- a/chromium/components/download/internal/common/download_item_impl_delegate.cc +++ b/chromium/components/download/internal/common/download_item_impl_delegate.cc @@ -6,7 +6,6 @@ #include "base/logging.h" #include "build/build_config.h" -#include "components/download/database/in_progress/download_entry.h" #include "components/download/public/common/auto_resumption_handler.h" #include "components/download/public/common/download_danger_type.h" #include "components/download/public/common/download_item_impl.h" @@ -86,11 +85,6 @@ void DownloadItemImplDelegate::DownloadRemoved(DownloadItemImpl* download) {} void DownloadItemImplDelegate::DownloadInterrupted(DownloadItemImpl* download) { } -base::Optional<DownloadEntry> DownloadItemImplDelegate::GetInProgressEntry( - DownloadItemImpl* download) { - return base::Optional<DownloadEntry>(); -} - bool DownloadItemImplDelegate::IsOffTheRecord() const { return false; } diff --git a/chromium/components/download/internal/common/download_job.cc b/chromium/components/download/internal/common/download_job.cc index 04861abe4a3..d27f2406816 100644 --- a/chromium/components/download/internal/common/download_job.cc +++ b/chromium/components/download/internal/common/download_job.cc @@ -76,8 +76,7 @@ void DownloadJob::OnDownloadFileInitialized( } bool DownloadJob::AddInputStream(std::unique_ptr<InputStream> stream, - int64_t offset, - int64_t length) { + int64_t offset) { DownloadFile* download_file = download_item_->GetDownloadFile(); if (!download_file) { CancelRequestWithOffset(offset); @@ -90,7 +89,7 @@ bool DownloadJob::AddInputStream(std::unique_ptr<InputStream> stream, GetDownloadTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&DownloadFile::AddInputStream, base::Unretained(download_file), - std::move(stream), offset, length)); + std::move(stream), offset)); return true; } diff --git a/chromium/components/download/internal/common/download_job_factory.cc b/chromium/components/download/internal/common/download_job_factory.cc index cd6274cac86..fb23ce85786 100644 --- a/chromium/components/download/internal/common/download_job_factory.cc +++ b/chromium/components/download/internal/common/download_job_factory.cc @@ -58,6 +58,8 @@ ConnectionType GetConnectionType( 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_49: + case net::HttpResponseInfo::CONNECTION_INFO_QUIC_50: case net::HttpResponseInfo::CONNECTION_INFO_QUIC_99: case net::HttpResponseInfo::CONNECTION_INFO_QUIC_999: return ConnectionType::kQUIC; 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 d35d7862c89..f4bc7a4ee13 100644 --- a/chromium/components/download/internal/common/download_path_reservation_tracker.cc +++ b/chromium/components/download/internal/common/download_path_reservation_tracker.cc @@ -121,7 +121,8 @@ bool IsFileNameInUse(const base::FilePath& path) { } // Returns true if the given path is in use by a path reservation, -// and has a different key then the item arg. +// and has a different key then the item arg. Called on the task runner returned +// by DownloadPathReservationTracker::GetTaskRunner(). bool IsAdditionalPathReserved(const base::FilePath& path, DownloadItem* item) { if (!g_reservation_map) return false; @@ -251,11 +252,8 @@ PathValidationResult ResolveReservationConflicts( : PathValidationResult::CONFLICT; case DownloadPathReservationTracker::OVERWRITE: - if (base::FeatureList::IsEnabled( - features::kPreventDownloadsWithSamePath) && - IsPathReserved(*target_path)) { + if (IsPathReserved(*target_path)) return PathValidationResult::CONFLICT; - } return PathValidationResult::SUCCESS; case DownloadPathReservationTracker::PROMPT: @@ -539,10 +537,14 @@ DownloadPathReservationTracker::GetTaskRunner() { } // static -bool DownloadPathReservationTracker::CheckDownloadPathForExistingDownload( +void DownloadPathReservationTracker::CheckDownloadPathForExistingDownload( const base::FilePath& target_path, - DownloadItem* download_item) { - return IsAdditionalPathReserved(target_path, download_item); + DownloadItem* download_item, + CheckDownloadPathCallback callback) { + base::PostTaskAndReplyWithResult( + GetTaskRunner().get(), FROM_HERE, + base::BindOnce(&IsAdditionalPathReserved, target_path, download_item), + std::move(callback)); } } // namespace download diff --git a/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc b/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc index 5c4e3e169aa..b9b339e3244 100644 --- a/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc +++ b/chromium/components/download/internal/common/download_path_reservation_tracker_unittest.cc @@ -15,12 +15,10 @@ #include "base/observer_list.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" -#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/test/test_file_util.h" #include "base/time/time.h" #include "build/build_config.h" -#include "components/download/public/common/download_features.h" #include "components/download/public/common/download_path_reservation_tracker.h" #include "components/download/public/common/mock_download_item.h" #include "net/base/filename_util.h" @@ -354,12 +352,6 @@ TEST_F(DownloadPathReservationTrackerTest, ConflictWithSource) { // Multiple reservations for the same path should uniquify around each other. TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) { - // When kPreventDownloadsWithSamePath is disabled, - // an OVERWRITE reservation with a conflicting path should return success - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndDisableFeature( - features::kPreventDownloadsWithSamePath); - std::unique_ptr<MockDownloadItem> item1 = CreateDownloadItem(1); base::FilePath path( GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); @@ -409,8 +401,8 @@ TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) { } RunUntilIdle(); - // Now acquire an overwriting reservation. We should end up with the same - // non-uniquified path for both reservations. + // Now acquire an overwriting reservation. It should end up with a CONFLICT + // result. std::unique_ptr<MockDownloadItem> item3 = CreateDownloadItem(2); base::FilePath reserved_path3; conflict_action = DownloadPathReservationTracker::OVERWRITE; @@ -419,7 +411,7 @@ TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) { EXPECT_TRUE(IsPathInUse(path)); EXPECT_FALSE(IsPathInUse(uniquified_path)); - EXPECT_EQ(PathValidationResult::SUCCESS, result); + EXPECT_EQ(PathValidationResult::CONFLICT, result); EXPECT_EQ(path.value(), reserved_path1.value()); EXPECT_EQ(path.value(), reserved_path3.value()); @@ -428,13 +420,9 @@ TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) { SetDownloadItemState(item3.get(), DownloadItem::COMPLETE); } -// When kPreventDownloadsWithSamePath flag is enabled, an OVERWRITE reservation -// with the same path as an active reservation should return a CONFLICT result. +// An OVERWRITE reservation with the same path as an active reservation should +// return a CONFLICT result. TEST_F(DownloadPathReservationTrackerTest, ConflictingReservation_Prevented) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - features::kPreventDownloadsWithSamePath); - std::unique_ptr<MockDownloadItem> item1 = CreateDownloadItem(1); base::FilePath path( GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"))); diff --git a/chromium/components/download/internal/common/download_response_handler.cc b/chromium/components/download/internal/common/download_response_handler.cc index e2e30819117..8e09e3e9b52 100644 --- a/chromium/components/download/internal/common/download_response_handler.cc +++ b/chromium/components/download/internal/common/download_response_handler.cc @@ -54,7 +54,7 @@ DownloadResponseHandler::DownloadResponseHandler( bool is_parallel_request, bool is_transient, bool fetch_error_body, - bool follow_cross_origin_redirects, + network::mojom::RedirectMode cross_origin_redirects, const DownloadUrlParameters::RequestHeadersType& request_headers, const std::string& request_origin, DownloadSource download_source, @@ -69,7 +69,7 @@ DownloadResponseHandler::DownloadResponseHandler( referrer_policy_(resource_request->referrer_policy), is_transient_(is_transient), fetch_error_body_(fetch_error_body), - follow_cross_origin_redirects_(follow_cross_origin_redirects), + cross_origin_redirects_(cross_origin_redirects), first_origin_(url::Origin::Create(resource_request->url)), request_headers_(request_headers), request_origin_(request_origin), @@ -158,17 +158,35 @@ DownloadResponseHandler::CreateDownloadCreateInfo( void DownloadResponseHandler::OnReceiveRedirect( const net::RedirectInfo& redirect_info, network::mojom::URLResponseHeadPtr head) { - if (!follow_cross_origin_redirects_ && - !first_origin_.IsSameOriginWith( - url::Origin::Create(redirect_info.new_url))) { - abort_reason_ = DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT; - url_chain_.push_back(redirect_info.new_url); - method_ = redirect_info.new_method; - referrer_ = GURL(redirect_info.new_referrer); - referrer_policy_ = redirect_info.new_referrer_policy; + // Check if redirect URL is web safe. + if (delegate_ && !delegate_->CanRequestURL(redirect_info.new_url)) { + abort_reason_ = DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST; OnComplete(network::URLLoaderCompletionStatus(net::OK)); return; } + + if (!first_origin_.IsSameOriginWith( + url::Origin::Create(redirect_info.new_url))) { + // Cross-origin redirect. + switch (cross_origin_redirects_) { + case network::mojom::RedirectMode::kFollow: + // Pretend we didn't notice, and keep going. + break; + case network::mojom::RedirectMode::kManual: + abort_reason_ = DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT; + url_chain_.push_back(redirect_info.new_url); + method_ = redirect_info.new_method; + referrer_ = GURL(redirect_info.new_referrer); + referrer_policy_ = redirect_info.new_referrer_policy; + OnComplete(network::URLLoaderCompletionStatus(net::OK)); + return; + case network::mojom::RedirectMode::kError: + abort_reason_ = DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST; + OnComplete(network::URLLoaderCompletionStatus(net::OK)); + return; + } + } + if (is_partial_request_) { // A redirect while attempting a partial resumption indicates a potential // middle box. Trigger another interruption so that the @@ -178,13 +196,6 @@ void DownloadResponseHandler::OnReceiveRedirect( return; } - // Check if redirect URL is web safe. - if (delegate_ && !delegate_->CanRequestURL(redirect_info.new_url)) { - abort_reason_ = DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST; - OnComplete(network::URLLoaderCompletionStatus(net::OK)); - return; - } - url_chain_.push_back(redirect_info.new_url); method_ = redirect_info.new_method; referrer_ = GURL(redirect_info.new_referrer); @@ -214,7 +225,7 @@ void DownloadResponseHandler::OnStartLoadingResponseBody( mojom::DownloadStreamHandlePtr stream_handle = mojom::DownloadStreamHandle::New(); stream_handle->stream = std::move(body); - stream_handle->client_request = mojo::MakeRequest(&client_ptr_); + stream_handle->client_receiver = client_remote_.BindNewPipeAndPassReceiver(); OnResponseStarted(std::move(stream_handle)); } @@ -228,8 +239,8 @@ void DownloadResponseHandler::OnComplete( static_cast<net::Error>(status.error_code), has_strong_validators_, cert_status_, is_partial_request_, abort_reason_); - if (client_ptr_) { - client_ptr_->OnStreamCompleted( + if (client_remote_) { + client_remote_->OnStreamCompleted( ConvertInterruptReasonToMojoNetworkRequestStatus(reason)); } diff --git a/chromium/components/download/internal/common/download_stats.cc b/chromium/components/download/internal/common/download_stats.cc index d12e8625626..90c6c0fa692 100644 --- a/chromium/components/download/internal/common/download_stats.cc +++ b/chromium/components/download/internal/common/download_stats.cc @@ -1061,6 +1061,11 @@ void RecordParallelDownloadAddStreamSuccess(bool success, } } +void RecordParallelRequestCreationFailure(DownloadInterruptReason reason) { + base::UmaHistogramSparse("Download.ParallelDownload.CreationFailureReason", + reason); +} + void RecordParallelizableContentLength(int64_t content_length) { UMA_HISTOGRAM_CUSTOM_COUNTS("Download.ContentLength.Parallelizable", content_length / 1024, 1, kMaxFileSizeKb, 50); @@ -1278,6 +1283,17 @@ void RecordDownloadConnectionInfo( net::HttpResponseInfo::ConnectionInfo::NUM_OF_CONNECTION_INFOS); } +void RecordDownloadManagerCreationTimeSinceStartup( + base::TimeDelta elapsed_time) { + base::UmaHistogramLongTimes("Download.DownloadManager.CreationDelay", + elapsed_time); +} + +void RecordDownloadManagerMemoryUsage(size_t bytes_used) { + base::UmaHistogramMemoryKB("Download.DownloadManager.MemoryUsage", + bytes_used / 1000); +} + #if defined(OS_ANDROID) void RecordFirstBackgroundDownloadInterruptReason( DownloadInterruptReason reason, diff --git a/chromium/components/download/internal/common/download_task_runner.cc b/chromium/components/download/internal/common/download_task_runner.cc index cb198e7eff9..d34a5359b6e 100644 --- a/chromium/components/download/internal/common/download_task_runner.cc +++ b/chromium/components/download/internal/common/download_task_runner.cc @@ -35,6 +35,9 @@ base::LazySequencedTaskRunner g_download_task_runner = base::LazyInstance<scoped_refptr<base::SingleThreadTaskRunner>>:: DestructorAtExit g_io_task_runner = LAZY_INSTANCE_INITIALIZER; +base::LazyInstance<scoped_refptr<base::SequencedTaskRunner>>::DestructorAtExit + g_db_task_runner = LAZY_INSTANCE_INITIALIZER; + // Lock to protect |g_io_task_runner| base::Lock& GetIOTaskRunnerLock() { static base::NoDestructor<base::Lock> instance; @@ -63,4 +66,14 @@ scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner() { return g_io_task_runner.Get(); } +void SetDownloadDBTaskRunnerForTesting( + const scoped_refptr<base::SequencedTaskRunner>& task_runner) { + DCHECK(task_runner); + g_db_task_runner.Get() = task_runner; +} + +scoped_refptr<base::SequencedTaskRunner> GetDownloadDBTaskRunnerForTesting() { + return g_db_task_runner.Get(); +} + } // namespace download diff --git a/chromium/components/download/internal/common/download_utils.cc b/chromium/components/download/internal/common/download_utils.cc index d9bcc7b5ba0..0a595eb896a 100644 --- a/chromium/components/download/internal/common/download_utils.cc +++ b/chromium/components/download/internal/common/download_utils.cc @@ -4,6 +4,9 @@ #include "components/download/public/common/download_utils.h" +#include <memory> +#include <string> + #include "base/files/file_util.h" #include "base/format_macros.h" #include "base/i18n/file_util_icu.h" @@ -27,7 +30,7 @@ #if defined(OS_ANDROID) #include "base/android/content_uri_utils.h" #include "components/download/internal/common/android/download_collection_bridge.h" -#endif +#endif // defined(OS_ANDROID) namespace download { @@ -41,6 +44,31 @@ const int64_t kDefaultContentValidationLength = 1024; // file starting at the offset from the response. const int64_t kInvalidFileWriteOffset = -1; +// Default expiration time of download in days. Canceled and interrupted +// downloads will be deleted after expiration. +const int kDefaultDownloadExpiredTimeInDays = 90; + +#if defined(OS_ANDROID) +// Default maximum length of a downloaded file name on Android. +const int kDefaultMaxFileNameLengthOnAndroid = 127; + +DownloadItem::DownloadRenameResult RenameDownloadedFileForContentUri( + const base::FilePath& from_path, + const base::FilePath& display_name) { + if (static_cast<int>(display_name.value().length()) > + kDefaultMaxFileNameLengthOnAndroid) { + return DownloadItem::DownloadRenameResult::FAILURE_NAME_TOO_LONG; + } + + if (DownloadCollectionBridge::FileNameExists(display_name)) + return DownloadItem::DownloadRenameResult::FAILURE_NAME_CONFLICT; + + return DownloadCollectionBridge::RenameDownloadUri(from_path, display_name) + ? DownloadItem::DownloadRenameResult::SUCCESS + : DownloadItem::DownloadRenameResult::FAILURE_NAME_INVALID; +} +#endif // defined(OS_ANDROID) + void AppendExtraHeaders(net::HttpRequestHeaders* headers, DownloadUrlParameters* params) { for (const auto& header : params->request_headers()) @@ -57,23 +85,6 @@ DownloadInterruptReason HandleRequestCompletionStatus( 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) { - error_code = net::OK; - RecordDownloadCount(COMPLETED_WITH_CONTENT_LENGTH_MISMATCH_COUNT); - } - if (error_code == net::ERR_ABORTED) { // ERR_ABORTED == something outside of the network // stack cancelled the request. There aren't that many things that @@ -166,15 +177,8 @@ DownloadInterruptReason HandleSuccessfulServerResponse( return result; // The caller is expecting a partial response. - if (save_info && (save_info->offset > 0 || save_info->length > 0)) { + if (save_info && save_info->offset > 0) { if (http_headers.response_code() != net::HTTP_PARTIAL_CONTENT) { - // Server should send partial content when "If-Match" or - // "If-Unmodified-Since" check passes, and the range request header has - // last byte position. e.g. "Range:bytes=50-99". - if (save_info->length != DownloadSaveInfo::kLengthFullContent && - !fetch_error_body) - return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; - // Requested a partial range, but received the entire response, when // the range request header is "Range:bytes={offset}-". // The response can be HTTP 200 or other error code when @@ -193,9 +197,7 @@ DownloadInterruptReason HandleSuccessfulServerResponse( return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT; DCHECK_GE(first_byte, 0); - if (first_byte != save_info->offset || - (save_info->length > 0 && - last_byte != save_info->offset + save_info->length - 1)) { + if (first_byte != save_info->offset) { // The server returned a different range than the one we requested. Assume // the server doesn't support range request. return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE; @@ -253,13 +255,18 @@ void HandleResponseHeaders(const net::HttpResponseHeaders* headers, std::unique_ptr<network::ResourceRequest> CreateResourceRequest( DownloadUrlParameters* params) { - DCHECK(params->offset() >= 0); + DCHECK_GE(params->offset(), 0); std::unique_ptr<network::ResourceRequest> request( new network::ResourceRequest); request->method = params->method(); request->url = params->url(); request->request_initiator = params->initiator(); + if (!params->network_isolation_key().IsEmpty()) { + request->trusted_params = network::ResourceRequest::TrustedParams(); + request->trusted_params->network_isolation_key = + params->network_isolation_key(); + } request->do_not_prompt_for_login = params->do_not_prompt_for_login(); request->site_for_cookies = params->url(); request->referrer = params->referrer(); @@ -321,8 +328,7 @@ int GetLoadFlags(DownloadUrlParameters* params, bool has_upload_data) { std::unique_ptr<net::HttpRequestHeaders> GetAdditionalRequestHeaders( DownloadUrlParameters* params) { auto headers = std::make_unique<net::HttpRequestHeaders>(); - if (params->offset() == 0 && - params->length() == DownloadSaveInfo::kLengthFullContent) { + if (params->offset() == 0) { AppendExtraHeaders(headers.get(), params); return headers; } @@ -345,10 +351,7 @@ std::unique_ptr<net::HttpRequestHeaders> GetAdditionalRequestHeaders( // Add "Range" header. std::string range_header = - (params->length() == DownloadSaveInfo::kLengthFullContent) - ? base::StringPrintf("bytes=%" PRId64 "-", params->offset()) - : base::StringPrintf("bytes=%" PRId64 "-%" PRId64, params->offset(), - params->offset() + params->length() - 1); + base::StringPrintf("bytes=%" PRId64 "-", params->offset()); headers->SetHeader(net::HttpRequestHeaders::kRange, range_header); // Add "If-Range" headers. @@ -425,21 +428,21 @@ DownloadDBEntry CreateDownloadDBEntryFromItem(const DownloadItemImpl& item) { return entry; } -base::Optional<DownloadEntry> CreateDownloadEntryFromDownloadDBEntry( +std::unique_ptr<DownloadEntry> CreateDownloadEntryFromDownloadDBEntry( base::Optional<DownloadDBEntry> entry) { if (!entry || !entry->download_info) - return base::Optional<DownloadEntry>(); + return nullptr; base::Optional<InProgressInfo> in_progress_info = entry->download_info->in_progress_info; base::Optional<UkmInfo> ukm_info = entry->download_info->ukm_info; if (!ukm_info || !in_progress_info) - return base::Optional<DownloadEntry>(); + return nullptr; - return base::Optional<DownloadEntry>(DownloadEntry( + return std::make_unique<DownloadEntry>( entry->download_info->guid, std::string(), ukm_info->download_source, in_progress_info->fetch_error_body, in_progress_info->request_headers, - ukm_info->ukm_download_id)); + ukm_info->ukm_download_id); } uint64_t GetUniqueDownloadId() { @@ -557,7 +560,7 @@ bool IsDownloadDone(const GURL& url, case DownloadItem::INTERRUPTED: return GetDownloadResumeMode(url, reason, false /* restart_required */, false /* user_action_required */) == - download::ResumeMode::INVALID; + ResumeMode::INVALID; default: return false; } @@ -577,9 +580,14 @@ bool DeleteDownloadedFile(const base::FilePath& path) { return base::DeleteFile(path, false); } -download::DownloadItem::DownloadRenameResult RenameDownloadedFile( +DownloadItem::DownloadRenameResult RenameDownloadedFile( const base::FilePath& from_path, - const base::FilePath& to_path) { + const base::FilePath& display_name) { +#if defined(OS_ANDROID) + if (from_path.IsContentUri()) + return RenameDownloadedFileForContentUri(from_path, display_name); +#endif // defined(OS_ANDROID) + auto to_path = base::FilePath(from_path.DirName()).Append(display_name); if (!base::PathExists(from_path) || !base::DirectoryExists(from_path.DirName())) return DownloadItem::DownloadRenameResult::FAILURE_UNAVAILABLE; @@ -598,20 +606,9 @@ download::DownloadItem::DownloadRenameResult RenameDownloadedFile( return DownloadItem::DownloadRenameResult::FAILURE_NAME_TOO_LONG; } } -#if defined(OS_ANDROID) - if (from_path.IsContentUri()) { - return DownloadCollectionBridge::RenameDownloadUri(from_path, - to_path.BaseName()) - ? download::DownloadItem::DownloadRenameResult::SUCCESS - : download::DownloadItem::DownloadRenameResult:: - FAILURE_NAME_INVALID; - } -#endif - return base::Move(from_path, to_path) - ? download::DownloadItem::DownloadRenameResult::SUCCESS - : download::DownloadItem::DownloadRenameResult:: - FAILURE_NAME_INVALID; + ? DownloadItem::DownloadRenameResult::SUCCESS + : DownloadItem::DownloadRenameResult::FAILURE_NAME_INVALID; } int64_t GetDownloadValidationLengthConfig() { @@ -623,4 +620,12 @@ int64_t GetDownloadValidationLengthConfig() { ? result : kDefaultContentValidationLength; } + +base::TimeDelta GetExpiredDownloadDeleteTime() { + int expired_days = base::GetFieldTrialParamByFeatureAsInt( + features::kDeleteExpiredDownloads, kExpiredDownloadDeleteTimeFinchKey, + kDefaultDownloadExpiredTimeInDays); + return base::TimeDelta::FromDays(expired_days); +} + } // namespace download diff --git a/chromium/components/download/internal/common/download_worker.cc b/chromium/components/download/internal/common/download_worker.cc index b1e9792c36c..3960aae77cf 100644 --- a/chromium/components/download/internal/common/download_worker.cc +++ b/chromium/components/download/internal/common/download_worker.cc @@ -8,6 +8,7 @@ #include "components/download/internal/common/resource_downloader.h" #include "components/download/public/common/download_create_info.h" #include "components/download/public/common/download_interrupt_reasons.h" +#include "components/download/public/common/download_stats.h" #include "components/download/public/common/download_task_runner.h" #include "components/download/public/common/download_utils.h" #include "components/download/public/common/input_stream.h" @@ -68,11 +69,9 @@ void CreateUrlDownloadHandler( } // namespace DownloadWorker::DownloadWorker(DownloadWorker::Delegate* delegate, - int64_t offset, - int64_t length) + int64_t offset) : delegate_(delegate), offset_(offset), - length_(length), is_paused_(false), is_canceled_(false), url_download_handler_(nullptr, base::OnTaskRunnerDeleter(nullptr)) { @@ -115,7 +114,7 @@ void DownloadWorker::OnUrlDownloadStarted( URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr url_loader_factory_provider, UrlDownloadHandler* downloader, - const DownloadUrlParameters::OnStartedCallback& callback) { + DownloadUrlParameters::OnStartedCallback callback) { // |callback| is not used in subsequent requests. DCHECK(callback.is_null()); @@ -127,12 +126,16 @@ void DownloadWorker::OnUrlDownloadStarted( return; } - // TODO(xingliu): Add metric for error handling. + if (offset_ != create_info->offset) + create_info->result = DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE; + if (create_info->result != DOWNLOAD_INTERRUPT_REASON_NONE) { + RecordParallelRequestCreationFailure(create_info->result); VLOG(kWorkerVerboseLevel) << "Parallel download sub-request failed. reason = " << create_info->result; input_stream.reset(new CompletedInputStream(create_info->result)); + url_download_handler_.reset(); } // Pause the stream if user paused, still push the stream reader to the sink. diff --git a/chromium/components/download/internal/common/download_worker.h b/chromium/components/download/internal/common/download_worker.h index d560f0da584..bb91af9df67 100644 --- a/chromium/components/download/internal/common/download_worker.h +++ b/chromium/components/download/internal/common/download_worker.h @@ -38,13 +38,10 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker std::unique_ptr<DownloadCreateInfo> download_create_info) = 0; }; - DownloadWorker(DownloadWorker::Delegate* delegate, - int64_t offset, - int64_t length); + DownloadWorker(DownloadWorker::Delegate* delegate, int64_t offset); virtual ~DownloadWorker(); int64_t offset() const { return offset_; } - int64_t length() const { return length_; } // Send network request to ask for a download. void SendRequest(std::unique_ptr<DownloadUrlParameters> params, @@ -64,7 +61,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr url_loader_factory_provider, UrlDownloadHandler* downloader, - const DownloadUrlParameters::OnStartedCallback& callback) override; + DownloadUrlParameters::OnStartedCallback callback) override; void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override; void OnUrlDownloadHandlerCreated( UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) override; @@ -74,9 +71,6 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadWorker // The starting position of the content for this worker to download. int64_t offset_; - // The length of the request. May be 0 to fetch to the end of the file. - int64_t length_; - // States of the worker. bool is_paused_; bool is_canceled_; 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 694651a8ee3..235140d58e4 100644 --- a/chromium/components/download/internal/common/in_progress_download_manager.cc +++ b/chromium/components/download/internal/common/in_progress_download_manager.cc @@ -39,7 +39,8 @@ namespace { std::unique_ptr<DownloadItemImpl> CreateDownloadItemImpl( DownloadItemImplDelegate* delegate, - const DownloadDBEntry entry) { + const DownloadDBEntry entry, + std::unique_ptr<DownloadEntry> download_entry) { if (!entry.download_info) return nullptr; @@ -65,7 +66,8 @@ std::unique_ptr<DownloadItemImpl> CreateDownloadItemImpl( in_progress_info->state, in_progress_info->danger_type, in_progress_info->interrupt_reason, in_progress_info->paused, in_progress_info->metered, false, base::Time(), - in_progress_info->transient, in_progress_info->received_slices); + in_progress_info->transient, in_progress_info->received_slices, + std::move(download_entry)); } void OnUrlDownloadHandlerCreated( @@ -209,7 +211,6 @@ InProgressDownloadManager::InProgressDownloadManager( download_start_observer_(nullptr), is_origin_secure_cb_(is_origin_secure_cb), url_security_policy_(url_security_policy), - use_empty_db_(in_progress_db_dir.empty()), connector_(connector) { Initialize(in_progress_db_dir, db_provider); } @@ -222,12 +223,12 @@ void InProgressDownloadManager::OnUrlDownloadStarted( URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr url_loader_factory_provider, UrlDownloadHandler* downloader, - const DownloadUrlParameters::OnStartedCallback& callback) { + DownloadUrlParameters::OnStartedCallback callback) { StartDownload(std::move(download_create_info), std::move(input_stream), std::move(url_loader_factory_provider), base::BindOnce(&InProgressDownloadManager::CancelUrlDownload, weak_factory_.GetWeakPtr(), downloader), - callback); + std::move(callback)); } void InProgressDownloadManager::OnUrlDownloadStopped( @@ -343,7 +344,7 @@ void InProgressDownloadManager::Initialize( leveldb_proto::ProtoDatabaseProvider* db_provider) { std::unique_ptr<DownloadDB> download_db; - if (use_empty_db_) { + if (in_progress_db_dir.empty()) { download_db = std::make_unique<DownloadDB>(); } else { download_db = std::make_unique<DownloadDBImpl>( @@ -353,6 +354,10 @@ void InProgressDownloadManager::Initialize( download_db_cache_ = std::make_unique<DownloadDBCache>(std::move(download_db)); + if (GetDownloadDBTaskRunnerForTesting()) { + download_db_cache_->SetTimerTaskRunnerForTesting( + GetDownloadDBTaskRunnerForTesting()); + } download_db_cache_->Initialize(base::BindOnce( &InProgressDownloadManager::OnDBInitialized, weak_factory_.GetWeakPtr())); } @@ -397,7 +402,12 @@ void InProgressDownloadManager::DetermineDownloadTarget( : DownloadPathReservationTracker::OVERWRITE, base::Bind(&OnPathReserved, callback, download->GetDangerType(), intermediate_path_cb_, download->GetForcedFilePath())); -#endif +#else + callback.Run(download->GetTargetFilePath(), + DownloadItem::TARGET_DISPOSITION_OVERWRITE, + download->GetDangerType(), download->GetFullPath(), + DOWNLOAD_INTERRUPT_REASON_NONE); +#endif // defined(OS_ANDROID) } void InProgressDownloadManager::ResumeInterruptedDownload( @@ -416,16 +426,6 @@ bool InProgressDownloadManager::ShouldOpenDownload( return true; } -base::Optional<DownloadEntry> InProgressDownloadManager::GetInProgressEntry( - DownloadItemImpl* download) { - if (!download) - return base::Optional<DownloadEntry>(); - if (base::Contains(download_entries_, download->GetGuid())) - return download_entries_[download->GetGuid()]; - - return base::Optional<DownloadEntry>(); -} - void InProgressDownloadManager::ReportBytesWasted(DownloadItemImpl* download) { download_db_cache_->OnDownloadUpdated(download); } @@ -441,7 +441,7 @@ void InProgressDownloadManager::StartDownload( URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr url_loader_factory_provider, DownloadJob::CancelRequestCallback cancel_request_callback, - const DownloadUrlParameters::OnStartedCallback& on_started) { + DownloadUrlParameters::OnStartedCallback on_started) { DCHECK(info); if (info->is_new_download && @@ -476,7 +476,7 @@ void InProgressDownloadManager::StartDownload( // DownloadItem. if (delegate_ && !GetDownloadByGuid(info->guid)) { delegate_->StartDownloadItem( - std::move(info), on_started, + std::move(info), std::move(on_started), base::BindOnce(&InProgressDownloadManager::StartDownloadWithItem, weak_factory_.GetWeakPtr(), std::move(stream), std::move(url_loader_factory_provider), @@ -553,7 +553,7 @@ void InProgressDownloadManager::OnDBInitialized( bool success, std::unique_ptr<std::vector<DownloadDBEntry>> entries) { #if defined(OS_ANDROID) - if (!use_empty_db_ && + if (entries->size() > 0 && DownloadCollectionBridge::NeedToRetrieveDisplayNames()) { DownloadCollectionBridge::GetDisplayNamesCallback callback = base::BindOnce(&InProgressDownloadManager::OnDownloadNamesRetrieved, @@ -577,40 +577,35 @@ void InProgressDownloadManager::OnDownloadNamesRetrieved( int num_duplicates = 0; display_names_ = std::move(display_names); for (const auto& entry : *entries) { - base::Optional<DownloadEntry> download_entry = - CreateDownloadEntryFromDownloadDBEntry(entry); - if (download_entry) - download_entries_[download_entry->guid] = download_entry.value(); - if (base::FeatureList::IsEnabled(features::kDownloadDBForNewDownloads)) { - auto item = CreateDownloadItemImpl(this, entry); - if (!item) - continue; - uint32_t download_id = item->GetId(); - // Remove entries with duplicate ids. - if (download_id != DownloadItem::kInvalidId && - base::Contains(download_ids, download_id)) { + auto item = CreateDownloadItemImpl( + this, entry, CreateDownloadEntryFromDownloadDBEntry(entry)); + if (!item) + continue; + uint32_t download_id = item->GetId(); + // Remove entries with duplicate ids. + if (download_id != DownloadItem::kInvalidId && + base::Contains(download_ids, download_id)) { + RemoveInProgressDownload(item->GetGuid()); + num_duplicates++; + continue; + } +#if defined(OS_ANDROID) + const base::FilePath& path = item->GetTargetFilePath(); + if (path.IsContentUri()) { + base::FilePath display_name = GetDownloadDisplayName(path); + // If a download doesn't have a display name, remove it. + if (display_name.empty()) { RemoveInProgressDownload(item->GetGuid()); - num_duplicates++; continue; + } else { + item->SetDisplayName(display_name); } -#if defined(OS_ANDROID) - const base::FilePath& path = item->GetTargetFilePath(); - if (path.IsContentUri()) { - base::FilePath display_name = GetDownloadDisplayName(path); - // If a download doesn't have a display name, remove it. - if (display_name.empty()) { - RemoveInProgressDownload(item->GetGuid()); - continue; - } else { - item->SetDisplayName(display_name); - } - } -#endif - item->AddObserver(download_db_cache_.get()); - OnNewDownloadCreated(item.get()); - in_progress_downloads_.emplace_back(std::move(item)); - download_ids.insert(download_id); } +#endif + item->AddObserver(download_db_cache_.get()); + OnNewDownloadCreated(item.get()); + in_progress_downloads_.emplace_back(std::move(item)); + download_ids.insert(download_id); } if (num_duplicates > 0) RecordDuplicateInProgressDownloadIdCount(num_duplicates); @@ -636,7 +631,6 @@ base::FilePath InProgressDownloadManager::GetDownloadDisplayName( } void InProgressDownloadManager::OnAllInprogressDownloadsLoaded() { - download_entries_.clear(); display_names_.reset(); } diff --git a/chromium/components/download/internal/common/parallel_download_job.cc b/chromium/components/download/internal/common/parallel_download_job.cc index a2e1e42495d..26b7e4b2f7c 100644 --- a/chromium/components/download/internal/common/parallel_download_job.cc +++ b/chromium/components/download/internal/common/parallel_download_job.cc @@ -125,12 +125,8 @@ void ParallelDownloadJob::OnInputStreamReady( DownloadWorker* worker, std::unique_ptr<InputStream> input_stream, std::unique_ptr<DownloadCreateInfo> download_create_info) { - // If server returns a wrong range, abort the parallel request. - bool success = download_create_info->offset == worker->offset(); - if (success) { - success = DownloadJob::AddInputStream(std::move(input_stream), - worker->offset(), worker->length()); - } + bool success = + DownloadJob::AddInputStream(std::move(input_stream), worker->offset()); RecordParallelDownloadAddStreamSuccess( success, range_support_ == RangeRequestSupportType::kSupport); @@ -236,15 +232,14 @@ void ParallelDownloadJob::ForkSubRequests( // All parallel requests are half open, which sends request headers like // "Range:50-". // If server rejects a certain request, others should take over. - CreateRequest(it->offset, DownloadSaveInfo::kLengthFullContent); + CreateRequest(it->offset); } } -void ParallelDownloadJob::CreateRequest(int64_t offset, int64_t length) { +void ParallelDownloadJob::CreateRequest(int64_t offset) { DCHECK(download_item_); - DCHECK_EQ(DownloadSaveInfo::kLengthFullContent, length); - auto worker = std::make_unique<DownloadWorker>(this, offset, length); + auto worker = std::make_unique<DownloadWorker>(this, offset); net::NetworkTrafficAnnotationTag traffic_annotation = net::DefineNetworkTrafficAnnotation("parallel_download_job", R"( @@ -277,10 +272,6 @@ void ParallelDownloadJob::CreateRequest(int64_t offset, int64_t length) { download_params->set_etag(download_item_->GetETag()); download_params->set_offset(offset); - // Setting the length will result in range request to fetch a slice of the - // file. - download_params->set_length(length); - // Subsequent range requests don't need the "If-Range" header. download_params->set_use_if_range(false); @@ -290,8 +281,10 @@ void ParallelDownloadJob::CreateRequest(int64_t offset, int64_t length) { download_params->set_referrer_policy(net::URLRequest::NEVER_CLEAR_REFERRER); // TODO(xingliu): We should not support redirect at all for parallel requests. - // Currently the network service code path still can redirect. - download_params->set_follow_cross_origin_redirects(false); + // Currently the network service code path still can redirect as long as it's + // the same origin. + download_params->set_cross_origin_redirects( + network::mojom::RedirectMode::kError); // Send the request. worker->SendRequest(std::move(download_params), diff --git a/chromium/components/download/internal/common/parallel_download_job.h b/chromium/components/download/internal/common/parallel_download_job.h index e502805555b..564a885f713 100644 --- a/chromium/components/download/internal/common/parallel_download_job.h +++ b/chromium/components/download/internal/common/parallel_download_job.h @@ -88,9 +88,8 @@ class COMPONENTS_DOWNLOAD_EXPORT ParallelDownloadJob void ForkSubRequests(const DownloadItem::ReceivedSlices& slices_to_download); // Create one range request, virtual for testing. Range request will start - // from |offset| to |length|. Range request will be half open, e.g. - // "Range:50-" if |length| is 0. - virtual void CreateRequest(int64_t offset, int64_t length); + // from |offset| and will be half open. + virtual void CreateRequest(int64_t offset); // Information about the initial request when download is started. int64_t initial_request_offset_; diff --git a/chromium/components/download/internal/common/parallel_download_job_unittest.cc b/chromium/components/download/internal/common/parallel_download_job_unittest.cc index 7909c2ee000..f6faf8d1c40 100644 --- a/chromium/components/download/internal/common/parallel_download_job_unittest.cc +++ b/chromium/components/download/internal/common/parallel_download_job_unittest.cc @@ -67,8 +67,8 @@ class ParallelDownloadJobForTest : public ParallelDownloadJob { min_slice_size_(min_slice_size), min_remaining_time_(min_remaining_time) {} - void CreateRequest(int64_t offset, int64_t length) override { - auto worker = std::make_unique<DownloadWorker>(this, offset, length); + void CreateRequest(int64_t offset) override { + auto worker = std::make_unique<DownloadWorker>(this, offset); DCHECK(workers_.find(offset) == workers_.end()); workers_[offset] = std::move(worker); @@ -155,7 +155,6 @@ class ParallelDownloadJobTest : public testing::Test { void VerifyWorker(int64_t offset, int64_t length) const { EXPECT_TRUE(job_->workers_.find(offset) != job_->workers_.end()); EXPECT_EQ(offset, job_->workers_[offset]->offset()); - EXPECT_EQ(length, job_->workers_[offset]->length()); } void OnFileInitialized(DownloadInterruptReason result, int64_t bytes_wasted) { diff --git a/chromium/components/download/internal/common/parallel_download_utils_unittest.cc b/chromium/components/download/internal/common/parallel_download_utils_unittest.cc index b0c8462d916..8672f934f99 100644 --- a/chromium/components/download/internal/common/parallel_download_utils_unittest.cc +++ b/chromium/components/download/internal/common/parallel_download_utils_unittest.cc @@ -37,14 +37,12 @@ class ParallelDownloadUtilsRecoverErrorTest // Creates a source stream to test. std::unique_ptr<DownloadFileImpl::SourceStream> CreateSourceStream( - int64_t offset, - int64_t length) { + int64_t offset) { input_stream_ = new StrictMock<MockInputStream>(); EXPECT_CALL(*input_stream_, GetCompletionStatus()) .WillRepeatedly(Return(DOWNLOAD_INTERRUPT_REASON_NONE)); return std::make_unique<DownloadFileImpl::SourceStream>( - offset, length, offset, - std::unique_ptr<MockInputStream>(input_stream_)); + offset, offset, std::unique_ptr<MockInputStream>(input_stream_)); } protected: @@ -140,15 +138,14 @@ TEST_P(ParallelDownloadUtilsRecoverErrorTest, // Create a stream that will work on byte range "100-". const int kErrorStreamOffset = 100; - auto error_stream = CreateSourceStream(kErrorStreamOffset, - DownloadSaveInfo::kLengthFullContent); + auto error_stream = CreateSourceStream(kErrorStreamOffset); error_stream->set_finished(true); // Get starting offset of preceding stream. int64_t preceding_offset = GetParam(); EXPECT_LT(preceding_offset, kErrorStreamOffset); - auto preceding_stream = CreateSourceStream( - preceding_offset, DownloadSaveInfo::kLengthFullContent); + auto preceding_stream = CreateSourceStream(preceding_offset); + // Half open preceding stream can always recover the error for later streams. EXPECT_FALSE(preceding_stream->is_finished()); EXPECT_EQ(0u, preceding_stream->bytes_written()); EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); @@ -170,88 +167,74 @@ TEST_P(ParallelDownloadUtilsRecoverErrorTest, preceding_stream->OnBytesConsumed(1000u, 1000u); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - // Now capped the length of preceding stream with different values. - preceding_stream = CreateSourceStream(preceding_offset, - kErrorStreamOffset - preceding_offset); - // Since preceding stream can't reach the first byte of the error stream, it - // will fail. + int64_t bytes_consumed = kErrorStreamOffset - preceding_offset - 1; + // Half open successfully finished preceding stream should always be + // able to recover error, even if it is not reaching the error offset as the + // error stream might be requesting something our of range. + preceding_stream = CreateSourceStream(preceding_offset); preceding_stream->set_finished(false); - EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); + EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->set_finished(true); - int64_t bytes_consumed = kErrorStreamOffset - preceding_offset; preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed); - EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - - // Inject an error results in failure, even if data written exceeds the first - // byte of error stream. - EXPECT_CALL(*input_stream_, GetCompletionStatus()) - .WillRepeatedly(Return(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE)); - preceding_stream->OnBytesConsumed(1000u, 1000u); - EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); + EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); + preceding_stream->OnBytesConsumed(1, 1); + EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - // Make preceding stream can reach the first byte of error stream. - preceding_stream = CreateSourceStream( - preceding_offset, kErrorStreamOffset - preceding_offset + 1); - // Since the error stream is half opened, no matter what it should fail. - preceding_stream->set_finished(false); + // If the preceding stream is truncated, it should never be able to recover + // a half open stream. + preceding_stream = CreateSourceStream(preceding_offset); + preceding_stream->TruncateLengthWithWrittenDataBlock(kErrorStreamOffset, 1); + EXPECT_EQ(preceding_stream->length(), kErrorStreamOffset - preceding_offset); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->set_finished(true); + EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->OnBytesConsumed(1, 1); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - - // Preceding stream that never download data won't recover the error stream. - preceding_stream = CreateSourceStream(preceding_offset, -1); - EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); } // Verify recovery for length capped error stream. -// Since the error stream length is capped, assume the previous stream length -// is also capped or the previous stream is finished due to error like http -// 404. TEST_P(ParallelDownloadUtilsRecoverErrorTest, RecoverErrorForLengthCappedErrorStream) { // Create a stream that will work on byte range "100-150". const int kErrorStreamLength = 50; - auto error_stream = - CreateSourceStream(kErrorStreamOffset, kErrorStreamLength); + auto error_stream = CreateSourceStream(kErrorStreamOffset); + error_stream->TruncateLengthWithWrittenDataBlock( + kErrorStreamOffset + kErrorStreamLength, 1); + EXPECT_EQ(error_stream->length(), 50); error_stream->set_finished(true); // Get starting offset of preceding stream. const int64_t preceding_offset = GetParam(); EXPECT_LT(preceding_offset, kErrorStreamOffset); - // Create preceding stream capped before starting offset of error stream. - auto preceding_stream = CreateSourceStream( - preceding_offset, kErrorStreamOffset - preceding_offset); + // Create an half open preceding stream. + auto preceding_stream = CreateSourceStream(preceding_offset); EXPECT_FALSE(preceding_stream->is_finished()); EXPECT_EQ(0u, preceding_stream->bytes_written()); - // Since the preceding stream can never reach the starting offset, for an - // unfinished stream, we rely on length instead of bytes written. - EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); + // Since the preceding stream can reach the starting offset, it should be able + // to recover the error stream.. + EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); int64_t bytes_consumed = kErrorStreamOffset - preceding_offset; preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed); - EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); + EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->OnBytesConsumed(kErrorStreamLength - 1, kErrorStreamLength - 1); - EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); + EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->OnBytesConsumed(1, 1); - - // Create preceding stream that can reach the upper bound of error stream. - // Since it's unfinished, it potentially can take over error stream's work - // even if no data is written. - preceding_stream = CreateSourceStream( - preceding_offset, - kErrorStreamOffset - preceding_offset + kErrorStreamLength); - EXPECT_FALSE(preceding_stream->is_finished()); - EXPECT_EQ(0u, preceding_stream->bytes_written()); EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - // Finished preceding stream only checks data written. - preceding_stream = CreateSourceStream(preceding_offset, 1); + // If preceding stream is truncated after error stream, checks data written. + preceding_stream = CreateSourceStream(preceding_offset); + preceding_stream->TruncateLengthWithWrittenDataBlock( + kErrorStreamOffset + kErrorStreamLength, 1); + EXPECT_EQ(preceding_stream->length(), + kErrorStreamOffset + kErrorStreamLength - preceding_offset); + EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->set_finished(true); + EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->OnBytesConsumed(bytes_consumed, bytes_consumed); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); preceding_stream->OnBytesConsumed(kErrorStreamLength - 1, @@ -266,8 +249,17 @@ TEST_P(ParallelDownloadUtilsRecoverErrorTest, .WillRepeatedly(Return(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE)); EXPECT_TRUE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); - // Preceding stream that never download data won't recover the error stream. - preceding_stream = CreateSourceStream(preceding_offset, -1); + // If preceding stream is truncated before or in the middle of error stream, + // it should not recover the error stream when it reaches its length. + preceding_stream = CreateSourceStream(preceding_offset); + preceding_stream->TruncateLengthWithWrittenDataBlock(kErrorStreamOffset + 1, + 1); + EXPECT_EQ(preceding_stream->length(), + kErrorStreamOffset + 1 - preceding_offset); + EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); + preceding_stream->set_finished(true); + EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); + preceding_stream->OnBytesConsumed(bytes_consumed + 1, bytes_consumed + 1); EXPECT_FALSE(CanRecoverFromError(error_stream.get(), preceding_stream.get())); } diff --git a/chromium/components/download/internal/common/resource_downloader.cc b/chromium/components/download/internal/common/resource_downloader.cc index cf8829ee8d4..0b728af59d2 100644 --- a/chromium/components/download/internal/common/resource_downloader.cc +++ b/chromium/components/download/internal/common/resource_downloader.cc @@ -145,7 +145,7 @@ void ResourceDownloader::Start( std::unique_ptr<DownloadUrlParameters> download_url_parameters, bool is_parallel_request, bool is_background_mode) { - callback_ = download_url_parameters->callback(); + callback_ = std::move(download_url_parameters->callback()); upload_callback_ = download_url_parameters->upload_callback(); guid_ = download_url_parameters->guid(); is_content_initiated_ = download_url_parameters->content_initiated(); @@ -157,7 +157,7 @@ void ResourceDownloader::Start( download_url_parameters->GetSaveInfo()), is_parallel_request, download_url_parameters->is_transient(), download_url_parameters->fetch_error_body(), - download_url_parameters->follow_cross_origin_redirects(), + download_url_parameters->cross_origin_redirects(), download_url_parameters->request_headers(), download_url_parameters->request_origin(), download_url_parameters->download_source(), @@ -198,7 +198,7 @@ void ResourceDownloader::InterceptResponse( false, /* is_parallel_request */ false, /* is_transient */ false, /* fetch_error_body */ - true, /* follow_cross_origin_redirects */ + network::mojom::RedirectMode::kFollow, download::DownloadUrlParameters::RequestHeadersType(), std::string(), /* request_origin */ download::DownloadSource::NAVIGATION, std::move(url_chain), @@ -240,7 +240,7 @@ void ResourceDownloader::OnResponseStarted( URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr( new URLLoaderFactoryProvider(url_loader_factory_), base::OnTaskRunnerDeleter(base::ThreadTaskRunnerHandle::Get())), - this, callback_)); + this, std::move(callback_))); } void ResourceDownloader::OnReceiveRedirect() { 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 9cf5796b068..dfbf5ae1f04 100644 --- a/chromium/components/download/internal/common/simple_download_manager_coordinator.cc +++ b/chromium/components/download/internal/common/simple_download_manager_coordinator.cc @@ -8,25 +8,30 @@ #include "components/download/public/common/all_download_event_notifier.h" #include "components/download/public/common/download_item.h" +#include "components/download/public/common/download_stats.h" #include "components/download/public/common/simple_download_manager.h" namespace download { SimpleDownloadManagerCoordinator::SimpleDownloadManagerCoordinator( const DownloadWhenFullManagerStartsCallBack& - download_when_full_manager_starts_cb) + download_when_full_manager_starts_cb, + bool record_full_download_manager_delay) : simple_download_manager_(nullptr), has_all_history_downloads_(false), current_manager_has_all_history_downloads_(false), initialized_(false), download_when_full_manager_starts_cb_( - download_when_full_manager_starts_cb) {} + download_when_full_manager_starts_cb), + creation_time_ticks_(record_full_download_manager_delay + ? base::TimeTicks::Now() + : base::TimeTicks()) {} SimpleDownloadManagerCoordinator::~SimpleDownloadManagerCoordinator() { if (simple_download_manager_) simple_download_manager_->RemoveObserver(this); for (auto& observer : observers_) - observer.OnManagerGoingDown(); + observer.OnManagerGoingDown(this); } void SimpleDownloadManagerCoordinator::SetSimpleDownloadManager( @@ -42,6 +47,11 @@ void SimpleDownloadManagerCoordinator::SetSimpleDownloadManager( current_manager_has_all_history_downloads_ = manages_all_history_downloads; simple_download_manager_ = simple_download_manager; simple_download_manager_->AddObserver(this); + + if (manages_all_history_downloads && !creation_time_ticks_.is_null()) { + RecordDownloadManagerCreationTimeSinceStartup(base::TimeTicks::Now() - + creation_time_ticks_); + } } void SimpleDownloadManagerCoordinator::AddObserver(Observer* observer) { diff --git a/chromium/components/download/internal/common/stream_handle_input_stream.cc b/chromium/components/download/internal/common/stream_handle_input_stream.cc index d6a2a8236d0..bdfe62ed96d 100644 --- a/chromium/components/download/internal/common/stream_handle_input_stream.cc +++ b/chromium/components/download/internal/common/stream_handle_input_stream.cc @@ -27,9 +27,9 @@ StreamHandleInputStream::~StreamHandleInputStream() = default; void StreamHandleInputStream::Initialize() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - binding_ = std::make_unique<mojo::Binding<mojom::DownloadStreamClient>>( - this, std::move(stream_handle_->client_request)); - binding_->set_connection_error_handler(base::BindOnce( + receiver_ = std::make_unique<mojo::Receiver<mojom::DownloadStreamClient>>( + this, std::move(stream_handle_->client_receiver)); + receiver_->set_disconnect_handler(base::BindOnce( &StreamHandleInputStream::OnStreamCompleted, base::Unretained(this), mojom::NetworkRequestStatus::USER_CANCELED)); handle_watcher_ = std::make_unique<mojo::SimpleWatcher>( @@ -45,6 +45,8 @@ void StreamHandleInputStream::RegisterDataReadyCallback( const mojo::SimpleWatcher::ReadyCallback& callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (handle_watcher_) { + if (handle_watcher_->IsWatching()) + ClearDataReadyCallback(); handle_watcher_->Watch(stream_handle_->stream.get(), MOJO_HANDLE_SIGNAL_READABLE, callback); } diff --git a/chromium/components/download/network/BUILD.gn b/chromium/components/download/network/BUILD.gn index 9b3e61bcfd4..99f96d601e8 100644 --- a/chromium/components/download/network/BUILD.gn +++ b/chromium/components/download/network/BUILD.gn @@ -44,8 +44,10 @@ if (is_android) { deps = [ "//base:base_java", + "//base:jni_java", "//net/android:net_java", ] + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] } generate_jni("jni_headers") { diff --git a/chromium/components/download/network/android/java/src/org/chromium/components/download/NetworkStatusListenerAndroid.java b/chromium/components/download/network/android/java/src/org/chromium/components/download/NetworkStatusListenerAndroid.java index febd8d98081..aa4dbfb00ac 100644 --- a/chromium/components/download/network/android/java/src/org/chromium/components/download/NetworkStatusListenerAndroid.java +++ b/chromium/components/download/network/android/java/src/org/chromium/components/download/NetworkStatusListenerAndroid.java @@ -7,6 +7,7 @@ package org.chromium.components.download; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; import org.chromium.net.NetworkChangeNotifierAutoDetect; import org.chromium.net.NetworkChangeNotifierAutoDetect.Observer; import org.chromium.net.RegistrationPolicyAlwaysRegister; @@ -59,7 +60,8 @@ public final class NetworkStatusListenerAndroid implements Observer { @Override public void onConnectionTypeChanged(int newConnectionType) { if (mNativePtr != 0) { - nativeNotifyNetworkChange(mNativePtr, newConnectionType); + NetworkStatusListenerAndroidJni.get().notifyNetworkChange( + mNativePtr, NetworkStatusListenerAndroid.this, newConnectionType); } } @@ -87,6 +89,9 @@ public final class NetworkStatusListenerAndroid implements Observer { @Override public void purgeActiveNetworkList(long[] activeNetIds) {} - private native void nativeNotifyNetworkChange( - long nativeNetworkStatusListenerAndroid, int connectionType); + @NativeMethods + interface Natives { + void notifyNetworkChange(long nativeNetworkStatusListenerAndroid, + NetworkStatusListenerAndroid caller, int connectionType); + } } diff --git a/chromium/components/download/public/common/BUILD.gn b/chromium/components/download/public/common/BUILD.gn index 3febd81f0b4..981dee7f995 100644 --- a/chromium/components/download/public/common/BUILD.gn +++ b/chromium/components/download/public/common/BUILD.gn @@ -102,7 +102,7 @@ if (is_android) { deps = [ "//base:base_java", - "//third_party/android_deps:com_android_support_support_annotations_java", + "//third_party/android_deps:androidx_annotation_annotation_java", ] } @@ -143,6 +143,7 @@ source_set("test_support") { public_deps = [ ":public", "//base", + "//components/download/database", "//net", "//services/service_manager/public/cpp:cpp", "//testing/gmock", diff --git a/chromium/components/download/public/common/DEPS b/chromium/components/download/public/common/DEPS index cf72027ee02..9a82ec5086b 100644 --- a/chromium/components/download/public/common/DEPS +++ b/chromium/components/download/public/common/DEPS @@ -6,6 +6,7 @@ include_rules = [ "+mojo/public/cpp/system", "+net/base/io_buffer.h", "+net/base/net_errors.h", + "+net/base/network_isolation_key.h", "+net/cert/cert_status_flags.h", "+net/http/http_response_headers.h", "+net/http/http_response_info.h", diff --git a/chromium/components/download/public/common/all_download_event_notifier.h b/chromium/components/download/public/common/all_download_event_notifier.h index d9a8989b5d1..c786702341a 100644 --- a/chromium/components/download/public/common/all_download_event_notifier.h +++ b/chromium/components/download/public/common/all_download_event_notifier.h @@ -56,7 +56,7 @@ class COMPONENTS_DOWNLOAD_EXPORT AllDownloadEventNotifier private: // SimpleDownloadManagerCoordinator::Observer void OnDownloadsInitialized(bool active_downloads_only) override; - void OnManagerGoingDown() override; + void OnManagerGoingDown(SimpleDownloadManagerCoordinator* manager) override; void OnDownloadCreated(DownloadItem* item) override; // DownloadItem::Observer diff --git a/chromium/components/download/public/common/download_danger_type.h b/chromium/components/download/public/common/download_danger_type.h index e93fbb52efd..074a59a6e5a 100644 --- a/chromium/components/download/public/common/download_danger_type.h +++ b/chromium/components/download/public/common/download_danger_type.h @@ -53,6 +53,25 @@ enum DownloadDangerType { // Download is password protected, and should be blocked according to policy. DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED = 11, + // Download is too large, and should be blocked according to policy. See the + // BlockLargeFileTransfer policy for details. + DOWNLOAD_DANGER_TYPE_BLOCKED_TOO_LARGE = 12, + + // Download deep scanning identified sensitive content, and recommended + // warning the user. + DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING = 13, + + // Download deep scanning identified sensitive content, and recommended + // blocking the file. + DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK = 14, + + // Download deep scanning identified no problems. + DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE = 15, + + // Download deep scanning identified a problem, but the file has already been + // opened by the user. + DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS = 16, + // 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 3411080f7eb..a4be721070d 100644 --- a/chromium/components/download/public/common/download_features.cc +++ b/chromium/components/download/public/common/download_features.cc @@ -30,17 +30,11 @@ const base::Feature kParallelDownloading { #endif }; -const base::Feature kDownloadDBForNewDownloads{ - "DownloadDBForNewDownloads", base::FEATURE_ENABLED_BY_DEFAULT}; - #if defined(OS_ANDROID) const base::Feature kRefreshExpirationDate{"RefreshExpirationDate", base::FEATURE_ENABLED_BY_DEFAULT}; #endif -const base::Feature kPreventDownloadsWithSamePath{ - "PreventDownloadsWithSamePath", base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kUseInProgressDownloadManagerForDownloadService{ "UseInProgressDownloadManagerForDownloadService", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -58,6 +52,10 @@ const base::Feature kUseParallelRequestsForHTTP2{ const base::Feature kUseParallelRequestsForQUIC{ "UseParallelRequestsForQUIC", base::FEATURE_DISABLED_BY_DEFAULT}; + +const base::Feature kDeleteExpiredDownloads{"DeleteExpiredDownloads", + base::FEATURE_ENABLED_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 345844aafa9..311afcac42b 100644 --- a/chromium/components/download/public/common/download_features.h +++ b/chromium/components/download/public/common/download_features.h @@ -23,20 +23,11 @@ COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature // Whether a download can be handled by parallel jobs. COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature kParallelDownloading; -// Whether metadata for new in-progress downloads will be be stored in download -// DB, rather than history DB. -COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature - kDownloadDBForNewDownloads; - #if defined(OS_ANDROID) // Whether download expiration date will be refreshed on resumption. COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature kRefreshExpirationDate; #endif -// Whether concurrent downloads to the same target path should be allowed. -COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature - kPreventDownloadsWithSamePath; - // Whether in-progress download manager will be used to initialize download // service. COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature @@ -58,6 +49,10 @@ COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature // Whether parallel download is used for QUIC connections. COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature kUseParallelRequestsForQUIC; + +// Whether to delete expired download. +COMPONENTS_DOWNLOAD_EXPORT extern const base::Feature kDeleteExpiredDownloads; + } // namespace features } // namespace download diff --git a/chromium/components/download/public/common/download_file.h b/chromium/components/download/public/common/download_file.h index 7f81cfbebc1..939294260e4 100644 --- a/chromium/components/download/public/common/download_file.h +++ b/chromium/components/download/public/common/download_file.h @@ -72,8 +72,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFile { // Add an input stream to write into a slice of the file, used for // parallel download. virtual void AddInputStream(std::unique_ptr<InputStream> stream, - int64_t offset, - int64_t length) = 0; + int64_t offset) = 0; // Rename the download file to |full_path|. If that file exists // |full_path| will be uniquified by suffixing " (<number>)" to the diff --git a/chromium/components/download/public/common/download_file_impl.h b/chromium/components/download/public/common/download_file_impl.h index 59ef5d5ee4a..6c7e6f26b64 100644 --- a/chromium/components/download/public/common/download_file_impl.h +++ b/chromium/components/download/public/common/download_file_impl.h @@ -15,6 +15,7 @@ #include <unordered_map> #include <vector> +#include "base/cancelable_callback.h" #include "base/files/file.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -60,8 +61,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { const DownloadItem::ReceivedSlices& received_slices, bool is_parallelizable) override; void AddInputStream(std::unique_ptr<InputStream> stream, - int64_t offset, - int64_t length) override; + int64_t offset) override; void RenameAndUniquify(const base::FilePath& full_path, const RenameCompletionCallback& callback) override; void RenameAndAnnotate( @@ -102,7 +102,6 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { class COMPONENTS_DOWNLOAD_EXPORT SourceStream { public: SourceStream(int64_t offset, - int64_t length, int64_t starting_file_write_offset, std::unique_ptr<InputStream> stream); ~SourceStream(); @@ -156,6 +155,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { void set_finished(bool finish) { finished_ = finish; } size_t index() { return index_; } void set_index(size_t index) { index_ = index; } + base::CancelableOnceClosure* read_stream_callback() { + return &read_stream_callback_; + } private: // Starting position of the stream, this is from the network response. @@ -189,6 +191,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { // The stream through which data comes. std::unique_ptr<InputStream> input_stream_; + // Cancelable callback to read from the |input_stream_|. + base::CancelableOnceClosure read_stream_callback_; + DISALLOW_COPY_AND_ASSIGN(SourceStream); }; @@ -277,9 +282,6 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { // Register callback and start to read data from the stream. void RegisterAndActivateStream(SourceStream* source_stream); - // Helper method to activate a stream and start reading from it. - void ActivateStream(SourceStream* source_stream); - // Called when a stream completes. void OnStreamCompleted(SourceStream* source_stream); @@ -302,6 +304,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { // Otherwise, return the current file size. int64_t TotalBytesReceived() const; + // Sends an error update to the observer. + void SendErrorUpdateIfFinished(DownloadInterruptReason reason); + // Helper method to handle stream error void HandleStreamError(SourceStream* source_stream, DownloadInterruptReason reason); @@ -359,8 +364,13 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadFileImpl : public DownloadFile { base::TimeDelta download_time_with_parallel_streams_; base::TimeDelta download_time_without_parallel_streams_; + // The slices received, this is being updated when new data are written. std::vector<DownloadItem::ReceivedSlice> received_slices_; + // Slices to download, calculated during the initialization and are not + // updated when new data are written. + std::vector<DownloadItem::ReceivedSlice> slice_to_download_; + // Used to track whether the download is paused or not. This value is ignored // when network service is disabled as download pause/resumption is handled // by DownloadRequestCore in that case. diff --git a/chromium/components/download/public/common/download_item.h b/chromium/components/download/public/common/download_item.h index df473cfe887..f5617b56b1f 100644 --- a/chromium/components/download/public/common/download_item.h +++ b/chromium/components/download/public/common/download_item.h @@ -491,6 +491,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItem : public base::SupportsUserData { virtual void OnContentCheckCompleted(DownloadDangerType danger_type, DownloadInterruptReason reason) = 0; + // Called when async scanning completes with the given |danger_type|. + virtual void OnAsyncScanningCompleted(DownloadDangerType danger_type) = 0; + // Mark the download to be auto-opened when completed. virtual void SetOpenWhenComplete(bool open) = 0; diff --git a/chromium/components/download/public/common/download_item_impl.h b/chromium/components/download/public/common/download_item_impl.h index 9df918424e7..5dab7f4e818 100644 --- a/chromium/components/download/public/common/download_item_impl.h +++ b/chromium/components/download/public/common/download_item_impl.h @@ -19,6 +19,7 @@ #include "base/optional.h" #include "base/threading/thread_checker_impl.h" #include "base/time/time.h" +#include "components/download/database/in_progress/download_entry.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_interrupt_reasons.h" @@ -191,7 +192,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl bool opened, base::Time last_access_time, bool transient, - const std::vector<DownloadItem::ReceivedSlice>& received_slices); + const std::vector<DownloadItem::ReceivedSlice>& received_slices, + std::unique_ptr<DownloadEntry> download_entry); // Constructing for a regular download. // |net_log| is constructed externally for our use. @@ -290,6 +292,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl DownloadCreationType GetDownloadCreationType() const override; void OnContentCheckCompleted(DownloadDangerType danger_type, DownloadInterruptReason reason) override; + void OnAsyncScanningCompleted(DownloadDangerType danger_type) override; void SetOpenWhenComplete(bool open) override; void SetOpened(bool opened) override; void SetLastAccessTime(base::Time last_access_time) override; @@ -368,6 +371,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl void SetAutoResumeCountForTesting(int32_t auto_resume_count); + // Gets the approximate memory usage of this item. + size_t GetApproximateMemoryUsage() const; + private: // Fine grained states of a download. // diff --git a/chromium/components/download/public/common/download_item_impl_delegate.h b/chromium/components/download/public/common/download_item_impl_delegate.h index 975357cffac..5f0be3b9c1d 100644 --- a/chromium/components/download/public/common/download_item_impl_delegate.h +++ b/chromium/components/download/public/common/download_item_impl_delegate.h @@ -23,7 +23,6 @@ class Connector; } // namespace service_manager namespace download { -struct DownloadEntry; class DownloadItemImpl; // Delegate for operations that a DownloadItemImpl can't do for itself. @@ -107,10 +106,6 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImplDelegate { // Called when the download is interrupted. virtual void DownloadInterrupted(DownloadItemImpl* download); - // Get the in progress entry for the download item. - virtual base::Optional<DownloadEntry> GetInProgressEntry( - DownloadItemImpl* download); - // Whether the download is off the record. virtual bool IsOffTheRecord() const; diff --git a/chromium/components/download/public/common/download_job.h b/chromium/components/download/public/common/download_job.h index a4348310bf3..42d56093eb8 100644 --- a/chromium/components/download/public/common/download_job.h +++ b/chromium/components/download/public/common/download_job.h @@ -64,9 +64,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadJob { // Add an input stream to the download sink. Return false if we start to // destroy download file. - bool AddInputStream(std::unique_ptr<InputStream> stream, - int64_t offset, - int64_t length); + bool AddInputStream(std::unique_ptr<InputStream> stream, int64_t offset); DownloadItem* download_item_; diff --git a/chromium/components/download/public/common/download_path_reservation_tracker.h b/chromium/components/download/public/common/download_path_reservation_tracker.h index 6c0b83a12cb..f27cb372c8b 100644 --- a/chromium/components/download/public/common/download_path_reservation_tracker.h +++ b/chromium/components/download/public/common/download_path_reservation_tracker.h @@ -111,13 +111,17 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadPathReservationTracker { // tests. static bool IsPathInUseForTesting(const base::FilePath& path); - // Returns true if there is an existing path reservation, separate from the - // download_item. Called by + using CheckDownloadPathCallback = + base::OnceCallback<void(bool /* file_exists */)>; + + // Checks to see if there is an existing path reservation that is separate + // from the |download_item|, and calls |callback| with the result. Called by // ChromeDownloadManagerDelegate::OnDownloadTargetDetermined to see if there // is a target collision. - static bool CheckDownloadPathForExistingDownload( + static void CheckDownloadPathForExistingDownload( const base::FilePath& target_path, - DownloadItem* download_item); + DownloadItem* download_item, + CheckDownloadPathCallback callback); static scoped_refptr<base::SequencedTaskRunner> GetTaskRunner(); }; diff --git a/chromium/components/download/public/common/download_response_handler.h b/chromium/components/download/public/common/download_response_handler.h index 08d93025b27..0d8b3f2ad63 100644 --- a/chromium/components/download/public/common/download_response_handler.h +++ b/chromium/components/download/public/common/download_response_handler.h @@ -15,6 +15,7 @@ #include "components/download/public/common/download_stream.mojom.h" #include "components/download/public/common/download_url_parameters.h" #include "components/download/public/common/download_utils.h" +#include "mojo/public/cpp/bindings/remote.h" #include "net/cert/cert_status_flags.h" #include "services/network/public/cpp/resource_response.h" #include "services/network/public/mojom/url_loader.mojom.h" @@ -48,7 +49,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler bool is_parallel_request, bool is_transient, bool fetch_error_body, - bool follow_cross_origin_redirects, + network::mojom::RedirectMode cross_origin_redirects, const DownloadUrlParameters::RequestHeadersType& request_headers, const std::string& request_origin, DownloadSource download_source, @@ -90,7 +91,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler net::URLRequest::ReferrerPolicy referrer_policy_; bool is_transient_; bool fetch_error_body_; - bool follow_cross_origin_redirects_; + network::mojom::RedirectMode cross_origin_redirects_; url::Origin first_origin_; DownloadUrlParameters::RequestHeadersType request_headers_; std::string request_origin_; @@ -104,8 +105,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler // The abort reason if this class decides to block the download. DownloadInterruptReason abort_reason_; - // Mojo interface ptr to send the completion status to the download sink. - mojom::DownloadStreamClientPtr client_ptr_; + // Mojo interface remote to send the completion status to the download sink. + mojo::Remote<mojom::DownloadStreamClient> client_remote_; // Whether the download is running in background mode. bool is_background_mode_; diff --git a/chromium/components/download/public/common/download_save_info.h b/chromium/components/download/public/common/download_save_info.h index 9f249c7bda6..f2e0043b3a1 100644 --- a/chromium/components/download/public/common/download_save_info.h +++ b/chromium/components/download/public/common/download_save_info.h @@ -56,12 +56,6 @@ struct COMPONENTS_DOWNLOAD_EXPORT DownloadSaveInfo { // used for validation purpose. int64_t file_offset = -1; - // The number of the bytes to download from |offset|. - // Ask to retrieve segment of the download file when length is greater than 0. - // Request the rest of the file starting from |offset|, when length is - // |kLengthFullContent|. - int64_t length = kLengthFullContent; - // The state of the hash. If specified, this hash state must indicate the // state of the partial file for the first |offset| bytes. std::unique_ptr<crypto::SecureHash> hash_state; diff --git a/chromium/components/download/public/common/download_stats.h b/chromium/components/download/public/common/download_stats.h index ffafffa18b8..49a45d98ac6 100644 --- a/chromium/components/download/public/common/download_stats.h +++ b/chromium/components/download/public/common/download_stats.h @@ -463,6 +463,15 @@ COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadResumed( COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadConnectionInfo( net::HttpResponseInfo::ConnectionInfo connection_info); +COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadManagerCreationTimeSinceStartup( + base::TimeDelta elapsed_time); + +COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadManagerMemoryUsage( + size_t bytes_used); + +COMPONENTS_DOWNLOAD_EXPORT void RecordParallelRequestCreationFailure( + DownloadInterruptReason reason); + #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 diff --git a/chromium/components/download/public/common/download_stream.mojom b/chromium/components/download/public/common/download_stream.mojom index 5083aaa903f..d3636948f22 100644 --- a/chromium/components/download/public/common/download_stream.mojom +++ b/chromium/components/download/public/common/download_stream.mojom @@ -24,5 +24,5 @@ interface DownloadStreamClient { struct DownloadStreamHandle { handle<data_pipe_consumer> stream; - DownloadStreamClient& client_request; -};
\ No newline at end of file + pending_receiver<DownloadStreamClient> client_receiver; +}; diff --git a/chromium/components/download/public/common/download_task_runner.h b/chromium/components/download/public/common/download_task_runner.h index 5f5879004e9..35ec925ea26 100644 --- a/chromium/components/download/public/common/download_task_runner.h +++ b/chromium/components/download/public/common/download_task_runner.h @@ -23,6 +23,14 @@ COMPONENTS_DOWNLOAD_EXPORT void SetIOTaskRunner( COMPONENTS_DOWNLOAD_EXPORT scoped_refptr<base::SingleThreadTaskRunner> GetIOTaskRunner(); +// Sets the task runner for download DB, must be called on UI thread. +COMPONENTS_DOWNLOAD_EXPORT void SetDownloadDBTaskRunnerForTesting( + const scoped_refptr<base::SequencedTaskRunner>& task_runner); + +// Gets the task runner for download DB, must be called on UI thread. +COMPONENTS_DOWNLOAD_EXPORT scoped_refptr<base::SequencedTaskRunner> +GetDownloadDBTaskRunnerForTesting(); + } // namespace download #endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_TASK_RUNNER_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..49ae91b243b 100644 --- a/chromium/components/download/public/common/download_url_parameters.cc +++ b/chromium/components/download/public/common/download_url_parameters.cc @@ -35,7 +35,7 @@ DownloadUrlParameters::DownloadUrlParameters( frame_tree_node_id_(-1), url_(url), do_not_prompt_for_login_(false), - follow_cross_origin_redirects_(true), + cross_origin_redirects_(network::mojom::RedirectMode::kFollow), fetch_error_body_(false), transient_(false), traffic_annotation_(traffic_annotation), diff --git a/chromium/components/download/public/common/download_url_parameters.h b/chromium/components/download/public/common/download_url_parameters.h index f276eddce7a..2ff090834bf 100644 --- a/chromium/components/download/public/common/download_url_parameters.h +++ b/chromium/components/download/public/common/download_url_parameters.h @@ -18,9 +18,11 @@ #include "components/download/public/common/download_interrupt_reasons.h" #include "components/download/public/common/download_save_info.h" #include "components/download/public/common/download_source.h" +#include "net/base/network_isolation_key.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request.h" #include "services/network/public/cpp/resource_request_body.h" +#include "services/network/public/mojom/fetch_api.mojom-shared.h" #include "storage/browser/blob/blob_data_handle.h" #include "url/gurl.h" #include "url/origin.h" @@ -55,7 +57,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { // are not created when a resource throttle or a resource handler blocks the // download request. I.e. the download triggered a warning of some sort and // the user chose to not to proceed with the download as a result. - typedef base::Callback<void(DownloadItem*, DownloadInterruptReason)> + typedef base::OnceCallback<void(DownloadItem*, DownloadInterruptReason)> OnStartedCallback; typedef std::pair<std::string, std::string> RequestHeadersNameValuePair; @@ -153,7 +155,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { void set_post_id(int64_t post_id) { post_id_ = post_id; } // See OnStartedCallback above. - void set_callback(const OnStartedCallback& callback) { callback_ = callback; } + void set_callback(OnStartedCallback callback) { + callback_ = std::move(callback); + } // If not empty, specifies the full target path for the download. This value // overrides the filename suggested by a Content-Disposition headers. It @@ -171,15 +175,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { // If |offset| is non-zero, then a byte range request will be issued to fetch // the range of bytes starting at |offset|. - // Use |set_length| to specify the last byte position, or the range - // request will be "Range:bytes={offset}-" to retrieve the rest of the file. void set_offset(int64_t offset) { save_info_.offset = offset; } - // When |length| > 0, the range of bytes will be from - // |save_info_.offset| to |save_info_.offset| + |length| - 1. - // See |DownloadSaveInfo.length|. - void set_length(int64_t length) { save_info_.length = length; } - // Sets the offset to start writing to the file. If set, The data received // before |file_offset| are discarded or are used for validation purpose. void set_file_offset(int64_t file_offset) { @@ -210,11 +207,13 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { do_not_prompt_for_login_ = do_not_prompt; } - // If |follow_cross_origin_redirects| is true, we will follow cross origin - // redirects while downloading, otherwise, we'll attempt to navigate to the - // URL or cancel the download. - void set_follow_cross_origin_redirects(bool follow_cross_origin_redirects) { - follow_cross_origin_redirects_ = follow_cross_origin_redirects; + // If |cross_origin_redirects| is kFollow, we will follow cross origin + // redirects while downloading. If it is kManual, then we'll attempt to + // navigate to the URL or cancel the download. If it is kError, then we will + // fail the download (kFail). + void set_cross_origin_redirects( + network::mojom::RedirectMode cross_origin_redirects) { + cross_origin_redirects_ = cross_origin_redirects; } // Sets whether to download the response body even if the server returns @@ -257,7 +256,12 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { require_safety_checks_ = require_safety_checks; } - const OnStartedCallback& callback() const { return callback_; } + void set_network_isolation_key( + const net::NetworkIsolationKey& network_isolation_key) { + network_isolation_key_ = network_isolation_key; + } + + OnStartedCallback& callback() { return callback_; } bool content_initiated() const { return content_initiated_; } const std::string& last_modified() const { return last_modified_; } const std::string& etag() const { return etag_; } @@ -296,20 +300,22 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { return save_info_.suggested_name; } int64_t offset() const { return save_info_.offset; } - int64_t length() const { return save_info_.length; } const std::string& hash_of_partial_file() const { return save_info_.hash_of_partial_file; } bool prompt() const { return save_info_.prompt_for_save_location; } const GURL& url() const { return url_; } bool do_not_prompt_for_login() const { return do_not_prompt_for_login_; } - bool follow_cross_origin_redirects() const { - return follow_cross_origin_redirects_; + network::mojom::RedirectMode cross_origin_redirects() const { + return cross_origin_redirects_; } bool fetch_error_body() const { return fetch_error_body_; } bool is_transient() const { return transient_; } std::string guid() const { return guid_; } bool require_safety_checks() const { return require_safety_checks_; } + const net::NetworkIsolationKey& network_isolation_key() const { + return network_isolation_key_; + } // STATE CHANGING: All save_info_ sub-objects will be in an indeterminate // state following this call. @@ -348,7 +354,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { DownloadSaveInfo save_info_; GURL url_; bool do_not_prompt_for_login_; - bool follow_cross_origin_redirects_; + network::mojom::RedirectMode cross_origin_redirects_; bool fetch_error_body_; bool transient_; std::string guid_; @@ -357,6 +363,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters { DownloadSource download_source_; UploadProgressCallback upload_callback_; bool require_safety_checks_; + net::NetworkIsolationKey network_isolation_key_; 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 d48f61ae8ed..737c193c819 100644 --- a/chromium/components/download/public/common/download_utils.h +++ b/chromium/components/download/public/common/download_utils.h @@ -5,6 +5,8 @@ #ifndef COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_UTILS_H_ #define COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_UTILS_H_ +#include <memory> + #include "components/download/database/download_db_entry.h" #include "components/download/database/in_progress/download_entry.h" #include "components/download/public/common/download_export.h" @@ -75,7 +77,7 @@ CreateDownloadDBEntryFromItem(const DownloadItemImpl& item); // Helper function to convert DownloadDBEntry to DownloadEntry. // TODO(qinmin): remove this function after DownloadEntry is deprecated. -COMPONENTS_DOWNLOAD_EXPORT base::Optional<DownloadEntry> +COMPONENTS_DOWNLOAD_EXPORT std::unique_ptr<DownloadEntry> CreateDownloadEntryFromDownloadDBEntry(base::Optional<DownloadDBEntry> entry); COMPONENTS_DOWNLOAD_EXPORT uint64_t GetUniqueDownloadId(); @@ -98,10 +100,10 @@ COMPONENTS_DOWNLOAD_EXPORT bool IsDownloadDone( COMPONENTS_DOWNLOAD_EXPORT bool DeleteDownloadedFile( const base::FilePath& path); -// Rename downloaded file from |oldpath| to newname. -COMPONENTS_DOWNLOAD_EXPORT download::DownloadItem::DownloadRenameResult +// Rename downloaded file |from_path| to a new |display_name|. +COMPONENTS_DOWNLOAD_EXPORT DownloadItem::DownloadRenameResult RenameDownloadedFile(const base::FilePath& from_path, - const base::FilePath& to_path); + const base::FilePath& display_name); // Finch parameter key value for number of bytes used for content validation // during resumption. @@ -111,6 +113,13 @@ constexpr char kDownloadContentValidationLengthFinchKey[] = // Get the number of bytes to validate from finch configuration. int64_t GetDownloadValidationLengthConfig(); +// Finch parameter key value for the time to delete expired downloads in days. +constexpr char kExpiredDownloadDeleteTimeFinchKey[] = + "expired_download_delete_days"; + +// Returns the time to delete expired downloads. +COMPONENTS_DOWNLOAD_EXPORT base::TimeDelta GetExpiredDownloadDeleteTime(); + } // namespace download #endif // COMPONENTS_DOWNLOAD_PUBLIC_COMMON_DOWNLOAD_UTILS_H_ diff --git a/chromium/components/download/public/common/in_progress_download_manager.h b/chromium/components/download/public/common/in_progress_download_manager.h index 25d2058628b..42b2f5a5353 100644 --- a/chromium/components/download/public/common/in_progress_download_manager.h +++ b/chromium/components/download/public/common/in_progress_download_manager.h @@ -76,7 +76,7 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager // create the DownloadItem from in-progress cache. virtual void StartDownloadItem( std::unique_ptr<DownloadCreateInfo> info, - const DownloadUrlParameters::OnStartedCallback& on_started, + DownloadUrlParameters::OnStartedCallback on_started, StartDownloadItemCallback callback) {} }; @@ -124,13 +124,12 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info); - void StartDownload( - std::unique_ptr<DownloadCreateInfo> info, - std::unique_ptr<InputStream> stream, - URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr - url_loader_factory_provider, - DownloadJob::CancelRequestCallback cancel_request_callback, - const DownloadUrlParameters::OnStartedCallback& on_started); + void StartDownload(std::unique_ptr<DownloadCreateInfo> info, + std::unique_ptr<InputStream> stream, + URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr + url_loader_factory_provider, + DownloadJob::CancelRequestCallback cancel_request_callback, + DownloadUrlParameters::OnStartedCallback on_started); // Shutting down the manager and stop all downloads. void ShutDown(); @@ -142,8 +141,6 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager const GURL& site_url) override; bool ShouldOpenDownload(DownloadItemImpl* item, const ShouldOpenDownloadCallback& callback) override; - base::Optional<DownloadEntry> GetInProgressEntry( - DownloadItemImpl* download) override; void ReportBytesWasted(DownloadItemImpl* download) override; // Called to remove an in-progress download. @@ -215,7 +212,7 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr url_loader_factory_provider, UrlDownloadHandler* downloader, - const DownloadUrlParameters::OnStartedCallback& callback) override; + DownloadUrlParameters::OnStartedCallback callback) override; void OnUrlDownloadStopped(UrlDownloadHandler* downloader) override; void OnUrlDownloadHandlerCreated( UrlDownloadHandler::UniqueUrlDownloadHandlerPtr downloader) override; @@ -261,12 +258,6 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager // Cache for DownloadDB. std::unique_ptr<DownloadDBCache> download_db_cache_; - using DownloadEntryMap = std::map<std::string, DownloadEntry>; - // DownloadEntries to provide persistent information when creating download - // item. - // TODO(qinmin): remove this once features::kDownloadDBForNewDownloads is - // enabled by default. - DownloadEntryMap download_entries_; // listens to information about in-progress download items. std::unique_ptr<DownloadItem::Observer> in_progress_download_observer_; @@ -303,9 +294,6 @@ class COMPONENTS_DOWNLOAD_EXPORT InProgressDownloadManager // Used to check if the URL is safe. URLSecurityPolicy url_security_policy_; - // Whether this object uses an empty database and no history will be saved. - bool use_empty_db_; - // Connector to the service manager. service_manager::Connector* connector_; diff --git a/chromium/components/download/public/common/mock_download_file.cc b/chromium/components/download/public/common/mock_download_file.cc index 4d24d9e54a9..601f4fe75c8 100644 --- a/chromium/components/download/public/common/mock_download_file.cc +++ b/chromium/components/download/public/common/mock_download_file.cc @@ -32,11 +32,10 @@ MockDownloadFile::MockDownloadFile() { MockDownloadFile::~MockDownloadFile() {} void MockDownloadFile::AddInputStream(std::unique_ptr<InputStream> input_stream, - int64_t offset, - int64_t length) { + int64_t offset) { // Gmock currently can't mock method that takes move-only parameters, // delegate the EXPECT_CALL count to |DoAddByteStream|. - DoAddInputStream(input_stream.get(), offset, length); + DoAddInputStream(input_stream.get(), offset); } } // namespace download diff --git a/chromium/components/download/public/common/mock_download_file.h b/chromium/components/download/public/common/mock_download_file.h index 585223e493a..917e534c101 100644 --- a/chromium/components/download/public/common/mock_download_file.h +++ b/chromium/components/download/public/common/mock_download_file.h @@ -35,10 +35,9 @@ class MockDownloadFile : public DownloadFile { const DownloadItem::ReceivedSlices& received_slices, bool is_parallelizable)); void AddInputStream(std::unique_ptr<InputStream> input_stream, - int64_t offset, - int64_t length) override; - MOCK_METHOD3(DoAddInputStream, - void(InputStream* input_stream, int64_t offset, int64_t length)); + int64_t offset) override; + MOCK_METHOD2(DoAddInputStream, + void(InputStream* input_stream, int64_t offset)); MOCK_METHOD2(OnResponseCompleted, void(int64_t offset, DownloadInterruptReason status)); MOCK_METHOD2(AppendDataToFile, diff --git a/chromium/components/download/public/common/mock_download_item.h b/chromium/components/download/public/common/mock_download_item.h index 09ea72f712a..a37d5f946e5 100644 --- a/chromium/components/download/public/common/mock_download_item.h +++ b/chromium/components/download/public/common/mock_download_item.h @@ -14,6 +14,7 @@ #include "base/observer_list.h" #include "base/optional.h" #include "base/time/time.h" +#include "components/download/public/common/download_danger_type.h" #include "components/download/public/common/download_interrupt_reasons.h" #include "components/download/public/common/download_item.h" #include "testing/gmock/include/gmock/gmock.h" @@ -123,6 +124,7 @@ class MockDownloadItem : public DownloadItem { MOCK_CONST_METHOD1(DebugString, std::string(bool)); MOCK_METHOD1(SimulateErrorForTesting, void(DownloadInterruptReason)); MOCK_METHOD2(Rename, void(const base::FilePath&, RenameDownloadCallback)); + MOCK_METHOD1(OnAsyncScanningCompleted, void(DownloadDangerType)); private: base::ObserverList<Observer>::Unchecked observers_; diff --git a/chromium/components/download/public/common/mock_download_item_impl.cc b/chromium/components/download/public/common/mock_download_item_impl.cc index 05b6a9117fc..9a47c3aefe6 100644 --- a/chromium/components/download/public/common/mock_download_item_impl.cc +++ b/chromium/components/download/public/common/mock_download_item_impl.cc @@ -36,7 +36,8 @@ MockDownloadItemImpl::MockDownloadItemImpl(DownloadItemImplDelegate* delegate) false, base::Time(), true, - DownloadItem::ReceivedSlices()) {} + DownloadItem::ReceivedSlices(), + nullptr /* download_entry */) {} MockDownloadItemImpl::~MockDownloadItemImpl() = default; 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 a69e556e449..c5d7a5f89e4 100644 --- a/chromium/components/download/public/common/simple_download_manager_coordinator.h +++ b/chromium/components/download/public/common/simple_download_manager_coordinator.h @@ -12,6 +12,7 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "base/time/time.h" #include "components/download/public/common/download_export.h" #include "components/download/public/common/download_url_parameters.h" #include "components/download/public/common/simple_download_manager.h" @@ -35,7 +36,8 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManagerCoordinator Observer() = default; virtual ~Observer() = default; - virtual void OnManagerGoingDown() {} + virtual void OnManagerGoingDown( + SimpleDownloadManagerCoordinator* coordinator) {} virtual void OnDownloadsInitialized(bool active_downloads_only) {} virtual void OnDownloadCreated(DownloadItem* item) {} @@ -46,7 +48,8 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManagerCoordinator using DownloadWhenFullManagerStartsCallBack = base::RepeatingCallback<void(std::unique_ptr<DownloadUrlParameters>)>; SimpleDownloadManagerCoordinator(const DownloadWhenFullManagerStartsCallBack& - download_when_full_manager_starts_cb); + download_when_full_manager_starts_cb, + bool record_full_download_manager_delay); ~SimpleDownloadManagerCoordinator() override; void AddObserver(Observer* observer); @@ -107,6 +110,9 @@ class COMPONENTS_DOWNLOAD_EXPORT SimpleDownloadManagerCoordinator // Observers that want to be notified of changes to the set of downloads. base::ObserverList<Observer>::Unchecked observers_; + // Time when this object was created. + base::TimeTicks creation_time_ticks_; + base::WeakPtrFactory<SimpleDownloadManagerCoordinator> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(SimpleDownloadManagerCoordinator); diff --git a/chromium/components/download/public/common/stream_handle_input_stream.h b/chromium/components/download/public/common/stream_handle_input_stream.h index a54097e9007..f490b773970 100644 --- a/chromium/components/download/public/common/stream_handle_input_stream.h +++ b/chromium/components/download/public/common/stream_handle_input_stream.h @@ -8,7 +8,7 @@ #include "components/download/public/common/download_export.h" #include "components/download/public/common/download_stream.mojom.h" #include "components/download/public/common/input_stream.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/system/simple_watcher.h" namespace download { @@ -40,7 +40,7 @@ class COMPONENTS_DOWNLOAD_EXPORT StreamHandleInputStream // Objects for consuming a mojo data pipe. mojom::DownloadStreamHandlePtr stream_handle_; std::unique_ptr<mojo::SimpleWatcher> handle_watcher_; - std::unique_ptr<mojo::Binding<mojom::DownloadStreamClient>> binding_; + std::unique_ptr<mojo::Receiver<mojom::DownloadStreamClient>> receiver_; // Whether the producer has completed handling the response. bool is_response_completed_; diff --git a/chromium/components/download/public/common/url_download_handler.h b/chromium/components/download/public/common/url_download_handler.h index c2d514914bd..3f4a9d169fe 100644 --- a/chromium/components/download/public/common/url_download_handler.h +++ b/chromium/components/download/public/common/url_download_handler.h @@ -28,7 +28,7 @@ class COMPONENTS_DOWNLOAD_EXPORT UrlDownloadHandler { URLLoaderFactoryProvider::URLLoaderFactoryProviderPtr url_loader_factory_provider, UrlDownloadHandler* downloader, - const DownloadUrlParameters::OnStartedCallback& callback) = 0; + DownloadUrlParameters::OnStartedCallback callback) = 0; // Called after the connection is cancelled or finished. virtual void OnUrlDownloadStopped(UrlDownloadHandler* downloader) = 0; diff --git a/chromium/components/download/public/task/BUILD.gn b/chromium/components/download/public/task/BUILD.gn index f98a9b294f4..7342a2fd92a 100644 --- a/chromium/components/download/public/task/BUILD.gn +++ b/chromium/components/download/public/task/BUILD.gn @@ -30,7 +30,7 @@ if (is_android) { deps = [ "//base:base_java", - "//third_party/android_deps:com_android_support_support_annotations_java", + "//third_party/android_deps:androidx_annotation_annotation_java", ] } |