1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
// 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/enterprise/enterprise_search_manager.h"
#include <memory>
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/values.h"
#include "components/omnibox/common/omnibox_feature_configs.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_value_map.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/search_engines/default_search_manager.h"
#include "components/search_engines/template_url_data.h"
#include "components/search_engines/template_url_data_util.h"
namespace {
std::unique_ptr<TemplateURLData> DictToTemplateURLData(
const base::Value& engine) {
const base::Value::Dict& url_dict = engine.GetDict();
std::unique_ptr<TemplateURLData> turl_data =
TemplateURLDataFromDictionary(url_dict);
CHECK(turl_data);
return turl_data;
}
} // namespace
// A dictionary to hold all data related to the site search engines defined by
// policy.
const char EnterpriseSearchManager::kSiteSearchSettingsPrefName[] =
"site_search_settings.template_url_data";
// A list to hold the keywords of site search engines which the user
// has overridden.
const char
EnterpriseSearchManager::kSiteSearchSettingsOverriddenKeywordsPrefName[] =
"site_search_settings.overridden_keywords";
// A dictionary to hold all TemplateURL data related to the enterprise search
// aggregator defined by policy.
const char
EnterpriseSearchManager::kEnterpriseSearchAggregatorSettingsPrefName[] =
"enterprise_search_aggregator_settings.template_url_data";
// A boolean to hold whether a shortcut is required for the enterprise search
// aggregator.
const char EnterpriseSearchManager::
kEnterpriseSearchAggregatorSettingsRequireShortcutPrefName[] =
"enterprise_search_aggregator_settings.require_shortcut";
EnterpriseSearchManager::EnterpriseSearchManager(
PrefService* pref_service,
const ObserverCallback& change_observer)
: pref_service_(pref_service), change_observer_(change_observer) {
if (pref_service_) {
pref_change_registrar_.Init(pref_service_);
pref_change_registrar_.Add(
kSiteSearchSettingsPrefName,
base::BindRepeating(&EnterpriseSearchManager::OnPrefChanged,
base::Unretained(this)));
if (base::FeatureList::IsEnabled(omnibox::kEnableSearchAggregatorPolicy)) {
pref_change_registrar_.Add(
kEnterpriseSearchAggregatorSettingsPrefName,
base::BindRepeating(&EnterpriseSearchManager::OnPrefChanged,
base::Unretained(this)));
}
OnPrefChanged();
}
}
EnterpriseSearchManager::~EnterpriseSearchManager() = default;
// static
void EnterpriseSearchManager::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterListPref(kSiteSearchSettingsPrefName);
registry->RegisterListPref(kSiteSearchSettingsOverriddenKeywordsPrefName);
registry->RegisterListPref(kEnterpriseSearchAggregatorSettingsPrefName);
registry->RegisterBooleanPref(
kEnterpriseSearchAggregatorSettingsRequireShortcutPrefName, false);
}
bool EnterpriseSearchManager::GetRequireShortcutValue() const {
// Prefer mock `require_shortcut` over `require_shortcut` from pref.
// TODO(crbug.com/402175538): Remove the ability to override pref engines via
// feature.
if (!omnibox_feature_configs::SearchAggregatorProvider::Get()
.AreMockEnginesValid()) {
// Use the `require_shortcut` preference value if set by policy.
const PrefService::Preference* pref = pref_service_->FindPreference(
kEnterpriseSearchAggregatorSettingsRequireShortcutPrefName);
return pref && pref->GetValue()->GetBool();
}
return omnibox_feature_configs::SearchAggregatorProvider::Get()
.require_shortcut;
}
void EnterpriseSearchManager::OnPrefChanged() {
if (!change_observer_) {
return;
}
EnterpriseSearchManager::OwnedTemplateURLDataVector search_engines;
LoadingResult site_search_loading_result = LoadSearchEnginesFromPrefs(
pref_service_->FindPreference(kSiteSearchSettingsPrefName),
&search_engines);
LoadingResult search_aggregator_loading_result =
LoadSearchAggregator(&search_engines);
if (site_search_loading_result != LoadingResult::kUnavailable ||
search_aggregator_loading_result != LoadingResult::kUnavailable) {
change_observer_.Run(std::move(search_engines));
}
}
// Adds the search providers read from `pref` to `search_engines`. Returns true
// if `pref` exists and is managed.
EnterpriseSearchManager::LoadingResult
EnterpriseSearchManager::LoadSearchEnginesFromPrefs(
const PrefService::Preference* pref,
EnterpriseSearchManager::OwnedTemplateURLDataVector* search_engines) {
// Only accept site search engine created by policy.
if (!pref || !pref->IsManaged()) {
return LoadingResult::kUnavailable;
}
// Get the list of engines from the main policy pref.
const base::Value::List& engine_list = pref->GetValue()->GetList();
// For site search engines, load the
// `kSiteSearchSettingsOverriddenKeywordsPrefName` pref dictionary.
if (base::FeatureList::IsEnabled(
omnibox::kEnableSiteSearchAllowUserOverridePolicy) &&
pref->name() == kSiteSearchSettingsPrefName) {
LoadOverriddenKeywordsPref(engine_list);
}
LoadingResult result = LoadingResult::kAvailableEmpty;
for (const base::Value& engine : engine_list) {
const base::Value::Dict& engine_dict = engine.GetDict();
const std::string* keyword =
engine_dict.FindString(DefaultSearchManager::kKeyword);
CHECK(keyword);
if (base::FeatureList::IsEnabled(
omnibox::kEnableSiteSearchAllowUserOverridePolicy) &&
pref_service_
->GetList(EnterpriseSearchManager::
kSiteSearchSettingsOverriddenKeywordsPrefName)
.contains(*keyword)) {
continue;
}
search_engines->emplace_back(DictToTemplateURLData(engine));
result = LoadingResult::kAvailableNonEmpty;
}
return result;
}
EnterpriseSearchManager::LoadingResult
EnterpriseSearchManager::LoadSearchAggregator(
EnterpriseSearchManager::OwnedTemplateURLDataVector* search_engines) {
// Prefer mock engines over engines from pref.
// TODO(crbug.com/402175538): Remove the ability to override pref engines via
// feature.
if (!omnibox_feature_configs::SearchAggregatorProvider::Get()
.AreMockEnginesValid()) {
return LoadSearchEnginesFromPrefs(
pref_service_->FindPreference(
kEnterpriseSearchAggregatorSettingsPrefName),
search_engines);
}
// NOTE: This function assumes that `search_engines` does not contain any
// engines that should be overridden by the feature config.
std::ranges::transform(
omnibox_feature_configs::SearchAggregatorProvider::Get()
.CreateMockSearchEngines(),
std::back_inserter(*search_engines), [](const base::Value& mock_engine) {
return DictToTemplateURLData(mock_engine);
});
return LoadingResult::kAvailableNonEmpty;
}
void EnterpriseSearchManager::LoadOverriddenKeywordsPref(
const base::Value::List& engine_list) {
ScopedListPrefUpdate overridden_keywords_update(
pref_service_, kSiteSearchSettingsOverriddenKeywordsPrefName);
base::Value::List& overridden_keywords_list =
overridden_keywords_update.Get();
// Keep track of keywords present in the current policy along with whether
// they are enforced by policy.
base::flat_map<std::string, bool> policy_keywords_enforced_status;
for (const base::Value& engine : engine_list) {
const base::Value::Dict& engine_dict = engine.GetDict();
const std::string* keyword =
engine_dict.FindString(DefaultSearchManager::kKeyword);
CHECK(keyword);
bool enforced_by_policy =
engine_dict.FindBool(DefaultSearchManager::kEnforcedByPolicy)
.value_or(false);
policy_keywords_enforced_status[*keyword] = enforced_by_policy;
}
// Remove keywords from the overridden keywords list for engines that are no
// longer present in the policy or that are NOW enforced.
overridden_keywords_list.EraseIf(
[&policy_keywords_enforced_status](const base::Value& v) {
auto it = policy_keywords_enforced_status.find(v.GetString());
return it == policy_keywords_enforced_status.end() || it->second;
});
}
void EnterpriseSearchManager::AddOverriddenKeyword(const std::string& keyword) {
if (!pref_service_) {
return;
}
ScopedListPrefUpdate overridden_keywords_update(
pref_service_, kSiteSearchSettingsOverriddenKeywordsPrefName);
overridden_keywords_update.Get().Append(keyword);
}
|