• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CreateAPIPermission(const std::string & permission_str,const base::Value * permission_value,APIPermissionSet::ParseSource source,APIPermissionSet * api_permissions,base::string16 * error,std::vector<std::string> * unhandled_permissions)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 
ParseChildPermissions(const std::string & base_name,const base::Value * permission_value,APIPermissionSet::ParseSource source,APIPermissionSet * api_permissions,base::string16 * error,std::vector<std::string> * unhandled_permissions)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 
insert(APIPermission::ID id)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 
insert(APIPermission * permission)129 void APIPermissionSet::insert(APIPermission* permission) {
130   BaseSetOperators<APIPermissionSet>::insert(permission);
131 }
132 
133 // static
ParseFromJSON(const base::ListValue * permissions,APIPermissionSet::ParseSource source,APIPermissionSet * api_permissions,base::string16 * error,std::vector<std::string> * unhandled_permissions)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 
AddImpliedPermissions()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