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 base::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 std::string error_details; 45 if (!permission->FromValue(permission_value, &error_details, 46 unhandled_permissions)) { 47 if (error) { 48 if (error_details.empty()) { 49 *error = ErrorUtils::FormatErrorMessageUTF16( 50 errors::kInvalidPermission, 51 permission_info->name()); 52 } else { 53 *error = ErrorUtils::FormatErrorMessageUTF16( 54 errors::kInvalidPermissionWithDetail, 55 permission_info->name(), 56 error_details); 57 } 58 return false; 59 } 60 LOG(WARNING) << "Parse permission failed."; 61 } else { 62 api_permissions->insert(permission.release()); 63 } 64 return true; 65 } 66 67 if (unhandled_permissions) 68 unhandled_permissions->push_back(permission_str); 69 else 70 LOG(WARNING) << "Unknown permission[" << permission_str << "]."; 71 72 return true; 73 } 74 75 bool ParseChildPermissions(const std::string& base_name, 76 const base::Value* permission_value, 77 APIPermissionSet::ParseSource source, 78 APIPermissionSet* api_permissions, 79 base::string16* error, 80 std::vector<std::string>* unhandled_permissions) { 81 if (permission_value) { 82 const base::ListValue* permissions; 83 if (!permission_value->GetAsList(&permissions)) { 84 if (error) { 85 *error = ErrorUtils::FormatErrorMessageUTF16( 86 errors::kInvalidPermission, base_name); 87 return false; 88 } 89 LOG(WARNING) << "Permission value is not a list."; 90 // Failed to parse, but since error is NULL, failures are not fatal so 91 // return true here anyway. 92 return true; 93 } 94 95 for (size_t i = 0; i < permissions->GetSize(); ++i) { 96 std::string permission_str; 97 if (!permissions->GetString(i, &permission_str)) { 98 // permission should be a string 99 if (error) { 100 *error = ErrorUtils::FormatErrorMessageUTF16( 101 errors::kInvalidPermission, 102 base_name + '.' + base::IntToString(i)); 103 return false; 104 } 105 LOG(WARNING) << "Permission is not a string."; 106 continue; 107 } 108 109 if (!CreateAPIPermission( 110 base_name + '.' + permission_str, NULL, source, 111 api_permissions, error, unhandled_permissions)) 112 return false; 113 } 114 } 115 116 return CreateAPIPermission(base_name, NULL, source, 117 api_permissions, error, NULL); 118 } 119 120 } // namespace 121 122 void APIPermissionSet::insert(APIPermission::ID id) { 123 const APIPermissionInfo* permission_info = 124 PermissionsInfo::GetInstance()->GetByID(id); 125 DCHECK(permission_info); 126 insert(permission_info->CreateAPIPermission()); 127 } 128 129 void APIPermissionSet::insert(APIPermission* permission) { 130 BaseSetOperators<APIPermissionSet>::insert(permission); 131 } 132 133 // static 134 bool APIPermissionSet::ParseFromJSON( 135 const base::ListValue* permissions, 136 APIPermissionSet::ParseSource source, 137 APIPermissionSet* api_permissions, 138 base::string16* error, 139 std::vector<std::string>* unhandled_permissions) { 140 for (size_t i = 0; i < permissions->GetSize(); ++i) { 141 std::string permission_str; 142 const base::Value* permission_value = NULL; 143 if (!permissions->GetString(i, &permission_str)) { 144 const base::DictionaryValue* dict = NULL; 145 // permission should be a string or a single key dict. 146 if (!permissions->GetDictionary(i, &dict) || dict->size() != 1) { 147 if (error) { 148 *error = ErrorUtils::FormatErrorMessageUTF16( 149 errors::kInvalidPermission, base::IntToString(i)); 150 return false; 151 } 152 LOG(WARNING) << "Permission is not a string or single key dict."; 153 continue; 154 } 155 base::DictionaryValue::Iterator it(*dict); 156 permission_str = it.key(); 157 permission_value = &it.value(); 158 } 159 160 // Check if this permission is a special case where its value should 161 // be treated as a list of child permissions. 162 if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) { 163 if (!ParseChildPermissions(permission_str, permission_value, source, 164 api_permissions, error, unhandled_permissions)) 165 return false; 166 continue; 167 } 168 169 if (!CreateAPIPermission(permission_str, permission_value, source, 170 api_permissions, error, unhandled_permissions)) 171 return false; 172 } 173 return true; 174 } 175 176 void APIPermissionSet::AddImpliedPermissions() { 177 // The fileSystem.write and fileSystem.directory permissions imply 178 // fileSystem.writeDirectory. 179 // TODO(sammc): Remove this. See http://crbug.com/284849. 180 if (ContainsKey(map(), APIPermission::kFileSystemWrite) && 181 ContainsKey(map(), APIPermission::kFileSystemDirectory)) { 182 insert(APIPermission::kFileSystemWriteDirectory); 183 } 184 } 185 186 } // namespace extensions 187