Home | History | Annotate | Download | only in search_engines
      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
    461