Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / extensions / common / permissions / api_permission_set.cc
blobd21ab439dea801adbc71857552e72ff23e562839
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.
5 #include "extensions/common/permissions/api_permission_set.h"
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"
15 namespace extensions {
17 namespace errors = manifest_errors;
19 namespace {
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) {
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);
41 return false;
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);
58 return false;
60 LOG(WARNING) << "Parse permission failed.";
61 } else {
62 api_permissions->insert(permission.release());
64 return true;
67 if (unhandled_permissions)
68 unhandled_permissions->push_back(permission_str);
69 else
70 LOG(WARNING) << "Unknown permission[" << permission_str << "].";
72 return true;
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;
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;
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;
105 LOG(WARNING) << "Permission is not a string.";
106 continue;
109 if (!CreateAPIPermission(
110 base_name + '.' + permission_str, NULL, source,
111 api_permissions, error, unhandled_permissions))
112 return false;
116 return CreateAPIPermission(base_name, NULL, source,
117 api_permissions, error, NULL);
120 } // namespace
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());
129 void APIPermissionSet::insert(APIPermission* permission) {
130 BaseSetOperators<APIPermissionSet>::insert(permission);
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;
152 LOG(WARNING) << "Permission is not a string or single key dict.";
153 continue;
155 base::DictionaryValue::Iterator it(*dict);
156 permission_str = it.key();
157 permission_value = &it.value();
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;
169 if (!CreateAPIPermission(permission_str, permission_value, source,
170 api_permissions, error, unhandled_permissions))
171 return false;
173 return true;
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);
186 } // namespace extensions