Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / extensions / common / permissions / api_permission_set.cc
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       if (error) {
47         if (error_details.empty()) {
48           *error = ErrorUtils::FormatErrorMessageUTF16(
49               errors::kInvalidPermission,
50               permission_info->name());
51         } else {
52           *error = ErrorUtils::FormatErrorMessageUTF16(
53               errors::kInvalidPermissionWithDetail,
54               permission_info->name(),
55               error_details);
56         }
57         return false;
58       }
59       LOG(WARNING) << "Parse permission failed.";
60     } else {
61       api_permissions->insert(permission.release());
62     }
63     return true;
64   }
65
66   if (unhandled_permissions)
67     unhandled_permissions->push_back(permission_str);
68   else
69     LOG(WARNING) << "Unknown permission[" << permission_str << "].";
70
71   return true;
72 }
73
74 bool ParseChildPermissions(const std::string& base_name,
75                            const base::Value* permission_value,
76                            APIPermissionSet::ParseSource source,
77                            APIPermissionSet* api_permissions,
78                            base::string16* error,
79                            std::vector<std::string>* unhandled_permissions) {
80   if (permission_value) {
81     const base::ListValue* permissions;
82     if (!permission_value->GetAsList(&permissions)) {
83       if (error) {
84         *error = ErrorUtils::FormatErrorMessageUTF16(
85             errors::kInvalidPermission, base_name);
86         return false;
87       }
88       LOG(WARNING) << "Permission value is not a list.";
89       // Failed to parse, but since error is NULL, failures are not fatal so
90       // return true here anyway.
91       return true;
92     }
93
94     for (size_t i = 0; i < permissions->GetSize(); ++i) {
95       std::string permission_str;
96       if (!permissions->GetString(i, &permission_str)) {
97         // permission should be a string
98         if (error) {
99           *error = ErrorUtils::FormatErrorMessageUTF16(
100               errors::kInvalidPermission,
101               base_name + '.' + base::IntToString(i));
102           return false;
103         }
104         LOG(WARNING) << "Permission is not a string.";
105         continue;
106       }
107
108       if (!CreateAPIPermission(
109               base_name + '.' + permission_str, NULL, source,
110               api_permissions, error, unhandled_permissions))
111         return false;
112     }
113   }
114
115   return CreateAPIPermission(base_name, NULL, source,
116                              api_permissions, error, NULL);
117 }
118
119 }  // namespace
120
121 void APIPermissionSet::insert(APIPermission::ID id) {
122   const APIPermissionInfo* permission_info =
123       PermissionsInfo::GetInstance()->GetByID(id);
124   DCHECK(permission_info);
125   insert(permission_info->CreateAPIPermission());
126 }
127
128 void APIPermissionSet::insert(APIPermission* permission) {
129   BaseSetOperators<APIPermissionSet>::insert(permission);
130 }
131
132 // static
133 bool APIPermissionSet::ParseFromJSON(
134     const base::ListValue* permissions,
135     APIPermissionSet::ParseSource source,
136     APIPermissionSet* api_permissions,
137     base::string16* error,
138     std::vector<std::string>* unhandled_permissions) {
139   for (size_t i = 0; i < permissions->GetSize(); ++i) {
140     std::string permission_str;
141     const base::Value* permission_value = NULL;
142     if (!permissions->GetString(i, &permission_str)) {
143       const base::DictionaryValue* dict = NULL;
144       // permission should be a string or a single key dict.
145       if (!permissions->GetDictionary(i, &dict) || dict->size() != 1) {
146         if (error) {
147           *error = ErrorUtils::FormatErrorMessageUTF16(
148               errors::kInvalidPermission, base::IntToString(i));
149           return false;
150         }
151         LOG(WARNING) << "Permission is not a string or single key dict.";
152         continue;
153       }
154       base::DictionaryValue::Iterator it(*dict);
155       permission_str = it.key();
156       permission_value = &it.value();
157     }
158
159     // Check if this permission is a special case where its value should
160     // be treated as a list of child permissions.
161     if (PermissionsInfo::GetInstance()->HasChildPermissions(permission_str)) {
162       if (!ParseChildPermissions(permission_str, permission_value, source,
163                                  api_permissions, error, unhandled_permissions))
164         return false;
165       continue;
166     }
167
168     if (!CreateAPIPermission(permission_str, permission_value, source,
169                              api_permissions, error, unhandled_permissions))
170       return false;
171   }
172   return true;
173 }
174
175 void APIPermissionSet::AddImpliedPermissions() {
176   // The fileSystem.write and fileSystem.directory permissions imply
177   // fileSystem.writeDirectory.
178   // TODO(sammc): Remove this. See http://crbug.com/284849.
179   if (ContainsKey(map(), APIPermission::kFileSystemWrite) &&
180       ContainsKey(map(), APIPermission::kFileSystemDirectory)) {
181     insert(APIPermission::kFileSystemWriteDirectory);
182   }
183 }
184
185 }  // namespace extensions