1// Copyright (c) 2012 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/common/extensions/permissions/api_permission_set.h" 6 7#include "base/logging.h" 8#include "base/strings/string_number_conversions.h" 9#include "base/values.h" 10#include "chrome/common/extensions/extension_manifest_constants.h" 11#include "chrome/common/extensions/permissions/permissions_info.h" 12#include "extensions/common/error_utils.h" 13 14namespace errors = extension_manifest_errors; 15 16namespace { 17 18using extensions::APIPermission; 19using extensions::APIPermissionInfo; 20using extensions::APIPermissionSet; 21using extensions::ErrorUtils; 22using extensions::PermissionsInfo; 23 24bool CreateAPIPermission( 25 const std::string& permission_str, 26 const base::Value* permission_value, 27 APIPermissionSet::ParseSource source, 28 APIPermissionSet* api_permissions, 29 string16* error, 30 std::vector<std::string>* unhandled_permissions) { 31 32 const APIPermissionInfo* permission_info = 33 PermissionsInfo::GetInstance()->GetByName(permission_str); 34 if (permission_info) { 35 scoped_ptr<APIPermission> permission( 36 permission_info->CreateAPIPermission()); 37 if (source != APIPermissionSet::kAllowInternalPermissions && 38 permission_info->is_internal()) { 39 // An internal permission specified in permissions list is an error. 40 if (error) { 41 *error = ErrorUtils::FormatErrorMessageUTF16( 42 errors::kPermissionNotAllowedInManifest, permission_str); 43 } 44 return false; 45 } 46 47 if (!permission->FromValue(permission_value)) { 48 if (error) { 49 *error = ErrorUtils::FormatErrorMessageUTF16( 50 errors::kInvalidPermission, permission_info->name()); 51 return false; 52 } 53 LOG(WARNING) << "Parse permission failed."; 54 } else { 55 api_permissions->insert(permission.release()); 56 } 57 return true; 58 } 59 60 if (unhandled_permissions) 61 unhandled_permissions->push_back(permission_str); 62 else 63 LOG(WARNING) << "Unknown permission[" << permission_str << "]."; 64 65 return true; 66} 67 68bool ParseChildPermissions(const std::string& base_name, 69 const base::Value* permission_value, 70 APIPermissionSet::ParseSource source, 71 APIPermissionSet* api_permissions, 72 string16* error, 73 std::vector<std::string>* unhandled_permissions) { 74 if (permission_value) { 75 const base::ListValue* permissions; 76 if (!permission_value->GetAsList(&permissions)) { 77 if (error) { 78 *error = ErrorUtils::FormatErrorMessageUTF16( 79 errors::kInvalidPermission, base_name); 80 return false; 81 } 82 LOG(WARNING) << "Permission value is not a list."; 83 // Failed to parse, but since error is NULL, failures are not fatal so 84 // return true here anyway. 85 return true; 86 } 87 88 for (size_t i = 0; i < permissions->GetSize(); ++i) { 89 std::string permission_str; 90 if (!permissions->GetString(i, &permission_str)) { 91 // permission should be a string 92 if (error) { 93 *error = ErrorUtils::FormatErrorMessageUTF16( 94 errors::kInvalidPermission, 95 base_name + '.' + base::IntToString(i)); 96 return false; 97 } 98 LOG(WARNING) << "Permission is not a string."; 99 continue; 100 } 101 102 if (!CreateAPIPermission( 103 base_name + '.' + permission_str, NULL, source, 104 api_permissions, error, unhandled_permissions)) 105 return false; 106 } 107 } 108 109 return CreateAPIPermission(base_name, NULL, source, 110 api_permissions, error, NULL); 111} 112 113} // namespace 114 115namespace extensions { 116 117APIPermissionSet::APIPermissionSet() { 118} 119 120APIPermissionSet::APIPermissionSet(const APIPermissionSet& set) { 121 this->operator=(set); 122} 123 124APIPermissionSet::~APIPermissionSet() { 125} 126 127APIPermissionSet::const_iterator::const_iterator( 128 const APIPermissionMap::const_iterator& it) 129 : it_(it) { 130} 131 132APIPermissionSet::const_iterator::const_iterator( 133 const const_iterator& ids_it) 134 : it_(ids_it.it_) { 135} 136 137APIPermissionSet& APIPermissionSet::operator=(const APIPermissionSet& rhs) { 138 const_iterator it = rhs.begin(); 139 const const_iterator end = rhs.end(); 140 while (it != end) { 141 insert(it->Clone()); 142 ++it; 143 } 144 return *this; 145} 146 147bool APIPermissionSet::operator==(const APIPermissionSet& rhs) const { 148 const_iterator it = begin(); 149 const_iterator rhs_it = rhs.begin(); 150 const_iterator it_end = end(); 151 const_iterator rhs_it_end = rhs.end(); 152 153 while (it != it_end && rhs_it != rhs_it_end) { 154 if (!it->Equal(*rhs_it)) 155 return false; 156 ++it; 157 ++rhs_it; 158 } 159 return it == it_end && rhs_it == rhs_it_end; 160} 161 162void APIPermissionSet::insert(APIPermission::ID id) { 163 const APIPermissionInfo* permission_info = 164 PermissionsInfo::GetInstance()->GetByID(id); 165 insert(permission_info->CreateAPIPermission()); 166} 167 168void APIPermissionSet::insert(APIPermission* permission) { 169 map_[permission->id()].reset(permission); 170} 171 172bool APIPermissionSet::Contains(const APIPermissionSet& rhs) const { 173 APIPermissionSet::const_iterator it1 = begin(); 174 APIPermissionSet::const_iterator it2 = rhs.begin(); 175 APIPermissionSet::const_iterator end1 = end(); 176 APIPermissionSet::const_iterator end2 = rhs.end(); 177 178 while (it1 != end1 && it2 != end2) { 179 if (it1->id() > it2->id()) { 180 return false; 181 } else if (it1->id() < it2->id()) { 182 ++it1; 183 } else { 184 if (!it1->Contains(*it2)) 185 return false; 186 ++it1; 187 ++it2; 188 } 189 } 190 191 return it2 == end2; 192} 193 194void APIPermissionSet::Difference( 195 const APIPermissionSet& set1, 196 const APIPermissionSet& set2, 197 APIPermissionSet* set3) { 198 CHECK(set3); 199 set3->clear(); 200 201 APIPermissionSet::const_iterator it1 = set1.begin(); 202 APIPermissionSet::const_iterator it2 = set2.begin(); 203 const APIPermissionSet::const_iterator end1 = set1.end(); 204 const APIPermissionSet::const_iterator end2 = set2.end(); 205 206 while (it1 != end1 && it2 != end2) { 207 if (it1->id() < it2->id()) { 208 set3->insert(it1->Clone()); 209 ++it1; 210 } else if (it1->id() > it2->id()) { 211 ++it2; 212 } else { 213 APIPermission* p = it1->Diff(*it2); 214 if (p) 215 set3->insert(p); 216 ++it1; 217 ++it2; 218 } 219 } 220 221 while (it1 != end1) { 222 set3->insert(it1->Clone()); 223 ++it1; 224 } 225} 226 227void APIPermissionSet::Intersection( 228 const APIPermissionSet& set1, 229 const APIPermissionSet& set2, 230 APIPermissionSet* set3) { 231 DCHECK(set3); 232 set3->clear(); 233 234 APIPermissionSet::const_iterator it1 = set1.begin(); 235 APIPermissionSet::const_iterator it2 = set2.begin(); 236 const APIPermissionSet::const_iterator end1 = set1.end(); 237 const APIPermissionSet::const_iterator end2 = set2.end(); 238 239 while (it1 != end1 && it2 != end2) { 240 if (it1->id() < it2->id()) { 241 ++it1; 242 } else if (it1->id() > it2->id()) { 243 ++it2; 244 } else { 245 APIPermission* p = it1->Intersect(*it2); 246 if (p) 247 set3->insert(p); 248 ++it1; 249 ++it2; 250 } 251 } 252} 253 254void APIPermissionSet::Union( 255 const APIPermissionSet& set1, 256 const APIPermissionSet& set2, 257 APIPermissionSet* set3) { 258 DCHECK(set3); 259 set3->clear(); 260 261 APIPermissionSet::const_iterator it1 = set1.begin(); 262 APIPermissionSet::const_iterator it2 = set2.begin(); 263 const APIPermissionSet::const_iterator end1 = set1.end(); 264 const APIPermissionSet::const_iterator end2 = set2.end(); 265 266 while (true) { 267 if (it1 == end1) { 268 while (it2 != end2) { 269 set3->insert(it2->Clone()); 270 ++it2; 271 } 272 break; 273 } 274 if (it2 == end2) { 275 while (it1 != end1) { 276 set3->insert(it1->Clone()); 277 ++it1; 278 } 279 break; 280 } 281 if (it1->id() < it2->id()) { 282 set3->insert(it1->Clone()); 283 ++it1; 284 } else if (it1->id() > it2->id()) { 285 set3->insert(it2->Clone()); 286 ++it2; 287 } else { 288 set3->insert(it1->Union(*it2)); 289 ++it1; 290 ++it2; 291 } 292 } 293} 294 295// static 296bool APIPermissionSet::ParseFromJSON( 297 const base::ListValue* permissions, 298 APIPermissionSet::ParseSource source, 299 APIPermissionSet* api_permissions, 300 string16* error, 301 std::vector<std::string>* unhandled_permissions) { 302 for (size_t i = 0; i < permissions->GetSize(); ++i) { 303 std::string permission_str; 304 const base::Value* permission_value = NULL; 305 if (!permissions->GetString(i, &permission_str)) { 306 const base::DictionaryValue* dict = NULL; 307 // permission should be a string or a single key dict. 308 if (!permissions->GetDictionary(i, &dict) || dict->size() != 1) { 309 if (error) { 310 *error = ErrorUtils::FormatErrorMessageUTF16( 311 errors::kInvalidPermission, base::IntToString(i)); 312 return false; 313 } 314 LOG(WARNING) << "Permission is not a string or single key dict."; 315 continue; 316 } 317 base::DictionaryValue::Iterator it(*dict); 318 permission_str = it.key(); 319 permission_value = &it.value(); 320 } 321 322 // Check if this permission is a special case where its value should 323 // be treated as a list of child permissions. 324 if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) { 325 if (!ParseChildPermissions(permission_str, permission_value, source, 326 api_permissions, error, unhandled_permissions)) 327 return false; 328 continue; 329 } 330 331 if (!CreateAPIPermission(permission_str, permission_value, source, 332 api_permissions, error, unhandled_permissions)) 333 return false; 334 } 335 return true; 336} 337 338} // namespace extensions 339