Home | History | Annotate | Download | only in permissions
      1 // Copyright 2013 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 "extensions/common/permissions/api_permission_set.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/stl_util.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/values.h"
     11 #include "extensions/common/error_utils.h"
     12 #include "extensions/common/manifest_constants.h"
     13 #include "extensions/common/permissions/permissions_info.h"
     14 
     15 namespace extensions {
     16 
     17 namespace errors = manifest_errors;
     18 
     19 namespace {
     20 
     21 bool CreateAPIPermission(
     22     const std::string& permission_str,
     23     const base::Value* permission_value,
     24     APIPermissionSet::ParseSource source,
     25     APIPermissionSet* api_permissions,
     26     base::string16* error,
     27     std::vector<std::string>* unhandled_permissions) {
     28 
     29   const APIPermissionInfo* permission_info =
     30       PermissionsInfo::GetInstance()->GetByName(permission_str);
     31   if (permission_info) {
     32     scoped_ptr<APIPermission> permission(
     33         permission_info->CreateAPIPermission());
     34     if (source != APIPermissionSet::kAllowInternalPermissions &&
     35         permission_info->is_internal()) {
     36       // An internal permission specified in permissions list is an error.
     37       if (error) {
     38         *error = ErrorUtils::FormatErrorMessageUTF16(
     39             errors::kPermissionNotAllowedInManifest, permission_str);
     40       }
     41       return false;
     42     }
     43 
     44     std::string error_details;
     45     if (!permission->FromValue(permission_value, &error_details,
     46                                unhandled_permissions)) {
     47       if (error) {
     48         if (error_details.empty()) {
     49           *error = ErrorUtils::FormatErrorMessageUTF16(
     50               errors::kInvalidPermission,
     51               permission_info->name());
     52         } else {
     53           *error = ErrorUtils::FormatErrorMessageUTF16(
     54               errors::kInvalidPermissionWithDetail,
     55               permission_info->name(),
     56               error_details);
     57         }
     58         return false;
     59       }
     60       LOG(WARNING) << "Parse permission failed.";
     61     } else {
     62       api_permissions->insert(permission.release());
     63     }
     64     return true;
     65   }
     66 
     67   if (unhandled_permissions)
     68     unhandled_permissions->push_back(permission_str);
     69   else
     70     LOG(WARNING) << "Unknown permission[" << permission_str << "].";
     71 
     72   return true;
     73 }
     74 
     75 bool ParseChildPermissions(const std::string& base_name,
     76                            const base::Value* permission_value,
     77                            APIPermissionSet::ParseSource source,
     78                            APIPermissionSet* api_permissions,
     79                            base::string16* error,
     80                            std::vector<std::string>* unhandled_permissions) {
     81   if (permission_value) {
     82     const base::ListValue* permissions;
     83     if (!permission_value->GetAsList(&permissions)) {
     84       if (error) {
     85         *error = ErrorUtils::FormatErrorMessageUTF16(
     86             errors::kInvalidPermission, base_name);
     87         return false;
     88       }
     89       LOG(WARNING) << "Permission value is not a list.";
     90       // Failed to parse, but since error is NULL, failures are not fatal so
     91       // return true here anyway.
     92       return true;
     93     }
     94 
     95     for (size_t i = 0; i < permissions->GetSize(); ++i) {
     96       std::string permission_str;
     97       if (!permissions->GetString(i, &permission_str)) {
     98         // permission should be a string
     99         if (error) {
    100           *error = ErrorUtils::FormatErrorMessageUTF16(
    101               errors::kInvalidPermission,
    102               base_name + '.' + base::IntToString(i));
    103           return false;
    104         }
    105         LOG(WARNING) << "Permission is not a string.";
    106         continue;
    107       }
    108 
    109       if (!CreateAPIPermission(
    110               base_name + '.' + permission_str, NULL, source,
    111               api_permissions, error, unhandled_permissions))
    112         return false;
    113     }
    114   }
    115 
    116   return CreateAPIPermission(base_name, NULL, source,
    117                              api_permissions, error, NULL);
    118 }
    119 
    120 }  // namespace
    121 
    122 void APIPermissionSet::insert(APIPermission::ID id) {
    123   const APIPermissionInfo* permission_info =
    124       PermissionsInfo::GetInstance()->GetByID(id);
    125   DCHECK(permission_info);
    126   insert(permission_info->CreateAPIPermission());
    127 }
    128 
    129 void APIPermissionSet::insert(APIPermission* permission) {
    130   BaseSetOperators<APIPermissionSet>::insert(permission);
    131 }
    132 
    133 // static
    134 bool APIPermissionSet::ParseFromJSON(
    135     const base::ListValue* permissions,
    136     APIPermissionSet::ParseSource source,
    137     APIPermissionSet* api_permissions,
    138     base::string16* error,
    139     std::vector<std::string>* unhandled_permissions) {
    140   for (size_t i = 0; i < permissions->GetSize(); ++i) {
    141     std::string permission_str;
    142     const base::Value* permission_value = NULL;
    143     if (!permissions->GetString(i, &permission_str)) {
    144       const base::DictionaryValue* dict = NULL;
    145       // permission should be a string or a single key dict.
    146       if (!permissions->GetDictionary(i, &dict) || dict->size() != 1) {
    147         if (error) {
    148           *error = ErrorUtils::FormatErrorMessageUTF16(
    149               errors::kInvalidPermission, base::IntToString(i));
    150           return false;
    151         }
    152         LOG(WARNING) << "Permission is not a string or single key dict.";
    153         continue;
    154       }
    155       base::DictionaryValue::Iterator it(*dict);
    156       permission_str = it.key();
    157       permission_value = &it.value();
    158     }
    159 
    160     // Check if this permission is a special case where its value should
    161     // be treated as a list of child permissions.
    162     if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) {
    163       if (!ParseChildPermissions(permission_str, permission_value, source,
    164                                  api_permissions, error, unhandled_permissions))
    165         return false;
    166       continue;
    167     }
    168 
    169     if (!CreateAPIPermission(permission_str, permission_value, source,
    170                              api_permissions, error, unhandled_permissions))
    171       return false;
    172   }
    173   return true;
    174 }
    175 
    176 void APIPermissionSet::AddImpliedPermissions() {
    177   // The fileSystem.write and fileSystem.directory permissions imply
    178   // fileSystem.writeDirectory.
    179   // TODO(sammc): Remove this. See http://crbug.com/284849.
    180   if (ContainsKey(map(), APIPermission::kFileSystemWrite) &&
    181       ContainsKey(map(), APIPermission::kFileSystemDirectory)) {
    182     insert(APIPermission::kFileSystemWriteDirectory);
    183   }
    184 }
    185 
    186 }  // namespace extensions
    187