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 #include "chrome/common/extensions/permissions/api_permission_set.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/strings/string_number_conversions.h"
      9 #include "base/values.h"
     10 #include "chrome/common/extensions/extension_manifest_constants.h"
     11 #include "chrome/common/extensions/permissions/permissions_info.h"
     12 #include "extensions/common/error_utils.h"
     13 
     14 namespace errors = extension_manifest_errors;
     15 
     16 namespace {
     17 
     18 using extensions::APIPermission;
     19 using extensions::APIPermissionInfo;
     20 using extensions::APIPermissionSet;
     21 using extensions::ErrorUtils;
     22 using extensions::PermissionsInfo;
     23 
     24 bool CreateAPIPermission(
     25     const std::string& permission_str,
     26     const base::Value* permission_value,
     27     APIPermissionSet::ParseSource source,
     28     APIPermissionSet* api_permissions,
     29     string16* error,
     30     std::vector<std::string>* unhandled_permissions) {
     31 
     32   const APIPermissionInfo* permission_info =
     33       PermissionsInfo::GetInstance()->GetByName(permission_str);
     34   if (permission_info) {
     35     scoped_ptr<APIPermission> permission(
     36         permission_info->CreateAPIPermission());
     37     if (source != APIPermissionSet::kAllowInternalPermissions &&
     38         permission_info->is_internal()) {
     39       // An internal permission specified in permissions list is an error.
     40       if (error) {
     41         *error = ErrorUtils::FormatErrorMessageUTF16(
     42             errors::kPermissionNotAllowedInManifest, permission_str);
     43       }
     44       return false;
     45     }
     46 
     47     if (!permission->FromValue(permission_value)) {
     48       if (error) {
     49         *error = ErrorUtils::FormatErrorMessageUTF16(
     50             errors::kInvalidPermission, permission_info->name());
     51         return false;
     52       }
     53       LOG(WARNING) << "Parse permission failed.";
     54     } else {
     55       api_permissions->insert(permission.release());
     56     }
     57     return true;
     58   }
     59 
     60   if (unhandled_permissions)
     61     unhandled_permissions->push_back(permission_str);
     62   else
     63     LOG(WARNING) << "Unknown permission[" << permission_str << "].";
     64 
     65   return true;
     66 }
     67 
     68 bool ParseChildPermissions(const std::string& base_name,
     69                            const base::Value* permission_value,
     70                            APIPermissionSet::ParseSource source,
     71                            APIPermissionSet* api_permissions,
     72                            string16* error,
     73                            std::vector<std::string>* unhandled_permissions) {
     74   if (permission_value) {
     75     const base::ListValue* permissions;
     76     if (!permission_value->GetAsList(&permissions)) {
     77       if (error) {
     78         *error = ErrorUtils::FormatErrorMessageUTF16(
     79             errors::kInvalidPermission, base_name);
     80         return false;
     81       }
     82       LOG(WARNING) << "Permission value is not a list.";
     83       // Failed to parse, but since error is NULL, failures are not fatal so
     84       // return true here anyway.
     85       return true;
     86     }
     87 
     88     for (size_t i = 0; i < permissions->GetSize(); ++i) {
     89       std::string permission_str;
     90       if (!permissions->GetString(i, &permission_str)) {
     91         // permission should be a string
     92         if (error) {
     93           *error = ErrorUtils::FormatErrorMessageUTF16(
     94               errors::kInvalidPermission,
     95               base_name + '.' + base::IntToString(i));
     96           return false;
     97         }
     98         LOG(WARNING) << "Permission is not a string.";
     99         continue;
    100       }
    101 
    102       if (!CreateAPIPermission(
    103               base_name + '.' + permission_str, NULL, source,
    104               api_permissions, error, unhandled_permissions))
    105         return false;
    106     }
    107   }
    108 
    109   return CreateAPIPermission(base_name, NULL, source,
    110                              api_permissions, error, NULL);
    111 }
    112 
    113 }  // namespace
    114 
    115 namespace extensions {
    116 
    117 APIPermissionSet::APIPermissionSet() {
    118 }
    119 
    120 APIPermissionSet::APIPermissionSet(const APIPermissionSet& set) {
    121   this->operator=(set);
    122 }
    123 
    124 APIPermissionSet::~APIPermissionSet() {
    125 }
    126 
    127 APIPermissionSet::const_iterator::const_iterator(
    128     const APIPermissionMap::const_iterator& it)
    129   : it_(it) {
    130 }
    131 
    132 APIPermissionSet::const_iterator::const_iterator(
    133     const const_iterator& ids_it)
    134   : it_(ids_it.it_) {
    135 }
    136 
    137 APIPermissionSet& APIPermissionSet::operator=(const APIPermissionSet& rhs) {
    138   const_iterator it = rhs.begin();
    139   const const_iterator end = rhs.end();
    140   while (it != end) {
    141     insert(it->Clone());
    142     ++it;
    143   }
    144   return *this;
    145 }
    146 
    147 bool APIPermissionSet::operator==(const APIPermissionSet& rhs) const {
    148   const_iterator it = begin();
    149   const_iterator rhs_it = rhs.begin();
    150   const_iterator it_end = end();
    151   const_iterator rhs_it_end = rhs.end();
    152 
    153   while (it != it_end && rhs_it != rhs_it_end) {
    154     if (!it->Equal(*rhs_it))
    155       return false;
    156     ++it;
    157     ++rhs_it;
    158   }
    159   return it == it_end && rhs_it == rhs_it_end;
    160 }
    161 
    162 void APIPermissionSet::insert(APIPermission::ID id) {
    163   const APIPermissionInfo* permission_info =
    164       PermissionsInfo::GetInstance()->GetByID(id);
    165   insert(permission_info->CreateAPIPermission());
    166 }
    167 
    168 void APIPermissionSet::insert(APIPermission* permission) {
    169   map_[permission->id()].reset(permission);
    170 }
    171 
    172 bool APIPermissionSet::Contains(const APIPermissionSet& rhs) const {
    173   APIPermissionSet::const_iterator it1 = begin();
    174   APIPermissionSet::const_iterator it2 = rhs.begin();
    175   APIPermissionSet::const_iterator end1 = end();
    176   APIPermissionSet::const_iterator end2 = rhs.end();
    177 
    178   while (it1 != end1 && it2 != end2) {
    179     if (it1->id() > it2->id()) {
    180       return false;
    181     } else if (it1->id() < it2->id()) {
    182       ++it1;
    183     } else {
    184         if (!it1->Contains(*it2))
    185           return false;
    186       ++it1;
    187       ++it2;
    188     }
    189   }
    190 
    191   return it2 == end2;
    192 }
    193 
    194 void APIPermissionSet::Difference(
    195     const APIPermissionSet& set1,
    196     const APIPermissionSet& set2,
    197     APIPermissionSet* set3) {
    198   CHECK(set3);
    199   set3->clear();
    200 
    201   APIPermissionSet::const_iterator it1 = set1.begin();
    202   APIPermissionSet::const_iterator it2 = set2.begin();
    203   const APIPermissionSet::const_iterator end1 = set1.end();
    204   const APIPermissionSet::const_iterator end2 = set2.end();
    205 
    206   while (it1 != end1 && it2 != end2) {
    207     if (it1->id() < it2->id()) {
    208       set3->insert(it1->Clone());
    209       ++it1;
    210     } else if (it1->id() > it2->id()) {
    211       ++it2;
    212     } else {
    213       APIPermission* p = it1->Diff(*it2);
    214       if (p)
    215         set3->insert(p);
    216       ++it1;
    217       ++it2;
    218     }
    219   }
    220 
    221   while (it1 != end1) {
    222     set3->insert(it1->Clone());
    223     ++it1;
    224   }
    225 }
    226 
    227 void APIPermissionSet::Intersection(
    228     const APIPermissionSet& set1,
    229     const APIPermissionSet& set2,
    230     APIPermissionSet* set3) {
    231   DCHECK(set3);
    232   set3->clear();
    233 
    234   APIPermissionSet::const_iterator it1 = set1.begin();
    235   APIPermissionSet::const_iterator it2 = set2.begin();
    236   const APIPermissionSet::const_iterator end1 = set1.end();
    237   const APIPermissionSet::const_iterator end2 = set2.end();
    238 
    239   while (it1 != end1 && it2 != end2) {
    240     if (it1->id() < it2->id()) {
    241       ++it1;
    242     } else if (it1->id() > it2->id()) {
    243       ++it2;
    244     } else {
    245       APIPermission* p = it1->Intersect(*it2);
    246       if (p)
    247         set3->insert(p);
    248       ++it1;
    249       ++it2;
    250     }
    251   }
    252 }
    253 
    254 void APIPermissionSet::Union(
    255     const APIPermissionSet& set1,
    256     const APIPermissionSet& set2,
    257     APIPermissionSet* set3) {
    258   DCHECK(set3);
    259   set3->clear();
    260 
    261   APIPermissionSet::const_iterator it1 = set1.begin();
    262   APIPermissionSet::const_iterator it2 = set2.begin();
    263   const APIPermissionSet::const_iterator end1 = set1.end();
    264   const APIPermissionSet::const_iterator end2 = set2.end();
    265 
    266   while (true) {
    267     if (it1 == end1) {
    268       while (it2 != end2) {
    269         set3->insert(it2->Clone());
    270         ++it2;
    271       }
    272       break;
    273     }
    274     if (it2 == end2) {
    275       while (it1 != end1) {
    276         set3->insert(it1->Clone());
    277         ++it1;
    278       }
    279       break;
    280     }
    281     if (it1->id() < it2->id()) {
    282       set3->insert(it1->Clone());
    283       ++it1;
    284     } else if (it1->id() > it2->id()) {
    285       set3->insert(it2->Clone());
    286       ++it2;
    287     } else {
    288       set3->insert(it1->Union(*it2));
    289       ++it1;
    290       ++it2;
    291     }
    292   }
    293 }
    294 
    295 // static
    296 bool APIPermissionSet::ParseFromJSON(
    297     const base::ListValue* permissions,
    298     APIPermissionSet::ParseSource source,
    299     APIPermissionSet* api_permissions,
    300     string16* error,
    301     std::vector<std::string>* unhandled_permissions) {
    302   for (size_t i = 0; i < permissions->GetSize(); ++i) {
    303     std::string permission_str;
    304     const base::Value* permission_value = NULL;
    305     if (!permissions->GetString(i, &permission_str)) {
    306       const base::DictionaryValue* dict = NULL;
    307       // permission should be a string or a single key dict.
    308       if (!permissions->GetDictionary(i, &dict) || dict->size() != 1) {
    309         if (error) {
    310           *error = ErrorUtils::FormatErrorMessageUTF16(
    311               errors::kInvalidPermission, base::IntToString(i));
    312           return false;
    313         }
    314         LOG(WARNING) << "Permission is not a string or single key dict.";
    315         continue;
    316       }
    317       base::DictionaryValue::Iterator it(*dict);
    318       permission_str = it.key();
    319       permission_value = &it.value();
    320     }
    321 
    322     // Check if this permission is a special case where its value should
    323     // be treated as a list of child permissions.
    324     if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) {
    325       if (!ParseChildPermissions(permission_str, permission_value, source,
    326                                  api_permissions, error, unhandled_permissions))
    327         return false;
    328       continue;
    329     }
    330 
    331     if (!CreateAPIPermission(permission_str, permission_value, source,
    332                              api_permissions, error, unhandled_permissions))
    333       return false;
    334   }
    335   return true;
    336 }
    337 
    338 }  // namespace extensions
    339