// Copyright 2020 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/safe_browsing/download_protection/deep_scanning_request.h"

#include <algorithm>
#include <unordered_map>

#include "base/command_line.h"
#include "base/containers/flat_map.h"
#include "base/containers/span.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/weak_ptr.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/chrome_download_manager_delegate.h"
#include "chrome/browser/download/download_core_service.h"
#include "chrome/browser/download/download_core_service_factory.h"
#include "chrome/browser/download/download_item_warning_data.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/enterprise/connectors/common.h"
#include "chrome/browser/enterprise/connectors/connectors_service.h"
#include "chrome/browser/enterprise/connectors/reporting/realtime_reporting_client.h"
#include "chrome/browser/enterprise/connectors/reporting/realtime_reporting_client_factory.h"
#include "chrome/browser/enterprise/connectors/test/deep_scanning_test_utils.h"
#include "chrome/browser/policy/dm_token_utils.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h"
#include "chrome/browser/safe_browsing/download_protection/download_item_metadata.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/download_protection/file_system_access_metadata.h"
#include "chrome/common/pref_names.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/download/public/common/mock_download_item.h"
#include "components/enterprise/common/proto/connectors.pb.h"
#include "components/enterprise/common/proto/synced/browser_events.pb.h"
#include "components/enterprise/connectors/core/common.h"
#include "components/enterprise/connectors/core/connectors_prefs.h"
#include "components/enterprise/connectors/core/features.h"
#include "components/enterprise/connectors/core/reporting_constants.h"
#include "components/enterprise/obfuscation/core/download_obfuscator.h"
#include "components/policy/core/common/cloud/dm_token.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/safe_browsing/core/common/features.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_item_utils.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "crypto/sha2.h"
#include "net/base/mime_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/ash/components/system/fake_statistics_provider.h"
#endif

#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
#include "chrome/browser/enterprise/data_protection/data_protection_features.h"
#endif

namespace safe_browsing {

using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::ReturnRefOfCopy;

namespace {

constexpr char kUserName[] = "test@chromium.org";

constexpr char kScanForDlpAndMalware[] = R"(
{
  "service_provider": "google",
  "enable": [
    {
      "url_list": ["*"],
      "tags": ["dlp", "malware"]
    }
  ],
  "block_until_verdict": 1
})";

constexpr char kScanForMalware[] = R"(
{
  "service_provider": "google",
  "enable": [
    {
      "url_list": ["*"],
      "tags": ["malware"]
    }
  ],
  "block_until_verdict": 1
})";

constexpr char kScanForDlp[] = R"(
{
  "service_provider": "google",
  "enable": [
    {
      "url_list": ["*"],
      "tags": ["dlp"]
    }
  ],
  "block_until_verdict": 1
})";

constexpr char kNoScan[] = R"({"service_provider": "google"})";

constexpr char kScanId[] = "scan_id";

std::string GetFileName(const std::string& full_path) {
#if BUILDFLAG(IS_CHROMEOS)
  return base::FilePath(full_path).BaseName().AsUTF8Unsafe();
#else
  return full_path;
#endif  // BUILDFLAG(IS_CHROMEOS)
}

#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
const std::set<std::string>* ExeMimeTypes() {
  static std::set<std::string> set = {"application/x-msdownload",
                                      "application/x-ms-dos-executable",
                                      "application/octet-stream"};
  return &set;
}

struct ForceSaveToCloudPrioritizationTestParams {
  std::vector<base::test::FeatureRef> enabled_features;
  std::vector<base::test::FeatureRef> disabled_features;
  enterprise_connectors::ContentAnalysisResponse response;
  DownloadCheckResult expected_result;
  const char* test_name;
};

// Helper to generate responses
enterprise_connectors::ContentAnalysisResponse CreateResponse(
    const std::vector<
        enterprise_connectors::TriggeredRule::ForceSaveToCloudDestination>&
        destinations) {
  enterprise_connectors::ContentAnalysisResponse response;
  auto* dlp_result = response.add_results();
  dlp_result->set_tag("dlp");
  dlp_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  for (auto destination : destinations) {
    auto* dlp_rule = dlp_result->add_triggered_rules();
    dlp_rule->set_action(
        enterprise_connectors::TriggeredRule::FORCE_SAVE_TO_CLOUD);
    dlp_rule->set_force_save_to_cloud_destination(destination);
  }
  return response;
}
#endif  // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)

// Helpers for the proto-base reporting events
chrome::cros::reporting::proto::UnscannedFileEvent CreateUnscannedFileEvent(
    const std::string& profile_identifier,
    const std::string& user_name,
    const std::string& file_name,
    const std::string& sha256,
    const std::string& content_type,
    size_t content_size,
    chrome::cros::reporting::proto::UnscannedFileEvent::UnscannedReason reason,
    chrome::cros::reporting::proto::EventResult event_result,
    bool include_referrer = true) {
  chrome::cros::reporting::proto::UnscannedFileEvent event;

  event.set_url("https://example.com/download.exe");
  event.set_tab_url("https://example.com/");
  event.set_source("");
  event.set_destination("");
  event.set_trigger(
      chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD);
  event.set_scan_id(kScanId);

  if (event_result ==
      chrome::cros::reporting::proto::EventResult::EVENT_RESULT_BYPASSED) {
    event.set_clicked_through(true);
  } else {
    event.set_clicked_through(false);
  }

  event.set_file_name(GetFileName(file_name));
  event.set_profile_identifier(profile_identifier);
  event.set_profile_user_name(user_name);

  event.set_download_digest_sha_256(sha256);
  event.set_content_type(content_type);
  event.set_content_size(content_size);
  event.set_unscanned_reason(reason);
  event.set_event_result(event_result);

  if (include_referrer &&
      base::FeatureList::IsEnabled(safe_browsing::kEnhancedFieldsForSecOps)) {
    auto* referrer = event.add_referrers();
    referrer->set_url("https://example.com/download.exe");
    referrer->set_ip("example.com");
  }

  return event;
}

chrome::cros::reporting::proto::SafeBrowsingDangerousDownloadEvent
CreateDangerousDownloadEvent(
    const std::string& url,
    const std::string& tab_url,
    const std::string& source,
    const std::string& destination,
    const std::string& file_name,
    const std::string& sha256,
    chrome::cros::reporting::proto::SafeBrowsingDangerousDownloadEvent::
        DangerousDownloadThreatType threat_type,
    chrome::cros::reporting::proto::DataTransferEventTrigger trigger,
    size_t content_size,
    chrome::cros::reporting::proto::EventResult event_result,
    const std::string& username,
    const std::string& profile_identifier,
    const std::string& scan_id,
    bool include_referrer = true) {
  chrome::cros::reporting::proto::SafeBrowsingDangerousDownloadEvent event;

  event.set_url(url);
  event.set_tab_url(tab_url);
  event.set_source(source);
  event.set_destination(destination);
  event.set_download_digest_sha256(sha256);
  event.set_content_type("application/octet-stream");
  event.set_content_size(content_size);
  event.set_scan_id(scan_id);
  event.set_trigger(trigger);
  event.set_clicked_through(false);

  if (include_referrer) {
    ::chrome::cros::reporting::proto::UrlInfo referrers;
    referrers.set_ip("example.com");
    referrers.set_url("https://example.com/download.exe");
    *event.add_referrers() = referrers;
  }

  event.set_file_name(GetFileName(file_name));
  event.set_profile_identifier(profile_identifier);
  event.set_profile_user_name(username);
  event.set_threat_type(threat_type);
  event.set_event_result(event_result);

  return event;
}

chrome::cros::reporting::proto::SafeBrowsingDangerousDownloadEvent
CreateDangerousDownloadEvent(
    const std::string& profile_identifier,
    const std::string& user_name,
    const std::string& file_name,
    chrome::cros::reporting::proto::SafeBrowsingDangerousDownloadEvent::
        DangerousDownloadThreatType threat_type,
    chrome::cros::reporting::proto::EventResult event_result,
    bool include_referrer = true) {
  return CreateDangerousDownloadEvent(
      /*url=*/"https://example.com/download.exe",
      /*tab_url=*/"https://example.com/",
      /*source=*/"",
      /*destination=*/"", file_name,
      /*sha256=*/
      "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
      threat_type,
      /*trigger=*/
      chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD,
      /*content_size=*/std::string("download contents").size(), event_result,
      user_name, profile_identifier,
      /*scan_id=*/kScanId, include_referrer);
}

#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
chrome::cros::reporting::proto::DlpSensitiveDataEvent
CreateDlpSensitiveDataEventForForceSaveToCloud(
    const std::string& profile_identifier,
    const std::string& user_name,
    const std::string& file_name,
    const std::string& destination) {
  chrome::cros::reporting::proto::DlpSensitiveDataEvent event;

  event.set_url("https://example.com/download.exe");
  event.set_tab_url("https://example.com/");
  event.set_source("");
  event.set_download_digest_sha_256(
      "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C");
  event.set_content_type("application/octet-stream");
  event.set_content_size(std::string("download contents").size());
  event.set_trigger(
      chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD);
  event.set_clicked_through(false);
  event.set_scan_id("scan_id");
  event.set_event_result(chrome::cros::reporting::proto::EventResult::
                             EVENT_RESULT_FORCED_SAVE_TO_CLOUD);

  auto* referrers = event.add_referrers();
  referrers->set_ip("example.com");
  referrers->set_url("https://example.com/download.exe");

  auto* triggered_rule = event.add_triggered_rule_info();
  triggered_rule->set_action(
      chrome::cros::reporting::proto::TriggeredRuleInfo::FORCE_SAVE_TO_CLOUD);
  triggered_rule->set_rule_name("dlp_rule");
  triggered_rule->set_rule_id(0);

  event.set_file_name(GetFileName(file_name));
  event.set_destination(destination);
  event.set_profile_identifier(profile_identifier);
  event.set_profile_user_name(user_name);

  return event;
}

chrome::cros::reporting::proto::DlpSensitiveDataEvent
CreateDlpSensitiveDataEvent(
    const std::string& url,
    const std::string& tab_url,
    const std::string& source,
    const std::string& destination,
    const std::string& file_name,
    const std::string& sha256,
    chrome::cros::reporting::proto::DataTransferEventTrigger trigger,
    const enterprise_connectors::ContentAnalysisResponse::Result& dlp_result,
    size_t content_size,
    chrome::cros::reporting::proto::EventResult event_result,
    const std::string& username,
    const std::string& profile_identifier,
    const std::string& scan_id,
    bool include_referrer = true) {
  chrome::cros::reporting::proto::DlpSensitiveDataEvent event;

  event.set_url(url);
  event.set_tab_url(tab_url);
  event.set_source(source);
  event.set_destination(destination);
  event.set_download_digest_sha_256(sha256);
  event.set_content_type("application/octet-stream");
  event.set_content_size(content_size);
  event.set_trigger(trigger);
  event.set_clicked_through(false);
  event.set_scan_id(scan_id);
  event.set_event_result(event_result);

  if (include_referrer) {
    auto* referrers = event.add_referrers();
    referrers->set_ip("example.com");
    referrers->set_url("https://example.com/download.exe");
  }

  for (const auto& rule : dlp_result.triggered_rules()) {
    auto* triggered_rule = event.add_triggered_rule_info();
    int rule_id = 0;
    if (base::StringToInt(rule.rule_id(), &rule_id)) {
      triggered_rule->set_rule_id(rule_id);
    }
    triggered_rule->set_rule_name(rule.rule_name());

    switch (rule.action()) {
      case enterprise_connectors::TriggeredRule::REPORT_ONLY:
        triggered_rule->set_action(
            chrome::cros::reporting::proto::TriggeredRuleInfo::REPORT_ONLY);
        break;
      case enterprise_connectors::TriggeredRule::WARN:
        triggered_rule->set_action(
            chrome::cros::reporting::proto::TriggeredRuleInfo::WARN);
        break;
      case enterprise_connectors::TriggeredRule::BLOCK:
        triggered_rule->set_action(
            chrome::cros::reporting::proto::TriggeredRuleInfo::BLOCK);
        break;
      case enterprise_connectors::TriggeredRule::FORCE_SAVE_TO_CLOUD:
        triggered_rule->set_action(chrome::cros::reporting::proto::
                                       TriggeredRuleInfo::FORCE_SAVE_TO_CLOUD);
        break;
      case enterprise_connectors::TriggeredRule::JUSTIFICATION_REQUIRED:
        triggered_rule->set_action(
            chrome::cros::reporting::proto::TriggeredRuleInfo::
                JUSTIFICATION_REQUIRED);
        break;
      case enterprise_connectors::TriggeredRule::KEEP_IN_MANAGED_CHROME:
        triggered_rule->set_action(
            chrome::cros::reporting::proto::TriggeredRuleInfo::
                KEEP_IN_MANAGED_CHROME);
        break;
      case enterprise_connectors::TriggeredRule::ACTION_UNSPECIFIED:
        triggered_rule->set_action(
            chrome::cros::reporting::proto::TriggeredRuleInfo::ACTION_UNKNOWN);
        break;
    }
  }

  event.set_file_name(GetFileName(file_name));
  event.set_profile_identifier(profile_identifier);
  event.set_profile_user_name(username);

  return event;
}

std::vector<ForceSaveToCloudPrioritizationTestParams>
GetForceSaveToCloudPrioritizationTestCases() {
  namespace dp_features = enterprise_data_protection;
  const auto response_gdrive =
      CreateResponse({enterprise_connectors::TriggeredRule::CORP_G_DRIVE});
  const auto response_onedrive =
      CreateResponse({enterprise_connectors::TriggeredRule::CORP_ONEDRIVE});
  const auto response_both =
      CreateResponse({enterprise_connectors::TriggeredRule::CORP_G_DRIVE,
                      enterprise_connectors::TriggeredRule::CORP_ONEDRIVE});

  return {
      // Cloud feature enabled
      {{dp_features::kEnableForceDownloadToCloud},
       {},
       response_gdrive,
       DownloadCheckResult::FORCE_SAVE_TO_GDRIVE,
       "CloudEnabledGDriveResponse"},
      {{dp_features::kEnableForceDownloadToCloud},
       {},
       response_onedrive,
       DownloadCheckResult::FORCE_SAVE_TO_ONEDRIVE,
       "CloudEnabledOneDriveResponse"},
      {{dp_features::kEnableForceDownloadToCloud},
       {},
       response_both,
       DownloadCheckResult::FORCE_SAVE_TO_GDRIVE,
       "CloudEnabledBothResponse"},

      // Cloud feature disabled (OneDrive falls back as conditionally allowed)
      {{},
       {dp_features::kEnableForceDownloadToCloud},
       response_gdrive,
       DownloadCheckResult::SENSITIVE_CONTENT_BLOCK,
       "CloudDisabledGDriveResponse"},
      {{},
       {dp_features::kEnableForceDownloadToCloud},
       response_onedrive,
       DownloadCheckResult::FORCE_SAVE_TO_ONEDRIVE,
       "CloudDisabledOneDriveResponse"},
      {{},
       {dp_features::kEnableForceDownloadToCloud},
       response_both,
       DownloadCheckResult::FORCE_SAVE_TO_ONEDRIVE,
       "CloudDisabledBothResponse"},
  };
}
#endif  // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)

}  // namespace

// Enum to select item type used for deep scanning metadata.
enum class MetadataSourceType { kDownloadItem, kFileSystemAccessWriteItem };

class FakeBinaryUploadService
    : public enterprise_connectors::BinaryUploadService {
 public:
  void MaybeUploadForDeepScanning(
      std::unique_ptr<enterprise_connectors::BinaryUploadRequest> request)
      override {
    last_request_ = request->content_analysis_request();
    const std::string& filename = request->filename();
    request->FinishRequest(saved_results_[filename],
                           saved_responses_[filename]);

    if (!quit_on_last_request_.is_null()) {
      if (++num_finished_requests_ == saved_responses_.size()) {
        quit_on_last_request_.Run();
      }
    }
  }

  void MaybeAcknowledge(
      std::unique_ptr<enterprise_connectors::BinaryUploadAck> ack) override {
    EXPECT_EQ(final_action_, ack->ack().final_action());
    ++num_acks_;
    ASSERT_TRUE(
        std::ranges::contains(requests_tokens_, ack->ack().request_token()));
  }

  void MaybeCancelRequests(
      std::unique_ptr<enterprise_connectors::BinaryUploadCancelRequests> cancel)
      override {
    was_cancelled_ = true;
    last_cancel_user_action_id_ = cancel->get_user_action_id();
  }

  bool was_cancelled() const { return was_cancelled_; }
  std::string last_cancel_user_action_id() const {
    return last_cancel_user_action_id_;
  }

  base::WeakPtr<enterprise_connectors::BinaryUploadService> AsWeakPtr()
      override {
    return weak_ptr_factory_.GetWeakPtr();
  }

  void SetResponse(const base::FilePath& path,
                   enterprise_connectors::ScanRequestUploadResult result,
                   enterprise_connectors::ContentAnalysisResponse response) {
    saved_results_[path.AsUTF8Unsafe()] = result;
    saved_responses_[path.AsUTF8Unsafe()] = response;
    requests_tokens_.push_back(response.request_token());
  }

  const enterprise_connectors::ContentAnalysisRequest& last_request() {
    return last_request_;
  }

  void SetQuitOnLastRequest(base::RepeatingClosure closure) {
    quit_on_last_request_ = std::move(closure);
  }

  void SetExpectedFinalAction(
      enterprise_connectors::ContentAnalysisAcknowledgement::FinalAction
          final_action) {
    final_action_ = final_action;
  }

  size_t num_finished_requests() { return num_finished_requests_; }
  size_t num_acks() { return num_acks_; }

  void Reset() {
    saved_results_.clear();
    saved_responses_.clear();
    requests_tokens_.clear();
    num_finished_requests_ = 0;
    num_acks_ = 0;
  }

 private:
  base::flat_map<std::string, enterprise_connectors::ScanRequestUploadResult>
      saved_results_;
  base::flat_map<std::string, enterprise_connectors::ContentAnalysisResponse>
      saved_responses_;
  enterprise_connectors::ContentAnalysisRequest last_request_;
  std::vector<std::string> requests_tokens_;
  enterprise_connectors::ContentAnalysisAcknowledgement::FinalAction
      final_action_ = enterprise_connectors::ContentAnalysisAcknowledgement::
          ACTION_UNSPECIFIED;

  base::RepeatingClosure quit_on_last_request_;
  size_t num_finished_requests_ = 0;
  size_t num_acks_ = 0;
  bool was_cancelled_ = false;
  std::string last_cancel_user_action_id_;
  base::WeakPtrFactory<FakeBinaryUploadService> weak_ptr_factory_{this};
};

class FakeDownloadProtectionService : public DownloadProtectionService {
 public:
  FakeDownloadProtectionService() : DownloadProtectionService(nullptr) {}

  void RequestFinished(DeepScanningRequest* request) override {}

  enterprise_connectors::BinaryUploadService* GetBinaryUploadService(
      Profile* profile,
      const enterprise_connectors::AnalysisSettings&) override {
    CHECK(profile);
    if (binary_upload_service_override_) {
      return binary_upload_service_override_;
    }
    return &binary_upload_service_;
  }

  FakeBinaryUploadService* GetFakeBinaryUploadService() {
    return &binary_upload_service_;
  }

  void set_binary_upload_service(
      enterprise_connectors::BinaryUploadService* service) {
    binary_upload_service_override_ = service;
  }

 private:
  FakeBinaryUploadService binary_upload_service_;
  raw_ptr<enterprise_connectors::BinaryUploadService>
      binary_upload_service_override_ = nullptr;
};

class DeepScanningRequestTest : public testing::Test {
 public:
  DeepScanningRequestTest() {
    SetFeatures(
        /*enabled=*/{safe_browsing::kEnhancedFieldsForSecOps},
        /*disabled=*/{});
  }

  void SetUp() override {
    profile_manager_ = std::make_unique<TestingProfileManager>(
        TestingBrowserProcess::GetGlobal());
    EXPECT_TRUE(profile_manager_->SetUp());
    profile_ = profile_manager_->CreateTestingProfile("test-user");

    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());

    download_path_ = temp_dir_.GetPath().AppendASCII("download.exe");
    for (const char* file_name : {"foo.txt", "bar.txt", "baz.txt"}) {
      base::FilePath final_path = temp_dir_.GetPath().AppendASCII(file_name);
      base::FilePath current_path =
          temp_dir_.GetPath().AppendASCII(base::StrCat({file_name, ".tmp"}));
      base::File file(current_path,
                      base::File::FLAG_CREATE | base::File::FLAG_WRITE);
      file.WriteAtCurrentPos(base::as_byte_span(std::string_view(file_name)));
      secondary_files_.push_back(current_path);
      secondary_files_targets_.push_back(final_path);
    }

    std::string download_contents = "download contents";
    download_hash_ = crypto::SHA256HashString(download_contents);
    tab_url_string_ = "https://example.com/";
    download_url_ = GURL("https://example.com/download.exe");
    tab_url_ = GURL(tab_url_string_);

    base::File download(download_path_,
                        base::File::FLAG_CREATE | base::File::FLAG_WRITE);
    download.WriteAtCurrentPos(base::as_byte_span(download_contents));
    download.Close();

    EXPECT_CALL(item_, GetFullPath()).WillRepeatedly(ReturnRef(download_path_));
    EXPECT_CALL(item_, GetTotalBytes())
        .WillRepeatedly(Return(download_contents.size()));
    EXPECT_CALL(item_, GetURL()).WillRepeatedly(ReturnRef(download_url_));
    EXPECT_CALL(item_, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url_));
    EXPECT_CALL(item_, GetHash()).WillRepeatedly(ReturnRef(download_hash_));
    EXPECT_CALL(item_, GetTargetFilePath())
        .WillRepeatedly(ReturnRef(download_path_));
    EXPECT_CALL(item_, GetMimeType())
        .WillRepeatedly(Return("application/octet-stream"));
    EXPECT_CALL(item_, GetUrlChain())
        .WillRepeatedly(ReturnRefOfCopy(std::vector<GURL>()));
    EXPECT_CALL(item_, GetTabReferrerUrl())
        .WillRepeatedly(ReturnRefOfCopy(GURL()));
    EXPECT_CALL(item_, GetDangerType())
        .WillRepeatedly(Return(download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS));
    EXPECT_CALL(item_, GetReceivedBytes()).WillRepeatedly(Return(0));
    EXPECT_CALL(item_, HasUserGesture()).WillRepeatedly(Return(false));
    EXPECT_CALL(item_, RequireSafetyChecks()).WillRepeatedly(Return(true));
    content::DownloadItemUtils::AttachInfoForTesting(&item_, profile_, nullptr);

    SetDMTokenForTesting(policy::DMToken::CreateValidToken("dm_token"));

    DownloadCoreServiceFactory::GetForBrowserContext(profile_)
        ->SetDownloadManagerDelegateForTesting(
            std::make_unique<ChromeDownloadManagerDelegate>(profile_));

    // Default source type for `DownloadItem` only tests.
    metadata_source_type_ = MetadataSourceType::kDownloadItem;

    // Create test web contents for setting FSA tab url.
    web_contents_ =
        content::WebContentsTester::CreateTestWebContents(profile_, nullptr);
    content::WebContentsTester::For(web_contents_.get())
        ->SetLastCommittedURL(tab_url_);
  }

  void TearDown() override {
    SetDMTokenForTesting(policy::DMToken::CreateEmptyToken());
    web_contents_.reset();
  }

  void AddUrlToProfilePrefList(const char* pref_name, const GURL& url) {
    ScopedListPrefUpdate(profile_->GetPrefs(), pref_name)
        ->Append(url.GetHost());
  }

  void SetFeatures(const std::vector<base::test::FeatureRef>& enabled,
                   const std::vector<base::test::FeatureRef>& disabled) {
    scoped_feature_list_.Reset();
    scoped_feature_list_.InitWithFeatures(enabled, disabled);
  }

  void ValidateDefaultSettings(
      const std::optional<enterprise_connectors::AnalysisSettings>& settings) {
    ASSERT_TRUE(settings.has_value());

    enterprise_connectors::AnalysisSettings default_settings;
    default_settings.tags = {{"malware", enterprise_connectors::TagSettings()}};
    enterprise_connectors::CloudAnalysisSettings cloud_settings;
    cloud_settings.analysis_url =
        GURL("https://safebrowsing.google.com/safebrowsing/uploads/scan");
    default_settings.cloud_or_local_settings =
        enterprise_connectors::CloudOrLocalAnalysisSettings(
            std::move(cloud_settings));
    default_settings.block_until_verdict =
        enterprise_connectors::BlockUntilVerdict::kBlock;

    for (const auto& tag : settings.value().tags) {
      ASSERT_EQ(tag.second.requires_justification,
                default_settings.tags[tag.first].requires_justification);
      ASSERT_EQ(tag.second.custom_message.message,
                default_settings.tags[tag.first].custom_message.message);
      ASSERT_EQ(tag.second.custom_message.learn_more_url,
                default_settings.tags[tag.first].custom_message.learn_more_url);
    }
    ASSERT_EQ(settings.value().block_large_files,
              default_settings.block_large_files);
    ASSERT_EQ(settings.value().block_password_protected_files,
              default_settings.block_password_protected_files);
    ASSERT_EQ(settings.value().block_until_verdict,
              default_settings.block_until_verdict);
    ASSERT_EQ(settings.value().cloud_or_local_settings.analysis_url(),
              default_settings.cloud_or_local_settings.analysis_url());
  }

  void SetLastResult(DownloadCheckResult result) { last_result_ = result; }

  std::optional<enterprise_connectors::AnalysisSettings> settings() {
    std::unique_ptr<DeepScanningMetadata> metadata = CreateMetadata();
    return DeepScanningRequest::ShouldUploadBinary(*metadata);
  }

  std::unique_ptr<DeepScanningMetadata> CreateMetadata() {
    switch (metadata_source_type_) {
      case MetadataSourceType::kDownloadItem:
        return std::make_unique<DownloadItemMetadata>(&item_);
      case MetadataSourceType::kFileSystemAccessWriteItem:
        auto write_item =
            std::make_unique<content::FileSystemAccessWriteItem>();
        write_item->target_file_path = download_path_;
        write_item->full_path = download_path_;
        write_item->frame_url = download_url_;
        write_item->browser_context = profile_;
        if (web_contents_) {
          write_item->web_contents = web_contents_->GetWeakPtr();
        }
        write_item->size = item_.GetTotalBytes();
        write_item->sha256_hash = download_hash_;
        write_item->has_user_gesture = false;

        return std::make_unique<FileSystemAccessMetadata>(
            std::move(write_item));
    }
    return nullptr;
  }

  void SetMetadataSourceType(MetadataSourceType type) {
    metadata_source_type_ = type;
  }

  TestingProfile* profile() { return profile_; }

 protected:
  base::test::ScopedFeatureList scoped_feature_list_;
  content::BrowserTaskEnvironment task_environment_;
  std::unique_ptr<TestingProfileManager> profile_manager_;
  raw_ptr<TestingProfile> profile_;

  FakeDownloadProtectionService download_protection_service_;
  download::MockDownloadItem item_;

  base::ScopedTempDir temp_dir_;
  base::FilePath download_path_;
  std::vector<base::FilePath> secondary_files_;
  std::vector<base::FilePath> secondary_files_targets_;
  GURL download_url_;
  GURL tab_url_;
  std::string tab_url_string_;
  std::string download_hash_;

  DownloadCheckResult last_result_;

  MetadataSourceType metadata_source_type_;
  std::unique_ptr<content::WebContents> web_contents_;
  content::RenderViewHostTestEnabler enabler_;
};

class DeepScanningRequestSourceTypeTest
    : public DeepScanningRequestTest,
      public testing::WithParamInterface<MetadataSourceType> {
 public:
  void SetUp() override {
    DeepScanningRequestTest::SetUp();
    SetMetadataSourceType(GetParam());
  }
};

class DeepScanningRequestFeaturesEnabledTest
    : public DeepScanningRequestSourceTypeTest {};

TEST_P(DeepScanningRequestFeaturesEnabledTest, ChecksFeatureFlags) {
  enterprise_connectors::test::SetAnalysisConnector(
      profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
      kScanForDlpAndMalware);

  // Try each request with settings indicating both DLP and Malware requests
  // should be sent to show features work correctly.
  auto dlp_and_malware_settings = []() {
    enterprise_connectors::AnalysisSettings settings;
    settings.tags = {{"dlp", enterprise_connectors::TagSettings()},
                     {"malware", enterprise_connectors::TagSettings()}};
    settings.block_until_verdict =
        enterprise_connectors::BlockUntilVerdict::kBlock;
    return settings;
  };

  // A request using the Connector protos doesn't account for the 2 legacy
  // feature flags, so the 2 tags should always stay.
  auto expect_dlp_and_malware_tags = [this]() {
    EXPECT_EQ(2, download_protection_service_.GetFakeBinaryUploadService()
                     ->last_request()
                     .tags_size());

    EXPECT_EQ("dlp", download_protection_service_.GetFakeBinaryUploadService()
                         ->last_request()
                         .tags(0));
    EXPECT_EQ("malware",
              download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .tags(1));
    EXPECT_TRUE(download_protection_service_.GetFakeBinaryUploadService()
                    ->last_request()
                    .blocking());
  };

  {
    base::RunLoop run_loop;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](base::RepeatingClosure closure, DownloadCheckResult result) {
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                closure.Run();
              }
            },
            run_loop.QuitClosure()),
        &download_protection_service_, dlp_and_malware_settings(),
        /*password=*/std::nullopt);

    request.Start();
    run_loop.Run();
    expect_dlp_and_malware_tags();
  }
}

TEST_P(DeepScanningRequestFeaturesEnabledTest, VerifyBlockingSet) {
  enterprise_connectors::test::SetAnalysisConnector(
      profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
      kScanForDlpAndMalware);

  auto no_block_settings = []() {
    enterprise_connectors::AnalysisSettings settings;
    settings.block_until_verdict =
        enterprise_connectors::BlockUntilVerdict::kNoBlock;
    return settings;
  };

  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](base::RepeatingClosure closure, DownloadCheckResult result) {
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              closure.Run();
            }
          },
          run_loop.QuitClosure()),
      &download_protection_service_, no_block_settings(),
      /*password=*/std::nullopt);

  request.Start();
  run_loop.Run();
  EXPECT_FALSE(download_protection_service_.GetFakeBinaryUploadService()
                   ->last_request()
                   .blocking());
}

INSTANTIATE_TEST_SUITE_P(
    FeaturesEnabled,
    DeepScanningRequestFeaturesEnabledTest,
    testing::Values(MetadataSourceType::kDownloadItem,
                    MetadataSourceType::kFileSystemAccessWriteItem));

class DeepScanningRequestAllFeaturesEnabledTest
    : public DeepScanningRequestSourceTypeTest {};

TEST_P(DeepScanningRequestAllFeaturesEnabledTest,
       GeneratesCorrectRequestFromPolicy) {
  {
    enterprise_connectors::test::SetAnalysisConnector(
        profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
        kScanForDlpAndMalware);
    // Override mime type to platform-independent value for testing.
    net::ScopedOverrideGetMimeTypeForTesting override_mime_type(
        "application/octet-stream");
    base::RunLoop run_loop;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](base::RepeatingClosure closure, DownloadCheckResult result) {
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                closure.Run();
              }
            },
            run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    request.Start();
    run_loop.Run();
    EXPECT_EQ(2, download_protection_service_.GetFakeBinaryUploadService()
                     ->last_request()
                     .tags_size());
    EXPECT_EQ("dlp", download_protection_service_.GetFakeBinaryUploadService()
                         ->last_request()
                         .tags(0));
    EXPECT_EQ("malware",
              download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .tags(1));
    EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .request_data()
                  .url(),
              download_url_.spec());
    EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .request_data()
                  .tab_url(),
              GURL("https://example.com"));
    EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .request_data()
                  .content_type(),
              "application/octet-stream");
    EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .reason(),
              enterprise_connectors::ContentAnalysisRequest::NORMAL_DOWNLOAD);
  }

  {
    base::RunLoop run_loop;
    enterprise_connectors::test::SetAnalysisConnector(
        profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
        kScanForMalware);
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](base::RepeatingClosure closure, DownloadCheckResult result) {
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                closure.Run();
              }
            },
            run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    request.Start();
    run_loop.Run();
    EXPECT_EQ(1, download_protection_service_.GetFakeBinaryUploadService()
                     ->last_request()
                     .tags_size());
    EXPECT_EQ("malware",
              download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .tags(0));
    EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .reason(),
              enterprise_connectors::ContentAnalysisRequest::NORMAL_DOWNLOAD);
  }

  {
    base::RunLoop run_loop;
    enterprise_connectors::test::SetAnalysisConnector(
        profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
        kScanForDlp);
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](base::RepeatingClosure closure, DownloadCheckResult result) {
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                closure.Run();
              }
            },
            run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    request.Start();
    run_loop.Run();
    EXPECT_EQ(1, download_protection_service_.GetFakeBinaryUploadService()
                     ->last_request()
                     .tags_size());
    EXPECT_EQ("dlp", download_protection_service_.GetFakeBinaryUploadService()
                         ->last_request()
                         .tags(0));
    EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .reason(),
              enterprise_connectors::ContentAnalysisRequest::NORMAL_DOWNLOAD);
  }

  {
    base::RunLoop run_loop;
    enterprise_connectors::test::SetAnalysisConnector(
        profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED, kNoScan);
    EXPECT_FALSE(settings().has_value());
    enterprise_connectors::AnalysisSettings analysis_settings;
    analysis_settings.block_until_verdict =
        enterprise_connectors::BlockUntilVerdict::kBlock;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](base::RepeatingClosure closure, DownloadCheckResult result) {
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                closure.Run();
              }
            },
            run_loop.QuitClosure()),
        &download_protection_service_, std::move(analysis_settings),
        /*password=*/std::nullopt);

    request.Start();
    run_loop.Run();
    EXPECT_TRUE(download_protection_service_.GetFakeBinaryUploadService()
                    ->last_request()
                    .tags()
                    .empty());
    EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                  ->last_request()
                  .reason(),
              enterprise_connectors::ContentAnalysisRequest::NORMAL_DOWNLOAD);
  }
}

class DeepScanningAPPRequestTest : public DeepScanningRequestTest {};

class TestCancellationFakeBinaryUploadService : public FakeBinaryUploadService {
 public:
  void set_synchronous_cancel(bool sync) { synchronous_cancel_ = sync; }
  void SetQuitOnUploadCallback(base::OnceClosure closure) {
    quit_on_upload_ = std::move(closure);
  }

  void MaybeUploadForDeepScanning(
      std::unique_ptr<enterprise_connectors::BinaryUploadRequest> request)
      override {
    pending_request_ = std::move(request);
    if (quit_on_upload_) {
      std::move(quit_on_upload_).Run();
    }
  }

  void MaybeCancelRequests(
      std::unique_ptr<enterprise_connectors::BinaryUploadCancelRequests> cancel)
      override {
    FakeBinaryUploadService::MaybeCancelRequests(std::move(cancel));
    if (pending_request_ && synchronous_cancel_) {
      pending_request_->FinishRequest(
          enterprise_connectors::ScanRequestUploadResult::kUserCancelled,
          enterprise_connectors::ContentAnalysisResponse());
      pending_request_.reset();
    }
  }

 private:
  std::unique_ptr<enterprise_connectors::BinaryUploadRequest> pending_request_;
  bool synchronous_cancel_ = false;
  base::OnceClosure quit_on_upload_;
};

class TouchObserver : public DeepScanningRequest::Observer {
 public:
  void OnFinish(DeepScanningRequest* request) override { ++on_finish_called_; }

  int on_finish_called() const { return on_finish_called_; }

 private:
  int on_finish_called_ = 0;
};

TEST_F(DeepScanningAPPRequestTest, FinishRequestCalledOnceWithCancellation) {
  for (bool synchronous_cancel : {true, false}) {
    TestCancellationFakeBinaryUploadService cancel_upload_service;
    cancel_upload_service.set_synchronous_cancel(synchronous_cancel);
    download_protection_service_.set_binary_upload_service(
        &cancel_upload_service);

    enterprise_connectors::AnalysisSettings settings;
    settings.tags = {{"malware", enterprise_connectors::TagSettings()}};

    std::unique_ptr<DeepScanningRequest> request =
        std::make_unique<DeepScanningRequest>(
            CreateMetadata(),
            DownloadItemWarningData::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
            DownloadCheckResult::SAFE, base::DoNothing(),
            &download_protection_service_, std::move(settings),
            /*password=*/std::nullopt);

    TouchObserver touch_observer;
    request->AddObserver(&touch_observer);

    request->Start();
    request->OnDownloadDestroyed(&item_);

    // Regardless of whether the cancellation executes synchronously or
    // asynchronously, the WeakPtr guard inside OnDownloadDestroyed ensures
    // FinishRequest (and thus OnFinish) is called exactly once to clear state.
    EXPECT_EQ(touch_observer.on_finish_called(), 1);

    download_protection_service_.set_binary_upload_service(nullptr);
  }
}

TEST_F(DeepScanningAPPRequestTest,
       DownloadDestroyedNullBrowserContextCrashTest) {
  // Overwrite the item's browser context with nullptr to simulate a normal
  // download destruction where the browser context is lost.
  content::DownloadItemUtils::AttachInfoForTesting(&item_, nullptr, nullptr);

  enterprise_connectors::AnalysisSettings settings;
  settings.tags = {{"malware", enterprise_connectors::TagSettings()}};

  std::unique_ptr<DeepScanningRequest> request =
      std::make_unique<DeepScanningRequest>(
          CreateMetadata(),
          DownloadItemWarningData::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
          DownloadCheckResult::SAFE, base::DoNothing(),
          &download_protection_service_, std::move(settings),
          /*password=*/std::nullopt);

  // OnDownloadDestroyed should successfully complete and call FinishRequest /
  // AcknowledgeRequest without any null-dereference crashes because of the new
  // null guards.
  request->OnDownloadDestroyed(&item_);
}

TEST_F(DeepScanningAPPRequestTest, CancelsUploadOnDownloadDestroyed) {
  enterprise_connectors::AnalysisSettings settings;
  settings.tags = {{"malware", enterprise_connectors::TagSettings()}};

  std::unique_ptr<DeepScanningRequest> request =
      std::make_unique<DeepScanningRequest>(
          CreateMetadata(),
          DownloadItemWarningData::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
          DownloadCheckResult::SAFE, base::DoNothing(),
          &download_protection_service_, std::move(settings),
          /*password=*/std::nullopt);

  std::string user_action_id = request->user_action_id();
  request->Start();

  request->OnDownloadDestroyed(&item_);

  EXPECT_TRUE(download_protection_service_.GetFakeBinaryUploadService()
                  ->was_cancelled());
  EXPECT_EQ(user_action_id,
            download_protection_service_.GetFakeBinaryUploadService()
                ->last_cancel_user_action_id());
}

TEST_F(DeepScanningAPPRequestTest, GeneratesCorrectRequestForConsumer) {
  enterprise_connectors::AnalysisSettings settings;
  settings.tags = {{"malware", enterprise_connectors::TagSettings()}};
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](base::RepeatingClosure closure, DownloadCheckResult result) {
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              closure.Run();
            }
          },
          run_loop.QuitClosure()),
      &download_protection_service_, std::move(settings),
      /*password=*/std::nullopt);

  request.Start();
  run_loop.Run();

  EXPECT_EQ(1, download_protection_service_.GetFakeBinaryUploadService()
                   ->last_request()
                   .tags()
                   .size());
  EXPECT_EQ("malware",
            download_protection_service_.GetFakeBinaryUploadService()
                ->last_request()
                .tags()[0]);
  EXPECT_FALSE(download_protection_service_.GetFakeBinaryUploadService()
                   ->last_request()
                   .has_device_token());
}

class DeepScanningReportingTest : public DeepScanningRequestTest {
 public:
  void SetUp() override {
    DeepScanningRequestTest::SetUp();

    client_ = std::make_unique<policy::MockCloudPolicyClient>();

    enterprise_connectors::RealtimeReportingClientFactory::GetInstance()
        ->SetTestingFactory(
            profile_, base::BindRepeating([](content::BrowserContext* context) {
              return std::unique_ptr<KeyedService>(
                  new enterprise_connectors::RealtimeReportingClient(context));
            }));

    enterprise_connectors::RealtimeReportingClientFactory::GetForProfile(
        profile_)
        ->SetBrowserCloudPolicyClientForTesting(client_.get());
    identity_test_environment_.MakePrimaryAccountAvailable(
        kUserName, signin::ConsentLevel::kSignin);
    enterprise_connectors::RealtimeReportingClientFactory::GetForProfile(
        profile_)
        ->SetIdentityManagerForTesting(
            identity_test_environment_.identity_manager());

    enterprise_connectors::test::SetOnSecurityEventReporting(
        profile_->GetPrefs(), true);

#if BUILDFLAG(IS_CHROMEOS)
    fake_statistics_provider_.SetMachineStatistic(ash::system::kSerialNumberKey,
                                                  "fake_serial_number");
#endif

    enterprise_connectors::test::SetAnalysisConnector(
        profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
        kScanForDlpAndMalware);
  }

  void TearDown() override {
    enterprise_connectors::RealtimeReportingClientFactory::GetForProfile(
        profile_)
        ->SetBrowserCloudPolicyClientForTesting(nullptr);
    DeepScanningRequestTest::TearDown();
  }

 protected:
#if BUILDFLAG(IS_CHROMEOS)
  ash::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
#endif
  std::unique_ptr<policy::MockCloudPolicyClient> client_;
  signin::IdentityTestEnvironment identity_test_environment_;
};

class DeepScanningReportingSourceTypeTest
    : public DeepScanningReportingTest,
      public testing::WithParamInterface<MetadataSourceType> {
 public:
  void SetUp() override {
    DeepScanningReportingTest::SetUp();
    SetMetadataSourceType(GetParam());
  }

  MetadataSourceType GetMetadataSourceType() { return GetParam(); }
};

// TODO(crbug.com/433865922): Disable this test because of flakiness.
#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
TEST_P(DeepScanningReportingSourceTypeTest,
       DISABLED_ProcessesResponseCorrectly) {
  {
    base::RunLoop run_loop;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](DeepScanningRequestTest* test,
               base::RepeatingClosure quit_closure,
               DownloadCheckResult result) {
              test->SetLastResult(result);
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                quit_closure.Run();
              }
            },
            base::Unretained(this), run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* malware_result = response.add_results();
    malware_result->set_tag("malware");
    malware_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    auto* malware_rule = malware_result->add_triggered_rules();
    malware_rule->set_action(enterprise_connectors::TriggeredRule::BLOCK);
    malware_rule->set_rule_name("malware");

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    auto* dlp_rule = dlp_result->add_triggered_rules();
    dlp_rule->set_action(enterprise_connectors::TriggeredRule::BLOCK);
    dlp_rule->set_rule_name("dlp_rule");
    dlp_rule->set_rule_id("0");

    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        download_path_,
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::WARN);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    auto expected_dangerous_event = CreateDangerousDownloadEvent(
        /*url=*/"https://example.com/download.exe",
        /*tab_url=*/"https://example.com/",
        /*source=*/"",
        /*destination=*/"",
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*threat_type=*/
        chrome::cros::reporting::proto::SafeBrowsingDangerousDownloadEvent::
            DANGEROUS,
        /*trigger=*/
        chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD,
        /*content_size=*/std::string("download contents").size(),
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED,
        /*username=*/kUserName,
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*scan_id=*/kScanId,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    auto expected_dlp_event = CreateDlpSensitiveDataEvent(
        /*url=*/"https://example.com/download.exe",
        /*tab_url=*/"https://example.com/",
        /*source=*/"",
        /*destination=*/"",
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*trigger=*/
        chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD,
        /*dlp_result=*/*dlp_result,
        /*content_size=*/std::string("download contents").size(),
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED,
        /*username=*/kUserName,
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*scan_id=*/kScanId,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    validator.ExpectDangerousDeepScanningResultAndSensitiveDataEvent(
        std::move(expected_dangerous_event), std::move(expected_dlp_event),
        ExeMimeTypes());

    request.Start();

    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::DANGEROUS, last_result_);
  }

  {
    base::RunLoop run_loop;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](DeepScanningRequestTest* test,
               base::RepeatingClosure quit_closure,
               DownloadCheckResult result) {
              test->SetLastResult(result);
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                quit_closure.Run();
              }
            },
            base::Unretained(this), run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* malware_result = response.add_results();
    malware_result->set_tag("malware");
    malware_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    auto* malware_rule = malware_result->add_triggered_rules();
    malware_rule->set_action(enterprise_connectors::TriggeredRule::WARN);
    malware_rule->set_rule_name("uws");

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    auto* dlp_rule = dlp_result->add_triggered_rules();
    dlp_rule->set_action(enterprise_connectors::TriggeredRule::WARN);
    dlp_rule->set_rule_name("dlp_rule");
    dlp_rule->set_rule_id("0");

    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        download_path_,
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::WARN);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    auto expected_dangerous_event = CreateDangerousDownloadEvent(
        /*url=*/"https://example.com/download.exe",
        /*tab_url=*/"https://example.com/",
        /*source=*/"",
        /*destination=*/"",
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*threat_type=*/
        chrome::cros::reporting::proto::SafeBrowsingDangerousDownloadEvent::
            POTENTIALLY_UNWANTED,
        /*trigger=*/
        chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD,
        /*content_size=*/std::string("download contents").size(),
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED,
        /*username=*/kUserName,
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*scan_id=*/kScanId,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    auto expected_dlp_event = CreateDlpSensitiveDataEvent(
        /*url=*/"https://example.com/download.exe",
        /*tab_url=*/"https://example.com/",
        /*source=*/"",
        /*destination=*/"",
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*trigger=*/
        chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD,
        /*dlp_result=*/*dlp_result,
        /*content_size=*/std::string("download contents").size(),
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED,
        /*username=*/kUserName,
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*scan_id=*/kScanId,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    validator.ExpectDangerousDeepScanningResultAndSensitiveDataEvent(
        std::move(expected_dangerous_event), std::move(expected_dlp_event),
        ExeMimeTypes());

    request.Start();

    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::POTENTIALLY_UNWANTED, last_result_);
  }

  {
    base::RunLoop run_loop;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](DeepScanningRequestTest* test,
               base::RepeatingClosure quit_closure,
               DownloadCheckResult result) {
              test->SetLastResult(result);
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                quit_closure.Run();
              }
            },
            base::Unretained(this), run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    auto* dlp_rule = dlp_result->add_triggered_rules();
    dlp_rule->set_action(enterprise_connectors::TriggeredRule::BLOCK);
    dlp_rule->set_rule_name("dlp_rule");
    dlp_rule->set_rule_id("0");

    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        download_path_,
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    auto expected_dlp_event = CreateDlpSensitiveDataEvent(
        /*url=*/"https://example.com/download.exe",
        /*tab_url=*/"https://example.com/",
        /*source=*/"",
        /*destination=*/"",
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*trigger=*/
        chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD,
        /*dlp_result=*/*dlp_result,
        /*content_size=*/std::string("download contents").size(),
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_BLOCKED,
        /*username=*/kUserName,
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*scan_id=*/kScanId,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    validator.ExpectSensitiveDataEvent(std::move(expected_dlp_event));

    request.Start();

    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::SENSITIVE_CONTENT_BLOCK, last_result_);
  }

  {
    base::RunLoop run_loop;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](DeepScanningRequestTest* test,
               base::RepeatingClosure quit_closure,
               DownloadCheckResult result) {
              test->SetLastResult(result);
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                quit_closure.Run();
              }
            },
            base::Unretained(this), run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    auto* dlp_rule = dlp_result->add_triggered_rules();
    dlp_rule->set_action(enterprise_connectors::TriggeredRule::WARN);
    dlp_rule->set_rule_name("dlp_rule");
    dlp_rule->set_rule_id("0");

    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        download_path_,
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::WARN);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    auto expected_dlp_event = CreateDlpSensitiveDataEvent(
        /*url=*/"https://example.com/download.exe",
        /*tab_url=*/"https://example.com/",
        /*source=*/"",
        /*destination=*/"",
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*trigger=*/
        chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD,
        /*dlp_result=*/*dlp_result,
        /*content_size=*/std::string("download contents").size(),
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED,
        /*username=*/kUserName,
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*scan_id=*/kScanId,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    validator.ExpectSensitiveDataEvent(std::move(expected_dlp_event));

    request.Start();

    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::SENSITIVE_CONTENT_WARNING, last_result_);
  }

  {
    base::RunLoop run_loop;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](DeepScanningRequestTest* test,
               base::RepeatingClosure quit_closure,
               DownloadCheckResult result) {
              test->SetLastResult(result);
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                quit_closure.Run();
              }
            },
            base::Unretained(this), run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    auto* dlp_rule1 = dlp_result->add_triggered_rules();
    dlp_rule1->set_action(enterprise_connectors::TriggeredRule::WARN);
    dlp_rule1->set_rule_name("dlp_rule1");
    dlp_rule1->set_rule_id("0");
    auto* dlp_rule2 = dlp_result->add_triggered_rules();
    dlp_rule2->set_action(enterprise_connectors::TriggeredRule::BLOCK);
    dlp_rule2->set_rule_name("dlp_rule2");
    dlp_rule2->set_rule_id("0");

    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        download_path_,
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    auto expected_dlp_event = CreateDlpSensitiveDataEvent(
        /*url=*/"https://example.com/download.exe",
        /*tab_url=*/"https://example.com/",
        /*source=*/"",
        /*destination=*/"",
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*trigger=*/
        chrome::cros::reporting::proto::DataTransferEventTrigger::FILE_DOWNLOAD,
        /*dlp_result=*/*dlp_result,
        /*content_size=*/std::string("download contents").size(),
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_BLOCKED,
        /*username=*/kUserName,
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*scan_id=*/kScanId,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    validator.ExpectSensitiveDataEvent(std::move(expected_dlp_event));

    request.Start();

    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::SENSITIVE_CONTENT_BLOCK, last_result_);
  }

  {
    base::RunLoop run_loop;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](DeepScanningRequestTest* test,
               base::RepeatingClosure quit_closure,
               DownloadCheckResult result) {
              test->SetLastResult(result);
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                quit_closure.Run();
              }
            },
            base::Unretained(this), run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::FAILURE);

    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        download_path_,
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    auto expected_unscanned_event = CreateUnscannedFileEvent(
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*user_name=*/kUserName,
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*content_type=*/"application/octet-stream",
        /*content_size=*/std::string("download contents").size(),
        /*reason=*/
        chrome::cros::reporting::proto::UnscannedFileEvent::DLP_SCAN_FAILED,
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_ALLOWED,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    validator.ExpectUnscannedFileEvent(std::move(expected_unscanned_event));

    request.Start();

    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::SAFE, last_result_);
  }

  {
    base::RunLoop run_loop;
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE,
        base::BindRepeating(
            [](DeepScanningRequestTest* test,
               base::RepeatingClosure quit_closure,
               DownloadCheckResult result) {
              test->SetLastResult(result);
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                quit_closure.Run();
              }
            },
            base::Unretained(this), run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* malware_result = response.add_results();
    malware_result->set_tag("malware");
    malware_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::FAILURE);

    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        download_path_,
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    auto expected_unscanned_event = CreateUnscannedFileEvent(
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*user_name=*/kUserName,
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*content_type=*/"application/octet-stream",
        /*content_size=*/std::string("download contents").size(),
        /*reason=*/
        chrome::cros::reporting::proto::UnscannedFileEvent::MALWARE_SCAN_FAILED,
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_ALLOWED,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    validator.ExpectUnscannedFileEvent(std::move(expected_unscanned_event));

    request.Start();

    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::SAFE, last_result_);
  }

  {
    base::RunLoop run_loop;
    // The DownloadCheckResult passed below should be used if scanning fails.
    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::DANGEROUS,
        base::BindRepeating(
            [](DeepScanningRequestTest* test,
               base::RepeatingClosure quit_closure,
               DownloadCheckResult result) {
              test->SetLastResult(result);
              if (result != DownloadCheckResult::ASYNC_SCANNING) {
                quit_closure.Run();
              }
            },
            base::Unretained(this), run_loop.QuitClosure()),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    EXPECT_CALL(item_, GetDangerType())
        .WillRepeatedly(Return(download::DownloadDangerType::
                                   DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT));

    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* malware_result = response.add_results();
    malware_result->set_tag("malware");
    malware_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::FAILURE);

    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        download_path_,
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);

    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            GetMetadataSourceType() == MetadataSourceType::kDownloadItem
                ? enterprise_connectors::ContentAnalysisAcknowledgement::WARN
                : enterprise_connectors::ContentAnalysisAcknowledgement::
                      ALLOW);  // for fsa item scans, the pre-scan result is
                               // always ALLOW

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    auto expected_result =
        GetMetadataSourceType() == MetadataSourceType::kDownloadItem
            ? chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED
            : chrome::cros::reporting::proto::EventResult::EVENT_RESULT_ALLOWED;

    auto expected_unscanned_event = CreateUnscannedFileEvent(
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*user_name=*/kUserName,
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*content_type=*/"application/octet-stream",
        /*content_size=*/std::string("download contents").size(),
        /*reason=*/
        chrome::cros::reporting::proto::UnscannedFileEvent::MALWARE_SCAN_FAILED,
        /*event_result=*/expected_result,
        /*include_referrer=*/GetMetadataSourceType() ==
            MetadataSourceType::kDownloadItem);

    validator.ExpectUnscannedFileEvent(std::move(expected_unscanned_event));

    request.Start();

    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::DANGEROUS, last_result_);
  }
}

TEST_F(DeepScanningReportingTest, ReportForceSaveToOneDrive) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* dlp_result = response.add_results();
  dlp_result->set_tag("dlp");
  dlp_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  auto* dlp_rule = dlp_result->add_triggered_rules();
  dlp_rule->set_action(
      enterprise_connectors::TriggeredRule::FORCE_SAVE_TO_CLOUD);
  dlp_rule->set_force_save_to_cloud_destination(
      enterprise_connectors::TriggeredRule::CORP_ONEDRIVE);
  dlp_rule->set_rule_name("dlp_rule");
  dlp_rule->set_rule_id("0");

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto expected_event = CreateDlpSensitiveDataEventForForceSaveToCloud(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*destination=*/"OneDrive");

  validator.ExpectSensitiveDataEvent(std::move(expected_event));

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::FORCE_SAVE_TO_ONEDRIVE, last_result_);
}

TEST_F(DeepScanningReportingTest, ReportForceSaveToGDrive) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* dlp_result = response.add_results();
  dlp_result->set_tag("dlp");
  dlp_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  auto* dlp_rule = dlp_result->add_triggered_rules();
  dlp_rule->set_action(
      enterprise_connectors::TriggeredRule::FORCE_SAVE_TO_CLOUD);
  dlp_rule->set_force_save_to_cloud_destination(
      enterprise_connectors::TriggeredRule::CORP_G_DRIVE);
  dlp_rule->set_rule_name("dlp_rule");
  dlp_rule->set_rule_id("0");

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto expected_event = CreateDlpSensitiveDataEventForForceSaveToCloud(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*destination=*/"Google Drive");
  validator.ExpectSensitiveDataEvent(std::move(expected_event));

  // Enable the feature to allow FORCE_SAVE_TO_GDRIVE result.
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitWithFeatures(
      {enterprise_data_protection::kEnableForceDownloadToCloud}, {});

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::FORCE_SAVE_TO_GDRIVE, last_result_);
}

#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
class DeepScanningReportingAutomationTest : public DeepScanningReportingTest {
 public:
  DeepScanningReportingAutomationTest() {
    scoped_features_.InitWithFeatures(
        {enterprise_data_protection::kEnableForceDownloadToCloud,
         safe_browsing::kEnhancedFieldsForSecOps},
        {});
  }

  void SetUp() override {
    DeepScanningReportingTest::SetUp();
    scoped_command_line_.GetProcessCommandLine()->AppendSwitch(
        switches::kEnableAutomation);
    content::DownloadItemUtils::AttachInfoForTesting(&item_, profile_,
                                                     web_contents_.get());
  }

 protected:
  base::test::ScopedFeatureList scoped_features_;
  base::test::ScopedCommandLine scoped_command_line_;
};

TEST_F(DeepScanningReportingAutomationTest,
       ReportForceSaveToGDriveBypassesDialogWithAutomation) {
  base::RunLoop run_loop;

  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* dlp_result = response.add_results();
  dlp_result->set_tag("dlp");
  dlp_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  auto* dlp_rule = dlp_result->add_triggered_rules();
  dlp_rule->set_action(
      enterprise_connectors::TriggeredRule::FORCE_SAVE_TO_CLOUD);
  dlp_rule->set_force_save_to_cloud_destination(
      enterprise_connectors::TriggeredRule::CORP_G_DRIVE);
  dlp_rule->set_rule_name("dlp_rule");
  dlp_rule->set_rule_id("0");

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto expected_event = CreateDlpSensitiveDataEventForForceSaveToCloud(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*destination=*/"Google Drive");
  validator.ExpectSensitiveDataEvent(std::move(expected_event));

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::FORCE_SAVE_TO_GDRIVE, last_result_);
}
#endif  // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)

class ForceSaveToCloudPrioritizationTest
    : public DeepScanningReportingTest,
      public testing::WithParamInterface<
          ForceSaveToCloudPrioritizationTestParams> {};

TEST_P(ForceSaveToCloudPrioritizationTest, AllCases) {
  const auto& params = GetParam();
  SetFeatures(params.enabled_features, params.disabled_features);
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindLambdaForTesting([&](DownloadCheckResult result) {
        SetLastResult(result);
        if (result != DownloadCheckResult::ASYNC_SCANNING) {
          run_loop.Quit();
        }
      }),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      params.response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  request.Start();
  run_loop.Run();
  EXPECT_EQ(params.expected_result, last_result_);
}

INSTANTIATE_TEST_SUITE_P(
    DeepScanningReportingTest,
    ForceSaveToCloudPrioritizationTest,
    testing::ValuesIn(GetForceSaveToCloudPrioritizationTestCases()),
    [](const testing::TestParamInfo<
        ForceSaveToCloudPrioritizationTest::ParamType>& info) {
      return info.param.test_name;
    });
#endif  // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)

TEST_F(DeepScanningReportingTest, ConsumerEncryptedArchiveSuccess) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* malware_result = response.add_results();
  malware_result->set_tag("malware");
  malware_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);

  DownloadItemWarningData::SetIsTopLevelEncryptedArchive(&item_, true);
  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));

  request.Start();

  run_loop.Run();

  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));
}

TEST_F(DeepScanningReportingTest, ConsumerEncryptedArchiveFailed) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* malware_result = response.add_results();
  malware_result->set_tag("malware");
  malware_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  malware_result->set_status_error_message(
      enterprise_connectors::ContentAnalysisResponse::Result::
          DECRYPTION_FAILED);

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);

  DownloadItemWarningData::SetIsTopLevelEncryptedArchive(&item_, true);
  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));

  request.Start();

  run_loop.Run();

  EXPECT_TRUE(DownloadItemWarningData::HasIncorrectPassword(&item_));
}

TEST_F(DeepScanningReportingTest, ConsumerUnencryptedArchive) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_CONSUMER_PROMPT,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* malware_result = response.add_results();
  malware_result->set_tag("malware");
  malware_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);

  DownloadItemWarningData::SetIsTopLevelEncryptedArchive(&item_, false);
  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));

  request.Start();

  run_loop.Run();

  EXPECT_FALSE(DownloadItemWarningData::HasIncorrectPassword(&item_));
}

#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
TEST_F(DeepScanningReportingTest, CustomMessagePrioritization) {
  SetFeatures(
      /*enabled=*/{enterprise_data_protection::kEnableForceDownloadToCloud},
      /*disabled=*/{});

  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  // Rule 1: WARN with a custom message.
  auto* result1 = response.add_results();
  result1->set_tag("dlp");
  result1->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  auto* rule1 = result1->add_triggered_rules();
  rule1->set_action(enterprise_connectors::TriggeredRule::WARN);
  rule1->mutable_custom_rule_message()->add_message_segments()->set_text(
      "Warn Custom Message");

  // Rule 2: FORCE_SAVE_TO_CLOUD without a custom message.
  auto* rule2 = result1->add_triggered_rules();
  rule2->set_action(enterprise_connectors::TriggeredRule::FORCE_SAVE_TO_CLOUD);
  rule2->set_force_save_to_cloud_destination(
      enterprise_connectors::TriggeredRule::CORP_G_DRIVE);

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  request.Start();
  run_loop.Run();

  // The final result should be FORCE_SAVE_TO_GDRIVE because it's higher
  // precedence than WARN.
  EXPECT_EQ(DownloadCheckResult::FORCE_SAVE_TO_GDRIVE, last_result_);
}
#endif  // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)

TEST_P(DeepScanningReportingSourceTypeTest, MultipleFiles) {
  {
    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* malware_result = response.add_results();
    malware_result->set_tag("malware");
    malware_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    base::flat_map<base::FilePath, base::FilePath> current_paths_to_final_paths;

    auto metadata = CreateMetadata();
    current_paths_to_final_paths[metadata->GetFullPath()] =
        metadata->GetTargetFilePath();
    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        metadata->GetTargetFilePath(),
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);
    for (size_t i = 0; i < secondary_files_.size(); ++i) {
      current_paths_to_final_paths[secondary_files_[i]] =
          secondary_files_targets_[i];

      enterprise_connectors::ContentAnalysisResponse response_copy = response;
      response.set_request_token(
          base::StrCat({kScanId, base::NumberToString(i)}));

      download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
          secondary_files_targets_[i],
          enterprise_connectors::ScanRequestUploadResult::kSuccess,
          response_copy);
    }

    DeepScanningRequest request(
        std::move(metadata), DownloadCheckResult::SAFE,
        base::BindRepeating(&DeepScanningRequestTest::SetLastResult,
                            base::Unretained(this)),
        &download_protection_service_, settings().value(),
        current_paths_to_final_paths);

    base::RunLoop run_loop;
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetQuitOnLastRequest(run_loop.QuitClosure());
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    validator.ExpectNoReport();

    request.Start();
    run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::DEEP_SCANNED_SAFE, last_result_);
    EXPECT_EQ(4u, download_protection_service_.GetFakeBinaryUploadService()
                      ->num_finished_requests());
    EXPECT_EQ(
        4u,
        download_protection_service_.GetFakeBinaryUploadService()->num_acks());
    download_protection_service_.GetFakeBinaryUploadService()->Reset();
  }

  {
    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* malware_result = response.add_results();
    malware_result->set_tag("malware");
    malware_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    base::flat_map<base::FilePath, base::FilePath> current_paths_to_final_paths;

    auto metadata = CreateMetadata();
    current_paths_to_final_paths[metadata->GetFullPath()] =
        metadata->GetTargetFilePath();
    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        metadata->GetTargetFilePath(),
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);
    for (size_t i = 0; i < secondary_files_.size(); ++i) {
      current_paths_to_final_paths[secondary_files_[i]] =
          secondary_files_targets_[i];

      enterprise_connectors::ContentAnalysisResponse response_copy = response;
      response_copy.set_request_token(
          base::StrCat({kScanId, base::NumberToString(i)}));

      if (i == 0) {
        response_copy.mutable_results(0)->set_status(
            enterprise_connectors::ContentAnalysisResponse::Result::FAILURE);
      }

      download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
          secondary_files_targets_[i],
          enterprise_connectors::ScanRequestUploadResult::kSuccess,
          response_copy);
    }

    DeepScanningRequest request(
        std::move(metadata), DownloadCheckResult::SAFE,
        base::BindRepeating(&DeepScanningRequestTest::SetLastResult,
                            base::Unretained(this)),
        &download_protection_service_, settings().value(),
        current_paths_to_final_paths);

    base::RunLoop run_loop;
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetQuitOnLastRequest(run_loop.QuitClosure());
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::ALLOW);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    // Only mock the 0th file with a scan failure, so only the 0th file triggers
    // UnscannedFileEvent with request_token (i.e. scan_id) "kScanId0" set above

    auto expected_event = CreateUnscannedFileEvent(
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*user_name=*/kUserName,
        /*file_name=*/secondary_files_targets_[0].AsUTF8Unsafe(),
        /*sha256=*/
        "DDAB29FF2C393EE52855D21A240EB05F775DF88E3CE347DF759F0C4B80356C35",
        /*content_type=*/"text/plain",
        /*content_size=*/std::string("foo.exe").size(),
        /*reason=*/
        chrome::cros::reporting::proto::UnscannedFileEvent::MALWARE_SCAN_FAILED,
        /*event_result=*/
        chrome::cros::reporting::proto::EventResult::EVENT_RESULT_ALLOWED,
        /*include_referrer=*/GetParam() == MetadataSourceType::kDownloadItem);
    expected_event.set_scan_id(kScanId + std::string("0"));

    validator.ExpectUnscannedFileEvent(std::move(expected_event));

    request.Start();
    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::SAFE, last_result_);
    EXPECT_EQ(4u, download_protection_service_.GetFakeBinaryUploadService()
                      ->num_finished_requests());
    EXPECT_EQ(
        4u,
        download_protection_service_.GetFakeBinaryUploadService()->num_acks());
    download_protection_service_.GetFakeBinaryUploadService()->Reset();
  }

  {
    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* malware_result = response.add_results();
    malware_result->set_tag("malware");
    malware_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    base::flat_map<base::FilePath, base::FilePath> current_paths_to_final_paths;

    auto metadata = CreateMetadata();
    current_paths_to_final_paths[metadata->GetFullPath()] =
        metadata->GetTargetFilePath();
    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        metadata->GetTargetFilePath(),
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    std::vector<enterprise_connectors::ContentAnalysisResponse::Result>
        expected_dlp_verdicts;
    for (size_t i = 0; i < secondary_files_.size(); ++i) {
      current_paths_to_final_paths[secondary_files_[i]] =
          secondary_files_targets_[i];

      enterprise_connectors::ContentAnalysisResponse response_copy = response;
      response_copy.set_request_token(
          base::StrCat({kScanId, base::NumberToString(i)}));

      if (i == 0) {
        auto* dlp_rule =
            response_copy.mutable_results(1)->add_triggered_rules();
        dlp_rule->set_action(enterprise_connectors::TriggeredRule::WARN);
        dlp_rule->set_rule_name("warn_dlp_rule");
        dlp_rule->set_rule_id("0");
        expected_dlp_verdicts.push_back(response_copy.results(1));
      } else if (i == 1) {
        auto* dlp_rule =
            response_copy.mutable_results(1)->add_triggered_rules();
        dlp_rule->set_action(enterprise_connectors::TriggeredRule::BLOCK);
        dlp_rule->set_rule_name("block_dlp_rule");
        dlp_rule->set_rule_id("1");
        expected_dlp_verdicts.push_back(response_copy.results(1));
      }

      download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
          secondary_files_targets_[i],
          enterprise_connectors::ScanRequestUploadResult::kSuccess,
          response_copy);
    }

    DeepScanningRequest request(
        std::move(metadata), DownloadCheckResult::SAFE,
        base::BindRepeating(&DeepScanningRequestTest::SetLastResult,
                            base::Unretained(this)),
        &download_protection_service_, settings().value(),
        current_paths_to_final_paths);

    base::RunLoop run_loop;
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetQuitOnLastRequest(run_loop.QuitClosure());
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    std::vector<chrome::cros::reporting::proto::DlpSensitiveDataEvent>
        expected_events;

    for (size_t i = 0; i < secondary_files_.size(); ++i) {
      chrome::cros::reporting::proto::DlpSensitiveDataEvent expected_event;
      expected_event.set_url("https://example.com/download.exe");
      expected_event.set_tab_url("https://example.com/");
      expected_event.set_source("");
      expected_event.set_destination("");

      expected_event.set_content_type("text/plain");
      expected_event.set_content_size(std::string("foo.exe").size());
      expected_event.set_trigger(chrome::cros::reporting::proto::
                                     DataTransferEventTrigger::FILE_DOWNLOAD);
      expected_event.set_clicked_through(false);

      if (GetParam() == MetadataSourceType::kDownloadItem) {
        ::chrome::cros::reporting::proto::UrlInfo referrers;
        referrers.set_ip("example.com");
        referrers.set_url("https://example.com/download.exe");
        *expected_event.add_referrers() = referrers;
      }

      chrome::cros::reporting::proto::TriggeredRuleInfo triggered_rule;
      if (i == 0) {
        triggered_rule.set_rule_name("warn_dlp_rule");
        triggered_rule.set_action(
            chrome::cros::reporting::proto::TriggeredRuleInfo::WARN);
        triggered_rule.set_rule_id(0);
      } else if (i == 1) {
        triggered_rule.set_rule_name("block_dlp_rule");
        triggered_rule.set_action(
            chrome::cros::reporting::proto::TriggeredRuleInfo::BLOCK);
        triggered_rule.set_rule_id(1);
      }
      *expected_event.add_triggered_rule_info() = triggered_rule;

      expected_event.set_profile_identifier(profile_->GetPath().AsUTF8Unsafe());
      expected_event.set_profile_user_name(kUserName);

      expected_events.emplace_back(expected_event);
    }

    std::vector<std::string> expected_file_names;
    for (const auto& path : {secondary_files_targets_[0].AsUTF8Unsafe(),
                             secondary_files_targets_[1].AsUTF8Unsafe()}) {
      expected_file_names.push_back(GetFileName(path));
    }

    validator.ExpectSensitiveDataEvents(
        std::move(expected_events), expected_file_names,
        {
            "DDAB29FF2C393EE52855D21A240EB05F775DF88E3CE347DF759F0C4B80356C3"
            "5",
            "08BD2D247CC7AA38B8C4B7FD20EE7EDAD0B593C3DEBCE92F595C9D016DA40BA"
            "E",
        },
        {enterprise_connectors::EventResultToString(
             enterprise_connectors::EventResult::BLOCKED),
         enterprise_connectors::EventResultToString(
             enterprise_connectors::EventResult::BLOCKED)},
        {
            kScanId + std::string("0"),
            kScanId + std::string("1"),
        });

    request.Start();
    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::SENSITIVE_CONTENT_BLOCK, last_result_);
    EXPECT_EQ(4u, download_protection_service_.GetFakeBinaryUploadService()
                      ->num_finished_requests());
    EXPECT_EQ(
        4u,
        download_protection_service_.GetFakeBinaryUploadService()->num_acks());
    download_protection_service_.GetFakeBinaryUploadService()->Reset();
  }

#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
  {
    enterprise_connectors::ContentAnalysisResponse response;
    response.set_request_token(kScanId);

    auto* malware_result = response.add_results();
    malware_result->set_tag("malware");
    malware_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);

    auto* dlp_result = response.add_results();
    dlp_result->set_tag("dlp");
    dlp_result->set_status(
        enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
    base::flat_map<base::FilePath, base::FilePath> current_paths_to_final_paths;

    auto metadata = CreateMetadata();
    current_paths_to_final_paths[metadata->GetFullPath()] =
        metadata->GetTargetFilePath();
    download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
        metadata->GetTargetFilePath(),
        enterprise_connectors::ScanRequestUploadResult::kSuccess, response);
    std::vector<enterprise_connectors::ContentAnalysisResponse::Result>
        expected_dlp_verdicts;
    for (size_t i = 0; i < secondary_files_.size(); ++i) {
      current_paths_to_final_paths[secondary_files_[i]] =
          secondary_files_targets_[i];

      enterprise_connectors::ContentAnalysisResponse response_copy = response;
      response_copy.set_request_token(
          base::StrCat({kScanId, base::NumberToString(i)}));

      if (i == 0) {
        auto* dlp_rule =
            response_copy.mutable_results(1)->add_triggered_rules();
        dlp_rule->set_action(
            enterprise_connectors::TriggeredRule::FORCE_SAVE_TO_CLOUD);
        dlp_rule->set_force_save_to_cloud_destination(
            enterprise_connectors::TriggeredRule::CORP_G_DRIVE);
        dlp_rule->set_rule_name("dlp_rule");
        dlp_rule->set_rule_id("0");
        expected_dlp_verdicts.push_back(response_copy.results(1));
      }

      download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
          secondary_files_targets_[i],
          enterprise_connectors::ScanRequestUploadResult::kSuccess,
          response_copy);
    }

    if (GetParam() == MetadataSourceType::kFileSystemAccessWriteItem) {
      web_contents_.reset();
    }

    DeepScanningRequest request(
        std::move(metadata), DownloadCheckResult::SAFE,
        base::BindRepeating(&DeepScanningRequestTest::SetLastResult,
                            base::Unretained(this)),
        &download_protection_service_, settings().value(),
        current_paths_to_final_paths);

    base::RunLoop run_loop;
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetQuitOnLastRequest(run_loop.QuitClosure());
    download_protection_service_.GetFakeBinaryUploadService()
        ->SetExpectedFinalAction(
            enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    std::vector<chrome::cros::reporting::proto::DlpSensitiveDataEvent>
        expected_events;

    for (size_t i = 0; i < secondary_files_.size(); ++i) {
      if (i == 0) {
        chrome::cros::reporting::proto::DlpSensitiveDataEvent expected_event;
        expected_event.set_url("https://example.com/download.exe");
        expected_event.set_tab_url("https://example.com/");
        expected_event.set_source("");
        expected_event.set_destination("Google Drive");

        expected_event.set_content_type("text/plain");
        expected_event.set_content_size(std::string("foo.exe").size());
        expected_event.set_trigger(chrome::cros::reporting::proto::
                                       DataTransferEventTrigger::FILE_DOWNLOAD);
        expected_event.set_clicked_through(false);

        if (GetParam() == MetadataSourceType::kDownloadItem) {
          ::chrome::cros::reporting::proto::UrlInfo referrers;
          referrers.set_ip("example.com");
          referrers.set_url("https://example.com/download.exe");
          *expected_event.add_referrers() = referrers;
        }

        chrome::cros::reporting::proto::TriggeredRuleInfo triggered_rule;
        triggered_rule.set_rule_name("dlp_rule");
        triggered_rule.set_action(chrome::cros::reporting::proto::
                                      TriggeredRuleInfo::FORCE_SAVE_TO_CLOUD);
        triggered_rule.set_rule_id(0);
        *expected_event.add_triggered_rule_info() = triggered_rule;

        expected_event.set_profile_identifier(
            profile_->GetPath().AsUTF8Unsafe());
        expected_event.set_profile_user_name(kUserName);

        expected_events.emplace_back(expected_event);
      }
    }

    std::vector<std::string> expected_file_names;
    for (const auto& path : {secondary_files_targets_[0].AsUTF8Unsafe()}) {
      expected_file_names.push_back(GetFileName(path));
    }

    validator.ExpectSensitiveDataEvents(
        std::move(expected_events), expected_file_names,
        {
            "DDAB29FF2C393EE52855D21A240EB05F775DF88E3CE347DF759F0C4B80356C3"
            "5",
        },
        {enterprise_connectors::EventResultToString(
            enterprise_connectors::EventResult::FORCED_SAVE_TO_CLOUD)},
        {
            kScanId + std::string("0"),
        });

    base::test::ScopedFeatureList scoped_feature_list;
    scoped_feature_list.InitWithFeatures(
        {enterprise_data_protection::kEnableForceDownloadToCloud}, {});

    request.Start();
    run_loop.Run();
    validator_run_loop.Run();

    EXPECT_EQ(DownloadCheckResult::FORCE_SAVE_TO_GDRIVE, last_result_);
    EXPECT_EQ(4u, download_protection_service_.GetFakeBinaryUploadService()
                      ->num_finished_requests());
    EXPECT_EQ(
        4u,
        download_protection_service_.GetFakeBinaryUploadService()->num_acks());
    download_protection_service_.GetFakeBinaryUploadService()->Reset();
  }
#endif  //  BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
}

TEST_P(DeepScanningReportingSourceTypeTest, Timeout) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);
  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kTimeout,
      response);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto expected_event = CreateUnscannedFileEvent(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*sha256=*/
      "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
      /*content_type=*/"application/octet-stream",
      /*content_size=*/std::string("download contents").size(),
      /*reason=*/
      chrome::cros::reporting::proto::UnscannedFileEvent::TIMEOUT,
      /*event_result=*/
      chrome::cros::reporting::proto::EventResult::EVENT_RESULT_ALLOWED,
      /*include_referrer=*/GetParam() == MetadataSourceType::kDownloadItem);

  validator.ExpectUnscannedFileEvent(std::move(expected_event));

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::SAFE, last_result_);
}

TEST_P(DeepScanningReportingSourceTypeTest, CancelledByUser) {
  if (GetParam() != MetadataSourceType::kDownloadItem) {
    return;
  }

  for (bool enabled : {true, false}) {
    base::test::ScopedFeatureList scoped_feature_list;
    if (enabled) {
      scoped_feature_list.InitAndEnableFeature(
          enterprise_connectors::kEnableCancelUploadOnContentAnalysis);
    } else {
      scoped_feature_list.InitAndDisableFeature(
          enterprise_connectors::kEnableCancelUploadOnContentAnalysis);
    }

    // Use TestCancellationFakeBinaryUploadService to support synchronous cancel
    // callbacks.
    TestCancellationFakeBinaryUploadService cancel_upload_service;
    cancel_upload_service.set_synchronous_cancel(true);
    download_protection_service_.set_binary_upload_service(
        &cancel_upload_service);

    DeepScanningRequest request(
        CreateMetadata(),
        DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
        DownloadCheckResult::SAFE, base::DoNothing(),
        &download_protection_service_, settings().value(),
        /*password=*/std::nullopt);

    // Set the download item state to CANCELLED.
    EXPECT_CALL(item_, GetState())
        .WillRepeatedly(testing::Return(download::DownloadItem::CANCELLED));

    enterprise_connectors::test::EventReportValidator validator(client_.get());
    base::RunLoop validator_run_loop;
    validator.SetDoneClosure(validator_run_loop.QuitClosure());

    auto expected_event = CreateUnscannedFileEvent(
        /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
        /*user_name=*/kUserName,
        /*file_name=*/download_path_.AsUTF8Unsafe(),
        /*sha256=*/
        "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
        /*content_type=*/"application/octet-stream",
        /*content_size=*/std::string("download contents").size(),
        /*reason=*/
        chrome::cros::reporting::proto::UnscannedFileEvent::USER_CANCELLED,
        /*event_result=*/
        enabled
            ? chrome::cros::reporting::proto::EventResult::
                  EVENT_RESULT_CANCELLED_BY_USER
            : chrome::cros::reporting::proto::EventResult::EVENT_RESULT_ALLOWED,
        /*include_referrer=*/true);

    expected_event.clear_scan_id();

    validator.ExpectUnscannedFileEvent(std::move(expected_event));

    base::RunLoop upload_run_loop;
    cancel_upload_service.SetQuitOnUploadCallback(
        upload_run_loop.QuitClosure());

    request.Start();

    upload_run_loop.Run();

    // Simulate the download being cancelled by the user, which notifies
    // observers via OnDownloadUpdated.
    request.OnDownloadUpdated(&item_);

    // Trigger OnDownloadDestroyed which launches upload cancellation and
    // resolves reporting.
    request.OnDownloadDestroyed(&item_);

    validator_run_loop.Run();

    download_protection_service_.set_binary_upload_service(nullptr);
  }
}

INSTANTIATE_TEST_SUITE_P(
    Reporting,
    DeepScanningReportingSourceTypeTest,
    testing::Values(MetadataSourceType::kDownloadItem,
                    MetadataSourceType::kFileSystemAccessWriteItem));

class DeepScanningDownloadFailClosedTest
    : public DeepScanningRequestTest,
      public testing::WithParamInterface<
          std::tuple<enterprise_connectors::ScanRequestUploadResult, bool>> {
 public:
  enterprise_connectors::ScanRequestUploadResult upload_result() const {
    return std::get<0>(GetParam());
  }

  bool should_fail_closed() const { return std::get<1>(GetParam()); }

  // Use a string since the setting value is inserted into a JSON policy.
  const char* default_action_setting_value() const {
    return should_fail_closed() ? "block" : "allow";
  }
};

INSTANTIATE_TEST_SUITE_P(
    ,
    DeepScanningDownloadFailClosedTest,
    testing::Combine(
        testing::Values(
            enterprise_connectors::ScanRequestUploadResult::kUploadFailure,
            enterprise_connectors::ScanRequestUploadResult::kTimeout,
            enterprise_connectors::ScanRequestUploadResult::kFailedToGetToken,
            enterprise_connectors::ScanRequestUploadResult::kTooManyRequests,
            enterprise_connectors::ScanRequestUploadResult::kUnknown),
        testing::Bool()));

TEST_P(DeepScanningDownloadFailClosedTest, HandlesDefaultActionCorrectly) {
  constexpr char kDefaultActionPref[] = R"({
    "service_provider": "google",
    "enable": [
      {
        "url_list": ["*"],
        "tags": ["dlp"]
      }
    ],
    "block_until_verdict": 1,
    "default_action": "%s"
    })";

  enterprise_connectors::test::SetAnalysisConnector(
      profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
      base::StringPrintf(kDefaultActionPref, default_action_setting_value()));

  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindLambdaForTesting([this, quit_closure = run_loop.QuitClosure()](
                                     DownloadCheckResult result) {
        SetLastResult(result);
        if (result != DownloadCheckResult::ASYNC_SCANNING) {
          quit_closure.Run();
        }
      }),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, upload_result(),
      enterprise_connectors::ContentAnalysisResponse());

  request.Start();

  run_loop.Run();

  if (should_fail_closed()) {
    EXPECT_EQ(DownloadCheckResult::BLOCKED_SCAN_FAILED, last_result_);
  } else {
    EXPECT_EQ(DownloadCheckResult::SAFE, last_result_);
  }
}

class DeepScanningDownloadRestrictionsTest
    : public DeepScanningReportingTest,
      public testing::WithParamInterface<policy::DownloadRestriction> {
 public:
  void SetUp() override {
    DeepScanningReportingTest::SetUp();
    profile_->GetPrefs()->SetInteger(
        policy::policy_prefs::kDownloadRestrictions,
        static_cast<int>(download_restriction()));

    enterprise_connectors::test::SetAnalysisConnector(
        profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
        kScanForDlpAndMalware);
  }

  policy::DownloadRestriction download_restriction() const {
    return testing::WithParamInterface<policy::DownloadRestriction>::GetParam();
  }

  enterprise_connectors::EventResult expected_event_result_for_malware() const {
    switch (download_restriction()) {
      case policy::DownloadRestriction::NONE:
        return enterprise_connectors::EventResult::WARNED;
      case policy::DownloadRestriction::DANGEROUS_FILES:
      case policy::DownloadRestriction::MALICIOUS_FILES:
      case policy::DownloadRestriction::POTENTIALLY_DANGEROUS_FILES:
      case policy::DownloadRestriction::ALL_FILES:
        return enterprise_connectors::EventResult::BLOCKED;
    }
  }

  enterprise_connectors::EventResult expected_event_result_for_safe_large_file()
      const {
    switch (download_restriction()) {
      case policy::DownloadRestriction::NONE:
      case policy::DownloadRestriction::DANGEROUS_FILES:
      case policy::DownloadRestriction::MALICIOUS_FILES:
      case policy::DownloadRestriction::POTENTIALLY_DANGEROUS_FILES:
        return enterprise_connectors::EventResult::ALLOWED;
      case policy::DownloadRestriction::ALL_FILES:
        return enterprise_connectors::EventResult::BLOCKED;
    }
  }

  enterprise_connectors::ContentAnalysisAcknowledgement::FinalAction
  expected_final_action() const {
    switch (download_restriction()) {
      case policy::DownloadRestriction::NONE:
        return enterprise_connectors::ContentAnalysisAcknowledgement::WARN;
      case policy::DownloadRestriction::DANGEROUS_FILES:
      case policy::DownloadRestriction::MALICIOUS_FILES:
      case policy::DownloadRestriction::POTENTIALLY_DANGEROUS_FILES:
      case policy::DownloadRestriction::ALL_FILES:
        return enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK;
    }
  }
};

INSTANTIATE_TEST_SUITE_P(
    ,
    DeepScanningDownloadRestrictionsTest,
    testing::Values(policy::DownloadRestriction::NONE,
                    policy::DownloadRestriction::DANGEROUS_FILES,
                    policy::DownloadRestriction::POTENTIALLY_DANGEROUS_FILES,
                    policy::DownloadRestriction::ALL_FILES,
                    policy::DownloadRestriction::MALICIOUS_FILES));

TEST_P(DeepScanningDownloadRestrictionsTest,
       GeneratesCorrectReport_DeepScanMalwareBlocked) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* malware_result = response.add_results();
  malware_result->set_tag("malware");
  malware_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  auto* malware_rule = malware_result->add_triggered_rules();
  malware_rule->set_action(enterprise_connectors::TriggeredRule::BLOCK);
  malware_rule->set_rule_name("malware");

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(expected_final_action());

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto event_result =
      (GetParam() == policy::DownloadRestriction::NONE)
          ? chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED
          : chrome::cros::reporting::proto::EventResult::EVENT_RESULT_BLOCKED;

  auto expected_event = CreateDangerousDownloadEvent(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*threat_type=*/
      chrome::cros::reporting::proto::SafeBrowsingDangerousDownloadEvent::
          DANGEROUS,
      /*event_result=*/event_result);

  validator.ExpectDangerousDownloadEvent(std::move(expected_event));

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::DANGEROUS, last_result_);
}

TEST_P(DeepScanningDownloadRestrictionsTest,
       GeneratesCorrectReport_DeepScanMalwareWarned) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* malware_result = response.add_results();
  malware_result->set_tag("malware");
  malware_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  auto* malware_rule = malware_result->add_triggered_rules();
  malware_rule->set_action(enterprise_connectors::TriggeredRule::WARN);
  malware_rule->set_rule_name("uws");

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_, enterprise_connectors::ScanRequestUploadResult::kSuccess,
      response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::WARN);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto expected_event = CreateDangerousDownloadEvent(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*threat_type=*/
      chrome::cros::reporting::proto::SafeBrowsingDangerousDownloadEvent::
          POTENTIALLY_UNWANTED,
      /*event_result=*/
      chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED);

  validator.ExpectDangerousDownloadEvent(std::move(expected_event));

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::POTENTIALLY_UNWANTED, last_result_);
}

TEST_P(DeepScanningDownloadRestrictionsTest,
       GeneratesCorrectReportForLargeFiles_DeepScanSafe) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_,
      enterprise_connectors::ScanRequestUploadResult::kFileTooLarge, response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto event_result =
      (GetParam() == policy::DownloadRestriction::ALL_FILES)
          ? chrome::cros::reporting::proto::EventResult::EVENT_RESULT_BLOCKED
          : chrome::cros::reporting::proto::EventResult::EVENT_RESULT_ALLOWED;

  auto expected_event = CreateUnscannedFileEvent(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*sha256=*/
      "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
      /*content_type=*/"application/octet-stream",
      /*content_size=*/std::string("download contents").size(),
      /*reason=*/
      chrome::cros::reporting::proto::UnscannedFileEvent::FILE_TOO_LARGE,
      /*event_result=*/event_result);

  validator.ExpectUnscannedFileEvent(std::move(expected_event));

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::SAFE, last_result_);
}

TEST_P(DeepScanningDownloadRestrictionsTest,
       GeneratesCorrectReportForLargeFiles_DeepScanDlpBlocked) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* dlp_result = response.add_results();
  dlp_result->set_tag("dlp");
  dlp_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  auto* dlp_rule = dlp_result->add_triggered_rules();
  dlp_rule->set_action(enterprise_connectors::TriggeredRule::BLOCK);
  dlp_rule->set_rule_name("dlp");

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_,
      enterprise_connectors::ScanRequestUploadResult::kFileTooLarge, response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto expected_event = CreateUnscannedFileEvent(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*sha256=*/
      "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
      /*content_type=*/"application/octet-stream",
      /*content_size=*/std::string("download contents").size(),
      /*reason=*/
      chrome::cros::reporting::proto::UnscannedFileEvent::FILE_TOO_LARGE,
      /*event_result=*/
      chrome::cros::reporting::proto::EventResult::EVENT_RESULT_BLOCKED);

  validator.ExpectUnscannedFileEvent(std::move(expected_event));

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::SENSITIVE_CONTENT_BLOCK, last_result_);
}

#if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
TEST_P(DeepScanningDownloadRestrictionsTest,
       LargeFiles_DeepScanForceSaveToGDrive) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* dlp_result = response.add_results();
  dlp_result->set_tag("dlp");
  dlp_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  auto* dlp_rule = dlp_result->add_triggered_rules();
  dlp_rule->set_action(
      enterprise_connectors::TriggeredRule::FORCE_SAVE_TO_CLOUD);
  dlp_rule->set_force_save_to_cloud_destination(
      enterprise_connectors::TriggeredRule::CORP_G_DRIVE);
  dlp_rule->set_rule_name("dlp_rule");
  dlp_rule->set_rule_id("0");

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_,
      enterprise_connectors::ScanRequestUploadResult::kFileTooLarge, response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto expected_event = CreateUnscannedFileEvent(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*sha256=*/
      "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
      /*content_type=*/"application/octet-stream",
      /*content_size=*/std::string("download contents").size(),
      /*reason=*/
      chrome::cros::reporting::proto::UnscannedFileEvent::FILE_TOO_LARGE,
      /*event_result=*/
      chrome::cros::reporting::proto::EventResult::
          EVENT_RESULT_FORCED_SAVE_TO_CLOUD);
  expected_event.set_destination("Google Drive");

  validator.ExpectUnscannedFileEvent(std::move(expected_event));

  // Enable the feature to allow FORCE_SAVE_TO_GDRIVE result.
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitWithFeatures(
      {enterprise_data_protection::kEnableForceDownloadToCloud}, {});

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::FORCE_SAVE_TO_GDRIVE, last_result_);
}

TEST_P(DeepScanningDownloadRestrictionsTest,
       LargeFiles_DeepScanForceSaveToOneDrive) {
  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  auto* dlp_result = response.add_results();
  dlp_result->set_tag("dlp");
  dlp_result->set_status(
      enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS);
  auto* dlp_rule = dlp_result->add_triggered_rules();
  dlp_rule->set_action(
      enterprise_connectors::TriggeredRule::FORCE_SAVE_TO_CLOUD);
  dlp_rule->set_force_save_to_cloud_destination(
      enterprise_connectors::TriggeredRule::CORP_ONEDRIVE);
  dlp_rule->set_rule_name("dlp_rule");
  dlp_rule->set_rule_id("0");

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_,
      enterprise_connectors::ScanRequestUploadResult::kFileTooLarge, response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto expected_event = CreateUnscannedFileEvent(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*sha256=*/
      "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
      /*content_type=*/"application/octet-stream",
      /*content_size=*/std::string("download contents").size(),
      /*reason=*/
      chrome::cros::reporting::proto::UnscannedFileEvent::FILE_TOO_LARGE,
      /*event_result=*/
      chrome::cros::reporting::proto::EventResult::
          EVENT_RESULT_FORCED_SAVE_TO_CLOUD);
  expected_event.set_destination("OneDrive");

  validator.ExpectUnscannedFileEvent(std::move(expected_event));

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::FORCE_SAVE_TO_ONEDRIVE, last_result_);
}
#endif  // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)

TEST_P(DeepScanningDownloadRestrictionsTest,
       GeneratesCorrectReportForLargeFiles_PreScanDangerous) {
  base::RunLoop run_loop;
  // If `item_` has a dangerous DownloadDangerType before a deep scan and that
  // deep scan fails, the corresponding unscanned file event should match the
  // EventResult imposed by DownloadRestrictions.
  EXPECT_CALL(item_, GetDangerType())
      .WillRepeatedly(Return(download::DownloadDangerType::
                                 DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT));
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::DANGEROUS,
      base::BindRepeating(
          [](DeepScanningRequestTest* test, base::RepeatingClosure quit_closure,
             DownloadCheckResult result) {
            test->SetLastResult(result);
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              quit_closure.Run();
            }
          },
          base::Unretained(this), run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  enterprise_connectors::ContentAnalysisResponse response;
  response.set_request_token(kScanId);

  download_protection_service_.GetFakeBinaryUploadService()->SetResponse(
      download_path_,
      enterprise_connectors::ScanRequestUploadResult::kFileTooLarge, response);
  download_protection_service_.GetFakeBinaryUploadService()
      ->SetExpectedFinalAction(
          enterprise_connectors::ContentAnalysisAcknowledgement::BLOCK);

  enterprise_connectors::test::EventReportValidator validator(client_.get());
  base::RunLoop validator_run_loop;
  validator.SetDoneClosure(validator_run_loop.QuitClosure());

  auto event_result =
      (GetParam() == policy::DownloadRestriction::NONE)
          ? chrome::cros::reporting::proto::EventResult::EVENT_RESULT_WARNED
          : chrome::cros::reporting::proto::EventResult::EVENT_RESULT_BLOCKED;

  auto expected_event = CreateUnscannedFileEvent(
      /*profile_identifier=*/profile_->GetPath().AsUTF8Unsafe(),
      /*user_name=*/kUserName,
      /*file_name=*/download_path_.AsUTF8Unsafe(),
      /*sha256=*/
      "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C",
      /*content_type=*/"application/octet-stream",
      /*content_size=*/std::string("download contents").size(),
      /*reason=*/
      chrome::cros::reporting::proto::UnscannedFileEvent::FILE_TOO_LARGE,
      /*event_result=*/event_result);

  validator.ExpectUnscannedFileEvent(std::move(expected_event));

  request.Start();

  run_loop.Run();
  validator_run_loop.Run();

  EXPECT_EQ(DownloadCheckResult::DANGEROUS, last_result_);
}

class DeepScanningRequestConnectorsFeatureTest
    : public DeepScanningRequestTest {};

TEST_F(DeepScanningRequestConnectorsFeatureTest,
       ShouldUploadBinary_MalwareListPolicy) {
  enterprise_connectors::test::SetAnalysisConnector(
      profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
      kScanForMalware);

  content::DownloadItemUtils::AttachInfoForTesting(&item_, profile_, nullptr);
  EXPECT_CALL(item_, GetURL()).WillRepeatedly(ReturnRef(download_url_));

  // Without the malware policy list set, the item should be uploaded.
  ValidateDefaultSettings(settings());

  // With the old malware policy list set, the item should be uploaded since
  // DeepScanningRequest ignores that policy.
  AddUrlToProfilePrefList(prefs::kSafeBrowsingAllowlistDomains, download_url_);
  ValidateDefaultSettings(settings());

  // With the new malware policy list set, the item should not be uploaded since
  // DeepScanningRequest honours that policy.
  enterprise_connectors::test::SetAnalysisConnector(
      profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
      base::StringPrintf(
          R"({
                            "service_provider": "google",
                            "enable": [
                              {"url_list": ["*"], "tags": ["malware"]}
                            ],
                            "disable": [
                              {"url_list": ["%s"], "tags": ["malware"]}
                            ],
                            "block_until_verdict": 1
                          })",
          download_url_.GetHost().c_str()));
  EXPECT_FALSE(settings().has_value());
}

TEST_F(DeepScanningRequestConnectorsFeatureTest, ShouldUploadBinary_FileURLs) {
  enterprise_connectors::test::SetAnalysisConnector(
      profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
      kScanForDlpAndMalware);

  content::DownloadItemUtils::AttachInfoForTesting(&item_, profile_, nullptr);

  // Even if the policy indicates scanning should occur, file:/// URLs should
  // never return settings.
  GURL url_1("file:///a/path/to/a/file");
  EXPECT_CALL(item_, GetURL()).WillRepeatedly(ReturnRef(url_1));
  EXPECT_FALSE(settings().has_value());

  GURL url_2("file:///file.txt");
  EXPECT_CALL(item_, GetURL()).WillRepeatedly(ReturnRef(url_2));
  EXPECT_FALSE(settings().has_value());

  GURL url_3("file:///C:\\a\\path\\to\\a\\file");
  EXPECT_CALL(item_, GetURL()).WillRepeatedly(ReturnRef(url_3));
  EXPECT_FALSE(settings().has_value());

  GURL url_4("file:///C:\\file.txt");
  EXPECT_CALL(item_, GetURL()).WillRepeatedly(ReturnRef(url_4));
  EXPECT_FALSE(settings().has_value());
}

TEST_P(DeepScanningRequestAllFeaturesEnabledTest, PopulatesRequest) {
  enterprise_connectors::test::SetAnalysisConnector(
      profile_->GetPrefs(), enterprise_connectors::FILE_DOWNLOADED,
      kScanForDlpAndMalware);

  // Override mime type to platform-independent value for testing.
  net::ScopedOverrideGetMimeTypeForTesting override_mime_type(
      "application/octet-stream");

  base::RunLoop run_loop;
  DeepScanningRequest request(
      CreateMetadata(),
      DownloadItemWarningData::DeepScanTrigger::TRIGGER_POLICY,
      DownloadCheckResult::SAFE,
      base::BindRepeating(
          [](base::RepeatingClosure closure, DownloadCheckResult result) {
            if (result != DownloadCheckResult::ASYNC_SCANNING) {
              closure.Run();
            }
          },
          run_loop.QuitClosure()),
      &download_protection_service_, settings().value(),
      /*password=*/std::nullopt);

  request.Start();
  run_loop.Run();
  EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                ->last_request()
                .request_data()
                .filename(),
            download_path_.AsUTF8Unsafe());
  EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                ->last_request()
                .request_data()
                .digest(),
            // Hex-encoding of 'hash'
            "76E00EB33811F5778A5EE557512C30D9341D4FEB07646BCE3E4DB13F9428573C");
  EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                ->last_request()
                .request_data()
                .content_type(),
            "application/octet-stream");
  EXPECT_EQ(download_protection_service_.GetFakeBinaryUploadService()
                ->last_request()
                .request_data()
                .tab_url(),
            GURL("https://example.com"));
}

INSTANTIATE_TEST_SUITE_P(
    AllFeaturesEnabled,
    DeepScanningRequestAllFeaturesEnabledTest,
    testing::Values(MetadataSourceType::kDownloadItem,
                    MetadataSourceType::kFileSystemAccessWriteItem));

}  // namespace safe_browsing
