// 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.
#import "ios/chrome/browser/search_engine_choice/model/search_engine_choice_util.h"
#import "base/check_deref.h"
#import "base/feature_list.h"
#import "base/memory/raw_ptr.h"
#import "base/test/metrics/histogram_tester.h"
#import "base/test/scoped_feature_list.h"
#import "components/metrics/metrics_pref_names.h"
#import "components/policy/core/common/mock_policy_service.h"
#import "components/search_engines/search_engine_choice/search_engine_choice_service.h"
#import "components/search_engines/search_engines_pref_names.h"
#import "components/search_engines/search_engines_switches.h"
#import "components/search_engines/template_url_data.h"
#import "components/search_engines/template_url_prepopulate_data.h"
#import "components/search_engines/template_url_service.h"
#import "components/signin/public/base/signin_switches.h"
#import "ios/chrome/browser/policy/model/browser_state_policy_connector_mock.h"
#import "ios/chrome/browser/search_engines/model/template_url_service_factory.h"
#import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
#import "ios/chrome/browser/signin/model/authentication_service_factory.h"
#import "ios/web/public/test/web_task_environment.h"
#import "testing/gtest/include/gtest/gtest.h"
#import "testing/platform_test.h"
class SearchEngineChoiceUtilTest : public PlatformTest {
public:
SearchEngineChoiceUtilTest() {
// Override the country checks to simulate being in Belgium.
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kSearchEngineChoiceCountry, "BE");
InitMockPolicyService();
TestChromeBrowserState::Builder builder;
builder.SetPolicyConnector(
std::make_unique<BrowserStatePolicyConnectorMock>(
std::move(policy_service_), &schema_registry_));
builder.AddTestingFactory(
ios::TemplateURLServiceFactory::GetInstance(),
ios::TemplateURLServiceFactory::GetDefaultFactory());
browser_state_ = std::move(builder).Build();
template_url_service_ = ios::TemplateURLServiceFactory::GetForBrowserState(
browser_state_.get());
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kForceSearchEngineChoiceScreen);
}
TestChromeBrowserState& browser_state() { return *browser_state_; }
base::HistogramTester histogram_tester_;
TemplateURLService& template_url_service() { return *template_url_service_; }
base::test::ScopedFeatureList& feature_list() { return feature_list_; }
private:
void InitMockPolicyService() {
policy_service_ = std::make_unique<policy::MockPolicyService>();
ON_CALL(*policy_service_.get(),
GetPolicies(::testing::Eq(policy::PolicyNamespace(
policy::POLICY_DOMAIN_CHROME, std::string()))))
.WillByDefault(::testing::ReturnRef(policy_map_));
}
web::WebTaskEnvironment task_environment_;
policy::SchemaRegistry schema_registry_;
base::test::ScopedFeatureList feature_list_{
switches::kSearchEngineChoiceTrigger};
std::unique_ptr<TestChromeBrowserState> browser_state_;
// Owned by browser_state_.
raw_ptr<TemplateURLService> template_url_service_;
std::unique_ptr<policy::MockPolicyService> policy_service_;
policy::PolicyMap policy_map_;
};
TEST_F(SearchEngineChoiceUtilTest, ShowChoiceScreenIfPoliciesAreNotSet) {
EXPECT_TRUE(ShouldDisplaySearchEngineChoiceScreen(
browser_state(), search_engines::ChoicePromo::kDialog,
/*app_started_via_external_intent=*/false));
histogram_tester_.ExpectUniqueSample(
search_engines::kSearchEngineChoiceScreenProfileInitConditionsHistogram,
search_engines::SearchEngineChoiceScreenConditions::kEligible, 1);
}
TEST_F(SearchEngineChoiceUtilTest,
ShowChoiceScreenIfPoliciesAreNotSetStartedByExternalIntent) {
EXPECT_FALSE(ShouldDisplaySearchEngineChoiceScreen(
browser_state(), search_engines::ChoicePromo::kDialog,
/*app_started_via_external_intent=*/true));
histogram_tester_.ExpectUniqueSample(
search_engines::kSearchEngineChoiceScreenProfileInitConditionsHistogram,
search_engines::SearchEngineChoiceScreenConditions::
kAppStartedByExternalIntent,
1);
}
TEST_F(
SearchEngineChoiceUtilTest,
ShowChoiceScreenIfPoliciesAreNotSetStartedByExternalIntentAlmostMaxCount) {
ASSERT_GT(switches::kSearchEngineChoiceMaximumSkipCount.Get(), 0);
PrefService* pref_service = browser_state().GetPrefs();
pref_service->SetInteger(
prefs::kDefaultSearchProviderChoiceScreenSkippedCount,
switches::kSearchEngineChoiceMaximumSkipCount.Get() - 1);
EXPECT_FALSE(ShouldDisplaySearchEngineChoiceScreen(
browser_state(), search_engines::ChoicePromo::kDialog,
/*app_started_via_external_intent=*/true));
histogram_tester_.ExpectUniqueSample(
search_engines::kSearchEngineChoiceScreenProfileInitConditionsHistogram,
search_engines::SearchEngineChoiceScreenConditions::
kAppStartedByExternalIntent,
1);
}
TEST_F(
SearchEngineChoiceUtilTest,
ShowChoiceScreenIfPoliciesAreNotSetStartedByExternalIntentMaxCountReached) {
PrefService* pref_service = browser_state().GetPrefs();
pref_service->SetInteger(
prefs::kDefaultSearchProviderChoiceScreenSkippedCount,
switches::kSearchEngineChoiceMaximumSkipCount.Get());
EXPECT_TRUE(ShouldDisplaySearchEngineChoiceScreen(
browser_state(), search_engines::ChoicePromo::kDialog,
/*app_started_via_external_intent=*/true));
histogram_tester_.ExpectUniqueSample(
search_engines::kSearchEngineChoiceScreenProfileInitConditionsHistogram,
search_engines::SearchEngineChoiceScreenConditions::kEligible, 1);
}
TEST_F(SearchEngineChoiceUtilTest,
DoNotShowChoiceScreenIfUserHasCustomSearchEngineSetAsDefault) {
feature_list().Reset();
feature_list().InitAndEnableFeatureWithParameters(
switches::kSearchEngineChoiceTrigger,
{{switches::kSearchEngineChoiceTriggerSkipFor3p.name, "false"}});
// A custom search engine will have a `prepopulate_id` of 0.
const int kCustomSearchEnginePrepopulateId = 0;
TemplateURLData template_url_data;
template_url_data.prepopulate_id = kCustomSearchEnginePrepopulateId;
template_url_data.SetURL("https://www.example.com/?q={searchTerms}");
template_url_service().SetUserSelectedDefaultSearchProvider(
template_url_service().Add(
std::make_unique<TemplateURL>(template_url_data)));
EXPECT_FALSE(ShouldDisplaySearchEngineChoiceScreen(
browser_state(), search_engines::ChoicePromo::kDialog,
/*app_started_via_external_intent=*/false));
histogram_tester_.ExpectUniqueSample(
search_engines::kSearchEngineChoiceScreenProfileInitConditionsHistogram,
search_engines::SearchEngineChoiceScreenConditions::
kHasCustomSearchEngine,
1);
}
TEST_F(SearchEngineChoiceUtilTest,
DoNotShowChoiceScreenIfUserHasNonGoogleSearchEngineSetAsDefault) {
feature_list().Reset();
feature_list().InitAndEnableFeatureWithParameters(
switches::kSearchEngineChoiceTrigger,
{{switches::kSearchEngineChoiceTriggerSkipFor3p.name, "true"}});
// A custom search engine will have a `prepopulate_id` of 0.
const int kCustomSearchEnginePrepopulateId = 0;
TemplateURLData template_url_data;
template_url_data.prepopulate_id = kCustomSearchEnginePrepopulateId;
template_url_data.SetURL("https://www.example.com/?q={searchTerms}");
template_url_service().SetUserSelectedDefaultSearchProvider(
template_url_service().Add(
std::make_unique<TemplateURL>(template_url_data)));
EXPECT_FALSE(ShouldDisplaySearchEngineChoiceScreen(
browser_state(), search_engines::ChoicePromo::kDialog,
/*app_started_via_external_intent=*/false));
histogram_tester_.ExpectUniqueSample(
search_engines::kSearchEngineChoiceScreenProfileInitConditionsHistogram,
search_engines::SearchEngineChoiceScreenConditions::
kHasNonGoogleSearchEngine,
1);
}