| // 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 |