| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/download/download_warning_desktop_hats_utils.h" |
| |
| #include <memory> |
| |
| #include "base/files/file_path.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "chrome/browser/download/download_item_warning_data.h" |
| #include "chrome/browser/ui/hats/hats_service.h" |
| #include "chrome/browser/ui/hats/hats_service_factory.h" |
| #include "chrome/browser/ui/hats/mock_hats_service.h" |
| #include "chrome/browser/ui/hats/survey_config.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/download/public/common/download_danger_type.h" |
| #include "components/download/public/common/download_item.h" |
| #include "components/download/public/common/mock_download_item.h" |
| #include "components/safe_browsing/buildflags.h" |
| #include "components/safe_browsing/core/common/features.h" |
| #include "components/safe_browsing/core/common/proto/csd.pb.h" |
| #include "components/safe_browsing/core/common/safe_browsing_prefs.h" |
| #include "content/public/browser/download_item_utils.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| #if BUILDFLAG(SAFE_BROWSING_DOWNLOAD_PROTECTION) |
| #include "chrome/browser/safe_browsing/download_protection/download_protection_service.h" |
| #endif |
| |
| namespace { |
| |
| using download::DownloadItem; |
| using download::MockDownloadItem; |
| using Fields = DownloadWarningHatsProductSpecificData::Fields; |
| using ::testing::_; |
| using ::testing::Eq; |
| using ::testing::HasSubstr; |
| using ::testing::Key; |
| using ::testing::NiceMock; |
| using ::testing::Not; |
| using ::testing::Return; |
| using ::testing::ReturnRefOfCopy; |
| using ::testing::UnorderedElementsAreArray; |
| |
| constexpr char kUrl[] = "https://www.site.example/file.pdf"; |
| constexpr char kReferrerUrl[] = "https://www.site.example/referrer"; |
| constexpr char kPlaceholderPrefix[] = "Not logged"; |
| const base::FilePath::CharType kFilename[] = FILE_PATH_LITERAL("my_file.pdf"); |
| constexpr base::TimeDelta kIgnoreDelay = base::Seconds(10); |
| |
| // Matcher that checks for the presence of a particular bits data field and |
| // checks that the field value matches the given matcher. |
| MATCHER_P2(BitsDataMatches, field, matcher, "") { |
| const auto it = arg.bits_data().find(field); |
| if (it == arg.bits_data().end()) { |
| return false; |
| } |
| return ExplainMatchResult(matcher, it->second, result_listener); |
| } |
| |
| // As above, but for string data. |
| MATCHER_P2(StringDataMatches, field, matcher, "") { |
| const auto it = arg.string_data().find(field); |
| if (it == arg.string_data().end()) { |
| return false; |
| } |
| return ExplainMatchResult(matcher, it->second, result_listener); |
| } |
| |
| // Checks that the `fields` (vector of strings) exactly matches the keys in the |
| // `arg` (map of string->T). |
| MATCHER_P(UnorderedKeysAre, fields, "") { |
| std::vector<std::string> keys; |
| for (const auto& [key, val] : arg) { |
| keys.push_back(key); |
| } |
| return ExplainMatchResult(UnorderedElementsAreArray(fields), keys, |
| result_listener); |
| } |
| |
| class DownloadWarningDesktopHatsUtilsTest : public ::testing::Test { |
| public: |
| DownloadWarningDesktopHatsUtilsTest() = default; |
| |
| ~DownloadWarningDesktopHatsUtilsTest() override = default; |
| |
| void SetUp() override { |
| profile_ = TestingProfile::Builder().Build(); |
| item_ = SetUpMockDownloadItem(); |
| mock_hats_service_ = static_cast<MockHatsService*>( |
| HatsServiceFactory::GetInstance()->SetTestingFactoryAndUse( |
| profile_.get(), base::BindRepeating(&BuildMockHatsService))); |
| } |
| |
| void TearDown() override { mock_hats_service_ = nullptr; } |
| |
| std::unique_ptr<NiceMock<MockDownloadItem>> SetUpMockDownloadItem() { |
| auto item = std::make_unique<NiceMock<MockDownloadItem>>(); |
| content::DownloadItemUtils::AttachInfoForTesting(item.get(), profile_.get(), |
| nullptr); |
| SetUpDefaultsForItem(item.get()); |
| return item; |
| } |
| |
| // Sets up defaults for the mock download item_. These are not necessarily |
| // valid/consistent with the Safe Browsing state, but we just want to test |
| // that the values are reflected in the PSD and don't necessarily care what |
| // they are. |
| // Advances the time by 7 seconds. |
| void SetUpDefaultsForItem(MockDownloadItem* item) { |
| ON_CALL(*item, GetURL()).WillByDefault(ReturnRefOfCopy(GURL(kUrl))); |
| ON_CALL(*item, GetReferrerUrl()) |
| .WillByDefault(ReturnRefOfCopy(GURL(kReferrerUrl))); |
| ON_CALL(*item, GetFileNameToReportUser()) |
| .WillByDefault(Return(base::FilePath(kFilename))); |
| ON_CALL(*item, IsDangerous()).WillByDefault(Return(true)); |
| ON_CALL(*item, GetDangerType()) |
| .WillByDefault( |
| Return(download::DownloadDangerType:: |
| DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE)); |
| |
| // Set up the time since download started. |
| base::Time start_time = base::Time::Now(); |
| ON_CALL(*item, GetStartTime()).WillByDefault(Return(start_time)); |
| |
| // Add some warning action events. |
| task_environment_.FastForwardBy(base::Seconds(5)); |
| DownloadItemWarningData::AddWarningActionEvent( |
| item, DownloadItemWarningData::WarningSurface::BUBBLE_MAINPAGE, |
| DownloadItemWarningData::WarningAction::SHOWN); |
| task_environment_.FastForwardBy(base::Seconds(1)); |
| DownloadItemWarningData::AddWarningActionEvent( |
| item, DownloadItemWarningData::WarningSurface::BUBBLE_MAINPAGE, |
| DownloadItemWarningData::WarningAction::OPEN_SUBPAGE); |
| task_environment_.FastForwardBy(base::Seconds(1)); |
| DownloadItemWarningData::AddWarningActionEvent( |
| item, DownloadItemWarningData::WarningSurface::BUBBLE_SUBPAGE, |
| DownloadItemWarningData::WarningAction::CLOSE); |
| |
| ON_CALL(*item, IsDone()).WillByDefault(Return(false)); |
| |
| #if BUILDFLAG(SAFE_BROWSING_DOWNLOAD_PROTECTION) |
| // Set tailored verdict for cookie theft. |
| safe_browsing::ClientDownloadResponse::TailoredVerdict tailored_verdict; |
| tailored_verdict.set_tailored_verdict_type( |
| safe_browsing::ClientDownloadResponse::TailoredVerdict::COOKIE_THEFT); |
| safe_browsing::DownloadProtectionService::SetDownloadProtectionData( |
| item, "token", |
| safe_browsing::ClientDownloadResponse::DANGEROUS_ACCOUNT_COMPROMISE, |
| std::move(tailored_verdict)); |
| #endif // BUILDFLAG(SAFE_BROWSING_DOWNLOAD_PROTECTION) |
| |
| ON_CALL(*item, HasUserGesture()).WillByDefault(Return(true)); |
| } |
| |
| void ExpectDefaultPsd(const DownloadWarningHatsProductSpecificData& psd) { |
| EXPECT_THAT(psd, |
| StringDataMatches(Fields::kSecondsSinceDownloadStarted, "7")); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kSecondsSinceWarningShown, "2")); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kDangerType, |
| HasSubstr("AccountCompromise"))); |
| #if BUILDFLAG(FULL_SAFE_BROWSING) |
| EXPECT_THAT( |
| psd, StringDataMatches(Fields::kDangerType, HasSubstr("Cookie theft"))); |
| #endif |
| EXPECT_THAT(psd, StringDataMatches(Fields::kWarningType, "Dangerous")); |
| EXPECT_THAT(psd, BitsDataMatches(Fields::kUserGesture, true)); |
| EXPECT_THAT(psd, BitsDataMatches(Fields::kPartialViewEnabled, true)); |
| } |
| |
| void ExpectDefaultPsdForSafeBrowsing( |
| const DownloadWarningHatsProductSpecificData& psd) { |
| EXPECT_THAT(psd, StringDataMatches(Fields::kUrlDownload, kUrl)); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kUrlReferrer, kReferrerUrl)); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kFilename, "my_file.pdf")); |
| } |
| |
| void ExpectPlaceholderForSafeBrowsing( |
| const DownloadWarningHatsProductSpecificData& psd) { |
| EXPECT_THAT(psd, StringDataMatches(Fields::kUrlDownload, |
| HasSubstr(kPlaceholderPrefix))); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kUrlReferrer, |
| HasSubstr(kPlaceholderPrefix))); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kFilename, |
| HasSubstr(kPlaceholderPrefix))); |
| } |
| |
| void ExpectDefaultPsdForEnhancedSafeBrowsing( |
| const DownloadWarningHatsProductSpecificData& psd) { |
| EXPECT_THAT( |
| psd, StringDataMatches(Fields::kWarningInteractions, |
| "BUBBLE_MAINPAGE:SHOWN:0,BUBBLE_MAINPAGE:OPEN_" |
| "SUBPAGE:1000,BUBBLE_SUBPAGE:CLOSE:2000")); |
| } |
| |
| void ExpectPlaceholderForEnhancedSafeBrowsing( |
| const DownloadWarningHatsProductSpecificData& psd) { |
| EXPECT_THAT(psd, StringDataMatches(Fields::kWarningInteractions, |
| HasSubstr(kPlaceholderPrefix))); |
| } |
| |
| protected: |
| content::BrowserTaskEnvironment task_environment_{ |
| base::test::TaskEnvironment::TimeSource::MOCK_TIME}; |
| base::test::ScopedFeatureList features_; |
| std::unique_ptr<TestingProfile> profile_; |
| std::unique_ptr<NiceMock<MockDownloadItem>> item_; |
| raw_ptr<MockHatsService> mock_hats_service_ = nullptr; |
| }; |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| ProductSpecificData_NoSafeBrowsing) { |
| safe_browsing::SetSafeBrowsingState( |
| profile_->GetPrefs(), safe_browsing::SafeBrowsingState::NO_SAFE_BROWSING); |
| |
| auto psd = DownloadWarningHatsProductSpecificData::Create( |
| DownloadWarningHatsType::kDownloadBubbleBypass, item_.get()); |
| |
| // Test the PSD fields added afterwards. |
| // This shouldn't do anything because this is a download bubble trigger. |
| psd.AddNumPageWarnings(10); |
| psd.AddPartialViewInteraction(true); |
| |
| // All fields for download bubble are included. |
| EXPECT_THAT(psd.bits_data(), |
| UnorderedKeysAre( |
| DownloadWarningHatsProductSpecificData::GetBitsDataFields( |
| DownloadWarningHatsType::kDownloadBubbleBypass))); |
| EXPECT_THAT(psd.string_data(), |
| UnorderedKeysAre( |
| DownloadWarningHatsProductSpecificData::GetStringDataFields( |
| DownloadWarningHatsType::kDownloadBubbleBypass))); |
| |
| ExpectDefaultPsd(psd); |
| ExpectPlaceholderForSafeBrowsing(psd); |
| ExpectPlaceholderForEnhancedSafeBrowsing(psd); |
| |
| EXPECT_THAT( |
| psd, StringDataMatches(Fields::kSafeBrowsingState, "No Safe Browsing")); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kOutcome, HasSubstr("Bypass"))); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kSurface, HasSubstr("bubble"))); |
| |
| EXPECT_THAT(psd, BitsDataMatches(Fields::kPartialViewInteraction, true)); |
| EXPECT_THAT(psd, Not(StringDataMatches(Fields::kNumPageWarnings, _))); |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| ProductSpecificData_StandardSafeBrowsing) { |
| safe_browsing::SetSafeBrowsingState( |
| profile_->GetPrefs(), |
| safe_browsing::SafeBrowsingState::STANDARD_PROTECTION); |
| |
| auto psd = DownloadWarningHatsProductSpecificData::Create( |
| DownloadWarningHatsType::kDownloadsPageHeed, item_.get()); |
| |
| // Test the PSD fields added afterwards. |
| psd.AddNumPageWarnings(10); |
| // This shouldn't do anything because this is a download page trigger. |
| psd.AddPartialViewInteraction(true); |
| |
| // All fields for downloads page are included. |
| EXPECT_THAT(psd.bits_data(), |
| UnorderedKeysAre( |
| DownloadWarningHatsProductSpecificData::GetBitsDataFields( |
| DownloadWarningHatsType::kDownloadsPageHeed))); |
| EXPECT_THAT(psd.string_data(), |
| UnorderedKeysAre( |
| DownloadWarningHatsProductSpecificData::GetStringDataFields( |
| DownloadWarningHatsType::kDownloadsPageHeed))); |
| |
| ExpectDefaultPsd(psd); |
| ExpectDefaultPsdForSafeBrowsing(psd); |
| ExpectPlaceholderForEnhancedSafeBrowsing(psd); |
| |
| EXPECT_THAT(psd, StringDataMatches(Fields::kSafeBrowsingState, |
| "Standard Protection")); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kOutcome, HasSubstr("Heed"))); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kSurface, HasSubstr("page"))); |
| |
| EXPECT_THAT(psd, StringDataMatches(Fields::kNumPageWarnings, "10")); |
| EXPECT_THAT(psd, Not(BitsDataMatches(Fields::kPartialViewInteraction, _))); |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| ProductSpecificData_EnhancedSafeBrowsing) { |
| safe_browsing::SetSafeBrowsingState( |
| profile_->GetPrefs(), |
| safe_browsing::SafeBrowsingState::ENHANCED_PROTECTION); |
| |
| auto psd = DownloadWarningHatsProductSpecificData::Create( |
| DownloadWarningHatsType::kDownloadBubbleIgnore, item_.get()); |
| |
| // Test the PSD fields added afterwards. |
| // This shouldn't do anything because this is a download bubble trigger. |
| psd.AddNumPageWarnings(10); |
| psd.AddPartialViewInteraction(true); |
| |
| // All fields for download bubble are included. |
| EXPECT_THAT(psd.bits_data(), |
| UnorderedKeysAre( |
| DownloadWarningHatsProductSpecificData::GetBitsDataFields( |
| DownloadWarningHatsType::kDownloadBubbleIgnore))); |
| EXPECT_THAT(psd.string_data(), |
| UnorderedKeysAre( |
| DownloadWarningHatsProductSpecificData::GetStringDataFields( |
| DownloadWarningHatsType::kDownloadBubbleIgnore))); |
| |
| ExpectDefaultPsd(psd); |
| ExpectDefaultPsdForSafeBrowsing(psd); |
| ExpectDefaultPsdForEnhancedSafeBrowsing(psd); |
| |
| EXPECT_THAT(psd, StringDataMatches(Fields::kSafeBrowsingState, |
| "Enhanced Protection")); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kOutcome, HasSubstr("Ignore"))); |
| EXPECT_THAT(psd, StringDataMatches(Fields::kSurface, HasSubstr("bubble"))); |
| |
| EXPECT_THAT(psd, BitsDataMatches(Fields::kPartialViewInteraction, true)); |
| EXPECT_THAT(psd, Not(StringDataMatches(Fields::kNumPageWarnings, _))); |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| DelayedDownloadWarningHatsLauncher_LaunchesSurvey) { |
| base::test::ScopedFeatureList features; |
| features.InitAndEnableFeatureWithParameters( |
| safe_browsing::kDownloadWarningSurvey, |
| {{safe_browsing::kDownloadWarningSurveyType.name, |
| "2" /*kDownloadBubbleIgnore*/}}); |
| |
| DelayedDownloadWarningHatsLauncher launcher{profile_.get(), kIgnoreDelay}; |
| EXPECT_TRUE(launcher.TryScheduleTask( |
| DownloadWarningHatsType::kDownloadBubbleIgnore, item_.get())); |
| launcher.RecordBrowserActivity(); |
| EXPECT_CALL(*mock_hats_service_, |
| LaunchSurvey(kHatsSurveyTriggerDownloadWarningBubbleIgnore, _, _, |
| _, _, _, _)); |
| task_environment_.FastForwardBy(kIgnoreDelay); |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| DelayedDownloadWarningHatsLauncher_DoesntScheduleDuplicateSurvey) { |
| base::test::ScopedFeatureList features; |
| features.InitAndEnableFeatureWithParameters( |
| safe_browsing::kDownloadWarningSurvey, |
| {{safe_browsing::kDownloadWarningSurveyType.name, |
| "2" /*kDownloadBubbleIgnore*/}}); |
| |
| DelayedDownloadWarningHatsLauncher launcher{profile_.get(), kIgnoreDelay}; |
| EXPECT_TRUE(launcher.TryScheduleTask( |
| DownloadWarningHatsType::kDownloadBubbleIgnore, item_.get())); |
| EXPECT_FALSE(launcher.TryScheduleTask( |
| DownloadWarningHatsType::kDownloadBubbleIgnore, item_.get())); |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| DelayedDownloadWarningHatsLauncher_MultipleSurveys) { |
| safe_browsing::SetSafeBrowsingState( |
| profile_->GetPrefs(), |
| safe_browsing::SafeBrowsingState::STANDARD_PROTECTION); |
| |
| base::test::ScopedFeatureList features; |
| features.InitAndEnableFeatureWithParameters( |
| safe_browsing::kDownloadWarningSurvey, |
| {{safe_browsing::kDownloadWarningSurveyType.name, |
| "2" /*kDownloadBubbleIgnore*/}}); |
| |
| std::unique_ptr<NiceMock<MockDownloadItem>> other_item = |
| SetUpMockDownloadItem(); |
| ON_CALL(*other_item, GetFileNameToReportUser()) |
| .WillByDefault( |
| Return(base::FilePath(FILE_PATH_LITERAL("other_file.pdf")))); |
| |
| DelayedDownloadWarningHatsLauncher launcher{profile_.get(), kIgnoreDelay}; |
| EXPECT_TRUE(launcher.TryScheduleTask( |
| DownloadWarningHatsType::kDownloadBubbleIgnore, item_.get())); |
| launcher.RecordBrowserActivity(); |
| task_environment_.FastForwardBy(kIgnoreDelay / 2); |
| EXPECT_TRUE(launcher.TryScheduleTask( |
| DownloadWarningHatsType::kDownloadBubbleIgnore, other_item.get())); |
| { |
| EXPECT_CALL( |
| *mock_hats_service_, |
| LaunchSurvey( |
| kHatsSurveyTriggerDownloadWarningBubbleIgnore, _, _, _, |
| Contains(Pair(Fields::kFilename, HasSubstr("my_file.pdf"))), _, _)); |
| task_environment_.FastForwardBy(kIgnoreDelay / 2); |
| } |
| launcher.RecordBrowserActivity(); |
| { |
| EXPECT_CALL( |
| *mock_hats_service_, |
| LaunchSurvey( |
| kHatsSurveyTriggerDownloadWarningBubbleIgnore, _, _, _, |
| Contains(Pair(Fields::kFilename, HasSubstr("other_file.pdf"))), _, |
| _)); |
| task_environment_.FastForwardBy(kIgnoreDelay / 2); |
| } |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| DelayedDownloadWarningHatsLauncher_WithholdsSurveyIfNoUserActivity) { |
| base::test::ScopedFeatureList features; |
| features.InitAndEnableFeatureWithParameters( |
| safe_browsing::kDownloadWarningSurvey, |
| {{safe_browsing::kDownloadWarningSurveyType.name, |
| "2" /*kDownloadBubbleIgnore*/}}); |
| |
| DelayedDownloadWarningHatsLauncher launcher{profile_.get(), kIgnoreDelay}; |
| launcher.TryScheduleTask(DownloadWarningHatsType::kDownloadBubbleIgnore, |
| item_.get()); |
| EXPECT_CALL(*mock_hats_service_, |
| LaunchSurvey(kHatsSurveyTriggerDownloadWarningBubbleIgnore, _, _, |
| _, _, _, _)) |
| .Times(0); |
| task_environment_.FastForwardBy(2 * kIgnoreDelay); |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| DelayedDownloadWarningHatsLauncher_DeletesTaskWhenItemDeleted) { |
| base::test::ScopedFeatureList features; |
| features.InitAndEnableFeatureWithParameters( |
| safe_browsing::kDownloadWarningSurvey, |
| {{safe_browsing::kDownloadWarningSurveyType.name, |
| "2" /*kDownloadBubbleIgnore*/}}); |
| |
| DelayedDownloadWarningHatsLauncher launcher{profile_.get(), kIgnoreDelay}; |
| EXPECT_TRUE(launcher.TryScheduleTask( |
| DownloadWarningHatsType::kDownloadBubbleIgnore, item_.get())); |
| item_.reset(); |
| |
| launcher.RecordBrowserActivity(); |
| EXPECT_CALL(*mock_hats_service_, |
| LaunchSurvey(kHatsSurveyTriggerDownloadWarningBubbleIgnore, _, _, |
| _, _, _, _)) |
| .Times(0); |
| task_environment_.FastForwardBy(kIgnoreDelay); |
| |
| item_ = SetUpMockDownloadItem(); |
| // Trying again works because the older task was deleted. |
| EXPECT_TRUE(launcher.TryScheduleTask( |
| DownloadWarningHatsType::kDownloadBubbleIgnore, item_.get())); |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| MaybeGetDownloadWarningHatsTrigger_FeatureDisabled) { |
| base::test::ScopedFeatureList features; |
| features.InitAndDisableFeature(safe_browsing::kDownloadWarningSurvey); |
| |
| for (DownloadWarningHatsType type : |
| {DownloadWarningHatsType::kDownloadBubbleBypass, |
| DownloadWarningHatsType::kDownloadBubbleHeed, |
| DownloadWarningHatsType::kDownloadBubbleIgnore, |
| DownloadWarningHatsType::kDownloadsPageBypass, |
| DownloadWarningHatsType::kDownloadsPageHeed, |
| DownloadWarningHatsType::kDownloadsPageIgnore}) { |
| EXPECT_FALSE(MaybeGetDownloadWarningHatsTrigger(type)); |
| } |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| MaybeGetDownloadWarningHatsTrigger_ParamOutOfRange) { |
| for (DownloadWarningHatsType type : |
| {DownloadWarningHatsType::kDownloadBubbleBypass, |
| DownloadWarningHatsType::kDownloadBubbleHeed, |
| DownloadWarningHatsType::kDownloadBubbleIgnore, |
| DownloadWarningHatsType::kDownloadsPageBypass, |
| DownloadWarningHatsType::kDownloadsPageHeed, |
| DownloadWarningHatsType::kDownloadsPageIgnore}) { |
| for (const std::string& param_value : {"", "-1", "6"}) { |
| base::test::ScopedFeatureList features; |
| features.InitAndEnableFeatureWithParameters( |
| safe_browsing::kDownloadWarningSurvey, |
| {{safe_browsing::kDownloadWarningSurveyType.name, param_value}}); |
| |
| EXPECT_FALSE(MaybeGetDownloadWarningHatsTrigger(type)); |
| } |
| } |
| } |
| |
| TEST_F(DownloadWarningDesktopHatsUtilsTest, |
| MaybeGetDownloadWarningHatsTrigger_OnlyReturnsTriggerIfEligible) { |
| for (DownloadWarningHatsType type : |
| {DownloadWarningHatsType::kDownloadBubbleBypass, |
| DownloadWarningHatsType::kDownloadBubbleHeed, |
| DownloadWarningHatsType::kDownloadBubbleIgnore, |
| DownloadWarningHatsType::kDownloadsPageBypass, |
| DownloadWarningHatsType::kDownloadsPageHeed, |
| DownloadWarningHatsType::kDownloadsPageIgnore}) { |
| for (int param_value = 0; param_value < 6; ++param_value) { |
| std::string param_value_string = base::NumberToString(param_value); |
| base::test::ScopedFeatureList features; |
| features.InitAndEnableFeatureWithParameters( |
| safe_browsing::kDownloadWarningSurvey, |
| {{safe_browsing::kDownloadWarningSurveyType.name, |
| param_value_string}}); |
| |
| bool eligible = param_value == static_cast<int>(type); |
| EXPECT_EQ(MaybeGetDownloadWarningHatsTrigger(type).has_value(), eligible); |
| } |
| } |
| } |
| |
| } // namespace |