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
;
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.
38 *error
= ErrorUtils::FormatErrorMessageUTF16(
39 errors::kPermissionNotAllowedInManifest
, permission_str
);
44 std::string error_details
;
45 if (!permission
->FromValue(permission_value
, &error_details
,
46 unhandled_permissions
)) {
48 if (error_details
.empty()) {
49 *error
= ErrorUtils::FormatErrorMessageUTF16(
50 errors::kInvalidPermission
,
51 permission_info
->name());
53 *error
= ErrorUtils::FormatErrorMessageUTF16(
54 errors::kInvalidPermissionWithDetail
,
55 permission_info
->name(),
60 LOG(WARNING
) << "Parse permission failed.";
62 api_permissions
->insert(permission
.release());
67 if (unhandled_permissions
)
68 unhandled_permissions
->push_back(permission_str
);
70 LOG(WARNING
) << "Unknown permission[" << permission_str
<< "].";
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
)) {
85 *error
= ErrorUtils::FormatErrorMessageUTF16(
86 errors::kInvalidPermission
, base_name
);
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.
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
100 *error
= ErrorUtils::FormatErrorMessageUTF16(
101 errors::kInvalidPermission
,
102 base_name
+ '.' + base::IntToString(i
));
105 LOG(WARNING
) << "Permission is not a string.";
109 if (!CreateAPIPermission(
110 base_name
+ '.' + permission_str
, NULL
, source
,
111 api_permissions
, error
, unhandled_permissions
))
116 return CreateAPIPermission(base_name
, NULL
, source
,
117 api_permissions
, error
, NULL
);
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
);
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) {
148 *error
= ErrorUtils::FormatErrorMessageUTF16(
149 errors::kInvalidPermission
, base::IntToString(i
));
152 LOG(WARNING
) << "Permission is not a string or single key dict.";
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
))
169 if (!CreateAPIPermission(permission_str
, permission_value
, source
,
170 api_permissions
, error
, unhandled_permissions
))
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