Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / components / search_engines / default_search_policy_handler.cc
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.
4
5 #include "components/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 "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"
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->SetString(prefs::kDefaultSearchProviderEncodings, encodings);
174 }
175
176
177 // DefaultSearchPolicyHandler implementation -----------------------------------
178
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());
184     } else {
185       handlers_.push_back(new SimplePolicyHandler(
186           policy_name,
187           kDefaultSearchPolicyMap[i].preference_path,
188           kDefaultSearchPolicyMap[i].value_type));
189     }
190   }
191 }
192
193 DefaultSearchPolicyHandler::~DefaultSearchPolicyHandler() {
194   STLDeleteElements(&handlers_);
195 }
196
197 bool DefaultSearchPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
198                                                      PolicyErrorMap* errors) {
199   if (!CheckIndividualPolicies(policies, errors))
200     return false;
201
202   if (DefaultSearchProviderIsDisabled(policies)) {
203     // Add an error for all specified default search policies except
204     // DefaultSearchProviderEnabled.
205
206     for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
207              handlers_.begin();
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);
213       }
214     }
215     return true;
216   }
217
218   const base::Value* url;
219   std::string dummy;
220   if (DefaultSearchURLIsValid(policies, &url, &dummy) ||
221       !AnyDefaultSearchPoliciesSpecified(policies))
222     return true;
223   errors->AddError(key::kDefaultSearchProviderSearchURL, url ?
224       IDS_POLICY_INVALID_SEARCH_URL_ERROR : IDS_POLICY_NOT_SPECIFIED_ERROR);
225   return false;
226 }
227
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);
234     return;
235   }
236
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
239   // aren't used.
240   const base::Value* dummy;
241   std::string url;
242   if (!DefaultSearchURLIsValid(policies, &dummy, &url))
243     return;
244
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,
251                         policy_name,
252                         kDefaultSearchPolicyDataMap[i].preference_path,
253                         dict.get());
254         break;
255       case base::Value::TYPE_LIST:
256         SetListInPref(policies,
257                       policy_name,
258                       kDefaultSearchPolicyDataMap[i].preference_path,
259                       dict.get());
260         break;
261       default:
262         NOTREACHED();
263         break;
264     }
265   }
266
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);
280
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);
288
289   std::string host(GURL(url).host());
290   if (host.empty())
291     host = "_";
292   if (name.empty())
293     dict->SetString(DefaultSearchManager::kShortName, host);
294   if (keyword.empty())
295     dict->SetString(DefaultSearchManager::kKeyword, host);
296
297   DefaultSearchManager::AddPrefValueToMap(dict.release(), prefs);
298 }
299
300 void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
301                                                      PrefValueMap* prefs) {
302   HandleDictionaryPref(policies, prefs);
303
304   if (DefaultSearchProviderIsDisabled(policies)) {
305     prefs->SetBoolean(prefs::kDefaultSearchProviderEnabled, false);
306
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());
318     prefs->SetString(
319         prefs::kDefaultSearchProviderSearchTermsReplacementKey, std::string());
320     prefs->SetString(prefs::kDefaultSearchProviderImageURL, std::string());
321     prefs->SetString(
322         prefs::kDefaultSearchProviderSearchURLPostParams, std::string());
323     prefs->SetString(
324         prefs::kDefaultSearchProviderSuggestURLPostParams, std::string());
325     prefs->SetString(
326         prefs::kDefaultSearchProviderInstantURLPostParams, std::string());
327     prefs->SetString(
328         prefs::kDefaultSearchProviderImageURLPostParams, std::string());
329   } else {
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
332     // aren't used.
333     const base::Value* dummy;
334     std::string url;
335     if (DefaultSearchURLIsValid(policies, &dummy, &url)) {
336
337       for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
338                handlers_.begin();
339            handler != handlers_.end(); ++handler) {
340         (*handler)->ApplyPolicySettings(policies, prefs);
341       }
342
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(
351           prefs,
352           prefs::kDefaultSearchProviderSearchTermsReplacementKey);
353       EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderImageURL);
354       EnsureStringPrefExists(
355           prefs,
356           prefs::kDefaultSearchProviderSearchURLPostParams);
357       EnsureStringPrefExists(
358           prefs,
359           prefs::kDefaultSearchProviderSuggestURLPostParams);
360       EnsureStringPrefExists(
361           prefs,
362           prefs::kDefaultSearchProviderInstantURLPostParams);
363       EnsureStringPrefExists(
364           prefs,
365           prefs::kDefaultSearchProviderImageURLPostParams);
366
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());
372       if (host.empty())
373         host = "_";
374       if (!prefs->GetString(prefs::kDefaultSearchProviderName, &name) ||
375           name.empty()) {
376         prefs->SetString(prefs::kDefaultSearchProviderName, host);
377       }
378       if (!prefs->GetString(prefs::kDefaultSearchProviderKeyword, &keyword) ||
379           keyword.empty()) {
380         prefs->SetString(prefs::kDefaultSearchProviderKeyword, host);
381       }
382
383       // And clear the IDs since these are not specified via policy.
384       prefs->SetString(prefs::kDefaultSearchProviderID, std::string());
385       prefs->SetString(prefs::kDefaultSearchProviderPrepopulateID,
386                        std::string());
387     }
388   }
389 }
390
391 bool DefaultSearchPolicyHandler::CheckIndividualPolicies(
392     const PolicyMap& policies,
393     PolicyErrorMap* errors) {
394   for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
395            handlers_.begin();
396        handler != handlers_.end(); ++handler) {
397     if (!(*handler)->CheckPolicySettings(policies, errors))
398       return false;
399   }
400   return true;
401 }
402
403 bool DefaultSearchPolicyHandler::HasDefaultSearchPolicy(
404     const PolicyMap& policies,
405     const char* policy_name) {
406   return policies.Get(policy_name) != NULL;
407 }
408
409 bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified(
410     const PolicyMap& policies) {
411   for (std::vector<TypeCheckingPolicyHandler*>::const_iterator handler =
412            handlers_.begin();
413        handler != handlers_.end(); ++handler) {
414     if (policies.Get((*handler)->policy_name()))
415       return true;
416   }
417   return false;
418 }
419
420 bool DefaultSearchPolicyHandler::DefaultSearchProviderIsDisabled(
421     const PolicyMap& policies) {
422   const base::Value* provider_enabled =
423       policies.GetValue(key::kDefaultSearchProviderEnabled);
424   bool enabled = true;
425   return provider_enabled && provider_enabled->GetAsBoolean(&enabled) &&
426       !enabled;
427 }
428
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) ||
435       url_string->empty())
436     return false;
437   TemplateURLData data;
438   data.SetURL(*url_string);
439   SearchTermsData search_terms_data;
440   return TemplateURL(data).SupportsReplacement(search_terms_data);
441 }
442
443 void DefaultSearchPolicyHandler::EnsureStringPrefExists(
444     PrefValueMap* prefs,
445     const std::string& path) {
446   std::string value;
447   if (!prefs->GetString(path, &value))
448     prefs->SetString(path, value);
449 }
450
451 void DefaultSearchPolicyHandler::EnsureListPrefExists(
452     PrefValueMap* prefs,
453     const std::string& path) {
454   base::Value* value;
455   base::ListValue* list_value;
456   if (!prefs->GetValue(path, &value) || !value->GetAsList(&list_value))
457     prefs->SetValue(path, new base::ListValue());
458 }
459
460 }  // namespace policy