Extract SIGPIPE ignoring code to a common place.
[chromium-blink-merge.git] / chrome / common / extensions / permissions / api_permission_set.cc
blob0211e2a37d9b4c304fc5fa3dc1b5742c1fab2d2d
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;
16 namespace {
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,
27 string16* error,
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)) {
36 if (error) {
37 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
38 errors::kInvalidPermission, permission_info->name());
39 return false;
41 LOG(WARNING) << "Parse permission failed.";
42 } else {
43 api_permissions->insert(permission.release());
45 return true;
48 if (unhandled_permissions)
49 unhandled_permissions->push_back(permission_str);
50 else
51 LOG(WARNING) << "Unknown permission[" << permission_str << "].";
53 return true;
56 bool ParseChildPermissions(const std::string& base_name,
57 const Value* permission_value,
58 APIPermissionSet* api_permissions,
59 string16* error,
60 std::vector<std::string>* unhandled_permissions) {
61 if (permission_value) {
62 const ListValue* permissions;
63 if (!permission_value->GetAsList(&permissions)) {
64 if (error) {
65 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
66 errors::kInvalidPermission, base_name);
67 return false;
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.
72 return true;
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
79 if (error) {
80 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
81 errors::kInvalidPermission,
82 base_name + '.' + base::IntToString(i));
83 return false;
85 LOG(WARNING) << "Permission is not a string.";
86 continue;
89 if (!CreateAPIPermission(base_name + '.' + permission_str, NULL,
90 api_permissions, error, unhandled_permissions))
91 return false;
95 return CreateAPIPermission(base_name, NULL, api_permissions, error, NULL);
98 } // namespace
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)
114 : it_(it) {
117 APIPermissionSet::const_iterator::const_iterator(
118 const const_iterator& ids_it)
119 : it_(ids_it.it_) {
122 APIPermissionSet& APIPermissionSet::operator=(const APIPermissionSet& rhs) {
123 const_iterator it = rhs.begin();
124 const const_iterator end = rhs.end();
125 while (it != end) {
126 insert(it->Clone());
127 ++it;
129 return *this;
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))
140 return false;
141 ++it;
142 ++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()) {
166 return false;
167 } else if (it1->id() < it2->id()) {
168 ++it1;
169 } else {
170 if (!it1->Contains(*it2))
171 return false;
172 ++it1;
173 ++it2;
177 return it2 == end2;
180 void APIPermissionSet::Difference(
181 const APIPermissionSet& set1,
182 const APIPermissionSet& set2,
183 APIPermissionSet* set3) {
184 CHECK(set3);
185 set3->clear();
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());
195 ++it1;
196 } else if (it1->id() > it2->id()) {
197 ++it2;
198 } else {
199 APIPermission* p = it1->Diff(*it2);
200 if (p)
201 set3->insert(p);
202 ++it1;
203 ++it2;
207 while (it1 != end1) {
208 set3->insert(it1->Clone());
209 ++it1;
213 void APIPermissionSet::Intersection(
214 const APIPermissionSet& set1,
215 const APIPermissionSet& set2,
216 APIPermissionSet* set3) {
217 DCHECK(set3);
218 set3->clear();
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()) {
227 ++it1;
228 } else if (it1->id() > it2->id()) {
229 ++it2;
230 } else {
231 APIPermission* p = it1->Intersect(*it2);
232 if (p)
233 set3->insert(p);
234 ++it1;
235 ++it2;
240 void APIPermissionSet::Union(
241 const APIPermissionSet& set1,
242 const APIPermissionSet& set2,
243 APIPermissionSet* set3) {
244 DCHECK(set3);
245 set3->clear();
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();
252 while (true) {
253 if (it1 == end1) {
254 while (it2 != end2) {
255 set3->insert(it2->Clone());
256 ++it2;
258 break;
260 if (it2 == end2) {
261 while (it1 != end1) {
262 set3->insert(it1->Clone());
263 ++it1;
265 break;
267 if (it1->id() < it2->id()) {
268 set3->insert(it1->Clone());
269 ++it1;
270 } else if (it1->id() > it2->id()) {
271 set3->insert(it2->Clone());
272 ++it2;
273 } else {
274 set3->insert(it1->Union(*it2));
275 ++it1;
276 ++it2;
281 // static
282 bool APIPermissionSet::ParseFromJSON(
283 const ListValue* permissions,
284 APIPermissionSet* api_permissions,
285 string16* error,
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) {
295 if (error) {
296 *error = ExtensionErrorUtils::FormatErrorMessageUTF16(
297 errors::kInvalidPermission, base::IntToString(i));
298 return false;
300 LOG(WARNING) << "Permission is not a string or single key dict.";
301 continue;
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))
313 return false;
314 continue;
317 if (!CreateAPIPermission(permission_str, permission_value,
318 api_permissions, error, unhandled_permissions))
319 return false;
321 return true;
324 } // namespace extensions