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/chrome_notification_types.h"
12 #include "chrome/browser/search_engines/default_search_manager.h"
13 #include "chrome/browser/search_engines/search_terms_data.h"
14 #include "chrome/browser/search_engines/template_url.h"
15 #include "chrome/common/pref_names.h"
16 #include "components/policy/core/browser/policy_error_map.h"
17 #include "components/policy/core/common/policy_map.h"
18 #include "content/public/browser/notification_service.h"
19 #include "grit/component_strings.h"
20 #include "policy/policy_constants.h"
25 // Extracts a list from a policy value and adds it to a pref dictionary.
26 void SetListInPref(const PolicyMap
& policies
,
27 const char* policy_name
,
29 base::DictionaryValue
* dict
) {
31 const base::Value
* policy_value
= policies
.GetValue(policy_name
);
32 const base::ListValue
* policy_list
= NULL
;
34 bool is_list
= policy_value
->GetAsList(&policy_list
);
37 dict
->Set(key
, policy_list
? policy_list
->DeepCopy() : new base::ListValue());
40 // Extracts a string from a policy value and adds it to a pref dictionary.
41 void SetStringInPref(const PolicyMap
& policies
,
42 const char* policy_name
,
44 base::DictionaryValue
* dict
) {
46 const base::Value
* policy_value
= policies
.GetValue(policy_name
);
49 bool is_string
= policy_value
->GetAsString(&str
);
52 dict
->SetString(key
, str
);
57 // List of policy types to preference names, for policies affecting the default
59 const PolicyToPreferenceMapEntry kDefaultSearchPolicyMap
[] = {
60 { key::kDefaultSearchProviderEnabled
,
61 prefs::kDefaultSearchProviderEnabled
,
62 base::Value::TYPE_BOOLEAN
},
63 { key::kDefaultSearchProviderName
,
64 prefs::kDefaultSearchProviderName
,
65 base::Value::TYPE_STRING
},
66 { key::kDefaultSearchProviderKeyword
,
67 prefs::kDefaultSearchProviderKeyword
,
68 base::Value::TYPE_STRING
},
69 { key::kDefaultSearchProviderSearchURL
,
70 prefs::kDefaultSearchProviderSearchURL
,
71 base::Value::TYPE_STRING
},
72 { key::kDefaultSearchProviderSuggestURL
,
73 prefs::kDefaultSearchProviderSuggestURL
,
74 base::Value::TYPE_STRING
},
75 { key::kDefaultSearchProviderInstantURL
,
76 prefs::kDefaultSearchProviderInstantURL
,
77 base::Value::TYPE_STRING
},
78 { key::kDefaultSearchProviderIconURL
,
79 prefs::kDefaultSearchProviderIconURL
,
80 base::Value::TYPE_STRING
},
81 { key::kDefaultSearchProviderEncodings
,
82 prefs::kDefaultSearchProviderEncodings
,
83 base::Value::TYPE_LIST
},
84 { key::kDefaultSearchProviderAlternateURLs
,
85 prefs::kDefaultSearchProviderAlternateURLs
,
86 base::Value::TYPE_LIST
},
87 { key::kDefaultSearchProviderSearchTermsReplacementKey
,
88 prefs::kDefaultSearchProviderSearchTermsReplacementKey
,
89 base::Value::TYPE_STRING
},
90 { key::kDefaultSearchProviderImageURL
,
91 prefs::kDefaultSearchProviderImageURL
,
92 base::Value::TYPE_STRING
},
93 { key::kDefaultSearchProviderNewTabURL
,
94 prefs::kDefaultSearchProviderNewTabURL
,
95 base::Value::TYPE_STRING
},
96 { key::kDefaultSearchProviderSearchURLPostParams
,
97 prefs::kDefaultSearchProviderSearchURLPostParams
,
98 base::Value::TYPE_STRING
},
99 { key::kDefaultSearchProviderSuggestURLPostParams
,
100 prefs::kDefaultSearchProviderSuggestURLPostParams
,
101 base::Value::TYPE_STRING
},
102 { key::kDefaultSearchProviderInstantURLPostParams
,
103 prefs::kDefaultSearchProviderInstantURLPostParams
,
104 base::Value::TYPE_STRING
},
105 { key::kDefaultSearchProviderImageURLPostParams
,
106 prefs::kDefaultSearchProviderImageURLPostParams
,
107 base::Value::TYPE_STRING
},
110 // List of policy types to preference names, for policies affecting the default
112 const PolicyToPreferenceMapEntry kDefaultSearchPolicyDataMap
[] = {
113 {key::kDefaultSearchProviderName
, DefaultSearchManager::kShortName
,
114 base::Value::TYPE_STRING
},
115 {key::kDefaultSearchProviderKeyword
, DefaultSearchManager::kKeyword
,
116 base::Value::TYPE_STRING
},
117 {key::kDefaultSearchProviderSearchURL
, DefaultSearchManager::kURL
,
118 base::Value::TYPE_STRING
},
119 {key::kDefaultSearchProviderSuggestURL
,
120 DefaultSearchManager::kSuggestionsURL
, base::Value::TYPE_STRING
},
121 {key::kDefaultSearchProviderInstantURL
, DefaultSearchManager::kInstantURL
,
122 base::Value::TYPE_STRING
},
123 {key::kDefaultSearchProviderIconURL
, DefaultSearchManager::kFaviconURL
,
124 base::Value::TYPE_STRING
},
125 {key::kDefaultSearchProviderEncodings
,
126 DefaultSearchManager::kInputEncodings
, base::Value::TYPE_LIST
},
127 {key::kDefaultSearchProviderAlternateURLs
,
128 DefaultSearchManager::kAlternateURLs
, base::Value::TYPE_LIST
},
129 {key::kDefaultSearchProviderSearchTermsReplacementKey
,
130 DefaultSearchManager::kSearchTermsReplacementKey
,
131 base::Value::TYPE_STRING
},
132 {key::kDefaultSearchProviderImageURL
, DefaultSearchManager::kImageURL
,
133 base::Value::TYPE_STRING
},
134 {key::kDefaultSearchProviderNewTabURL
, DefaultSearchManager::kNewTabURL
,
135 base::Value::TYPE_STRING
},
136 {key::kDefaultSearchProviderSearchURLPostParams
,
137 DefaultSearchManager::kSearchURLPostParams
, base::Value::TYPE_STRING
},
138 {key::kDefaultSearchProviderSuggestURLPostParams
,
139 DefaultSearchManager::kSuggestionsURLPostParams
, base::Value::TYPE_STRING
},
140 {key::kDefaultSearchProviderInstantURLPostParams
,
141 DefaultSearchManager::kInstantURLPostParams
, base::Value::TYPE_STRING
},
142 {key::kDefaultSearchProviderImageURLPostParams
,
143 DefaultSearchManager::kImageURLPostParams
, base::Value::TYPE_STRING
},
146 // DefaultSearchEncodingsPolicyHandler implementation --------------------------
148 DefaultSearchEncodingsPolicyHandler::DefaultSearchEncodingsPolicyHandler()
149 : TypeCheckingPolicyHandler(key::kDefaultSearchProviderEncodings
,
150 base::Value::TYPE_LIST
) {}
152 DefaultSearchEncodingsPolicyHandler::~DefaultSearchEncodingsPolicyHandler() {
155 void DefaultSearchEncodingsPolicyHandler::ApplyPolicySettings(
156 const PolicyMap
& policies
, PrefValueMap
* prefs
) {
157 // The DefaultSearchProviderEncodings policy has type list, but the related
158 // preference has type string. Convert one into the other here, using
159 // ';' as a separator.
160 const base::Value
* value
= policies
.GetValue(policy_name());
161 const base::ListValue
* list
;
162 if (!value
|| !value
->GetAsList(&list
))
165 base::ListValue::const_iterator
iter(list
->begin());
166 base::ListValue::const_iterator
end(list
->end());
167 std::vector
<std::string
> string_parts
;
168 for (; iter
!= end
; ++iter
) {
170 if ((*iter
)->GetAsString(&s
)) {
171 string_parts
.push_back(s
);
174 std::string encodings
= JoinString(string_parts
, ';');
175 prefs
->SetValue(prefs::kDefaultSearchProviderEncodings
,
176 base::Value::CreateStringValue(encodings
));
180 // DefaultSearchPolicyHandler implementation -----------------------------------
182 DefaultSearchPolicyHandler::DefaultSearchPolicyHandler() {
183 for (size_t i
= 0; i
< arraysize(kDefaultSearchPolicyMap
); ++i
) {
184 const char* policy_name
= kDefaultSearchPolicyMap
[i
].policy_name
;
185 if (policy_name
== key::kDefaultSearchProviderEncodings
) {
186 handlers_
.push_back(new DefaultSearchEncodingsPolicyHandler());
188 handlers_
.push_back(new SimplePolicyHandler(
190 kDefaultSearchPolicyMap
[i
].preference_path
,
191 kDefaultSearchPolicyMap
[i
].value_type
));
196 DefaultSearchPolicyHandler::~DefaultSearchPolicyHandler() {
197 STLDeleteElements(&handlers_
);
200 bool DefaultSearchPolicyHandler::CheckPolicySettings(const PolicyMap
& policies
,
201 PolicyErrorMap
* errors
) {
202 if (!CheckIndividualPolicies(policies
, errors
))
205 if (DefaultSearchProviderIsDisabled(policies
)) {
206 // Add an error for all specified default search policies except
207 // DefaultSearchProviderEnabled.
209 for (std::vector
<TypeCheckingPolicyHandler
*>::const_iterator handler
=
211 handler
!= handlers_
.end(); ++handler
) {
212 const char* policy_name
= (*handler
)->policy_name();
213 if (policy_name
!= key::kDefaultSearchProviderEnabled
&&
214 HasDefaultSearchPolicy(policies
, policy_name
)) {
215 errors
->AddError(policy_name
, IDS_POLICY_DEFAULT_SEARCH_DISABLED
);
221 const base::Value
* url
;
223 if (DefaultSearchURLIsValid(policies
, &url
, &dummy
) ||
224 !AnyDefaultSearchPoliciesSpecified(policies
))
226 errors
->AddError(key::kDefaultSearchProviderSearchURL
, url
?
227 IDS_POLICY_INVALID_SEARCH_URL_ERROR
: IDS_POLICY_NOT_SPECIFIED_ERROR
);
231 void DefaultSearchPolicyHandler::HandleDictionaryPref(const PolicyMap
& policies
,
232 PrefValueMap
* prefs
) {
233 if (DefaultSearchProviderIsDisabled(policies
)) {
234 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue
);
235 dict
->SetBoolean(DefaultSearchManager::kDisabledByPolicy
, true);
236 DefaultSearchManager::AddPrefValueToMap(dict
.release(), prefs
);
240 // The search URL is required. The other entries are optional. Just make
241 // sure that they are all specified via policy, so that the regular prefs
243 const base::Value
* dummy
;
245 if (!DefaultSearchURLIsValid(policies
, &dummy
, &url
))
248 scoped_ptr
<base::DictionaryValue
> dict(new base::DictionaryValue
);
249 for (size_t i
= 0; i
< arraysize(kDefaultSearchPolicyDataMap
); ++i
) {
250 const char* policy_name
= kDefaultSearchPolicyDataMap
[i
].policy_name
;
251 switch (kDefaultSearchPolicyDataMap
[i
].value_type
) {
252 case base::Value::TYPE_STRING
:
253 SetStringInPref(policies
,
255 kDefaultSearchPolicyDataMap
[i
].preference_path
,
258 case base::Value::TYPE_LIST
:
259 SetListInPref(policies
,
261 kDefaultSearchPolicyDataMap
[i
].preference_path
,
270 // Set the fields which are not specified by the policy to default values.
271 dict
->SetString(DefaultSearchManager::kID
,
272 base::Int64ToString(kInvalidTemplateURLID
));
273 dict
->SetInteger(DefaultSearchManager::kPrepopulateID
, 0);
274 dict
->SetString(DefaultSearchManager::kSyncGUID
, std::string());
275 dict
->SetString(DefaultSearchManager::kOriginatingURL
, std::string());
276 dict
->SetBoolean(DefaultSearchManager::kSafeForAutoReplace
, true);
277 dict
->SetDouble(DefaultSearchManager::kDateCreated
,
278 base::Time::Now().ToInternalValue());
279 dict
->SetDouble(DefaultSearchManager::kLastModified
,
280 base::Time::Now().ToInternalValue());
281 dict
->SetInteger(DefaultSearchManager::kUsageCount
, 0);
282 dict
->SetBoolean(DefaultSearchManager::kCreatedByPolicy
, true);
284 // For the name and keyword, default to the host if not specified. If
285 // there is no host (as is the case with file URLs of the form:
286 // "file:///c:/..."), use "_" to guarantee that the keyword is non-empty.
287 std::string name
, keyword
;
288 dict
->GetString(DefaultSearchManager::kKeyword
, &keyword
);
289 dict
->GetString(DefaultSearchManager::kShortName
, &name
);
290 dict
->GetString(DefaultSearchManager::kURL
, &url
);
292 std::string
host(GURL(url
).host());
296 dict
->SetString(DefaultSearchManager::kShortName
, host
);
298 dict
->SetString(DefaultSearchManager::kKeyword
, host
);
300 DefaultSearchManager::AddPrefValueToMap(dict
.release(), prefs
);
303 void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap
& policies
,
304 PrefValueMap
* prefs
) {
305 HandleDictionaryPref(policies
, prefs
);
307 if (DefaultSearchProviderIsDisabled(policies
)) {
308 prefs
->SetBoolean(prefs::kDefaultSearchProviderEnabled
, false);
310 // If default search is disabled, the other fields are ignored.
311 prefs
->SetString(prefs::kDefaultSearchProviderName
, std::string());
312 prefs
->SetString(prefs::kDefaultSearchProviderSearchURL
, std::string());
313 prefs
->SetString(prefs::kDefaultSearchProviderSuggestURL
, std::string());
314 prefs
->SetString(prefs::kDefaultSearchProviderIconURL
, std::string());
315 prefs
->SetString(prefs::kDefaultSearchProviderEncodings
, std::string());
316 prefs
->SetString(prefs::kDefaultSearchProviderKeyword
, std::string());
317 prefs
->SetString(prefs::kDefaultSearchProviderInstantURL
, std::string());
318 prefs
->SetString(prefs::kDefaultSearchProviderNewTabURL
, std::string());
319 prefs
->SetValue(prefs::kDefaultSearchProviderAlternateURLs
,
320 new base::ListValue());
322 prefs::kDefaultSearchProviderSearchTermsReplacementKey
, std::string());
323 prefs
->SetString(prefs::kDefaultSearchProviderImageURL
, std::string());
325 prefs::kDefaultSearchProviderSearchURLPostParams
, std::string());
327 prefs::kDefaultSearchProviderSuggestURLPostParams
, std::string());
329 prefs::kDefaultSearchProviderInstantURLPostParams
, std::string());
331 prefs::kDefaultSearchProviderImageURLPostParams
, std::string());
333 // The search URL is required. The other entries are optional. Just make
334 // sure that they are all specified via policy, so that the regular prefs
336 const base::Value
* dummy
;
338 if (DefaultSearchURLIsValid(policies
, &dummy
, &url
)) {
340 for (std::vector
<TypeCheckingPolicyHandler
*>::const_iterator handler
=
342 handler
!= handlers_
.end(); ++handler
) {
343 (*handler
)->ApplyPolicySettings(policies
, prefs
);
346 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderSuggestURL
);
347 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderIconURL
);
348 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderEncodings
);
349 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderKeyword
);
350 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderInstantURL
);
351 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderNewTabURL
);
352 EnsureListPrefExists(prefs
, prefs::kDefaultSearchProviderAlternateURLs
);
353 EnsureStringPrefExists(
355 prefs::kDefaultSearchProviderSearchTermsReplacementKey
);
356 EnsureStringPrefExists(prefs
, prefs::kDefaultSearchProviderImageURL
);
357 EnsureStringPrefExists(
359 prefs::kDefaultSearchProviderSearchURLPostParams
);
360 EnsureStringPrefExists(
362 prefs::kDefaultSearchProviderSuggestURLPostParams
);
363 EnsureStringPrefExists(
365 prefs::kDefaultSearchProviderInstantURLPostParams
);
366 EnsureStringPrefExists(
368 prefs::kDefaultSearchProviderImageURLPostParams
);
370 // For the name and keyword, default to the host if not specified. If
371 // there is no host (file: URLs? Not sure), use "_" to guarantee that the
372 // keyword is non-empty.
373 std::string name
, keyword
;
374 std::string
host(GURL(url
).host());
377 if (!prefs
->GetString(prefs::kDefaultSearchProviderName
, &name
) ||
379 prefs
->SetString(prefs::kDefaultSearchProviderName
, host
);
381 if (!prefs
->GetString(prefs::kDefaultSearchProviderKeyword
, &keyword
) ||
383 prefs
->SetString(prefs::kDefaultSearchProviderKeyword
, host
);
386 // And clear the IDs since these are not specified via policy.
387 prefs
->SetString(prefs::kDefaultSearchProviderID
, std::string());
388 prefs
->SetString(prefs::kDefaultSearchProviderPrepopulateID
,
392 content::NotificationService::current()->Notify(
393 chrome::NOTIFICATION_DEFAULT_SEARCH_POLICY_CHANGED
,
394 content::NotificationService::AllSources(),
395 content::NotificationService::NoDetails());
398 bool DefaultSearchPolicyHandler::CheckIndividualPolicies(
399 const PolicyMap
& policies
,
400 PolicyErrorMap
* errors
) {
401 for (std::vector
<TypeCheckingPolicyHandler
*>::const_iterator handler
=
403 handler
!= handlers_
.end(); ++handler
) {
404 if (!(*handler
)->CheckPolicySettings(policies
, errors
))
410 bool DefaultSearchPolicyHandler::HasDefaultSearchPolicy(
411 const PolicyMap
& policies
,
412 const char* policy_name
) {
413 return policies
.Get(policy_name
) != NULL
;
416 bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified(
417 const PolicyMap
& policies
) {
418 for (std::vector
<TypeCheckingPolicyHandler
*>::const_iterator handler
=
420 handler
!= handlers_
.end(); ++handler
) {
421 if (policies
.Get((*handler
)->policy_name()))
427 bool DefaultSearchPolicyHandler::DefaultSearchProviderIsDisabled(
428 const PolicyMap
& policies
) {
429 const base::Value
* provider_enabled
=
430 policies
.GetValue(key::kDefaultSearchProviderEnabled
);
432 return provider_enabled
&& provider_enabled
->GetAsBoolean(&enabled
) &&
436 bool DefaultSearchPolicyHandler::DefaultSearchURLIsValid(
437 const PolicyMap
& policies
,
438 const base::Value
** url_value
,
439 std::string
* url_string
) {
440 *url_value
= policies
.GetValue(key::kDefaultSearchProviderSearchURL
);
441 if (!*url_value
|| !(*url_value
)->GetAsString(url_string
) ||
444 TemplateURLData data
;
445 data
.SetURL(*url_string
);
446 SearchTermsData search_terms_data
;
447 return TemplateURL(NULL
, data
).SupportsReplacementUsingTermsData(
451 void DefaultSearchPolicyHandler::EnsureStringPrefExists(
453 const std::string
& path
) {
455 if (!prefs
->GetString(path
, &value
))
456 prefs
->SetString(path
, value
);
459 void DefaultSearchPolicyHandler::EnsureListPrefExists(
461 const std::string
& path
) {
463 base::ListValue
* list_value
;
464 if (!prefs
->GetValue(path
, &value
) || !value
->GetAsList(&list_value
))
465 prefs
->SetValue(path
, new base::ListValue());
468 } // namespace policy