| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/search_engines/default_search_manager.h" |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/strings/string_split.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/task_environment.h" |
| #include "base/time/time.h" |
| #include "build/build_config.h" |
| #include "components/regional_capabilities/regional_capabilities_switches.h" |
| #include "components/search_engines/search_engine_choice/search_engine_choice_service.h" |
| #include "components/search_engines/search_engine_type.h" |
| #include "components/search_engines/search_engines_pref_names.h" |
| #include "components/search_engines/search_engines_switches.h" |
| #include "components/search_engines/search_engines_test_environment.h" |
| #include "components/search_engines/search_engines_test_util.h" |
| #include "components/search_engines/template_url_data.h" |
| #include "components/search_engines/template_url_data_util.h" |
| #include "components/search_engines/template_url_prepopulate_data.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "components/variations/scoped_variations_ids_provider.h" |
| #include "services/preferences/tracked/pref_hash_filter.h" |
| #include "template_url_prepopulate_data_resolver.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/search_engines_data/resources/definitions/prepopulated_engines.h" |
| #include "url/gurl.h" |
| |
| #if BUILDFLAG(IS_WIN) |
| #include "base/win/win_util.h" |
| #endif // BUILDFLAG(IS_WIN) |
| |
| namespace { |
| |
| void SetOverrides(sync_preferences::TestingPrefServiceSyncable* prefs, |
| bool update) { |
| auto overrides = base::Value::List(); |
| |
| // Lambda facilitating insertion of TemplateURL definitions, ensuring that all |
| // mandatory fields are present. |
| auto add_definition = [&overrides](TemplateURLID id, |
| std::string name_and_keyword, |
| std::string base_url) { |
| auto alternate_urls = base::Value::List(); |
| alternate_urls.Append(base_url + "/alternate?q={searchTerms}"); |
| |
| overrides.Append( |
| base::Value::Dict() |
| .Set("name", name_and_keyword) |
| .Set("id", (int)id) |
| .Set("keyword", name_and_keyword) |
| .Set("search_url", base_url + "/search?q={searchTerms}") |
| .Set("suggest_url", base_url + "/suggest?q={searchTerms}") |
| .Set("favicon_url", base_url + "/favicon.ico") |
| .Set("encoding", "UTF-8") |
| .Set("alternate_urls", std::move(alternate_urls))); |
| }; |
| |
| add_definition(100, update ? "new_foo" : "foo", "https://atlas.com"); |
| add_definition(101, update ? "new_bar" : "bar", "https://brave.com"); |
| add_definition(102, update ? "new_bar" : "bar", "https://conduit.com"); |
| add_definition(103, "at.yahoo.com", "https://at.search.yahoo.com"); |
| add_definition(104, "emea.yahoo.com", "https://emea.search.yahoo.com"); |
| |
| prefs->SetUserPref(prefs::kSearchProviderOverridesVersion, base::Value(1)); |
| prefs->SetUserPref(prefs::kSearchProviderOverrides, std::move(overrides)); |
| } |
| |
| void SetPolicy(sync_preferences::TestingPrefServiceSyncable* prefs, |
| bool enabled, |
| TemplateURLData* data, |
| bool is_mandatory) { |
| if (enabled) { |
| EXPECT_FALSE(data->keyword().empty()); |
| EXPECT_FALSE(data->url().empty()); |
| } |
| base::Value::Dict entry = TemplateURLDataToDictionary(*data); |
| entry.Set(DefaultSearchManager::kDisabledByPolicy, !enabled); |
| |
| is_mandatory ? prefs->SetManagedPref( |
| DefaultSearchManager::kDefaultSearchProviderDataPrefName, |
| std::move(entry)) |
| : prefs->SetRecommendedPref( |
| DefaultSearchManager::kDefaultSearchProviderDataPrefName, |
| std::move(entry)); |
| } |
| |
| } // namespace |
| |
| class DefaultSearchManagerTest : public testing::Test { |
| public: |
| void SetUp() override { |
| // Override the country checks to simulate being in the US. |
| base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( |
| switches::kSearchEngineChoiceCountry, "US"); |
| PrefHashFilter::RegisterProfilePrefs(pref_service()->registry()); |
| } |
| |
| sync_preferences::TestingPrefServiceSyncable* pref_service() { |
| return &search_engines_test_environment_.pref_service(); |
| } |
| |
| search_engines::SearchEngineChoiceService* search_engine_choice_service() { |
| return &search_engines_test_environment_.search_engine_choice_service(); |
| } |
| |
| TemplateURLPrepopulateData::Resolver& prepopulate_data_resolver() { |
| return search_engines_test_environment_.prepopulate_data_resolver(); |
| } |
| |
| std::unique_ptr<DefaultSearchManager> create_manager() { |
| return std::make_unique<DefaultSearchManager>( |
| pref_service(), search_engine_choice_service(), |
| search_engines_test_environment_.prepopulate_data_resolver(), |
| DefaultSearchManager::ObserverCallback()); |
| } |
| |
| std::unique_ptr<TemplateURLData> set_default_search_provider_data_pref( |
| const std::string& keyword) { |
| std::unique_ptr<TemplateURLData> data = |
| GenerateDummyTemplateURLData(keyword); |
| pref_service()->SetDict( |
| DefaultSearchManager::kDefaultSearchProviderDataPrefName, |
| TemplateURLDataToDictionary(*data)); |
| return data; |
| } |
| |
| void set_mirrored_default_search_provider_data_pref( |
| const std::string& keyword) { |
| std::unique_ptr<TemplateURLData> data = |
| GenerateDummyTemplateURLData(keyword); |
| pref_service()->SetDict( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName, |
| TemplateURLDataToDictionary(*data)); |
| } |
| |
| private: |
| base::test::TaskEnvironment task_environment_; |
| variations::test::ScopedVariationsIdsProvider scoped_variations_ids_provider_{ |
| variations::VariationsIdsProvider::Mode::kUseSignedInState}; |
| search_engines::SearchEnginesTestEnvironment search_engines_test_environment_; |
| }; |
| |
| // Test that a TemplateURLData object is properly written and read from Prefs. |
| TEST_F(DefaultSearchManagerTest, ReadAndWritePref) { |
| auto manager = create_manager(); |
| TemplateURLData data; |
| data.SetShortName(u"name1"); |
| data.SetKeyword(u"key1"); |
| data.SetURL("http://foo1/{searchTerms}"); |
| data.suggestions_url = "http://sugg1"; |
| data.alternate_urls.push_back("http://foo1/alt"); |
| data.favicon_url = GURL("http://icon1"); |
| data.safe_for_autoreplace = true; |
| data.input_encodings = base::SplitString( |
| "UTF-8;UTF-16", ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| data.date_created = base::Time(); |
| data.last_modified = base::Time(); |
| data.last_modified = base::Time(); |
| data.regulatory_origin = RegulatoryExtensionType::kAndroidEEA; |
| |
| manager->SetUserSelectedDefaultSearchEngine(data); |
| const TemplateURLData* read_data = manager->GetDefaultSearchEngine(nullptr); |
| ExpectSimilar(&data, read_data); |
| } |
| |
| // Test DefaultSearchmanager handles user-selected DSEs correctly. |
| TEST_F(DefaultSearchManagerTest, DefaultSearchSetByUserPref) { |
| auto manager = create_manager(); |
| std::unique_ptr<TemplateURLData> fallback_t_url_data = |
| prepopulate_data_resolver().GetFallbackSearch(); |
| EXPECT_EQ(fallback_t_url_data->keyword(), |
| TemplateURLPrepopulateData::google.keyword); |
| EXPECT_EQ(fallback_t_url_data->prepopulate_id, |
| TemplateURLPrepopulateData::google.id); |
| DefaultSearchManager::Source source = DefaultSearchManager::FROM_POLICY; |
| // If no user pref is set, we should use the pre-populated values. |
| ExpectSimilar(fallback_t_url_data.get(), |
| manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); |
| |
| base::HistogramTester histograms; |
| |
| // Setting a user pref overrides the pre-populated values. |
| std::unique_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user"); |
| manager->SetUserSelectedDefaultSearchEngine(*data); |
| |
| ExpectSimilar(data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| |
| // Updating the user pref (externally to this instance of |
| // DefaultSearchManager) triggers an update. |
| std::unique_ptr<TemplateURLData> new_data = |
| GenerateDummyTemplateURLData("user2"); |
| |
| auto other_manager = create_manager(); |
| other_manager->SetUserSelectedDefaultSearchEngine(*new_data); |
| |
| ExpectSimilar(new_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| |
| // Check that the mirrored pref metric didn't record a mismatch. |
| // Metric is recorded once for the first search manager, and then four more |
| // times when there are two search managers. |
| histograms.ExpectBucketCount( |
| DefaultSearchManager::kDefaultSearchEngineMirroredMetric, true, 1); |
| |
| histograms.ExpectBucketCount( |
| DefaultSearchManager::kDefaultSearchEngineMirroredMetric, false, 0); |
| |
| // Clearing the user pref should cause the default search to revert to the |
| // prepopulated values. |
| manager->ClearUserSelectedDefaultSearchEngine(); |
| ExpectSimilar(fallback_t_url_data.get(), |
| manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); |
| } |
| |
| // Test that DefaultSearch manager detects changes to kSearchProviderOverrides. |
| TEST_F(DefaultSearchManagerTest, DefaultSearchSetByOverrides) { |
| SetOverrides(pref_service(), false); |
| auto manager = create_manager(); |
| |
| std::unique_ptr<TemplateURLData> fallback_t_url_data = |
| prepopulate_data_resolver().GetFallbackSearch(); |
| EXPECT_NE(fallback_t_url_data->keyword(), |
| TemplateURLPrepopulateData::google.keyword); |
| EXPECT_NE(fallback_t_url_data->prepopulate_id, |
| TemplateURLPrepopulateData::google.id); |
| |
| DefaultSearchManager::Source source = DefaultSearchManager::FROM_POLICY; |
| EXPECT_TRUE(manager->GetDefaultSearchEngine(&source)); |
| TemplateURLData first_default(*manager->GetDefaultSearchEngine(&source)); |
| ExpectSimilar(fallback_t_url_data.get(), &first_default); |
| EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); |
| |
| // Update the overrides: |
| SetOverrides(pref_service(), true); |
| fallback_t_url_data = prepopulate_data_resolver().GetFallbackSearch(); |
| |
| // Make sure DefaultSearchManager updated: |
| ExpectSimilar(fallback_t_url_data.get(), |
| manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); |
| EXPECT_NE(manager->GetDefaultSearchEngine(nullptr)->short_name(), |
| first_default.short_name()); |
| EXPECT_NE(manager->GetDefaultSearchEngine(nullptr)->keyword(), |
| first_default.keyword()); |
| } |
| |
| // Test DefaultSearchManager handles policy-enforced DSEs correctly. |
| TEST_F(DefaultSearchManagerTest, DefaultSearchSetByEnforcedPolicy) { |
| auto manager = create_manager(); |
| std::unique_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user"); |
| manager->SetUserSelectedDefaultSearchEngine(*data); |
| |
| DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK; |
| ExpectSimilar(data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| |
| std::unique_ptr<TemplateURLData> policy_data = |
| GenerateDummyTemplateURLData("policy"); |
| SetPolicy(pref_service(), true, policy_data.get(), /*is_mandatory=*/true); |
| |
| ExpectSimilar(policy_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source); |
| |
| TemplateURLData null_policy_data; |
| SetPolicy(pref_service(), false, &null_policy_data, /*is_mandatory=*/true); |
| EXPECT_EQ(nullptr, manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source); |
| |
| pref_service()->RemoveManagedPref( |
| DefaultSearchManager::kDefaultSearchProviderDataPrefName); |
| ExpectSimilar(data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| } |
| |
| // Policy-recommended DSE is handled correctly when no existing DSE is present. |
| TEST_F(DefaultSearchManagerTest, DefaultSearchSetByRecommendedPolicy) { |
| auto manager = create_manager(); |
| DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK; |
| |
| // Set recommended policy DSE with valid data. |
| std::unique_ptr<TemplateURLData> policy_data = |
| GenerateDummyTemplateURLData("policy"); |
| SetPolicy(pref_service(), true, policy_data.get(), /*is_mandatory=*/false); |
| ExpectSimilar(policy_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_POLICY_RECOMMENDED, source); |
| |
| // Set recommended policy DSE with null data. |
| TemplateURLData null_policy_data; |
| SetPolicy(pref_service(), false, &null_policy_data, /*is_mandatory=*/false); |
| EXPECT_EQ(nullptr, manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_POLICY_RECOMMENDED, source); |
| |
| // Set user-configured DSE. |
| std::unique_ptr<TemplateURLData> user_data = |
| GenerateDummyTemplateURLData("user"); |
| manager->SetUserSelectedDefaultSearchEngine(*user_data); |
| // The user-configured DSE overrides the recommended policy DSE. |
| ExpectSimilar(user_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| |
| // Remove the recommended policy DSE. |
| pref_service()->RemoveRecommendedPref( |
| DefaultSearchManager::kDefaultSearchProviderDataPrefName); |
| ExpectSimilar(user_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| } |
| |
| // Policy-recommended DSE does not override existing DSE set by user. |
| TEST_F(DefaultSearchManagerTest, DefaultSearchSetByUserAndRecommendedPolicy) { |
| auto manager = create_manager(); |
| |
| // Set user-configured DSE. |
| std::unique_ptr<TemplateURLData> user_data = |
| GenerateDummyTemplateURLData("user"); |
| manager->SetUserSelectedDefaultSearchEngine(*user_data); |
| DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK; |
| ExpectSimilar(user_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| |
| // Check that the TemplateURLData was mirrored to the mirrored pref. |
| const base::Value* user_value = pref_service()->GetUserPrefValue( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName); |
| ASSERT_TRUE(user_value && user_value->is_dict()); |
| auto turl_data = TemplateURLDataFromDictionary(user_value->GetDict()); |
| ExpectSimilar(user_data.get(), turl_data.get()); |
| |
| // Set recommended policy DSE. |
| std::unique_ptr<TemplateURLData> policy_data = |
| GenerateDummyTemplateURLData("policy"); |
| SetPolicy(pref_service(), true, policy_data.get(), /*is_mandatory=*/false); |
| // The recommended policy DSE does not override the existing user DSE. |
| ExpectSimilar(user_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| |
| // Remove the recommended policy DSE. |
| pref_service()->RemoveRecommendedPref( |
| DefaultSearchManager::kDefaultSearchProviderDataPrefName); |
| ExpectSimilar(user_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| } |
| |
| // Test DefaultSearchManager handles extension-controlled DSEs correctly. |
| TEST_F(DefaultSearchManagerTest, DefaultSearchSetByExtension) { |
| auto manager = create_manager(); |
| std::unique_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user"); |
| manager->SetUserSelectedDefaultSearchEngine(*data); |
| |
| DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK; |
| ExpectSimilar(data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| |
| // Extension trumps prefs: |
| std::unique_ptr<TemplateURLData> extension_data_1 = |
| GenerateDummyTemplateURLData("ext1"); |
| SetExtensionDefaultSearchInPrefs(pref_service(), *extension_data_1); |
| ExpectSimilar(extension_data_1.get(), |
| manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_EXTENSION, source); |
| |
| // Policy trumps extension: |
| std::unique_ptr<TemplateURLData> policy_data = |
| GenerateDummyTemplateURLData("policy"); |
| SetPolicy(pref_service(), true, policy_data.get(), /*is_mandatory=*/true); |
| |
| ExpectSimilar(policy_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source); |
| pref_service()->RemoveManagedPref( |
| DefaultSearchManager::kDefaultSearchProviderDataPrefName); |
| |
| // Extensions trump each other: |
| std::unique_ptr<TemplateURLData> extension_data_2 = |
| GenerateDummyTemplateURLData("ext2"); |
| std::unique_ptr<TemplateURLData> extension_data_3 = |
| GenerateDummyTemplateURLData("ext3"); |
| |
| SetExtensionDefaultSearchInPrefs(pref_service(), *extension_data_2); |
| SetExtensionDefaultSearchInPrefs(pref_service(), *extension_data_3); |
| ExpectSimilar(extension_data_3.get(), |
| manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_EXTENSION, source); |
| |
| RemoveExtensionDefaultSearchFromPrefs(pref_service()); |
| ExpectSimilar(data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| } |
| |
| TEST_F(DefaultSearchManagerTest, |
| DefaultSearchSetByPlayAPI_MergeByPrepopulatedId) { |
| auto manager = create_manager(); |
| auto* builtin_engine = manager->GetDefaultSearchEngine(nullptr); |
| |
| // The test tries to set DSE to the one with prepopulate_id, matching existing |
| // prepopulated search engine. |
| auto supplied_engine = GenerateDummyTemplateURLData( |
| base::UTF16ToUTF8(builtin_engine->keyword())); |
| supplied_engine->prepopulate_id = builtin_engine->prepopulate_id; |
| // Needed by ExpectSimilar. |
| supplied_engine->favicon_url = builtin_engine->favicon_url; |
| |
| // Non-Play definitions should be reconciled using prepopulated_id. |
| manager->SetUserSelectedDefaultSearchEngine(*supplied_engine); |
| auto* result = manager->GetDefaultSearchEngine(nullptr); |
| ExpectSimilar(builtin_engine, result); |
| } |
| |
| TEST_F(DefaultSearchManagerTest, |
| DefaultSearchSetByPlayAPI_MergeByKeyword_FeatureEnabled) { |
| auto manager = create_manager(); |
| auto* builtin_engine = manager->GetDefaultSearchEngine(nullptr); |
| |
| auto supplied_engine = GenerateDummyTemplateURLData( |
| base::UTF16ToUTF8(builtin_engine->keyword())); |
| supplied_engine->regulatory_origin = RegulatoryExtensionType::kAndroidEEA; |
| // Needed by ExpectSimilar. |
| supplied_engine->favicon_url = builtin_engine->favicon_url; |
| |
| // Verify engine reconciled with builtin definition. |
| manager->SetUserSelectedDefaultSearchEngine(*supplied_engine); |
| auto* result = manager->GetDefaultSearchEngine(nullptr); |
| |
| TemplateURLData expected_engine = *builtin_engine; |
| expected_engine.regulatory_origin = RegulatoryExtensionType::kAndroidEEA; |
| ExpectSimilar(&expected_engine, result); |
| } |
| |
| TEST_F(DefaultSearchManagerTest, |
| DefaultSearchSetByPlayAPI_MergeByDomainName_FeatureEnabled) { |
| SetOverrides(pref_service(), false); |
| auto manager = create_manager(); |
| |
| // Find the expected engine. We could fabricate one too, this is easier. |
| auto all_engines = prepopulate_data_resolver().GetPrepopulatedEngines(); |
| const auto& builtin_engine = |
| *std::ranges::find_if(all_engines, [](const auto& engine) { |
| GURL url(engine->url()); |
| return url.is_valid() && url.host() == "emea.search.yahoo.com"; |
| }); |
| |
| auto supplied_engine = GenerateDummyTemplateURLData("yahoo.com"); |
| supplied_engine->SetURL("https://emea.search.yahoo.com/any_path"); |
| supplied_engine->regulatory_origin = RegulatoryExtensionType::kAndroidEEA; |
| // Needed by ExpectSimilar. |
| supplied_engine->favicon_url = builtin_engine->favicon_url; |
| |
| // Verify engine reconciled with builtin definition. |
| manager->SetUserSelectedDefaultSearchEngine(*supplied_engine); |
| auto* result = manager->GetDefaultSearchEngine(nullptr); |
| |
| TemplateURLData expected_engine = *builtin_engine; |
| expected_engine.regulatory_origin = RegulatoryExtensionType::kAndroidEEA; |
| ExpectSimilar(&expected_engine, result); |
| } |
| |
| #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) |
| TEST_F(DefaultSearchManagerTest, DefaultSearchReset) { |
| base::test::ScopedFeatureList feature_list{ |
| switches::kResetTamperedDefaultSearchEngine}; |
| base::HistogramTester histograms; |
| |
| set_default_search_provider_data_pref("search_engine_A"); |
| set_mirrored_default_search_provider_data_pref("search_engine_B"); |
| |
| auto manager = create_manager(); |
| |
| // The original and mirrored DSE prefs should have been cleared since they |
| // were holding different data. |
| EXPECT_TRUE( |
| pref_service() |
| ->GetDict(DefaultSearchManager::kDefaultSearchProviderDataPrefName) |
| .empty()); |
| EXPECT_TRUE( |
| pref_service() |
| ->GetDict( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName) |
| .empty()); |
| |
| // Mirror check reset recorded. |
| histograms.ExpectUniqueSample( |
| DefaultSearchManager::kDefaultSearchEngineMirrorCheckOutcomeMetric, |
| static_cast<int>( |
| DefaultSearchManager::DefaultSearchEngineMirrorCheckOutcomeType:: |
| kMirrorCheckReset), |
| 1); |
| |
| // Ensure the notification is shown. |
| EXPECT_TRUE(pref_service()->GetBoolean( |
| prefs::kShowDefaultSearchEngineResetNotification)); |
| |
| // The DSE should now be the fallback. |
| DefaultSearchManager::Source source; |
| manager->GetDefaultSearchEngine(&source); |
| EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); |
| } |
| |
| TEST_F(DefaultSearchManagerTest, UserDseChangeDisablesResetNotification) { |
| base::test::ScopedFeatureList feature_list{ |
| switches::kResetTamperedDefaultSearchEngine}; |
| |
| auto user_data = set_default_search_provider_data_pref("search_engine_A"); |
| set_mirrored_default_search_provider_data_pref("search_engine_B"); |
| |
| auto manager = create_manager(); |
| |
| // The DSE was reset and notification dialog will show. |
| EXPECT_TRUE(pref_service()->GetBoolean( |
| prefs::kShowDefaultSearchEngineResetNotification)); |
| DefaultSearchManager::Source source; |
| manager->GetDefaultSearchEngine(&source); |
| EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source); |
| |
| // Change the DSE (before the notification is shown). |
| set_default_search_provider_data_pref("search_engine_A"); |
| |
| // The DSE should have been changed. |
| ExpectSimilar(user_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| |
| // Ensure the notification is not shown. |
| EXPECT_FALSE(pref_service()->GetBoolean( |
| prefs::kShowDefaultSearchEngineResetNotification)); |
| } |
| |
| #if BUILDFLAG(IS_WIN) |
| TEST_F(DefaultSearchManagerTest, DefaultSearchNotResetForEnterprisePolicy) { |
| base::test::ScopedFeatureList feature_list{ |
| switches::kResetTamperedDefaultSearchEngine}; |
| // Simulate an enterprise device. |
| base::win::ScopedDomainStateForTesting scoped_domain_state_(true); |
| base::HistogramTester histograms; |
| |
| auto user_data = set_default_search_provider_data_pref("search_engine_A"); |
| set_mirrored_default_search_provider_data_pref("search_engine_B"); |
| |
| auto manager = create_manager(); |
| |
| // The DSE prefs should NOT be cleared since this is an enterprise device. |
| EXPECT_FALSE( |
| pref_service() |
| ->GetDict(DefaultSearchManager::kDefaultSearchProviderDataPrefName) |
| .empty()); |
| EXPECT_FALSE( |
| pref_service() |
| ->GetDict( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName) |
| .empty()); |
| |
| // DSE reset was skipped due to enterprise policy recorded. |
| histograms.ExpectUniqueSample( |
| DefaultSearchManager::kDefaultSearchEngineMirrorCheckOutcomeMetric, |
| static_cast<int>( |
| DefaultSearchManager::DefaultSearchEngineMirrorCheckOutcomeType:: |
| kResetSkippedForEnterpriseDevice), |
| 1); |
| |
| // Ensure the notification is not shown. |
| EXPECT_FALSE(pref_service()->GetBoolean( |
| prefs::kShowDefaultSearchEngineResetNotification)); |
| |
| // The DSE should not have been changed. |
| DefaultSearchManager::Source source; |
| ExpectSimilar(user_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| } |
| #endif // BUILDFLAG(IS_WIN) |
| |
| TEST_F(DefaultSearchManagerTest, DontResetDefaultSearchIfFeatureDisabled) { |
| base::test::ScopedFeatureList feature_list; |
| feature_list.InitAndDisableFeature( |
| switches::kResetTamperedDefaultSearchEngine); |
| base::HistogramTester histograms; |
| |
| auto user_data = set_default_search_provider_data_pref("search_engine_A"); |
| set_mirrored_default_search_provider_data_pref("search_engine_B"); |
| |
| auto manager = create_manager(); |
| |
| // The DSE prefs should NOT be cleared. |
| EXPECT_FALSE( |
| pref_service() |
| ->GetDict(DefaultSearchManager::kDefaultSearchProviderDataPrefName) |
| .empty()); |
| EXPECT_FALSE( |
| pref_service() |
| ->GetDict( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName) |
| .empty()); |
| |
| // Nothing recorded in DefaultSearchEngineTamperingReset metric. |
| histograms.ExpectTotalCount( |
| DefaultSearchManager::kDefaultSearchEngineMirrorCheckOutcomeMetric, 0); |
| |
| // Ensure the notification is not shown. |
| EXPECT_FALSE(pref_service()->GetBoolean( |
| prefs::kShowDefaultSearchEngineResetNotification)); |
| |
| // The DSE should not have been changed. |
| DefaultSearchManager::Source source; |
| ExpectSimilar(user_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| } |
| |
| TEST_F(DefaultSearchManagerTest, DontResetDefaultSearchIfPrefsMatch) { |
| base::test::ScopedFeatureList feature_list{ |
| switches::kResetTamperedDefaultSearchEngine}; |
| base::HistogramTester histograms; |
| |
| auto user_data = set_default_search_provider_data_pref("search_engine_A"); |
| pref_service()->SetDict( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName, |
| TemplateURLDataToDictionary(*user_data)); |
| |
| auto manager = create_manager(); |
| |
| // The DSE prefs should NOT be cleared since the original and mirrored pref |
| // are the same. |
| EXPECT_FALSE( |
| pref_service() |
| ->GetDict(DefaultSearchManager::kDefaultSearchProviderDataPrefName) |
| .empty()); |
| EXPECT_FALSE( |
| pref_service() |
| ->GetDict( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName) |
| .empty()); |
| |
| // No tampering detected recorded. |
| histograms.ExpectUniqueSample( |
| DefaultSearchManager::kDefaultSearchEngineMirrorCheckOutcomeMetric, |
| static_cast<int>( |
| DefaultSearchManager::DefaultSearchEngineMirrorCheckOutcomeType:: |
| kNoTamperingDetected), |
| 1); |
| |
| // Ensure the notification is not shown. |
| EXPECT_FALSE(pref_service()->GetBoolean( |
| prefs::kShowDefaultSearchEngineResetNotification)); |
| |
| // The DSE should not have been changed. |
| DefaultSearchManager::Source source; |
| ExpectSimilar(user_data.get(), manager->GetDefaultSearchEngine(&source)); |
| EXPECT_EQ(DefaultSearchManager::FROM_USER, source); |
| } |
| |
| TEST_F(DefaultSearchManagerTest, RecentHmacReset) { |
| base::test::ScopedFeatureList feature_list{ |
| switches::kResetTamperedDefaultSearchEngine}; |
| base::HistogramTester histograms; |
| |
| // Empty DSE pref and a filled mirror pref to simulate DSE reset by HMAC |
| // check. |
| EXPECT_TRUE( |
| pref_service() |
| ->GetDict(DefaultSearchManager::kDefaultSearchProviderDataPrefName) |
| .empty()); |
| set_mirrored_default_search_provider_data_pref("search_engine_A"); |
| // Simulate the HMAC based reset happened now. |
| PrefHashFilter::SetResetTime(pref_service()); |
| |
| auto manager = create_manager(); |
| |
| // The original DSE prefs should still be empty. |
| EXPECT_TRUE( |
| pref_service() |
| ->GetDict(DefaultSearchManager::kDefaultSearchProviderDataPrefName) |
| .empty()); |
| // The mirrored DSE pref should have been cleared. |
| EXPECT_TRUE( |
| pref_service() |
| ->GetDict( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName) |
| .empty()); |
| |
| // A recent HMAC reset was recorded. |
| histograms.ExpectUniqueSample( |
| DefaultSearchManager::kDefaultSearchEngineMirrorCheckOutcomeMetric, |
| static_cast<int>( |
| DefaultSearchManager::DefaultSearchEngineMirrorCheckOutcomeType:: |
| kRecentHmacReset), |
| 1); |
| |
| // Ensure the notification is shown. |
| EXPECT_TRUE(pref_service()->GetBoolean( |
| prefs::kShowDefaultSearchEngineResetNotification)); |
| } |
| |
| TEST_F(DefaultSearchManagerTest, StaleHmacReset) { |
| base::test::ScopedFeatureList feature_list{ |
| switches::kResetTamperedDefaultSearchEngine}; |
| base::HistogramTester histograms; |
| |
| // Empty DSE pref and a filled mirror pref to simulate DSE reset by HMAC |
| // check. |
| EXPECT_TRUE( |
| pref_service() |
| ->GetDict(DefaultSearchManager::kDefaultSearchProviderDataPrefName) |
| .empty()); |
| set_mirrored_default_search_provider_data_pref("search_engine_A"); |
| // Simulate the HMAC based reset happened previously. |
| PrefHashFilter::ClearResetTime(pref_service()); |
| |
| auto manager = create_manager(); |
| |
| // The original DSE prefs should still be empty. |
| EXPECT_TRUE( |
| pref_service() |
| ->GetDict(DefaultSearchManager::kDefaultSearchProviderDataPrefName) |
| .empty()); |
| // The mirrored DSE pref should have been cleared. |
| EXPECT_TRUE( |
| pref_service() |
| ->GetDict( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName) |
| .empty()); |
| |
| // A stale HMAC reset was recorded. |
| histograms.ExpectUniqueSample( |
| DefaultSearchManager::kDefaultSearchEngineMirrorCheckOutcomeMetric, |
| static_cast<int>( |
| DefaultSearchManager::DefaultSearchEngineMirrorCheckOutcomeType:: |
| kStaleHmacReset), |
| 1); |
| |
| // Ensure the notification is not shown. |
| EXPECT_FALSE(pref_service()->GetBoolean( |
| prefs::kShowDefaultSearchEngineResetNotification)); |
| } |
| |
| TEST_F(DefaultSearchManagerTest, EncryptionResetShowsNotification) { |
| base::test::ScopedFeatureList feature_list{ |
| switches::kResetTamperedDefaultSearchEngine}; |
| base::HistogramTester histograms; |
| |
| // Set up matching prefs so that no reset happens on initialization. |
| auto user_data = set_default_search_provider_data_pref("search_engine_A"); |
| pref_service()->SetDict( |
| DefaultSearchManager::kMirroredDefaultSearchProviderDataPrefName, |
| TemplateURLDataToDictionary(*user_data)); |
| |
| auto manager = create_manager(); |
| |
| // Verify that no reset occurred on initialization. |
| EXPECT_FALSE( |
| pref_service() |
| ->GetDict(DefaultSearchManager::kDefaultSearchProviderDataPrefName) |
| .empty()); |
| |
| // Simulate an encryption-based reset by setting the reset time |
| // and clearing the main DSE pref. |
| PrefHashFilter::SetResetTime(pref_service()); |
| pref_service()->ClearPref( |
| DefaultSearchManager::kDefaultSearchProviderDataPrefName); |
| |
| // Ensure the notification is shown. |
| EXPECT_TRUE(pref_service()->GetBoolean( |
| prefs::kShowDefaultSearchEngineResetNotification)); |
| } |
| #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) |