1 // Copyright (c) 2012 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 "chrome/common/extensions/permissions/api_permission_set.h"
7 #include "base/logging.h"
8 #include "base/string_number_conversions.h"
9 #include "base/values.h"
10 #include "chrome/common/extensions/extension_error_utils.h"
11 #include "chrome/common/extensions/extension_manifest_constants.h"
12 #include "chrome/common/extensions/permissions/permissions_info.h"
14 namespace errors
= extension_manifest_errors
;
18 using extensions::PermissionsInfo
;
19 using extensions::APIPermission
;
20 using extensions::APIPermissionInfo
;
21 using extensions::APIPermissionSet
;
23 bool CreateAPIPermission(
24 const std::string
& permission_str
,
25 const base::Value
* permission_value
,
26 APIPermissionSet
* api_permissions
,
28 std::vector
<std::string
>* unhandled_permissions
) {
29 PermissionsInfo
* info
= PermissionsInfo::GetInstance();
31 const APIPermissionInfo
* permission_info
= info
->GetByName(permission_str
);
32 if (permission_info
) {
33 scoped_ptr
<APIPermission
> permission(
34 permission_info
->CreateAPIPermission());
35 if (!permission
->FromValue(permission_value
)) {
37 *error
= ExtensionErrorUtils::FormatErrorMessageUTF16(
38 errors::kInvalidPermission
, permission_info
->name());
41 LOG(WARNING
) << "Parse permission failed.";
43 api_permissions
->insert(permission
.release());
48 if (unhandled_permissions
)
49 unhandled_permissions
->push_back(permission_str
);
51 LOG(WARNING
) << "Unknown permission[" << permission_str
<< "].";
56 bool ParseChildPermissions(const std::string
& base_name
,
57 const Value
* permission_value
,
58 APIPermissionSet
* api_permissions
,
60 std::vector
<std::string
>* unhandled_permissions
) {
61 if (permission_value
) {
62 const ListValue
* permissions
;
63 if (!permission_value
->GetAsList(&permissions
)) {
65 *error
= ExtensionErrorUtils::FormatErrorMessageUTF16(
66 errors::kInvalidPermission
, base_name
);
69 LOG(WARNING
) << "Permission value is not a list.";
70 // Failed to parse, but since error is NULL, failures are not fatal so
71 // return true here anyway.
75 for (size_t i
= 0; i
< permissions
->GetSize(); ++i
) {
76 std::string permission_str
;
77 if (!permissions
->GetString(i
, &permission_str
)) {
78 // permission should be a string
80 *error
= ExtensionErrorUtils::FormatErrorMessageUTF16(
81 errors::kInvalidPermission
,
82 base_name
+ '.' + base::IntToString(i
));
85 LOG(WARNING
) << "Permission is not a string.";
89 if (!CreateAPIPermission(base_name
+ '.' + permission_str
, NULL
,
90 api_permissions
, error
, unhandled_permissions
))
95 return CreateAPIPermission(base_name
, NULL
, api_permissions
, error
, NULL
);
100 namespace extensions
{
102 APIPermissionSet::APIPermissionSet() {
105 APIPermissionSet::APIPermissionSet(const APIPermissionSet
& set
) {
106 this->operator=(set
);
109 APIPermissionSet::~APIPermissionSet() {
112 APIPermissionSet::const_iterator::const_iterator(
113 const APIPermissionMap::const_iterator
& it
)
117 APIPermissionSet::const_iterator::const_iterator(
118 const const_iterator
& ids_it
)
122 APIPermissionSet
& APIPermissionSet::operator=(const APIPermissionSet
& rhs
) {
123 const_iterator it
= rhs
.begin();
124 const const_iterator end
= rhs
.end();
132 bool APIPermissionSet::operator==(const APIPermissionSet
& rhs
) const {
133 const_iterator it
= begin();
134 const_iterator rhs_it
= rhs
.begin();
135 const_iterator it_end
= end();
136 const_iterator rhs_it_end
= rhs
.end();
138 while (it
!= it_end
&& rhs_it
!= rhs_it_end
) {
139 if (!it
->Equal(*rhs_it
))
144 return it
== it_end
&& rhs_it
== rhs_it_end
;
147 void APIPermissionSet::insert(APIPermission::ID id
) {
148 const APIPermissionInfo
* permission_info
=
149 PermissionsInfo::GetInstance()->GetByID(id
);
150 insert(permission_info
->CreateAPIPermission());
153 void APIPermissionSet::insert(
154 APIPermission
* permission
) {
155 map_
[permission
->id()].reset(permission
);
158 bool APIPermissionSet::Contains(const APIPermissionSet
& rhs
) const {
159 APIPermissionSet::const_iterator it1
= begin();
160 APIPermissionSet::const_iterator it2
= rhs
.begin();
161 APIPermissionSet::const_iterator end1
= end();
162 APIPermissionSet::const_iterator end2
= rhs
.end();
164 while (it1
!= end1
&& it2
!= end2
) {
165 if (it1
->id() > it2
->id()) {
167 } else if (it1
->id() < it2
->id()) {
170 if (!it1
->Contains(*it2
))
180 void APIPermissionSet::Difference(
181 const APIPermissionSet
& set1
,
182 const APIPermissionSet
& set2
,
183 APIPermissionSet
* set3
) {
187 APIPermissionSet::const_iterator it1
= set1
.begin();
188 APIPermissionSet::const_iterator it2
= set2
.begin();
189 const APIPermissionSet::const_iterator end1
= set1
.end();
190 const APIPermissionSet::const_iterator end2
= set2
.end();
192 while (it1
!= end1
&& it2
!= end2
) {
193 if (it1
->id() < it2
->id()) {
194 set3
->insert(it1
->Clone());
196 } else if (it1
->id() > it2
->id()) {
199 APIPermission
* p
= it1
->Diff(*it2
);
207 while (it1
!= end1
) {
208 set3
->insert(it1
->Clone());
213 void APIPermissionSet::Intersection(
214 const APIPermissionSet
& set1
,
215 const APIPermissionSet
& set2
,
216 APIPermissionSet
* set3
) {
220 APIPermissionSet::const_iterator it1
= set1
.begin();
221 APIPermissionSet::const_iterator it2
= set2
.begin();
222 const APIPermissionSet::const_iterator end1
= set1
.end();
223 const APIPermissionSet::const_iterator end2
= set2
.end();
225 while (it1
!= end1
&& it2
!= end2
) {
226 if (it1
->id() < it2
->id()) {
228 } else if (it1
->id() > it2
->id()) {
231 APIPermission
* p
= it1
->Intersect(*it2
);
240 void APIPermissionSet::Union(
241 const APIPermissionSet
& set1
,
242 const APIPermissionSet
& set2
,
243 APIPermissionSet
* set3
) {
247 APIPermissionSet::const_iterator it1
= set1
.begin();
248 APIPermissionSet::const_iterator it2
= set2
.begin();
249 const APIPermissionSet::const_iterator end1
= set1
.end();
250 const APIPermissionSet::const_iterator end2
= set2
.end();
254 while (it2
!= end2
) {
255 set3
->insert(it2
->Clone());
261 while (it1
!= end1
) {
262 set3
->insert(it1
->Clone());
267 if (it1
->id() < it2
->id()) {
268 set3
->insert(it1
->Clone());
270 } else if (it1
->id() > it2
->id()) {
271 set3
->insert(it2
->Clone());
274 set3
->insert(it1
->Union(*it2
));
282 bool APIPermissionSet::ParseFromJSON(
283 const ListValue
* permissions
,
284 APIPermissionSet
* api_permissions
,
286 std::vector
<std::string
>* unhandled_permissions
) {
287 PermissionsInfo
* info
= PermissionsInfo::GetInstance();
288 for (size_t i
= 0; i
< permissions
->GetSize(); ++i
) {
289 std::string permission_str
;
290 const base::Value
* permission_value
= NULL
;
291 if (!permissions
->GetString(i
, &permission_str
)) {
292 const base::DictionaryValue
* dict
= NULL
;
293 // permission should be a string or a single key dict.
294 if (!permissions
->GetDictionary(i
, &dict
) || dict
->size() != 1) {
296 *error
= ExtensionErrorUtils::FormatErrorMessageUTF16(
297 errors::kInvalidPermission
, base::IntToString(i
));
300 LOG(WARNING
) << "Permission is not a string or single key dict.";
303 base::DictionaryValue::Iterator
it(*dict
);
304 permission_str
= it
.key();
305 permission_value
= &it
.value();
308 // Check if this permission is a special case where its value should
309 // be treated as a list of child permissions.
310 if (info
->HasChildPermissions(permission_str
)) {
311 if (!ParseChildPermissions(permission_str
, permission_value
,
312 api_permissions
, error
, unhandled_permissions
))
317 if (!CreateAPIPermission(permission_str
, permission_value
,
318 api_permissions
, error
, unhandled_permissions
))
324 } // namespace extensions