1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/search_engines/default_search_policy_handler.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/values.h"
13 #include "build/build_config.h"
14 #include "components/policy/core/browser/policy_error_map.h"
15 #include "components/policy/core/common/policy_map.h"
16 #include "components/policy/policy_constants.h"
17 #include "components/prefs/pref_value_map.h"
18 #include "components/search_engines/default_search_manager.h"
19 #include "components/search_engines/search_engines_pref_names.h"
20 #include "components/search_engines/search_terms_data.h"
21 #include "components/search_engines/template_url.h"
22 #include "components/strings/grit/components_strings.h"
27 // Extracts a list from a policy value and adds it to a pref dictionary.
28 void SetListInPref(const PolicyMap& policies,
29 const char* policy_name,
31 base::Value::Dict& dict) {
32 const base::Value* policy_value =
33 policies.GetValue(policy_name, base::Value::Type::LIST);
34 dict.Set(key, policy_value ? policy_value->Clone()
35 : base::Value(base::Value::Type::LIST));
38 // Extracts a string from a policy value and adds it to a pref dictionary.
39 void SetStringInPref(const PolicyMap& policies,
40 const char* policy_name,
42 base::Value::Dict& dict) {
43 const base::Value* policy_value =
44 policies.GetValue(policy_name, base::Value::Type::STRING);
45 dict.Set(key, policy_value ? policy_value->GetString() : std::string());
48 void SetBooleanInPref(const PolicyMap& policies,
49 const char* policy_name,
51 base::Value::Dict& dict) {
52 const base::Value* policy_value =
53 policies.GetValue(policy_name, base::Value::Type::BOOLEAN);
54 dict.SetByDottedPath(key, policy_value && policy_value->GetBool());
59 // List of policy types to preference names, for policies affecting the default
60 // search provider. Please update ApplyPolicySettings() when add or remove
62 const PolicyToPreferenceMapEntry kDefaultSearchPolicyDataMap[] = {
63 {key::kDefaultSearchProviderEnabled, prefs::kDefaultSearchProviderEnabled,
64 base::Value::Type::BOOLEAN},
65 {key::kDefaultSearchProviderName, DefaultSearchManager::kShortName,
66 base::Value::Type::STRING},
67 {key::kDefaultSearchProviderKeyword, DefaultSearchManager::kKeyword,
68 base::Value::Type::STRING},
69 {key::kDefaultSearchProviderSearchURL, DefaultSearchManager::kURL,
70 base::Value::Type::STRING},
71 {key::kDefaultSearchProviderSuggestURL,
72 DefaultSearchManager::kSuggestionsURL, base::Value::Type::STRING},
73 {key::kDefaultSearchProviderIconURL, DefaultSearchManager::kFaviconURL,
74 base::Value::Type::STRING},
75 {key::kDefaultSearchProviderEncodings,
76 DefaultSearchManager::kInputEncodings, base::Value::Type::LIST},
77 {key::kDefaultSearchProviderAlternateURLs,
78 DefaultSearchManager::kAlternateURLs, base::Value::Type::LIST},
79 {key::kDefaultSearchProviderImageURL, DefaultSearchManager::kImageURL,
80 base::Value::Type::STRING},
81 {key::kDefaultSearchProviderNewTabURL, DefaultSearchManager::kNewTabURL,
82 base::Value::Type::STRING},
83 {key::kDefaultSearchProviderSearchURLPostParams,
84 DefaultSearchManager::kSearchURLPostParams, base::Value::Type::STRING},
85 {key::kDefaultSearchProviderSuggestURLPostParams,
86 DefaultSearchManager::kSuggestionsURLPostParams,
87 base::Value::Type::STRING},
88 {key::kDefaultSearchProviderImageURLPostParams,
89 DefaultSearchManager::kImageURLPostParams, base::Value::Type::STRING},
90 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
91 {key::kDefaultSearchProviderContextMenuAccessAllowed,
92 prefs::kDefaultSearchProviderContextMenuAccessAllowed,
93 base::Value::Type::BOOLEAN},
97 // DefaultSearchPolicyHandler implementation -----------------------------------
99 DefaultSearchPolicyHandler::DefaultSearchPolicyHandler() {}
101 DefaultSearchPolicyHandler::~DefaultSearchPolicyHandler() {}
103 bool DefaultSearchPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
104 PolicyErrorMap* errors) {
105 if (!CheckIndividualPolicies(policies, errors))
108 if (!DefaultSearchProviderPolicyIsSet(policies) ||
109 DefaultSearchProviderIsDisabled(policies)) {
110 // Add an error for all specified default search policies except
111 // DefaultSearchProviderEnabled and
112 // DefaultSearchProviderContextMenuAccessAllowed.
114 for (const auto& policy_map_entry : kDefaultSearchPolicyDataMap) {
115 const char* policy_name = policy_map_entry.policy_name;
116 if (policy_name != key::kDefaultSearchProviderEnabled &&
117 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
118 policy_name != key::kDefaultSearchProviderContextMenuAccessAllowed &&
120 HasDefaultSearchPolicy(policies, policy_name)) {
121 errors->AddError(policy_name, IDS_POLICY_DEFAULT_SEARCH_DISABLED);
127 const base::Value* url;
129 if (DefaultSearchURLIsValid(policies, &url, &dummy) ||
130 !AnyDefaultSearchPoliciesSpecified(policies))
132 errors->AddError(key::kDefaultSearchProviderSearchURL, url ?
133 IDS_POLICY_INVALID_SEARCH_URL_ERROR : IDS_POLICY_NOT_SPECIFIED_ERROR);
137 void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
138 PrefValueMap* prefs) {
139 // If the main switch is not set don't set anything.
140 if (!DefaultSearchProviderPolicyIsSet(policies))
143 if (DefaultSearchProviderIsDisabled(policies)) {
144 base::Value::Dict dict;
145 dict.Set(DefaultSearchManager::kDisabledByPolicy, true);
146 DefaultSearchManager::AddPrefValueToMap(std::move(dict), prefs);
150 // The search URL is required. The other entries are optional. Just make
151 // sure that they are all specified via policy, so that the regular prefs
153 const base::Value* dummy;
155 if (!DefaultSearchURLIsValid(policies, &dummy, &url))
158 base::Value::Dict dict;
160 // Set pref values for policies affecting the default
161 // search provider, which are listed in kDefaultSearchPolicyDataMap.
162 // Set or remove pref accordingly when kDefaultSearchPolicyDataMap has a
163 // change, then revise the number in the check below to be correct.
164 SetBooleanInPref(policies, key::kDefaultSearchProviderEnabled,
165 prefs::kDefaultSearchProviderEnabled, dict);
166 SetStringInPref(policies, key::kDefaultSearchProviderName,
167 DefaultSearchManager::kShortName, dict);
168 SetStringInPref(policies, key::kDefaultSearchProviderKeyword,
169 DefaultSearchManager::kKeyword, dict);
170 SetStringInPref(policies, key::kDefaultSearchProviderSearchURL,
171 DefaultSearchManager::kURL, dict);
172 SetStringInPref(policies, key::kDefaultSearchProviderSuggestURL,
173 DefaultSearchManager::kSuggestionsURL, dict);
174 SetStringInPref(policies, key::kDefaultSearchProviderIconURL,
175 DefaultSearchManager::kFaviconURL, dict);
176 SetListInPref(policies, key::kDefaultSearchProviderEncodings,
177 DefaultSearchManager::kInputEncodings, dict);
178 SetListInPref(policies, key::kDefaultSearchProviderAlternateURLs,
179 DefaultSearchManager::kAlternateURLs, dict);
180 SetStringInPref(policies, key::kDefaultSearchProviderImageURL,
181 DefaultSearchManager::kImageURL, dict);
182 SetStringInPref(policies, key::kDefaultSearchProviderNewTabURL,
183 DefaultSearchManager::kNewTabURL, dict);
184 SetStringInPref(policies, key::kDefaultSearchProviderSearchURLPostParams,
185 DefaultSearchManager::kSearchURLPostParams, dict);
186 SetStringInPref(policies, key::kDefaultSearchProviderSuggestURLPostParams,
187 DefaultSearchManager::kSuggestionsURLPostParams, dict);
188 SetStringInPref(policies, key::kDefaultSearchProviderImageURLPostParams,
189 DefaultSearchManager::kImageURLPostParams, dict);
190 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
191 SetBooleanInPref(policies,
192 key::kDefaultSearchProviderContextMenuAccessAllowed,
193 prefs::kDefaultSearchProviderContextMenuAccessAllowed, dict);
194 size_t policyCount = 14;
196 size_t policyCount = 13;
199 CHECK_EQ(policyCount, std::size(kDefaultSearchPolicyDataMap));
201 // Set the fields which are not specified by the policy to default values.
202 dict.Set(DefaultSearchManager::kID,
203 base::NumberToString(kInvalidTemplateURLID));
204 dict.Set(DefaultSearchManager::kPrepopulateID, 0);
205 dict.Set(DefaultSearchManager::kStarterPackId, 0);
206 dict.Set(DefaultSearchManager::kSyncGUID, std::string());
207 dict.Set(DefaultSearchManager::kOriginatingURL, std::string());
208 dict.Set(DefaultSearchManager::kSafeForAutoReplace, true);
209 dict.Set(DefaultSearchManager::kDateCreated,
210 static_cast<double>(base::Time::Now().ToInternalValue()));
211 dict.Set(DefaultSearchManager::kLastModified,
212 static_cast<double>(base::Time::Now().ToInternalValue()));
213 dict.Set(DefaultSearchManager::kUsageCount, 0);
214 dict.Set(DefaultSearchManager::kCreatedByPolicy, true);
216 // For the name and keyword, default to the host if not specified. If
217 // there is no host (as is the case with file URLs of the form:
218 // "file:///c:/..."), use "_" to guarantee that the keyword is non-empty.
219 std::string* keyword = dict.FindString(DefaultSearchManager::kKeyword);
220 std::string* name = dict.FindString(DefaultSearchManager::kShortName);
221 std::string* url_str = dict.FindString(DefaultSearchManager::kURL);
225 std::string host(GURL(url).host());
228 if (!name || name->empty())
229 dict.Set(DefaultSearchManager::kShortName, host);
230 if (!keyword || keyword->empty())
231 dict.Set(DefaultSearchManager::kKeyword, host);
233 DefaultSearchManager::AddPrefValueToMap(std::move(dict), prefs);
236 bool DefaultSearchPolicyHandler::CheckIndividualPolicies(
237 const PolicyMap& policies,
238 PolicyErrorMap* errors) {
240 for (const auto& policy_map_entry : kDefaultSearchPolicyDataMap) {
241 // It's safe to use `GetValueUnsafe()` as multiple policy types are handled.
242 // It's important to check policy type for all policies and not just exit on
243 // the first error, so we report all policy errors.
244 const base::Value* value =
245 policies.GetValueUnsafe(policy_map_entry.policy_name);
246 if (value && value->type() != policy_map_entry.value_type) {
247 errors->AddError(policy_map_entry.policy_name, IDS_POLICY_TYPE_ERROR,
248 base::Value::GetTypeName(policy_map_entry.value_type));
255 bool DefaultSearchPolicyHandler::HasDefaultSearchPolicy(
256 const PolicyMap& policies,
257 const char* policy_name) {
258 return policies.Get(policy_name) != nullptr;
261 bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified(
262 const PolicyMap& policies) {
263 for (const auto& policy_map_entry : kDefaultSearchPolicyDataMap) {
264 if (policies.Get(policy_map_entry.policy_name))
270 bool DefaultSearchPolicyHandler::DefaultSearchProviderIsDisabled(
271 const PolicyMap& policies) {
272 const base::Value* provider_enabled = policies.GetValue(
273 key::kDefaultSearchProviderEnabled, base::Value::Type::BOOLEAN);
274 return provider_enabled && !provider_enabled->GetBool();
277 bool DefaultSearchPolicyHandler::DefaultSearchProviderPolicyIsSet(
278 const PolicyMap& policies) {
279 return HasDefaultSearchPolicy(policies, key::kDefaultSearchProviderEnabled);
282 bool DefaultSearchPolicyHandler::DefaultSearchURLIsValid(
283 const PolicyMap& policies,
284 const base::Value** url_value,
285 std::string* url_string) {
286 *url_value = policies.GetValue(key::kDefaultSearchProviderSearchURL,
287 base::Value::Type::STRING);
291 *url_string = (*url_value)->GetString();
292 if (url_string->empty())
294 TemplateURLData data;
295 data.SetURL(*url_string);
296 SearchTermsData search_terms_data;
297 return TemplateURL(data).SupportsReplacement(search_terms_data);
300 void DefaultSearchPolicyHandler::EnsureStringPrefExists(
302 const std::string& path) {
304 if (!prefs->GetString(path, &value))
305 prefs->SetString(path, value);
308 void DefaultSearchPolicyHandler::EnsureListPrefExists(
310 const std::string& path) {
312 if (!prefs->GetValue(path, &value) || !value->is_list())
313 prefs->SetValue(path, base::Value(base::Value::Type::LIST));
316 } // namespace policy