Home | History | Annotate | Download | only in permissions
      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