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 "extensions/common/permissions/api_permission_set.h" 6 7 #include "base/logging.h" 8 #include "base/stl_util.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/values.h" 11 #include "extensions/common/error_utils.h" 12 #include "extensions/common/manifest_constants.h" 13 #include "extensions/common/permissions/permissions_info.h" 14 15 namespace extensions { 16 17 namespace errors = manifest_errors; 18 19 namespace { 20 21 bool CreateAPIPermission( 22 const std::string& permission_str, 23 const base::Value* permission_value, 24 APIPermissionSet::ParseSource source, 25 APIPermissionSet* api_permissions, 26 string16* error, 27 std::vector<std::string>* unhandled_permissions) { 28 29 const APIPermissionInfo* permission_info = 30 PermissionsInfo::GetInstance()->GetByName(permission_str); 31 if (permission_info) { 32 scoped_ptr<APIPermission> permission( 33 permission_info->CreateAPIPermission()); 34 if (source != APIPermissionSet::kAllowInternalPermissions && 35 permission_info->is_internal()) { 36 // An internal permission specified in permissions list is an error. 37 if (error) { 38 *error = ErrorUtils::FormatErrorMessageUTF16( 39 errors::kPermissionNotAllowedInManifest, permission_str); 40 } 41 return false; 42 } 43 44 if (!permission->FromValue(permission_value)) { 45 if (error) { 46 *error = ErrorUtils::FormatErrorMessageUTF16( 47 errors::kInvalidPermission, permission_info->name()); 48 return false; 49 } 50 LOG(WARNING) << "Parse permission failed."; 51 } else { 52 api_permissions->insert(permission.release()); 53 } 54 return true; 55 } 56 57 if (unhandled_permissions) 58 unhandled_permissions->push_back(permission_str); 59 else 60 LOG(WARNING) << "Unknown permission[" << permission_str << "]."; 61 62 return true; 63 } 64 65 bool ParseChildPermissions(const std::string& base_name, 66 const base::Value* permission_value, 67 APIPermissionSet::ParseSource source, 68 APIPermissionSet* api_permissions, 69 string16* error, 70 std::vector<std::string>* unhandled_permissions) { 71 if (permission_value) { 72 const base::ListValue* permissions; 73 if (!permission_value->GetAsList(&permissions)) { 74 if (error) { 75 *error = ErrorUtils::FormatErrorMessageUTF16( 76 errors::kInvalidPermission, base_name); 77 return false; 78 } 79 LOG(WARNING) << "Permission value is not a list."; 80 // Failed to parse, but since error is NULL, failures are not fatal so 81 // return true here anyway. 82 return true; 83 } 84 85 for (size_t i = 0; i < permissions->GetSize(); ++i) { 86 std::string permission_str; 87 if (!permissions->GetString(i, &permission_str)) { 88 // permission should be a string 89 if (error) { 90 *error = ErrorUtils::FormatErrorMessageUTF16( 91 errors::kInvalidPermission, 92 base_name + '.' + base::IntToString(i)); 93 return false; 94 } 95 LOG(WARNING) << "Permission is not a string."; 96 continue; 97 } 98 99 if (!CreateAPIPermission( 100 base_name + '.' + permission_str, NULL, source, 101 api_permissions, error, unhandled_permissions)) 102 return false; 103 } 104 } 105 106 return CreateAPIPermission(base_name, NULL, source, 107 api_permissions, error, NULL); 108 } 109 110 } // namespace 111 112 void APIPermissionSet::insert(APIPermission::ID id) { 113 const APIPermissionInfo* permission_info = 114 PermissionsInfo::GetInstance()->GetByID(id); 115 insert(permission_info->CreateAPIPermission()); 116 } 117 118 void APIPermissionSet::insert(APIPermission* permission) { 119 BaseSetOperators<APIPermissionSet>::insert(permission); 120 } 121 122 // static 123 bool APIPermissionSet::ParseFromJSON( 124 const base::ListValue* permissions, 125 APIPermissionSet::ParseSource source, 126 APIPermissionSet* api_permissions, 127 string16* error, 128 std::vector<std::string>* unhandled_permissions) { 129 for (size_t i = 0; i < permissions->GetSize(); ++i) { 130 std::string permission_str; 131 const base::Value* permission_value = NULL; 132 if (!permissions->GetString(i, &permission_str)) { 133 const base::DictionaryValue* dict = NULL; 134 // permission should be a string or a single key dict. 135 if (!permissions->GetDictionary(i, &dict) || dict->size() != 1) { 136 if (error) { 137 *error = ErrorUtils::FormatErrorMessageUTF16( 138 errors::kInvalidPermission, base::IntToString(i)); 139 return false; 140 } 141 LOG(WARNING) << "Permission is not a string or single key dict."; 142 continue; 143 } 144 base::DictionaryValue::Iterator it(*dict); 145 permission_str = it.key(); 146 permission_value = &it.value(); 147 } 148 149 // Check if this permission is a special case where its value should 150 // be treated as a list of child permissions. 151 if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) { 152 if (!ParseChildPermissions(permission_str, permission_value, source, 153 api_permissions, error, unhandled_permissions)) 154 return false; 155 continue; 156 } 157 158 if (!CreateAPIPermission(permission_str, permission_value, source, 159 api_permissions, error, unhandled_permissions)) 160 return false; 161 } 162 return true; 163 } 164 165 void APIPermissionSet::AddImpliedPermissions() { 166 // The fileSystem.write and fileSystem.directory permissions imply 167 // fileSystem.writeDirectory. 168 // TODO(sammc): Remove this. See http://crbug.com/284849. 169 if (ContainsKey(map(), APIPermission::kFileSystemWrite) && 170 ContainsKey(map(), APIPermission::kFileSystemDirectory)) { 171 insert(APIPermission::kFileSystemWriteDirectory); 172 } 173 } 174 175 } // namespace extensions 176