diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-28 15:28:34 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-08-28 13:54:51 +0000 |
commit | 2a19c63448c84c1805fb1a585c3651318bb86ca7 (patch) | |
tree | eb17888e8531aa6ee5e85721bd553b832a7e5156 /chromium/content/browser/download | |
parent | b014812705fc80bff0a5c120dfcef88f349816dc (diff) | |
download | qtwebengine-chromium-2a19c63448c84c1805fb1a585c3651318bb86ca7.tar.gz |
BASELINE: Update Chromium to 69.0.3497.70
Change-Id: I2b7b56e4e7a8b26656930def0d4575dc32b900a0
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/browser/download')
21 files changed, 721 insertions, 290 deletions
diff --git a/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc b/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc deleted file mode 100644 index d5d418186a1..00000000000 --- a/chromium/content/browser/download/blob_download_url_loader_factory_getter.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/download/blob_download_url_loader_factory_getter.h" - -#include "components/download/public/common/download_task_runner.h" -#include "content/browser/url_loader_factory_getter.h" -#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" -#include "services/network/public/mojom/url_loader_factory.mojom.h" -#include "storage/browser/blob/blob_data_handle.h" -#include "storage/browser/blob/blob_url_loader_factory.h" - -namespace content { - -BlobDownloadURLLoaderFactoryGetter::BlobDownloadURLLoaderFactoryGetter( - const GURL& url, - std::unique_ptr<storage::BlobDataHandle> blob_data_handle) - : url_(url), blob_data_handle_(std::move(blob_data_handle)) { - DCHECK(url.SchemeIs(url::kBlobScheme)); -} - -BlobDownloadURLLoaderFactoryGetter::~BlobDownloadURLLoaderFactoryGetter() = - default; - -scoped_refptr<network::SharedURLLoaderFactory> -BlobDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() { - DCHECK(download::GetIOTaskRunner()); - DCHECK(download::GetIOTaskRunner()->BelongsToCurrentThread()); - network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; - storage::BlobURLLoaderFactory::Create( - std::move(blob_data_handle_), url_, - mojo::MakeRequest(&url_loader_factory_ptr_info)); - return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( - std::move(url_loader_factory_ptr_info)); -} - -} // namespace content diff --git a/chromium/content/browser/download/blob_download_url_loader_factory_getter.h b/chromium/content/browser/download/blob_download_url_loader_factory_getter.h deleted file mode 100644 index 10938f46c42..00000000000 --- a/chromium/content/browser/download/blob_download_url_loader_factory_getter.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_DOWNLOAD_BLOB_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ -#define CONTENT_BROWSER_DOWNLOAD_BLOB_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ - -#include "components/download/public/common/download_url_loader_factory_getter.h" -#include "url/gurl.h" - -namespace storage { -class BlobDataHandle; -} - -namespace content { - -// Class for retrieving the URLLoaderFactory for a blob URL. -class BlobDownloadURLLoaderFactoryGetter - : public download::DownloadURLLoaderFactoryGetter { - public: - BlobDownloadURLLoaderFactoryGetter( - const GURL& url, - std::unique_ptr<storage::BlobDataHandle> blob_data_handle); - - // download::DownloadURLLoaderFactoryGetter implementation. - scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; - - protected: - ~BlobDownloadURLLoaderFactoryGetter() override; - - private: - GURL url_; - std::unique_ptr<storage::BlobDataHandle> blob_data_handle_; - - DISALLOW_COPY_AND_ASSIGN(BlobDownloadURLLoaderFactoryGetter); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_DOWNLOAD_BLOB_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc index 1cae12047b7..58882960352 100644 --- a/chromium/content/browser/download/download_browsertest.cc +++ b/chromium/content/browser/download/download_browsertest.cc @@ -43,6 +43,7 @@ #include "content/public/browser/download_request_utils.h" #include "content/public/browser/resource_throttle.h" #include "content/public/common/content_paths.h" +#include "content/public/common/content_switches.h" #include "content/public/common/webplugininfo.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" @@ -67,6 +68,8 @@ #include "ppapi/buildflags/buildflags.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/platform/web_mouse_event.h" #include "url/gurl.h" #if BUILDFLAG(ENABLE_PLUGINS) @@ -231,7 +234,7 @@ class DownloadFileWithDelayFactory : public download::DownloadFileFactory { private: std::vector<base::Closure> rename_callbacks_; - bool waiting_; + base::OnceClosure stop_waiting_; base::WeakPtrFactory<DownloadFileWithDelayFactory> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory); @@ -288,8 +291,7 @@ void DownloadFileWithDelay::RenameCallbackWrapper( } DownloadFileWithDelayFactory::DownloadFileWithDelayFactory() - : waiting_(false), - weak_ptr_factory_(this) {} + : weak_ptr_factory_(this) {} DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {} @@ -307,8 +309,8 @@ download::DownloadFile* DownloadFileWithDelayFactory::CreateFile( void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); rename_callbacks_.push_back(std::move(callback)); - if (waiting_) - base::RunLoop::QuitCurrentWhenIdleDeprecated(); + if (stop_waiting_) + std::move(stop_waiting_).Run(); } void DownloadFileWithDelayFactory::GetAllRenameCallbacks( @@ -321,9 +323,9 @@ void DownloadFileWithDelayFactory::WaitForSomeCallback() { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (rename_callbacks_.empty()) { - waiting_ = true; - RunMessageLoop(); - waiting_ = false; + base::RunLoop run_loop; + stop_waiting_ = run_loop.QuitClosure(); + run_loop.Run(); } } @@ -366,11 +368,12 @@ class CountingDownloadFile : public download::DownloadFileImpl { // until data is returned. static int GetNumberActiveFilesFromFileThread() { int result = -1; + base::RunLoop run_loop; download::GetDownloadTaskRunner()->PostTaskAndReply( FROM_HERE, base::BindOnce(&CountingDownloadFile::GetNumberActiveFiles, &result), - base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); - base::RunLoop().Run(); + run_loop.QuitClosure()); + run_loop.Run(); DCHECK_NE(-1, result); return result; } @@ -2893,10 +2896,9 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); } -// A filename suggestion specified via a @download attribute should be effective -// if the final download URL is in the same origin as the initial download URL. -// Test that this holds even if there are cross origin redirects in the middle -// of the redirect chain. +// A filename suggestion specified via a @download attribute should not be +// effective if there are cross origin redirects in the middle of the redirect +// chain. IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeSameOriginRedirect) { net::EmbeddedTestServer origin_one; @@ -2939,12 +2941,135 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadManagerForShell(shell())->GetAllDownloads(&downloads); ASSERT_EQ(1u, downloads.size()); - EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"), + EXPECT_EQ(FILE_PATH_LITERAL("download"), downloads[0]->GetTargetFilePath().BaseName().value()); ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete()); ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); } +// A file type that Blink can handle should not be downloaded if there are cross +// origin redirects in the middle of the redirect chain. +IN_PROC_BROWSER_TEST_F(DownloadContentTest, + DownloadAttributeSameOriginRedirectNavigation) { + net::EmbeddedTestServer origin_one; + net::EmbeddedTestServer origin_two; + ASSERT_TRUE(origin_one.InitializeAndListen()); + ASSERT_TRUE(origin_two.InitializeAndListen()); + + // The download-attribute.html page contains an anchor element whose href is + // set to the value of the query parameter (specified as |target| in the URL + // below). The suggested filename for the anchor is 'suggested-filename'. When + // the page is loaded, a script simulates a click on the anchor, triggering a + // download of the target URL. + // + // We construct two test servers; origin_one and origin_two. Once started, the + // server URLs will differ by the port number. Therefore they will be in + // different origins. + GURL download_url = origin_one.GetURL("/ping"); + GURL referrer_url = origin_one.GetURL( + std::string("/download-attribute.html?target=") + download_url.spec()); + origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); + + // <origin_one>/download-attribute.html initiates a download of + // <origin_one>/ping, which redirects to <origin_two>/download. The latter + // serves an HTML document. + origin_one.RegisterRequestHandler( + CreateRedirectHandler("/ping", origin_two.GetURL("/download"))); + origin_two.RegisterRequestHandler( + CreateBasicResponseHandler("/download", net::HTTP_OK, base::StringPairs(), + "text/html", "<title>hello</title>")); + + origin_one.StartAcceptingConnections(); + origin_two.StartAcceptingConnections(); + + base::string16 expected_title(base::UTF8ToUTF16("hello")); + TitleWatcher observer(shell()->web_contents(), expected_title); + NavigateToURL(shell(), referrer_url); + ASSERT_EQ(expected_title, observer.WaitAndGetTitle()); + + std::vector<download::DownloadItem*> downloads; + DownloadManagerForShell(shell())->GetAllDownloads(&downloads); + ASSERT_EQ(0u, downloads.size()); + + ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete()); + ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); +} + +// A download initiated by the user via alt-click on a link should download, +// even when redirected cross origin. +// +// Alt-click doesn't make sense on Android, and download a HTML file results +// in an intent, so just skip. +#if !defined(OS_ANDROID) +IN_PROC_BROWSER_TEST_F(DownloadContentTest, + DownloadAttributeSameOriginRedirectAltClick) { + net::EmbeddedTestServer origin_one; + net::EmbeddedTestServer origin_two; + ASSERT_TRUE(origin_one.InitializeAndListen()); + ASSERT_TRUE(origin_two.InitializeAndListen()); + + // The download-attribute.html page contains an anchor element whose href is + // set to the value of the query parameter (specified as |target| in the URL + // below). The suggested filename for the anchor is 'suggested-filename'. We + // will later send a "real" click to the anchor, triggering a download of the + // target URL. + // + // We construct two test servers; origin_one and origin_two. Once started, the + // server URLs will differ by the port number. Therefore they will be in + // different origins. + GURL download_url = origin_one.GetURL("/ping"); + GURL referrer_url = origin_one.GetURL( + std::string("/download-attribute.html?noclick=") + download_url.spec()); + origin_one.ServeFilesFromDirectory(GetTestFilePath("download", "")); + + // <origin_one>/download-attribute.html initiates a download of + // <origin_one>/ping, which redirects to <origin_two>/download. The latter + // serves an HTML document. + origin_one.RegisterRequestHandler( + CreateRedirectHandler("/ping", origin_two.GetURL("/download"))); + origin_two.RegisterRequestHandler( + CreateBasicResponseHandler("/download", net::HTTP_OK, base::StringPairs(), + "text/html", "<title>hello</title>")); + + origin_one.StartAcceptingConnections(); + origin_two.StartAcceptingConnections(); + + std::unique_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1)); + NavigateToURL(shell(), referrer_url); + + // Alt-click the link. + blink::WebMouseEvent mouse_event( + blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kAltKey, + blink::WebInputEvent::GetStaticTimeStampForTests()); + mouse_event.button = blink::WebMouseEvent::Button::kLeft; + mouse_event.SetPositionInWidget(15, 15); + mouse_event.click_count = 1; + shell()->web_contents()->GetRenderViewHost()->GetWidget()->ForwardMouseEvent( + mouse_event); + mouse_event.SetType(blink::WebInputEvent::kMouseUp); + shell()->web_contents()->GetRenderViewHost()->GetWidget()->ForwardMouseEvent( + mouse_event); + + observer->WaitForFinished(); + EXPECT_EQ( + 1u, observer->NumDownloadsSeenInState(download::DownloadItem::COMPLETE)); + + std::vector<download::DownloadItem*> downloads; + DownloadManagerForShell(shell())->GetAllDownloads(&downloads); + ASSERT_EQ(1u, downloads.size()); +#if defined(OS_WIN) + EXPECT_EQ(FILE_PATH_LITERAL("download.htm"), + downloads[0]->GetTargetFilePath().BaseName().value()); +#else + EXPECT_EQ(FILE_PATH_LITERAL("download.html"), + downloads[0]->GetTargetFilePath().BaseName().value()); +#endif + + ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete()); + ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete()); +} +#endif // !defined(OS_ANDROID) + // Test that the suggested filename for data: URLs works. IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeDataUrl) { net::EmbeddedTestServer server; @@ -2988,23 +3113,33 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeServerError) { // should result in a network error page. IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeNetworkError) { SetupErrorInjectionDownloads(); + WebContents* content = shell()->web_contents(); GURL url = TestDownloadHttpResponse::GetNextURLForDownload(); GURL server_url = embedded_test_server()->GetURL(url.host(), url.path()); - TestDownloadHttpResponse::Parameters parameters; + GURL document_url = embedded_test_server()->GetURL( + std::string("/download/download-attribute.html?target=") + + server_url.spec()); + // Simulate a network failure by injecting an error before the response // header. + TestDownloadHttpResponse::Parameters parameters; parameters.injected_errors.push(-1); parameters.inject_error_cb = inject_error_callback(); TestDownloadHttpResponse::StartServing(parameters, server_url); - GURL document_url = embedded_test_server()->GetURL( - std::string("/download/download-attribute.html?target=") + - server_url.spec()); - auto observer = std::make_unique<content::TestNavigationObserver>( - shell()->web_contents(), 2); - NavigateToURL(shell(), document_url); - observer->Wait(); - EXPECT_FALSE(observer->last_navigation_succeeded()); + content::TestNavigationManager navigation_document(content, document_url); + content::TestNavigationManager navigation_download(content, server_url); + shell()->LoadURL(document_url); + navigation_document.WaitForNavigationFinished(); + navigation_download.WaitForNavigationFinished(); + + EXPECT_TRUE(navigation_document.was_successful()); + EXPECT_FALSE(navigation_download.was_successful()); + + NavigationEntry* navigation_entry = + shell()->web_contents()->GetController().GetLastCommittedEntry(); + EXPECT_EQ(PAGE_TYPE_ERROR, navigation_entry->GetPageType()); + EXPECT_EQ(server_url, navigation_entry->GetURL()); } // A request that fails due to it being rejected by policy should result in a @@ -3031,6 +3166,28 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeBlobURL) { download->GetTargetFilePath().BaseName().value().c_str()); } +class DownloadContentTestWithMojoBlobURLs : public DownloadContentTest { + public: + DownloadContentTestWithMojoBlobURLs() { + scoped_feature_list_.InitAndEnableFeature(blink::features::kMojoBlobURLs); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(DownloadContentTestWithMojoBlobURLs, + DownloadAttributeBlobURL) { + GURL document_url = + embedded_test_server()->GetURL("/download/download-attribute-blob.html"); + download::DownloadItem* download = + StartDownloadAndReturnItem(shell(), document_url); + WaitForCompletion(download); + + EXPECT_STREQ(FILE_PATH_LITERAL("suggested-filename.txt"), + download->GetTargetFilePath().BaseName().value().c_str()); +} + IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeSameSiteCookie) { base::ThreadRestrictions::ScopedAllowIO allow_io_during_test; net::EmbeddedTestServer test_server; @@ -3470,41 +3627,92 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, FetchErrorResponseBodyResumption) { std::string("header_value")); } -IN_PROC_BROWSER_TEST_F(DownloadContentTest, - DISABLED_ForceDownloadMultipartRelatedPage) { - // Force downloading the MHTML. - DownloadTestContentBrowserClient new_client; - new_client.set_allowed_rendering_mhtml_over_http(false); - ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client); +IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadFromWebUI) { + GURL webui_url("chrome://resources/images/apps/blue_button.png"); + NavigateToURL(shell(), webui_url); + SetupEnsureNoPendingDownloads(); + std::unique_ptr<download::DownloadUrlParameters> download_parameters( + DownloadRequestUtils::CreateDownloadForWebContentsMainFrame( + shell()->web_contents(), webui_url, TRAFFIC_ANNOTATION_FOR_TESTS)); + std::unique_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1)); + DownloadManagerForShell(shell())->DownloadUrl(std::move(download_parameters)); + observer->WaitForFinished(); + + EXPECT_TRUE(EnsureNoPendingDownloads()); + + std::vector<download::DownloadItem*> downloads; + DownloadManagerForShell(shell())->GetAllDownloads(&downloads); + ASSERT_EQ(1u, downloads.size()); + ASSERT_EQ(download::DownloadItem::COMPLETE, downloads[0]->GetState()); +} + +// Test fixture for forcing MHTML download. +class MhtmlDownloadTest : public DownloadContentTest { + protected: + void SetUpOnMainThread() override { + DownloadContentTest::SetUpOnMainThread(); + + // Force downloading the MHTML. + new_client_.set_allowed_rendering_mhtml_over_http(false); + old_client_ = SetBrowserClientForTesting(&new_client_); + } + void TearDownOnMainThread() override { + SetBrowserClientForTesting(old_client_); + DownloadContentTest::TearDownOnMainThread(); + } + + private: + DownloadTestContentBrowserClient new_client_; + ContentBrowserClient* old_client_; +}; + +IN_PROC_BROWSER_TEST_F(MhtmlDownloadTest, ForceDownloadMultipartRelatedPage) { NavigateToURLAndWaitForDownload( shell(), // .mhtml file is mapped to "multipart/related" by the test server. embedded_test_server()->GetURL("/download/hello.mhtml"), download::DownloadItem::COMPLETE); - SetBrowserClientForTesting(old_client); } -IN_PROC_BROWSER_TEST_F(DownloadContentTest, ForceDownloadMessageRfc822Page) { - // Force downloading the MHTML. - DownloadTestContentBrowserClient new_client; - new_client.set_allowed_rendering_mhtml_over_http(false); - ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client); - +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(ADDRESS_SANITIZER) +// Flaky https://crbug.com/852073 +#define MAYBE_ForceDownloadMessageRfc822Page \ + DISABLED_ForceDownloadMessageRfc822Page +#else +#define MAYBE_ForceDownloadMessageRfc822Page ForceDownloadMessageRfc822Page +#endif +IN_PROC_BROWSER_TEST_F(MhtmlDownloadTest, + MAYBE_ForceDownloadMessageRfc822Page) { NavigateToURLAndWaitForDownload( shell(), // .mht file is mapped to "message/rfc822" by the test server. embedded_test_server()->GetURL("/download/test.mht"), download::DownloadItem::COMPLETE); - SetBrowserClientForTesting(old_client); } -IN_PROC_BROWSER_TEST_F(DownloadContentTest, AllowRenderMultipartRelatedPage) { - // Allows loading the MHTML, instead of downloading it. - DownloadTestContentBrowserClient new_client; - new_client.set_allowed_rendering_mhtml_over_http(true); - ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client); +// Test fixture for loading MHTML. +class MhtmlLoadingTest : public DownloadContentTest { + protected: + void SetUpOnMainThread() override { + DownloadContentTest::SetUpOnMainThread(); + + // Allows loading the MHTML, instead of downloading it. + new_client_.set_allowed_rendering_mhtml_over_http(true); + old_client_ = SetBrowserClientForTesting(&new_client_); + } + + void TearDownOnMainThread() override { + SetBrowserClientForTesting(old_client_); + DownloadContentTest::TearDownOnMainThread(); + } + private: + DownloadTestContentBrowserClient new_client_; + ContentBrowserClient* old_client_; +}; + +IN_PROC_BROWSER_TEST_F(MhtmlLoadingTest, AllowRenderMultipartRelatedPage) { // .mhtml file is mapped to "multipart/related" by the test server. GURL url = embedded_test_server()->GetURL("/download/hello.mhtml"); auto observer = std::make_unique<content::TestNavigationObserver>(url); @@ -3514,15 +3722,9 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, AllowRenderMultipartRelatedPage) { NavigateToURL(shell(), url); observer->WaitForNavigationFinished(); - SetBrowserClientForTesting(old_client); } -IN_PROC_BROWSER_TEST_F(DownloadContentTest, AllowRenderMessageRfc822Page) { - // Allows loading the MHTML, instead of downloading it. - DownloadTestContentBrowserClient new_client; - new_client.set_allowed_rendering_mhtml_over_http(true); - ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client); - +IN_PROC_BROWSER_TEST_F(MhtmlLoadingTest, AllowRenderMessageRfc822Page) { // .mht file is mapped to "message/rfc822" by the test server. GURL url = embedded_test_server()->GetURL("/download/test.mht"); auto observer = std::make_unique<content::TestNavigationObserver>(url); @@ -3532,7 +3734,6 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, AllowRenderMessageRfc822Page) { NavigateToURL(shell(), url); observer->WaitForNavigationFinished(); - SetBrowserClientForTesting(old_client); } } // namespace content diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc index 081c7a2c2f1..f8c137fe6d7 100644 --- a/chromium/content/browser/download/download_manager_impl.cc +++ b/chromium/content/browser/download/download_manager_impl.cc @@ -21,8 +21,9 @@ #include "base/supports_user_data.h" #include "base/synchronization/lock.h" #include "build/build_config.h" -#include "components/download/downloader/in_progress/download_entry.h" -#include "components/download/downloader/in_progress/in_progress_cache_impl.h" +#include "components/download/database/in_progress/download_entry.h" +#include "components/download/database/in_progress/in_progress_cache_impl.h" +#include "components/download/database/switches.h" #include "components/download/public/common/download_create_info.h" #include "components/download/public/common/download_file.h" #include "components/download/public/common/download_interrupt_reasons.h" @@ -38,14 +39,15 @@ #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/download/blob_download_url_loader_factory_getter.h" #include "content/browser/download/byte_stream_input_stream.h" #include "content/browser/download/download_resource_handler.h" #include "content/browser/download/download_url_loader_factory_getter_impl.h" #include "content/browser/download/download_utils.h" +#include "content/browser/download/file_download_url_loader_factory_getter.h" #include "content/browser/download/network_download_url_loader_factory_getter.h" #include "content/browser/download/url_downloader.h" #include "content/browser/download/url_downloader_factory.h" +#include "content/browser/download/web_ui_download_url_loader_factory_getter.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/loader/resource_request_info_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" @@ -112,6 +114,18 @@ bool CanRequestURLFromRenderer(int render_process_id, GURL url) { return true; } +void OnDownloadStarted( + download::DownloadItemImpl* download, + const download::DownloadUrlParameters::OnStartedCallback& on_started) { + if (on_started.is_null()) + return; + + if (!download || download->GetState() == download::DownloadItem::CANCELLED) + on_started.Run(nullptr, download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); + else + on_started.Run(download, download::DOWNLOAD_INTERRUPT_REASON_NONE); +} + // Creates an interrupted download and calls StartDownload. Can be called on // any thread. void CreateInterruptedDownload( @@ -136,7 +150,7 @@ void CreateInterruptedDownload( void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params, std::unique_ptr<storage::BlobDataHandle> blob_data_handle, content::ResourceContext* resource_context, - uint32_t download_id, + bool is_new_download, base::WeakPtr<DownloadManagerImpl> download_manager) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -146,7 +160,8 @@ void BeginDownload(std::unique_ptr<download::DownloadUrlParameters> params, params->set_blob_storage_context_getter( base::BindOnce(&BlobStorageContextGetter, resource_context)); std::unique_ptr<net::URLRequest> url_request = - DownloadRequestCore::CreateRequestOnIOThread(download_id, params.get()); + DownloadRequestCore::CreateRequestOnIOThread(is_new_download, + params.get()); if (blob_data_handle) { storage::BlobProtocolHandler::SetRequestedBlobDataHandle( url_request.get(), std::move(blob_data_handle)); @@ -288,17 +303,15 @@ DownloadManagerImpl::DownloadManagerImpl(BrowserContext* browser_context) if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) download::UrlDownloadHandlerFactory::Install(new UrlDownloaderFactory()); in_progress_manager_ = std::make_unique<download::InProgressDownloadManager>( - this, base::BindRepeating(&IsOriginSecure)); - in_progress_manager_->Initialize( - IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(), - base::BindOnce(&DownloadManagerImpl::PostInitialization, - weak_factory_.GetWeakPtr(), - DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE)); + this, IsOffTheRecord() ? base::FilePath() : browser_context_->GetPath(), + base::BindRepeating(&IsOriginSecure)); + in_progress_manager_->NotifyWhenInitialized(base::BindOnce( + &DownloadManagerImpl::OnInProgressDownloadManagerInitialized, + weak_factory_.GetWeakPtr())); } DownloadManagerImpl::~DownloadManagerImpl() { DCHECK(!shutdown_needed_); - download::SetIOTaskRunner(nullptr); } download::DownloadItemImpl* DownloadManagerImpl::CreateActiveItem( @@ -311,6 +324,10 @@ download::DownloadItemImpl* DownloadManagerImpl::CreateActiveItem( downloads_[id] = base::WrapUnique(download); downloads_by_guid_[download->GetGuid()] = download; + DownloadItemUtils::AttachInfo( + download, GetBrowserContext(), + WebContentsImpl::FromRenderFrameHostID(info.render_process_id, + info.render_frame_id)); return download; } @@ -419,6 +436,25 @@ bool DownloadManagerImpl::InterceptDownload( const download::DownloadCreateInfo& info) { WebContents* web_contents = WebContentsImpl::FromRenderFrameHostID( info.render_process_id, info.render_frame_id); + if (info.is_new_download && + info.result == + download::DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT) { + if (web_contents) { + std::vector<GURL> url_chain(info.url_chain); + GURL url = url_chain.back(); + url_chain.pop_back(); + NavigationController::LoadURLParams params(url); + params.has_user_gesture = info.has_user_gesture; + params.referrer = Referrer( + info.referrer_url, Referrer::NetReferrerPolicyToBlinkReferrerPolicy( + info.referrer_policy)); + params.redirect_chain = url_chain; + web_contents->GetController().LoadURLWithParams(params); + } + if (info.request_handle) + info.request_handle->CancelRequest(false); + return true; + } if (!delegate_ || !delegate_->InterceptDownloadIfApplicable( info.url(), info.mime_type, info.request_origin, web_contents)) { @@ -455,37 +491,59 @@ base::FilePath DownloadManagerImpl::GetDefaultDownloadDirectory() { return default_download_directory; } -void DownloadManagerImpl::OnNewDownloadStarted( - download::DownloadItem* download) { - for (auto& observer : observers_) - observer.OnDownloadCreated(this, download); +void DownloadManagerImpl::OnInProgressDownloadManagerInitialized() { + std::vector<std::unique_ptr<download::DownloadItemImpl>> + in_progress_downloads = in_progress_manager_->TakeInProgressDownloads(); + 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; + downloads_[download->GetId()] = std::move(download); + for (auto& observer : observers_) + observer.OnDownloadCreated(this, item); + DVLOG(20) << __func__ << "() download = " << item->DebugString(true); + } + PostInitialization(DOWNLOAD_INITIALIZATION_DEPENDENCY_IN_PROGRESS_CACHE); } -download::DownloadItemImpl* DownloadManagerImpl::GetDownloadItem( - uint32_t id, - bool new_download, - const download::DownloadCreateInfo& info) { +void DownloadManagerImpl::StartDownloadItem( + std::unique_ptr<download::DownloadCreateInfo> info, + const download::DownloadUrlParameters::OnStartedCallback& on_started, + download::InProgressDownloadManager::StartDownloadItemCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK_NE(download::DownloadItem::kInvalidId, id); - download::DownloadItemImpl* download = nullptr; - if (new_download) { - download = CreateActiveItem(id, info); + if (!info->is_new_download) { + 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); + OnDownloadStarted(download, on_started); } else { - auto item_iterator = downloads_.find(id); - // Trying to resume an interrupted download. - if (item_iterator == downloads_.end() || - (item_iterator->second->GetState() == - download::DownloadItem::CANCELLED)) { - return nullptr; - } - download = item_iterator->second.get(); + GetNextId( + base::BindRepeating(&DownloadManagerImpl::CreateNewDownloadItemToStart, + weak_factory_.GetWeakPtr(), base::Passed(&info), + on_started, base::Passed(&callback))); } - DownloadItemUtils::AttachInfo( - download, GetBrowserContext(), - WebContentsImpl::FromRenderFrameHostID(info.render_process_id, - info.render_frame_id)); - return download; +} + +void DownloadManagerImpl::CreateNewDownloadItemToStart( + std::unique_ptr<download::DownloadCreateInfo> info, + const download::DownloadUrlParameters::OnStartedCallback& on_started, + download::InProgressDownloadManager::StartDownloadItemCallback callback, + uint32_t id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + download::DownloadItemImpl* download = CreateActiveItem(id, *info); + std::move(callback).Run(std::move(info), 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. + for (auto& observer : observers_) + observer.OnDownloadCreated(this, download); + OnDownloadStarted(download, on_started); } net::URLRequestContextGetter* DownloadManagerImpl::GetURLRequestContextGetter( @@ -517,6 +575,18 @@ void DownloadManagerImpl::CheckForHistoryFilesRemoval() { } } +void DownloadManagerImpl::OnHistoryQueryComplete( + base::OnceClosure load_history_downloads_cb) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + download::switches::kEnableDownloadDB) && + !in_progress_cache_initialized_) { + load_history_downloads_cb_ = std::move(load_history_downloads_cb); + } else { + std::move(load_history_downloads_cb).Run(); + } +} + void DownloadManagerImpl::CheckForFileRemoval( download::DownloadItemImpl* download_item) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -595,10 +665,9 @@ void DownloadManagerImpl::CreateSavePackageDownloadItemWithId( // download. void DownloadManagerImpl::ResumeInterruptedDownload( std::unique_ptr<download::DownloadUrlParameters> params, - uint32_t id, const GURL& site_url) { BeginDownloadInternal(std::move(params), nullptr /* blob_data_handle */, - nullptr /* blob_url_loader_factory */, id, site_url); + nullptr /* blob_url_loader_factory */, false, site_url); } void DownloadManagerImpl::SetDownloadItemFactoryForTesting( @@ -697,9 +766,9 @@ download::DownloadInterruptReason DownloadManagerImpl::BeginDownloadRequest( // TODO(ananta) // Find a better way to create the DownloadResourceHandler instance. std::unique_ptr<ResourceHandler> handler( - DownloadResourceHandler::CreateForNewRequest(url_request.get(), - params->request_origin(), - params->download_source())); + DownloadResourceHandler::CreateForNewRequest( + url_request.get(), params->request_origin(), + params->download_source(), params->follow_cross_origin_redirects())); ResourceDispatcherHostImpl::Get()->BeginURLRequest( std::move(url_request), std::move(handler), true, // download @@ -784,8 +853,7 @@ void DownloadManagerImpl::DownloadUrl( auto* rfh = RenderFrameHost::FromID(params->render_process_host_id(), params->render_frame_host_routing_id()); BeginDownloadInternal(std::move(params), std::move(blob_data_handle), - std::move(blob_url_loader_factory), - download::DownloadItem::kInvalidId, + std::move(blob_url_loader_factory), true, rfh ? rfh->GetSiteInstance()->GetSiteURL() : GURL()); } @@ -824,10 +892,15 @@ download::DownloadItem* DownloadManagerImpl::CreateDownloadItem( bool transient, const std::vector<download::DownloadItem::ReceivedSlice>& received_slices) { if (base::ContainsKey(downloads_, id)) { - NOTREACHED(); - return nullptr; + // 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(); + } } - DCHECK(!base::ContainsKey(downloads_by_guid_, guid)); download::DownloadItemImpl* item = 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, @@ -855,6 +928,8 @@ 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(); break; case DOWNLOAD_INITIALIZATION_DEPENDENCY_NONE: default: @@ -1016,9 +1091,8 @@ void DownloadManagerImpl::InterceptNavigationOnChecksComplete( void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete( std::unique_ptr<download::DownloadUrlParameters> params, - std::unique_ptr<storage::BlobDataHandle> blob_data_handle, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, - uint32_t id, + bool is_new_download, const GURL& site_url, bool is_download_allowed) { if (!is_download_allowed) { @@ -1038,6 +1112,7 @@ void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete( } } + DCHECK_EQ(params->url().SchemeIsBlob(), bool{blob_url_loader_factory}); scoped_refptr<download::DownloadURLLoaderFactoryGetter> url_loader_factory_getter; if (blob_url_loader_factory) { @@ -1045,10 +1120,14 @@ void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete( url_loader_factory_getter = base::MakeRefCounted<DownloadURLLoaderFactoryGetterImpl>( blob_url_loader_factory->Clone()); - } else if (params->url().SchemeIsBlob()) { + } else if (params->url().SchemeIsFile()) { url_loader_factory_getter = - base::MakeRefCounted<BlobDownloadURLLoaderFactoryGetter>( - params->url(), std::move(blob_data_handle)); + base::MakeRefCounted<FileDownloadURLLoaderFactoryGetter>( + params->url(), browser_context_->GetPath()); + } else if (params->url().SchemeIs(content::kChromeUIScheme)) { + url_loader_factory_getter = + base::MakeRefCounted<WebUIDownloadURLLoaderFactoryGetter>( + rfh, params->url()); } else { StoragePartitionImpl* storage_partition = static_cast<StoragePartitionImpl*>( @@ -1058,16 +1137,16 @@ void DownloadManagerImpl::BeginResourceDownloadOnChecksComplete( CreateDownloadURLLoaderFactoryGetter(storage_partition, rfh, true); } - in_progress_manager_->BeginDownload(std::move(params), - std::move(url_loader_factory_getter), id, - site_url, tab_url, tab_referrer_url); + in_progress_manager_->BeginDownload( + std::move(params), std::move(url_loader_factory_getter), is_new_download, + site_url, tab_url, tab_referrer_url); } void DownloadManagerImpl::BeginDownloadInternal( std::unique_ptr<download::DownloadUrlParameters> params, std::unique_ptr<storage::BlobDataHandle> blob_data_handle, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, - uint32_t id, + bool is_new_download, const GURL& site_url) { // Check if the renderer is permitted to request the requested URL. if (params->render_process_host_id() >= 0 && @@ -1096,8 +1175,7 @@ void DownloadManagerImpl::BeginDownloadInternal( on_can_download_checks_done = base::BindOnce( &DownloadManagerImpl::BeginResourceDownloadOnChecksComplete, weak_factory_.GetWeakPtr(), std::move(params), - std::move(blob_data_handle), std::move(blob_url_loader_factory), - id, site_url); + std::move(blob_url_loader_factory), is_new_download, site_url); if (delegate_) { delegate_->CheckDownloadAllowed(std::move(web_contents_getter), url, method, @@ -1107,9 +1185,8 @@ void DownloadManagerImpl::BeginDownloadInternal( } BeginResourceDownloadOnChecksComplete( - std::move(params), std::move(blob_data_handle), - std::move(blob_url_loader_factory), id, site_url, - rfh ? !content_initiated : true); + std::move(params), std::move(blob_url_loader_factory), is_new_download, + site_url, rfh ? !content_initiated : true); } else { StoragePartition* storage_partition = BrowserContext::GetStoragePartitionForSite(browser_context_, site_url); @@ -1119,7 +1196,7 @@ void DownloadManagerImpl::BeginDownloadInternal( BrowserThread::IO, FROM_HERE, base::BindOnce(&BeginDownload, std::move(params), std::move(blob_data_handle), - browser_context_->GetResourceContext(), id, + browser_context_->GetResourceContext(), is_new_download, weak_factory_.GetWeakPtr())); } } diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h index 041492c4347..4f07f57f252 100644 --- a/chromium/content/browser/download/download_manager_impl.h +++ b/chromium/content/browser/download/download_manager_impl.h @@ -128,6 +128,8 @@ class CONTENT_EXPORT DownloadManagerImpl int NonMaliciousInProgressCount() const override; BrowserContext* GetBrowserContext() const override; void CheckForHistoryFilesRemoval() override; + void OnHistoryQueryComplete( + base::OnceClosure load_history_downloads_cb) override; download::DownloadItem* GetDownload(uint32_t id) override; download::DownloadItem* GetDownloadByGuid(const std::string& guid) override; @@ -194,14 +196,27 @@ class CONTENT_EXPORT DownloadManagerImpl // InProgressDownloadManager::Delegate implementations. bool InterceptDownload(const download::DownloadCreateInfo& info) override; base::FilePath GetDefaultDownloadDirectory() override; - download::DownloadItemImpl* GetDownloadItem( - uint32_t id, - bool new_download, - const download::DownloadCreateInfo& info) override; + void StartDownloadItem( + std::unique_ptr<download::DownloadCreateInfo> info, + const download::DownloadUrlParameters::OnStartedCallback& on_started, + download::InProgressDownloadManager::StartDownloadItemCallback callback) + override; net::URLRequestContextGetter* GetURLRequestContextGetter( const download::DownloadCreateInfo& info) override; - void OnNewDownloadStarted(download::DownloadItem* download) override; - void GetNextId(const DownloadIdCallback& callback) override; + + // Called when InProgressDownloadManager is initialzed. + void OnInProgressDownloadManagerInitialized(); + + // Creates a new download item and call |callback|. + void CreateNewDownloadItemToStart( + std::unique_ptr<download::DownloadCreateInfo> info, + const download::DownloadUrlParameters::OnStartedCallback& on_started, + download::InProgressDownloadManager::StartDownloadItemCallback callback, + uint32_t id); + + // Called to get an ID for a new download. |callback| may be called + // synchronously. + void GetNextId(const DownloadIdCallback& callback); // Create a new active item based on the info. Separate from // StartDownload() for testing. @@ -209,7 +224,6 @@ class CONTENT_EXPORT DownloadManagerImpl uint32_t id, const download::DownloadCreateInfo& info); - // Called with the result of DownloadManagerDelegate::CheckForFileExistence. // Updates the state of the file and then notifies this update to the file's // observer. @@ -227,7 +241,6 @@ class CONTENT_EXPORT DownloadManagerImpl std::string GetApplicationClientIdForFileScanning() const override; void ResumeInterruptedDownload( std::unique_ptr<download::DownloadUrlParameters> params, - uint32_t id, const GURL& site_url) override; void OpenDownload(download::DownloadItemImpl* download) override; bool IsMostRecentDownloadItemAtFilePath( @@ -248,7 +261,7 @@ class CONTENT_EXPORT DownloadManagerImpl std::unique_ptr<download::DownloadUrlParameters> params, std::unique_ptr<storage::BlobDataHandle> blob_data_handle, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, - uint32_t id, + bool is_new_download, const GURL& site_url); void InterceptNavigationOnChecksComplete( @@ -261,9 +274,8 @@ class CONTENT_EXPORT DownloadManagerImpl bool is_download_allowed); void BeginResourceDownloadOnChecksComplete( std::unique_ptr<download::DownloadUrlParameters> params, - std::unique_ptr<storage::BlobDataHandle> blob_data_handle, scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, - uint32_t id, + bool is_new_download, const GURL& site_url, bool is_download_allowed); @@ -314,6 +326,9 @@ class CONTENT_EXPORT DownloadManagerImpl std::unique_ptr<download::InProgressDownloadManager> in_progress_manager_; + // Callback to run to load all history downloads. + base::OnceClosure load_history_downloads_cb_; + base::WeakPtrFactory<DownloadManagerImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(DownloadManagerImpl); diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc index 9ccc49d3df7..c4e5f80b78f 100644 --- a/chromium/content/browser/download/download_manager_impl_unittest.cc +++ b/chromium/content/browser/download/download_manager_impl_unittest.cc @@ -320,6 +320,36 @@ class MockByteStreamReader : public ByteStreamReader { MOCK_METHOD1(RegisterCallback, void(const base::Closure&)); }; +class TestInProgressManager : public download::InProgressDownloadManager { + public: + TestInProgressManager(); + ~TestInProgressManager() override = default; + + std::vector<std::unique_ptr<download::DownloadItemImpl>> + TakeInProgressDownloads() override; + + void AddDownloadItem(std::unique_ptr<download::DownloadItemImpl> item); + + private: + std::vector<std::unique_ptr<download::DownloadItemImpl>> download_items_; +}; + +TestInProgressManager::TestInProgressManager() + : download::InProgressDownloadManager( + nullptr, + base::FilePath(), + download::InProgressDownloadManager::IsOriginSecureCallback()) {} + +void TestInProgressManager::AddDownloadItem( + std::unique_ptr<download::DownloadItemImpl> item) { + download_items_.emplace_back(std::move(item)); +} + +std::vector<std::unique_ptr<download::DownloadItemImpl>> +TestInProgressManager::TakeInProgressDownloads() { + return std::move(download_items_); +} + } // namespace class DownloadManagerTest : public testing::Test { @@ -450,6 +480,15 @@ class DownloadManagerTest : public testing::Test { base::Unretained(this))); } + void OnInProgressDownloadManagerInitialized() { + download_manager_->OnInProgressDownloadManagerInitialized(); + } + + void SetInProgressDownloadManager( + std::unique_ptr<download::InProgressDownloadManager> manager) { + download_manager_->in_progress_manager_ = std::move(manager); + } + protected: // Key test variable; we'll keep it available to sub-classes. std::unique_ptr<DownloadManagerImpl> download_manager_; @@ -609,4 +648,34 @@ TEST_F(DownloadManagerTest, RemoveDownloadsByURL) { EXPECT_EQ(remove_count, 1); } +// Confirm that in-progress downloads will be taken and managed by +// DownloadManager. +TEST_F(DownloadManagerTest, OnInProgressDownloadsLoaded) { + auto in_progress_manager = std::make_unique<TestInProgressManager>(); + const char kGuid[] = "8DF158E8-C980-4618-BB03-EBA3242EB48B"; + 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"), + 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(), + download::DownloadItem::INTERRUPTED, + download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED, false, + base::Time::Now(), true, + std::vector<download::DownloadItem::ReceivedSlice>()); + in_progress_manager->AddDownloadItem(std::move(in_progress_item)); + SetInProgressDownloadManager(std::move(in_progress_manager)); + EXPECT_CALL(GetMockObserver(), OnDownloadCreated(download_manager_.get(), _)) + .WillOnce(Return()); + OnInProgressDownloadManagerInitialized(); + ASSERT_TRUE(download_manager_->GetDownloadByGuid(kGuid)); + + download::DownloadItem* download = + download_manager_->GetDownloadByGuid(kGuid); + download->Remove(); + ASSERT_FALSE(download_manager_->GetDownloadByGuid(kGuid)); +} + } // namespace content diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc index 3b2045e18ee..fb6a33bcd83 100644 --- a/chromium/content/browser/download/download_request_core.cc +++ b/chromium/content/browser/download/download_request_core.cc @@ -56,14 +56,14 @@ class DownloadRequestData : public base::SupportsUserData::Data { static void Attach(net::URLRequest* request, download::DownloadUrlParameters* download_parameters, - uint32_t download_id); + bool is_new_download); static DownloadRequestData* Get(const net::URLRequest* request); static void Detach(net::URLRequest* request); std::unique_ptr<download::DownloadSaveInfo> TakeSaveInfo() { return std::move(save_info_); } - uint32_t download_id() const { return download_id_; } + bool is_new_download() const { return is_new_download_; } std::string guid() const { return guid_; } bool is_transient() const { return transient_; } bool fetch_error_body() const { return fetch_error_body_; } @@ -80,7 +80,7 @@ class DownloadRequestData : public base::SupportsUserData::Data { static const int kKey; std::unique_ptr<download::DownloadSaveInfo> save_info_; - uint32_t download_id_ = download::DownloadItem::kInvalidId; + bool is_new_download_; std::string guid_; bool fetch_error_body_ = false; download::DownloadUrlParameters::RequestHeadersType request_headers_; @@ -95,11 +95,11 @@ const int DownloadRequestData::kKey = 0; // static void DownloadRequestData::Attach(net::URLRequest* request, download::DownloadUrlParameters* parameters, - uint32_t download_id) { + bool is_new_download) { auto request_data = std::make_unique<DownloadRequestData>(); request_data->save_info_.reset( new download::DownloadSaveInfo(parameters->GetSaveInfo())); - request_data->download_id_ = download_id; + request_data->is_new_download_ = is_new_download; request_data->guid_ = parameters->guid(); request_data->fetch_error_body_ = parameters->fetch_error_body(); request_data->request_headers_ = parameters->request_headers(); @@ -125,16 +125,15 @@ const int DownloadRequestCore::kDownloadByteStreamSize = 100 * 1024; // static std::unique_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread( - uint32_t download_id, + bool is_new_download, download::DownloadUrlParameters* params) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(download_id == download::DownloadItem::kInvalidId || - !params->content_initiated()) - << "Content initiated downloads shouldn't specify a download ID"; + DCHECK(is_new_download || !params->content_initiated()) + << "Content initiated downloads should be a new download"; std::unique_ptr<net::URLRequest> request = CreateURLRequestOnIOThread(params); - DownloadRequestData::Attach(request.get(), params, download_id); + DownloadRequestData::Attach(request.get(), params, is_new_download); return request; } @@ -155,7 +154,7 @@ DownloadRequestCore::DownloadRequestCore( download::DownloadSource download_source) : delegate_(delegate), request_(request), - download_id_(download::DownloadItem::kInvalidId), + is_new_download_(true), fetch_error_body_(false), transient_(false), bytes_read_(0), @@ -193,7 +192,7 @@ DownloadRequestCore::DownloadRequestCore( DownloadRequestData* request_data = DownloadRequestData::Get(request_); if (request_data) { save_info_ = request_data->TakeSaveInfo(); - download_id_ = request_data->download_id(); + is_new_download_ = request_data->is_new_download(); guid_ = request_data->guid(); fetch_error_body_ = request_data->fetch_error_body(); request_headers_ = request_data->request_headers(); @@ -228,8 +227,9 @@ DownloadRequestCore::CreateDownloadCreateInfo( create_info->connection_info = request()->response_info().connection_info; create_info->url_chain = request()->url_chain(); create_info->referrer_url = GURL(request()->referrer()); + create_info->referrer_policy = request()->referrer_policy(); create_info->result = result; - create_info->download_id = download_id_; + create_info->is_new_download = is_new_download_; create_info->guid = guid_; create_info->transient = transient_; create_info->response_headers = request()->response_headers(); diff --git a/chromium/content/browser/download/download_request_core.h b/chromium/content/browser/download/download_request_core.h index 409e3e3912d..0fdd19edd45 100644 --- a/chromium/content/browser/download/download_request_core.h +++ b/chromium/content/browser/download/download_request_core.h @@ -109,7 +109,7 @@ class CONTENT_EXPORT DownloadRequestCore std::string DebugString() const; static std::unique_ptr<net::URLRequest> CreateRequestOnIOThread( - uint32_t download_id, + bool is_new_download, download::DownloadUrlParameters* params); // Size of the buffer used between the DownloadRequestCore and the @@ -129,7 +129,7 @@ class CONTENT_EXPORT DownloadRequestCore // "Passthrough" fields. These are only kept here so that they can be used to // populate the download::DownloadCreateInfo when the time comes. std::unique_ptr<download::DownloadSaveInfo> save_info_; - uint32_t download_id_; + bool is_new_download_; std::string guid_; bool fetch_error_body_; download::DownloadUrlParameters::RequestHeadersType request_headers_; diff --git a/chromium/content/browser/download/download_request_core_unittest.cc b/chromium/content/browser/download/download_request_core_unittest.cc index 4d9c0db919d..5c6fb4e426b 100644 --- a/chromium/content/browser/download/download_request_core_unittest.cc +++ b/chromium/content/browser/download/download_request_core_unittest.cc @@ -46,8 +46,7 @@ class DownloadRequestCoreTest : public testing::Test { } void CreateRequestOnIOThread(download::DownloadUrlParameters* params) { - url_request_ = DownloadRequestCore::CreateRequestOnIOThread( - download::DownloadItem::kInvalidId, params); + url_request_ = DownloadRequestCore::CreateRequestOnIOThread(true, params); DCHECK(url_request_.get()); } diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc index d409db6c596..752cc1af42d 100644 --- a/chromium/content/browser/download/download_resource_handler.cc +++ b/chromium/content/browser/download/download_resource_handler.cc @@ -24,6 +24,7 @@ #include "content/browser/loader/resource_controller.h" #include "content/browser/loader/resource_dispatcher_host_impl.h" #include "content/browser/loader/resource_request_info_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_request_utils.h" #include "content/public/browser/navigation_entry.h" @@ -109,10 +110,8 @@ void InitializeDownloadTabInfoOnUIThread( tab_info->tab_url = entry->GetURL(); tab_info->tab_referrer_url = entry->GetReferrer().url; - tab_info->ukm_source_id = ukm::UkmRecorder::GetNewSourceID(); - download::DownloadUkmHelper::UpdateSourceURL( - ukm::UkmRecorder::Get(), tab_info->ukm_source_id, - web_contents->GetLastCommittedURL()); + tab_info->ukm_source_id = static_cast<WebContentsImpl*>(web_contents) + ->GetUkmSourceIdForLastCommittedSource(); } } } @@ -120,14 +119,35 @@ void InitializeDownloadTabInfoOnUIThread( void DeleteOnUIThread( std::unique_ptr<DownloadResourceHandler::DownloadTabInfo> tab_info) {} +void NavigateOnUIThread( + const GURL& url, + const std::vector<GURL> url_chain, + const Referrer& referrer, + bool has_user_gesture, + const ResourceRequestInfo::WebContentsGetter& wc_getter) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + WebContents* web_contents = wc_getter.Run(); + if (web_contents) { + NavigationController::LoadURLParams params(url); + params.has_user_gesture = has_user_gesture; + params.referrer = referrer; + params.redirect_chain = url_chain; + web_contents->GetController().LoadURLWithParams(params); + } +} + } // namespace DownloadResourceHandler::DownloadResourceHandler( net::URLRequest* request, const std::string& request_origin, - download::DownloadSource download_source) + download::DownloadSource download_source, + bool follow_cross_origin_redirects) : ResourceHandler(request), tab_info_(new DownloadTabInfo()), + follow_cross_origin_redirects_(follow_cross_origin_redirects), + first_origin_(url::Origin::Create(request->url())), core_(request, this, false, request_origin, download_source) { // Do UI thread initialization for tab_info_ asap after // DownloadResourceHandler creation since the tab could be navigated @@ -157,7 +177,7 @@ std::unique_ptr<ResourceHandler> DownloadResourceHandler::Create( net::URLRequest* request) { DCHECK_CURRENTLY_ON(BrowserThread::IO); std::unique_ptr<ResourceHandler> handler(new DownloadResourceHandler( - request, std::string(), download::DownloadSource::NAVIGATION)); + request, std::string(), download::DownloadSource::NAVIGATION, true)); return handler; } @@ -165,10 +185,11 @@ std::unique_ptr<ResourceHandler> DownloadResourceHandler::Create( std::unique_ptr<ResourceHandler> DownloadResourceHandler::CreateForNewRequest( net::URLRequest* request, const std::string& request_origin, - download::DownloadSource download_source) { + download::DownloadSource download_source, + bool follow_cross_origin_redirects) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - std::unique_ptr<ResourceHandler> handler( - new DownloadResourceHandler(request, request_origin, download_source)); + std::unique_ptr<ResourceHandler> handler(new DownloadResourceHandler( + request, request_origin, download_source, follow_cross_origin_redirects)); return handler; } @@ -176,6 +197,21 @@ void DownloadResourceHandler::OnRequestRedirected( const net::RedirectInfo& redirect_info, network::ResourceResponse* response, std::unique_ptr<ResourceController> controller) { + url::Origin new_origin(url::Origin::Create(redirect_info.new_url)); + if (!follow_cross_origin_redirects_ && + !first_origin_.IsSameOriginWith(new_origin)) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce( + &NavigateOnUIThread, redirect_info.new_url, request()->url_chain(), + Referrer(GURL(redirect_info.new_referrer), + Referrer::NetReferrerPolicyToBlinkReferrerPolicy( + redirect_info.new_referrer_policy)), + GetRequestInfo()->HasUserGesture(), + GetRequestInfo()->GetWebContentsGetterForRequest())); + controller->Cancel(); + return; + } if (core_.OnRequestRedirected()) { controller->Resume(); } else { @@ -242,10 +278,6 @@ void DownloadResourceHandler::OnResponseCompleted( controller->Resume(); } -void DownloadResourceHandler::OnDataDownloaded(int bytes_downloaded) { - NOTREACHED(); -} - void DownloadResourceHandler::PauseRequest() { core_.PauseRequest(); } @@ -262,7 +294,7 @@ void DownloadResourceHandler::OnStart( // download entirely. if (create_info->result == download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED && - create_info->download_id == download::DownloadItem::kInvalidId) { + create_info->is_new_download) { if (!callback.is_null()) BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, diff --git a/chromium/content/browser/download/download_resource_handler.h b/chromium/content/browser/download/download_resource_handler.h index 39f1982b309..2d206330813 100644 --- a/chromium/content/browser/download/download_resource_handler.h +++ b/chromium/content/browser/download/download_resource_handler.h @@ -44,7 +44,8 @@ class CONTENT_EXPORT DownloadResourceHandler // |id| should be invalid if the id should be automatically assigned. DownloadResourceHandler(net::URLRequest* request, const std::string& request_origin, - download::DownloadSource download_source); + download::DownloadSource download_source, + bool follow_cross_origin_redirects); // static // This function is passed into ResourceDispatcherHostImpl during its @@ -61,7 +62,8 @@ class CONTENT_EXPORT DownloadResourceHandler static std::unique_ptr<ResourceHandler> CreateForNewRequest( net::URLRequest* request, const std::string& request_origin, - download::DownloadSource download_source); + download::DownloadSource download_source, + bool follow_cross_origin_redirects); void OnRequestRedirected( const net::RedirectInfo& redirect_info, @@ -90,9 +92,6 @@ class CONTENT_EXPORT DownloadResourceHandler const net::URLRequestStatus& status, std::unique_ptr<ResourceController> controller) override; - // N/A to this flavor of DownloadHandler. - void OnDataDownloaded(int bytes_downloaded) override; - void PauseRequest(); void ResumeRequest(); @@ -120,6 +119,9 @@ class CONTENT_EXPORT DownloadResourceHandler // deletion must occur on the IO thread. std::unique_ptr<DownloadTabInfo> tab_info_; + bool follow_cross_origin_redirects_; + url::Origin first_origin_; + DownloadRequestCore core_; DISALLOW_COPY_AND_ASSIGN(DownloadResourceHandler); diff --git a/chromium/content/browser/download/download_utils.cc b/chromium/content/browser/download/download_utils.cc index ab0e360a306..fec2b6a861c 100644 --- a/chromium/content/browser/download/download_utils.cc +++ b/chromium/content/browser/download/download_utils.cc @@ -9,8 +9,8 @@ #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/task_scheduler/post_task.h" -#include "components/download/downloader/in_progress/download_entry.h" -#include "components/download/downloader/in_progress/in_progress_cache.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" 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 new file mode 100644 index 00000000000..973baed881d --- /dev/null +++ b/chromium/content/browser/download/file_download_url_loader_factory_getter.cc @@ -0,0 +1,44 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/download/file_download_url_loader_factory_getter.h" + +#include "base/task_scheduler/post_task.h" +#include "base/task_scheduler/task_traits.h" +#include "components/download/public/common/download_task_runner.h" +#include "content/browser/file_url_loader_factory.h" +#include "content/browser/url_loader_factory_getter.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" +#include "services/network/public/mojom/url_loader_factory.mojom.h" + +namespace content { + +FileDownloadURLLoaderFactoryGetter::FileDownloadURLLoaderFactoryGetter( + const GURL& url, + const base::FilePath& profile_path) + : url_(url), profile_path_(profile_path) { + DCHECK(url.SchemeIs(url::kFileScheme)); +} + +FileDownloadURLLoaderFactoryGetter::~FileDownloadURLLoaderFactoryGetter() = + default; + +scoped_refptr<network::SharedURLLoaderFactory> +FileDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() { + DCHECK(download::GetIOTaskRunner()->BelongsToCurrentThread()); + + network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info; + mojo::MakeStrongBinding( + std::make_unique<FileURLLoaderFactory>( + profile_path_, base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BACKGROUND, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), + MakeRequest(&url_loader_factory_ptr_info)); + + return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( + std::move(url_loader_factory_ptr_info)); +} + +} // namespace content 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 new file mode 100644 index 00000000000..9c3e79c7a13 --- /dev/null +++ b/chromium/content/browser/download/file_download_url_loader_factory_getter.h @@ -0,0 +1,36 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_DOWNLOAD_FILE_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ +#define CONTENT_BROWSER_DOWNLOAD_FILE_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ + +#include "base/files/file_path.h" +#include "components/download/public/common/download_url_loader_factory_getter.h" +#include "url/gurl.h" + +namespace content { + +// Class for retrieving the URLLoaderFactory for a file URL. +class FileDownloadURLLoaderFactoryGetter + : public download::DownloadURLLoaderFactoryGetter { + public: + FileDownloadURLLoaderFactoryGetter(const GURL& url, + const base::FilePath& profile_path); + + // download::DownloadURLLoaderFactoryGetter implementation. + scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; + + protected: + ~FileDownloadURLLoaderFactoryGetter() override; + + private: + GURL url_; + base::FilePath profile_path_; + + DISALLOW_COPY_AND_ASSIGN(FileDownloadURLLoaderFactoryGetter); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DOWNLOAD_FILE_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ diff --git a/chromium/content/browser/download/mhtml_generation_browsertest.cc b/chromium/content/browser/download/mhtml_generation_browsertest.cc index d3e9279628a..379cc3ac485 100644 --- a/chromium/content/browser/download/mhtml_generation_browsertest.cc +++ b/chromium/content/browser/download/mhtml_generation_browsertest.cc @@ -13,7 +13,7 @@ #include "base/macros.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/histogram_tester.h" +#include "base/test/metrics/histogram_tester.h" #include "base/threading/thread_restrictions.h" #include "components/download/public/common/download_task_runner.h" #include "content/browser/renderer_host/render_process_host_impl.h" diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc index 7035f3e49d4..0310f540c34 100644 --- a/chromium/content/browser/download/save_package.cc +++ b/chromium/content/browser/download/save_package.cc @@ -44,6 +44,7 @@ #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/common/frame_messages.h" #include "content/common/view_messages.h" #include "content/public/browser/browser_context.h" @@ -257,7 +258,8 @@ void SavePackage::InternalInit() { download::RecordSavePackageEvent(download::SAVE_PACKAGE_STARTED); - ukm_source_id_ = ukm::UkmRecorder::GetNewSourceID(); + ukm_source_id_ = static_cast<WebContentsImpl*>(web_contents()) + ->GetUkmSourceIdForLastCommittedSource(); ukm_download_id_ = download::GetUniqueDownloadId(); download::DownloadUkmHelper::RecordDownloadStarted( ukm_download_id_, ukm_source_id_, download::DownloadContent::TEXT, @@ -284,9 +286,6 @@ bool SavePackage::Init( std::unique_ptr<download::DownloadRequestHandleInterface> request_handle( new SavePackageRequestHandle(AsWeakPtr())); - download::DownloadUkmHelper::UpdateSourceURL( - ukm::UkmRecorder::Get(), ukm_source_id_, - web_contents()->GetLastCommittedURL()); RenderFrameHost* frame_host = web_contents()->GetMainFrame(); download_manager_->CreateSavePackageDownloadItem( saved_main_file_path_, page_url_, diff --git a/chromium/content/browser/download/url_downloader.cc b/chromium/content/browser/download/url_downloader.cc index 034fadddce8..e44234a31f5 100644 --- a/chromium/content/browser/download/url_downloader.cc +++ b/chromium/content/browser/download/url_downloader.cc @@ -13,6 +13,7 @@ #include "components/download/public/common/download_interrupt_reasons.h" #include "components/download/public/common/download_request_handle_interface.h" #include "components/download/public/common/download_url_parameters.h" +#include "components/download/public/common/url_download_request_handle.h" #include "content/browser/byte_stream.h" #include "content/browser/download/byte_stream_input_stream.h" #include "content/public/browser/browser_thread.h" @@ -25,43 +26,6 @@ namespace content { -class UrlDownloader::RequestHandle - : public download::DownloadRequestHandleInterface { - public: - RequestHandle(base::WeakPtr<UrlDownloader> downloader, - scoped_refptr<base::SequencedTaskRunner> downloader_task_runner) - : downloader_(downloader), - downloader_task_runner_(downloader_task_runner) {} - RequestHandle(RequestHandle&& other) - : downloader_(std::move(other.downloader_)), - downloader_task_runner_(std::move(other.downloader_task_runner_)) {} - RequestHandle& operator=(RequestHandle&& other) { - downloader_ = std::move(other.downloader_); - downloader_task_runner_ = std::move(other.downloader_task_runner_); - return *this; - } - - // DownloadRequestHandleInterface - void PauseRequest() override { - downloader_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&UrlDownloader::PauseRequest, downloader_)); - } - void ResumeRequest() override { - downloader_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&UrlDownloader::ResumeRequest, downloader_)); - } - void CancelRequest(bool user_cancel) override { - downloader_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&UrlDownloader::CancelRequest, downloader_)); - } - - private: - base::WeakPtr<UrlDownloader> downloader_; - scoped_refptr<base::SequencedTaskRunner> downloader_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(RequestHandle); -}; - // static std::unique_ptr<UrlDownloader> UrlDownloader::BeginDownload( base::WeakPtr<download::UrlDownloadHandler::Delegate> delegate, @@ -221,7 +185,7 @@ void UrlDownloader::OnStart( std::unique_ptr<download::DownloadCreateInfo> create_info, std::unique_ptr<ByteStreamReader> stream_reader, const download::DownloadUrlParameters::OnStartedCallback& callback) { - create_info->request_handle.reset(new RequestHandle( + create_info->request_handle.reset(new download::UrlDownloadRequestHandle( weak_ptr_factory_.GetWeakPtr(), base::SequencedTaskRunnerHandle::Get())); BrowserThread::PostTask( diff --git a/chromium/content/browser/download/url_downloader.h b/chromium/content/browser/download/url_downloader.h index 0ee10feddf7..e5b7289ea15 100644 --- a/chromium/content/browser/download/url_downloader.h +++ b/chromium/content/browser/download/url_downloader.h @@ -42,8 +42,6 @@ class UrlDownloader : public net::URLRequest::Delegate, bool is_parallel_request); private: - class RequestHandle; - void Start(); // URLRequest::Delegate: @@ -64,9 +62,10 @@ class UrlDownloader : public net::URLRequest::Delegate, override; void OnReadyToRead() override; - void PauseRequest(); - void ResumeRequest(); - void CancelRequest(); + // UrlDownloadHandler implementations. + void PauseRequest() override; + void ResumeRequest() override; + void CancelRequest() override; // Called when the UrlDownloader is done with the request. Posts a task to // remove itself from its download manager, which in turn would cause the diff --git a/chromium/content/browser/download/url_downloader_factory.cc b/chromium/content/browser/download/url_downloader_factory.cc index 752cea70a5d..5a66bd2b9fa 100644 --- a/chromium/content/browser/download/url_downloader_factory.cc +++ b/chromium/content/browser/download/url_downloader_factory.cc @@ -23,8 +23,7 @@ UrlDownloaderFactory::CreateUrlDownloadHandler( url_loader_factory_getter, const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { std::unique_ptr<net::URLRequest> url_request = - DownloadRequestCore::CreateRequestOnIOThread( - download::DownloadItem::kInvalidId, params.get()); + DownloadRequestCore::CreateRequestOnIOThread(true, params.get()); return download::UrlDownloadHandler::UniqueUrlDownloadHandlerPtr( UrlDownloader::BeginDownload(delegate, std::move(url_request), diff --git a/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc new file mode 100644 index 00000000000..c4873157c81 --- /dev/null +++ b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.cc @@ -0,0 +1,33 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/download/web_ui_download_url_loader_factory_getter.h" + +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_ui_url_loader_factory.h" +#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" + +namespace content { + +WebUIDownloadURLLoaderFactoryGetter::WebUIDownloadURLLoaderFactoryGetter( + RenderFrameHost* rfh, + const GURL& url) { + auto factory_request = mojo::MakeRequest(&factory_info_); + factory_ = + CreateWebUIURLLoader(rfh, url.scheme(), base::flat_set<std::string>()); + factory_->Clone(std::move(factory_request)); +} + +WebUIDownloadURLLoaderFactoryGetter::~WebUIDownloadURLLoaderFactoryGetter() { + BrowserThread::GetTaskRunnerForThread(BrowserThread::UI) + ->DeleteSoon(FROM_HERE, std::move(factory_)); +} + +scoped_refptr<network::SharedURLLoaderFactory> +WebUIDownloadURLLoaderFactoryGetter::GetURLLoaderFactory() { + return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>( + std::move(factory_info_)); +} + +} // namespace content diff --git a/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.h b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.h new file mode 100644 index 00000000000..5f39fd718c4 --- /dev/null +++ b/chromium/content/browser/download/web_ui_download_url_loader_factory_getter.h @@ -0,0 +1,40 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_DOWNLOAD_WEB_UI_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ +#define CONTENT_BROWSER_DOWNLOAD_WEB_UI_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ + +#include "base/files/file_path.h" +#include "components/download/public/common/download_url_loader_factory_getter.h" +#include "services/network/public/mojom/url_loader_factory.mojom.h" + +class GURL; + +namespace content { +class RenderFrameHost; + +// Class for retrieving the URLLoaderFactory for a webui URL. +class WebUIDownloadURLLoaderFactoryGetter + : public download::DownloadURLLoaderFactoryGetter { + public: + WebUIDownloadURLLoaderFactoryGetter(RenderFrameHost* rfh, const GURL& url); + + // download::DownloadURLLoaderFactoryGetter implementation. + scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override; + + protected: + ~WebUIDownloadURLLoaderFactoryGetter() override; + + private: + network::mojom::URLLoaderFactoryPtrInfo factory_info_; + + // Lives on the UI thread and must be deleted there. + std::unique_ptr<network::mojom::URLLoaderFactory> factory_; + + DISALLOW_COPY_AND_ASSIGN(WebUIDownloadURLLoaderFactoryGetter); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_DOWNLOAD_WEB_UI_DOWNLOAD_URL_LOADER_FACTORY_GETTER_H_ |