summaryrefslogtreecommitdiffstats
path: root/extensions/common/permissions/api_permission_set.cc
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/common/permissions/api_permission_set.cc')
-rw-r--r--extensions/common/permissions/api_permission_set.cc343
1 files changed, 343 insertions, 0 deletions
diff --git a/extensions/common/permissions/api_permission_set.cc b/extensions/common/permissions/api_permission_set.cc
new file mode 100644
index 0000000..ebaf8d8
--- /dev/null
+++ b/extensions/common/permissions/api_permission_set.cc
@@ -0,0 +1,343 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/api_permission_set.h"
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/values.h"
+#include "extensions/common/error_utils.h"
+#include "extensions/common/manifest_constants.h"
+#include "extensions/common/permissions/permissions_info.h"
+
+namespace extensions {
+
+namespace errors = manifest_errors;
+
+namespace {
+
+bool CreateAPIPermission(
+ const std::string& permission_str,
+ const base::Value* permission_value,
+ APIPermissionSet::ParseSource source,
+ APIPermissionSet* api_permissions,
+ string16* error,
+ std::vector<std::string>* unhandled_permissions) {
+
+ const APIPermissionInfo* permission_info =
+ PermissionsInfo::GetInstance()->GetByName(permission_str);
+ if (permission_info) {
+ scoped_ptr<APIPermission> permission(
+ permission_info->CreateAPIPermission());
+ if (source != APIPermissionSet::kAllowInternalPermissions &&
+ permission_info->is_internal()) {
+ // An internal permission specified in permissions list is an error.
+ if (error) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kPermissionNotAllowedInManifest, permission_str);
+ }
+ return false;
+ }
+
+ if (!permission->FromValue(permission_value)) {
+ if (error) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidPermission, permission_info->name());
+ return false;
+ }
+ LOG(WARNING) << "Parse permission failed.";
+ } else {
+ api_permissions->insert(permission.release());
+ }
+ return true;
+ }
+
+ if (unhandled_permissions)
+ unhandled_permissions->push_back(permission_str);
+ else
+ LOG(WARNING) << "Unknown permission[" << permission_str << "].";
+
+ return true;
+}
+
+bool ParseChildPermissions(const std::string& base_name,
+ const base::Value* permission_value,
+ APIPermissionSet::ParseSource source,
+ APIPermissionSet* api_permissions,
+ string16* error,
+ std::vector<std::string>* unhandled_permissions) {
+ if (permission_value) {
+ const base::ListValue* permissions;
+ if (!permission_value->GetAsList(&permissions)) {
+ if (error) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidPermission, base_name);
+ return false;
+ }
+ LOG(WARNING) << "Permission value is not a list.";
+ // Failed to parse, but since error is NULL, failures are not fatal so
+ // return true here anyway.
+ return true;
+ }
+
+ for (size_t i = 0; i < permissions->GetSize(); ++i) {
+ std::string permission_str;
+ if (!permissions->GetString(i, &permission_str)) {
+ // permission should be a string
+ if (error) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidPermission,
+ base_name + '.' + base::IntToString(i));
+ return false;
+ }
+ LOG(WARNING) << "Permission is not a string.";
+ continue;
+ }
+
+ if (!CreateAPIPermission(
+ base_name + '.' + permission_str, NULL, source,
+ api_permissions, error, unhandled_permissions))
+ return false;
+ }
+ }
+
+ return CreateAPIPermission(base_name, NULL, source,
+ api_permissions, error, NULL);
+}
+
+} // namespace
+
+APIPermissionSet::APIPermissionSet() {
+}
+
+APIPermissionSet::APIPermissionSet(const APIPermissionSet& set) {
+ this->operator=(set);
+}
+
+APIPermissionSet::~APIPermissionSet() {
+}
+
+APIPermissionSet::const_iterator::const_iterator(
+ const APIPermissionMap::const_iterator& it)
+ : it_(it) {
+}
+
+APIPermissionSet::const_iterator::const_iterator(
+ const const_iterator& ids_it)
+ : it_(ids_it.it_) {
+}
+
+APIPermissionSet& APIPermissionSet::operator=(const APIPermissionSet& rhs) {
+ const_iterator it = rhs.begin();
+ const const_iterator end = rhs.end();
+ while (it != end) {
+ insert(it->Clone());
+ ++it;
+ }
+ return *this;
+}
+
+bool APIPermissionSet::operator==(const APIPermissionSet& rhs) const {
+ const_iterator it = begin();
+ const_iterator rhs_it = rhs.begin();
+ const_iterator it_end = end();
+ const_iterator rhs_it_end = rhs.end();
+
+ while (it != it_end && rhs_it != rhs_it_end) {
+ if (!it->Equal(*rhs_it))
+ return false;
+ ++it;
+ ++rhs_it;
+ }
+ return it == it_end && rhs_it == rhs_it_end;
+}
+
+void APIPermissionSet::insert(APIPermission::ID id) {
+ const APIPermissionInfo* permission_info =
+ PermissionsInfo::GetInstance()->GetByID(id);
+ insert(permission_info->CreateAPIPermission());
+}
+
+void APIPermissionSet::insert(APIPermission* permission) {
+ map_[permission->id()].reset(permission);
+}
+
+bool APIPermissionSet::Contains(const APIPermissionSet& rhs) const {
+ APIPermissionSet::const_iterator it1 = begin();
+ APIPermissionSet::const_iterator it2 = rhs.begin();
+ APIPermissionSet::const_iterator end1 = end();
+ APIPermissionSet::const_iterator end2 = rhs.end();
+
+ while (it1 != end1 && it2 != end2) {
+ if (it1->id() > it2->id()) {
+ return false;
+ } else if (it1->id() < it2->id()) {
+ ++it1;
+ } else {
+ if (!it1->Contains(*it2))
+ return false;
+ ++it1;
+ ++it2;
+ }
+ }
+
+ return it2 == end2;
+}
+
+void APIPermissionSet::Difference(
+ const APIPermissionSet& set1,
+ const APIPermissionSet& set2,
+ APIPermissionSet* set3) {
+ CHECK(set3);
+ set3->clear();
+
+ APIPermissionSet::const_iterator it1 = set1.begin();
+ APIPermissionSet::const_iterator it2 = set2.begin();
+ const APIPermissionSet::const_iterator end1 = set1.end();
+ const APIPermissionSet::const_iterator end2 = set2.end();
+
+ while (it1 != end1 && it2 != end2) {
+ if (it1->id() < it2->id()) {
+ set3->insert(it1->Clone());
+ ++it1;
+ } else if (it1->id() > it2->id()) {
+ ++it2;
+ } else {
+ APIPermission* p = it1->Diff(*it2);
+ if (p)
+ set3->insert(p);
+ ++it1;
+ ++it2;
+ }
+ }
+
+ while (it1 != end1) {
+ set3->insert(it1->Clone());
+ ++it1;
+ }
+}
+
+void APIPermissionSet::Intersection(
+ const APIPermissionSet& set1,
+ const APIPermissionSet& set2,
+ APIPermissionSet* set3) {
+ DCHECK(set3);
+ set3->clear();
+
+ APIPermissionSet::const_iterator it1 = set1.begin();
+ APIPermissionSet::const_iterator it2 = set2.begin();
+ const APIPermissionSet::const_iterator end1 = set1.end();
+ const APIPermissionSet::const_iterator end2 = set2.end();
+
+ while (it1 != end1 && it2 != end2) {
+ if (it1->id() < it2->id()) {
+ ++it1;
+ } else if (it1->id() > it2->id()) {
+ ++it2;
+ } else {
+ APIPermission* p = it1->Intersect(*it2);
+ if (p)
+ set3->insert(p);
+ ++it1;
+ ++it2;
+ }
+ }
+}
+
+void APIPermissionSet::Union(
+ const APIPermissionSet& set1,
+ const APIPermissionSet& set2,
+ APIPermissionSet* set3) {
+ DCHECK(set3);
+ set3->clear();
+
+ APIPermissionSet::const_iterator it1 = set1.begin();
+ APIPermissionSet::const_iterator it2 = set2.begin();
+ const APIPermissionSet::const_iterator end1 = set1.end();
+ const APIPermissionSet::const_iterator end2 = set2.end();
+
+ while (true) {
+ if (it1 == end1) {
+ while (it2 != end2) {
+ set3->insert(it2->Clone());
+ ++it2;
+ }
+ break;
+ }
+ if (it2 == end2) {
+ while (it1 != end1) {
+ set3->insert(it1->Clone());
+ ++it1;
+ }
+ break;
+ }
+ if (it1->id() < it2->id()) {
+ set3->insert(it1->Clone());
+ ++it1;
+ } else if (it1->id() > it2->id()) {
+ set3->insert(it2->Clone());
+ ++it2;
+ } else {
+ set3->insert(it1->Union(*it2));
+ ++it1;
+ ++it2;
+ }
+ }
+}
+
+// static
+bool APIPermissionSet::ParseFromJSON(
+ const base::ListValue* permissions,
+ APIPermissionSet::ParseSource source,
+ APIPermissionSet* api_permissions,
+ string16* error,
+ std::vector<std::string>* unhandled_permissions) {
+ for (size_t i = 0; i < permissions->GetSize(); ++i) {
+ std::string permission_str;
+ const base::Value* permission_value = NULL;
+ if (!permissions->GetString(i, &permission_str)) {
+ const base::DictionaryValue* dict = NULL;
+ // permission should be a string or a single key dict.
+ if (!permissions->GetDictionary(i, &dict) || dict->size() != 1) {
+ if (error) {
+ *error = ErrorUtils::FormatErrorMessageUTF16(
+ errors::kInvalidPermission, base::IntToString(i));
+ return false;
+ }
+ LOG(WARNING) << "Permission is not a string or single key dict.";
+ continue;
+ }
+ base::DictionaryValue::Iterator it(*dict);
+ permission_str = it.key();
+ permission_value = &it.value();
+ }
+
+ // Check if this permission is a special case where its value should
+ // be treated as a list of child permissions.
+ if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) {
+ if (!ParseChildPermissions(permission_str, permission_value, source,
+ api_permissions, error, unhandled_permissions))
+ return false;
+ continue;
+ }
+
+ if (!CreateAPIPermission(permission_str, permission_value, source,
+ api_permissions, error, unhandled_permissions))
+ return false;
+ }
+ return true;
+}
+
+void APIPermissionSet::AddImpliedPermissions() {
+ // The fileSystem.write and fileSystem.directory permissions imply
+ // fileSystem.writeDirectory.
+ // TODO(sammc): Remove this. See http://crbug.com/284849.
+ if (ContainsKey(map_, APIPermission::kFileSystemWrite) &&
+ ContainsKey(map_, APIPermission::kFileSystemDirectory)) {
+ insert(APIPermission::kFileSystemWriteDirectory);
+ }
+}
+
+} // namespace extensions