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/extensions/policy_handlers.h" 6 7#include "base/logging.h" 8#include "base/prefs/pref_value_map.h" 9#include "chrome/browser/extensions/external_policy_loader.h" 10#include "chrome/common/pref_names.h" 11#include "components/policy/core/browser/policy_error_map.h" 12#include "components/policy/core/common/policy_map.h" 13#include "extensions/browser/pref_names.h" 14#include "extensions/common/extension.h" 15#include "grit/components_strings.h" 16#include "policy/policy_constants.h" 17 18namespace extensions { 19 20// ExtensionListPolicyHandler implementation ----------------------------------- 21 22ExtensionListPolicyHandler::ExtensionListPolicyHandler(const char* policy_name, 23 const char* pref_path, 24 bool allow_wildcards) 25 : policy::TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST), 26 pref_path_(pref_path), 27 allow_wildcards_(allow_wildcards) {} 28 29ExtensionListPolicyHandler::~ExtensionListPolicyHandler() {} 30 31bool ExtensionListPolicyHandler::CheckPolicySettings( 32 const policy::PolicyMap& policies, 33 policy::PolicyErrorMap* errors) { 34 return CheckAndGetList(policies, errors, NULL); 35} 36 37void ExtensionListPolicyHandler::ApplyPolicySettings( 38 const policy::PolicyMap& policies, 39 PrefValueMap* prefs) { 40 scoped_ptr<base::ListValue> list; 41 policy::PolicyErrorMap errors; 42 if (CheckAndGetList(policies, &errors, &list) && list) 43 prefs->SetValue(pref_path(), list.release()); 44} 45 46const char* ExtensionListPolicyHandler::pref_path() const { 47 return pref_path_; 48} 49 50bool ExtensionListPolicyHandler::CheckAndGetList( 51 const policy::PolicyMap& policies, 52 policy::PolicyErrorMap* errors, 53 scoped_ptr<base::ListValue>* extension_ids) { 54 if (extension_ids) 55 extension_ids->reset(); 56 57 const base::Value* value = NULL; 58 if (!CheckAndGetValue(policies, errors, &value)) 59 return false; 60 61 if (!value) 62 return true; 63 64 const base::ListValue* list_value = NULL; 65 if (!value->GetAsList(&list_value)) { 66 NOTREACHED(); 67 return false; 68 } 69 70 // Filter the list, rejecting any invalid extension IDs. 71 scoped_ptr<base::ListValue> filtered_list(new base::ListValue()); 72 for (base::ListValue::const_iterator entry(list_value->begin()); 73 entry != list_value->end(); ++entry) { 74 std::string id; 75 if (!(*entry)->GetAsString(&id)) { 76 errors->AddError(policy_name(), 77 entry - list_value->begin(), 78 IDS_POLICY_TYPE_ERROR, 79 ValueTypeToString(base::Value::TYPE_STRING)); 80 continue; 81 } 82 if (!(allow_wildcards_ && id == "*") && 83 !extensions::Extension::IdIsValid(id)) { 84 errors->AddError(policy_name(), 85 entry - list_value->begin(), 86 IDS_POLICY_VALUE_FORMAT_ERROR); 87 continue; 88 } 89 filtered_list->Append(base::Value::CreateStringValue(id)); 90 } 91 92 if (extension_ids) 93 *extension_ids = filtered_list.Pass(); 94 95 return true; 96} 97 98// ExtensionInstallForcelistPolicyHandler implementation ----------------------- 99 100ExtensionInstallForcelistPolicyHandler::ExtensionInstallForcelistPolicyHandler() 101 : policy::TypeCheckingPolicyHandler(policy::key::kExtensionInstallForcelist, 102 base::Value::TYPE_LIST) {} 103 104ExtensionInstallForcelistPolicyHandler:: 105 ~ExtensionInstallForcelistPolicyHandler() {} 106 107bool ExtensionInstallForcelistPolicyHandler::CheckPolicySettings( 108 const policy::PolicyMap& policies, 109 policy::PolicyErrorMap* errors) { 110 const base::Value* value; 111 return CheckAndGetValue(policies, errors, &value) && 112 ParseList(value, NULL, errors); 113} 114 115void ExtensionInstallForcelistPolicyHandler::ApplyPolicySettings( 116 const policy::PolicyMap& policies, 117 PrefValueMap* prefs) { 118 const base::Value* value = NULL; 119 scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); 120 if (CheckAndGetValue(policies, NULL, &value) && 121 value && 122 ParseList(value, dict.get(), NULL)) { 123 prefs->SetValue(pref_names::kInstallForceList, dict.release()); 124 } 125} 126 127bool ExtensionInstallForcelistPolicyHandler::ParseList( 128 const base::Value* policy_value, 129 base::DictionaryValue* extension_dict, 130 policy::PolicyErrorMap* errors) { 131 if (!policy_value) 132 return true; 133 134 const base::ListValue* policy_list_value = NULL; 135 if (!policy_value->GetAsList(&policy_list_value)) { 136 // This should have been caught in CheckPolicySettings. 137 NOTREACHED(); 138 return false; 139 } 140 141 for (base::ListValue::const_iterator entry(policy_list_value->begin()); 142 entry != policy_list_value->end(); ++entry) { 143 std::string entry_string; 144 if (!(*entry)->GetAsString(&entry_string)) { 145 if (errors) { 146 errors->AddError(policy_name(), 147 entry - policy_list_value->begin(), 148 IDS_POLICY_TYPE_ERROR, 149 ValueTypeToString(base::Value::TYPE_STRING)); 150 } 151 continue; 152 } 153 154 // Each string item of the list has the following form: 155 // <extension_id>;<update_url> 156 // Note: The update URL might also contain semicolons. 157 size_t pos = entry_string.find(';'); 158 if (pos == std::string::npos) { 159 if (errors) { 160 errors->AddError(policy_name(), 161 entry - policy_list_value->begin(), 162 IDS_POLICY_VALUE_FORMAT_ERROR); 163 } 164 continue; 165 } 166 167 std::string extension_id = entry_string.substr(0, pos); 168 std::string update_url = entry_string.substr(pos+1); 169 if (!extensions::Extension::IdIsValid(extension_id) || 170 !GURL(update_url).is_valid()) { 171 if (errors) { 172 errors->AddError(policy_name(), 173 entry - policy_list_value->begin(), 174 IDS_POLICY_VALUE_FORMAT_ERROR); 175 } 176 continue; 177 } 178 179 if (extension_dict) { 180 extensions::ExternalPolicyLoader::AddExtension( 181 extension_dict, extension_id, update_url); 182 } 183 } 184 185 return true; 186} 187 188// ExtensionURLPatternListPolicyHandler implementation ------------------------- 189 190ExtensionURLPatternListPolicyHandler::ExtensionURLPatternListPolicyHandler( 191 const char* policy_name, 192 const char* pref_path) 193 : policy::TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST), 194 pref_path_(pref_path) {} 195 196ExtensionURLPatternListPolicyHandler::~ExtensionURLPatternListPolicyHandler() {} 197 198bool ExtensionURLPatternListPolicyHandler::CheckPolicySettings( 199 const policy::PolicyMap& policies, 200 policy::PolicyErrorMap* errors) { 201 const base::Value* value = NULL; 202 if (!CheckAndGetValue(policies, errors, &value)) 203 return false; 204 205 if (!value) 206 return true; 207 208 const base::ListValue* list_value = NULL; 209 if (!value->GetAsList(&list_value)) { 210 NOTREACHED(); 211 return false; 212 } 213 214 // Check that the list contains valid URLPattern strings only. 215 for (base::ListValue::const_iterator entry(list_value->begin()); 216 entry != list_value->end(); ++entry) { 217 std::string url_pattern_string; 218 if (!(*entry)->GetAsString(&url_pattern_string)) { 219 errors->AddError(policy_name(), 220 entry - list_value->begin(), 221 IDS_POLICY_TYPE_ERROR, 222 ValueTypeToString(base::Value::TYPE_STRING)); 223 return false; 224 } 225 226 URLPattern pattern(URLPattern::SCHEME_ALL); 227 if (pattern.Parse(url_pattern_string) != URLPattern::PARSE_SUCCESS) { 228 errors->AddError(policy_name(), 229 entry - list_value->begin(), 230 IDS_POLICY_VALUE_FORMAT_ERROR); 231 return false; 232 } 233 } 234 235 return true; 236} 237 238void ExtensionURLPatternListPolicyHandler::ApplyPolicySettings( 239 const policy::PolicyMap& policies, 240 PrefValueMap* prefs) { 241 if (!pref_path_) 242 return; 243 const base::Value* value = policies.GetValue(policy_name()); 244 if (value) 245 prefs->SetValue(pref_path_, value->DeepCopy()); 246} 247 248} // namespace extensions 249