1 // Copyright 2014 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 "components/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 "components/policy/core/browser/policy_error_map.h"
12 #include "components/policy/core/common/policy_map.h"
13 #include "components/search_engines/default_search_manager.h"
14 #include "components/search_engines/search_engines_pref_names.h"
15 #include "components/search_engines/search_terms_data.h"
16 #include "components/search_engines/template_url.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
->SetString(prefs::kDefaultSearchProviderEncodings
, encodings
);
177 // DefaultSearchPolicyHandler implementation -----------------------------------
179 DefaultSearchPolicyHandler::DefaultSearchPolicyHandler() {
180 for (size_t i
= 0; i
< arraysize(kDefaultSearchPolicyMap
); ++i
) {
181 const char* policy_name
= kDefaultSearchPolicyMap
[i
].policy_name
;
182 if (policy_name
== key::kDefaultSearchProviderEncodings
) {
183 handlers_
.push_back(new DefaultSearchEncodingsPolicyHandler());
185 handlers_
.push_back(new SimplePolicyHandler(
187 kDefaultSearchPolicyMap
[i
].preference_path
,
188 kDefaultSearchPolicyMap
[i
].value_type
));
193 DefaultSearchPolicyHandler::~DefaultSearchPolicyHandler() {
194 STLDeleteElements(&handlers_
);
197 bool DefaultSearchPolicyHandler::CheckPolicySettings(const PolicyMap
& policies
,
198 PolicyErrorMap
* errors
) {
199 if (!CheckIndividualPolicies(policies
, errors
))
202 if (DefaultSearchProviderIsDisabled(policies
)) {
203 // Add an error for all specified default search policies except
204 // DefaultSearchProviderEnabled.
206 for (std::vector
<TypeCheckingPolicyHandler
*>::const_iterator handler
=
208 handler
!= handlers_
.end(); ++handler
) {
209 const char* policy_name
= (*handler
)->policy_name();
210 if (policy_name
!= key::kDefaultSearchProviderEnabled
&&
211 HasDefaultSearchPolicy(policies
, policy_name
)) {
212 errors
->AddError(policy_name
, IDS_POLICY_DEFAULT_SEARCH_DISABLED
);
218 const base::Value
* url
;
220 if (DefaultSearchURLIsValid(policies
, &url
, &dummy
) ||
221 !AnyDefaultSearchPoliciesSpecified(policies
))
223 errors
->AddError(key::kDefaultSearchProviderSearchURL
, url
?
224 IDS_POLICY_INVALID_SEARCH_URL_ERROR
: IDS_POLICY_NOT_SPECIFIED_ERROR
);
228 void DefaultSearchPolicyHandler::HandleDictionaryPref(const PolicyMap
& policies
,
229 PrefValueMap
* prefs
) {
230 if (DefaultSearchProviderIsDisabled(policies
)) {
231 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue
);
232 dict
->SetBoolean(DefaultSearchManager::kDisabledByPolicy
, true);
233 DefaultSearchManager::AddPrefValueToMap(dict
.release(), prefs
);
237 // The search URL is required. The other entries are optional. Just make
238 // sure that they are all specified via policy, so that the regular prefs
240 const base::Value
* dummy
;
242 if (!DefaultSearchURLIsValid(policies
, &dummy
, &url
))
245 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue
);
246 for (size_t i
= 0; i
< arraysize(kDefaultSearchPolicyDataMap
); ++i
) {
247 const char* policy_name
= kDefaultSearchPolicyDataMap
[i
].policy_name
;
248 switch (kDefaultSearchPolicyDataMap
[i
].value_type
) {
249 case base::Value::TYPE_STRING
:
250 SetStringInPref(policies
,
252 kDefaultSearchPolicyDataMap
[i
].preference_path
,
255 case base::Value::TYPE_LIST
:
256 SetListInPref(policies
,
258 kDefaultSearchPolicyDataMap
[i
].preference_path
,
267 // Set the fields which are not specified by the policy to default values.
268 dict
->SetString(DefaultSearchManager::kID
,
269 base::Int64ToString(kInvalidTemplateURLID
));
270 dict
->SetInteger(DefaultSearchManager::kPrepopulateID
, 0);
271 dict
->SetString(DefaultSearchManager::kSyncGUID
, std::string());
272 dict
->SetString(DefaultSearchManager::kOriginatingURL
, std::string());
273 dict
->SetBoolean(DefaultSearchManager::kSafeForAutoReplace
, true);
274 dict
->SetDouble(DefaultSearchManager::kDateCreated
,
275 base::Time::Now().ToInternalValue());
276 dict
->SetDouble(DefaultSearchManager::kLastModified
,
277 base::Time::Now().ToInternalValue());
278 dict
->SetInteger(DefaultSearchManager::kUsageCount
, 0);
279 dict
->SetBoolean(DefaultSearchManager::kCreatedByPolicy
, true);
281 // For the name and keyword, default to the host if not specified. If
282 // there is no host (as is the case with file URLs of the form:
283 // "file:///c:/..."), use "_" to guarantee that the keyword is non-empty.
284 std::string name
, keyword
;
285 dict
->GetString(DefaultSearchManager::kKeyword
, &keyword
);
286 dict
->GetString(DefaultSearchManager::kShortName
, &name
);
287 dict
->GetString(DefaultSearchManager::kURL
, &url
);
289 std::string
host(GURL(url
).host());
293 dict
->SetString(DefaultSearchManager::kShortName
, host
);
295 dict
->SetString(DefaultSearchManager::kKeyword
, host
);
297 DefaultSearchManager::AddPrefValueToMap(dict
.release(), prefs
);
300 void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap
& policies
,
301 PrefValueMap
* prefs
) {
302 HandleDictionaryPref(policies
, prefs
);
304 if (DefaultSearchProviderIsDisabled(policies
)) {
305 prefs
->SetBoolean(prefs::kDefaultSearchProviderEnabled
, false);
307 // If default search is disabled, the other fields are ignored.
308 prefs
->SetString(prefs::kDefaultSearchProviderName
, std::string());
309 prefs
->SetString(prefs::kDefaultSearchProviderSearchURL
, std::string());
310 prefs
->SetString(prefs::kDefaultSearchProviderSuggestURL
, std::string());
311 prefs
->SetString(prefs::kDefaultSearchProviderIconURL
, std::string());
312 prefs
->SetString(prefs::kDefaultSearchProviderEncodings
, std::string());
313 prefs
->SetString(prefs::kDefaultSearchProviderKeyword
, std::string());
314 prefs
->SetString(prefs::kDefaultSearchProviderInstantURL
, std::string());
315 prefs
->SetString(prefs::kDefaultSearchProviderNewTabURL
, std::string());
316 prefs
->SetValue(prefs::kDefaultSearchProviderAlternateURLs
,
317 new base::ListValue());
319 prefs::kDefaultSearchProviderSearchTermsReplacementKey
, std::string());
320 prefs
->SetString(prefs::kDefaultSearchProviderImageURL
, std::string());
322 prefs::kDefaultSearchProviderSearchURLPostParams
, std::string());
324 prefs::kDefaultSearchProviderSuggestURLPostParams
, std::string());
326 prefs::kDefaultSearchProviderInstantURLPostParams
, std::string());
328 prefs::kDefaultSearchProviderImageURLPostParams
, std::string());
330 // The search URL is required. The other entries are optional. Just make
331 // sure that they are all specified via policy, so that the regular prefs
333 const base::Value
* dummy
;
335 if (DefaultSearchURLIsValid(policies
, &dummy
, &url
)) {
337 for (std::vector
<TypeCheckingPolicyHandler
*>::const_iterator handler
=
339 handler
!= handlers_
.end(); ++handler
) {
340 (*handler
)->ApplyPolicySettings(policies
, prefs
);
343 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderSuggestURL
);
344 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderIconURL
);
345 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderEncodings
);
346 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderKeyword
);
347 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderInstantURL
);
348 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderNewTabURL
);
349 EnsureListPrefExists(prefs
, prefs::kDefaultSearchProviderAlternateURLs
);
350 EnsureStringPrefExists(
352 prefs::kDefaultSearchProviderSearchTermsReplacementKey
);
353 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderImageURL
);
354 EnsureStringPrefExists(
356 prefs::kDefaultSearchProviderSearchURLPostParams
);
357 EnsureStringPrefExists(
359 prefs::kDefaultSearchProviderSuggestURLPostParams
);
360 EnsureStringPrefExists(
362 prefs::kDefaultSearchProviderInstantURLPostParams
);
363 EnsureStringPrefExists(
365 prefs::kDefaultSearchProviderImageURLPostParams
);
367 // For the name and keyword, default to the host if not specified. If
368 // there is no host (file: URLs? Not sure), use "_" to guarantee that the
369 // keyword is non-empty.
370 std::string name
, keyword
;
371 std::string
host(GURL(url
).host());
374 if (!prefs
->GetString(prefs::kDefaultSearchProviderName
, &name
) ||
376 prefs
->SetString(prefs::kDefaultSearchProviderName
, host
);
378 if (!prefs
->GetString(prefs::kDefaultSearchProviderKeyword
, &keyword
) ||
380 prefs
->SetString(prefs::kDefaultSearchProviderKeyword
, host
);
383 // And clear the IDs since these are not specified via policy.
384 prefs
->SetString(prefs::kDefaultSearchProviderID
, std::string());
385 prefs
->SetString(prefs::kDefaultSearchProviderPrepopulateID
,
391 bool DefaultSearchPolicyHandler::CheckIndividualPolicies(
392 const PolicyMap
& policies
,
393 PolicyErrorMap
* errors
) {
394 for (std::vector
<TypeCheckingPolicyHandler
*>::const_iterator handler
=
396 handler
!= handlers_
.end(); ++handler
) {
397 if (!(*handler
)->CheckPolicySettings(policies
, errors
))
403 bool DefaultSearchPolicyHandler::HasDefaultSearchPolicy(
404 const PolicyMap
& policies
,
405 const char* policy_name
) {
406 return policies
.Get(policy_name
) != NULL
;
409 bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified(
410 const PolicyMap
& policies
) {
411 for (std::vector
<TypeCheckingPolicyHandler
*>::const_iterator handler
=
413 handler
!= handlers_
.end(); ++handler
) {
414 if (policies
.Get((*handler
)->policy_name()))
420 bool DefaultSearchPolicyHandler::DefaultSearchProviderIsDisabled(
421 const PolicyMap
& policies
) {
422 const base::Value
* provider_enabled
=
423 policies
.GetValue(key::kDefaultSearchProviderEnabled
);
425 return provider_enabled
&& provider_enabled
->GetAsBoolean(&enabled
) &&
429 bool DefaultSearchPolicyHandler::DefaultSearchURLIsValid(
430 const PolicyMap
& policies
,
431 const base::Value
** url_value
,
432 std::string
* url_string
) {
433 *url_value
= policies
.GetValue(key::kDefaultSearchProviderSearchURL
);
434 if (!*url_value
|| !(*url_value
)->GetAsString(url_string
) ||
437 TemplateURLData data
;
438 data
.SetURL(*url_string
);
439 SearchTermsData search_terms_data
;
440 return TemplateURL(data
).SupportsReplacement(search_terms_data
);
443 void DefaultSearchPolicyHandler::EnsureStringPrefExists(
445 const std::string
& path
) {
447 if (!prefs
->GetString(path
, &value
))
448 prefs
->SetString(path
, value
);
451 void DefaultSearchPolicyHandler::EnsureListPrefExists(
453 const std::string
& path
) {
455 base::ListValue
* list_value
;
456 if (!prefs
->GetValue(path
, &value
) || !value
->GetAsList(&list_value
))
457 prefs
->SetValue(path
, new base::ListValue());
460 } // namespace policy