Extensions: Remove the legacy GetMessages/HasMessages
[chromium-blink-merge.git] / extensions / common / permissions / api_permission_set.cc
blob82d2faafbdbaa6f06da74b72e7548e63d9c30f7c
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 void APIPermissionSet::AddImpliedPermissions() {
186 // The fileSystem.write and fileSystem.directory permissions imply
187 // fileSystem.writeDirectory.
188 // Has a corresponding rule in ChromePermissionMessageProvider.
189 // TODO(sammc): Remove this. See http://crbug.com/284849.
190 if (ContainsKey(map(), APIPermission::kFileSystemWrite) &&
191 ContainsKey(map(), APIPermission::kFileSystemDirectory)) {
192 insert(APIPermission::kFileSystemWriteDirectory);
196 PermissionID::PermissionID(APIPermission::ID id)
197 : std::pair<APIPermission::ID, base::string16>(id, base::string16()) {
200 PermissionID::PermissionID(APIPermission::ID id,
201 const base::string16& parameter)
202 : std::pair<APIPermission::ID, base::string16>(id, parameter) {
205 PermissionID::~PermissionID() {
208 PermissionIDSet::PermissionIDSet() {
211 PermissionIDSet::~PermissionIDSet() {
214 void PermissionIDSet::insert(APIPermission::ID permission_id) {
215 insert(permission_id, base::string16());
218 void PermissionIDSet::insert(APIPermission::ID permission_id,
219 const base::string16& permission_detail) {
220 permissions_.insert(PermissionID(permission_id, permission_detail));
223 void PermissionIDSet::InsertAll(const PermissionIDSet& permission_set) {
224 for (const auto& permission : permission_set.permissions_) {
225 permissions_.insert(permission);
229 void PermissionIDSet::erase(APIPermission::ID permission_id) {
230 permissions_.erase(PermissionID(permission_id));
233 std::vector<base::string16> PermissionIDSet::GetAllPermissionParameters()
234 const {
235 std::vector<base::string16> params;
236 for (const auto& permission : permissions_) {
237 params.push_back(permission.parameter());
239 return params;
242 bool PermissionIDSet::ContainsID(APIPermission::ID permission_id) const {
243 auto it = permissions_.lower_bound(PermissionID(permission_id));
244 return it != permissions_.end() && it->id() == permission_id;
247 bool PermissionIDSet::ContainsAllIDs(
248 const std::set<APIPermission::ID>& permission_ids) const {
249 return std::includes(permissions_.begin(), permissions_.end(),
250 permission_ids.begin(), permission_ids.end(),
251 [] (const PermissionIDCompareHelper& lhs,
252 const PermissionIDCompareHelper& rhs) {
253 return lhs.id < rhs.id;
257 PermissionIDSet PermissionIDSet::GetAllPermissionsWithIDs(
258 const std::set<APIPermission::ID>& permission_ids) const {
259 PermissionIDSet subset;
260 for (const auto& permission : permissions_) {
261 if (ContainsKey(permission_ids, permission.id())) {
262 subset.permissions_.insert(permission);
265 return subset;
268 bool PermissionIDSet::Includes(const PermissionIDSet& subset) const {
269 return base::STLIncludes(permissions_, subset.permissions_);
272 bool PermissionIDSet::Equals(const PermissionIDSet& set) const {
273 return permissions_ == set.permissions_;
276 // static
277 PermissionIDSet PermissionIDSet::Difference(const PermissionIDSet& set_1,
278 const PermissionIDSet& set_2) {
279 return PermissionIDSet(base::STLSetDifference<std::set<PermissionID>>(
280 set_1.permissions_, set_2.permissions_));
283 size_t PermissionIDSet::size() const {
284 return permissions_.size();
287 bool PermissionIDSet::empty() const {
288 return permissions_.empty();
291 PermissionIDSet::PermissionIDSet(const std::set<PermissionID>& permissions)
292 : permissions_(permissions) {
295 } // namespace extensions