chromium/chrome/browser/download/chrome_download_manager_delegate_unittest.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.

#include "chrome/browser/download/chrome_download_manager_delegate.h"

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <optional>
#include <string>
#include <utility>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/uuid.h"
#include "build/build_config.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/download/download_core_service_impl.h"
#include "chrome/browser/download/download_item_model.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/download/insecure_download_blocking.h"
#include "chrome/browser/tab_group_sync/tab_group_sync_tab_state.h"
#include "chrome/common/buildflags.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/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.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_stats.h"
#include "components/download/public/common/download_target_info.h"
#include "components/download/public/common/mock_download_item.h"
#include "components/enterprise/buildflags/buildflags.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/content/common/file_type_policies_test_util.h"
#include "components/safe_search_api/safe_search_util.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/test/mock_download_manager.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "net/base/network_change_notifier.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/shell_dialogs/selected_file_info.h"
#include "url/origin.h"

#if BUILDFLAG(FULL_SAFE_BROWSING)
#include "chrome/browser/policy/dm_token_utils.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_service.h"
#include "chrome/browser/safe_browsing/download_protection/download_protection_util.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
#include "components/safe_browsing/core/common/features.h"
#include "components/safe_browsing/core/common/proto/csd.pb.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#endif

#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/public/browser/plugin_service.h"
#endif

#if BUILDFLAG(IS_ANDROID)
#include "base/android/build_info.h"
#include "chrome/browser/download/download_prompt_status.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_delegate.h"
#include "components/infobars/core/infobar_manager.h"
#endif

#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
#include "chrome/browser/enterprise/connectors/test/deep_scanning_test_utils.h"
#endif  // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)

DownloadItem;
DownloadPathReservationTracker;
PathValidationResult;
ConnectionType;
DownloadFileType;
_;
AnyNumber;
AtMost;
DoAll;
Invoke;
Ref;
Return;
ReturnArg;
ReturnPointee;
ReturnRef;
ReturnRefOfCopy;
SetArgPointee;
StrictMock;
WithArg;
Origin;

namespace {

class MockWebContentsDelegate : public content::WebContentsDelegate {};

ACTION_P3(ScheduleCallback2, result0, result1) {}

// Subclass of the ChromeDownloadManagerDelegate that replaces a few interaction
// points for ease of testing.
class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate {};

// A DownloadCoreService that returns the TestChromeDownloadManagerDelegate.
class TestDownloadCoreService : public DownloadCoreServiceImpl {};

TestDownloadCoreService::TestDownloadCoreService(Profile* profile)
    :{}

TestDownloadCoreService::~TestDownloadCoreService() = default;

ChromeDownloadManagerDelegate*
TestDownloadCoreService::GetDownloadManagerDelegate() {}

static std::unique_ptr<KeyedService> CreateTestDownloadCoreService(
    content::BrowserContext* browser_context) {}

class ChromeDownloadManagerDelegateTest
    : public ChromeRenderViewHostTestHarness {};

ChromeDownloadManagerDelegateTest::ChromeDownloadManagerDelegateTest()
    :{}

void ChromeDownloadManagerDelegateTest::SetUp() {}

void ChromeDownloadManagerDelegateTest::TearDown() {}

void ChromeDownloadManagerDelegateTest::VerifyAndClearExpectations() {}

std::unique_ptr<download::MockDownloadItem>
ChromeDownloadManagerDelegateTest::CreateActiveDownloadItem(int32_t id) {}

base::FilePath ChromeDownloadManagerDelegateTest::GetPathInDownloadDir(
    const char* relative_path) {}

download::DownloadTargetInfo
ChromeDownloadManagerDelegateTest::DetermineDownloadTarget(
    DownloadItem* download_item) {}

void ChromeDownloadManagerDelegateTest::OnConfirmationCallbackComplete(
    DownloadTargetDeterminerDelegate::ConfirmationCallback callback,
    DownloadConfirmationResult result,
    const ui::SelectedFileInfo& selected_file_info) {}

TestChromeDownloadManagerDelegate*
    ChromeDownloadManagerDelegateTest::delegate() {}

content::MockDownloadManager*
    ChromeDownloadManagerDelegateTest::download_manager() {}

DownloadPrefs* ChromeDownloadManagerDelegateTest::download_prefs() {}

PrefService* ChromeDownloadManagerDelegateTest::pref_service() {}

std::unique_ptr<download::MockDownloadItem>
ChromeDownloadManagerDelegateTest::PrepareDownloadItemForInsecureBlocking(
    const GURL& download_url,
    const std::optional<Origin>& request_initiator,
    const std::optional<GURL>& redirect_url) {}

void ExpectExtensionOnlyIn(const InsecureDownloadExtensions& ext,
                           const std::string& initiator,
                           const std::string& download,
                           base::HistogramTester& tester) {}

// Determine download target for |download_item| after enabling active content
// download blocking with the |parameters| enabled. Verify |extension|,
// |interrupt_reason| and |insecure_download_status|. Used by
// BlockedAsActiveContent_ tests.
void ChromeDownloadManagerDelegateTest::VerifyMixedContentExtensionOverride(
    DownloadItem* download_item,
    const base::FieldTrialParams& parameters,
    InsecureDownloadExtensions extension,
    download::DownloadInterruptReason interrupt_reason,
    download::DownloadItem::InsecureDownloadStatus insecure_download_status) {}

}  // namespace

TEST_F(ChromeDownloadManagerDelegateTest, LastSavePath) {}

TEST_F(ChromeDownloadManagerDelegateTest, ConflictAction) {}

TEST_F(ChromeDownloadManagerDelegateTest, MaybeDangerousContent) {}

TEST_F(ChromeDownloadManagerDelegateTest, DragAndDropDangerous) {}

TEST_F(ChromeDownloadManagerDelegateTest, BlockedByPolicy) {}

TEST_F(ChromeDownloadManagerDelegateTest, NoSafetyChecksNotBlockedByPolicy) {}

#if BUILDFLAG(IS_ANDROID)
TEST_F(ChromeDownloadManagerDelegateTest, InterceptDownloadByOfflinePages) {
  const GURL kUrl("http://example.com/foo");
  std::string mime_type = "text/html";
  bool should_intercept = delegate()->InterceptDownloadIfApplicable(
      kUrl, "", "", mime_type, "", 10, false /*is_transient*/, nullptr);
  EXPECT_TRUE(should_intercept);

  should_intercept = delegate()->InterceptDownloadIfApplicable(
      kUrl, "", "", mime_type, "", 10, true /*is_transient*/, nullptr);
  EXPECT_FALSE(should_intercept);

  should_intercept = delegate()->InterceptDownloadIfApplicable(
      kUrl, "", "attachment" /*content_disposition*/, mime_type, "", 10,
      false /*is_transient*/, nullptr);
  EXPECT_FALSE(should_intercept);
}

namespace {
class TestDownloadMessageBridge : public DownloadMessageBridge {
 public:
  TestDownloadMessageBridge() = default;

  TestDownloadMessageBridge(const TestDownloadMessageBridge&) = delete;
  TestDownloadMessageBridge& operator=(const TestDownloadMessageBridge&) =
      delete;

  void ShowUnsupportedDownloadMessage(
      content::WebContents* web_contents) override {
    message_shown_count_++;
  }

  // Returns the number of times ShowUnsupportedDownloadMessage has been called.
  int GetMessageShownCount() { return message_shown_count_; }

 private:
  int message_shown_count_;
};

}  // namespace

TEST_F(ChromeDownloadManagerDelegateTest, InterceptDownloadForAutomotive) {
  if (!base::android::BuildInfo::GetInstance()->is_automotive()) {
    GTEST_SKIP() << "This test should only run on automotive.";
  }
  base::HistogramTester histograms;

  TestDownloadMessageBridge* message_bridge = new TestDownloadMessageBridge();
  delegate()->SetDownloadMessageBridgeForTesting(
      static_cast<DownloadMessageBridge*>(message_bridge));

  const GURL kUrl("http://example.com/foo");
  std::string mime_type = "image/png";
  bool should_intercept = delegate()->InterceptDownloadIfApplicable(
      kUrl, "", "", mime_type, "", 10, false /*is_transient*/, nullptr);
  EXPECT_FALSE(should_intercept);

  mime_type = "application/pdf";
  should_intercept = delegate()->InterceptDownloadIfApplicable(
      kUrl, "", "", mime_type, "", 10, false /*is_transient*/, nullptr);
  EXPECT_TRUE(should_intercept);
  histograms.ExpectUniqueSample("Download.Blocked.ContentType.Automotive",
                                download::DownloadContent::PDF, 1);

  EXPECT_EQ(1, message_bridge->GetMessageShownCount());
}
#endif

TEST_F(ChromeDownloadManagerDelegateTest,
       BlockedAsActiveContent_HttpsTargetOk) {}

TEST_F(ChromeDownloadManagerDelegateTest, BlockedAsActiveContent_HttpPageOk) {}

TEST_F(ChromeDownloadManagerDelegateTest,
       BlockedAsActiveContent_InferredInitiatorStillBlocked) {}

TEST_F(ChromeDownloadManagerDelegateTest, BlockedAsActiveContent_HttpChain) {}

TEST_F(ChromeDownloadManagerDelegateTest,
       BlockedAsActiveContent_BenignExtensionsIgnored) {}

// Verify that downloads initiated by a non-unique hostname are blocked and
// we record that the download was from a non-unique source.
TEST_F(ChromeDownloadManagerDelegateTest,
       BlockedAsActiveContent_NonUniqueInitiator) {}

// Verify that downloads from a non-unique download url aren't treated as secure
// nor do they record different metrics.
TEST_F(ChromeDownloadManagerDelegateTest,
       BlockedAsActiveContent_NonUniqueFinalUrl) {}

// Verify that downloads coming from localhost are considered secure.
TEST_F(ChromeDownloadManagerDelegateTest, BlockedAsActiveContent_Localhost) {}

// Verify that downloads initiated by localhost are considered secure.
TEST_F(ChromeDownloadManagerDelegateTest,
       BlockedAsActiveContent_LocalhostInitiator) {}

// Verify that insecure in a blob URL are considered secure.
TEST_F(ChromeDownloadManagerDelegateTest,
       BlockedAsActiveContent_BlobConsideredSecure) {}

TEST_F(ChromeDownloadManagerDelegateTest, BlockedAsActiveContent_SilentBlock) {}

TEST_F(ChromeDownloadManagerDelegateTest, BlockedAsActiveContent_Warn) {}

TEST_F(ChromeDownloadManagerDelegateTest, BlockedAsActiveContent_Block) {}

// MIXEDSCRIPT content setting only applies to Desktop.
#if !BUILDFLAG(IS_ANDROID)
TEST_F(ChromeDownloadManagerDelegateTest,
       BlockedAsActiveContent_PolicyOverride) {}

TEST_F(ChromeDownloadManagerDelegateTest, DownloadBlockedForSyncedTab) {}
#endif  // !BUILDFLAG(IS_ANDROID)

TEST_F(ChromeDownloadManagerDelegateTest, InsecureDownloadsBlocked) {}

// Verify that insecure downloads not blocked normally are blocked when
// HTTPS-First mode is enabled.
TEST_F(ChromeDownloadManagerDelegateTest,
       InsecureDownloadsBlocked_ExclusionsRemovedInHFM) {}

// Test that we block context-menu-initiated downloads if initiator is insecure.
TEST_F(ChromeDownloadManagerDelegateTest,
       InsecureDownloadsBlocked_InferredInitiatorBlocked) {}

TEST_F(ChromeDownloadManagerDelegateTest, WithoutHistoryDbNextId) {}

TEST_F(ChromeDownloadManagerDelegateTest, WithHistoryDbNextId) {}

TEST_F(ChromeDownloadManagerDelegateTest, SanitizeGoogleSearchLink) {}

#if !BUILDFLAG(IS_ANDROID)
namespace {
// Verify the file picker confirmation result matches |expected_result|. Run
// |completion_closure| on completion.
void VerifyFilePickerConfirmation(
    DownloadConfirmationResult expected_result,
    base::RepeatingClosure completion_closure,
    DownloadConfirmationResult result,
    const ui::SelectedFileInfo& selected_file_info) {}
}  // namespace

// Test that it is fine to remove a download before its file picker is being
// shown.
TEST_F(ChromeDownloadManagerDelegateTest,
       RemovingDownloadBeforeShowingFilePicker) {}
#endif  // BUILDFLAG(IS_ANDROID)

#if !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(ChromeDownloadManagerDelegateTest, ScheduleCancelForEphemeralWarning) {}

TEST_F(ChromeDownloadManagerDelegateTest,
       ScheduleCancelForEphemeralWarning_DownloadKept) {}
#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)

TEST_F(ChromeDownloadManagerDelegateTest, CancelAllEphemeralWarnings) {}
#endif  // !BUILDFLAG(IS_ANDROID)

#if BUILDFLAG(FULL_SAFE_BROWSING)
namespace {

ReportType;

struct SafeBrowsingTestParameters {};

class TestDownloadProtectionService
    : public safe_browsing::DownloadProtectionService {};

class FakeSafeBrowsingService : public safe_browsing::TestSafeBrowsingService {};

class ChromeDownloadManagerDelegateTestWithSafeBrowsing
    : public ChromeDownloadManagerDelegateTest,
      public ::testing::WithParamInterface<SafeBrowsingTestParameters> {};

void ChromeDownloadManagerDelegateTestWithSafeBrowsing::SetUp() {}

void ChromeDownloadManagerDelegateTestWithSafeBrowsing::TearDown() {}

const SafeBrowsingTestParameters kSafeBrowsingTestCases[] =;

INSTANTIATE_TEST_SUITE_P();

}  // namespace

TEST_P(ChromeDownloadManagerDelegateTestWithSafeBrowsing, CheckClientDownload) {}

TEST_P(ChromeDownloadManagerDelegateTestWithSafeBrowsing,
       SkipCheckClientDownload) {}

// Auto cancel is only available on platforms with download bubble.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(ChromeDownloadManagerDelegateTestWithSafeBrowsing,
       AutoCanceledReport_Sent) {}

TEST_F(ChromeDownloadManagerDelegateTestWithSafeBrowsing,
       AutoCanceledReport_NotSentStandardProtection) {}

TEST_F(ChromeDownloadManagerDelegateTestWithSafeBrowsing,
       AutoCanceledReport_NotSentNotDangerous) {}
#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)

TEST_F(ChromeDownloadManagerDelegateTestWithSafeBrowsing,
       CanceledReportAtShutdown_Persisted) {}

TEST_F(ChromeDownloadManagerDelegateTestWithSafeBrowsing,
       TrustedSourcesPolicyNotTrusted) {}

// TODO(crbug.com/41328715) Add a Windows version of this test.
#if !BUILDFLAG(IS_WIN)
TEST_F(ChromeDownloadManagerDelegateTestWithSafeBrowsing,
       TrustedSourcesPolicyTrusted) {}

TEST_F(ChromeDownloadManagerDelegateTestWithSafeBrowsing,
       TrustedSourcesDontExemptEnterpriseScans) {}
#endif  // !BUILDFLAG(IS_WIN)
#endif  // FULL_SAFE_BROWSING

#if BUILDFLAG(IS_ANDROID)

namespace {

class AndroidDownloadInfobarCounter
    : public infobars::InfoBarManager::Observer {
 public:
  explicit AndroidDownloadInfobarCounter(content::WebContents* web_contents)
      : infobar_manager_(
            infobars::ContentInfoBarManager::FromWebContents(web_contents)) {
    infobar_manager_->AddObserver(this);
  }

  ~AndroidDownloadInfobarCounter() override {
    infobar_manager_->RemoveObserver(this);
  }

  int CheckAndResetInfobarCount() {
    int count = infobar_count_;
    infobar_count_ = 0;
    return count;
  }

 private:
  void OnInfoBarAdded(infobars::InfoBar* infobar) override {
    if (infobar->delegate()->GetIdentifier() ==
        infobars::InfoBarDelegate::DUPLICATE_DOWNLOAD_INFOBAR_DELEGATE_ANDROID)
      ++infobar_count_;
    infobar->delegate()->InfoBarDismissed();
    infobar->RemoveSelf();
  }

  raw_ptr<infobars::ContentInfoBarManager> infobar_manager_ = nullptr;
  int infobar_count_ = 0;
};

class TestDownloadDialogBridge : public DownloadDialogBridge {
 public:
  TestDownloadDialogBridge() = default;

  TestDownloadDialogBridge(const TestDownloadDialogBridge&) = delete;
  TestDownloadDialogBridge& operator=(const TestDownloadDialogBridge&) = delete;

  // DownloadDialogBridge implementation.
  void ShowDialog(gfx::NativeWindow native_window,
                  int64_t total_bytes,
                  ConnectionType connection_type,
                  DownloadLocationDialogType dialog_type,
                  const base::FilePath& suggested_path,
                  Profile* profile,
                  DownloadDialogBridge::DialogCallback callback) override {
    dialog_shown_count_++;
    dialog_type_ = dialog_type;
    if (callback) {
      DownloadDialogResult result;
      result.location_result = DownloadLocationDialogResult::USER_CANCELED;
      std::move(callback).Run(std::move(result));
    }
  }

  // Returns the number of times ShowDialog has been called.
  int GetDialogShownCount() { return dialog_shown_count_; }

  // Returns the type of the last dialog that was called to be shown.
  DownloadLocationDialogType GetDialogType() { return dialog_type_; }

  // Resets the stored information.
  void ResetStoredVariables() {
    dialog_shown_count_ = 0;
    dialog_type_ = DownloadLocationDialogType::NO_DIALOG;
  }

 private:
  int dialog_shown_count_;
  DownloadLocationDialogType dialog_type_;
  DownloadTargetDeterminerDelegate::ConfirmationCallback
      dialog_complete_callback_;
};

}  // namespace

TEST_F(ChromeDownloadManagerDelegateTest, RequestConfirmation_Android) {
  DeleteContents();
  SetContents(CreateTestWebContents());

  base::test::ScopedFeatureList scoped_list;
  profile()->GetTestingPrefService()->SetInteger(
      prefs::kPromptForDownloadAndroid,
      static_cast<int>(DownloadPromptStatus::SHOW_PREFERENCE));

  enum class WebContents { AVAILABLE, NONE };
  enum class ExpectPath { FULL, EMPTY };
  struct {
    DownloadConfirmationReason confirmation_reason;
    DownloadConfirmationResult expected_result;
    WebContents web_contents;
    DownloadLocationDialogType dialog_type;
    ExpectPath path;
  } kTestCases[] = {
      // SAVE_AS
      {DownloadConfirmationReason::SAVE_AS,
       DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
       WebContents::AVAILABLE, DownloadLocationDialogType::NO_DIALOG,
       ExpectPath::FULL},
      {DownloadConfirmationReason::SAVE_AS,
       DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
       WebContents::NONE, DownloadLocationDialogType::NO_DIALOG,
       ExpectPath::FULL},

      // !web_contents
      {DownloadConfirmationReason::PREFERENCE,
       DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
       WebContents::NONE, DownloadLocationDialogType::NO_DIALOG,
       ExpectPath::FULL},
      {DownloadConfirmationReason::TARGET_CONFLICT,
       DownloadConfirmationResult::CANCELED, WebContents::NONE,
       DownloadLocationDialogType::NO_DIALOG, ExpectPath::EMPTY},
      {DownloadConfirmationReason::TARGET_NO_SPACE,
       DownloadConfirmationResult::CANCELED, WebContents::NONE,
       DownloadLocationDialogType::NO_DIALOG, ExpectPath::EMPTY},
      {DownloadConfirmationReason::TARGET_PATH_NOT_WRITEABLE,
       DownloadConfirmationResult::CANCELED, WebContents::NONE,
       DownloadLocationDialogType::NO_DIALOG, ExpectPath::EMPTY},
      {DownloadConfirmationReason::NAME_TOO_LONG,
       DownloadConfirmationResult::CANCELED, WebContents::NONE,
       DownloadLocationDialogType::NO_DIALOG, ExpectPath::EMPTY},

      // UNEXPECTED
      {DownloadConfirmationReason::UNEXPECTED,
       DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE,
       DownloadLocationDialogType::NO_DIALOG, ExpectPath::EMPTY},
      {DownloadConfirmationReason::UNEXPECTED,
       DownloadConfirmationResult::CANCELED, WebContents::NONE,
       DownloadLocationDialogType::NO_DIALOG, ExpectPath::EMPTY},

      // TARGET_CONFLICT
      {DownloadConfirmationReason::TARGET_CONFLICT,
       DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE,
       DownloadLocationDialogType::NAME_CONFLICT, ExpectPath::EMPTY},

      // Other error dialogs
      {DownloadConfirmationReason::TARGET_NO_SPACE,
       DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE,
       DownloadLocationDialogType::LOCATION_FULL, ExpectPath::EMPTY},
      {DownloadConfirmationReason::TARGET_PATH_NOT_WRITEABLE,
       DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE,
       DownloadLocationDialogType::LOCATION_NOT_FOUND, ExpectPath::EMPTY},
      {DownloadConfirmationReason::NAME_TOO_LONG,
       DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE,
       DownloadLocationDialogType::NAME_TOO_LONG, ExpectPath::EMPTY},
  };

  EXPECT_CALL(*delegate(), RequestConfirmation_(_, _, _, _))
      .WillRepeatedly(Invoke(
          delegate(),
          &TestChromeDownloadManagerDelegate::RequestConfirmationConcrete));
  base::FilePath fake_path = GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt"));
  GURL url("http://example.com");
  TestDownloadDialogBridge* dialog_bridge = new TestDownloadDialogBridge();
  delegate()->SetDownloadDialogBridgeForTesting(
      static_cast<DownloadDialogBridge*>(dialog_bridge));

  for (const auto& test_case : kTestCases) {
    std::unique_ptr<download::MockDownloadItem> download_item =
        CreateActiveDownloadItem(1);
    content::DownloadItemUtils::AttachInfoForTesting(
        download_item.get(), profile(),
        test_case.web_contents == WebContents::AVAILABLE ? web_contents()
                                                         : nullptr);
    EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(url));
    dialog_bridge->ResetStoredVariables();

    base::test::TestFuture<DownloadConfirmationResult,
                           const ui::SelectedFileInfo&>
        future;
    delegate()->RequestConfirmation(download_item.get(), fake_path,
                                    test_case.confirmation_reason,
                                    future.GetCallback());
    EXPECT_EQ(test_case.expected_result, future.Get<0>());
    EXPECT_EQ(test_case.path == ExpectPath::FULL
                  ? ui::SelectedFileInfo(fake_path)
                  : ui::SelectedFileInfo(),
              future.Get<1>());

    EXPECT_EQ(
        test_case.dialog_type != DownloadLocationDialogType::NO_DIALOG ? 1 : 0,
        dialog_bridge->GetDialogShownCount());
    EXPECT_EQ(test_case.dialog_type, dialog_bridge->GetDialogType());

    EXPECT_CALL(*download_item, GetState())
        .WillRepeatedly(Return(DownloadItem::COMPLETE));
    download_item->NotifyObserversDownloadUpdated();
  }
}
#endif  // BUILDFLAG(IS_ANDROID)