diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-13 15:05:36 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2019-02-14 10:33:47 +0000 |
commit | e684a3455bcc29a6e3e66a004e352dea4e1141e7 (patch) | |
tree | d55b4003bde34d7d05f558f02cfd82b2a66a7aac /chromium/content/browser/download | |
parent | 2b94bfe47ccb6c08047959d1c26e392919550e86 (diff) | |
download | qtwebengine-chromium-e684a3455bcc29a6e3e66a004e352dea4e1141e7.tar.gz |
BASELINE: Update Chromium to 72.0.3626.110 and Ninja to 1.9.0
Change-Id: Ic57220b00ecc929a893c91f5cc552f5d3e99e922
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/content/browser/download')
13 files changed, 437 insertions, 97 deletions
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc index 97421cd8745..4fcfe051d6c 100644 --- a/chromium/content/browser/download/download_browsertest.cc +++ b/chromium/content/browser/download/download_browsertest.cc @@ -1686,6 +1686,72 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RedirectWhileResume) { EXPECT_GT(parameters.size, requests[2]->transferred_byte_count); } +// Verify that DownloadUrl can support URL redirect. +IN_PROC_BROWSER_TEST_F(DownloadContentTest, RedirectDownload) { + // Setup a redirect chain with two URL. + GURL first_url = embedded_test_server()->GetURL("example.com", "/first-url"); + GURL download_url = + embedded_test_server()->GetURL("example.com", "/download"); + TestDownloadHttpResponse::StartServingStaticResponse( + base::StringPrintf("HTTP/1.1 302 Redirect\r\n" + "Location: %s\r\n\r\n", + download_url.spec().c_str()), + first_url); + TestDownloadHttpResponse::StartServing(TestDownloadHttpResponse::Parameters(), + download_url); + + // Start a download and explicitly specify to support redirect. + std::unique_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1)); + auto download_parameters = std::make_unique<download::DownloadUrlParameters>( + first_url, TRAFFIC_ANNOTATION_FOR_TESTS); + download_parameters->set_follow_cross_origin_redirects(true); + DownloadManagerForShell(shell())->DownloadUrl(std::move(download_parameters)); + observer->WaitForFinished(); + + // Verify download is done. + std::vector<download::DownloadItem*> downloads; + DownloadManagerForShell(shell())->GetAllDownloads(&downloads); + EXPECT_EQ(1u, downloads.size()); + EXPECT_EQ(download::DownloadItem::COMPLETE, downloads[0]->GetState()); +} + +// Verify that DownloadUrl() to URL with unsafe scheme should fail. +IN_PROC_BROWSER_TEST_F(DownloadContentTest, RedirectUnsafeDownload) { + // Setup a redirect chain with two URL. + GURL first_url = embedded_test_server()->GetURL("example.com", "/first-url"); + GURL unsafe_url = GURL("unsafe:///etc/passwd"); + TestDownloadHttpResponse::StartServingStaticResponse( + base::StringPrintf("HTTP/1.1 302 Redirect\r\n" + "Location: %s\r\n\r\n", + unsafe_url.spec().c_str()), + first_url); + TestDownloadHttpResponse::StartServing(TestDownloadHttpResponse::Parameters(), + unsafe_url); + + // Start a download and explicitly specify to support redirect. + DownloadManager* download_manager = DownloadManagerForShell(shell()); + std::unique_ptr<DownloadTestObserverInterrupted> observer = + std::make_unique<DownloadTestObserverInterrupted>( + download_manager, 1, + DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); + auto download_parameters = std::make_unique<download::DownloadUrlParameters>( + first_url, TRAFFIC_ANNOTATION_FOR_TESTS); + download_parameters->set_follow_cross_origin_redirects(true); + download_manager->DownloadUrl(std::move(download_parameters)); + observer->WaitForFinished(); + + // Verify download failed. + std::vector<download::DownloadItem*> downloads; + DownloadManagerForShell(shell())->GetAllDownloads(&downloads); + EXPECT_EQ(1u, downloads.size()); + EXPECT_EQ(download::DownloadItem::INTERRUPTED, downloads[0]->GetState()); + + // The interrupt reason must match, notice the embedded test server used in + // tests may also fail even if the download passed the security check. + EXPECT_EQ(download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST, + downloads[0]->GetLastReason()); +} + // If the server response for the resumption request specifies a bad range (i.e. // not the range that was requested or an invalid or missing Content-Range // header), then the download should be marked as interrupted again without @@ -3237,8 +3303,8 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeNetworkError) { IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeInvalidURL) { GURL url = embedded_test_server()->GetURL( "/download/download-attribute.html?target=about:version"); - auto observer = std::make_unique<content::TestNavigationObserver>( - GURL(url::kAboutBlankURL)); + auto observer = + std::make_unique<content::TestNavigationObserver>(GURL(kBlockedURL)); observer->WatchExistingWebContents(); observer->StartWatchingNewWebContents(); NavigateToURL(shell(), url); diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc index a0220133cd2..74940229a0d 100644 --- a/chromium/content/browser/download/download_manager_impl.cc +++ b/chromium/content/browser/download/download_manager_impl.cc @@ -23,7 +23,6 @@ #include "base/task/post_task.h" #include "build/build_config.h" #include "components/download/database/in_progress/download_entry.h" -#include "components/download/database/in_progress/in_progress_cache_impl.h" #include "components/download/public/common/download_create_info.h" #include "components/download/public/common/download_features.h" #include "components/download/public/common/download_file.h" @@ -40,7 +39,7 @@ #include "components/download/public/common/url_download_handler_factory.h" #include "content/browser/byte_stream.h" #include "content/browser/child_process_security_policy_impl.h" -#include "content/browser/devtools/render_frame_devtools_agent_host.h" +#include "content/browser/devtools/devtools_instrumentation.h" #include "content/browser/download/byte_stream_input_stream.h" #include "content/browser/download/download_resource_handler.h" #include "content/browser/download/download_utils.h" @@ -61,13 +60,13 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/browser/download_item_utils.h" #include "content/public/browser/download_manager_delegate.h" +#include "content/public/browser/download_request_utils.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/resource_context.h" #include "content/public/browser/web_contents_delegate.h" -#include "content/public/common/browser_side_navigation_policy.h" #include "content/public/common/origin_util.h" #include "content/public/common/previews_state.h" #include "content/public/common/referrer.h" @@ -89,6 +88,17 @@ namespace content { namespace { +#if defined(OS_ANDROID) +void DeleteDownloadedFileOnUIThread(const base::FilePath& file_path) { + if (!file_path.empty()) { + download::GetDownloadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(base::IgnoreResult(&download::DeleteDownloadedFile), + file_path)); + } +} +#endif + StoragePartitionImpl* GetStoragePartition(BrowserContext* context, int render_process_id, int render_frame_id) { @@ -105,18 +115,6 @@ StoragePartitionImpl* GetStoragePartition(BrowserContext* context, BrowserContext::GetStoragePartition(context, site_instance)); } -bool CanRequestURLFromRenderer(int render_process_id, GURL url) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - // Check if the renderer is permitted to request the requested URL. - if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL( - render_process_id, url)) { - DVLOG(1) << "Denied unauthorized download request for " - << url.possibly_invalid_spec(); - return false; - } - return true; -} - void OnDownloadStarted( download::DownloadItemImpl* download, const download::DownloadUrlParameters::OnStartedCallback& on_started) { @@ -279,7 +277,7 @@ CreateDownloadURLLoaderFactoryGetter(StoragePartitionImpl* storage_partition, network::mojom::URLLoaderFactoryPtrInfo devtools_factory_ptr_info; network::mojom::URLLoaderFactoryRequest devtools_factory_request = MakeRequest(&devtools_factory_ptr_info); - if (RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory( + if (devtools_instrumentation::WillCreateURLLoaderFactory( static_cast<RenderFrameHostImpl*>(rfh), true, is_download, &devtools_factory_request)) { proxy_factory_ptr_info = std::move(devtools_factory_ptr_info); @@ -305,6 +303,9 @@ DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context) browser_context_->RetriveInProgressDownloadManager()), next_download_id_(download::DownloadItem::kInvalidId), is_history_download_id_retrieved_(false), + should_persist_new_download_(false), + cancelled_download_cleared_from_history_(0), + interrupted_download_cleared_from_history_(0), weak_factory_(this) { DCHECK(browser_context); download::SetIOTaskRunner( @@ -317,7 +318,8 @@ DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context) std::make_unique<download::InProgressDownloadManager>( this, IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(), - base::BindRepeating(&IsOriginSecure)); + base::BindRepeating(&IsOriginSecure), + base::BindRepeating(&DownloadRequestUtils::IsURLSafe)); } else { in_progress_manager_->set_delegate(this); in_progress_manager_->set_download_start_observer(nullptr); @@ -367,7 +369,7 @@ void DownloadManagerImpl::GetNextId(GetNextIdCallback callback) { base::BindRepeating(&DownloadManagerImpl::OnHistoryNextIdRetrived, weak_factory_.GetWeakPtr())); } else { - OnHistoryNextIdRetrived(download::DownloadItem::kInvalidId + 1); + OnHistoryNextIdRetrived(download::DownloadItem::kInvalidId); } } } @@ -386,6 +388,10 @@ void DownloadManagerImpl::SetNextId(uint32_t next_id) { void DownloadManagerImpl::OnHistoryNextIdRetrived(uint32_t next_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); is_history_download_id_retrieved_ = true; + if (next_id == download::DownloadItem::kInvalidId) + next_id++; + else + should_persist_new_download_ = true; SetNextId(next_id); } @@ -544,19 +550,23 @@ void DownloadManagerImpl::OnInProgressDownloadManagerInitialized() { in_progress_downloads = in_progress_manager_->TakeInProgressDownloads(); uint32_t max_id = download::DownloadItem::kInvalidId; for (auto& download : in_progress_downloads) { - DCHECK(!base::ContainsKey(downloads_by_guid_, download->GetGuid())); - DCHECK(!base::ContainsKey(downloads_, download->GetId())); - DownloadItemUtils::AttachInfo(download.get(), GetBrowserContext(), nullptr); - download::DownloadItemImpl* item = download.get(); - item->SetDelegate(this); - downloads_by_guid_[download->GetGuid()] = item; uint32_t id = download->GetId(); - downloads_[id] = std::move(download); + if (base::ContainsKey(in_progress_downloads_, id)) { + in_progress_manager_->RemoveInProgressDownload(download->GetGuid()); + continue; + } if (id > max_id) max_id = id; - for (auto& observer : observers_) - observer.OnDownloadCreated(this, item); - DVLOG(20) << __func__ << "() download = " << item->DebugString(true); +#if defined(OS_ANDROID) + // On android, clean up cancelled and non resumable interrupted downloads. + if (ShouldClearDownloadFromDB(download->GetURL(), download->GetState(), + download->GetLastReason())) { + cleared_download_guids_on_startup_.insert(download->GetGuid()); + DeleteDownloadedFileOnUIThread(download->GetFullPath()); + continue; + } +#endif // defined(OS_ANDROID) + in_progress_downloads_[id] = std::move(download); } PostInitialization(DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE); SetNextId(max_id + 1); @@ -572,7 +582,8 @@ void DownloadManagerImpl::StartDownloadItem( download::DownloadItemImpl* download = downloads_by_guid_[info->guid]; if (!download || download->GetState() == download::DownloadItem::CANCELLED) download = nullptr; - std::move(callback).Run(std::move(info), download); + std::move(callback).Run(std::move(info), download, + should_persist_new_download_); OnDownloadStarted(download, on_started); } else { GetNextId(base::BindOnce(&DownloadManagerImpl::CreateNewDownloadItemToStart, @@ -589,7 +600,8 @@ void DownloadManagerImpl::CreateNewDownloadItemToStart( DCHECK_CURRENTLY_ON(BrowserThread::UI); download::DownloadItemImpl* download = CreateActiveItem(id, *info); - std::move(callback).Run(std::move(info), download); + std::move(callback).Run(std::move(info), download, + should_persist_new_download_); // For new downloads, we notify here, rather than earlier, so that // the download_file is bound to download and all the usual // setters (e.g. Cancel) work. @@ -703,11 +715,7 @@ void DownloadManagerImpl::CreateSavePackageDownloadItemWithId( DownloadItemUtils::AttachInfo(download_item, GetBrowserContext(), WebContentsImpl::FromRenderFrameHostID( render_process_id, render_frame_id)); - downloads_[download_item->GetId()] = base::WrapUnique(download_item); - DCHECK(!base::ContainsKey(downloads_by_guid_, download_item->GetGuid())); - downloads_by_guid_[download_item->GetGuid()] = download_item; - for (auto& observer : observers_) - observer.OnDownloadCreated(this, download_item); + OnDownloadCreated(base::WrapUnique(download_item)); if (!item_created.is_null()) item_created.Run(download_item); } @@ -943,29 +951,55 @@ download::DownloadItem* DownloadManagerImpl::CreateDownloadItem( base::Time last_access_time, bool transient, const std::vector<download::DownloadItem::ReceivedSlice>& received_slices) { - if (base::ContainsKey(downloads_, id)) { - // If a completed or cancelled download item is already in the history db, - // remove it from the in-progress db. - if (state == download::DownloadItem::COMPLETE || - state == download::DownloadItem::CANCELLED) { - in_progress_manager_->RemoveInProgressDownload(guid); - } else { - return downloads_[id].get(); - } + // Retrive the in-progress download if it exists. Notice that this also + // removes it from |in_progress_downloads_|. + auto in_progress_download = RetrieveInProgressDownload(id); +#if defined(OS_ANDROID) + // On Android, there is no way to interact with cancelled or non-resumable + // download. Simply returning null and don't store them in this class to + // reduce memory usage. + if (cleared_download_guids_on_startup_.find(guid) != + cleared_download_guids_on_startup_.end()) { + return nullptr; + } + if (url_chain.empty() || + ShouldClearDownloadFromDB(url_chain.back(), state, interrupt_reason)) { + DeleteDownloadedFileOnUIThread(current_path); + return nullptr; } - download::DownloadItemImpl* item = item_factory_->CreatePersistedItem( +#endif + auto item = base::WrapUnique(item_factory_->CreatePersistedItem( this, guid, id, current_path, target_path, url_chain, referrer_url, site_url, tab_url, tab_refererr_url, mime_type, original_mime_type, start_time, end_time, etag, last_modified, received_bytes, total_bytes, hash, state, danger_type, interrupt_reason, opened, last_access_time, - transient, received_slices); - DownloadItemUtils::AttachInfo(item, GetBrowserContext(), nullptr); - downloads_[id] = base::WrapUnique(item); - downloads_by_guid_[guid] = item; + transient, received_slices)); + if (in_progress_download) { + // If the download item from history db is already in terminal state, + // remove it from the in-progress db. Otherwise, use the in-progress db one. + if (item->IsDone()) { + in_progress_manager_->RemoveInProgressDownload(guid); + } else { + item = std::move(in_progress_download); + item->SetDelegate(this); + } + } + download::DownloadItemImpl* download = item.get(); + DownloadItemUtils::AttachInfo(download, GetBrowserContext(), nullptr); + OnDownloadCreated(std::move(item)); + return download; +} + +void DownloadManagerImpl::OnDownloadCreated( + std::unique_ptr<download::DownloadItemImpl> download) { + DCHECK(!base::ContainsKey(downloads_, download->GetId())); + DCHECK(!base::ContainsKey(downloads_by_guid_, download->GetGuid())); + download::DownloadItemImpl* item = download.get(); + downloads_[item->GetId()] = std::move(download); + downloads_by_guid_[item->GetGuid()] = item; for (auto& observer : observers_) observer.OnDownloadCreated(this, item); DVLOG(20) << __func__ << "() download = " << item->DebugString(true); - return item; } void DownloadManagerImpl::PostInitialization( @@ -980,8 +1014,11 @@ void DownloadManagerImpl::PostInitialization( break; case DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE: in_progress_cache_initialized_ = true; - if (load_history_downloads_cb_) - std::move(load_history_downloads_cb_).Run(); + // Post a task to load downloads from history db. + if (load_history_downloads_cb_) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, std::move(load_history_downloads_cb_)); + } break; case DOWNLOAD_INITIALIZATION_DEPENDENCY_NONE: default: @@ -993,10 +1030,38 @@ void DownloadManagerImpl::PostInitialization( // cache are initialized. initialized_ = history_db_initialized_ && in_progress_cache_initialized_; - if (initialized_) { + if (!initialized_) + return; + +#if defined(OS_ANDROID) + for (const auto& guid : cleared_download_guids_on_startup_) + in_progress_manager_->RemoveInProgressDownload(guid); + if (cancelled_download_cleared_from_history_ > 0) { + UMA_HISTOGRAM_COUNTS_1000( + "MobileDownload.CancelledDownloadRemovedFromHistory", + cancelled_download_cleared_from_history_); + } + + if (interrupted_download_cleared_from_history_ > 0) { + UMA_HISTOGRAM_COUNTS_1000( + "MobileDownload.InterruptedDownloadsRemovedFromHistory", + interrupted_download_cleared_from_history_); + } +#endif + + // If there are still downloads in |in_progress_downloads_|, import them + // now. + for (auto& download : in_progress_downloads_) { + auto item = std::move(download.second); + item->SetDelegate(this); + DownloadItemUtils::AttachInfo(item.get(), GetBrowserContext(), nullptr); + OnDownloadCreated(std::move(item)); + } + in_progress_downloads_.clear(); + + in_progress_manager_->OnAllInprogressDownloadsLoaded(); for (auto& observer : observers_) observer.OnManagerInitialized(); - } } bool DownloadManagerImpl::IsManagerInitialized() const { @@ -1175,7 +1240,8 @@ void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete( } else if (params->url().SchemeIsFile()) { url_loader_factory_getter = base::MakeRefCounted<FileDownloadURLLoaderFactoryGetter>( - params->url(), browser_context_->GetPath()); + params->url(), browser_context_->GetPath(), + BrowserContext::GetSharedCorsOriginAccessList(browser_context_)); } else if (params->url().SchemeIs(content::kChromeUIScheme)) { url_loader_factory_getter = base::MakeRefCounted<WebUIDownloadURLLoaderFactoryGetter>( @@ -1220,8 +1286,8 @@ void DownloadManagerImpl::BeginDownloadInternal( const GURL& site_url) { // Check if the renderer is permitted to request the requested URL. if (params->render_process_host_id() >= 0 && - !CanRequestURLFromRenderer(params->render_process_host_id(), - params->url())) { + !DownloadRequestUtils::IsURLSafe(params->render_process_host_id(), + params->url())) { CreateInterruptedDownload( std::move(params), download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST, @@ -1230,6 +1296,15 @@ void DownloadManagerImpl::BeginDownloadInternal( } if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { + // Ideally everywhere a blob: URL is downloaded a URLLoaderFactory for that + // blob URL is also passed, but since that isn't always the case, create + // a new factory if we don't have one already. + if (!blob_url_loader_factory && params->url().SchemeIsBlob()) { + blob_url_loader_factory = + ChromeBlobStorageContext::URLLoaderFactoryForUrl(browser_context_, + params->url()); + } + auto* rfh = RenderFrameHost::FromID(params->render_process_host_id(), params->render_frame_host_routing_id()); bool content_initiated = params->content_initiated(); @@ -1274,4 +1349,34 @@ bool DownloadManagerImpl::IsNextIdInitialized() const { return is_history_download_id_retrieved_ && in_progress_cache_initialized_; } +#if defined(OS_ANDROID) +bool DownloadManagerImpl::ShouldClearDownloadFromDB( + const GURL& url, + download::DownloadItem::DownloadState state, + download::DownloadInterruptReason reason) { + if (state == download::DownloadItem::CANCELLED) { + ++cancelled_download_cleared_from_history_; + return true; + } + if (reason != download::DOWNLOAD_INTERRUPT_REASON_NONE && + download::GetDownloadResumeMode(url, reason, false /* restart_required */, + false /* user_action_required */) == + download::ResumeMode::INVALID) { + ++interrupted_download_cleared_from_history_; + return true; + } + return false; +} +#endif // defined(OS_ANDROID) + +std::unique_ptr<download::DownloadItemImpl> +DownloadManagerImpl::RetrieveInProgressDownload(uint32_t id) { + if (base::ContainsKey(in_progress_downloads_, id)) { + auto download = std::move(in_progress_downloads_[id]); + in_progress_downloads_.erase(id); + return download; + } + return nullptr; +} + } // namespace content diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h index 5f53beb1236..b94e85cf289 100644 --- a/chromium/content/browser/download/download_manager_impl.h +++ b/chromium/content/browser/download/download_manager_impl.h @@ -20,6 +20,7 @@ #include "base/observer_list.h" #include "base/sequenced_task_runner_helpers.h" #include "base/synchronization/lock.h" +#include "build/build_config.h" #include "components/download/public/common/download_item_impl_delegate.h" #include "components/download/public/common/download_url_parameters.h" #include "components/download/public/common/in_progress_download_manager.h" @@ -132,6 +133,7 @@ class CONTENT_EXPORT DownloadManagerImpl base::OnceClosure load_history_downloads_cb) override; download::DownloadItem* GetDownload(uint32_t id) override; download::DownloadItem* GetDownloadByGuid(const std::string& guid) override; + void GetNextId(GetNextIdCallback callback) override; // UrlDownloadHandler::Delegate implementation. void OnUrlDownloadStarted( @@ -214,11 +216,6 @@ class CONTENT_EXPORT DownloadManagerImpl download::InProgressDownloadManager::StartDownloadItemCallback callback, uint32_t id); - using GetNextIdCallback = base::OnceCallback<void(uint32_t)>; - // Called to get an ID for a new download. |callback| may be called - // synchronously. - void GetNextId(GetNextIdCallback callback); - // Sets the |next_download_id_| if the |next_id| is larger. Runs all the // |id_callbacks_| if both the ID from both history db and in-progress db // are retrieved. @@ -291,6 +288,22 @@ class CONTENT_EXPORT DownloadManagerImpl // Whether |next_download_id_| is initialized. bool IsNextIdInitialized() const; + // Called when a new download is created. + void OnDownloadCreated(std::unique_ptr<download::DownloadItemImpl> download); + + // Retrieves a download from |in_progress_downloads_|. + std::unique_ptr<download::DownloadItemImpl> RetrieveInProgressDownload( + uint32_t id); + +#if defined(OS_ANDROID) + // Check whether a download should be cleared from history. On Android, + // cancelled and non-resumable interrupted download will be cleaned up to + // save memory. + bool ShouldClearDownloadFromDB(const GURL& url, + download::DownloadItem::DownloadState state, + download::DownloadInterruptReason reason); +#endif // defined(OS_ANDROID) + // Factory for creation of downloads items. std::unique_ptr<download::DownloadItemFactory> item_factory_; @@ -349,6 +362,20 @@ class CONTENT_EXPORT DownloadManagerImpl // Whether next download ID from history DB is being retrieved. bool is_history_download_id_retrieved_; + // Whether new download should be persisted to the in progress download + // database. + bool should_persist_new_download_; + + // The download GUIDs that are cleared up on startup. + std::set<std::string> cleared_download_guids_on_startup_; + int cancelled_download_cleared_from_history_; + int interrupted_download_cleared_from_history_; + + // In progress downloads returned by |in_progress_manager_| that are not yet + // added to |downloads_|. + std::unordered_map<uint32_t, std::unique_ptr<download::DownloadItemImpl>> + in_progress_downloads_; + // Callbacks to run once download ID is determined. using IdCallbackVector = std::vector<std::unique_ptr<GetNextIdCallback>>; IdCallbackVector id_callbacks_; diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc index fa6bd708f10..9fd5ebe21be 100644 --- a/chromium/content/browser/download/download_manager_impl_unittest.cc +++ b/chromium/content/browser/download/download_manager_impl_unittest.cc @@ -69,6 +69,10 @@ class ByteStreamReader; namespace { +bool URLAlwaysSafe(int render_process_id, const GURL& url) { + return true; +} + class MockDownloadManagerDelegate : public DownloadManagerDelegate { public: MockDownloadManagerDelegate(); @@ -161,20 +165,20 @@ class MockDownloadItemFactory std::unique_ptr<download::DownloadRequestHandleInterface> request_handle) override; - void set_is_download_started(bool is_download_started) { - is_download_started_ = is_download_started; + void set_is_download_persistent(bool is_download_persistent) { + is_download_persistent_ = is_download_persistent; } private: std::map<uint32_t, download::MockDownloadItemImpl*> items_; download::DownloadItemImplDelegate item_delegate_; - bool is_download_started_; + bool is_download_persistent_; DISALLOW_COPY_AND_ASSIGN(MockDownloadItemFactory); }; MockDownloadItemFactory::MockDownloadItemFactory() - : is_download_started_(false) {} + : is_download_persistent_(false) {} MockDownloadItemFactory::~MockDownloadItemFactory() {} @@ -248,7 +252,45 @@ download::DownloadItemImpl* MockDownloadItemFactory::CreateActiveItem( .WillRepeatedly(Return(download_id)); EXPECT_CALL(*result, GetGuid()) .WillRepeatedly(ReturnRefOfCopy(base::GenerateGUID())); - if (is_download_started_) { + EXPECT_CALL(*result, GetUrlChain()) + .WillRepeatedly(ReturnRefOfCopy(std::vector<GURL>())); + EXPECT_CALL(*result, GetReferrerUrl()) + .WillRepeatedly(ReturnRefOfCopy(GURL())); + EXPECT_CALL(*result, GetTabUrl()).WillRepeatedly(ReturnRefOfCopy(GURL())); + EXPECT_CALL(*result, GetTabReferrerUrl()) + .WillRepeatedly(ReturnRefOfCopy(GURL())); + EXPECT_CALL(*result, GetETag()) + .WillRepeatedly(ReturnRefOfCopy(std::string())); + EXPECT_CALL(*result, GetLastModifiedTime()) + .WillRepeatedly(ReturnRefOfCopy(std::string())); + EXPECT_CALL(*result, GetMimeType()).WillRepeatedly(Return(std::string())); + EXPECT_CALL(*result, GetOriginalMimeType()) + .WillRepeatedly(Return(std::string())); + EXPECT_CALL(*result, GetTotalBytes()).WillRepeatedly(Return(0)); + EXPECT_CALL(*result, GetFullPath()) + .WillRepeatedly( + ReturnRefOfCopy(base::FilePath(FILE_PATH_LITERAL("foo")))); + EXPECT_CALL(*result, GetTargetFilePath()) + .WillRepeatedly( + ReturnRefOfCopy(base::FilePath(FILE_PATH_LITERAL("foo")))); + EXPECT_CALL(*result, GetReceivedBytes()).WillRepeatedly(Return(0)); + EXPECT_CALL(*result, GetStartTime()).WillRepeatedly(Return(base::Time())); + EXPECT_CALL(*result, GetEndTime()).WillRepeatedly(Return(base::Time())); + EXPECT_CALL(*result, GetReceivedSlices()) + .WillRepeatedly(ReturnRefOfCopy( + std::vector<download::DownloadItem::ReceivedSlice>())); + EXPECT_CALL(*result, GetHash()) + .WillRepeatedly(ReturnRefOfCopy(std::string())); + EXPECT_CALL(*result, GetState()) + .WillRepeatedly(Return(download::DownloadItem::IN_PROGRESS)); + EXPECT_CALL(*result, GetDangerType()) + .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)); + EXPECT_CALL(*result, GetLastReason()) + .WillRepeatedly(Return(download::DOWNLOAD_INTERRUPT_REASON_NONE)); + EXPECT_CALL(*result, IsPaused()).WillRepeatedly(Return(false)); + EXPECT_CALL(*result, IsTemporary()).WillRepeatedly(Return(false)); + + if (is_download_persistent_) { EXPECT_CALL(*result, RemoveObserver(_)); EXPECT_CALL(*result, AddObserver(_)); } @@ -337,7 +379,8 @@ TestInProgressManager::TestInProgressManager() : download::InProgressDownloadManager( nullptr, base::FilePath(), - download::InProgressDownloadManager::IsOriginSecureCallback()) {} + download::InProgressDownloadManager::IsOriginSecureCallback(), + base::BindRepeating(&URLAlwaysSafe)) {} void TestInProgressManager::AddDownloadItem( std::unique_ptr<download::DownloadItemImpl> item) { @@ -483,6 +526,11 @@ class DownloadManagerTest : public testing::Test { download_manager_->OnInProgressDownloadManagerInitialized(); } + void OnHistoryDBInitialized() { + download_manager_->PostInitialization( + DownloadManager::DOWNLOAD_INITIALIZATION_DEPENDENCY_HISTORY_DB); + } + void SetInProgressDownloadManager( std::unique_ptr<download::InProgressDownloadManager> manager) { download_manager_->in_progress_manager_ = std::move(manager); @@ -519,7 +567,9 @@ TEST_F(DownloadManagerTest, StartDownload) { std::unique_ptr<download::DownloadCreateInfo> info( new download::DownloadCreateInfo); std::unique_ptr<ByteStreamReader> stream(new MockByteStreamReader); - uint32_t local_id(5); // Random value + // Random value, a non 0 value means history db is properly loaded, and new + // downloads should be persisted to the in-progress db. + uint32_t local_id(5); base::FilePath download_path(FILE_PATH_LITERAL("download/path")); OnInProgressDownloadManagerInitialized(); @@ -544,13 +594,49 @@ TEST_F(DownloadManagerTest, StartDownload) { MockCreateFile(Ref(*info->save_info.get()), input_stream.get())) .WillOnce(Return(mock_file)); - mock_download_item_factory_->set_is_download_started(true); + mock_download_item_factory_->set_is_download_persistent(true); download_manager_->StartDownload( std::move(info), std::move(input_stream), nullptr, download::DownloadUrlParameters::OnStartedCallback()); EXPECT_TRUE(download_manager_->GetDownload(local_id)); } +// Test the case that a new download is started when history db failed to +// initialize. +TEST_F(DownloadManagerTest, StartDownloadWithoutHistoryDB) { + std::unique_ptr<download::DownloadCreateInfo> info( + new download::DownloadCreateInfo); + std::unique_ptr<ByteStreamReader> stream(new MockByteStreamReader); + base::FilePath download_path(FILE_PATH_LITERAL("download/path")); + OnInProgressDownloadManagerInitialized(); + EXPECT_FALSE(download_manager_->GetDownload(1)); + + EXPECT_CALL(GetMockObserver(), OnDownloadCreated(download_manager_.get(), _)) + .WillOnce(Return()); + // Returning kInvalidId to indicate that the history db failed. + EXPECT_CALL(GetMockDownloadManagerDelegate(), GetNextId(_)) + .WillOnce(RunCallback<0>(download::DownloadItem::kInvalidId)); + +#if !defined(USE_X11) + // Doing nothing will set the default download directory to null. + EXPECT_CALL(GetMockDownloadManagerDelegate(), GetSaveDir(_, _, _, _)); +#endif + EXPECT_CALL(GetMockDownloadManagerDelegate(), + ApplicationClientIdForFileScanning()) + .WillRepeatedly(Return("client-id")); + download::MockDownloadFile* mock_file = new download::MockDownloadFile; + auto input_stream = + std::make_unique<ByteStreamInputStream>(std::move(stream)); + EXPECT_CALL(*mock_download_file_factory_.get(), + MockCreateFile(Ref(*info->save_info.get()), input_stream.get())) + .WillOnce(Return(mock_file)); + + download_manager_->StartDownload( + std::move(info), std::move(input_stream), nullptr, + download::DownloadUrlParameters::OnStartedCallback()); + EXPECT_TRUE(download_manager_->GetDownload(1)); +} + // Confirm that calling DetermineDownloadTarget behaves properly if the delegate // blocks starting. TEST_F(DownloadManagerTest, DetermineDownloadTarget_True) { @@ -602,9 +688,11 @@ TEST_F(DownloadManagerTest, GetDownloadByGuid) { ASSERT_FALSE(download_manager_->GetDownloadByGuid("")); const char kGuid[] = "8DF158E8-C980-4618-BB03-EBA3242EB48B"; + std::vector<GURL> url_chain; + url_chain.emplace_back("http://example.com/1.zip"); download::DownloadItem* persisted_item = download_manager_->CreateDownloadItem( - kGuid, 10, base::FilePath(), base::FilePath(), std::vector<GURL>(), + kGuid, 10, base::FilePath(), base::FilePath(), url_chain, GURL("http://example.com/a"), GURL("http://example.com/a"), GURL("http://example.com/a"), GURL("http://example.com/a"), "application/octet-stream", "application/octet-stream", @@ -653,13 +741,14 @@ TEST_F(DownloadManagerTest, RemoveDownloadsByURL) { TEST_F(DownloadManagerTest, OnInProgressDownloadsLoaded) { auto in_progress_manager = std::make_unique<TestInProgressManager>(); const char kGuid[] = "8DF158E8-C980-4618-BB03-EBA3242EB48B"; + std::vector<GURL> url_chain; + url_chain.emplace_back("http://example.com/1.zip"); auto in_progress_item = std::make_unique<download::DownloadItemImpl>( in_progress_manager.get(), kGuid, 10, base::FilePath(), base::FilePath(), - std::vector<GURL>(), GURL("http://example.com/a"), + url_chain, GURL("http://example.com/a"), GURL("http://example.com/a"), GURL("http://example.com/a"), GURL("http://example.com/a"), - GURL("http://example.com/a"), "application/octet-stream", - "application/octet-stream", base::Time::Now(), base::Time::Now(), - std::string(), std::string(), 10, 10, std::string(), + "application/octet-stream", "application/octet-stream", base::Time::Now(), + base::Time::Now(), std::string(), std::string(), 10, 10, std::string(), download::DownloadItem::INTERRUPTED, download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, false, @@ -670,8 +759,10 @@ TEST_F(DownloadManagerTest, OnInProgressDownloadsLoaded) { EXPECT_CALL(GetMockObserver(), OnDownloadCreated(download_manager_.get(), _)) .WillOnce(Return()); OnInProgressDownloadManagerInitialized(); - ASSERT_TRUE(download_manager_->GetDownloadByGuid(kGuid)); + ASSERT_FALSE(download_manager_->GetDownloadByGuid(kGuid)); + OnHistoryDBInitialized(); + ASSERT_TRUE(download_manager_->GetDownloadByGuid(kGuid)); download::DownloadItem* download = download_manager_->GetDownloadByGuid(kGuid); download->Remove(); diff --git a/chromium/content/browser/download/download_request_utils.cc b/chromium/content/browser/download/download_request_utils.cc index 86de66d1a75..2704f4d19b8 100644 --- a/chromium/content/browser/download/download_request_utils.cc +++ b/chromium/content/browser/download/download_request_utils.cc @@ -5,6 +5,7 @@ #include "content/public/browser/download_request_utils.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" @@ -26,4 +27,16 @@ DownloadRequestUtils::CreateDownloadForWebContentsMainFrame( render_frame_host->GetRoutingID(), traffic_annotation)); } +// static +bool DownloadRequestUtils::IsURLSafe(int render_process_id, const GURL& url) { + // Check if the renderer is permitted to request the requested URL. + if (!ChildProcessSecurityPolicy::GetInstance()->CanRequestURL( + render_process_id, url)) { + DVLOG(1) << "Denied unauthorized download request for " + << url.possibly_invalid_spec(); + return false; + } + return true; +} + } // namespace content diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc index d022b897f75..e595dd5abba 100644 --- a/chromium/content/browser/download/download_resource_handler.cc +++ b/chromium/content/browser/download/download_resource_handler.cc @@ -31,7 +31,6 @@ #include "content/public/browser/download_request_utils.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/common/browser_side_navigation_policy.h" #include "services/network/public/cpp/resource_response.h" namespace content { diff --git a/chromium/content/browser/download/download_utils.cc b/chromium/content/browser/download/download_utils.cc index 89d3af0f95a..d4f2f562f42 100644 --- a/chromium/content/browser/download/download_utils.cc +++ b/chromium/content/browser/download/download_utils.cc @@ -10,7 +10,6 @@ #include "base/strings/stringprintf.h" #include "base/task/post_task.h" #include "components/download/database/in_progress/download_entry.h" -#include "components/download/database/in_progress/in_progress_cache.h" #include "components/download/public/common/download_create_info.h" #include "components/download/public/common/download_interrupt_reasons_utils.h" #include "components/download/public/common/download_save_info.h" @@ -21,6 +20,7 @@ #include "content/browser/resource_context_impl.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/download_manager_delegate.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" diff --git a/chromium/content/browser/download/file_download_url_loader_factory_getter.cc b/chromium/content/browser/download/file_download_url_loader_factory_getter.cc index 86dfd9a6aee..52582d0caf3 100644 --- a/chromium/content/browser/download/file_download_url_loader_factory_getter.cc +++ b/chromium/content/browser/download/file_download_url_loader_factory_getter.cc @@ -17,8 +17,13 @@ namespace content { FileDownloadURLLoaderFactoryGetter::FileDownloadURLLoaderFactoryGetter( const GURL& url, - const base::FilePath& profile_path) - : url_(url), profile_path_(profile_path) { + const base::FilePath& profile_path, + scoped_refptr<const SharedCorsOriginAccessList> + shared_cors_origin_access_list) + : url_(url), + profile_path_(profile_path), + shared_cors_origin_access_list_( + std::move(shared_cors_origin_access_list)) { DCHECK(url.SchemeIs(url::kFileScheme)); } @@ -32,9 +37,10 @@ FileDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() { network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; mojo::MakeStrongBinding( std::make_unique<FileURLLoaderFactory>( - profile_path_, base::CreateSequencedTaskRunnerWithTraits( - {base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), + profile_path_, shared_cors_origin_access_list_, + base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), MakeRequest(&url_loader_factory_ptr_info)); return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( diff --git a/chromium/content/browser/download/file_download_url_loader_factory_getter.h b/chromium/content/browser/download/file_download_url_loader_factory_getter.h index 9c3e79c7a13..6629f4c810a 100644 --- a/chromium/content/browser/download/file_download_url_loader_factory_getter.h +++ b/chromium/content/browser/download/file_download_url_loader_factory_getter.h @@ -6,7 +6,9 @@ #define CONTENT_BROWSER_DOWNLOAD_FILE_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ #include "base/files/file_path.h" +#include "base/memory/scoped_refptr.h" #include "components/download/public/common/download_url_loader_factory_getter.h" +#include "content/public/browser/shared_cors_origin_access_list.h" #include "url/gurl.h" namespace content { @@ -15,8 +17,11 @@ namespace content { class FileDownloadURLLoaderFactoryGetter : public download::DownloadURLLoaderFactoryGetter { public: - FileDownloadURLLoaderFactoryGetter(const GURL& url, - const base::FilePath& profile_path); + FileDownloadURLLoaderFactoryGetter( + const GURL& url, + const base::FilePath& profile_path, + scoped_refptr<const SharedCorsOriginAccessList> + shared_cors_origin_access_list); // download::DownloadURLLoaderFactoryGetter implementation. scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; @@ -27,6 +32,8 @@ class FileDownloadURLLoaderFactoryGetter private: GURL url_; base::FilePath profile_path_; + const scoped_refptr<const SharedCorsOriginAccessList> + shared_cors_origin_access_list_; DISALLOW_COPY_AND_ASSIGN(FileDownloadURLLoaderFactoryGetter); }; diff --git a/chromium/content/browser/download/url_downloader.cc b/chromium/content/browser/download/url_downloader.cc index 15b46abdb33..62939781aa7 100644 --- a/chromium/content/browser/download/url_downloader.cc +++ b/chromium/content/browser/download/url_downloader.cc @@ -19,6 +19,8 @@ #include "content/browser/download/byte_stream_input_stream.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/download_request_utils.h" +#include "content/public/common/child_process_host.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" @@ -41,14 +43,16 @@ std::unique_ptr<UrlDownloader> UrlDownloader::BeginDownload( Referrer::SanitizeForRequest(request->url(), referrer); Referrer::SetReferrerForRequest(request.get(), sanitized_referrer); + // TODO(xingliu): Figure out if we can support blob scheme. if (request->url().SchemeIs(url::kBlobScheme)) return nullptr; // From this point forward, the |UrlDownloader| is responsible for // |started_callback|. - std::unique_ptr<UrlDownloader> downloader( - new UrlDownloader(std::move(request), delegate, is_parallel_request, - params->request_origin(), params->download_source())); + std::unique_ptr<UrlDownloader> downloader(new UrlDownloader( + std::move(request), delegate, is_parallel_request, + params->request_origin(), params->follow_cross_origin_redirects(), + params->download_source())); downloader->Start(); return downloader; @@ -59,6 +63,7 @@ UrlDownloader::UrlDownloader( base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate, bool is_parallel_request, const std::string& request_origin, + bool follow_cross_origin_redirects, download::DownloadSource download_source) : request_(std::move(request)), delegate_(delegate), @@ -67,6 +72,7 @@ UrlDownloader::UrlDownloader( is_parallel_request, request_origin, download_source), + follow_cross_origin_redirects_(follow_cross_origin_redirects), weak_ptr_factory_(this) {} UrlDownloader::~UrlDownloader() { @@ -82,13 +88,19 @@ void UrlDownloader::Start() { void UrlDownloader::OnReceivedRedirect(net::URLRequest* request, const net::RedirectInfo& redirect_info, bool* defer_redirect) { - DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); - // We are going to block redirects even if DownloadRequestCore allows it. No - // redirects are expected for download requests that are made without a - // renderer, which are currently exclusively resumption requests. Since there - // is no security policy being applied here, it's safer to block redirects and - // revisit if some previously unknown legitimate use case arises for redirects - // while resuming. + DVLOG(1) << __func__ << " , request url: " << request_->url().spec() + << " ,redirect url:" << redirect_info.new_url; + if (follow_cross_origin_redirects_) { + if (!DownloadRequestUtils::IsURLSafe(ChildProcessHost::kInvalidUniqueID, + redirect_info.new_url)) { + core_.OnWillAbort( + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST); + request_->CancelWithError(net::ERR_UNSAFE_REDIRECT); + } + return; + } + + // Block redirects since there is no security policy being applied here. core_.OnWillAbort(download::DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE); request_->CancelWithError(net::ERR_UNSAFE_REDIRECT); } @@ -103,6 +115,14 @@ void UrlDownloader::OnResponseStarted(net::URLRequest* request, int net_error) { return; } + if (!DownloadRequestUtils::IsURLSafe(ChildProcessHost::kInvalidUniqueID, + request_->url())) { + core_.OnWillAbort( + download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST); + request_->CancelWithError(net::ERR_DISALLOWED_URL_SCHEME); + return; + } + if (core_.OnResponseStarted(std::string())) StartReading(false); // Read the first chunk. else diff --git a/chromium/content/browser/download/url_downloader.h b/chromium/content/browser/download/url_downloader.h index e5b7289ea15..6552a4032ba 100644 --- a/chromium/content/browser/download/url_downloader.h +++ b/chromium/content/browser/download/url_downloader.h @@ -32,6 +32,7 @@ class UrlDownloader : public net::URLRequest::Delegate, base::WeakPtr<UrlDownloadHandler::Delegate> delegate, bool is_parallel_request, const std::string& request_origin, + bool follow_cross_origin_redirects, download::DownloadSource download_source); ~UrlDownloader() override; @@ -78,6 +79,8 @@ class UrlDownloader : public net::URLRequest::Delegate, base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate_; DownloadRequestCore core_; + const bool follow_cross_origin_redirects_; + base::WeakPtrFactory<UrlDownloader> weak_ptr_factory_; }; diff --git a/chromium/content/browser/download/url_downloader_factory.cc b/chromium/content/browser/download/url_downloader_factory.cc index c6a915457d2..9d2c16550a8 100644 --- a/chromium/content/browser/download/url_downloader_factory.cc +++ b/chromium/content/browser/download/url_downloader_factory.cc @@ -22,6 +22,7 @@ UrlDownloaderFactory::CreateUrlDownloadHandler( base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate, scoped_refptr<download::DownloadURLLoaderFactoryGetter> url_loader_factory_getter, + const download::URLSecurityPolicy& url_security_policy, scoped_refptr<net::URLRequestContextGetter> url_request_context_getter, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { std::unique_ptr<net::URLRequest> url_request = diff --git a/chromium/content/browser/download/url_downloader_factory.h b/chromium/content/browser/download/url_downloader_factory.h index bda99732608..23b287feb37 100644 --- a/chromium/content/browser/download/url_downloader_factory.h +++ b/chromium/content/browser/download/url_downloader_factory.h @@ -6,6 +6,7 @@ #define CONTENT_BROWSER_DOWNLOAD_URL_DOWNLOADER_FACTORY_H_ #include "base/memory/ref_counted.h" +#include "components/download/public/common/download_utils.h" #include "components/download/public/common/url_download_handler_factory.h" namespace download { @@ -32,6 +33,7 @@ class UrlDownloaderFactory : public download::UrlDownloadHandlerFactory { base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate, scoped_refptr<download::DownloadURLLoaderFactoryGetter> shared_url_loader_factory, + const download::URLSecurityPolicy& url_security_policy, scoped_refptr<net::URLRequestContextGetter> url_request_context_getter, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) override; }; |