1 // Copyright 2014 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 EXTENSIONS_COMMON_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_ 6 #define EXTENSIONS_COMMON_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_ 7 8 #include <set> 9 #include <string> 10 11 #include "base/json/json_writer.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/values.h" 14 #include "extensions/common/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: SetDisjunctionPermission(const APIPermissionInfo * info)31 explicit SetDisjunctionPermission(const APIPermissionInfo* info) 32 : APIPermission(info) {} 33 ~SetDisjunctionPermission()34 ~SetDisjunctionPermission() {} 35 36 // APIPermission overrides HasMessages()37 virtual bool HasMessages() const OVERRIDE { return !data_set_.empty(); } 38 Check(const APIPermission::CheckParam * param)39 virtual bool Check(const APIPermission::CheckParam* param) const OVERRIDE { 40 for (typename std::set<PermissionDataType>::const_iterator i = 41 data_set_.begin(); 42 i != data_set_.end(); 43 ++i) { 44 if (i->Check(param)) 45 return true; 46 } 47 return false; 48 } 49 Contains(const APIPermission * rhs)50 virtual bool Contains(const APIPermission* rhs) const OVERRIDE { 51 CHECK(rhs->info() == info()); 52 const SetDisjunctionPermission* perm = 53 static_cast<const SetDisjunctionPermission*>(rhs); 54 return base::STLIncludes<std::set<PermissionDataType> >( 55 data_set_, perm->data_set_); 56 } 57 Equal(const APIPermission * rhs)58 virtual bool Equal(const APIPermission* rhs) const OVERRIDE { 59 CHECK(rhs->info() == info()); 60 const SetDisjunctionPermission* perm = 61 static_cast<const SetDisjunctionPermission*>(rhs); 62 return data_set_ == perm->data_set_; 63 } 64 Clone()65 virtual APIPermission* Clone() const OVERRIDE { 66 SetDisjunctionPermission* result = new DerivedType(info()); 67 result->data_set_ = data_set_; 68 return result; 69 } 70 Diff(const APIPermission * rhs)71 virtual APIPermission* Diff(const APIPermission* rhs) const OVERRIDE { 72 CHECK(rhs->info() == info()); 73 const SetDisjunctionPermission* perm = 74 static_cast<const SetDisjunctionPermission*>(rhs); 75 scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info())); 76 result->data_set_ = base::STLSetDifference<std::set<PermissionDataType> >( 77 data_set_, perm->data_set_); 78 return result->data_set_.empty() ? NULL : result.release(); 79 } 80 Union(const APIPermission * rhs)81 virtual APIPermission* Union(const APIPermission* rhs) const OVERRIDE { 82 CHECK(rhs->info() == info()); 83 const SetDisjunctionPermission* perm = 84 static_cast<const SetDisjunctionPermission*>(rhs); 85 scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info())); 86 result->data_set_ = base::STLSetUnion<std::set<PermissionDataType> >( 87 data_set_, perm->data_set_); 88 return result.release(); 89 } 90 Intersect(const APIPermission * rhs)91 virtual APIPermission* Intersect(const APIPermission* rhs) const OVERRIDE { 92 CHECK(rhs->info() == info()); 93 const SetDisjunctionPermission* perm = 94 static_cast<const SetDisjunctionPermission*>(rhs); 95 scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info())); 96 result->data_set_ = base::STLSetIntersection<std::set<PermissionDataType> >( 97 data_set_, perm->data_set_); 98 return result->data_set_.empty() ? NULL : result.release(); 99 } 100 FromValue(const base::Value * value,std::string * error,std::vector<std::string> * unhandled_permissions)101 virtual bool FromValue( 102 const base::Value* value, 103 std::string* error, 104 std::vector<std::string>* unhandled_permissions) OVERRIDE { 105 data_set_.clear(); 106 const base::ListValue* list = NULL; 107 108 if (!value || !value->GetAsList(&list) || list->GetSize() == 0) { 109 if (error) 110 *error = "NULL or empty permission list"; 111 return false; 112 } 113 114 for (size_t i = 0; i < list->GetSize(); ++i) { 115 const base::Value* item_value = NULL; 116 bool got_item = list->Get(i, &item_value); 117 DCHECK(got_item); 118 DCHECK(item_value); 119 120 PermissionDataType data; 121 if (data.FromValue(item_value)) { 122 data_set_.insert(data); 123 } else { 124 std::string unknown_permission; 125 base::JSONWriter::Write(item_value, &unknown_permission); 126 if (unhandled_permissions) { 127 unhandled_permissions->push_back(unknown_permission); 128 } else { 129 if (error) { 130 *error = "Cannot parse an item from the permission list: " + 131 unknown_permission; 132 } 133 return false; 134 } 135 } 136 } 137 return true; 138 } 139 ToValue()140 virtual scoped_ptr<base::Value> ToValue() const OVERRIDE { 141 base::ListValue* list = new base::ListValue(); 142 typename std::set<PermissionDataType>::const_iterator i; 143 for (i = data_set_.begin(); i != data_set_.end(); ++i) { 144 scoped_ptr<base::Value> item_value(i->ToValue()); 145 list->Append(item_value.release()); 146 } 147 return scoped_ptr<base::Value>(list); 148 } 149 Write(IPC::Message * m)150 virtual void Write(IPC::Message* m) const OVERRIDE { 151 IPC::WriteParam(m, data_set_); 152 } 153 Read(const IPC::Message * m,PickleIterator * iter)154 virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE { 155 return IPC::ReadParam(m, iter, &data_set_); 156 } 157 Log(std::string * log)158 virtual void Log(std::string* log) const OVERRIDE { 159 IPC::LogParam(data_set_, log); 160 } 161 162 protected: 163 std::set<PermissionDataType> data_set_; 164 }; 165 166 } // namespace extensions 167 168 #endif // EXTENSIONS_COMMON_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_ 169