chromium/chrome/browser/download/download_browsertest.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include <stdint.h>

#include <algorithm>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include "base/base64.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_file_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/uuid.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_browsertest_utils.h"
#include "chrome/browser/download/download_commands.h"
#include "chrome/browser/download/download_core_service.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/download/download_crx_util.h"
#include "chrome/browser/download/download_history.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_item_web_app_data.h"
#include "chrome/browser/download/download_manager_utils.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/download/download_request_limiter.h"
#include "chrome/browser/download/download_shelf.h"
#include "chrome/browser/download/download_target_determiner.h"
#include "chrome/browser/download/download_test_file_activity_observer.h"
#include "chrome/browser/download/simple_download_manager_coordinator_factory.h"
#include "chrome/browser/extensions/install_verifier.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_key.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu_browsertest_util.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/download/public/common/download_danger_type.h"
#include "components/download/public/common/download_features.h"
#include "components/download/public/common/download_interrupt_reasons.h"
#include "components/download/public/common/download_item.h"
#include "components/download/public/common/in_progress_download_manager.h"
#include "components/history/content/browser/download_conversions.h"
#include "components/history/core/browser/download_constants.h"
#include "components/history/core/browser/download_row.h"
#include "components/history/core/browser/history_service.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/infobars/core/confirm_infobar_delegate.h"
#include "components/infobars/core/infobar.h"
#include "components/lookalikes/core/safety_tip_test_utils.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/permissions/permission_request_manager.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/content/browser/safe_browsing_service_interface.h"
#include "components/safe_browsing/content/common/file_type_policies_test_util.h"
#include "components/safe_browsing/content/common/proto/download_file_types.pb.h"
#include "components/safe_browsing/core/common/proto/csd.pb.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/security_state/core/security_state.h"
#include "components/services/quarantine/test_support.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/context_menu_params.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/storage_partition_config.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
#include "content/public/test/fenced_frame_test_util.h"
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/slow_download_http_response.h"
#include "content/public/test/test_download_http_response.h"
#include "content/public/test/test_file_error_injector.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/url_loader_interceptor.h"
#include "content/public/test/url_loader_monitor.h"
#include "extensions/browser/extension_dialog_auto_confirm.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/scoped_ignore_content_verifier_for_test.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/features.h"
#include "net/base/filename_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "net/test/scoped_mutually_exclusive_feature_list.h"
#include "net/test/url_request/url_request_mock_http_job.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "pdf/buildflags.h"
#include "services/device/public/mojom/wake_lock.mojom.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/network_utils.h"
#include "third_party/blink/public/common/loader/referrer_utils.h"
#include "third_party/blink/public/common/switches.h"
#include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/geometry/point_conversions.h"

#if !BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/download/bubble/download_bubble_ui_controller.h"
#include "chrome/browser/download/bubble/download_display_controller.h"
#include "chrome/browser/ui/download/download_display.h"
#endif

#if BUILDFLAG(FULL_SAFE_BROWSING)
#include "chrome/browser/safe_browsing/download_protection/download_feedback_service.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_service.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
#endif

#if BUILDFLAG(ENABLE_PDF)
#include "base/test/with_feature_override.h"
#include "chrome/browser/pdf/pdf_extension_test_util.h"
#include "chrome/browser/pdf/test_pdf_viewer_stream_manager.h"
#include "chrome/browser/ui/pdf/chrome_pdf_document_helper_client.h"
#include "components/pdf/browser/pdf_document_helper.h"
#include "pdf/pdf_features.h"
#endif

BrowserContext;
BrowserThread;
DownloadManager;
URLLoaderInterceptor;
URLLoaderMonitor;
WebContents;
DownloadItem;
DownloadUrlParameters;
Extension;
URLRequestMockHTTPJob;
EmbeddedTestServer;

namespace {

class InnerWebContentsAttachedWaiter : public content::WebContentsObserver {};

void VerifyNewDownloadId(uint32_t expected_download_id, uint32_t download_id) {}

class DownloadTestContentBrowserClient : public content::ContentBrowserClient {};

class CreatedObserver : public content::DownloadManager::Observer {};

class OnCanDownloadDecidedObserver {};

class PercentWaiter : public download::DownloadItem::Observer {};

// IDs and paths of CRX files used in tests.
const char kGoodCrxId[] =;
const char kGoodCrxPath[] =;

const char kLargeThemeCrxId[] =;
const char kLargeThemePath[] =;

// User script file used in tests.
const char kUserScriptPath[] =;

// Get History Information.
class DownloadsHistoryDataCollector {};

bool WasAutoOpened(DownloadItem* item) {}

bool IsDownloadExternallyRemoved(DownloadItem* item) {}

#if !BUILDFLAG(IS_CHROMEOS)
// Called when a download starts. Marks the download as hidden.
void SetHiddenDownloadCallback(DownloadItem* item,
                               download::DownloadInterruptReason reason) {}
#endif

class SimpleDownloadManagerCoordinatorWaiter
    : public download::SimpleDownloadManagerCoordinator::Observer {};

void CreateCompletedDownload(content::DownloadManager* download_manager,
                             const std::string& guid,
                             const base::FilePath target_path,
                             std::vector<GURL> url_chain,
                             int64_t file_size) {}

#if !BUILDFLAG(IS_CHROMEOS)
// Whether download UI is visible at all (download toolbar button for download
// bubble, or download shelf).
bool IsDownloadUiVisible(BrowserWindow* window) {}

// Whether download details are visible in the UI (partial view for download
// bubble, or download shelf).
bool IsDownloadDetailedUiVisible(BrowserWindow* window) {}
#endif

}  // namespace

class HistoryObserver : public DownloadHistory::Observer {};

class DownloadReferrerPolicyTest
    : public DownloadTestBase,
      public ::testing::WithParamInterface<network::mojom::ReferrerPolicy> {};

INSTANTIATE_TEST_SUITE_P();

class MPArchDownloadTest : public DownloadTestBase {};

class PrerenderDownloadTest : public MPArchDownloadTest {};

namespace {

class FakeDownloadProtectionService
    : public safe_browsing::DownloadProtectionService {};

class FakeSafeBrowsingService : public safe_browsing::TestSafeBrowsingService {};

// Factory that creates FakeSafeBrowsingService instances.
class TestSafeBrowsingServiceFactory
    : public safe_browsing::SafeBrowsingServiceFactory {};

class DownloadTestWithFakeSafeBrowsing : public DownloadTestBase {};

class DownloadWakeLockTest : public DownloadTestBase {};

}  // namespace

DownloadTest;

// NOTES:
//
// Files for these tests are found in DIR_TEST_DATA (currently
// "chrome\test\data\", see chrome_paths.cc).
// Mock responses have extension .mock-http-headers appended to the file name.

// Download a file due to the associated MIME type.
IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadMimeType) {}

#if BUILDFLAG(IS_WIN)
// Download a file and confirm that the file is correctly quarantined.
//
// TODO(asanka): We should enable the test on Mac as well, but currently
// |browser_tests| aren't run from a process that has LSFileQuarantineEnabled
// bit set.
IN_PROC_BROWSER_TEST_F(DownloadTest, Quarantine_DependsOnLocalConfig) {
  embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL url =
      embedded_test_server()->GetURL("/" + std::string(kDownloadTest1Path));

  // Download the file and wait.  We do not expect the Select File dialog.
  DownloadAndWait(browser(), url);

  // Check state.  Special file state must be checked before CheckDownload,
  // as CheckDownload will delete the output file.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());
  base::FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
  base::FilePath downloaded_file(DestinationFile(browser(), file));
  base::ScopedAllowBlockingForTesting allow_blocking;
  EXPECT_TRUE(quarantine::IsFileQuarantined(downloaded_file, url, GURL()));
  CheckDownload(browser(), file, file);
}

// A couple of Windows specific tests to make sure we respect OS specific
// restrictions on Mark-Of-The-Web can be applied. While Chrome doesn't directly
// apply these policies, Chrome still needs to make sure the correct APIs are
// invoked during the download process that result in the expected MOTW
// behavior.

// Downloading a file from the local host shouldn't cause the application of a
// zone identifier.
IN_PROC_BROWSER_TEST_F(DownloadTest, CheckLocalhostZone_DependsOnLocalConfig) {
  embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
  ASSERT_TRUE(embedded_test_server()->Start());

  // Assumes that localhost maps to 127.0.0.1. Otherwise the test will fail
  // since EmbeddedTestServer is listening on that address.
  GURL url =
      embedded_test_server()->GetURL("localhost", "/downloads/a_zip_file.zip");
  DownloadAndWait(browser(), url);
  base::FilePath file(FILE_PATH_LITERAL("a_zip_file.zip"));
  base::FilePath downloaded_file(DestinationFile(browser(), file));
  EXPECT_FALSE(quarantine::IsFileQuarantined(downloaded_file, GURL(), GURL()));
}

// Same as the test above, but uses a file:// URL to a local file.
IN_PROC_BROWSER_TEST_F(DownloadTest, CheckLocalFileZone_DependsOnLocalConfig) {
  base::FilePath source_file = GetTestDataDirectory()
                                   .AppendASCII("downloads")
                                   .AppendASCII("a_zip_file.zip");

  GURL url = net::FilePathToFileURL(source_file);
  DownloadAndWait(browser(), url);
  base::FilePath file(FILE_PATH_LITERAL("a_zip_file.zip"));
  base::FilePath downloaded_file(DestinationFile(browser(), file));
  EXPECT_FALSE(quarantine::IsFileQuarantined(downloaded_file, GURL(), GURL()));
}
#endif

// Put up a Select File dialog when the file is downloaded, due to
// downloads preferences settings.
IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadMimeTypeSelect) {}

// Access a file with a viewable mime-type, verify that a download
// did not initiate.
IN_PROC_BROWSER_TEST_F(DownloadTest, NoDownload) {}

// EmbeddedTestServer::HandleRequestCallback function that returns the relative
// URL as the MIME type.
// E.g.:
//   C -> S: GET /foo/bar =>
//   S -> C: HTTP/1.1 200 OK
//           Content-Type: foo/bar
//           ...
static std::unique_ptr<net::test_server::HttpResponse>
RespondWithContentTypeHandler(const net::test_server::HttpRequest& request) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, MimeTypesToShowNotDownload) {}

// Verify that when the DownloadResourceThrottle cancels a download, the
// download never makes it to the downloads system.
IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadResourceThrottleCancels) {}

// Test to make sure 'download' attribute in anchor tag doesn't trigger a
// download if DownloadRequestLimiter disallows it.
IN_PROC_BROWSER_TEST_F(DownloadTest,
                       DownloadRequestLimiterDisallowsAnchorDownloadTag) {}

// Verify that non-active main frame downloads (e.g. prerendering) don't affect
// the DownloadRequestLimiter state of the WebContents.
IN_PROC_BROWSER_TEST_F(PrerenderDownloadTest,
                       DownloadRequestLimiterIsUnaffectedByPrerendering) {}

class FencedFrameDownloadTest : public MPArchDownloadTest {};

// Verify that fenced frame downloads don't affect the DownloadRequestLimiter
// state of the WebContents.
IN_PROC_BROWSER_TEST_F(FencedFrameDownloadTest,
                       DownloadRequestLimiterIsUnaffectedByFencedFrame) {}

// Fenced frame forces download sandbox flag, which should prevent downloads
// from fenced frames.
IN_PROC_BROWSER_TEST_F(FencedFrameDownloadTest,
                       FencedFrameSandboxFlagBlockDownload) {}

// This test verifies when fenced frame untrusted network is disabled
// immediately after user right clicks and before "Save Image As..." is
// selected, the download request is blocked.
IN_PROC_BROWSER_TEST_F(FencedFrameDownloadTest, NetworkCutoffBlockSaveImageAs) {}

// Download a 0-size file with a content-disposition header, verify that the
// download tab opened and the file exists as the filename specified in the
// header.  This also ensures we properly handle empty file downloads.
IN_PROC_BROWSER_TEST_F(DownloadTest, ContentDisposition) {}

// UnknownSize and KnownSize are tests which depend on
// SlowDownloadHttpResponse to serve content in a certain way. Data will be
// sent in two chunks where the first chunk is 35K and the second chunk is 10K.
// The test will first attempt to download a file; but the server will "pause"
// in the middle until the server receives a second request for
// "download-finish".  At that time, the download will finish.
// These tests don't currently test much due to holes in |RunSizeTest()|.  See
// comments in that routine for details.
IN_PROC_BROWSER_TEST_F(DownloadTest, UnknownSize) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, KnownSize) {}

// Test that when downloading an item in Incognito mode, we don't crash when
// closing the last Incognito window (http://crbug.com/13983).
IN_PROC_BROWSER_TEST_F(DownloadTest, IncognitoDownload) {}

// Download one file on-record, then download the same file off-record, and test
// that the filename is deduplicated.  The previous test tests for a specific
// bug; this next test tests that filename deduplication happens independently
// of DownloadManager/CDMD.
IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadTest_IncognitoRegular) {}

// Navigate to a new background page, but don't download.
IN_PROC_BROWSER_TEST_F(DownloadTest, DontCloseNewTab1) {}

// Download a file in a background tab. Verify that the tab is closed
// automatically.
IN_PROC_BROWSER_TEST_F(DownloadTest, CloseNewTab1) {}

// Open a web page in the current tab, then download a file in another tab via
// a Javascript call.
// Verify that we have 2 tabs.
//
// The download_page1.html page contains an openNew() function that opens a
// tab and then downloads download-test1.lib.
IN_PROC_BROWSER_TEST_F(DownloadTest, DontCloseNewTab2) {}

// Open a web page in the current tab, open another tab via a Javascript call,
// then download a file in the new tab.
// Verify that we have 2 tabs.
//
// The download_page2.html page contains an openNew() function that opens a
// tab.
IN_PROC_BROWSER_TEST_F(DownloadTest, DontCloseNewTab3) {}

// Open a web page in the current tab, then download a file via Javascript,
// which will do so in a temporary tab. Verify that we have 1 tab.
//
// The download_page3.html page contains an openNew() function that opens a
// tab with download-test1.lib in the URL.  When the URL is determined to be
// a download, the tab is closed automatically.
IN_PROC_BROWSER_TEST_F(DownloadTest, CloseNewTab2) {}

// Open a web page in the current tab, then call Javascript via a button to
// download a file in a new tab, which is closed automatically when the
// download begins.
// Verify that we have 1 tab.
//
// The download_page4.html page contains a form with download-test1.lib as the
// action.
IN_PROC_BROWSER_TEST_F(DownloadTest, CloseNewTab3) {}

// Open a second tab, then download a file in that tab. However, have the
// download be canceled by having the file picker act like the user canceled
// the download. The 2nd tab should be closed automatically.
// TODO(xingliu): Figure out why this is working for network service.
IN_PROC_BROWSER_TEST_F(DownloadTest, CloseNewTab4) {}

// EmbeddedTestServer::HandleRequestCallback function that responds with a
// redirect to the URL specified via a query string.
// E.g.:
//   C -> S: GET /redirect?http://example.com
//   S -> C: HTTP/1.1 301 Moved Permanently
//           Location: http://example.com
//           ...
static std::unique_ptr<net::test_server::HttpResponse>
ServerRedirectRequestHandler(const net::test_server::HttpRequest& request) {}

#if BUILDFLAG(IS_WIN)
// https://crbug.com/788160
#define MAYBE_DownloadHistoryCheck
#else
#define MAYBE_DownloadHistoryCheck
#endif
IN_PROC_BROWSER_TEST_F(DownloadTest, MAYBE_DownloadHistoryCheck) {}

// Make sure a dangerous file shows up properly in the history.
IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadHistoryDangerCheck) {}

// Test for crbug.com/14505. This tests that chrome:// urls are still functional
// after download of a file while viewing another chrome://.
IN_PROC_BROWSER_TEST_F(DownloadTest, ChromeURLAfterDownload) {}

// Test for crbug.com/12745. This tests that if a download is initiated from
// a chrome:// page that has registered and onunload handler, the browser
// will be able to close.
IN_PROC_BROWSER_TEST_F(DownloadTest, BrowserCloseAfterDownload) {}

// Test to make sure the 'download' attribute in anchor tag is respected.
IN_PROC_BROWSER_TEST_F(DownloadTest, AnchorDownloadTag) {}

// Test that navigating to a user script URL will result in a download.
IN_PROC_BROWSER_TEST_F(DownloadTest, UserScriptDownload) {}

// Test to make sure auto-open works.
// High flake rate; https://crbug.com/1247392.
IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_AutoOpenByUser) {}

// Download an extension. Expect a dangerous download warning.
// Deny the download.
IN_PROC_BROWSER_TEST_F(DownloadTest, CrxDenyInstall) {}

// Download an extension.  Expect a dangerous download warning.
// Allow the download, deny the install.
IN_PROC_BROWSER_TEST_F(DownloadTest, CrxInstallDenysPermissions) {}

// Download an extension.  Expect a dangerous download warning.
// Allow the download, and the install.
IN_PROC_BROWSER_TEST_F(DownloadTest, CrxInstallAcceptPermissions) {}

// Test installing a CRX that fails integrity checks.
IN_PROC_BROWSER_TEST_F(DownloadTest, CrxInvalid) {}

// Install a large (100kb) theme.
IN_PROC_BROWSER_TEST_F(DownloadTest, CrxLargeTheme) {}

// Tests for download initiation functions.
IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadUrl) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadUrlToPath) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, TransientDownload) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, NullInitiator) {}

class DownloadTestSplitCacheEnabledBase : public DownloadTest {};

enum class SplitCacheTestCase {};

const struct {} kTestCaseToFeatureMapping[] =;

std::string GetSplitCacheTestName(SplitCacheTestCase test_case) {}

class DownloadTestSplitCacheEnabled
    : public DownloadTestSplitCacheEnabledBase,
      public testing::WithParamInterface<SplitCacheTestCase> {};

INSTANTIATE_TEST_SUITE_P();

#if BUILDFLAG(ENABLE_PDF)
class PdfDownloadTestSplitCacheEnabled
    : public DownloadTestSplitCacheEnabledBase,
      public testing::WithParamInterface<std::tuple<bool, SplitCacheTestCase>> {};

// Test that the PDF can be saved from the primary frame's context menu.
IN_PROC_BROWSER_TEST_P(
    PdfDownloadTestSplitCacheEnabled,
    SaveMainFramePdfFromPrimaryFrameContextMenuBrowserInitiatedNavigation) {}

// Same as above but using a renderer-initiated navigation from a cross-origin
// document.
IN_PROC_BROWSER_TEST_P(
    PdfDownloadTestSplitCacheEnabled,
    SaveMainFramePdfFromPrimaryFrameContextMenuRendererInitiatedNavigation) {}

// Test that the PDF can be saved from the PDf extension frame's context menu.
IN_PROC_BROWSER_TEST_P(
    PdfDownloadTestSplitCacheEnabled,
    SaveMainFramePdfFromExtensionFrameContextMenuBrowserInitiatedNavigation) {}
// Same as above but using a renderer-initiated navigation from a cross-origin
// document.
IN_PROC_BROWSER_TEST_P(
    PdfDownloadTestSplitCacheEnabled,
    SaveMainFramePdfFromExtensionFrameContextMenuRendererInitiatedNavigation) {}

// Test that the PDF can be saved from the PDF content frame's context menu.
IN_PROC_BROWSER_TEST_P(
    PdfDownloadTestSplitCacheEnabled,
    SaveMainFramePdfFromContentFrameContextMenuBrowserInitiatedNavigation) {}

// Same as above but using a renderer-initiated navigation from a cross-origin
// document.
IN_PROC_BROWSER_TEST_P(
    PdfDownloadTestSplitCacheEnabled,
    SaveMainFramePdfFromContentFrameContextMenuRendererInitiatedNavigation) {}

IN_PROC_BROWSER_TEST_P(PdfDownloadTestSplitCacheEnabled,
                       SaveSubframePdfFromPdfUIIsolationInfo) {}
#endif  // BUILDFLAG(ENABLE_PDF)

IN_PROC_BROWSER_TEST_P(DownloadTestSplitCacheEnabled,
                       SaveSubframeImageFromContextMenuIsolationInfo) {}

#if BUILDFLAG(ENABLE_PDF)
IN_PROC_BROWSER_TEST_P(PdfDownloadTestSplitCacheEnabled,
                       SaveSubframePdfFromContextMenuIsolationInfo) {}

// TODO(crbug.com/40268279): Stop testing both modes after OOPIF PDF viewer
// launches.
INSTANTIATE_TEST_SUITE_P();
#endif  // BUILDFLAG(ENABLE_PDF)

class DownloadTestWithHistogramTester : public DownloadTest {};

IN_PROC_BROWSER_TEST_F(DownloadTestWithHistogramTester,
                       DISABLED_SavePageNonHTMLViaGet) {}

// Times out often on debug ChromeOS because test is slow.
#if BUILDFLAG(IS_CHROMEOS_ASH) && \
    (!defined(NDEBUG) || defined(MEMORY_SANITIZER))
#define MAYBE_SaveLargeImage
#elif BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
    BUILDFLAG(IS_CHROMEOS)
// Flaking on Windows, macOS, Linux, ChromeOS. https://crbug.com/1141263
#define MAYBE_SaveLargeImage
#else
#define MAYBE_SaveLargeImage
#endif
// Tests saving an image from a data URL that's bigger than url::kMaxURLChars.
IN_PROC_BROWSER_TEST_F(DownloadTest, MAYBE_SaveLargeImage) {}

// A EmbeddedTestServer::HandleRequestCallback function that checks for requests
// with query string ?allow-post-only, and returns a 404 response if the method
// is not POST. Similar for ?allow-get-only.
static std::unique_ptr<net::test_server::HttpResponse>
FilterMethodSpecificURLsHandler(const net::test_server::HttpRequest& request) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, SavePageNonHTMLViaPost) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, SaveImageInPostPage) {}

// TODO(crbug.com/40840482): Flaky on lacros.
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#define MAYBE_DownloadErrorsServer
#else
#define MAYBE_DownloadErrorsServer
#endif
IN_PROC_BROWSER_TEST_F(DownloadTest, MAYBE_DownloadErrorsServer) {}

// TODO(crbug.com/40197726): Flaky on multiple platforms.
IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_DownloadErrorsServerNavigate404) {}

#if BUILDFLAG(IS_MAC)
// https://crbug.com/739766
#define MAYBE_DownloadErrorsFile
#else
#define MAYBE_DownloadErrorsFile
#endif

IN_PROC_BROWSER_TEST_F(DownloadTest, MAYBE_DownloadErrorsFile) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadErrorReadonlyFolder) {}

// Test that we show a dangerous downloads warning for a dangerous file
// downloaded through a blob: URL.
IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadDangerousBlobData) {}

// A EmbeddedTestServer::HandleRequestCallback function that echoes the Referrer
// header as its contents. Only responds to the relative URL /echoreferrer
// E.g.:
//    C -> S: GET /foo
//            Referer: http://example.com/foo
//    S -> C: HTTP/1.1 200 OK
//            Content-Type: text/plain
//
//            http://example.com/foo
static std::unique_ptr<net::test_server::HttpResponse>
EchoReferrerRequestHandler(const net::test_server::HttpRequest& request) {}

IN_PROC_BROWSER_TEST_P(DownloadReferrerPolicyTest,
                       AltClickDownloadReferrerPolicy) {}

// This test ensures that the Referer header is properly sanitized when
// Save Link As is chosen from the context menu from a page with all possible
// referrer policies.
IN_PROC_BROWSER_TEST_P(DownloadReferrerPolicyTest, SaveLinkAsReferrerPolicy) {}

// TODO(crbug.com/40804227): Flaky on Lacros
#if BUILDFLAG(IS_CHROMEOS)
#define MAYBE_SaveLinkAsVsCrossOriginResourcePolicy
#else
#define MAYBE_SaveLinkAsVsCrossOriginResourcePolicy
#endif
// This test ensures that Cross-Origin-Resource-Policy response header doesn't
// apply to download requests initiated via Save Link As context menu (such
// requests are considered browser-initiated).  See also
// https://crbug.com/952834.
IN_PROC_BROWSER_TEST_F(DownloadTest,
                       MAYBE_SaveLinkAsVsCrossOriginResourcePolicy) {}

// This test ensures that the Referer header is properly sanitized when
// Save Image As is chosen from the context menu.
IN_PROC_BROWSER_TEST_P(DownloadReferrerPolicyTest,
                       DISABLED_SaveImageAsReferrerPolicy) {}

// This test ensures that a cross-domain download correctly sets the referrer
// according to the referrer policy.
IN_PROC_BROWSER_TEST_P(DownloadReferrerPolicyTest,
                       DownloadCrossDomainReferrerPolicy) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, TestMultipleDownloadsRequests) {}

// Test the scenario for 3 consecutive downloads, where each is triggered by
// creating an iframe with srcdoc to another iframe with src to a downloadable
// file. Only the 1st download is expected to happen.
IN_PROC_BROWSER_TEST_F(DownloadTest, MultipleDownloadsFromIframeSrcdoc) {}

// Test <a download> download that triggers a x-origin redirect to another
// download. The download should succeed.
IN_PROC_BROWSER_TEST_F(DownloadTest,
                       CrossOriginRedirectDownloadFromAnchorDownload) {}

// Test the scenario for 3 consecutive <a download> download attempts that all
// trigger a x-origin redirect to another download. Only the redirected download
// resulted from the 1st <a download> attempt should succeed.
IN_PROC_BROWSER_TEST_F(DownloadTest,
                       MultipleCrossOriginRedirectDownloadsFromAnchorDownload) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadTest_Renaming) {}

// Test that the entire download pipeline handles unicode correctly.
// Disabled on Windows due to flaky timeouts: crbug.com/446695
#if BUILDFLAG(IS_WIN)
#define MAYBE_DownloadTest_CrazyFilenames
#else
#define MAYBE_DownloadTest_CrazyFilenames
#endif
IN_PROC_BROWSER_TEST_F(DownloadTest, MAYBE_DownloadTest_CrazyFilenames) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadTest_Remove) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadTest_PauseResumeCancel) {}

// The Mac downloaded files quarantine feature is implemented by the
// Contents/Info.plist file in cocoa apps. browser_tests cannot test
// quarantining files on Mac because it is not a cocoa app.
// TODO(benjhayden) test the equivalents on other platforms.

#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)) && \
    defined(ARCH_CPU_ARM_FAMILY)
// Timing out on ARM linux: http://crbug.com/238459
#define MAYBE_DownloadTest_PercentComplete
#else
#define MAYBE_DownloadTest_PercentComplete
#endif
IN_PROC_BROWSER_TEST_F(DownloadTest, MAYBE_DownloadTest_PercentComplete) {}

// A download that is interrupted due to a file error should be able to be
// resumed.
IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_NoPrompt) {}

// A download that's interrupted due to a reason that indicates that the target
// path is invalid or unusable should cause a prompt to be displayed on
// resumption.
IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_WithPrompt) {}

// The user shouldn't be prompted on a resumed download unless a prompt is
// necessary due to the interrupt reason.
IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_WithPromptAlways) {}

// A download that is interrupted due to a transient error should be resumed
// automatically.
IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_Automatic) {}

// An interrupting download should be resumable multiple times.
IN_PROC_BROWSER_TEST_F(DownloadTest, Resumption_MultipleAttempts) {}

// The file empty.bin is served with a MIME type of application/octet-stream.
// The content body is empty. Make sure this case is handled properly and we
// don't regress on http://crbug.com/320394.
IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadTest_GZipWithNoContent) {}

// Test that the SecurityLevel of the initiating page is used for the histogram
// rather than the SecurityLevel of the download URL, and that downloads in new
// tabs are not tracked.
IN_PROC_BROWSER_TEST_F(DownloadTest, SecurityLevels) {}

// Tests that opening the downloads page will cause file existence check.
IN_PROC_BROWSER_TEST_F(DownloadTest, FileExistenceCheckOpeningDownloadsPage) {}

// Checks that the navigation resulting from a cross origin download navigates
// the correct iframe.
IN_PROC_BROWSER_TEST_F(DownloadTest, CrossOriginDownloadNavigatesIframe) {}

// Test is flaky on multiple platforms.
// https://crbug.com/1064435
IN_PROC_BROWSER_TEST_F(DownloadWakeLockTest,
                       DISABLED_WakeLockAcquireAndCancel) {}

// Downloading a data URL that's bigger than url::kMaxURLChars should work.
// Flaky: https://crbug.com/1141278
IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_DownloadLargeDataURL) {}

// Testing the behavior of resuming with only in-progress download manager.
class InProgressDownloadTest : public DownloadTest {};

// Check that if a download exists in both in-progress and history DB,
// resuming the download after loading the in-progress DB and before
// history initialization will continue downloading the item even if it
// is in a terminal state in history DB.
IN_PROC_BROWSER_TEST_F(InProgressDownloadTest,
                       ResumeInProgressDownloadBeforeLoadingHistory) {}

// Check that InProgressDownloadManager can handle transient downloads with the
// same GUID.
IN_PROC_BROWSER_TEST_F(InProgressDownloadTest,
                       DownloadURLWithInProgressManager) {}

// Tests that download a canvas image will show the file chooser.
IN_PROC_BROWSER_TEST_F(DownloadTest, SaveCanvasImage) {}

// Tests that accept header is correctly set when using context menu to download
// an image.
IN_PROC_BROWSER_TEST_F(DownloadTest, ContextMenuSaveImageWithAcceptHeader) {}

#if BUILDFLAG(FULL_SAFE_BROWSING)

namespace {

// This is a custom DownloadTestObserver for
// DangerousFileWithSBDisabledBeforeCompletion test that disables the
// SafeBrowsing service when a single download is IN_PROGRESS and has a target
// path assigned.  DownloadItemImpl is expected to call MaybeCompleteDownload
// soon afterwards and we want to disable the service before then.
class DisableSafeBrowsingOnInProgressDownload
    : public content::DownloadTestObserver {};

}  // namespace

IN_PROC_BROWSER_TEST_F(DownloadTest,
                       DangerousFileWithSBDisabledBeforeCompletion) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, DangerousFileWithSBDisabledBeforeStart) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, SafeSupportedFile) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, FeedbackServiceDiscardDownload) {}

// TODO the test is flaky on Mac. See https://crbug.com/1345657.
#if BUILDFLAG(IS_MAC)
#define MAYBE_FeedbackServiceKeepDownload
#else
#define MAYBE_FeedbackServiceKeepDownload
#endif
IN_PROC_BROWSER_TEST_F(DownloadTest, MAYBE_FeedbackServiceKeepDownload) {}

IN_PROC_BROWSER_TEST_F(DownloadTestWithFakeSafeBrowsing,
                       SendUncommonDownloadReportIfUserProceed) {}

IN_PROC_BROWSER_TEST_F(DownloadTestWithFakeSafeBrowsing,
                       SendDownloadReportIfUserProceedsDeepScanning) {}

IN_PROC_BROWSER_TEST_F(DownloadTestWithFakeSafeBrowsing,
                       SendUncommonDownloadReportIfUserDiscard) {}

IN_PROC_BROWSER_TEST_F(DownloadTestWithFakeSafeBrowsing,
                       NoUncommonDownloadReportIfIncognito) {}

#endif  // FULL_SAFE_BROWSING

// The rest of these tests rely on the download surface, which ChromeOS doesn't
// use (crbug.com/1323505 is tracking Download Bubble on ChromeOS).
#if !BUILDFLAG(IS_CHROMEOS)
// Test that the download surface is shown by starting a download.
//
// TODO(crbug.com/40266279): This test is flaky. Perhaps because it depends on
// focus, in which case it should be an interactive ui test instead of a
// browser test?
IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_DownloadAndWait) {}

// Tests for the download shelf.
#if BUILDFLAG(IS_CHROMEOS_ASH)
// Test that the download shelf is per-window by starting a download in one
// tab, opening a second tab, closing the shelf, going back to the first tab,
// and checking that the shelf is closed.
IN_PROC_BROWSER_TEST_F(DownloadTest, PerWindowShelf) {
  embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL url = embedded_test_server()->GetURL("/download-test3.gif");
  base::FilePath download_file(
      FILE_PATH_LITERAL("download-test3-attachment.gif"));

  // Download a file and wait.
  DownloadAndWait(browser(), url);

  base::FilePath file(FILE_PATH_LITERAL("download-test3.gif"));
  CheckDownload(browser(), download_file, file);

  // Check state.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());
  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());

  // Open a second tab and wait.
  EXPECT_TRUE(chrome::AddSelectedTabWithURL(
      browser(), GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED));
  EXPECT_EQ(2, browser()->tab_strip_model()->count());
  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());

  // Hide the download shelf.
  browser()->window()->GetDownloadShelf()->Close();
  EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());

  // Go to the first tab.
  browser()->tab_strip_model()->ActivateTabAt(
      0, TabStripUserGestureDetails(
             TabStripUserGestureDetails::GestureType::kOther));
  EXPECT_EQ(2, browser()->tab_strip_model()->count());

  // The shelf should now be closed.
  EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());
}

// Check whether the downloads shelf is closed when the downloads tab is
// invoked.
IN_PROC_BROWSER_TEST_F(DownloadTest, CloseShelfOnDownloadsTab) {
  embedded_test_server()->ServeFilesFromDirectory(GetTestDataDirectory());
  ASSERT_TRUE(embedded_test_server()->Start());
  GURL url =
      embedded_test_server()->GetURL("/" + std::string(kDownloadTest1Path));

  // Download the file and wait.  We do not expect the Select File dialog.
  DownloadAndWait(browser(), url);

  // Check state.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());
  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());

  // Open the downloads tab.
  chrome::ShowDownloads(browser());
  // The download shelf should now be closed.
  EXPECT_FALSE(browser()->window()->IsDownloadShelfVisible());
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

// Flaky. crbug.com/1383009
// Test that when downloading an item in Incognito mode, the download surface is
// not visible after closing the Incognito window.
IN_PROC_BROWSER_TEST_F(DownloadTest,
                       DISABLED_IncognitoDownloadSurfaceVisibility) {}

// Download a file in a new window.
// Verify that we have 2 windows, and the download surface is not visible in the
// first window, but is visible in the second window.
// Close the new window.
// Verify that we have 1 window, and the download surface is not visible.
//
// Regression test for http://crbug.com/44454
// TODO(crbug.com/40262026): Flaky on Linux.
#if BUILDFLAG(IS_LINUX)
#define MAYBE_NewWindow
#else
#define MAYBE_NewWindow
#endif
IN_PROC_BROWSER_TEST_F(DownloadTest, MAYBE_NewWindow) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, PRE_DownloadTest_History) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadTest_History) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, HiddenDownload) {}

// High flake rate; https://crbug.com/1247392.
IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_AutoOpenClosesSurface) {}

IN_PROC_BROWSER_TEST_F(DownloadTest, CrxDenyInstallClosesSurface) {}

// Test that the download UI surface only shows on the appropriate window for a
// web app.
IN_PROC_BROWSER_TEST_F(DownloadTest, WebAppDownloadOnlyShowsUiInWebAppWindow) {}

// Test that the download UI surface only does not show in a web app window
// for a regular Chrome window's downloads, even if it is the same domain.
IN_PROC_BROWSER_TEST_F(DownloadTest,
                       RegularBrowserDownloadDoesNotShowInWebAppWindow) {}
#endif  // !BUILDFLAG(IS_CHROMEOS)

// Test that web app info is properly attached to the download.
IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadFromWebApp) {}