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
)) {
47 if (error_details
.empty()) {
48 *error
= ErrorUtils::FormatErrorMessageUTF16(
49 errors::kInvalidPermission
,
50 permission_info
->name());
52 *error
= ErrorUtils::FormatErrorMessageUTF16(
53 errors::kInvalidPermissionWithDetail
,
54 permission_info
->name(),
59 LOG(WARNING
) << "Parse permission failed.";
61 api_permissions
->insert(permission
.release());
66 if (unhandled_permissions
)
67 unhandled_permissions
->push_back(permission_str
);
69 LOG(WARNING
) << "Unknown permission[" << permission_str
<< "].";
74 bool ParseChildPermissions(const std::string
& base_name
,
75 const base::Value
* permission_value
,
76 APIPermissionSet::ParseSource source
,
77 APIPermissionSet
* api_permissions
,
78 base::string16
* error
,
79 std::vector
<std::string
>* unhandled_permissions
) {
80 if (permission_value
) {
81 const base::ListValue
* permissions
;
82 if (!permission_value
->GetAsList(&permissions
)) {
84 *error
= ErrorUtils::FormatErrorMessageUTF16(
85 errors::kInvalidPermission
, base_name
);
88 LOG(WARNING
) << "Permission value is not a list.";
89 // Failed to parse, but since error is NULL, failures are not fatal so
90 // return true here anyway.
94 for (size_t i
= 0; i
< permissions
->GetSize(); ++i
) {
95 std::string permission_str
;
96 if (!permissions
->GetString(i
, &permission_str
)) {
97 // permission should be a string
99 *error
= ErrorUtils::FormatErrorMessageUTF16(
100 errors::kInvalidPermission
,
101 base_name
+ '.' + base::IntToString(i
));
104 LOG(WARNING
) << "Permission is not a string.";
108 if (!CreateAPIPermission(
109 base_name
+ '.' + permission_str
, NULL
, source
,
110 api_permissions
, error
, unhandled_permissions
))
115 return CreateAPIPermission(base_name
, NULL
, source
,
116 api_permissions
, error
, NULL
);
121 void APIPermissionSet::insert(APIPermission::ID id
) {
122 const APIPermissionInfo
* permission_info
=
123 PermissionsInfo::GetInstance()->GetByID(id
);
124 DCHECK(permission_info
);
125 insert(permission_info
->CreateAPIPermission());
128 void APIPermissionSet::insert(APIPermission
* permission
) {
129 BaseSetOperators
<APIPermissionSet
>::insert(permission
);
133 bool APIPermissionSet::ParseFromJSON(
134 const base::ListValue
* permissions
,
135 APIPermissionSet::ParseSource source
,
136 APIPermissionSet
* api_permissions
,
137 base::string16
* error
,
138 std::vector
<std::string
>* unhandled_permissions
) {
139 for (size_t i
= 0; i
< permissions
->GetSize(); ++i
) {
140 std::string permission_str
;
141 const base::Value
* permission_value
= NULL
;
142 if (!permissions
->GetString(i
, &permission_str
)) {
143 const base::DictionaryValue
* dict
= NULL
;
144 // permission should be a string or a single key dict.
145 if (!permissions
->GetDictionary(i
, &dict
) || dict
->size() != 1) {
147 *error
= ErrorUtils::FormatErrorMessageUTF16(
148 errors::kInvalidPermission
, base::IntToString(i
));
151 LOG(WARNING
) << "Permission is not a string or single key dict.";
154 base::DictionaryValue::Iterator
it(*dict
);
155 permission_str
= it
.key();
156 permission_value
= &it
.value();
159 // Check if this permission is a special case where its value should
160 // be treated as a list of child permissions.
161 if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str
)) {
162 if (!ParseChildPermissions(permission_str
, permission_value
, source
,
163 api_permissions
, error
, unhandled_permissions
))
168 if (!CreateAPIPermission(permission_str
, permission_value
, source
,
169 api_permissions
, error
, unhandled_permissions
))
175 void APIPermissionSet::AddImpliedPermissions() {
176 // The fileSystem.write and fileSystem.directory permissions imply
177 // fileSystem.writeDirectory.
178 // TODO(sammc): Remove this. See http://crbug.com/284849.
179 if (ContainsKey(map(), APIPermission::kFileSystemWrite
) &&
180 ContainsKey(map(), APIPermission::kFileSystemDirectory
)) {
181 insert(APIPermission::kFileSystemWriteDirectory
);
185 } // namespace extensions