blob: bf2afadea2ea1c83f27abba5034833a2d6b786e8 [file] [log] [blame]
// Copyright 2023 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/site_search_policy_handler.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/policy/core/browser/configuration_policy_pref_store.h"
#include "components/policy/core/browser/configuration_policy_pref_store_test.h"
#include "components/policy/core/browser/policy_error_map.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/core/common/schema.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_value_map.h"
#include "components/search_engines/default_search_manager.h"
#include "components/search_engines/enterprise_site_search_manager.h"
#include "components/search_engines/template_url_data.h"
#include "components/strings/grit/components_strings.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
using testing::AllOf;
using testing::ElementsAre;
namespace policy {
namespace {
// Represents field values for SiteSearchSettings policy, used for generating
// policy value entries. Fields set as nullptr will not be added to the
// entry dictionary.
struct TestProvider {
const char* name;
const char* shortcut;
const char* url;
bool featured_by_policy = false;
const char* favicon;
};
// Used for tests that require a list of valid providers.
TestProvider kValidTestProviders[] = {
{.name = "work name",
.shortcut = "work",
.url = "https://work.com/{searchTerms}",
.featured_by_policy = false,
.favicon = "https://work.com/favicon.ico"},
{.name = "docs name",
.shortcut = "docs",
.url = "https://docs.com/{searchTerms}",
.favicon = "https://docs.com/favicon.ico"},
};
// Used for tests that require providers with missing required fields. Missing
// fields for test are represented as nullptr.
TestProvider kMissingRequiredFieldsTestProviders[] = {
{.name = nullptr,
.shortcut = "missing_name",
.url = "https://missing_name.com/{searchTerms}",
.favicon = nullptr},
{.name = "missing_shortcut name",
.shortcut = nullptr,
.url = "https://missing_shortcut.com/{searchTerms}",
.favicon = nullptr},
{.name = "missing_url name",
.shortcut = "missing_url",
.url = nullptr,
.favicon = nullptr},
};
// Used for tests that require providers with empty required fields.
TestProvider kEmptyFieldTestProviders[] = {
{.name = "",
.shortcut = "empty_name",
.url = "https://empty_name.com/{searchTerms}",
.favicon = nullptr},
{.name = "empty_shortcut name",
.shortcut = "",
.url = "https://empty_shortcut.com/{searchTerms}",
.favicon = nullptr},
{.name = "empty_url name",
.shortcut = "empty_url",
.url = "",
.favicon = nullptr},
};
// Used for tests that require a provider with unknown field.
TestProvider kUnknownFieldTestProviders[] = {
{.name = "work name",
.shortcut = "work",
.url = "https://work.com/{searchTerms}",
.favicon = "https://work.com/favicon.ico"},
};
// Used for tests that require a list of providers with a duplicated shortcut,
// but at least one valid entry.
TestProvider kShortcutNotUniqueTestProviders[] = {
{.name = "work name",
.shortcut = "work",
.url = "https://work.com/q={searchTerms}&x",
.favicon = nullptr},
{.name = "also work name",
.shortcut = "work",
.url = "https://work.com/q={searchTerms}&y",
.favicon = nullptr},
{.name = "docs name",
.shortcut = "docs",
.url = "https://docs.com/{searchTerms}",
.favicon = "https://docs.com/favicon.ico"},
};
// Used for tests that require a list of providers with a duplicated shortcut
// and no valid entry.
TestProvider kNoUniqueShortcutTestProviders[] = {
{.name = "work name",
.shortcut = "work",
.url = "https://work.com/q={searchTerms}&x",
.favicon = nullptr},
{.name = "also work name",
.shortcut = "work",
.url = "https://work.com/q={searchTerms}&y",
.favicon = nullptr},
};
// Used for tests that require a provider shortcut containing a space
// and no valid entry.
TestProvider kShortcutWithSpacesTestProviders[] = {
{.name = "work name 1",
.shortcut = " shortcut",
.url = "https://work1.com/q={searchTerms}&x",
.favicon = nullptr},
{.name = "work name 2",
.shortcut = "shortcut ",
.url = "https://work2.com/q={searchTerms}&x",
.favicon = nullptr},
{.name = "work name 3",
.shortcut = "short cut",
.url = "https://work3.com/q={searchTerms}&x",
.favicon = nullptr},
};
// Used for tests that require a provider shortcut that stars with @.
TestProvider kShortcutStartsWithAtTestProviders[] = {
{.name = "invalid",
.shortcut = "@work",
.url = "https://work.com/q={searchTerms}&x",
.favicon = nullptr},
{.name = "valid",
.shortcut = "wo@rk",
.url = "https://work.com/q={searchTerms}&y",
.favicon = "https://work.com/favicon.ico"},
};
// Used for tests that require a provider with invalid non-empty URLs.
TestProvider kInvalidUrlTestProviders[] = {
{.name = "invalid1 name",
.shortcut = "invalid1",
.url = "https://work.com/q=searchTerms",
.favicon = nullptr},
{.name = "invalid2 name",
.shortcut = "invalid2",
.url = "https://work.com/q=%s",
.favicon = nullptr},
{.name = "invalid3 name",
.shortcut = "invalid3",
.url = "https://work.com",
.favicon = nullptr},
};
constexpr char kDSPKeyword[] = "dsp_keyword";
// Used for tests that require a provider with invalid non-empty URLs.
TestProvider kShortcutSameAsDSPKeywordTestProviders[] = {
{.name = "same as keyword",
.shortcut = kDSPKeyword,
.url = "https://work.com/q={searchTerms}&x",
.favicon = "https://work.com/favicon.ico"},
{.name = "something else",
.shortcut = "something_else",
.url = "https://work.com/q={searchTerms}&y",
.favicon = "https://work.com/favicon.ico"},
};
// Used for tests that require a provider with non-HTTPS URL.
TestProvider kNonHttpsUrlTestProviders[] = {
{.name = "work name",
.shortcut = "work",
.url = "http://work.com/q={searchTerms}",
.favicon = "http://work.com/favicon.ico"},
};
// Used for tests that require a list of featured providers.
TestProvider kTestProvidersWithFeaturedEntries[] = {
{.name = "work name",
.shortcut = "work",
.url = "https://work.com/{searchTerms}",
.featured_by_policy = true,
.favicon = "https://work.com/favicon.ico"},
{.name = "non-featured name",
.shortcut = "non-featured",
.url = "https://non-featured.com/{searchTerms}",
.featured_by_policy = false,
.favicon = "https://non-featured.com/favicon.ico"},
{.name = "docs name",
.shortcut = "docs",
.url = "https://docs.com/{searchTerms}",
.featured_by_policy = true,
.favicon = "https://docs.com/favicon.ico"},
};
// Creates a simple list item for the site search policy.
base::Value::Dict GenerateSiteSearchPolicyEntry(const std::string& name,
const std::string& shortcut,
const std::string& url,
bool featured_by_policy) {
base::Value::Dict entry;
entry.Set(SiteSearchPolicyHandler::kName, name);
entry.Set(SiteSearchPolicyHandler::kShortcut, shortcut);
entry.Set(SiteSearchPolicyHandler::kUrl, url);
entry.Set(SiteSearchPolicyHandler::kFeatured, featured_by_policy);
return entry;
}
base::Value::Dict GenerateSiteSearchPolicyEntry(TestProvider test_case) {
base::Value::Dict entry;
if (test_case.name) {
entry.Set(SiteSearchPolicyHandler::kName, test_case.name);
}
if (test_case.shortcut) {
entry.Set(SiteSearchPolicyHandler::kShortcut, test_case.shortcut);
}
if (test_case.url) {
entry.Set(SiteSearchPolicyHandler::kUrl, test_case.url);
}
entry.Set(SiteSearchPolicyHandler::kFeatured, test_case.featured_by_policy);
return entry;
}
// Accepts a dictionary that has a string field `field_name` with value
// `expected_value`.
MATCHER_P2(HasStringField,
field_name,
expected_value,
base::StringPrintf("%s string field `%s` with value `%s`",
negation ? "does not contain" : "contains",
field_name,
expected_value.c_str())) {
const std::string* dict_value = (arg).GetDict().FindString(field_name);
return dict_value && *dict_value == expected_value;
}
// Accepts a dictionary that has a boolean field `field_name` with value
// `expected_value`.
MATCHER_P2(HasBooleanField,
field_name,
expected_value,
base::StringPrintf("%s boolean field `%s` with value `%d`",
negation ? "does not contain" : "contains",
field_name,
expected_value)) {
std::optional<bool> dict_value = (arg).GetDict().FindBool(field_name);
return dict_value && *dict_value == expected_value;
}
// Accepts a dictionary that has a double field `field_name` with non-zero
// value.
MATCHER_P2(HasIntegerField,
field_name,
expected_value,
base::StringPrintf("%s integer field `%s` with value `%d`",
negation ? "does not contain" : "contains",
field_name,
expected_value)) {
std::optional<int> dict_value = (arg).GetDict().FindInt(field_name);
return dict_value && *dict_value == expected_value;
}
// Accepts a dictionary that has a double field `field_name` with non-zero
// value.
MATCHER_P(HasDoubleField,
field_name,
base::StringPrintf("%s double field `%s` with non-zero value",
negation ? "does not contain" : "contains",
field_name)) {
std::optional<double> dict_value = (arg).GetDict().FindDouble(field_name);
return dict_value && *dict_value != 0.0;
}
// Returns a matcher that accepts entries for the pref corresponding to the
// site search policy. Field values are obtained from |test_case|.
testing::Matcher<const base::Value&> IsSiteSearchEntry(TestProvider test_case,
bool featured) {
std::string expected_keyword =
base::StringPrintf("%s%s", (featured ? "@" : ""), test_case.shortcut);
return AllOf(
HasStringField(DefaultSearchManager::kShortName,
std::string(test_case.name)),
HasStringField(DefaultSearchManager::kKeyword, expected_keyword),
HasStringField(DefaultSearchManager::kURL, std::string(test_case.url)),
HasBooleanField(DefaultSearchManager::kFeaturedByPolicy, featured),
HasIntegerField(
DefaultSearchManager::kCreatedByPolicy,
static_cast<int>(TemplateURLData::CreatedByPolicy::kSiteSearch)),
HasBooleanField(DefaultSearchManager::kEnforcedByPolicy, false),
HasIntegerField(DefaultSearchManager::kIsActive,
static_cast<int>(TemplateURLData::ActiveStatus::kTrue)),
HasStringField(DefaultSearchManager::kFaviconURL,
std::string(test_case.favicon)),
HasBooleanField(DefaultSearchManager::kSafeForAutoReplace, false),
HasDoubleField(DefaultSearchManager::kDateCreated),
HasDoubleField(DefaultSearchManager::kLastModified));
}
testing::Matcher<const base::Value&> IsNonFeaturedSiteSearchEntry(
TestProvider test_case) {
return IsSiteSearchEntry(test_case, /*featured=*/false);
}
testing::Matcher<const base::Value&> IsFeaturedSiteSearchEntry(
TestProvider test_case) {
return IsSiteSearchEntry(test_case, /*featured=*/true);
}
MATCHER_P(HasValidationError,
expected_str,
base::StringPrintf("%s error message `%s` for `SiteSearchSettings`",
negation ? "does not contain" : "contains",
base::UTF16ToUTF8(expected_str).c_str())) {
return arg->HasError(key::kSiteSearchSettings) &&
arg->GetErrorMessages(key::kSiteSearchSettings).find(expected_str) !=
std::wstring::npos;
}
} // namespace
TEST(SiteSearchPolicyHandlerTest, FeatureDisabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
policy_value.Append(GenerateSiteSearchPolicyEntry(kValidTestProviders[0]));
policy_value.Append(GenerateSiteSearchPolicyEntry(kValidTestProviders[1]));
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_TRUE(errors.empty());
handler.ApplyPolicySettings(policies, &prefs);
base::Value* unset = nullptr;
ASSERT_FALSE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &unset));
}
TEST(SiteSearchPolicyHandlerTest, PolicyNotSet) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_TRUE(errors.empty());
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_TRUE(providers->GetList().empty());
}
TEST(SiteSearchPolicyHandlerTest, ValidSiteSearchEntries) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
policy_value.Append(GenerateSiteSearchPolicyEntry(kValidTestProviders[0]));
policy_value.Append(GenerateSiteSearchPolicyEntry(kValidTestProviders[1]));
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_TRUE(errors.empty());
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_THAT(
providers->GetList(),
ElementsAre(IsNonFeaturedSiteSearchEntry(kValidTestProviders[0]),
IsNonFeaturedSiteSearchEntry(kValidTestProviders[1])));
}
TEST(SiteSearchPolicyHandlerTest, InvalidFormat) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(false), nullptr);
ASSERT_FALSE(handler.CheckPolicySettings(policies, &errors));
EXPECT_TRUE(errors.HasError(key::kSiteSearchSettings));
}
TEST(SiteSearchPolicyHandlerTest, TooManySiteSearchEntries) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
// Policy value has one list entry over the max allowed.
base::Value::List policy_value;
for (int i = 0; i <= SiteSearchPolicyHandler::kMaxSiteSearchProviders; ++i) {
policy_value.Append(GenerateSiteSearchPolicyEntry(
base::StringPrintf("shortcut_%d", i), base::StringPrintf("name %d", i),
base::StringPrintf("https://site_%d.com/q={searchTerms}", i),
/*featured_by_policy=*/false));
}
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_FALSE(handler.CheckPolicySettings(policies, &errors));
EXPECT_THAT(&errors,
HasValidationError(l10n_util::GetStringFUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_MAX_PROVIDERS_LIMIT_ERROR,
base::NumberToString16(
SiteSearchPolicyHandler::kMaxSiteSearchProviders))));
}
TEST(SiteSearchPolicyHandlerTest, TooManyFeaturedSiteSearchEntries) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
// Policy value has one featured list entry over the max allowed.
base::Value::List policy_value;
for (int i = 0; i <= SiteSearchPolicyHandler::kMaxFeaturedProviders; ++i) {
policy_value.Append(GenerateSiteSearchPolicyEntry(
base::StringPrintf("shortcut_%d", i), base::StringPrintf("name %d", i),
base::StringPrintf("https://site_%d.com/q={searchTerms}", i),
/*featured_by_policy=*/true));
}
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_FALSE(handler.CheckPolicySettings(policies, &errors));
EXPECT_THAT(
&errors,
HasValidationError(l10n_util::GetStringFUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_MAX_FEATURED_PROVIDERS_LIMIT_ERROR,
base::NumberToString16(
SiteSearchPolicyHandler::kMaxFeaturedProviders))));
}
TEST(SiteSearchPolicyHandlerTest, MissingRequiredField) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
for (auto* it = std::begin(kMissingRequiredFieldsTestProviders);
it != std::end(kMissingRequiredFieldsTestProviders); ++it) {
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_FALSE(handler.CheckPolicySettings(policies, &errors));
EXPECT_TRUE(errors.HasError(key::kSiteSearchSettings));
}
}
TEST(SiteSearchPolicyHandlerTest, ShortcutNotUnique) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kShortcutNotUniqueTestProviders);
it != std::end(kShortcutNotUniqueTestProviders); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_THAT(&errors, HasValidationError(l10n_util::GetStringFUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_DUPLICATED_SHORTCUT,
u"work")));
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_THAT(providers->GetList(), ElementsAre(IsNonFeaturedSiteSearchEntry(
kShortcutNotUniqueTestProviders[2])));
}
TEST(SiteSearchPolicyHandlerTest, NoUniqueShortcut) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kNoUniqueShortcutTestProviders);
it != std::end(kNoUniqueShortcutTestProviders); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_FALSE(handler.CheckPolicySettings(policies, &errors));
EXPECT_THAT(&errors, HasValidationError(l10n_util::GetStringFUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_DUPLICATED_SHORTCUT,
u"work")));
}
TEST(SiteSearchPolicyHandlerTest, EmptyRequiredField) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kEmptyFieldTestProviders);
it != std::end(kEmptyFieldTestProviders); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_FALSE(handler.CheckPolicySettings(policies, &errors));
EXPECT_THAT(&errors, HasValidationError(l10n_util::GetStringUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_SHORTCUT_IS_EMPTY)));
EXPECT_THAT(&errors, HasValidationError(l10n_util::GetStringUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_NAME_IS_EMPTY)));
EXPECT_THAT(&errors, HasValidationError(l10n_util::GetStringUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_URL_IS_EMPTY)));
}
TEST(SiteSearchPolicyHandlerTest, UnknownField) {
constexpr char kUnknownFieldName[] = "unknown_field";
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::Dict entry =
GenerateSiteSearchPolicyEntry(kUnknownFieldTestProviders[0]);
entry.Set(kUnknownFieldName, true);
base::Value::List policy_value;
policy_value.Append(std::move(entry));
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
// A warning is registered during policy validation, but valid fields are
// still used for building a new template URL.
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_FALSE(errors.empty());
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_THAT(
providers->GetList(),
ElementsAre(IsNonFeaturedSiteSearchEntry(kUnknownFieldTestProviders[0])));
}
TEST(SiteSearchPolicyHandlerTest, ShortcutWithSpace) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kShortcutWithSpacesTestProviders);
it != std::end(kShortcutWithSpacesTestProviders); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_FALSE(handler.CheckPolicySettings(policies, &errors));
for (auto* it = std::begin(kShortcutWithSpacesTestProviders);
it != std::end(kShortcutWithSpacesTestProviders); ++it) {
EXPECT_THAT(&errors,
HasValidationError(l10n_util::GetStringFUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_SHORTCUT_CONTAINS_SPACE,
base::UTF8ToUTF16(it->shortcut))));
}
}
TEST(SiteSearchPolicyHandlerTest, ShortcutStartsWithAt) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kShortcutStartsWithAtTestProviders);
it != std::end(kShortcutStartsWithAtTestProviders); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_THAT(
&errors,
HasValidationError(l10n_util::GetStringFUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_SHORTCUT_STARTS_WITH_AT,
base::UTF8ToUTF16(kShortcutStartsWithAtTestProviders[0].shortcut))));
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_THAT(providers->GetList(),
ElementsAre(IsNonFeaturedSiteSearchEntry(
kShortcutStartsWithAtTestProviders[1])));
}
TEST(SiteSearchPolicyHandlerTest, InvalidUrl) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kInvalidUrlTestProviders);
it != std::end(kInvalidUrlTestProviders); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_FALSE(handler.CheckPolicySettings(policies, &errors));
for (auto* it = std::begin(kInvalidUrlTestProviders);
it != std::end(kInvalidUrlTestProviders); ++it) {
EXPECT_THAT(
&errors,
HasValidationError(l10n_util::GetStringFUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_URL_DOESNT_SUPPORT_REPLACEMENT,
base::UTF8ToUTF16(it->url))));
}
}
TEST(SiteSearchPolicyHandlerTest, ShortcutSameAsDSPKeyword_DSPEnabledNotSet) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kShortcutSameAsDSPKeywordTestProviders);
it != std::end(kShortcutSameAsDSPKeywordTestProviders); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kDefaultSearchProviderKeyword,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD, base::Value(kDSPKeyword), nullptr);
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_TRUE(errors.empty());
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_THAT(providers->GetList(),
ElementsAre(IsNonFeaturedSiteSearchEntry(
kShortcutSameAsDSPKeywordTestProviders[0]),
IsNonFeaturedSiteSearchEntry(
kShortcutSameAsDSPKeywordTestProviders[1])));
}
TEST(SiteSearchPolicyHandlerTest, ShortcutSameAsDSPKeyword_DSPDisabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kShortcutSameAsDSPKeywordTestProviders);
it != std::end(kShortcutSameAsDSPKeywordTestProviders); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kDefaultSearchProviderEnabled,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD, base::Value(false), nullptr);
policies.Set(key::kDefaultSearchProviderKeyword,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD, base::Value(kDSPKeyword), nullptr);
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_TRUE(errors.empty());
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_THAT(providers->GetList(),
ElementsAre(IsNonFeaturedSiteSearchEntry(
kShortcutSameAsDSPKeywordTestProviders[0]),
IsNonFeaturedSiteSearchEntry(
kShortcutSameAsDSPKeywordTestProviders[1])));
}
TEST(SiteSearchPolicyHandlerTest, ShortcutSameAsDSPKeyword_DSPEnabled) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kShortcutSameAsDSPKeywordTestProviders);
it != std::end(kShortcutSameAsDSPKeywordTestProviders); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kDefaultSearchProviderEnabled,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD, base::Value(true), nullptr);
policies.Set(key::kDefaultSearchProviderKeyword,
policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
policy::POLICY_SOURCE_CLOUD, base::Value(kDSPKeyword), nullptr);
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_THAT(&errors,
HasValidationError(l10n_util::GetStringFUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_SHORTCUT_EQUALS_DSP_KEYWORD,
base::UTF8ToUTF16(
kShortcutSameAsDSPKeywordTestProviders[0].shortcut))));
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_THAT(providers->GetList(),
ElementsAre(IsNonFeaturedSiteSearchEntry(
kShortcutSameAsDSPKeywordTestProviders[1])));
}
TEST(SiteSearchPolicyHandlerTest, NonHttpsUrl) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
policy_value.Append(
GenerateSiteSearchPolicyEntry(kNonHttpsUrlTestProviders[0]));
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_THAT(&errors,
HasValidationError(l10n_util::GetStringFUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_URL_NOT_HTTPS,
base::UTF8ToUTF16(kNonHttpsUrlTestProviders[0].url))));
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_THAT(
providers->GetList(),
ElementsAre(IsNonFeaturedSiteSearchEntry(kNonHttpsUrlTestProviders[0])));
}
TEST(SiteSearchPolicyHandlerTest, NoValidEntry) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(base::Value::List()), nullptr);
ASSERT_FALSE(handler.CheckPolicySettings(policies, &errors));
EXPECT_THAT(&errors, HasValidationError(l10n_util::GetStringUTF16(
IDS_POLICY_SITE_SEARCH_SETTINGS_NO_VALID_PROVIDER)));
}
TEST(SiteSearchPolicyHandlerTest, FeaturedSiteSearchEntries) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(omnibox::kSiteSearchSettingsPolicy);
SiteSearchPolicyHandler handler(
policy::Schema::Wrap(policy::GetChromeSchemaData()));
policy::PolicyMap policies;
PolicyErrorMap errors;
PrefValueMap prefs;
base::Value::List policy_value;
for (auto* it = std::begin(kTestProvidersWithFeaturedEntries);
it != std::end(kTestProvidersWithFeaturedEntries); ++it) {
policy_value.Append(GenerateSiteSearchPolicyEntry(*it));
}
policies.Set(key::kSiteSearchSettings, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(std::move(policy_value)), nullptr);
ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors));
EXPECT_TRUE(errors.empty());
handler.ApplyPolicySettings(policies, &prefs);
base::Value* providers = nullptr;
ASSERT_TRUE(prefs.GetValue(
EnterpriseSiteSearchManager::kSiteSearchSettingsPrefName, &providers));
ASSERT_NE(providers, nullptr);
ASSERT_TRUE(providers->is_list());
EXPECT_THAT(
providers->GetList(),
ElementsAre(
IsNonFeaturedSiteSearchEntry(kTestProvidersWithFeaturedEntries[0]),
IsFeaturedSiteSearchEntry(kTestProvidersWithFeaturedEntries[0]),
IsNonFeaturedSiteSearchEntry(kTestProvidersWithFeaturedEntries[1]),
IsNonFeaturedSiteSearchEntry(kTestProvidersWithFeaturedEntries[2]),
IsFeaturedSiteSearchEntry(kTestProvidersWithFeaturedEntries[2])));
}
} // namespace policy