Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/common/extensions/api/extension_api.h" | 5 #include "chrome/common/extensions/api/extension_api.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 7 #include <string> | 8 #include <string> |
| 8 #include <vector> | 9 #include <vector> |
| 9 | 10 |
| 10 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
| 11 #include "base/logging.h" | 12 #include "base/logging.h" |
| 12 #include "base/string_split.h" | 13 #include "base/string_split.h" |
| 13 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 14 #include "base/values.h" | 15 #include "base/values.h" |
| 15 #include "chrome/common/extensions/extension.h" | 16 #include "chrome/common/extensions/extension.h" |
| 16 #include "chrome/common/extensions/extension_permission_set.h" | 17 #include "chrome/common/extensions/extension_permission_set.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 30 ListValue* dependencies = NULL; | 31 ListValue* dependencies = NULL; |
| 31 if (!schema.GetList("dependencies", &dependencies)) | 32 if (!schema.GetList("dependencies", &dependencies)) |
| 32 return; | 33 return; |
| 33 for (size_t i = 0; i < dependencies->GetSize(); ++i) { | 34 for (size_t i = 0; i < dependencies->GetSize(); ++i) { |
| 34 std::string api_name; | 35 std::string api_name; |
| 35 if (dependencies->GetString(i, &api_name) && !reference.count(api_name)) | 36 if (dependencies->GetString(i, &api_name) && !reference.count(api_name)) |
| 36 out->insert(api_name); | 37 out->insert(api_name); |
| 37 } | 38 } |
| 38 } | 39 } |
| 39 | 40 |
| 41 // Returns whether the list at |name_space_node|.|child_kind| contains any | |
| 42 // children with an { "unprivileged": true } property. | |
| 43 bool HasUnprivilegedChild(const DictionaryValue* name_space_node, | |
| 44 const std::string& child_kind) { | |
| 45 ListValue* child_list = NULL; | |
| 46 name_space_node->GetList(child_kind, &child_list); | |
| 47 if (!child_list) | |
| 48 return false; | |
| 49 | |
| 50 for (size_t i = 0; i < child_list->GetSize(); ++i) { | |
| 51 DictionaryValue* item = NULL; | |
| 52 CHECK(child_list->GetDictionary(i, &item)); | |
| 53 bool unprivileged = false; | |
| 54 if (item->GetBoolean("unprivileged", &unprivileged)) | |
| 55 return unprivileged; | |
| 56 } | |
| 57 | |
| 58 return false; | |
| 59 } | |
| 60 | |
| 40 } // namespace | 61 } // namespace |
| 41 | 62 |
| 42 // static | 63 // static |
| 43 ExtensionAPI* ExtensionAPI::GetInstance() { | 64 ExtensionAPI* ExtensionAPI::GetInstance() { |
| 44 return Singleton<ExtensionAPI>::get(); | 65 return Singleton<ExtensionAPI>::get(); |
| 45 } | 66 } |
| 46 | 67 |
| 47 static base::ListValue* LoadSchemaList(int resource_id) { | 68 static base::ListValue* LoadSchemaList(int resource_id) { |
| 48 const bool kAllowTrailingCommas = false; | 69 const bool kAllowTrailingCommas = false; |
| 49 std::string error_message; | 70 std::string error_message; |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 IDR_EXTENSION_API_JSON_WEBNAVIGATION, | 151 IDR_EXTENSION_API_JSON_WEBNAVIGATION, |
| 131 IDR_EXTENSION_API_JSON_WEBREQUEST, | 152 IDR_EXTENSION_API_JSON_WEBREQUEST, |
| 132 IDR_EXTENSION_API_JSON_WEBSOCKETPROXYPRIVATE, | 153 IDR_EXTENSION_API_JSON_WEBSOCKETPROXYPRIVATE, |
| 133 IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE, | 154 IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE, |
| 134 IDR_EXTENSION_API_JSON_WINDOWS, | 155 IDR_EXTENSION_API_JSON_WINDOWS, |
| 135 }; | 156 }; |
| 136 | 157 |
| 137 for (size_t i = 0; i < arraysize(kJsonApiResourceIds); i++) { | 158 for (size_t i = 0; i < arraysize(kJsonApiResourceIds); i++) { |
| 138 LoadSchemaFromResource(kJsonApiResourceIds[i]); | 159 LoadSchemaFromResource(kJsonApiResourceIds[i]); |
| 139 } | 160 } |
| 161 | |
| 162 // Populate {completely,partially}_unprivileged_apis_. | |
| 163 for (SchemaMap::iterator it = schemas_.begin(); it != schemas_.end(); ++it) { | |
| 164 bool unprivileged = false; | |
| 165 it->second->GetBoolean("unprivileged", &unprivileged); | |
| 166 if (unprivileged) { | |
| 167 completely_unprivileged_apis_.insert(it->first); | |
| 168 continue; | |
| 169 } | |
| 170 | |
| 171 // Only need to look at functions/events; even though there are unprivileged | |
| 172 // properties (e.g. in extensions), access to those never reaches C++ land. | |
| 173 if (HasUnprivilegedChild(it->second.get(), "functions") || | |
| 174 HasUnprivilegedChild(it->second.get(), "events")) { | |
| 175 partially_unprivileged_apis_.insert(it->first); | |
| 176 } | |
| 177 } | |
| 140 } | 178 } |
| 141 | 179 |
| 142 ExtensionAPI::~ExtensionAPI() { | 180 ExtensionAPI::~ExtensionAPI() { |
| 143 } | 181 } |
| 144 | 182 |
| 145 bool ExtensionAPI::IsPrivileged(const std::string& full_name) const { | 183 bool ExtensionAPI::IsPrivileged(const std::string& full_name) const { |
| 146 std::vector<std::string> split_full_name; | 184 std::string api_name; |
|
Aaron Boodman
2012/02/16 00:17:13
This is going to be replaced with Feature stuff ev
not at google - send to devlin
2012/02/16 01:45:53
mos def.
| |
| 147 base::SplitString(full_name, '.', &split_full_name); | 185 std::string child_name; |
| 148 std::string name = split_full_name.back(); | |
| 149 split_full_name.pop_back(); | |
| 150 std::string name_space = JoinString(split_full_name, '.'); | |
| 151 | 186 |
| 152 // HACK(kalman): explicitly mark all Storage API methods as unprivileged. | 187 { |
| 153 // TODO(kalman): solve this in a more general way; the problem is that | 188 std::vector<std::string> split; |
| 154 // functions-on-properties are not found with the following algorithm. | 189 base::SplitString(full_name, '.', &split); |
| 155 if (name_space == "storage") | 190 std::reverse(split.begin(), split.end()); |
| 191 | |
| 192 api_name = split.back(); | |
| 193 split.pop_back(); | |
| 194 if (api_name == "experimental") { | |
| 195 api_name += "." + split.back(); | |
| 196 split.pop_back(); | |
| 197 } | |
| 198 | |
| 199 // This only really works properly if split.size() == 1, however: | |
| 200 // - if it's empty, it's ok to leave child_name empty; presumably there's | |
| 201 // no functions or events with empty names. | |
| 202 // - if it's > 1, we can just do our best. | |
| 203 if (split.size() > 0) | |
| 204 child_name = split[0]; | |
| 205 } | |
| 206 | |
| 207 if (completely_unprivileged_apis_.count(api_name)) | |
| 156 return false; | 208 return false; |
| 157 | 209 |
| 158 const base::DictionaryValue* name_space_node = GetSchema(name_space); | 210 if (partially_unprivileged_apis_.count(api_name)) { |
| 159 if (!name_space_node) | 211 const DictionaryValue* schema = GetSchema(api_name); |
| 160 return true; | 212 return IsChildNamePrivileged(schema, "functions", child_name) && |
| 161 | 213 IsChildNamePrivileged(schema, "events", child_name); |
| 162 if (!IsChildNamePrivileged(name_space_node, "functions", name) || | |
| 163 !IsChildNamePrivileged(name_space_node, "events", name)) { | |
| 164 return false; | |
| 165 } | 214 } |
| 166 | 215 |
| 167 return true; | 216 return true; |
| 168 } | 217 } |
| 169 | 218 |
| 170 DictionaryValue* ExtensionAPI::FindListItem( | 219 DictionaryValue* ExtensionAPI::FindListItem( |
| 171 const base::ListValue* list, | 220 const base::ListValue* list, |
| 172 const std::string& property_name, | 221 const std::string& property_name, |
| 173 const std::string& property_value) const { | 222 const std::string& property_value) const { |
| 174 for (size_t i = 0; i < list->GetSize(); ++i) { | 223 for (size_t i = 0; i < list->GetSize(); ++i) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 | 285 |
| 237 void ExtensionAPI::GetSchemasForPermissions( | 286 void ExtensionAPI::GetSchemasForPermissions( |
| 238 const ExtensionPermissionSet& permissions, SchemaMap* out) const { | 287 const ExtensionPermissionSet& permissions, SchemaMap* out) const { |
| 239 for (SchemaMap::const_iterator it = schemas_.begin(); it != schemas_.end(); | 288 for (SchemaMap::const_iterator it = schemas_.begin(); it != schemas_.end(); |
| 240 ++it) { | 289 ++it) { |
| 241 if (permissions.HasAnyAccessToAPI(it->first)) | 290 if (permissions.HasAnyAccessToAPI(it->first)) |
| 242 (*out)[it->first] = it->second; | 291 (*out)[it->first] = it->second; |
| 243 } | 292 } |
| 244 } | 293 } |
| 245 | 294 |
| 295 bool ExtensionAPI::IsWholeAPIPrivileged(const std::string& api_name) const { | |
| 296 return !completely_unprivileged_apis_.count(api_name) && | |
| 297 !partially_unprivileged_apis_.count(api_name); | |
| 246 } | 298 } |
| 299 | |
| 300 } // namespace extensions | |
| OLD | NEW |