Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / search_engines / default_search_policy_handler.cc
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.
4
5 #include "chrome/browser/search_engines/default_search_policy_handler.h"
6
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"
19
20 namespace policy {
21
22 namespace {
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,
26                    const char* key,
27                    base::DictionaryValue* dict) {
28   DCHECK(dict);
29   const base::Value* policy_value = policies.GetValue(policy_name);
30   const base::ListValue* policy_list = NULL;
31   if (policy_value) {
32     bool is_list = policy_value->GetAsList(&policy_list);
33     DCHECK(is_list);
34   }
35   dict->Set(key, policy_list ? policy_list->DeepCopy() : new base::ListValue());
36 }
37
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,
41                      const char* key,
42                      base::DictionaryValue* dict) {
43   DCHECK(dict);
44   const base::Value* policy_value = policies.GetValue(policy_name);
45   std::string str;
46   if (policy_value) {
47     bool is_string = policy_value->GetAsString(&str);
48     DCHECK(is_string);
49   }
50   dict->SetString(key, str);
51 }
52
53 }  // namespace
54
55 // List of policy types to preference names, for policies affecting the default
56 // search provider.
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 },
106 };
107
108 // List of policy types to preference names, for policies affecting the default
109 // search provider.
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},
142 };
143
144 // DefaultSearchEncodingsPolicyHandler implementation --------------------------
145
146 DefaultSearchEncodingsPolicyHandler::DefaultSearchEncodingsPolicyHandler()
147     : TypeCheckingPolicyHandler(key::kDefaultSearchProviderEncodings,
148                                 base::Value::TYPE_LIST) {}
149
150 DefaultSearchEncodingsPolicyHandler::~DefaultSearchEncodingsPolicyHandler() {
151 }
152
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))
161     return;
162
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) {
167     std::string s;
168     if ((*iter)->GetAsString(&s)) {
169       string_parts.push_back(s);
170     }
171   }
172   std::string encodings = JoinString(string_parts, ';');
173   prefs->SetValue(prefs::kDefaultSearchProviderEncodings,
174                   base::Value::CreateStringValue(encodings));
175 }
176
177
178 // DefaultSearchPolicyHandler implementation -----------------------------------
179
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());
185     } else {
186       handlers_.push_back(new SimplePolicyHandler(
187           policy_name,
188           kDefaultSearchPolicyMap[i].preference_path,
189           kDefaultSearchPolicyMap[i].value_type));
190     }
191   }
192 }
193
194 DefaultSearchPolicyHandler::~DefaultSearchPolicyHandler() {
195   STLDeleteElements(&handlers_);
196 }
197
198 bool DefaultSearchPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
199                                                      PolicyErrorMap* errors) {
200   if (!CheckIndividualPolicies(policies, errors))
201     return false;
202
203   if (DefaultSearchProviderIsDisabled(policies)) {
204     // Add an error for all specified default search policies except
205     // DefaultSearchProviderEnabled.
206
207     for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
208              handlers_.begin();
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);
214       }
215     }
216     return true;
217   }
218
219   const base::Value* url;
220   std::string dummy;
221   if (DefaultSearchURLIsValid(policies, &url, &dummy) ||
222       !AnyDefaultSearchPoliciesSpecified(policies))
223     return true;
224   errors->AddError(key::kDefaultSearchProviderSearchURL, url ?
225       IDS_POLICY_INVALID_SEARCH_URL_ERROR : IDS_POLICY_NOT_SPECIFIED_ERROR);
226   return false;
227 }
228
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);
235     return;
236   }
237
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
240   // aren't used.
241   const base::Value* dummy;
242   std::string url;
243   if (!DefaultSearchURLIsValid(policies, &dummy, &url))
244     return;
245
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,
252                         policy_name,
253                         kDefaultSearchPolicyDataMap[i].preference_path,
254                         dict.get());
255         break;
256       case base::Value::TYPE_LIST:
257         SetListInPref(policies,
258                       policy_name,
259                       kDefaultSearchPolicyDataMap[i].preference_path,
260                       dict.get());
261         break;
262       default:
263         NOTREACHED();
264         break;
265     }
266   }
267
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);
281
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);
289
290   std::string host(GURL(url).host());
291   if (host.empty())
292     host = "_";
293   if (name.empty())
294     dict->SetString(DefaultSearchManager::kShortName, host);
295   if (keyword.empty())
296     dict->SetString(DefaultSearchManager::kKeyword, host);
297
298   DefaultSearchManager::AddPrefValueToMap(dict.release(), prefs);
299 }
300
301 void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
302                                                      PrefValueMap* prefs) {
303   HandleDictionaryPref(policies, prefs);
304
305   if (DefaultSearchProviderIsDisabled(policies)) {
306     prefs->SetBoolean(prefs::kDefaultSearchProviderEnabled, false);
307
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());
319     prefs->SetString(
320         prefs::kDefaultSearchProviderSearchTermsReplacementKey, std::string());
321     prefs->SetString(prefs::kDefaultSearchProviderImageURL, std::string());
322     prefs->SetString(
323         prefs::kDefaultSearchProviderSearchURLPostParams, std::string());
324     prefs->SetString(
325         prefs::kDefaultSearchProviderSuggestURLPostParams, std::string());
326     prefs->SetString(
327         prefs::kDefaultSearchProviderInstantURLPostParams, std::string());
328     prefs->SetString(
329         prefs::kDefaultSearchProviderImageURLPostParams, std::string());
330   } else {
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
333     // aren't used.
334     const base::Value* dummy;
335     std::string url;
336     if (DefaultSearchURLIsValid(policies, &dummy, &url)) {
337
338       for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
339                handlers_.begin();
340            handler != handlers_.end(); ++handler) {
341         (*handler)->ApplyPolicySettings(policies, prefs);
342       }
343
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(
352           prefs,
353           prefs::kDefaultSearchProviderSearchTermsReplacementKey);
354       EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderImageURL);
355       EnsureStringPrefExists(
356           prefs,
357           prefs::kDefaultSearchProviderSearchURLPostParams);
358       EnsureStringPrefExists(
359           prefs,
360           prefs::kDefaultSearchProviderSuggestURLPostParams);
361       EnsureStringPrefExists(
362           prefs,
363           prefs::kDefaultSearchProviderInstantURLPostParams);
364       EnsureStringPrefExists(
365           prefs,
366           prefs::kDefaultSearchProviderImageURLPostParams);
367
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());
373       if (host.empty())
374         host = "_";
375       if (!prefs->GetString(prefs::kDefaultSearchProviderName, &name) ||
376           name.empty()) {
377         prefs->SetString(prefs::kDefaultSearchProviderName, host);
378       }
379       if (!prefs->GetString(prefs::kDefaultSearchProviderKeyword, &keyword) ||
380           keyword.empty()) {
381         prefs->SetString(prefs::kDefaultSearchProviderKeyword, host);
382       }
383
384       // And clear the IDs since these are not specified via policy.
385       prefs->SetString(prefs::kDefaultSearchProviderID, std::string());
386       prefs->SetString(prefs::kDefaultSearchProviderPrepopulateID,
387                        std::string());
388     }
389   }
390 }
391
392 bool DefaultSearchPolicyHandler::CheckIndividualPolicies(
393     const PolicyMap& policies,
394     PolicyErrorMap* errors) {
395   for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
396            handlers_.begin();
397        handler != handlers_.end(); ++handler) {
398     if (!(*handler)->CheckPolicySettings(policies, errors))
399       return false;
400   }
401   return true;
402 }
403
404 bool DefaultSearchPolicyHandler::HasDefaultSearchPolicy(
405     const PolicyMap& policies,
406     const char* policy_name) {
407   return policies.Get(policy_name) != NULL;
408 }
409
410 bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified(
411     const PolicyMap& policies) {
412   for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
413            handlers_.begin();
414        handler != handlers_.end(); ++handler) {
415     if (policies.Get((*handler)->policy_name()))
416       return true;
417   }
418   return false;
419 }
420
421 bool DefaultSearchPolicyHandler::DefaultSearchProviderIsDisabled(
422     const PolicyMap& policies) {
423   const base::Value* provider_enabled =
424       policies.GetValue(key::kDefaultSearchProviderEnabled);
425   bool enabled = true;
426   return provider_enabled && provider_enabled->GetAsBoolean(&enabled) &&
427       !enabled;
428 }
429
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) ||
436       url_string->empty())
437     return false;
438   TemplateURLData data;
439   data.SetURL(*url_string);
440   SearchTermsData search_terms_data;
441   return TemplateURL(data).SupportsReplacement(search_terms_data);
442 }
443
444 void DefaultSearchPolicyHandler::EnsureStringPrefExists(
445     PrefValueMap* prefs,
446     const std::string& path) {
447   std::string value;
448   if (!prefs->GetString(path, &value))
449     prefs->SetString(path, value);
450 }
451
452 void DefaultSearchPolicyHandler::EnsureListPrefExists(
453     PrefValueMap* prefs,
454     const std::string& path) {
455   base::Value* value;
456   base::ListValue* list_value;
457   if (!prefs->GetValue(path, &value) || !value->GetAsList(&list_value))
458     prefs->SetValue(path, new base::ListValue());
459 }
460
461 }  // namespace policy