ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / extensions / common / permissions / api_permission_set.cc
blobe7d54bd13defdb0693ee105aefb3893718d950b6
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 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.
37 if (error) {
38 *error = ErrorUtils::FormatErrorMessageUTF16(
39 errors::kPermissionNotAllowedInManifest, permission_str);
41 return false;
44 std::string error_details;
45 if (!permission->FromValue(permission_value, &error_details,
46 unhandled_permissions)) {
47 if (error) {
48 if (error_details.empty()) {
49 *error = ErrorUtils::FormatErrorMessageUTF16(
50 errors::kInvalidPermission,
51 permission_info->name());
52 } else {
53 *error = ErrorUtils::FormatErrorMessageUTF16(
54 errors::kInvalidPermissionWithDetail,
55 permission_info->name(),
56 error_details);
58 return false;
60 LOG(WARNING) << "Parse permission failed.";
61 } else {
62 api_permissions->insert(permission.release());
64 return true;
67 if (unhandled_permissions)
68 unhandled_permissions->push_back(permission_str);
69 else
70 LOG(WARNING) << "Unknown permission[" << permission_str << "].";
72 return true;
75 bool ParseChildPermissions(const std::string& base_name,
76 const base::Value* permission_value,
77 APIPermissionSet::ParseSource source,
78 APIPermissionSet* api_permissions,
79 base::string16* error,
80 std::vector<std::string>* unhandled_permissions) {
81 if (permission_value) {
82 const base::ListValue* permissions;
83 if (!permission_value->GetAsList(&permissions)) {
84 if (error) {
85 *error = ErrorUtils::FormatErrorMessageUTF16(
86 errors::kInvalidPermission, base_name);
87 return false;
89 LOG(WARNING) << "Permission value is not a list.";
90 // Failed to parse, but since error is NULL, failures are not fatal so
91 // return true here anyway.
92 return true;
95 for (size_t i = 0; i < permissions->GetSize(); ++i) {
96 std::string permission_str;
97 if (!permissions->GetString(i, &permission_str)) {
98 // permission should be a string
99 if (error) {
100 *error = ErrorUtils::FormatErrorMessageUTF16(
101 errors::kInvalidPermission,
102 base_name + '.' + base::IntToString(i));
103 return false;
105 LOG(WARNING) << "Permission is not a string.";
106 continue;
109 if (!CreateAPIPermission(
110 base_name + '.' + permission_str, NULL, source,
111 api_permissions, error, unhandled_permissions))
112 return false;
116 return CreateAPIPermission(base_name, NULL, source,
117 api_permissions, error, NULL);
120 } // namespace
122 void APIPermissionSet::insert(APIPermission::ID id) {
123 const APIPermissionInfo* permission_info =
124 PermissionsInfo::GetInstance()->GetByID(id);
125 DCHECK(permission_info);
126 insert(permission_info->CreateAPIPermission());
129 void APIPermissionSet::insert(APIPermission* permission) {
130 BaseSetOperators<APIPermissionSet>::insert(permission);
133 // static
134 bool APIPermissionSet::ParseFromJSON(
135 const base::ListValue* permissions,
136 APIPermissionSet::ParseSource source,
137 APIPermissionSet* api_permissions,
138 base::string16* error,
139 std::vector<std::string>* unhandled_permissions) {
140 for (size_t i = 0; i < permissions->GetSize(); ++i) {
141 std::string permission_str;
142 const base::Value* permission_value = NULL;
143 if (!permissions->GetString(i, &permission_str)) {
144 const base::DictionaryValue* dict = NULL;
145 // permission should be a string or a single key dict.
146 if (!permissions->GetDictionary(i, &dict) || dict->size() != 1) {
147 if (error) {
148 *error = ErrorUtils::FormatErrorMessageUTF16(
149 errors::kInvalidPermission, base::IntToString(i));
150 return false;
152 LOG(WARNING) << "Permission is not a string or single key dict.";
153 continue;
155 base::DictionaryValue::Iterator it(*dict);
156 permission_str = it.key();
157 permission_value = &it.value();
160 // Check if this permission is a special case where its value should
161 // be treated as a list of child permissions.
162 if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) {
163 if (!ParseChildPermissions(permission_str, permission_value, source,
164 api_permissions, error, unhandled_permissions))
165 return false;
166 continue;
169 if (!CreateAPIPermission(permission_str, permission_value, source,
170 api_permissions, error, unhandled_permissions))
171 return false;
173 return true;
176 void APIPermissionSet::AddImpliedPermissions() {
177 // The fileSystem.write and fileSystem.directory permissions imply
178 // fileSystem.writeDirectory.
179 // Has a corresponding rule in ChromePermissionMessageProvider.
180 // TODO(sammc): Remove this. See http://crbug.com/284849.
181 if (ContainsKey(map(), APIPermission::kFileSystemWrite) &&
182 ContainsKey(map(), APIPermission::kFileSystemDirectory)) {
183 insert(APIPermission::kFileSystemWriteDirectory);
187 PermissionID::PermissionID(APIPermission::ID id)
188 : std::pair<APIPermission::ID, base::string16>(id, base::string16()) {
191 PermissionID::PermissionID(APIPermission::ID id,
192 const base::string16& parameter)
193 : std::pair<APIPermission::ID, base::string16>(id, parameter) {
196 PermissionID::~PermissionID() {
199 PermissionIDSet::PermissionIDSet() : permissions_() {
202 PermissionIDSet::~PermissionIDSet() {
205 void PermissionIDSet::insert(APIPermission::ID permission_id) {
206 permissions_.insert(PermissionID(permission_id, base::string16()));
209 void PermissionIDSet::insert(APIPermission::ID permission_id,
210 base::string16 permission_detail) {
211 permissions_.insert(PermissionID(permission_id, permission_detail));
214 void PermissionIDSet::InsertAll(const PermissionIDSet& permission_set) {
215 for (const auto& permission : permission_set.permissions_) {
216 permissions_.insert(permission);
220 std::vector<base::string16> PermissionIDSet::GetAllPermissionParameters()
221 const {
222 std::vector<base::string16> details;
223 for (const auto& permission : permissions_) {
224 details.push_back(permission.parameter());
226 return details;
229 bool PermissionIDSet::ContainsAllIDs(
230 std::set<APIPermission::ID> permission_ids) {
231 // TODO(sashab): Find a more efficient way to implement this (e.g. store a set
232 // of IDs and use STLIncludes in base/stl_util.h).
233 PermissionIDSet subset;
234 for (const auto& permission_id : permission_ids) {
235 if (!ContainsID(permission_id)) {
236 return false;
239 return true;
242 PermissionIDSet PermissionIDSet::GetAllPermissionsWithIDs(
243 const std::set<APIPermission::ID>& permission_ids) const {
244 PermissionIDSet subset;
245 for (const auto& permission : permissions_) {
246 if (ContainsKey(permission_ids, permission.id())) {
247 subset.permissions_.insert(permission);
250 return subset;
253 bool PermissionIDSet::Includes(const PermissionIDSet& subset) const {
254 return base::STLIncludes<std::set<PermissionID>>(permissions_,
255 subset.permissions_);
258 // static
259 PermissionIDSet PermissionIDSet::Difference(const PermissionIDSet& set_1,
260 const PermissionIDSet& set_2) {
261 return PermissionIDSet(base::STLSetDifference<std::set<PermissionID>>(
262 set_1.permissions_, set_2.permissions_));
265 // static
266 PermissionIDSet PermissionIDSet::Intersection(const PermissionIDSet& set_1,
267 const PermissionIDSet& set_2) {
268 return PermissionIDSet(base::STLSetIntersection<std::set<PermissionID>>(
269 set_1.permissions_, set_2.permissions_));
272 // static
273 PermissionIDSet PermissionIDSet::Union(const PermissionIDSet& set_1,
274 const PermissionIDSet& set_2) {
275 return PermissionIDSet(base::STLSetUnion<std::set<PermissionID>>(
276 set_1.permissions_, set_2.permissions_));
279 size_t PermissionIDSet::size() const {
280 return permissions_.size();
283 bool PermissionIDSet::empty() const {
284 return permissions_.empty();
287 PermissionIDSet::PermissionIDSet(std::set<PermissionID> permissions)
288 : permissions_(permissions) {
291 bool PermissionIDSet::ContainsID(APIPermission::ID permission_id) {
292 // TODO(sashab): Find a more efficient way to implement this.
293 PermissionIDSet subset;
294 for (const auto& permission : permissions_) {
295 if (permission.id() == permission_id) {
296 return true;
299 return false;
302 } // namespace extensions