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

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

Issue 10025007: Convert tabs, windows, and extension APIs to feature system. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: blah Created 8 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
11 #include "base/json/json_reader.h" 11 #include "base/json/json_reader.h"
12 #include "base/json/json_writer.h" 12 #include "base/json/json_writer.h"
13 #include "base/lazy_instance.h" 13 #include "base/lazy_instance.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/string_number_conversions.h" 15 #include "base/string_number_conversions.h"
16 #include "base/string_split.h" 16 #include "base/string_split.h"
17 #include "base/string_util.h" 17 #include "base/string_util.h"
18 #include "base/values.h" 18 #include "base/values.h"
19 #include "chrome/common/extensions/api/extension_api_feature.h"
19 #include "chrome/common/extensions/api/generated_schemas.h" 20 #include "chrome/common/extensions/api/generated_schemas.h"
20 #include "chrome/common/extensions/extension.h" 21 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/extensions/extension_permission_set.h" 22 #include "chrome/common/extensions/extension_permission_set.h"
22 #include "chrome/common/extensions/simple_feature_provider.h" 23 #include "chrome/common/extensions/simple_feature_provider.h"
23 #include "googleurl/src/gurl.h" 24 #include "googleurl/src/gurl.h"
24 #include "grit/common_resources.h" 25 #include "grit/common_resources.h"
25 #include "ui/base/resource/resource_bundle.h" 26 #include "ui/base/resource/resource_bundle.h"
26 27
27 using base::DictionaryValue; 28 using base::DictionaryValue;
28 using base::ListValue; 29 using base::ListValue;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 } 189 }
189 190
190 // Populate feature maps. 191 // Populate feature maps.
191 // TODO(aa): Consider not storing features that can never run on the current 192 // TODO(aa): Consider not storing features that can never run on the current
192 // machine (e.g., because of platform restrictions). 193 // machine (e.g., because of platform restrictions).
193 bool uses_feature_system = false; 194 bool uses_feature_system = false;
194 schema->GetBoolean("uses_feature_system", &uses_feature_system); 195 schema->GetBoolean("uses_feature_system", &uses_feature_system);
195 if (!uses_feature_system) 196 if (!uses_feature_system)
196 continue; 197 continue;
197 198
198 Feature* feature = new Feature(); 199 ExtensionAPIFeature* feature = new ExtensionAPIFeature();
199 feature->set_name(schema_namespace); 200 feature->set_name(schema_namespace);
200 feature->Parse(schema); 201 feature->Parse(schema);
201 202
202 FeatureMap* schema_features = new FeatureMap(); 203 CHECK(!feature->contexts()->empty())
204 << "API feature '" << schema_namespace << "' includes no "
205 << "contexts and will never be available.";
206
203 CHECK(features_.insert( 207 CHECK(features_.insert(
204 std::make_pair(schema_namespace, 208 std::make_pair(schema_namespace,
205 make_linked_ptr(schema_features))).second); 209 make_linked_ptr(feature))).second);
206 CHECK(schema_features->insert(
207 std::make_pair("", make_linked_ptr(feature))).second);
208
209 for (size_t i = 0; i < arraysize(kChildKinds); ++i) {
210 ListValue* child_list = NULL;
211 schema->GetList(kChildKinds[i], &child_list);
212 if (!child_list)
213 continue;
214
215 for (size_t j = 0; j < child_list->GetSize(); ++j) {
216 DictionaryValue* child = NULL;
217 CHECK(child_list->GetDictionary(j, &child));
218
219 scoped_ptr<Feature> child_feature(new Feature(*feature));
220 child_feature->Parse(child);
221 if (child_feature->Equals(*feature))
222 continue; // no need to store no-op features
223
224 std::string child_name;
225 CHECK(child->GetString("name", &child_name));
226 child_feature->set_name(schema_namespace + "." + child_name);
227 CHECK(schema_features->insert(
228 std::make_pair(child_name,
229 make_linked_ptr(child_feature.release()))).second);
230 }
231 }
232 } 210 }
233 } 211 }
234 212
235 ExtensionAPI::ExtensionAPI() { 213 ExtensionAPI::ExtensionAPI() {
236 RegisterDependencyProvider("api", this); 214 RegisterDependencyProvider("api", this);
237 215
238 // TODO(aa): Can remove this when all JSON files are converted. 216 // TODO(aa): Can remove this when all JSON files are converted.
239 RegisterDependencyProvider("", this); 217 RegisterDependencyProvider("", this);
240 } 218 }
241 219
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 373
396 bool ExtensionAPI::IsAvailable(const std::string& full_name, 374 bool ExtensionAPI::IsAvailable(const std::string& full_name,
397 const Extension* extension, 375 const Extension* extension,
398 Feature::Context context) { 376 Feature::Context context) {
399 std::set<std::string> dependency_names; 377 std::set<std::string> dependency_names;
400 dependency_names.insert(full_name); 378 dependency_names.insert(full_name);
401 ResolveDependencies(&dependency_names); 379 ResolveDependencies(&dependency_names);
402 380
403 for (std::set<std::string>::iterator iter = dependency_names.begin(); 381 for (std::set<std::string>::iterator iter = dependency_names.begin();
404 iter != dependency_names.end(); ++iter) { 382 iter != dependency_names.end(); ++iter) {
405 Feature* feature = GetFeatureDependency(full_name); 383 Feature* feature = GetFeatureDependency(*iter);
406 CHECK(feature) << *iter; 384 CHECK(feature) << *iter;
407 385
408 Feature::Availability availability = 386 Feature::Availability availability =
409 feature->IsAvailableToContext(extension, context); 387 feature->IsAvailableToContext(extension, context);
410 if (availability != Feature::IS_AVAILABLE) 388 if (availability != Feature::IS_AVAILABLE)
411 return false; 389 return false;
412 } 390 }
413 391
414 return true; 392 return true;
415 } 393 }
416 394
417 bool ExtensionAPI::IsPrivileged(const std::string& full_name) { 395 bool ExtensionAPI::IsPrivileged(const std::string& full_name) {
418 std::string child_name; 396 std::string child_name;
419 std::string api_name = GetAPINameFromFullName(full_name, &child_name); 397 std::string api_name = GetAPINameFromFullName(full_name, &child_name);
420 398
421 // First try to use the feature system. 399 // First try to use the feature system.
422 Feature* feature(GetFeature(full_name)); 400 Feature* feature = GetFeature(full_name);
423 if (feature) { 401 if (feature) {
424 // An API is 'privileged' if it or any of its dependencies can only be run 402 // An API is 'privileged' if it or any of its dependencies can only be run
425 // in a blessed context. 403 // in a blessed context.
426 std::set<std::string> resolved_dependencies; 404 std::set<std::string> resolved_dependencies;
427 resolved_dependencies.insert(full_name); 405 resolved_dependencies.insert(full_name);
428 ResolveDependencies(&resolved_dependencies); 406 ResolveDependencies(&resolved_dependencies);
429 for (std::set<std::string>::iterator iter = resolved_dependencies.begin(); 407 for (std::set<std::string>::iterator iter = resolved_dependencies.begin();
430 iter != resolved_dependencies.end(); ++iter) { 408 iter != resolved_dependencies.end(); ++iter) {
431 Feature* dependency = GetFeatureDependency(*iter); 409 Feature* dependency = GetFeatureDependency(*iter);
432 for (std::set<Feature::Context>::iterator context = 410 if (dependency->contexts()->size() == 1u) {
433 dependency->contexts()->begin(); 411 Feature::Context context =
434 context != dependency->contexts()->end(); ++context) { 412 *(dependency->contexts()->begin());
435 if (*context != Feature::BLESSED_EXTENSION_CONTEXT) 413 if (context == Feature::BLESSED_EXTENSION_CONTEXT)
436 return false; 414 return true;
437 } 415 }
438 } 416 }
439 return true; 417 return false;
440 } 418 }
441 419
442 // If this API hasn't been converted yet, fall back to the old system. 420 // If this API hasn't been converted yet, fall back to the old system.
443 if (completely_unprivileged_apis_.count(api_name)) 421 if (completely_unprivileged_apis_.count(api_name))
444 return false; 422 return false;
445 423
446 const DictionaryValue* schema = GetSchema(api_name); 424 const DictionaryValue* schema = GetSchema(api_name);
447 if (partially_unprivileged_apis_.count(api_name)) 425 if (partially_unprivileged_apis_.count(api_name))
448 return IsChildNamePrivileged(schema, child_name); 426 return IsChildNamePrivileged(schema, child_name);
449 427
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 // about every API -- and the metadata is stored in the schemas themselves. 471 // about every API -- and the metadata is stored in the schemas themselves.
494 // This is a shame. 472 // This is a shame.
495 // TODO(aa/kalman): store metadata in a separate file and don't load all 473 // TODO(aa/kalman): store metadata in a separate file and don't load all
496 // schemas. 474 // schemas.
497 LoadAllSchemas(); 475 LoadAllSchemas();
498 476
499 std::set<std::string> temp_result; 477 std::set<std::string> temp_result;
500 478
501 // First handle all the APIs that have been converted to the feature system. 479 // First handle all the APIs that have been converted to the feature system.
502 if (extension) { 480 if (extension) {
503 for (APIFeatureMap::iterator iter = features_.begin(); 481 for (FeatureMap::iterator iter = features_.begin(); iter != features_.end();
504 iter != features_.end(); ++iter) { 482 ++iter) {
505 if (IsAvailable(iter->first, extension, context)) 483 if (IsAvailable(iter->first, extension, context))
506 temp_result.insert(iter->first); 484 temp_result.insert(iter->first);
507 } 485 }
508 } 486 }
509 487
510 // Second, fall back to the old way. 488 // Second, fall back to the old way.
511 // TODO(aa): Remove this when all APIs have been converted. 489 // TODO(aa): Remove this when all APIs have been converted.
512 switch (context) { 490 switch (context) {
513 case Feature::UNSPECIFIED_CONTEXT: 491 case Feature::UNSPECIFIED_CONTEXT:
514 break; 492 break;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 return result.Pass(); 532 return result.Pass();
555 } 533 }
556 534
557 Feature* ExtensionAPI::GetFeature(const std::string& full_name) { 535 Feature* ExtensionAPI::GetFeature(const std::string& full_name) {
558 // Ensure it's loaded. 536 // Ensure it's loaded.
559 GetSchema(full_name); 537 GetSchema(full_name);
560 538
561 std::string child_name; 539 std::string child_name;
562 std::string api_namespace = GetAPINameFromFullName(full_name, &child_name); 540 std::string api_namespace = GetAPINameFromFullName(full_name, &child_name);
563 541
564 APIFeatureMap::iterator feature_map = features_.find(api_namespace); 542 FeatureMap::iterator parent = features_.find(api_namespace);
565 if (feature_map == features_.end()) 543 if (parent == features_.end())
566 return NULL; 544 return NULL;
567 545
568 Feature* result = NULL; 546 Feature* child = parent->second->GetChild(child_name);
569 FeatureMap::iterator child_feature = feature_map->second->find(child_name); 547 if (child) {
570 if (child_feature != feature_map->second->end()) { 548 return child;
571 result = child_feature->second.get();
572 } else { 549 } else {
573 FeatureMap::iterator parent_feature = feature_map->second->find(""); 550 // TODO(aa): This is lame. We should generate a feature with the correct
574 CHECK(parent_feature != feature_map->second->end()); 551 // name on the fly. In order to do that, change the return type of this
575 result = parent_feature->second.get(); 552 // method to linked_ptr.
553 return parent->second.get();
576 } 554 }
577
578 if (result->contexts()->empty()) {
579 LOG(ERROR) << "API feature '" << full_name
580 << "' must specify at least one context.";
581 return NULL;
582 }
583
584 return result;
585 } 555 }
586 556
587 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { 557 Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) {
588 std::string feature_type; 558 std::string feature_type;
589 std::string feature_name; 559 std::string feature_name;
590 SplitDependencyName(full_name, &feature_type, &feature_name); 560 SplitDependencyName(full_name, &feature_type, &feature_name);
591 561
592 FeatureProviderMap::iterator provider = 562 FeatureProviderMap::iterator provider =
593 dependency_providers_.find(feature_type); 563 dependency_providers_.find(feature_type);
594 CHECK(provider != dependency_providers_.end()) << full_name; 564 CHECK(provider != dependency_providers_.end()) << full_name;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 } 596 }
627 597
628 *child_name = ""; 598 *child_name = "";
629 return ""; 599 return "";
630 } 600 }
631 601
632 void ExtensionAPI::GetAllowedAPIs( 602 void ExtensionAPI::GetAllowedAPIs(
633 const Extension* extension, std::set<std::string>* out) { 603 const Extension* extension, std::set<std::string>* out) {
634 for (SchemaMap::const_iterator i = schemas_.begin(); i != schemas_.end(); 604 for (SchemaMap::const_iterator i = schemas_.begin(); i != schemas_.end();
635 ++i) { 605 ++i) {
636 if (features_.find(i->first) != features_.end()) { 606 if (IsControlledByFeatureSystem(i->first))
637 // This API is controlled by the feature system. Nothing to do here.
638 continue; 607 continue;
639 }
640 608
641 if (extension->required_permission_set()->HasAnyAccessToAPI(i->first) || 609 if (extension->required_permission_set()->HasAnyAccessToAPI(i->first) ||
642 extension->optional_permission_set()->HasAnyAccessToAPI(i->first)) { 610 extension->optional_permission_set()->HasAnyAccessToAPI(i->first)) {
643 out->insert(i->first); 611 out->insert(i->first);
644 } 612 }
645 } 613 }
646 } 614 }
647 615
648 void ExtensionAPI::ResolveDependencies(std::set<std::string>* out) { 616 void ExtensionAPI::ResolveDependencies(std::set<std::string>* out) {
649 std::set<std::string> missing_dependencies; 617 std::set<std::string> missing_dependencies;
(...skipping 13 matching lines...) Expand all
663 const std::set<std::string>& excluding, 631 const std::set<std::string>& excluding,
664 std::set<std::string>* out) { 632 std::set<std::string>* out) {
665 std::string feature_type; 633 std::string feature_type;
666 std::string feature_name; 634 std::string feature_name;
667 SplitDependencyName(api_name, &feature_type, &feature_name); 635 SplitDependencyName(api_name, &feature_type, &feature_name);
668 636
669 // Only API features can have dependencies for now. 637 // Only API features can have dependencies for now.
670 if (feature_type != "api") 638 if (feature_type != "api")
671 return; 639 return;
672 640
641 // If this API is controlled by the feature system, use it to get dependencies
642 // to avoid loading the schema.
643 ExtensionAPIFeature* feature =
644 static_cast<ExtensionAPIFeature*>(GetFeature(api_name));
645 if (feature) {
646 for (std::set<std::string>::iterator it = feature->dependencies()->begin();
647 it != feature->dependencies()->end(); ++it) {
648 out->insert(*it);
649 }
650 return;
651 }
652
653 // Otherwise, fall back to the old system.
673 const DictionaryValue* schema = GetSchema(feature_name); 654 const DictionaryValue* schema = GetSchema(feature_name);
674 CHECK(schema) << "Schema for " << feature_name << " not found"; 655 CHECK(schema) << "Schema for " << feature_name << " not found";
675 656
676 ListValue* dependencies = NULL; 657 ListValue* dependencies = NULL;
677 if (!schema->GetList("dependencies", &dependencies)) 658 if (!schema->GetList("dependencies", &dependencies))
678 return; 659 return;
679 660
680 for (size_t i = 0; i < dependencies->GetSize(); ++i) { 661 for (size_t i = 0; i < dependencies->GetSize(); ++i) {
681 std::string dependency_name; 662 std::string dependency_name;
682 if (dependencies->GetString(i, &dependency_name) && 663 if (dependencies->GetString(i, &dependency_name) &&
683 !excluding.count(dependency_name)) { 664 !excluding.count(dependency_name)) {
684 out->insert(dependency_name); 665 out->insert(dependency_name);
685 } 666 }
686 } 667 }
687 } 668 }
688 669
689 void ExtensionAPI::RemovePrivilegedAPIs(std::set<std::string>* apis) { 670 void ExtensionAPI::RemovePrivilegedAPIs(std::set<std::string>* apis) {
690 std::set<std::string> privileged_apis; 671 std::set<std::string> privileged_apis;
691 for (std::set<std::string>::iterator i = apis->begin(); i != apis->end(); 672 for (std::set<std::string>::iterator i = apis->begin(); i != apis->end();
692 ++i) { 673 ++i) {
674 if (IsControlledByFeatureSystem(*i))
675 continue;
676
693 if (!completely_unprivileged_apis_.count(*i) && 677 if (!completely_unprivileged_apis_.count(*i) &&
694 !partially_unprivileged_apis_.count(*i)) { 678 !partially_unprivileged_apis_.count(*i)) {
695 privileged_apis.insert(*i); 679 privileged_apis.insert(*i);
696 } 680 }
697 } 681 }
698 for (std::set<std::string>::iterator i = privileged_apis.begin(); 682 for (std::set<std::string>::iterator i = privileged_apis.begin();
699 i != privileged_apis.end(); ++i) { 683 i != privileged_apis.end(); ++i) {
700 apis->erase(*i); 684 apis->erase(*i);
701 } 685 }
702 } 686 }
703 687
704 void ExtensionAPI::GetAPIsMatchingURL(const GURL& url, 688 void ExtensionAPI::GetAPIsMatchingURL(const GURL& url,
705 std::set<std::string>* out) { 689 std::set<std::string>* out) {
706 for (std::map<std::string, URLPatternSet>::const_iterator i = 690 for (std::map<std::string, URLPatternSet>::const_iterator i =
707 url_matching_apis_.begin(); i != url_matching_apis_.end(); ++i) { 691 url_matching_apis_.begin(); i != url_matching_apis_.end(); ++i) {
708 if (features_.find(i->first) != features_.end()) { 692 if (IsControlledByFeatureSystem(i->first))
709 // This API is controlled by the feature system. Nothing to do.
710 continue; 693 continue;
711 }
712 694
713 if (i->second.MatchesURL(url)) 695 if (i->second.MatchesURL(url))
714 out->insert(i->first); 696 out->insert(i->first);
715 } 697 }
716 } 698 }
717 699
718 void ExtensionAPI::LoadAllSchemas() { 700 void ExtensionAPI::LoadAllSchemas() {
719 while (unloaded_schemas_.size()) { 701 while (unloaded_schemas_.size()) {
720 LoadSchema(unloaded_schemas_.begin()->second); 702 LoadSchema(unloaded_schemas_.begin()->second);
721 } 703 }
722 } 704 }
723 705
706 bool ExtensionAPI::IsControlledByFeatureSystem(
707 const std::string& api_name) const {
708 return features_.find(api_name) != features_.end();
709 }
710
724 } // namespace extensions 711 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/common/extensions/api/extension_api.h ('k') | chrome/common/extensions/api/extension_api_feature.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698