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 // Helper object that is implicitly constructible from both a PermissionID and
22 // from an APIPermission::ID.
23 struct PermissionIDCompareHelper {
PermissionIDCompareHelperextensions::__anona76ac7830111::PermissionIDCompareHelper24 PermissionIDCompareHelper(const PermissionID& id) : id(id.id()) {}
PermissionIDCompareHelperextensions::__anona76ac7830111::PermissionIDCompareHelper25 PermissionIDCompareHelper(const APIPermission::ID id) : id(id) {}
26
27 APIPermission::ID id;
28 };
29
CreateAPIPermission(const std::string & permission_str,const base::Value * permission_value,APIPermissionSet::ParseSource source,APIPermissionSet * api_permissions,base::string16 * error,std::vector<std::string> * unhandled_permissions)30 bool CreateAPIPermission(
31 const std::string& permission_str,
32 const base::Value* permission_value,
33 APIPermissionSet::ParseSource source,
34 APIPermissionSet* api_permissions,
35 base::string16* error,
36 std::vector<std::string>* unhandled_permissions) {
37
38 const APIPermissionInfo* permission_info =
39 PermissionsInfo::GetInstance()->GetByName(permission_str);
40 if (permission_info) {
41 std::unique_ptr<APIPermission> permission(
42 permission_info->CreateAPIPermission());
43 if (source != APIPermissionSet::kAllowInternalPermissions &&
44 permission_info->is_internal()) {
45 // An internal permission specified in permissions list is an error.
46 if (error) {
47 *error = ErrorUtils::FormatErrorMessageUTF16(
48 errors::kPermissionNotAllowedInManifest, permission_str);
49 }
50 return false;
51 }
52
53 std::string error_details;
54 if (!permission->FromValue(permission_value, &error_details,
55 unhandled_permissions)) {
56 if (error) {
57 if (error_details.empty()) {
58 *error = ErrorUtils::FormatErrorMessageUTF16(
59 errors::kInvalidPermission,
60 permission_info->name());
61 } else {
62 *error = ErrorUtils::FormatErrorMessageUTF16(
63 errors::kInvalidPermissionWithDetail,
64 permission_info->name(),
65 error_details);
66 }
67 return false;
68 }
69 LOG(WARNING) << "Parse permission failed.";
70 } else {
71 api_permissions->insert(std::move(permission));
72 }
73 return true;
74 }
75
76 if (unhandled_permissions)
77 unhandled_permissions->push_back(permission_str);
78 else
79 LOG(WARNING) << "Unknown permission[" << permission_str << "].";
80
81 return true;
82 }
83
ParseChildPermissions(const std::string & base_name,const base::Value * permission_value,APIPermissionSet::ParseSource source,APIPermissionSet * api_permissions,base::string16 * error,std::vector<std::string> * unhandled_permissions)84 bool ParseChildPermissions(const std::string& base_name,
85 const base::Value* permission_value,
86 APIPermissionSet::ParseSource source,
87 APIPermissionSet* api_permissions,
88 base::string16* error,
89 std::vector<std::string>* unhandled_permissions) {
90 if (permission_value) {
91 if (!permission_value->is_list()) {
92 if (error) {
93 *error = ErrorUtils::FormatErrorMessageUTF16(
94 errors::kInvalidPermission, base_name);
95 return false;
96 }
97 LOG(WARNING) << "Permission value is not a list.";
98 // Failed to parse, but since error is NULL, failures are not fatal so
99 // return true here anyway.
100 return true;
101 }
102
103 base::Value::ConstListView list_view = permission_value->GetList();
104 for (size_t i = 0; i < list_view.size(); ++i) {
105 std::string permission_str;
106 if (!list_view[i].is_string()) {
107 // permission should be a string
108 if (error) {
109 *error = ErrorUtils::FormatErrorMessageUTF16(
110 errors::kInvalidPermission,
111 base_name + '.' + base::NumberToString(i));
112 return false;
113 }
114 LOG(WARNING) << "Permission is not a string.";
115 continue;
116 }
117
118 if (!CreateAPIPermission(base_name + '.' + list_view[i].GetString(),
119 nullptr, source, api_permissions, error,
120 unhandled_permissions))
121 return false;
122 }
123 }
124
125 return CreateAPIPermission(base_name, nullptr, source, api_permissions, error,
126 nullptr);
127 }
128
129 } // namespace
130
insert(APIPermission::ID id)131 void APIPermissionSet::insert(APIPermission::ID id) {
132 const APIPermissionInfo* permission_info =
133 PermissionsInfo::GetInstance()->GetByID(id);
134 DCHECK(permission_info);
135 insert(permission_info->CreateAPIPermission());
136 }
137
insert(std::unique_ptr<APIPermission> permission)138 void APIPermissionSet::insert(std::unique_ptr<APIPermission> permission) {
139 BaseSetOperators<APIPermissionSet>::insert(std::move(permission));
140 }
141
142 // static
ParseFromJSON(const base::Value * permissions,APIPermissionSet::ParseSource source,APIPermissionSet * api_permissions,base::string16 * error,std::vector<std::string> * unhandled_permissions)143 bool APIPermissionSet::ParseFromJSON(
144 const base::Value* permissions,
145 APIPermissionSet::ParseSource source,
146 APIPermissionSet* api_permissions,
147 base::string16* error,
148 std::vector<std::string>* unhandled_permissions) {
149 if (!permissions->is_list()) {
150 if (error) {
151 *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermission,
152 "<root>");
153 return false;
154 }
155 LOG(WARNING) << "Root Permissions value is not a list.";
156 // Failed to parse, but since error is NULL, failures are not fatal so
157 // return true here anyway.
158 return true;
159 }
160 base::Value::ConstListView list_view = permissions->GetList();
161 for (size_t i = 0; i < list_view.size(); ++i) {
162 std::string permission_str;
163 const base::Value* permission_value = nullptr;
164 // permission should be a string or a single key dict.
165 if (list_view[i].is_string()) {
166 permission_str = list_view[i].GetString();
167 } else if (list_view[i].is_dict() && list_view[i].DictSize() == 1) {
168 auto dict_iter = list_view[i].DictItems().begin();
169 permission_str = dict_iter->first;
170 permission_value = &dict_iter->second;
171 } else {
172 if (error) {
173 *error = ErrorUtils::FormatErrorMessageUTF16(errors::kInvalidPermission,
174 base::NumberToString(i));
175 return false;
176 }
177 LOG(WARNING) << "Permission is not a string or single key dict.";
178 continue;
179 }
180
181 // Check if this permission is a special case where its value should
182 // be treated as a list of child permissions.
183 if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) {
184 if (!ParseChildPermissions(permission_str, permission_value, source,
185 api_permissions, error, unhandled_permissions))
186 return false;
187 continue;
188 }
189
190 if (!CreateAPIPermission(permission_str, permission_value, source,
191 api_permissions, error, unhandled_permissions))
192 return false;
193 }
194 return true;
195 }
196
PermissionID(APIPermission::ID id)197 PermissionID::PermissionID(APIPermission::ID id)
198 : std::pair<APIPermission::ID, base::string16>(id, base::string16()) {
199 }
200
PermissionID(APIPermission::ID id,const base::string16 & parameter)201 PermissionID::PermissionID(APIPermission::ID id,
202 const base::string16& parameter)
203 : std::pair<APIPermission::ID, base::string16>(id, parameter) {
204 }
205
~PermissionID()206 PermissionID::~PermissionID() {
207 }
208
PermissionIDSet()209 PermissionIDSet::PermissionIDSet() {
210 }
211
PermissionIDSet(std::initializer_list<APIPermission::ID> permissions)212 PermissionIDSet::PermissionIDSet(
213 std::initializer_list<APIPermission::ID> permissions) {
214 for (auto permission : permissions) {
215 permissions_.insert(PermissionID(permission));
216 }
217 }
218
219 PermissionIDSet::PermissionIDSet(const PermissionIDSet& other) = default;
220
~PermissionIDSet()221 PermissionIDSet::~PermissionIDSet() {
222 }
223
insert(APIPermission::ID permission_id)224 void PermissionIDSet::insert(APIPermission::ID permission_id) {
225 insert(permission_id, base::string16());
226 }
227
insert(APIPermission::ID permission_id,const base::string16 & permission_detail)228 void PermissionIDSet::insert(APIPermission::ID permission_id,
229 const base::string16& permission_detail) {
230 permissions_.insert(PermissionID(permission_id, permission_detail));
231 }
232
InsertAll(const PermissionIDSet & permission_set)233 void PermissionIDSet::InsertAll(const PermissionIDSet& permission_set) {
234 for (const auto& permission : permission_set.permissions_) {
235 permissions_.insert(permission);
236 }
237 }
238
erase(APIPermission::ID permission_id)239 void PermissionIDSet::erase(APIPermission::ID permission_id) {
240 auto lower_bound = permissions_.lower_bound(PermissionID(permission_id));
241 auto upper_bound = lower_bound;
242 while (upper_bound != permissions_.end() &&
243 upper_bound->id() == permission_id) {
244 ++upper_bound;
245 }
246 permissions_.erase(lower_bound, upper_bound);
247 }
248
GetAllPermissionParameters() const249 std::vector<base::string16> PermissionIDSet::GetAllPermissionParameters()
250 const {
251 std::vector<base::string16> params;
252 for (const auto& permission : permissions_) {
253 params.push_back(permission.parameter());
254 }
255 return params;
256 }
257
ContainsID(PermissionID permission_id) const258 bool PermissionIDSet::ContainsID(PermissionID permission_id) const {
259 auto it = permissions_.lower_bound(permission_id);
260 return it != permissions_.end() && it->id() == permission_id.id();
261 }
262
ContainsID(APIPermission::ID permission_id) const263 bool PermissionIDSet::ContainsID(APIPermission::ID permission_id) const {
264 return ContainsID(PermissionID(permission_id));
265 }
266
ContainsAllIDs(const std::set<APIPermission::ID> & permission_ids) const267 bool PermissionIDSet::ContainsAllIDs(
268 const std::set<APIPermission::ID>& permission_ids) const {
269 return std::includes(permissions_.begin(), permissions_.end(),
270 permission_ids.begin(), permission_ids.end(),
271 [] (const PermissionIDCompareHelper& lhs,
272 const PermissionIDCompareHelper& rhs) {
273 return lhs.id < rhs.id;
274 });
275 }
276
ContainsAnyID(const std::set<APIPermission::ID> & permission_ids) const277 bool PermissionIDSet::ContainsAnyID(
278 const std::set<APIPermission::ID>& permission_ids) const {
279 for (APIPermission::ID id : permission_ids) {
280 if (ContainsID(id))
281 return true;
282 }
283 return false;
284 }
285
ContainsAnyID(const PermissionIDSet & other) const286 bool PermissionIDSet::ContainsAnyID(const PermissionIDSet& other) const {
287 for (const auto& id : other) {
288 if (ContainsID(id))
289 return true;
290 }
291 return false;
292 }
293
GetAllPermissionsWithID(APIPermission::ID permission_id) const294 PermissionIDSet PermissionIDSet::GetAllPermissionsWithID(
295 APIPermission::ID permission_id) const {
296 PermissionIDSet subset;
297 auto it = permissions_.lower_bound(PermissionID(permission_id));
298 while (it != permissions_.end() && it->id() == permission_id) {
299 subset.permissions_.insert(*it);
300 ++it;
301 }
302 return subset;
303 }
304
GetAllPermissionsWithIDs(const std::set<APIPermission::ID> & permission_ids) const305 PermissionIDSet PermissionIDSet::GetAllPermissionsWithIDs(
306 const std::set<APIPermission::ID>& permission_ids) const {
307 PermissionIDSet subset;
308 for (const auto& permission : permissions_) {
309 if (base::Contains(permission_ids, permission.id())) {
310 subset.permissions_.insert(permission);
311 }
312 }
313 return subset;
314 }
315
Includes(const PermissionIDSet & subset) const316 bool PermissionIDSet::Includes(const PermissionIDSet& subset) const {
317 return base::STLIncludes(permissions_, subset.permissions_);
318 }
319
Equals(const PermissionIDSet & set) const320 bool PermissionIDSet::Equals(const PermissionIDSet& set) const {
321 return permissions_ == set.permissions_;
322 }
323
324 // static
Difference(const PermissionIDSet & set_1,const PermissionIDSet & set_2)325 PermissionIDSet PermissionIDSet::Difference(const PermissionIDSet& set_1,
326 const PermissionIDSet& set_2) {
327 return PermissionIDSet(base::STLSetDifference<std::set<PermissionID>>(
328 set_1.permissions_, set_2.permissions_));
329 }
330
size() const331 size_t PermissionIDSet::size() const {
332 return permissions_.size();
333 }
334
empty() const335 bool PermissionIDSet::empty() const {
336 return permissions_.empty();
337 }
338
PermissionIDSet(const std::set<PermissionID> & permissions)339 PermissionIDSet::PermissionIDSet(const std::set<PermissionID>& permissions)
340 : permissions_(permissions) {
341 }
342
343 } // namespace extensions
344