| // Copyright 2014 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #include "components/search_engines/default_search_policy_handler.h" | 
 |  | 
 | #include <stddef.h> | 
 |  | 
 | #include <utility> | 
 |  | 
 | #include "base/strings/string_number_conversions.h" | 
 | #include "components/policy/core/browser/policy_error_map.h" | 
 | #include "components/policy/core/common/policy_map.h" | 
 | #include "components/policy/policy_constants.h" | 
 | #include "components/prefs/pref_value_map.h" | 
 | #include "components/search_engines/default_search_manager.h" | 
 | #include "components/search_engines/search_engines_pref_names.h" | 
 | #include "components/search_engines/search_terms_data.h" | 
 | #include "components/search_engines/template_url.h" | 
 | #include "components/strings/grit/components_strings.h" | 
 |  | 
 | namespace policy { | 
 |  | 
 | namespace { | 
 | // Extracts a list from a policy value and adds it to a pref dictionary. | 
 | void SetListInPref(const PolicyMap& policies, | 
 |                    const char* policy_name, | 
 |                    const char* key, | 
 |                    base::DictionaryValue* dict) { | 
 |   DCHECK(dict); | 
 |   const base::Value* policy_value = policies.GetValue(policy_name); | 
 |   const base::ListValue* policy_list = nullptr; | 
 |   if (policy_value) { | 
 |     bool is_list = policy_value->GetAsList(&policy_list); | 
 |     DCHECK(is_list); | 
 |   } | 
 |   dict->Set(key, policy_list | 
 |                      ? std::make_unique<base::Value>(policy_list->Clone()) | 
 |                      : std::make_unique<base::Value>(base::Value::Type::LIST)); | 
 | } | 
 |  | 
 | // Extracts a string from a policy value and adds it to a pref dictionary. | 
 | void SetStringInPref(const PolicyMap& policies, | 
 |                      const char* policy_name, | 
 |                      const char* key, | 
 |                      base::DictionaryValue* dict) { | 
 |   DCHECK(dict); | 
 |   const base::Value* policy_value = policies.GetValue(policy_name); | 
 |   std::string str; | 
 |   if (policy_value) { | 
 |     bool is_string = policy_value->GetAsString(&str); | 
 |     DCHECK(is_string); | 
 |   } | 
 |   dict->SetString(key, str); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | // List of policy types to preference names, for policies affecting the default | 
 | // search provider. | 
 | const PolicyToPreferenceMapEntry kDefaultSearchPolicyDataMap[] = { | 
 |     {key::kDefaultSearchProviderEnabled, prefs::kDefaultSearchProviderEnabled, | 
 |      base::Value::Type::BOOLEAN}, | 
 |     {key::kDefaultSearchProviderName, DefaultSearchManager::kShortName, | 
 |      base::Value::Type::STRING}, | 
 |     {key::kDefaultSearchProviderKeyword, DefaultSearchManager::kKeyword, | 
 |      base::Value::Type::STRING}, | 
 |     {key::kDefaultSearchProviderSearchURL, DefaultSearchManager::kURL, | 
 |      base::Value::Type::STRING}, | 
 |     {key::kDefaultSearchProviderSuggestURL, | 
 |      DefaultSearchManager::kSuggestionsURL, base::Value::Type::STRING}, | 
 |     {key::kDefaultSearchProviderIconURL, DefaultSearchManager::kFaviconURL, | 
 |      base::Value::Type::STRING}, | 
 |     {key::kDefaultSearchProviderEncodings, | 
 |      DefaultSearchManager::kInputEncodings, base::Value::Type::LIST}, | 
 |     {key::kDefaultSearchProviderAlternateURLs, | 
 |      DefaultSearchManager::kAlternateURLs, base::Value::Type::LIST}, | 
 |     {key::kDefaultSearchProviderImageURL, DefaultSearchManager::kImageURL, | 
 |      base::Value::Type::STRING}, | 
 |     {key::kDefaultSearchProviderNewTabURL, DefaultSearchManager::kNewTabURL, | 
 |      base::Value::Type::STRING}, | 
 |     {key::kDefaultSearchProviderSearchURLPostParams, | 
 |      DefaultSearchManager::kSearchURLPostParams, base::Value::Type::STRING}, | 
 |     {key::kDefaultSearchProviderSuggestURLPostParams, | 
 |      DefaultSearchManager::kSuggestionsURLPostParams, | 
 |      base::Value::Type::STRING}, | 
 |     {key::kDefaultSearchProviderImageURLPostParams, | 
 |      DefaultSearchManager::kImageURLPostParams, base::Value::Type::STRING}, | 
 | }; | 
 |  | 
 | // DefaultSearchPolicyHandler implementation ----------------------------------- | 
 |  | 
 | DefaultSearchPolicyHandler::DefaultSearchPolicyHandler() {} | 
 |  | 
 | DefaultSearchPolicyHandler::~DefaultSearchPolicyHandler() {} | 
 |  | 
 | bool DefaultSearchPolicyHandler::CheckPolicySettings(const PolicyMap& policies, | 
 |                                                      PolicyErrorMap* errors) { | 
 |   if (!CheckIndividualPolicies(policies, errors)) | 
 |     return false; | 
 |  | 
 |   if (!DefaultSearchProviderPolicyIsSet(policies) || | 
 |       DefaultSearchProviderIsDisabled(policies)) { | 
 |     // Add an error for all specified default search policies except | 
 |     // DefaultSearchProviderEnabled. | 
 |  | 
 |     for (const auto& policy_map_entry : kDefaultSearchPolicyDataMap) { | 
 |       const char* policy_name = policy_map_entry.policy_name; | 
 |       if (policy_name != key::kDefaultSearchProviderEnabled && | 
 |           HasDefaultSearchPolicy(policies, policy_name)) { | 
 |         errors->AddError(policy_name, IDS_POLICY_DEFAULT_SEARCH_DISABLED); | 
 |       } | 
 |     } | 
 |     return true; | 
 |   } | 
 |  | 
 |   const base::Value* url; | 
 |   std::string dummy; | 
 |   if (DefaultSearchURLIsValid(policies, &url, &dummy) || | 
 |       !AnyDefaultSearchPoliciesSpecified(policies)) | 
 |     return true; | 
 |   errors->AddError(key::kDefaultSearchProviderSearchURL, url ? | 
 |       IDS_POLICY_INVALID_SEARCH_URL_ERROR : IDS_POLICY_NOT_SPECIFIED_ERROR); | 
 |   return false; | 
 | } | 
 |  | 
 | void DefaultSearchPolicyHandler::ApplyPolicySettings(const PolicyMap& policies, | 
 |                                                      PrefValueMap* prefs) { | 
 |   // If the main switch is not set don't set anything. | 
 |   if (!DefaultSearchProviderPolicyIsSet(policies)) | 
 |     return; | 
 |  | 
 |   if (DefaultSearchProviderIsDisabled(policies)) { | 
 |     std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue); | 
 |     dict->SetBoolean(DefaultSearchManager::kDisabledByPolicy, true); | 
 |     DefaultSearchManager::AddPrefValueToMap(std::move(dict), prefs); | 
 |     return; | 
 |   } | 
 |  | 
 |   // The search URL is required.  The other entries are optional.  Just make | 
 |   // sure that they are all specified via policy, so that the regular prefs | 
 |   // aren't used. | 
 |   const base::Value* dummy; | 
 |   std::string url; | 
 |   if (!DefaultSearchURLIsValid(policies, &dummy, &url)) | 
 |     return; | 
 |  | 
 |   std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue); | 
 |   for (size_t i = 0; i < base::size(kDefaultSearchPolicyDataMap); ++i) { | 
 |     const char* policy_name = kDefaultSearchPolicyDataMap[i].policy_name; | 
 |     // kDefaultSearchProviderEnabled has already been handled. | 
 |     if (policy_name == key::kDefaultSearchProviderEnabled) | 
 |       continue; | 
 |  | 
 |     switch (kDefaultSearchPolicyDataMap[i].value_type) { | 
 |       case base::Value::Type::STRING: | 
 |         SetStringInPref(policies, | 
 |                         policy_name, | 
 |                         kDefaultSearchPolicyDataMap[i].preference_path, | 
 |                         dict.get()); | 
 |         break; | 
 |       case base::Value::Type::LIST: | 
 |         SetListInPref(policies, | 
 |                       policy_name, | 
 |                       kDefaultSearchPolicyDataMap[i].preference_path, | 
 |                       dict.get()); | 
 |         break; | 
 |       default: | 
 |         NOTREACHED(); | 
 |         break; | 
 |     } | 
 |   } | 
 |  | 
 |   // Set the fields which are not specified by the policy to default values. | 
 |   dict->SetString(DefaultSearchManager::kID, | 
 |                   base::NumberToString(kInvalidTemplateURLID)); | 
 |   dict->SetInteger(DefaultSearchManager::kPrepopulateID, 0); | 
 |   dict->SetString(DefaultSearchManager::kSyncGUID, std::string()); | 
 |   dict->SetString(DefaultSearchManager::kOriginatingURL, std::string()); | 
 |   dict->SetBoolean(DefaultSearchManager::kSafeForAutoReplace, true); | 
 |   dict->SetDouble(DefaultSearchManager::kDateCreated, | 
 |                   base::Time::Now().ToInternalValue()); | 
 |   dict->SetDouble(DefaultSearchManager::kLastModified, | 
 |                   base::Time::Now().ToInternalValue()); | 
 |   dict->SetInteger(DefaultSearchManager::kUsageCount, 0); | 
 |   dict->SetBoolean(DefaultSearchManager::kCreatedByPolicy, true); | 
 |  | 
 |   // For the name and keyword, default to the host if not specified.  If | 
 |   // there is no host (as is the case with file URLs of the form: | 
 |   // "file:///c:/..."), use "_" to guarantee that the keyword is non-empty. | 
 |   std::string name, keyword; | 
 |   dict->GetString(DefaultSearchManager::kKeyword, &keyword); | 
 |   dict->GetString(DefaultSearchManager::kShortName, &name); | 
 |   dict->GetString(DefaultSearchManager::kURL, &url); | 
 |  | 
 |   std::string host(GURL(url).host()); | 
 |   if (host.empty()) | 
 |     host = "_"; | 
 |   if (name.empty()) | 
 |     dict->SetString(DefaultSearchManager::kShortName, host); | 
 |   if (keyword.empty()) | 
 |     dict->SetString(DefaultSearchManager::kKeyword, host); | 
 |  | 
 |   DefaultSearchManager::AddPrefValueToMap(std::move(dict), prefs); | 
 | } | 
 |  | 
 | bool DefaultSearchPolicyHandler::CheckIndividualPolicies( | 
 |     const PolicyMap& policies, | 
 |     PolicyErrorMap* errors) { | 
 |   bool all_ok = true; | 
 |   for (const auto& policy_map_entry : kDefaultSearchPolicyDataMap) { | 
 |     // It's important to check policy type for all policies and not just exit on | 
 |     // the first error, so we report all policy errors. | 
 |     const base::Value* value = policies.GetValue(policy_map_entry.policy_name); | 
 |     if (value && value->type() != policy_map_entry.value_type) { | 
 |       errors->AddError(policy_map_entry.policy_name, IDS_POLICY_TYPE_ERROR, | 
 |                        base::Value::GetTypeName(policy_map_entry.value_type)); | 
 |       all_ok = false; | 
 |     } | 
 |   } | 
 |   return all_ok; | 
 | } | 
 |  | 
 | bool DefaultSearchPolicyHandler::HasDefaultSearchPolicy( | 
 |     const PolicyMap& policies, | 
 |     const char* policy_name) { | 
 |   return policies.Get(policy_name) != nullptr; | 
 | } | 
 |  | 
 | bool DefaultSearchPolicyHandler::AnyDefaultSearchPoliciesSpecified( | 
 |     const PolicyMap& policies) { | 
 |   for (const auto& policy_map_entry : kDefaultSearchPolicyDataMap) { | 
 |     if (policies.Get(policy_map_entry.policy_name)) | 
 |       return true; | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | bool DefaultSearchPolicyHandler::DefaultSearchProviderIsDisabled( | 
 |     const PolicyMap& policies) { | 
 |   const base::Value* provider_enabled = | 
 |       policies.GetValue(key::kDefaultSearchProviderEnabled); | 
 |   bool enabled = true; | 
 |   return provider_enabled && provider_enabled->GetAsBoolean(&enabled) && | 
 |       !enabled; | 
 | } | 
 |  | 
 | bool DefaultSearchPolicyHandler::DefaultSearchProviderPolicyIsSet( | 
 |     const PolicyMap& policies) { | 
 |   return HasDefaultSearchPolicy(policies, key::kDefaultSearchProviderEnabled); | 
 | } | 
 |  | 
 | bool DefaultSearchPolicyHandler::DefaultSearchURLIsValid( | 
 |     const PolicyMap& policies, | 
 |     const base::Value** url_value, | 
 |     std::string* url_string) { | 
 |   *url_value = policies.GetValue(key::kDefaultSearchProviderSearchURL); | 
 |   if (!*url_value || !(*url_value)->GetAsString(url_string) || | 
 |       url_string->empty()) | 
 |     return false; | 
 |   TemplateURLData data; | 
 |   data.SetURL(*url_string); | 
 |   SearchTermsData search_terms_data; | 
 |   return TemplateURL(data).SupportsReplacement(search_terms_data); | 
 | } | 
 |  | 
 | void DefaultSearchPolicyHandler::EnsureStringPrefExists( | 
 |     PrefValueMap* prefs, | 
 |     const std::string& path) { | 
 |   std::string value; | 
 |   if (!prefs->GetString(path, &value)) | 
 |     prefs->SetString(path, value); | 
 | } | 
 |  | 
 | void DefaultSearchPolicyHandler::EnsureListPrefExists( | 
 |     PrefValueMap* prefs, | 
 |     const std::string& path) { | 
 |   base::Value* value; | 
 |   base::ListValue* list_value; | 
 |   if (!prefs->GetValue(path, &value) || !value->GetAsList(&list_value)) | 
 |     prefs->SetValue(path, base::Value(base::Value::Type::LIST)); | 
 | } | 
 |  | 
 | }  // namespace policy |