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

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

Issue 15091002: Lazily load API schemas from resource files and convert all APIs to features (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: optimize and "parent" property Created 7 years, 7 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
(...skipping 28 matching lines...) Expand all
39 39
40 const char kUnavailableMessage[] = "You do not have permission to access this " 40 const char kUnavailableMessage[] = "You do not have permission to access this "
41 "API. Ensure that the required permission " 41 "API. Ensure that the required permission "
42 "or manifest property is included in your " 42 "or manifest property is included in your "
43 "manifest.json."; 43 "manifest.json.";
44 const char* kChildKinds[] = { 44 const char* kChildKinds[] = {
45 "functions", 45 "functions",
46 "events" 46 "events"
47 }; 47 };
48 48
49 // Returns true if |dict| has an unprivileged "true" property.
50 bool IsUnprivileged(const DictionaryValue* dict) {
51 bool unprivileged = false;
52 return dict->GetBoolean("unprivileged", &unprivileged) && unprivileged;
53 }
54
55 // Returns whether the list at |name_space_node|.|child_kind| contains any
56 // children with an { "unprivileged": true } property.
57 bool HasUnprivilegedChild(const DictionaryValue* name_space_node,
58 const std::string& child_kind) {
59 const ListValue* child_list = NULL;
60 const DictionaryValue* child_dict = NULL;
61
62 if (name_space_node->GetList(child_kind, &child_list)) {
63 for (size_t i = 0; i < child_list->GetSize(); ++i) {
64 const DictionaryValue* item = NULL;
65 CHECK(child_list->GetDictionary(i, &item));
66 if (IsUnprivileged(item))
67 return true;
68 }
69 } else if (name_space_node->GetDictionary(child_kind, &child_dict)) {
70 for (DictionaryValue::Iterator it(*child_dict); !it.IsAtEnd();
71 it.Advance()) {
72 const DictionaryValue* item = NULL;
73 CHECK(it.value().GetAsDictionary(&item));
74 if (IsUnprivileged(item))
75 return true;
76 }
77 }
78
79 return false;
80 }
81
82 base::StringPiece ReadFromResource(int resource_id) { 49 base::StringPiece ReadFromResource(int resource_id) {
83 return ResourceBundle::GetSharedInstance().GetRawDataResource( 50 return ResourceBundle::GetSharedInstance().GetRawDataResource(
84 resource_id); 51 resource_id);
85 } 52 }
86 53
87 scoped_ptr<ListValue> LoadSchemaList(const std::string& name, 54 scoped_ptr<ListValue> LoadSchemaList(const std::string& name,
88 const base::StringPiece& schema) { 55 const base::StringPiece& schema) {
89 std::string error_message; 56 std::string error_message;
90 scoped_ptr<Value> result( 57 scoped_ptr<Value> result(
91 base::JSONReader::ReadAndReturnError( 58 base::JSONReader::ReadAndReturnError(
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 CHECK(schema->GetList("types", &types)); 159 CHECK(schema->GetList("types", &types));
193 for (size_t i = 0; i < types->GetSize(); ++i) { 160 for (size_t i = 0; i < types->GetSize(); ++i) {
194 DictionaryValue *type = NULL; 161 DictionaryValue *type = NULL;
195 CHECK(types->GetDictionary(i, &type)); 162 CHECK(types->GetDictionary(i, &type));
196 MaybePrefixFieldWithNamespace(schema_namespace, type, "id"); 163 MaybePrefixFieldWithNamespace(schema_namespace, type, "id");
197 MaybePrefixFieldWithNamespace(schema_namespace, type, "customBindings"); 164 MaybePrefixFieldWithNamespace(schema_namespace, type, "customBindings");
198 } 165 }
199 } 166 }
200 167
201 // Modify the schema so that all types are fully qualified. 168 // Modify the schema so that all types are fully qualified.
202 void PrefixWithNamespace(const std::string& schema_namespace, 169 void PrefixWithNamespace(const std::string& schema_namespace,
not at google - send to devlin 2013/05/23 00:09:40 I would love to delete this method. Another time p
203 DictionaryValue* schema) { 170 DictionaryValue* schema) {
204 PrefixTypesWithNamespace(schema_namespace, schema); 171 PrefixTypesWithNamespace(schema_namespace, schema);
205 PrefixRefsWithNamespace(schema_namespace, schema); 172 PrefixRefsWithNamespace(schema_namespace, schema);
206 } 173 }
207 174
208 } // namespace 175 } // namespace
209 176
210 // static 177 // static
211 ExtensionAPI* ExtensionAPI::GetSharedInstance() { 178 ExtensionAPI* ExtensionAPI::GetSharedInstance() {
212 return g_lazy_instance.Get().api.get(); 179 return g_lazy_instance.Get().api.get();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 { 212 {
246 Value* value = NULL; 213 Value* value = NULL;
247 schema_list->Remove(schema_list->GetSize() - 1, &value); 214 schema_list->Remove(schema_list->GetSize() - 1, &value);
248 CHECK(value->IsType(Value::TYPE_DICTIONARY)); 215 CHECK(value->IsType(Value::TYPE_DICTIONARY));
249 schema = static_cast<DictionaryValue*>(value); 216 schema = static_cast<DictionaryValue*>(value);
250 } 217 }
251 218
252 CHECK(schema->GetString("namespace", &schema_namespace)); 219 CHECK(schema->GetString("namespace", &schema_namespace));
253 PrefixWithNamespace(schema_namespace, schema); 220 PrefixWithNamespace(schema_namespace, schema);
254 schemas_[schema_namespace] = make_linked_ptr(schema); 221 schemas_[schema_namespace] = make_linked_ptr(schema);
255 CHECK_EQ(1u, unloaded_schemas_.erase(schema_namespace)); 222 if (!GeneratedSchemas::IsGenerated(schema_namespace)) {
not at google - send to devlin 2013/05/23 00:09:40 don't need {}s anymore.
cduvall 2013/05/24 03:13:49 Done.
256 223 CHECK_EQ(1u, unloaded_schemas_.erase(schema_namespace));
257 // Populate |{completely,partially}_unprivileged_apis_|.
258
259 // For "partially", only need to look at functions/events; even though
260 // there are unprivileged properties (e.g. in extensions), access to those
261 // never reaches C++ land.
262 bool unprivileged = false;
263 if (schema->GetBoolean("unprivileged", &unprivileged) && unprivileged) {
264 completely_unprivileged_apis_.insert(schema_namespace);
265 } else if (HasUnprivilegedChild(schema, "functions") ||
266 HasUnprivilegedChild(schema, "events") ||
267 HasUnprivilegedChild(schema, "properties")) {
268 partially_unprivileged_apis_.insert(schema_namespace);
269 } 224 }
270 } 225 }
271 } 226 }
272 227
273 ExtensionAPI::ExtensionAPI() { 228 ExtensionAPI::ExtensionAPI() {
274 } 229 }
275 230
276 ExtensionAPI::~ExtensionAPI() { 231 ExtensionAPI::~ExtensionAPI() {
277 } 232 }
278 233
279 void ExtensionAPI::InitDefaultConfiguration() { 234 void ExtensionAPI::InitDefaultConfiguration() {
280 RegisterDependencyProvider( 235 RegisterDependencyProvider(
281 "api", BaseFeatureProvider::GetByName("api")); 236 "api", BaseFeatureProvider::GetByName("api"));
282 RegisterDependencyProvider( 237 RegisterDependencyProvider(
283 "manifest", BaseFeatureProvider::GetByName("manifest")); 238 "manifest", BaseFeatureProvider::GetByName("manifest"));
284 RegisterDependencyProvider( 239 RegisterDependencyProvider(
285 "permission", BaseFeatureProvider::GetByName("permission")); 240 "permission", BaseFeatureProvider::GetByName("permission"));
286 241
287 // Schemas to be loaded from resources. 242 // Schemas to be loaded from resources.
288 CHECK(unloaded_schemas_.empty()); 243 CHECK(unloaded_schemas_.empty());
289 RegisterSchema("app", ReadFromResource( 244 RegisterSchemaResource("app", IDR_EXTENSION_API_JSON_APP);
290 IDR_EXTENSION_API_JSON_APP)); 245 RegisterSchemaResource("browserAction", IDR_EXTENSION_API_JSON_BROWSERACTION);
291 RegisterSchema("browserAction", ReadFromResource( 246 RegisterSchemaResource("browsingData", IDR_EXTENSION_API_JSON_BROWSINGDATA);
292 IDR_EXTENSION_API_JSON_BROWSERACTION)); 247 RegisterSchemaResource("commands", IDR_EXTENSION_API_JSON_COMMANDS);
293 RegisterSchema("browsingData", ReadFromResource( 248 RegisterSchemaResource("declarativeContent",
294 IDR_EXTENSION_API_JSON_BROWSINGDATA)); 249 IDR_EXTENSION_API_JSON_DECLARATIVE_CONTENT);
295 RegisterSchema("commands", ReadFromResource( 250 RegisterSchemaResource("declarativeWebRequest",
296 IDR_EXTENSION_API_JSON_COMMANDS)); 251 IDR_EXTENSION_API_JSON_DECLARATIVE_WEBREQUEST);
297 RegisterSchema("declarativeContent", ReadFromResource( 252 RegisterSchemaResource("experimental.input.virtualKeyboard",
298 IDR_EXTENSION_API_JSON_DECLARATIVE_CONTENT)); 253 IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_VIRTUALKEYBOARD);
299 RegisterSchema("declarativeWebRequest", ReadFromResource( 254 RegisterSchemaResource("experimental.processes",
300 IDR_EXTENSION_API_JSON_DECLARATIVE_WEBREQUEST)); 255 IDR_EXTENSION_API_JSON_EXPERIMENTAL_PROCESSES);
301 RegisterSchema("experimental.input.virtualKeyboard", ReadFromResource( 256 RegisterSchemaResource("experimental.rlz",
302 IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_VIRTUALKEYBOARD)); 257 IDR_EXTENSION_API_JSON_EXPERIMENTAL_RLZ);
303 RegisterSchema("experimental.processes", ReadFromResource( 258 RegisterSchemaResource("runtime", IDR_EXTENSION_API_JSON_RUNTIME);
304 IDR_EXTENSION_API_JSON_EXPERIMENTAL_PROCESSES)); 259 RegisterSchemaResource("fileBrowserHandler",
305 RegisterSchema("experimental.rlz", ReadFromResource( 260 IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER);
306 IDR_EXTENSION_API_JSON_EXPERIMENTAL_RLZ)); 261 RegisterSchemaResource("fileBrowserPrivate",
307 RegisterSchema("runtime", ReadFromResource( 262 IDR_EXTENSION_API_JSON_FILEBROWSERPRIVATE);
308 IDR_EXTENSION_API_JSON_RUNTIME)); 263 RegisterSchemaResource("input.ime", IDR_EXTENSION_API_JSON_INPUT_IME);
309 RegisterSchema("fileBrowserHandler", ReadFromResource( 264 RegisterSchemaResource("inputMethodPrivate",
310 IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER)); 265 IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE);
311 RegisterSchema("fileBrowserPrivate", ReadFromResource( 266 RegisterSchemaResource("pageAction", IDR_EXTENSION_API_JSON_PAGEACTION);
312 IDR_EXTENSION_API_JSON_FILEBROWSERPRIVATE)); 267 RegisterSchemaResource("pageActions", IDR_EXTENSION_API_JSON_PAGEACTIONS);
313 RegisterSchema("input.ime", ReadFromResource( 268 RegisterSchemaResource("privacy", IDR_EXTENSION_API_JSON_PRIVACY);
314 IDR_EXTENSION_API_JSON_INPUT_IME)); 269 RegisterSchemaResource("proxy", IDR_EXTENSION_API_JSON_PROXY);
315 RegisterSchema("inputMethodPrivate", ReadFromResource( 270 RegisterSchemaResource("scriptBadge", IDR_EXTENSION_API_JSON_SCRIPTBADGE);
316 IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE)); 271 RegisterSchemaResource("streamsPrivate",
317 RegisterSchema("pageAction", ReadFromResource( 272 IDR_EXTENSION_API_JSON_STREAMSPRIVATE);
318 IDR_EXTENSION_API_JSON_PAGEACTION)); 273 RegisterSchemaResource("ttsEngine", IDR_EXTENSION_API_JSON_TTSENGINE);
319 RegisterSchema("pageActions", ReadFromResource( 274 RegisterSchemaResource("tts", IDR_EXTENSION_API_JSON_TTS);
320 IDR_EXTENSION_API_JSON_PAGEACTIONS)); 275 RegisterSchemaResource("types", IDR_EXTENSION_API_JSON_TYPES);
321 RegisterSchema("privacy", ReadFromResource( 276 RegisterSchemaResource("webRequestInternal",
322 IDR_EXTENSION_API_JSON_PRIVACY)); 277 IDR_EXTENSION_API_JSON_WEBREQUESTINTERNAL);
323 RegisterSchema("proxy", ReadFromResource( 278 RegisterSchemaResource("webstore", IDR_EXTENSION_API_JSON_WEBSTORE);
324 IDR_EXTENSION_API_JSON_PROXY)); 279 RegisterSchemaResource("webstorePrivate",
325 RegisterSchema("scriptBadge", ReadFromResource( 280 IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE);
326 IDR_EXTENSION_API_JSON_SCRIPTBADGE));
327 RegisterSchema("streamsPrivate", ReadFromResource(
328 IDR_EXTENSION_API_JSON_STREAMSPRIVATE));
329 RegisterSchema("ttsEngine", ReadFromResource(
330 IDR_EXTENSION_API_JSON_TTSENGINE));
331 RegisterSchema("tts", ReadFromResource(
332 IDR_EXTENSION_API_JSON_TTS));
333 RegisterSchema("types", ReadFromResource(
334 IDR_EXTENSION_API_JSON_TYPES));
335 RegisterSchema("webRequestInternal", ReadFromResource(
336 IDR_EXTENSION_API_JSON_WEBREQUESTINTERNAL));
337 RegisterSchema("webstore", ReadFromResource(
338 IDR_EXTENSION_API_JSON_WEBSTORE));
339 RegisterSchema("webstorePrivate", ReadFromResource(
340 IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE));
341
342 // Schemas to be loaded via JSON generated from IDL files.
343 GeneratedSchemas::Get(&unloaded_schemas_);
344 } 281 }
345 282
346 void ExtensionAPI::RegisterSchema(const std::string& name, 283 void ExtensionAPI::RegisterSchemaResource(const std::string& name,
347 const base::StringPiece& source) { 284 int resource_id) {
348 unloaded_schemas_[name] = source; 285 unloaded_schemas_[name] = resource_id;
349 } 286 }
350 287
351 void ExtensionAPI::RegisterDependencyProvider(const std::string& name, 288 void ExtensionAPI::RegisterDependencyProvider(const std::string& name,
352 FeatureProvider* provider) { 289 FeatureProvider* provider) {
353 dependency_providers_[name] = provider; 290 dependency_providers_[name] = provider;
354 } 291 }
355 292
356 bool ExtensionAPI::IsAnyFeatureAvailableToContext(const std::string& api_name, 293 bool ExtensionAPI::IsAnyFeatureAvailableToContext(const std::string& api_name,
357 Feature::Context context, 294 Feature::Context context,
358 const GURL& url) { 295 const GURL& url) {
359 FeatureProviderMap::iterator provider = dependency_providers_.find("api"); 296 FeatureProviderMap::iterator provider = dependency_providers_.find("api");
360 CHECK(provider != dependency_providers_.end()); 297 CHECK(provider != dependency_providers_.end());
361 std::set<std::string> features = provider->second->GetAllFeatureNames(); 298 std::vector<std::string> features = provider->second->GetAllFeatureNames();
not at google - send to devlin 2013/05/23 00:09:40 maybe we should make the providers cache their fea
cduvall 2013/05/24 03:13:49 Done.
362 299
363 // Check to see if there are any parts of this API that are allowed in this 300 // Check to see if there are any parts of this API that are allowed in this
364 // context. 301 // context.
365 for (std::set<std::string>::iterator i = features.begin(); 302 for (std::vector<std::string>::iterator i = features.begin();
366 i != features.end(); ++i) { 303 i != features.end(); ++i) {
367 const std::string& feature_name = *i; 304 const std::string& feature_name = *i;
368 if (feature_name != api_name && feature_name.find(api_name + ".") == 0) { 305 if (feature_name != api_name && feature_name.find(api_name + ".") == 0) {
369 if (IsAvailable(feature_name, NULL, context, url).is_available()) 306 if (IsAvailable(feature_name, NULL, context, url).is_available())
370 return true; 307 return true;
371 } 308 }
372 } 309 }
373 return IsAvailable(api_name, NULL, context, url).is_available(); 310 return IsAvailable(api_name, NULL, context, url).is_available();
374 } 311 }
375 312
376 Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name, 313 Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name,
377 const Extension* extension, 314 const Extension* extension,
378 Feature::Context context, 315 Feature::Context context,
379 const GURL& url) { 316 const GURL& url) {
380 std::string feature_type; 317 std::string feature_type;
381 std::string feature_name; 318 std::string feature_name;
382 SplitDependencyName(full_name, &feature_type, &feature_name); 319 SplitDependencyName(full_name, &feature_type, &feature_name);
383 320
384 std::string child_name; 321 std::string child_name;
385 std::string api_name = GetAPINameFromFullName(feature_name, &child_name); 322 std::string api_name = GetAPINameFromFullName(feature_name, &child_name);
386 323
387 Feature* feature = GetFeatureDependency(full_name); 324 Feature* feature = GetFeatureDependency(full_name);
388 325 CHECK(feature);
389 // Check APIs not using the feature system first.
390 if (!feature) {
391 return IsNonFeatureAPIAvailable(api_name, context, extension, url)
392 ? Feature::CreateAvailability(Feature::IS_AVAILABLE,
393 std::string())
394 : Feature::CreateAvailability(Feature::INVALID_CONTEXT,
395 kUnavailableMessage);
396 }
397 326
398 Feature::Availability availability = 327 Feature::Availability availability =
399 feature->IsAvailableToContext(extension, context, url); 328 feature->IsAvailableToContext(extension, context, url);
400 if (!availability.is_available()) 329 if (!availability.is_available())
401 return availability; 330 return availability;
402 331
403 for (std::set<std::string>::iterator iter = feature->dependencies().begin(); 332 for (std::set<std::string>::iterator iter = feature->dependencies().begin();
404 iter != feature->dependencies().end(); ++iter) { 333 iter != feature->dependencies().end(); ++iter) {
405 Feature::Availability dependency_availability = 334 Feature::Availability dependency_availability =
406 IsAvailable(*iter, extension, context, url); 335 IsAvailable(*iter, extension, context, url);
407 if (!dependency_availability.is_available()) 336 if (!dependency_availability.is_available())
408 return dependency_availability; 337 return dependency_availability;
409 } 338 }
410 339
411 return Feature::CreateAvailability(Feature::IS_AVAILABLE, std::string()); 340 return Feature::CreateAvailability(Feature::IS_AVAILABLE, std::string());
412 } 341 }
413 342
414 bool ExtensionAPI::IsPrivileged(const std::string& full_name) { 343 bool ExtensionAPI::IsPrivileged(const std::string& full_name) {
415 std::string child_name; 344 std::string child_name;
416 std::string api_name = GetAPINameFromFullName(full_name, &child_name); 345 std::string api_name = GetAPINameFromFullName(full_name, &child_name);
417 Feature* feature = GetFeatureDependency(full_name); 346 Feature* feature = GetFeatureDependency(full_name);
418 347
419 // First try to use the feature system. 348 CHECK(feature);
420 if (feature) { 349 // An API is 'privileged' if it can only be run in a blessed context.
421 // An API is 'privileged' if it can only be run in a blessed context. 350 return feature->GetContexts()->size() ==
422 return feature->GetContexts()->size() == 351 feature->GetContexts()->count(Feature::BLESSED_EXTENSION_CONTEXT);
not at google - send to devlin 2013/05/23 00:09:40 neat (unless it's empty, but well we're checking t
423 feature->GetContexts()->count(Feature::BLESSED_EXTENSION_CONTEXT);
424 }
425
426 // Get the schema now to populate |completely_unprivileged_apis_|.
427 const DictionaryValue* schema = GetSchema(api_name);
428 // If this API hasn't been converted yet, fall back to the old system.
429 if (completely_unprivileged_apis_.count(api_name))
430 return false;
431
432 if (partially_unprivileged_apis_.count(api_name))
433 return IsChildNamePrivileged(schema, child_name);
434
435 return true;
436 }
437
438 bool ExtensionAPI::IsChildNamePrivileged(const DictionaryValue* name_space_node,
439 const std::string& child_name) {
440 bool unprivileged = false;
441 const DictionaryValue* child = GetSchemaChild(name_space_node, child_name);
442 if (!child || !child->GetBoolean("unprivileged", &unprivileged))
443 return true;
444
445 return !unprivileged;
446 } 352 }
447 353
448 const DictionaryValue* ExtensionAPI::GetSchema(const std::string& full_name) { 354 const DictionaryValue* ExtensionAPI::GetSchema(const std::string& full_name) {
449 std::string child_name; 355 std::string child_name;
450 std::string api_name = GetAPINameFromFullName(full_name, &child_name); 356 std::string api_name = GetAPINameFromFullName(full_name, &child_name);
451 357
452 const DictionaryValue* result = NULL; 358 const DictionaryValue* result = NULL;
453 SchemaMap::iterator maybe_schema = schemas_.find(api_name); 359 SchemaMap::iterator maybe_schema = schemas_.find(api_name);
454 if (maybe_schema != schemas_.end()) { 360 if (maybe_schema != schemas_.end()) {
455 result = maybe_schema->second.get(); 361 result = maybe_schema->second.get();
456 } else { 362 } else {
457 // Might not have loaded yet; or might just not exist. 363 // Might not have loaded yet; or might just not exist.
458 std::map<std::string, base::StringPiece>::iterator maybe_schema_resource = 364 UnloadedSchemaMap::iterator maybe_schema_resource =
459 unloaded_schemas_.find(api_name); 365 unloaded_schemas_.find(api_name);
460 if (maybe_schema_resource == unloaded_schemas_.end()) 366 if (maybe_schema_resource != unloaded_schemas_.end()) {
367 LoadSchema(maybe_schema_resource->first,
368 ReadFromResource(maybe_schema_resource->second));
369 } else if (GeneratedSchemas::IsGenerated(api_name)) {
370 LoadSchema(api_name, GeneratedSchemas::Get(api_name));
371 } else {
461 return NULL; 372 return NULL;
373 }
462 374
463 LoadSchema(maybe_schema_resource->first, maybe_schema_resource->second);
464 maybe_schema = schemas_.find(api_name); 375 maybe_schema = schemas_.find(api_name);
465 CHECK(schemas_.end() != maybe_schema); 376 CHECK(schemas_.end() != maybe_schema);
466 result = maybe_schema->second.get(); 377 result = maybe_schema->second.get();
467 } 378 }
468 379
469 if (!child_name.empty()) 380 if (!child_name.empty())
470 result = GetSchemaChild(result, child_name); 381 result = GetSchemaChild(result, child_name);
471 382
472 return result; 383 return result;
473 } 384 }
474 385
475 namespace {
476
477 const char* kDisallowedPlatformAppFeatures[] = {
478 // "app" refers to the the legacy app namespace for hosted apps.
479 "app",
480 "extension",
481 "tabs",
482 "windows"
483 };
484
485 bool IsFeatureAllowedForExtension(const std::string& feature,
486 const extensions::Extension& extension) {
487 if (extension.is_platform_app()) {
488 for (size_t i = 0; i < arraysize(kDisallowedPlatformAppFeatures); ++i) {
489 if (feature == kDisallowedPlatformAppFeatures[i])
490 return false;
491 }
492 }
493
494 return true;
495 }
496
497 } // namespace
498
499 bool ExtensionAPI::IsNonFeatureAPIAvailable(const std::string& name,
500 Feature::Context context,
501 const Extension* extension,
502 const GURL& url) {
503 // Make sure schema is loaded.
504 GetSchema(name);
505 switch (context) {
506 case Feature::UNSPECIFIED_CONTEXT:
507 break;
508
509 case Feature::BLESSED_EXTENSION_CONTEXT:
510 if (extension) {
511 // Availability is determined by the permissions of the extension.
512 if (!IsAPIAllowed(name, extension))
513 return false;
514 if (!IsFeatureAllowedForExtension(name, *extension))
515 return false;
516 }
517 break;
518
519 case Feature::UNBLESSED_EXTENSION_CONTEXT:
520 case Feature::CONTENT_SCRIPT_CONTEXT:
521 if (extension) {
522 // Same as BLESSED_EXTENSION_CONTEXT, but only those APIs that are
523 // unprivileged.
524 if (!IsAPIAllowed(name, extension))
525 return false;
526 if (!IsPrivilegedAPI(name))
527 return false;
528 }
529 break;
530
531 case Feature::WEB_PAGE_CONTEXT:
532 return false;
533 }
534
535 return true;
536 }
537
538 std::set<std::string> ExtensionAPI::GetAllAPINames() {
539 std::set<std::string> result;
540 for (SchemaMap::iterator i = schemas_.begin(); i != schemas_.end(); ++i)
541 result.insert(i->first);
542 for (UnloadedSchemaMap::iterator i = unloaded_schemas_.begin();
543 i != unloaded_schemas_.end(); ++i) {
544 result.insert(i->first);
545 }
546 return result;
547 }
548
549 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { 386 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) {
550 std::string feature_type; 387 std::string feature_type;
551 std::string feature_name; 388 std::string feature_name;
552 SplitDependencyName(full_name, &feature_type, &feature_name); 389 SplitDependencyName(full_name, &feature_type, &feature_name);
553 390
554 FeatureProviderMap::iterator provider = 391 FeatureProviderMap::iterator provider =
555 dependency_providers_.find(feature_type); 392 dependency_providers_.find(feature_type);
556 if (provider == dependency_providers_.end()) 393 if (provider == dependency_providers_.end())
557 return NULL; 394 return NULL;
558 395
559 Feature* feature = provider->second->GetFeature(feature_name); 396 Feature* feature = provider->second->GetFeature(feature_name);
560 // Try getting the feature for the parent API, if this was a child. 397 // Try getting the feature for the parent API, if this was a child.
561 if (!feature) { 398 if (!feature) {
562 std::string child_name; 399 std::string child_name;
563 feature = provider->second->GetFeature( 400 feature = provider->second->GetFeature(
564 GetAPINameFromFullName(feature_name, &child_name)); 401 GetAPINameFromFullName(feature_name, &child_name));
565 } 402 }
566 return feature; 403 return feature;
567 } 404 }
568 405
569 std::string ExtensionAPI::GetAPINameFromFullName(const std::string& full_name, 406 std::string ExtensionAPI::GetAPINameFromFullName(const std::string& full_name,
570 std::string* child_name) { 407 std::string* child_name) {
571 std::string api_name_candidate = full_name; 408 std::string api_name_candidate = full_name;
572 while (true) { 409 while (true) {
573 if (schemas_.find(api_name_candidate) != schemas_.end() || 410 if (schemas_.find(api_name_candidate) != schemas_.end() ||
411 GeneratedSchemas::IsGenerated(api_name_candidate) ||
574 unloaded_schemas_.find(api_name_candidate) != unloaded_schemas_.end()) { 412 unloaded_schemas_.find(api_name_candidate) != unloaded_schemas_.end()) {
575 std::string result = api_name_candidate; 413 std::string result = api_name_candidate;
576 414
577 if (child_name) { 415 if (child_name) {
578 if (result.length() < full_name.length()) 416 if (result.length() < full_name.length())
579 *child_name = full_name.substr(result.length() + 1); 417 *child_name = full_name.substr(result.length() + 1);
580 else 418 else
581 *child_name = ""; 419 *child_name = "";
582 } 420 }
583 421
584 return result; 422 return result;
585 } 423 }
586 424
587 size_t last_dot_index = api_name_candidate.rfind('.'); 425 size_t last_dot_index = api_name_candidate.rfind('.');
588 if (last_dot_index == std::string::npos) 426 if (last_dot_index == std::string::npos)
589 break; 427 break;
590 428
591 api_name_candidate = api_name_candidate.substr(0, last_dot_index); 429 api_name_candidate = api_name_candidate.substr(0, last_dot_index);
592 } 430 }
593 431
594 *child_name = ""; 432 *child_name = "";
595 return std::string(); 433 return std::string();
596 } 434 }
597 435
598 bool ExtensionAPI::IsAPIAllowed(const std::string& name,
599 const Extension* extension) {
600 return PermissionsData::GetRequiredPermissions(extension)->
601 HasAnyAccessToAPI(name) ||
602 PermissionsData::GetOptionalPermissions(extension)->
603 HasAnyAccessToAPI(name);
604 }
605
606 bool ExtensionAPI::IsPrivilegedAPI(const std::string& name) {
607 return completely_unprivileged_apis_.count(name) ||
608 partially_unprivileged_apis_.count(name);
609 }
610
611 } // namespace extensions 436 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698