1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/search_engines/default_search_policy_handler.h"
7 #include "base/prefs/pref_value_map.h"
8 #include "base/stl_util.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/strings/string_util.h"
11 #include "chrome/browser/search_engines/default_search_manager.h"
12 #include "chrome/browser/search_engines/template_url.h"
13 #include "chrome/common/pref_names.h"
14 #include "components/policy/core/browser/policy_error_map.h"
15 #include "components/policy/core/common/policy_map.h"
16 #include "components/search_engines/search_terms_data.h"
17 #include "grit/components_strings.h"
18 #include "policy/policy_constants.h"
23 // Extracts a list from a policy value and adds it to a pref dictionary.
24 void SetListInPref(const PolicyMap& policies,
25 const char* policy_name,
27 base::DictionaryValue* dict) {
29 const base::Value* policy_value = policies.GetValue(policy_name);
30 const base::ListValue* policy_list = NULL;
32 bool is_list = policy_value->GetAsList(&policy_list);
35 dict->Set(key, policy_list ? policy_list->DeepCopy() : new base::ListValue());
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::DictionaryValue* dict) {
44 const base::Value* policy_value = policies.GetValue(policy_name);
47 bool is_string = policy_value->GetAsString(&str);
50 dict->SetString(key, str);
55 // List of policy types to preference names, for policies affecting the default
57 const PolicyToPreferenceMapEntry kDefaultSearchPolicyMap[] = {
58 { key::kDefaultSearchProviderEnabled,
59 prefs::kDefaultSearchProviderEnabled,
60 base::Value::TYPE_BOOLEAN },
61 { key::kDefaultSearchProviderName,
62 prefs::kDefaultSearchProviderName,
63 base::Value::TYPE_STRING },
64 { key::kDefaultSearchProviderKeyword,
65 prefs::kDefaultSearchProviderKeyword,
66 base::Value::TYPE_STRING },
67 { key::kDefaultSearchProviderSearchURL,
68 prefs::kDefaultSearchProviderSearchURL,
69 base::Value::TYPE_STRING },
70 { key::kDefaultSearchProviderSuggestURL,
71 prefs::kDefaultSearchProviderSuggestURL,
72 base::Value::TYPE_STRING },
73 { key::kDefaultSearchProviderInstantURL,
74 prefs::kDefaultSearchProviderInstantURL,
75 base::Value::TYPE_STRING },
76 { key::kDefaultSearchProviderIconURL,
77 prefs::kDefaultSearchProviderIconURL,
78 base::Value::TYPE_STRING },
79 { key::kDefaultSearchProviderEncodings,
80 prefs::kDefaultSearchProviderEncodings,
81 base::Value::TYPE_LIST },
82 { key::kDefaultSearchProviderAlternateURLs,
83 prefs::kDefaultSearchProviderAlternateURLs,
84 base::Value::TYPE_LIST },
85 { key::kDefaultSearchProviderSearchTermsReplacementKey,
86 prefs::kDefaultSearchProviderSearchTermsReplacementKey,
87 base::Value::TYPE_STRING },
88 { key::kDefaultSearchProviderImageURL,
89 prefs::kDefaultSearchProviderImageURL,
90 base::Value::TYPE_STRING },
91 { key::kDefaultSearchProviderNewTabURL,
92 prefs::kDefaultSearchProviderNewTabURL,
93 base::Value::TYPE_STRING },
94 { key::kDefaultSearchProviderSearchURLPostParams,
95 prefs::kDefaultSearchProviderSearchURLPostParams,
96 base::Value::TYPE_STRING },
97 { key::kDefaultSearchProviderSuggestURLPostParams,
98 prefs::kDefaultSearchProviderSuggestURLPostParams,
99 base::Value::TYPE_STRING },
100 { key::kDefaultSearchProviderInstantURLPostParams,
101 prefs::kDefaultSearchProviderInstantURLPostParams,
102 base::Value::TYPE_STRING },
103 { key::kDefaultSearchProviderImageURLPostParams,
104 prefs::kDefaultSearchProviderImageURLPostParams,
105 base::Value::TYPE_STRING },
108 // List of policy types to preference names, for policies affecting the default
110 const PolicyToPreferenceMapEntry kDefaultSearchPolicyDataMap[] = {
111 {key::kDefaultSearchProviderName, DefaultSearchManager::kShortName,
112 base::Value::TYPE_STRING},
113 {key::kDefaultSearchProviderKeyword, DefaultSearchManager::kKeyword,
114 base::Value::TYPE_STRING},
115 {key::kDefaultSearchProviderSearchURL, DefaultSearchManager::kURL,
116 base::Value::TYPE_STRING},
117 {key::kDefaultSearchProviderSuggestURL,
118 DefaultSearchManager::kSuggestionsURL, base::Value::TYPE_STRING},
119 {key::kDefaultSearchProviderInstantURL, DefaultSearchManager::kInstantURL,
120 base::Value::TYPE_STRING},
121 {key::kDefaultSearchProviderIconURL, DefaultSearchManager::kFaviconURL,
122 base::Value::TYPE_STRING},
123 {key::kDefaultSearchProviderEncodings,
124 DefaultSearchManager::kInputEncodings, base::Value::TYPE_LIST},
125 {key::kDefaultSearchProviderAlternateURLs,
126 DefaultSearchManager::kAlternateURLs, base::Value::TYPE_LIST},
127 {key::kDefaultSearchProviderSearchTermsReplacementKey,
128 DefaultSearchManager::kSearchTermsReplacementKey,
129 base::Value::TYPE_STRING},
130 {key::kDefaultSearchProviderImageURL, DefaultSearchManager::kImageURL,
131 base::Value::TYPE_STRING},
132 {key::kDefaultSearchProviderNewTabURL, DefaultSearchManager::kNewTabURL,
133 base::Value::TYPE_STRING},
134 {key::kDefaultSearchProviderSearchURLPostParams,
135 DefaultSearchManager::kSearchURLPostParams, base::Value::TYPE_STRING},
136 {key::kDefaultSearchProviderSuggestURLPostParams,
137 DefaultSearchManager::kSuggestionsURLPostParams, base::Value::TYPE_STRING},
138 {key::kDefaultSearchProviderInstantURLPostParams,
139 DefaultSearchManager::kInstantURLPostParams, base::Value::TYPE_STRING},
140 {key::kDefaultSearchProviderImageURLPostParams,
141 DefaultSearchManager::kImageURLPostParams, base::Value::TYPE_STRING},
144 // DefaultSearchEncodingsPolicyHandler implementation --------------------------
146 DefaultSearchEncodingsPolicyHandler::DefaultSearchEncodingsPolicyHandler()
147 : TypeCheckingPolicyHandler(key::kDefaultSearchProviderEncodings,
148 base::Value::TYPE_LIST) {}
150 DefaultSearchEncodingsPolicyHandler::~DefaultSearchEncodingsPolicyHandler() {
153 void DefaultSearchEncodingsPolicyHandler::ApplyPolicySettings(
154 const PolicyMap& policies, PrefValueMap* prefs) {
155 // The DefaultSearchProviderEncodings policy has type list, but the related
156 // preference has type string. Convert one into the other here, using
157 // ';' as a separator.
158 const base::Value* value = policies.GetValue(policy_name());
159 const base::ListValue* list;
160 if (!value || !value->GetAsList(&list))
163 base::ListValue::const_iterator iter(list->begin());
164 base::ListValue::const_iterator end(list->end());
165 std::vector<std::string> string_parts;
166 for (; iter != end; ++iter) {
168 if ((*iter)->GetAsString(&s)) {
169 string_parts.push_back(s);
172 std::string encodings = JoinString(string_parts, ';');
173 prefs->SetValue(prefs::kDefaultSearchProviderEncodings,
174 base::Value::CreateStringValue(encodings));
178 // DefaultSearchPolicyHandler implementation -----------------------------------
180 DefaultSearchPolicyHandler::DefaultSearchPolicyHandler() {
181 for (size_t i = 0; i < arraysize(kDefaultSearchPolicyMap); ++i) {
182 const char* policy_name = kDefaultSearchPolicyMap[i].policy_name;
183 if (policy_name == key::kDefaultSearchProviderEncodings) {
184 handlers_.push_back(new DefaultSearchEncodingsPolicyHandler());
186 handlers_.push_back(new SimplePolicyHandler(
188 kDefaultSearchPolicyMap[i].preference_path,
189 kDefaultSearchPolicyMap[i].value_type));
194 DefaultSearchPolicyHandler::~DefaultSearchPolicyHandler() {
195 STLDeleteElements(&handlers_);
198 bool DefaultSearchPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
199 PolicyErrorMap* errors) {
200 if (!CheckIndividualPolicies(policies, errors))
203 if (DefaultSearchProviderIsDisabled(policies)) {
204 // Add an error for all specified default search policies except
205 // DefaultSearchProviderEnabled.
207 for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
209 handler != handlers_.end(); ++handler) {
210 const char* policy_name = (*handler)->policy_name();
211 if (policy_name != key::kDefaultSearchProviderEnabled &&
212 HasDefaultSearchPolicy(policies, policy_name)) {
213 errors->AddError(policy_name, IDS_POLICY_DEFAULT_SEARCH_DISABLED);
219 const base::Value* url;
221 if (DefaultSearchURLIsValid(policies, &url, &dummy) ||
222 !AnyDefaultSearchPoliciesSpecified(policies))
224 errors->AddError(key::kDefaultSearchProviderSearchURL, url ?
225 IDS_POLICY_INVALID_SEARCH_URL_ERROR : IDS_POLICY_NOT_SPECIFIED_ERROR);
229 void DefaultSearchPolicyHandler::HandleDictionaryPref(const PolicyMap& policies,
230 PrefValueMap* prefs) {
231 if (DefaultSearchProviderIsDisabled(policies)) {
232 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
233 dict->SetBoolean(DefaultSearchManager::kDisabledByPolicy, true);
234 DefaultSearchManager::AddPrefValueToMap(dict.release(), prefs);
238 // The search URL is required. The other entries are optional. Just make
239 // sure that they are all specified via policy, so that the regular prefs
241 const base::Value* dummy;
243 if (!DefaultSearchURLIsValid(policies, &dummy, &url))
246 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
247 for (size_t i = 0; i < arraysize(kDefaultSearchPolicyDataMap); ++i) {
248 const char* policy_name = kDefaultSearchPolicyDataMap[i].policy_name;
249 switch (kDefaultSearchPolicyDataMap[i].value_type) {
250 case base::Value::TYPE_STRING:
251 SetStringInPref(policies,
253 kDefaultSearchPolicyDataMap[i].preference_path,
256 case base::Value::TYPE_LIST:
257 SetListInPref(policies,
259 kDefaultSearchPolicyDataMap[i].preference_path,
268 // Set the fields which are not specified by the policy to default values.
269 dict->SetString(DefaultSearchManager::kID,
270 base::Int64ToString(kInvalidTemplateURLID));
271 dict->SetInteger(DefaultSearchManager::kPrepopulateID, 0);
272 dict->SetString(DefaultSearchManager::kSyncGUID, std::string());
273 dict->SetString(DefaultSearchManager::kOriginatingURL, std::string());
274 dict->SetBoolean(DefaultSearchManager::kSafeForAutoReplace, true);
275 dict->SetDouble(DefaultSearchManager::kDateCreated,
276 base::Time::Now().ToInternalValue());
277 dict->SetDouble(DefaultSearchManager::kLastModified,
278 base::Time::Now().ToInternalValue());
279 dict->SetInteger(DefaultSearchManager::kUsageCount, 0);
280 dict->SetBoolean(DefaultSearchManager::kCreatedByPolicy, true);
282 // For the name and keyword, default to the host if not specified. If
283 // there is no host (as is the case with file URLs of the form:
284 // "file:///c:/..."), use "_" to guarantee that the keyword is non-empty.
285 std::string name, keyword;
286 dict->GetString(DefaultSearchManager::kKeyword, &keyword);
287 dict->GetString(DefaultSearchManager::kShortName, &name);
288 dict->GetString(DefaultSearchManager::kURL, &url);
290 std::string host(GURL(url).host());
294 dict->SetString(DefaultSearchManager::kShortName, host);
296 dict->SetString(DefaultSearchManager::kKeyword, host);
298 DefaultSearchManager::AddPrefValueToMap(dict.release(), prefs);
301 void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
302 PrefValueMap* prefs) {
303 HandleDictionaryPref(policies, prefs);
305 if (DefaultSearchProviderIsDisabled(policies)) {
306 prefs->SetBoolean(prefs::kDefaultSearchProviderEnabled, false);
308 // If default search is disabled, the other fields are ignored.
309 prefs->SetString(prefs::kDefaultSearchProviderName, std::string());
310 prefs->SetString(prefs::kDefaultSearchProviderSearchURL, std::string());
311 prefs->SetString(prefs::kDefaultSearchProviderSuggestURL, std::string());
312 prefs->SetString(prefs::kDefaultSearchProviderIconURL, std::string());
313 prefs->SetString(prefs::kDefaultSearchProviderEncodings, std::string());
314 prefs->SetString(prefs::kDefaultSearchProviderKeyword, std::string());
315 prefs->SetString(prefs::kDefaultSearchProviderInstantURL, std::string());
316 prefs->SetString(prefs::kDefaultSearchProviderNewTabURL, std::string());
317 prefs->SetValue(prefs::kDefaultSearchProviderAlternateURLs,
318 new base::ListValue());
320 prefs::kDefaultSearchProviderSearchTermsReplacementKey, std::string());
321 prefs->SetString(prefs::kDefaultSearchProviderImageURL, std::string());
323 prefs::kDefaultSearchProviderSearchURLPostParams, std::string());
325 prefs::kDefaultSearchProviderSuggestURLPostParams, std::string());
327 prefs::kDefaultSearchProviderInstantURLPostParams, std::string());
329 prefs::kDefaultSearchProviderImageURLPostParams, std::string());
331 // The search URL is required. The other entries are optional. Just make
332 // sure that they are all specified via policy, so that the regular prefs
334 const base::Value* dummy;
336 if (DefaultSearchURLIsValid(policies, &dummy, &url)) {
338 for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
340 handler != handlers_.end(); ++handler) {
341 (*handler)->ApplyPolicySettings(policies, prefs);
344 EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderSuggestURL);
345 EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderIconURL);
346 EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderEncodings);
347 EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderKeyword);
348 EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderInstantURL);
349 EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderNewTabURL);
350 EnsureListPrefExists(prefs, prefs::kDefaultSearchProviderAlternateURLs);
351 EnsureStringPrefExists(
353 prefs::kDefaultSearchProviderSearchTermsReplacementKey);
354 EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderImageURL);
355 EnsureStringPrefExists(
357 prefs::kDefaultSearchProviderSearchURLPostParams);
358 EnsureStringPrefExists(
360 prefs::kDefaultSearchProviderSuggestURLPostParams);
361 EnsureStringPrefExists(
363 prefs::kDefaultSearchProviderInstantURLPostParams);
364 EnsureStringPrefExists(
366 prefs::kDefaultSearchProviderImageURLPostParams);
368 // For the name and keyword, default to the host if not specified. If
369 // there is no host (file: URLs? Not sure), use "_" to guarantee that the
370 // keyword is non-empty.
371 std::string name, keyword;
372 std::string host(GURL(url).host());
375 if (!prefs->GetString(prefs::kDefaultSearchProviderName, &name) ||
377 prefs->SetString(prefs::kDefaultSearchProviderName, host);
379 if (!prefs->GetString(prefs::kDefaultSearchProviderKeyword, &keyword) ||
381 prefs->SetString(prefs::kDefaultSearchProviderKeyword, host);
384 // And clear the IDs since these are not specified via policy.
385 prefs->SetString(prefs::kDefaultSearchProviderID, std::string());
386 prefs->SetString(prefs::kDefaultSearchProviderPrepopulateID,
392 bool DefaultSearchPolicyHandler::CheckIndividualPolicies(
393 const PolicyMap& policies,
394 PolicyErrorMap* errors) {
395 for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
397 handler != handlers_.end(); ++handler) {
398 if (!(*handler)->CheckPolicySettings(policies, errors))
404 bool DefaultSearchPolicyHandler::HasDefaultSearchPolicy(
405 const PolicyMap& policies,
406 const char* policy_name) {
407 return policies.Get(policy_name) != NULL;
410 bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified(
411 const PolicyMap& policies) {
412 for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
414 handler != handlers_.end(); ++handler) {
415 if (policies.Get((*handler)->policy_name()))
421 bool DefaultSearchPolicyHandler::DefaultSearchProviderIsDisabled(
422 const PolicyMap& policies) {
423 const base::Value* provider_enabled =
424 policies.GetValue(key::kDefaultSearchProviderEnabled);
426 return provider_enabled && provider_enabled->GetAsBoolean(&enabled) &&
430 bool DefaultSearchPolicyHandler::DefaultSearchURLIsValid(
431 const PolicyMap& policies,
432 const base::Value** url_value,
433 std::string* url_string) {
434 *url_value = policies.GetValue(key::kDefaultSearchProviderSearchURL);
435 if (!*url_value || !(*url_value)->GetAsString(url_string) ||
438 TemplateURLData data;
439 data.SetURL(*url_string);
440 SearchTermsData search_terms_data;
441 return TemplateURL(data).SupportsReplacement(search_terms_data);
444 void DefaultSearchPolicyHandler::EnsureStringPrefExists(
446 const std::string& path) {
448 if (!prefs->GetString(path, &value))
449 prefs->SetString(path, value);
452 void DefaultSearchPolicyHandler::EnsureListPrefExists(
454 const std::string& path) {
456 base::ListValue* list_value;
457 if (!prefs->GetValue(path, &value) || !value->GetAsList(&list_value))
458 prefs->SetValue(path, new base::ListValue());
461 } // namespace policy