Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / common / permissions / api_permission_set.cc
blob9f6df2f45f85ad8557b3afbe1883a4c340811b05
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 // Helper object that is implicitly constructible from both a PermissionID and
22 // from an APIPermission::ID.
23 struct PermissionIDCompareHelper {
24 PermissionIDCompareHelper(const PermissionID& id) : id(id.id()) {}
25 PermissionIDCompareHelper(const APIPermission::ID id) : id(id) {}
27 APIPermission::ID id;
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) {
38 const APIPermissionInfo* permission_info =
39 PermissionsInfo::GetInstance()->GetByName(permission_str);
40 if (permission_info) {
41 scoped_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);
50 return false;
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);
67 return false;
69 LOG(WARNING) << "Parse permission failed.";
70 } else {
71 api_permissions->insert(permission.release());
73 return true;
76 if (unhandled_permissions)
77 unhandled_permissions->push_back(permission_str);
78 else
79 LOG(WARNING) << "Unknown permission[" << permission_str << "].";
81 return true;
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 const base::ListValue* permissions;
92 if (!permission_value->GetAsList(&permissions)) {
93 if (error) {
94 *error = ErrorUtils::FormatErrorMessageUTF16(
95 errors::kInvalidPermission, base_name);
96 return false;
98 LOG(WARNING) << "Permission value is not a list.";
99 // Failed to parse, but since error is NULL, failures are not fatal so
100 // return true here anyway.
101 return true;
104 for (size_t i = 0; i < permissions->GetSize(); ++i) {
105 std::string permission_str;
106 if (!permissions->GetString(i, &permission_str)) {
107 // permission should be a string
108 if (error) {
109 *error = ErrorUtils::FormatErrorMessageUTF16(
110 errors::kInvalidPermission,
111 base_name + '.' + base::IntToString(i));
112 return false;
114 LOG(WARNING) << "Permission is not a string.";
115 continue;
118 if (!CreateAPIPermission(
119 base_name + '.' + permission_str, NULL, source,
120 api_permissions, error, unhandled_permissions))
121 return false;
125 return CreateAPIPermission(base_name, NULL, source,
126 api_permissions, error, NULL);
129 } // namespace
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());
138 void APIPermissionSet::insert(APIPermission* permission) {
139 BaseSetOperators<APIPermissionSet>::insert(permission);
142 // static
143 bool APIPermissionSet::ParseFromJSON(
144 const base::ListValue* permissions,
145 APIPermissionSet::ParseSource source,
146 APIPermissionSet* api_permissions,
147 base::string16* error,
148 std::vector<std::string>* unhandled_permissions) {
149 for (size_t i = 0; i < permissions->GetSize(); ++i) {
150 std::string permission_str;
151 const base::Value* permission_value = NULL;
152 if (!permissions->GetString(i, &permission_str)) {
153 const base::DictionaryValue* dict = NULL;
154 // permission should be a string or a single key dict.
155 if (!permissions->GetDictionary(i, &dict) || dict->size() != 1) {
156 if (error) {
157 *error = ErrorUtils::FormatErrorMessageUTF16(
158 errors::kInvalidPermission, base::IntToString(i));
159 return false;
161 LOG(WARNING) << "Permission is not a string or single key dict.";
162 continue;
164 base::DictionaryValue::Iterator it(*dict);
165 permission_str = it.key();
166 permission_value = &it.value();
169 // Check if this permission is a special case where its value should
170 // be treated as a list of child permissions.
171 if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) {
172 if (!ParseChildPermissions(permission_str, permission_value, source,
173 api_permissions, error, unhandled_permissions))
174 return false;
175 continue;
178 if (!CreateAPIPermission(permission_str, permission_value, source,
179 api_permissions, error, unhandled_permissions))
180 return false;
182 return true;
185 PermissionID::PermissionID(APIPermission::ID id)
186 : std::pair<APIPermission::ID, base::string16>(id, base::string16()) {
189 PermissionID::PermissionID(APIPermission::ID id,
190 const base::string16& parameter)
191 : std::pair<APIPermission::ID, base::string16>(id, parameter) {
194 PermissionID::~PermissionID() {
197 PermissionIDSet::PermissionIDSet() {
200 PermissionIDSet::~PermissionIDSet() {
203 void PermissionIDSet::insert(APIPermission::ID permission_id) {
204 insert(permission_id, base::string16());
207 void PermissionIDSet::insert(APIPermission::ID permission_id,
208 const base::string16& permission_detail) {
209 permissions_.insert(PermissionID(permission_id, permission_detail));
212 void PermissionIDSet::InsertAll(const PermissionIDSet& permission_set) {
213 for (const auto& permission : permission_set.permissions_) {
214 permissions_.insert(permission);
218 void PermissionIDSet::erase(APIPermission::ID permission_id) {
219 permissions_.erase(PermissionID(permission_id));
222 std::vector<base::string16> PermissionIDSet::GetAllPermissionParameters()
223 const {
224 std::vector<base::string16> params;
225 for (const auto& permission : permissions_) {
226 params.push_back(permission.parameter());
228 return params;
231 bool PermissionIDSet::ContainsID(APIPermission::ID permission_id) const {
232 auto it = permissions_.lower_bound(PermissionID(permission_id));
233 return it != permissions_.end() && it->id() == permission_id;
236 bool PermissionIDSet::ContainsAllIDs(
237 const std::set<APIPermission::ID>& permission_ids) const {
238 return std::includes(permissions_.begin(), permissions_.end(),
239 permission_ids.begin(), permission_ids.end(),
240 [] (const PermissionIDCompareHelper& lhs,
241 const PermissionIDCompareHelper& rhs) {
242 return lhs.id < rhs.id;
246 bool PermissionIDSet::ContainsAnyID(
247 const std::set<APIPermission::ID>& permission_ids) const {
248 for (APIPermission::ID id : permission_ids) {
249 if (ContainsID(id))
250 return true;
252 return false;
255 PermissionIDSet PermissionIDSet::GetAllPermissionsWithID(
256 APIPermission::ID permission_id) const {
257 PermissionIDSet subset;
258 auto it = permissions_.lower_bound(PermissionID(permission_id));
259 while (it != permissions_.end() && it->id() == permission_id) {
260 subset.permissions_.insert(*it);
261 ++it;
263 return subset;
266 PermissionIDSet PermissionIDSet::GetAllPermissionsWithIDs(
267 const std::set<APIPermission::ID>& permission_ids) const {
268 PermissionIDSet subset;
269 for (const auto& permission : permissions_) {
270 if (ContainsKey(permission_ids, permission.id())) {
271 subset.permissions_.insert(permission);
274 return subset;
277 bool PermissionIDSet::Includes(const PermissionIDSet& subset) const {
278 return base::STLIncludes(permissions_, subset.permissions_);
281 bool PermissionIDSet::Equals(const PermissionIDSet& set) const {
282 return permissions_ == set.permissions_;
285 // static
286 PermissionIDSet PermissionIDSet::Difference(const PermissionIDSet& set_1,
287 const PermissionIDSet& set_2) {
288 return PermissionIDSet(base::STLSetDifference<std::set<PermissionID>>(
289 set_1.permissions_, set_2.permissions_));
292 size_t PermissionIDSet::size() const {
293 return permissions_.size();
296 bool PermissionIDSet::empty() const {
297 return permissions_.empty();
300 PermissionIDSet::PermissionIDSet(const std::set<PermissionID>& permissions)
301 : permissions_(permissions) {
304 } // namespace extensions