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/crx_file/id_util.h" 12 #include "components/policy/core/browser/policy_error_map.h" 13 #include "components/policy/core/common/policy_map.h" 14 #include "extensions/browser/pref_names.h" 15 #include "extensions/common/extension.h" 16 #include "grit/components_strings.h" 17 #include "policy/policy_constants.h" 18 19 namespace extensions { 20 21 // ExtensionListPolicyHandler implementation ----------------------------------- 22 23 ExtensionListPolicyHandler::ExtensionListPolicyHandler(const char* policy_name, 24 const char* pref_path, 25 bool allow_wildcards) 26 : policy::TypeCheckingPolicyHandler(policy_name, base::Value::TYPE_LIST), 27 pref_path_(pref_path), 28 allow_wildcards_(allow_wildcards) {} 29 30 ExtensionListPolicyHandler::~ExtensionListPolicyHandler() {} 31 32 bool ExtensionListPolicyHandler::CheckPolicySettings( 33 const policy::PolicyMap& policies, 34 policy::PolicyErrorMap* errors) { 35 return CheckAndGetList(policies, errors, NULL); 36 } 37 38 void ExtensionListPolicyHandler::ApplyPolicySettings( 39 const policy::PolicyMap& policies, 40 PrefValueMap* prefs) { 41 scoped_ptr<base::ListValue> list; 42 policy::PolicyErrorMap errors; 43 if (CheckAndGetList(policies, &errors, &list) && list) 44 prefs->SetValue(pref_path(), list.release()); 45 } 46 47 const char* ExtensionListPolicyHandler::pref_path() const { 48 return pref_path_; 49 } 50 51 bool ExtensionListPolicyHandler::CheckAndGetList( 52 const policy::PolicyMap& policies, 53 policy::PolicyErrorMap* errors, 54 scoped_ptr<base::ListValue>* extension_ids) { 55 if (extension_ids) 56 extension_ids->reset(); 57 58 const base::Value* value = NULL; 59 if (!CheckAndGetValue(policies, errors, &value)) 60 return false; 61 62 if (!value) 63 return true; 64 65 const base::ListValue* list_value = NULL; 66 if (!value->GetAsList(&list_value)) { 67 NOTREACHED(); 68 return false; 69 } 70 71 // Filter the list, rejecting any invalid extension IDs. 72 scoped_ptr<base::ListValue> filtered_list(new base::ListValue()); 73 for (base::ListValue::const_iterator entry(list_value->begin()); 74 entry != list_value->end(); ++entry) { 75 std::string id; 76 if (!(*entry)->GetAsString(&id)) { 77 errors->AddError(policy_name(), 78 entry - list_value->begin(), 79 IDS_POLICY_TYPE_ERROR, 80 ValueTypeToString(base::Value::TYPE_STRING)); 81 continue; 82 } 83 if (!(allow_wildcards_ && id == "*") && !crx_file::id_util::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(new base::StringValue(id)); 90 } 91 92 if (extension_ids) 93 *extension_ids = filtered_list.Pass(); 94 95 return true; 96 } 97 98 // ExtensionInstallForcelistPolicyHandler implementation ----------------------- 99 100 ExtensionInstallForcelistPolicyHandler::ExtensionInstallForcelistPolicyHandler() 101 : policy::TypeCheckingPolicyHandler(policy::key::kExtensionInstallForcelist, 102 base::Value::TYPE_LIST) {} 103 104 ExtensionInstallForcelistPolicyHandler:: 105 ~ExtensionInstallForcelistPolicyHandler() {} 106 107 bool 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 115 void 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 127 bool 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 (!crx_file::id_util::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 190 ExtensionURLPatternListPolicyHandler::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 196 ExtensionURLPatternListPolicyHandler::~ExtensionURLPatternListPolicyHandler() {} 197 198 bool 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 238 void 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