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. 4 5 #ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_ 6 #define CHROME_COMMON_EXTENSIONS_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_ 7 8 #include <algorithm> 9 #include <set> 10 #include <string> 11 12 #include "base/memory/scoped_ptr.h" 13 #include "base/values.h" 14 #include "chrome/common/extensions/extension_messages.h" 15 #include "extensions/common/permissions/api_permission.h" 16 #include "ipc/ipc_message.h" 17 #include "ipc/ipc_message_utils.h" 18 19 namespace extensions { 20 21 // An abstract base class for permissions that are represented by the 22 // disjunction of a set of conditions. Each condition is represented by a 23 // |PermissionDataType| (e.g. SocketPermissionData). If an 24 // APIPermission::CheckParam matches any of the conditions in the set, the 25 // permission is granted. 26 // 27 // For an example of how to use this class, see SocketPermission. 28 template <class PermissionDataType, class DerivedType> 29 class SetDisjunctionPermission : public APIPermission { 30 public: 31 explicit SetDisjunctionPermission(const APIPermissionInfo* info) 32 : APIPermission(info) { 33 } 34 35 ~SetDisjunctionPermission() { 36 } 37 38 // APIPermission overrides 39 virtual bool HasMessages() const OVERRIDE { 40 return !data_set_.empty(); 41 } 42 43 virtual bool Check(const APIPermission::CheckParam* param) const OVERRIDE { 44 for (typename std::set<PermissionDataType>::const_iterator i = 45 data_set_.begin(); i != data_set_.end(); ++i) { 46 if (i->Check(param)) 47 return true; 48 } 49 return false; 50 } 51 52 virtual bool Contains(const APIPermission* rhs) const OVERRIDE { 53 CHECK(rhs->info() == info()); 54 const SetDisjunctionPermission* perm = 55 static_cast<const SetDisjunctionPermission*>(rhs); 56 return std::includes( 57 data_set_.begin(), data_set_.end(), 58 perm->data_set_.begin(), perm->data_set_.end()); 59 } 60 61 virtual bool Equal(const APIPermission* rhs) const OVERRIDE { 62 CHECK(rhs->info() == info()); 63 const SetDisjunctionPermission* perm = 64 static_cast<const SetDisjunctionPermission*>(rhs); 65 return data_set_ == perm->data_set_; 66 } 67 68 virtual APIPermission* Clone() const OVERRIDE { 69 SetDisjunctionPermission* result = new DerivedType(info()); 70 result->data_set_ = data_set_; 71 return result; 72 } 73 74 virtual APIPermission* Diff(const APIPermission* rhs) const OVERRIDE { 75 CHECK(rhs->info() == info()); 76 const SetDisjunctionPermission* perm = 77 static_cast<const SetDisjunctionPermission*>(rhs); 78 scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info())); 79 std::set_difference( 80 data_set_.begin(), data_set_.end(), 81 perm->data_set_.begin(), perm->data_set_.end(), 82 std::inserter<std::set<PermissionDataType> >( 83 result->data_set_, result->data_set_.begin())); 84 return result->data_set_.empty() ? NULL : result.release(); 85 } 86 87 virtual APIPermission* Union(const APIPermission* rhs) const OVERRIDE { 88 CHECK(rhs->info() == info()); 89 const SetDisjunctionPermission* perm = 90 static_cast<const SetDisjunctionPermission*>(rhs); 91 scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info())); 92 std::set_union( 93 data_set_.begin(), data_set_.end(), 94 perm->data_set_.begin(), perm->data_set_.end(), 95 std::inserter<std::set<PermissionDataType> >( 96 result->data_set_, result->data_set_.begin())); 97 return result.release(); 98 } 99 100 virtual APIPermission* Intersect(const APIPermission* rhs) const OVERRIDE { 101 CHECK(rhs->info() == info()); 102 const SetDisjunctionPermission* perm = 103 static_cast<const SetDisjunctionPermission*>(rhs); 104 scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info())); 105 std::set_intersection( 106 data_set_.begin(), data_set_.end(), 107 perm->data_set_.begin(), perm->data_set_.end(), 108 std::inserter<std::set<PermissionDataType> >( 109 result->data_set_, result->data_set_.begin())); 110 return result->data_set_.empty() ? NULL : result.release(); 111 } 112 113 virtual bool FromValue(const base::Value* value) OVERRIDE { 114 data_set_.clear(); 115 const base::ListValue* list = NULL; 116 117 if (!value) 118 return false; 119 120 if (!value->GetAsList(&list) || list->GetSize() == 0) 121 return false; 122 123 for (size_t i = 0; i < list->GetSize(); ++i) { 124 const base::Value* item_value; 125 if (!list->Get(i, &item_value)) 126 return false; 127 128 PermissionDataType data; 129 if (!data.FromValue(item_value)) 130 return false; 131 132 data_set_.insert(data); 133 } 134 return true; 135 } 136 137 virtual scoped_ptr<base::Value> ToValue() const OVERRIDE { 138 base::ListValue* list = new base::ListValue(); 139 typename std::set<PermissionDataType>::const_iterator i; 140 for (i = data_set_.begin(); i != data_set_.end(); ++i) { 141 scoped_ptr<base::Value> item_value(i->ToValue()); 142 list->Append(item_value.release()); 143 } 144 return scoped_ptr<base::Value>(list); 145 } 146 147 virtual void Write(IPC::Message* m) const OVERRIDE { 148 IPC::WriteParam(m, data_set_); 149 } 150 151 virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE { 152 return IPC::ReadParam(m, iter, &data_set_); 153 } 154 155 virtual void Log(std::string* log) const OVERRIDE { 156 IPC::LogParam(data_set_, log); 157 } 158 159 protected: 160 std::set<PermissionDataType> data_set_; 161 }; 162 163 } // namespace extensions 164 165 #endif // CHROME_COMMON_EXTENSIONS_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_ 166