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

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

Issue 12770020: Revert 190836 "Implement API features for the Extension API feat..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 8 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 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 // TODO(aa): Remove this code when all API descriptions have been updated. 227 // TODO(aa): Remove this code when all API descriptions have been updated.
228 *feature_type = "api"; 228 *feature_type = "api";
229 *feature_name = full_name; 229 *feature_name = full_name;
230 return; 230 return;
231 } 231 }
232 232
233 *feature_type = full_name.substr(0, colon_index); 233 *feature_type = full_name.substr(0, colon_index);
234 *feature_name = full_name.substr(colon_index + 1); 234 *feature_name = full_name.substr(colon_index + 1);
235 } 235 }
236 236
237 bool ExtensionAPI::UsesFeatureSystem(const std::string& full_name) {
238 std::string api_name = GetAPINameFromFullName(full_name, NULL);
239 return features_.find(api_name) != features_.end();
240 }
241
237 void ExtensionAPI::LoadSchema(const std::string& name, 242 void ExtensionAPI::LoadSchema(const std::string& name,
238 const base::StringPiece& schema) { 243 const base::StringPiece& schema) {
239 scoped_ptr<ListValue> schema_list(LoadSchemaList(name, schema)); 244 scoped_ptr<ListValue> schema_list(LoadSchemaList(name, schema));
240 std::string schema_namespace; 245 std::string schema_namespace;
241 246
242 while (!schema_list->empty()) { 247 while (!schema_list->empty()) {
243 DictionaryValue* schema = NULL; 248 DictionaryValue* schema = NULL;
244 { 249 {
245 Value* value = NULL; 250 Value* value = NULL;
246 schema_list->Remove(schema_list->GetSize() - 1, &value); 251 schema_list->Remove(schema_list->GetSize() - 1, &value);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 child_feature->set_name(schema_namespace + "." + child_name); 325 child_feature->set_name(schema_namespace + "." + child_name);
321 CHECK(schema_features->insert( 326 CHECK(schema_features->insert(
322 std::make_pair(child_name, 327 std::make_pair(child_name,
323 make_linked_ptr(child_feature.release()))).second); 328 make_linked_ptr(child_feature.release()))).second);
324 } 329 }
325 } 330 }
326 } 331 }
327 } 332 }
328 333
329 ExtensionAPI::ExtensionAPI() { 334 ExtensionAPI::ExtensionAPI() {
335 RegisterDependencyProvider("api", this);
336
337 // TODO(aa): Can remove this when all JSON files are converted.
338 RegisterDependencyProvider("", this);
330 } 339 }
331 340
332 ExtensionAPI::~ExtensionAPI() { 341 ExtensionAPI::~ExtensionAPI() {
333 } 342 }
334 343
335 void ExtensionAPI::InitDefaultConfiguration() { 344 void ExtensionAPI::InitDefaultConfiguration() {
336 RegisterDependencyProvider( 345 RegisterDependencyProvider(
337 "api", BaseFeatureProvider::GetApiFeatures());
338 RegisterDependencyProvider(
339 "manifest", BaseFeatureProvider::GetManifestFeatures()); 346 "manifest", BaseFeatureProvider::GetManifestFeatures());
340 RegisterDependencyProvider( 347 RegisterDependencyProvider(
341 "permission", BaseFeatureProvider::GetPermissionFeatures()); 348 "permission", BaseFeatureProvider::GetPermissionFeatures());
342 349
343 // Schemas to be loaded from resources. 350 // Schemas to be loaded from resources.
344 CHECK(unloaded_schemas_.empty()); 351 CHECK(unloaded_schemas_.empty());
345 RegisterSchema("app", ReadFromResource( 352 RegisterSchema("app", ReadFromResource(
346 IDR_EXTENSION_API_JSON_APP)); 353 IDR_EXTENSION_API_JSON_APP));
347 RegisterSchema("browserAction", ReadFromResource( 354 RegisterSchema("browserAction", ReadFromResource(
348 IDR_EXTENSION_API_JSON_BROWSERACTION)); 355 IDR_EXTENSION_API_JSON_BROWSERACTION));
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 415
409 void ExtensionAPI::RegisterDependencyProvider(const std::string& name, 416 void ExtensionAPI::RegisterDependencyProvider(const std::string& name,
410 FeatureProvider* provider) { 417 FeatureProvider* provider) {
411 dependency_providers_[name] = provider; 418 dependency_providers_[name] = provider;
412 } 419 }
413 420
414 Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name, 421 Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name,
415 const Extension* extension, 422 const Extension* extension,
416 Feature::Context context, 423 Feature::Context context,
417 const GURL& url) { 424 const GURL& url) {
418 std::string feature_type; 425 std::set<std::string> dependency_names;
419 std::string feature_name; 426 dependency_names.insert(full_name);
420 SplitDependencyName(full_name, &feature_type, &feature_name); 427 ResolveDependencies(&dependency_names);
421
422 std::string child_name;
423 std::string api_name = GetAPINameFromFullName(feature_name, &child_name);
424
425 Feature* feature = GetFeatureDependency(full_name);
426 428
427 // Check APIs not using the feature system first. 429 // Check APIs not using the feature system first.
428 if (!feature) { 430 if (!UsesFeatureSystem(full_name)) {
429 return IsNonFeatureAPIAvailable(api_name, context, extension, url) ? 431 return IsNonFeatureAPIAvailable(full_name, context, extension, url) ?
430 Feature::CreateAvailability(Feature::IS_AVAILABLE, "") : 432 Feature::CreateAvailability(Feature::IS_AVAILABLE, "") :
431 Feature::CreateAvailability(Feature::INVALID_CONTEXT, 433 Feature::CreateAvailability(Feature::INVALID_CONTEXT,
432 kUnavailableMessage); 434 kUnavailableMessage);
433 } 435 }
434 436
435 Feature::Availability availability = 437 for (std::set<std::string>::iterator iter = dependency_names.begin();
436 feature->IsAvailableToContext(extension, context, url); 438 iter != dependency_names.end(); ++iter) {
437 if (!availability.is_available()) 439 Feature* feature = GetFeatureDependency(*iter);
438 return availability; 440 CHECK(feature) << *iter;
439 441
440 for (std::set<std::string>::iterator iter = feature->dependencies().begin(); 442 Feature::Availability availability =
441 iter != feature->dependencies().end(); ++iter) { 443 feature->IsAvailableToContext(extension, context, url);
442 Feature::Availability dependency_availability = 444 if (!availability.is_available())
443 IsAvailable(*iter, extension, context, url); 445 return availability;
444 if (!dependency_availability.is_available())
445 return dependency_availability;
446 } 446 }
447 447
448 return Feature::CreateAvailability(Feature::IS_AVAILABLE, ""); 448 return Feature::CreateAvailability(Feature::IS_AVAILABLE, "");
449 } 449 }
450 450
451 bool ExtensionAPI::IsPrivileged(const std::string& full_name) { 451 bool ExtensionAPI::IsPrivileged(const std::string& full_name) {
452 std::string child_name; 452 std::string child_name;
453 std::string api_name = GetAPINameFromFullName(full_name, &child_name); 453 std::string api_name = GetAPINameFromFullName(full_name, &child_name);
454 Feature* feature = GetFeatureDependency(full_name);
455 454
456 // First try to use the feature system. 455 // First try to use the feature system.
456 Feature* feature(GetFeature(full_name));
457 if (feature) { 457 if (feature) {
458 // An API is 'privileged' if it can only be run in a blessed context. 458 // An API is 'privileged' if it or any of its dependencies can only be run
459 return feature->GetContexts()->size() == 459 // in a blessed context.
460 feature->GetContexts()->count(Feature::BLESSED_EXTENSION_CONTEXT); 460 std::set<std::string> resolved_dependencies;
461 resolved_dependencies.insert(full_name);
462 ResolveDependencies(&resolved_dependencies);
463 for (std::set<std::string>::iterator iter = resolved_dependencies.begin();
464 iter != resolved_dependencies.end(); ++iter) {
465 Feature* dependency = GetFeatureDependency(*iter);
466 for (std::set<Feature::Context>::iterator context =
467 dependency->GetContexts()->begin();
468 context != dependency->GetContexts()->end(); ++context) {
469 if (*context != Feature::BLESSED_EXTENSION_CONTEXT)
470 return false;
471 }
472 }
473 return true;
461 } 474 }
462 475
463 // Get the schema now to populate |completely_unprivileged_apis_|.
464 const DictionaryValue* schema = GetSchema(api_name);
465 // If this API hasn't been converted yet, fall back to the old system. 476 // If this API hasn't been converted yet, fall back to the old system.
466 if (completely_unprivileged_apis_.count(api_name)) 477 if (completely_unprivileged_apis_.count(api_name))
467 return false; 478 return false;
468 479
480 const DictionaryValue* schema = GetSchema(api_name);
469 if (partially_unprivileged_apis_.count(api_name)) 481 if (partially_unprivileged_apis_.count(api_name))
470 return IsChildNamePrivileged(schema, child_name); 482 return IsChildNamePrivileged(schema, child_name);
471 483
472 return true; 484 return true;
473 } 485 }
474 486
475 bool ExtensionAPI::IsChildNamePrivileged(const DictionaryValue* name_space_node, 487 bool ExtensionAPI::IsChildNamePrivileged(const DictionaryValue* name_space_node,
476 const std::string& child_name) { 488 const std::string& child_name) {
477 bool unprivileged = false; 489 bool unprivileged = false;
478 const DictionaryValue* child = GetSchemaChild(name_space_node, child_name); 490 const DictionaryValue* child = GetSchemaChild(name_space_node, child_name);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
530 542
531 return true; 543 return true;
532 } 544 }
533 545
534 } // namespace 546 } // namespace
535 547
536 bool ExtensionAPI::IsNonFeatureAPIAvailable(const std::string& name, 548 bool ExtensionAPI::IsNonFeatureAPIAvailable(const std::string& name,
537 Feature::Context context, 549 Feature::Context context,
538 const Extension* extension, 550 const Extension* extension,
539 const GURL& url) { 551 const GURL& url) {
540 // Make sure schema is loaded.
541 GetSchema(name);
542 switch (context) { 552 switch (context) {
543 case Feature::UNSPECIFIED_CONTEXT: 553 case Feature::UNSPECIFIED_CONTEXT:
544 break; 554 break;
545 555
546 case Feature::BLESSED_EXTENSION_CONTEXT: 556 case Feature::BLESSED_EXTENSION_CONTEXT:
547 if (extension) { 557 if (extension) {
548 // Availability is determined by the permissions of the extension. 558 // Availability is determined by the permissions of the extension.
549 if (!IsAPIAllowed(name, extension)) 559 if (!IsAPIAllowed(name, extension))
550 return false; 560 return false;
551 if (!IsFeatureAllowedForExtension(name, *extension)) 561 if (!IsFeatureAllowedForExtension(name, *extension))
(...skipping 28 matching lines...) Expand all
580 std::set<std::string> result; 590 std::set<std::string> result;
581 for (SchemaMap::iterator i = schemas_.begin(); i != schemas_.end(); ++i) 591 for (SchemaMap::iterator i = schemas_.begin(); i != schemas_.end(); ++i)
582 result.insert(i->first); 592 result.insert(i->first);
583 for (UnloadedSchemaMap::iterator i = unloaded_schemas_.begin(); 593 for (UnloadedSchemaMap::iterator i = unloaded_schemas_.begin();
584 i != unloaded_schemas_.end(); ++i) { 594 i != unloaded_schemas_.end(); ++i) {
585 result.insert(i->first); 595 result.insert(i->first);
586 } 596 }
587 return result; 597 return result;
588 } 598 }
589 599
600 Feature* ExtensionAPI::GetFeature(const std::string& full_name) {
601 // Ensure it's loaded.
602 GetSchema(full_name);
603
604 std::string child_name;
605 std::string api_namespace = GetAPINameFromFullName(full_name, &child_name);
606
607 APIFeatureMap::iterator feature_map = features_.find(api_namespace);
608 if (feature_map == features_.end())
609 return NULL;
610
611 Feature* result = NULL;
612 FeatureMap::iterator child_feature = feature_map->second->find(child_name);
613 if (child_feature != feature_map->second->end()) {
614 result = child_feature->second.get();
615 } else {
616 FeatureMap::iterator parent_feature = feature_map->second->find("");
617 CHECK(parent_feature != feature_map->second->end());
618 result = parent_feature->second.get();
619 }
620
621 if (result->GetContexts()->empty()) {
622 LOG(ERROR) << "API feature '" << full_name
623 << "' must specify at least one context.";
624 return NULL;
625 }
626
627 return result;
628 }
629
590 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { 630 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) {
591 std::string feature_type; 631 std::string feature_type;
592 std::string feature_name; 632 std::string feature_name;
593 SplitDependencyName(full_name, &feature_type, &feature_name); 633 SplitDependencyName(full_name, &feature_type, &feature_name);
594 634
595 FeatureProviderMap::iterator provider = 635 FeatureProviderMap::iterator provider =
596 dependency_providers_.find(feature_type); 636 dependency_providers_.find(feature_type);
597 if (provider == dependency_providers_.end()) 637 CHECK(provider != dependency_providers_.end()) << full_name;
598 return NULL;
599 638
600 Feature* feature = provider->second->GetFeature(feature_name); 639 Feature* feature = provider->second->GetFeature(feature_name);
601 // Try getting the feature for the parent API, if this was a child. 640 CHECK(feature) << full_name;
602 if (!feature) { 641
603 std::string child_name;
604 feature = provider->second->GetFeature(
605 GetAPINameFromFullName(feature_name, &child_name));
606 }
607 return feature; 642 return feature;
608 } 643 }
609 644
610 std::string ExtensionAPI::GetAPINameFromFullName(const std::string& full_name, 645 std::string ExtensionAPI::GetAPINameFromFullName(const std::string& full_name,
611 std::string* child_name) { 646 std::string* child_name) {
612 std::string api_name_candidate = full_name; 647 std::string api_name_candidate = full_name;
613 while (true) { 648 while (true) {
614 if (features_.find(api_name_candidate) != features_.end() || 649 if (features_.find(api_name_candidate) != features_.end() ||
615 schemas_.find(api_name_candidate) != schemas_.end() || 650 schemas_.find(api_name_candidate) != schemas_.end() ||
616 unloaded_schemas_.find(api_name_candidate) != unloaded_schemas_.end()) { 651 unloaded_schemas_.find(api_name_candidate) != unloaded_schemas_.end()) {
(...skipping 19 matching lines...) Expand all
636 *child_name = ""; 671 *child_name = "";
637 return ""; 672 return "";
638 } 673 }
639 674
640 bool ExtensionAPI::IsAPIAllowed(const std::string& name, 675 bool ExtensionAPI::IsAPIAllowed(const std::string& name,
641 const Extension* extension) { 676 const Extension* extension) {
642 return extension->required_permission_set()->HasAnyAccessToAPI(name) || 677 return extension->required_permission_set()->HasAnyAccessToAPI(name) ||
643 extension->optional_permission_set()->HasAnyAccessToAPI(name); 678 extension->optional_permission_set()->HasAnyAccessToAPI(name);
644 } 679 }
645 680
681 void ExtensionAPI::ResolveDependencies(std::set<std::string>* out) {
682 std::set<std::string> missing_dependencies;
683 for (std::set<std::string>::iterator i = out->begin(); i != out->end(); ++i)
684 GetMissingDependencies(*i, *out, &missing_dependencies);
685
686 while (missing_dependencies.size()) {
687 std::string next = *missing_dependencies.begin();
688 missing_dependencies.erase(next);
689 out->insert(next);
690 GetMissingDependencies(next, *out, &missing_dependencies);
691 }
692 }
693
694 void ExtensionAPI::GetMissingDependencies(
695 const std::string& api_name,
696 const std::set<std::string>& excluding,
697 std::set<std::string>* out) {
698 std::string feature_type;
699 std::string feature_name;
700 SplitDependencyName(api_name, &feature_type, &feature_name);
701
702 // Only API features can have dependencies for now.
703 if (feature_type != "api")
704 return;
705
706 const DictionaryValue* schema = GetSchema(feature_name);
707 CHECK(schema) << "Schema for " << feature_name << " not found";
708
709 const ListValue* dependencies = NULL;
710 if (!schema->GetList("dependencies", &dependencies))
711 return;
712
713 for (size_t i = 0; i < dependencies->GetSize(); ++i) {
714 std::string dependency_name;
715 if (dependencies->GetString(i, &dependency_name) &&
716 !excluding.count(dependency_name)) {
717 out->insert(dependency_name);
718 }
719 }
720 }
721
646 bool ExtensionAPI::IsPrivilegedAPI(const std::string& name) { 722 bool ExtensionAPI::IsPrivilegedAPI(const std::string& name) {
647 return completely_unprivileged_apis_.count(name) || 723 return completely_unprivileged_apis_.count(name) ||
648 partially_unprivileged_apis_.count(name); 724 partially_unprivileged_apis_.count(name);
649 } 725 }
650 726
651 } // namespace extensions 727 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698