Index: chrome/common/extensions/api/extension_api.cc |
diff --git a/chrome/common/extensions/api/extension_api.cc b/chrome/common/extensions/api/extension_api.cc |
index 0b94a3c25da0f11b669b8934d6c543ee244a2409..cbf9b1765c8c83be4bba62f15843077599afde49 100644 |
--- a/chrome/common/extensions/api/extension_api.cc |
+++ b/chrome/common/extensions/api/extension_api.cc |
@@ -16,6 +16,7 @@ |
#include "base/string_split.h" |
#include "base/string_util.h" |
#include "base/values.h" |
+#include "chrome/common/extensions/api/extension_api_feature.h" |
#include "chrome/common/extensions/api/generated_schemas.h" |
#include "chrome/common/extensions/extension.h" |
#include "chrome/common/extensions/extension_permission_set.h" |
@@ -195,40 +196,17 @@ void ExtensionAPI::LoadSchema(const base::StringPiece& schema) { |
if (!uses_feature_system) |
continue; |
- Feature* feature = new Feature(); |
+ ExtensionAPIFeature* feature = new ExtensionAPIFeature(); |
feature->set_name(schema_namespace); |
feature->Parse(schema); |
- FeatureMap* schema_features = new FeatureMap(); |
+ CHECK(!feature->contexts()->empty()) |
+ << "API feature '" << schema_namespace << "' includes no " |
+ << "contexts and will never be available."; |
+ |
CHECK(features_.insert( |
std::make_pair(schema_namespace, |
- make_linked_ptr(schema_features))).second); |
- CHECK(schema_features->insert( |
- std::make_pair("", make_linked_ptr(feature))).second); |
- |
- for (size_t i = 0; i < arraysize(kChildKinds); ++i) { |
- ListValue* child_list = NULL; |
- schema->GetList(kChildKinds[i], &child_list); |
- if (!child_list) |
- continue; |
- |
- for (size_t j = 0; j < child_list->GetSize(); ++j) { |
- DictionaryValue* child = NULL; |
- CHECK(child_list->GetDictionary(j, &child)); |
- |
- scoped_ptr<Feature> child_feature(new Feature(*feature)); |
- child_feature->Parse(child); |
- if (child_feature->Equals(*feature)) |
- continue; // no need to store no-op features |
- |
- std::string child_name; |
- CHECK(child->GetString("name", &child_name)); |
- child_feature->set_name(schema_namespace + "." + child_name); |
- CHECK(schema_features->insert( |
- std::make_pair(child_name, |
- make_linked_ptr(child_feature.release()))).second); |
- } |
- } |
+ make_linked_ptr(feature))).second); |
} |
} |
@@ -402,7 +380,7 @@ bool ExtensionAPI::IsAvailable(const std::string& full_name, |
for (std::set<std::string>::iterator iter = dependency_names.begin(); |
iter != dependency_names.end(); ++iter) { |
- Feature* feature = GetFeatureDependency(full_name); |
+ Feature* feature = GetFeatureDependency(*iter); |
CHECK(feature) << *iter; |
Feature::Availability availability = |
@@ -419,7 +397,7 @@ bool ExtensionAPI::IsPrivileged(const std::string& full_name) { |
std::string api_name = GetAPINameFromFullName(full_name, &child_name); |
// First try to use the feature system. |
- Feature* feature(GetFeature(full_name)); |
+ Feature* feature = GetFeature(full_name); |
if (feature) { |
// An API is 'privileged' if it or any of its dependencies can only be run |
// in a blessed context. |
@@ -429,14 +407,14 @@ bool ExtensionAPI::IsPrivileged(const std::string& full_name) { |
for (std::set<std::string>::iterator iter = resolved_dependencies.begin(); |
iter != resolved_dependencies.end(); ++iter) { |
Feature* dependency = GetFeatureDependency(*iter); |
- for (std::set<Feature::Context>::iterator context = |
- dependency->contexts()->begin(); |
- context != dependency->contexts()->end(); ++context) { |
- if (*context != Feature::BLESSED_EXTENSION_CONTEXT) |
- return false; |
+ if (dependency->contexts()->size() == 1u) { |
+ Feature::Context context = |
+ *(dependency->contexts()->begin()); |
+ if (context == Feature::BLESSED_EXTENSION_CONTEXT) |
+ return true; |
} |
} |
- return true; |
+ return false; |
} |
// If this API hasn't been converted yet, fall back to the old system. |
@@ -500,8 +478,8 @@ scoped_ptr<std::set<std::string> > ExtensionAPI::GetAPIsForContext( |
// First handle all the APIs that have been converted to the feature system. |
if (extension) { |
- for (APIFeatureMap::iterator iter = features_.begin(); |
- iter != features_.end(); ++iter) { |
+ for (FeatureMap::iterator iter = features_.begin(); iter != features_.end(); |
+ ++iter) { |
if (IsAvailable(iter->first, extension, context)) |
temp_result.insert(iter->first); |
} |
@@ -561,27 +539,19 @@ Feature* ExtensionAPI::GetFeature(const std::string& full_name) { |
std::string child_name; |
std::string api_namespace = GetAPINameFromFullName(full_name, &child_name); |
- APIFeatureMap::iterator feature_map = features_.find(api_namespace); |
- if (feature_map == features_.end()) |
+ FeatureMap::iterator parent = features_.find(api_namespace); |
+ if (parent == features_.end()) |
return NULL; |
- Feature* result = NULL; |
- FeatureMap::iterator child_feature = feature_map->second->find(child_name); |
- if (child_feature != feature_map->second->end()) { |
- result = child_feature->second.get(); |
+ Feature* child = parent->second->GetChild(child_name); |
+ if (child) { |
+ return child; |
} else { |
- FeatureMap::iterator parent_feature = feature_map->second->find(""); |
- CHECK(parent_feature != feature_map->second->end()); |
- result = parent_feature->second.get(); |
+ // TODO(aa): This is lame. We should generate a feature with the correct |
+ // name on the fly. In order to do that, change the return type of this |
+ // method to linked_ptr. |
+ return parent->second.get(); |
} |
- |
- if (result->contexts()->empty()) { |
- LOG(ERROR) << "API feature '" << full_name |
- << "' must specify at least one context."; |
- return NULL; |
- } |
- |
- return result; |
} |
Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { |
@@ -633,10 +603,8 @@ void ExtensionAPI::GetAllowedAPIs( |
const Extension* extension, std::set<std::string>* out) { |
for (SchemaMap::const_iterator i = schemas_.begin(); i != schemas_.end(); |
++i) { |
- if (features_.find(i->first) != features_.end()) { |
- // This API is controlled by the feature system. Nothing to do here. |
+ if (IsControlledByFeatureSystem(i->first)) |
continue; |
- } |
if (extension->required_permission_set()->HasAnyAccessToAPI(i->first) || |
extension->optional_permission_set()->HasAnyAccessToAPI(i->first)) { |
@@ -670,6 +638,19 @@ void ExtensionAPI::GetMissingDependencies( |
if (feature_type != "api") |
return; |
+ // If this API is controlled by the feature system, use it to get dependencies |
+ // to avoid loading the schema. |
+ ExtensionAPIFeature* feature = |
+ static_cast<ExtensionAPIFeature*>(GetFeature(api_name)); |
+ if (feature) { |
+ for (std::set<std::string>::iterator it = feature->dependencies()->begin(); |
+ it != feature->dependencies()->end(); ++it) { |
+ out->insert(*it); |
+ } |
+ return; |
+ } |
+ |
+ // Otherwise, fall back to the old system. |
const DictionaryValue* schema = GetSchema(feature_name); |
CHECK(schema) << "Schema for " << feature_name << " not found"; |
@@ -690,6 +671,9 @@ void ExtensionAPI::RemovePrivilegedAPIs(std::set<std::string>* apis) { |
std::set<std::string> privileged_apis; |
for (std::set<std::string>::iterator i = apis->begin(); i != apis->end(); |
++i) { |
+ if (IsControlledByFeatureSystem(*i)) |
+ continue; |
+ |
if (!completely_unprivileged_apis_.count(*i) && |
!partially_unprivileged_apis_.count(*i)) { |
privileged_apis.insert(*i); |
@@ -705,10 +689,8 @@ void ExtensionAPI::GetAPIsMatchingURL(const GURL& url, |
std::set<std::string>* out) { |
for (std::map<std::string, URLPatternSet>::const_iterator i = |
url_matching_apis_.begin(); i != url_matching_apis_.end(); ++i) { |
- if (features_.find(i->first) != features_.end()) { |
- // This API is controlled by the feature system. Nothing to do. |
+ if (IsControlledByFeatureSystem(i->first)) |
continue; |
- } |
if (i->second.MatchesURL(url)) |
out->insert(i->first); |
@@ -721,4 +703,9 @@ void ExtensionAPI::LoadAllSchemas() { |
} |
} |
+bool ExtensionAPI::IsControlledByFeatureSystem( |
+ const std::string& api_name) const { |
+ return features_.find(api_name) != features_.end(); |
+} |
+ |
} // namespace extensions |