Home | History | Annotate | Download | only in permissions
      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:
     31   explicit SetDisjunctionPermission(const APIPermissionInfo* info)
     32       : APIPermission(info) {}
     33 
     34   ~SetDisjunctionPermission() {}
     35 
     36   // APIPermission overrides
     37   virtual bool HasMessages() const OVERRIDE { return !data_set_.empty(); }
     38 
     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 
     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 
     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 
     65   virtual APIPermission* Clone() const OVERRIDE {
     66     SetDisjunctionPermission* result = new DerivedType(info());
     67     result->data_set_ = data_set_;
     68     return result;
     69   }
     70 
     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 
     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 
     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 
    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 
    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 
    150   virtual void Write(IPC::Message* m) const OVERRIDE {
    151     IPC::WriteParam(m, data_set_);
    152   }
    153 
    154   virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE {
    155     return IPC::ReadParam(m, iter, &data_set_);
    156   }
    157 
    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