Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: chrome/common/extensions/api/extension_api.cc

Issue 9653022: Revert 125811 - Convert app_bindings.js to the schema_generated_bindings.js infrastructure. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 <algorithm>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/json/json_reader.h" 11 #include "base/json/json_reader.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/string_split.h" 13 #include "base/string_split.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "chrome/common/extensions/extension.h" 16 #include "chrome/common/extensions/extension.h"
17 #include "chrome/common/extensions/extension_permission_set.h" 17 #include "chrome/common/extensions/extension_permission_set.h"
18 #include "googleurl/src/gurl.h"
19 #include "grit/common_resources.h" 18 #include "grit/common_resources.h"
20 #include "ui/base/resource/resource_bundle.h" 19 #include "ui/base/resource/resource_bundle.h"
21 20
22 namespace extensions { 21 namespace extensions {
23 22
24 namespace { 23 namespace {
25 24
25 // Adds any APIs listed in "dependencies" found in |schema| but not in
26 // |reference| to |out|.
27 void GetMissingDependencies(
28 const DictionaryValue& schema,
29 const ExtensionAPI::SchemaMap& reference,
30 std::set<std::string>* out) {
31 ListValue* dependencies = NULL;
32 if (!schema.GetList("dependencies", &dependencies))
33 return;
34 for (size_t i = 0; i < dependencies->GetSize(); ++i) {
35 std::string api_name;
36 if (dependencies->GetString(i, &api_name) && !reference.count(api_name))
37 out->insert(api_name);
38 }
39 }
40
26 // Returns whether the list at |name_space_node|.|child_kind| contains any 41 // Returns whether the list at |name_space_node|.|child_kind| contains any
27 // children with an { "unprivileged": true } property. 42 // children with an { "unprivileged": true } property.
28 bool HasUnprivilegedChild(const DictionaryValue* name_space_node, 43 bool HasUnprivilegedChild(const DictionaryValue* name_space_node,
29 const std::string& child_kind) { 44 const std::string& child_kind) {
30 ListValue* child_list = NULL; 45 ListValue* child_list = NULL;
31 name_space_node->GetList(child_kind, &child_list); 46 name_space_node->GetList(child_kind, &child_list);
32 if (!child_list) 47 if (!child_list)
33 return false; 48 return false;
34 49
35 for (size_t i = 0; i < child_list->GetSize(); ++i) { 50 for (size_t i = 0; i < child_list->GetSize(); ++i) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 loaded->Remove(loaded->GetSize() - 1, &value); 88 loaded->Remove(loaded->GetSize() - 1, &value);
74 CHECK(value->IsType(Value::TYPE_DICTIONARY)); 89 CHECK(value->IsType(Value::TYPE_DICTIONARY));
75 const DictionaryValue* schema = static_cast<const DictionaryValue*>(value); 90 const DictionaryValue* schema = static_cast<const DictionaryValue*>(value);
76 CHECK(schema->GetString("namespace", &schema_namespace)); 91 CHECK(schema->GetString("namespace", &schema_namespace));
77 schemas_[schema_namespace] = linked_ptr<const DictionaryValue>(schema); 92 schemas_[schema_namespace] = linked_ptr<const DictionaryValue>(schema);
78 } 93 }
79 } 94 }
80 95
81 ExtensionAPI::ExtensionAPI() { 96 ExtensionAPI::ExtensionAPI() {
82 static int kJsonApiResourceIds[] = { 97 static int kJsonApiResourceIds[] = {
83 IDR_EXTENSION_API_JSON_APP,
84 IDR_EXTENSION_API_JSON_BOOKMARKS, 98 IDR_EXTENSION_API_JSON_BOOKMARKS,
85 IDR_EXTENSION_API_JSON_BROWSERACTION, 99 IDR_EXTENSION_API_JSON_BROWSERACTION,
86 IDR_EXTENSION_API_JSON_BROWSING_DATA, 100 IDR_EXTENSION_API_JSON_BROWSING_DATA,
87 IDR_EXTENSION_API_JSON_CHROMEAUTHPRIVATE, 101 IDR_EXTENSION_API_JSON_CHROMEAUTHPRIVATE,
88 IDR_EXTENSION_API_JSON_CHROMEOSINFOPRIVATE, 102 IDR_EXTENSION_API_JSON_CHROMEOSINFOPRIVATE,
89 IDR_EXTENSION_API_JSON_CHROMEPRIVATE, 103 IDR_EXTENSION_API_JSON_CHROMEPRIVATE,
90 IDR_EXTENSION_API_JSON_CONTENTSETTINGS, 104 IDR_EXTENSION_API_JSON_CONTENTSETTINGS,
91 IDR_EXTENSION_API_JSON_CONTEXTMENUS, 105 IDR_EXTENSION_API_JSON_CONTEXTMENUS,
92 IDR_EXTENSION_API_JSON_COOKIES, 106 IDR_EXTENSION_API_JSON_COOKIES,
93 IDR_EXTENSION_API_JSON_DEBUGGER, 107 IDR_EXTENSION_API_JSON_DEBUGGER,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 continue; 171 continue;
158 } 172 }
159 173
160 // Only need to look at functions/events; even though there are unprivileged 174 // Only need to look at functions/events; even though there are unprivileged
161 // properties (e.g. in extensions), access to those never reaches C++ land. 175 // properties (e.g. in extensions), access to those never reaches C++ land.
162 if (HasUnprivilegedChild(it->second.get(), "functions") || 176 if (HasUnprivilegedChild(it->second.get(), "functions") ||
163 HasUnprivilegedChild(it->second.get(), "events")) { 177 HasUnprivilegedChild(it->second.get(), "events")) {
164 partially_unprivileged_apis_.insert(it->first); 178 partially_unprivileged_apis_.insert(it->first);
165 } 179 }
166 } 180 }
167
168 // Populate |url_matching_apis_|.
169 for (SchemaMap::const_iterator it = schemas_.begin();
170 it != schemas_.end(); ++it) {
171 ListValue* matches = NULL;
172 {
173 Value* matches_value = NULL;
174 if (!it->second->Get("matches", &matches_value))
175 continue;
176 CHECK_EQ(Value::TYPE_LIST, matches_value->GetType());
177 matches = static_cast<ListValue*>(matches_value);
178 }
179 URLPatternSet pattern_set;
180 for (size_t i = 0; i < matches->GetSize(); ++i) {
181 std::string pattern;
182 CHECK(matches->GetString(i, &pattern));
183 pattern_set.AddPattern(
184 URLPattern(UserScript::kValidUserScriptSchemes, pattern));
185 }
186 url_matching_apis_[it->first] = pattern_set;
187 }
188 } 181 }
189 182
190 ExtensionAPI::~ExtensionAPI() { 183 ExtensionAPI::~ExtensionAPI() {
191 } 184 }
192 185
193 bool ExtensionAPI::IsPrivileged(const std::string& full_name) const { 186 bool ExtensionAPI::IsPrivileged(const std::string& full_name) const {
194 std::string api_name; 187 std::string api_name;
195 std::string child_name; 188 std::string child_name;
196 189
197 { 190 {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 250
258 return !unprivileged; 251 return !unprivileged;
259 } 252 }
260 253
261 const base::DictionaryValue* ExtensionAPI::GetSchema( 254 const base::DictionaryValue* ExtensionAPI::GetSchema(
262 const std::string& api_name) const { 255 const std::string& api_name) const {
263 SchemaMap::const_iterator maybe_schema = schemas_.find(api_name); 256 SchemaMap::const_iterator maybe_schema = schemas_.find(api_name);
264 return maybe_schema != schemas_.end() ? maybe_schema->second.get() : NULL; 257 return maybe_schema != schemas_.end() ? maybe_schema->second.get() : NULL;
265 } 258 }
266 259
267 scoped_ptr<std::set<std::string> > ExtensionAPI::GetAPIsForContext( 260 void ExtensionAPI::GetSchemasForExtension(const Extension& extension,
268 Feature::Context context, 261 GetSchemasFilter filter,
269 const Extension* extension, 262 SchemaMap* out) const {
270 const GURL& url) const { 263 // Check both required_permissions and optional_permissions since we need
271 scoped_ptr<std::set<std::string> > result(new std::set<std::string>()); 264 // to return all schemas that might be needed.
265 GetSchemasForPermissions(*extension.required_permission_set(), filter, out);
266 GetSchemasForPermissions(*extension.optional_permission_set(), filter, out);
272 267
273 switch (context) { 268 // Note that dependency resolution might introduce APIs outside of the filter
274 case Feature::UNSPECIFIED_CONTEXT: 269 // (for example, "extensions" has unprivileged componenents but relies on
275 break; 270 // "tabs" which doesn't). It doesn't matter because schema_generated_bindings
276 271 // does individual function/event based checking anyway, but it's a shame.
277 case Feature::PRIVILEGED_CONTEXT: 272 ResolveDependencies(out);
278 // Availability is determined by the permissions of the extension.
279 CHECK(extension);
280 GetAllowedAPIs(extension, result.get());
281 ResolveDependencies(result.get());
282 break;
283
284 case Feature::UNPRIVILEGED_CONTEXT:
285 case Feature::CONTENT_SCRIPT_CONTEXT:
286 // Availability is determined by the permissions of the extension
287 // (but only those APIs that are unprivileged).
288 CHECK(extension);
289 GetAllowedAPIs(extension, result.get());
290 // Resolving dependencies before removing unprivileged APIs means that
291 // some unprivileged APIs may have unrealised dependencies. Too bad!
292 ResolveDependencies(result.get());
293 RemovePrivilegedAPIs(result.get());
294 break;
295
296 case Feature::WEB_PAGE_CONTEXT:
297 // Availablility is determined by the url.
298 CHECK(url.is_valid());
299 GetAPIsMatchingURL(url, result.get());
300 break;
301 }
302
303 return result.Pass();
304 } 273 }
305 274
306 void ExtensionAPI::GetAllowedAPIs( 275 void ExtensionAPI::ResolveDependencies(SchemaMap* out) const {
307 const Extension* extension, std::set<std::string>* out) const { 276 std::set<std::string> missing_dependencies;
308 for (SchemaMap::const_iterator i = schemas_.begin(); i != schemas_.end(); 277 for (SchemaMap::const_iterator i = out->begin(); i != out->end(); ++i)
309 ++i) { 278 GetMissingDependencies(*i->second, *out, &missing_dependencies);
310 if (extension->required_permission_set()->HasAnyAccessToAPI(i->first) || 279
311 extension->optional_permission_set()->HasAnyAccessToAPI(i->first)) { 280 while (missing_dependencies.size()) {
312 out->insert(i->first); 281 std::string api_name = *missing_dependencies.begin();
313 } 282 missing_dependencies.erase(api_name);
283 linked_ptr<const DictionaryValue> schema = schemas_.find(api_name)->second;
284 (*out)[api_name] = schema;
285 GetMissingDependencies(*schema, *out, &missing_dependencies);
314 } 286 }
315 } 287 }
316 288
317 void ExtensionAPI::ResolveDependencies(std::set<std::string>* out) const { 289 void ExtensionAPI::GetDefaultSchemas(GetSchemasFilter filter,
318 std::set<std::string> missing_dependencies; 290 SchemaMap* out) const {
319 for (std::set<std::string>::iterator i = out->begin(); i != out->end(); ++i) 291 scoped_refptr<ExtensionPermissionSet> default_permissions(
320 GetMissingDependencies(*i, *out, &missing_dependencies); 292 new ExtensionPermissionSet());
293 GetSchemasForPermissions(*default_permissions, filter, out);
294 ResolveDependencies(out);
295 }
321 296
322 while (missing_dependencies.size()) { 297 void ExtensionAPI::GetSchemasForPermissions(
323 std::string next = *missing_dependencies.begin(); 298 const ExtensionPermissionSet& permissions,
324 missing_dependencies.erase(next); 299 GetSchemasFilter filter,
325 out->insert(next); 300 SchemaMap* out) const {
326 GetMissingDependencies(next, *out, &missing_dependencies); 301 for (SchemaMap::const_iterator it = schemas_.begin(); it != schemas_.end();
302 ++it) {
303 if (filter == ONLY_UNPRIVILEGED && IsWholeAPIPrivileged(it->first))
304 continue;
305 if (permissions.HasAnyAccessToAPI(it->first))
306 (*out)[it->first] = it->second;
327 } 307 }
328 } 308 }
329 309
330 void ExtensionAPI::GetMissingDependencies( 310 bool ExtensionAPI::IsWholeAPIPrivileged(const std::string& api_name) const {
331 const std::string& api_name, 311 return !completely_unprivileged_apis_.count(api_name) &&
332 const std::set<std::string>& excluding, 312 !partially_unprivileged_apis_.count(api_name);
333 std::set<std::string>* out) const {
334 const base::DictionaryValue* schema = GetSchema(api_name);
335 CHECK(schema) << "Schema for " << api_name << " not found";
336
337 ListValue* dependencies = NULL;
338 if (!schema->GetList("dependencies", &dependencies))
339 return;
340
341 for (size_t i = 0; i < dependencies->GetSize(); ++i) {
342 std::string api_name;
343 if (dependencies->GetString(i, &api_name) && !excluding.count(api_name))
344 out->insert(api_name);
345 }
346 }
347
348 void ExtensionAPI::RemovePrivilegedAPIs(std::set<std::string>* apis) const {
349 std::set<std::string> privileged_apis;
350 for (std::set<std::string>::iterator i = apis->begin(); i != apis->end();
351 ++i) {
352 if (!completely_unprivileged_apis_.count(*i) &&
353 !partially_unprivileged_apis_.count(*i)) {
354 privileged_apis.insert(*i);
355 }
356 }
357 for (std::set<std::string>::iterator i = privileged_apis.begin();
358 i != privileged_apis.end(); ++i) {
359 apis->erase(*i);
360 }
361 }
362
363 void ExtensionAPI::GetAPIsMatchingURL(const GURL& url,
364 std::set<std::string>* out) const {
365 for (std::map<std::string, URLPatternSet>::const_iterator i =
366 url_matching_apis_.begin(); i != url_matching_apis_.end(); ++i) {
367 if (i->second.MatchesURL(url))
368 out->insert(i->first);
369 }
370 } 313 }
371 314
372 } // namespace extensions 315 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/common/extensions/api/extension_api.h ('k') | chrome/common/extensions/api/extension_api_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698