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

Unified 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, 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 side-by-side diff with in-line comments
Download patch
Index: trunk/src/chrome/common/extensions/api/extension_api.cc
===================================================================
--- trunk/src/chrome/common/extensions/api/extension_api.cc (revision 190861)
+++ trunk/src/chrome/common/extensions/api/extension_api.cc (working copy)
@@ -234,6 +234,11 @@
*feature_name = full_name.substr(colon_index + 1);
}
+bool ExtensionAPI::UsesFeatureSystem(const std::string& full_name) {
+ std::string api_name = GetAPINameFromFullName(full_name, NULL);
+ return features_.find(api_name) != features_.end();
+}
+
void ExtensionAPI::LoadSchema(const std::string& name,
const base::StringPiece& schema) {
scoped_ptr<ListValue> schema_list(LoadSchemaList(name, schema));
@@ -327,6 +332,10 @@
}
ExtensionAPI::ExtensionAPI() {
+ RegisterDependencyProvider("api", this);
+
+ // TODO(aa): Can remove this when all JSON files are converted.
+ RegisterDependencyProvider("", this);
}
ExtensionAPI::~ExtensionAPI() {
@@ -334,8 +343,6 @@
void ExtensionAPI::InitDefaultConfiguration() {
RegisterDependencyProvider(
- "api", BaseFeatureProvider::GetApiFeatures());
- RegisterDependencyProvider(
"manifest", BaseFeatureProvider::GetManifestFeatures());
RegisterDependencyProvider(
"permission", BaseFeatureProvider::GetPermissionFeatures());
@@ -415,34 +422,27 @@
const Extension* extension,
Feature::Context context,
const GURL& url) {
- std::string feature_type;
- std::string feature_name;
- SplitDependencyName(full_name, &feature_type, &feature_name);
+ std::set<std::string> dependency_names;
+ dependency_names.insert(full_name);
+ ResolveDependencies(&dependency_names);
- std::string child_name;
- std::string api_name = GetAPINameFromFullName(feature_name, &child_name);
-
- Feature* feature = GetFeatureDependency(full_name);
-
// Check APIs not using the feature system first.
- if (!feature) {
- return IsNonFeatureAPIAvailable(api_name, context, extension, url) ?
+ if (!UsesFeatureSystem(full_name)) {
+ return IsNonFeatureAPIAvailable(full_name, context, extension, url) ?
Feature::CreateAvailability(Feature::IS_AVAILABLE, "") :
Feature::CreateAvailability(Feature::INVALID_CONTEXT,
kUnavailableMessage);
}
- Feature::Availability availability =
- feature->IsAvailableToContext(extension, context, url);
- if (!availability.is_available())
- return availability;
+ for (std::set<std::string>::iterator iter = dependency_names.begin();
+ iter != dependency_names.end(); ++iter) {
+ Feature* feature = GetFeatureDependency(*iter);
+ CHECK(feature) << *iter;
- for (std::set<std::string>::iterator iter = feature->dependencies().begin();
- iter != feature->dependencies().end(); ++iter) {
- Feature::Availability dependency_availability =
- IsAvailable(*iter, extension, context, url);
- if (!dependency_availability.is_available())
- return dependency_availability;
+ Feature::Availability availability =
+ feature->IsAvailableToContext(extension, context, url);
+ if (!availability.is_available())
+ return availability;
}
return Feature::CreateAvailability(Feature::IS_AVAILABLE, "");
@@ -451,21 +451,33 @@
bool ExtensionAPI::IsPrivileged(const std::string& full_name) {
std::string child_name;
std::string api_name = GetAPINameFromFullName(full_name, &child_name);
- Feature* feature = GetFeatureDependency(full_name);
// First try to use the feature system.
+ Feature* feature(GetFeature(full_name));
if (feature) {
- // An API is 'privileged' if it can only be run in a blessed context.
- return feature->GetContexts()->size() ==
- feature->GetContexts()->count(Feature::BLESSED_EXTENSION_CONTEXT);
+ // An API is 'privileged' if it or any of its dependencies can only be run
+ // in a blessed context.
+ std::set<std::string> resolved_dependencies;
+ resolved_dependencies.insert(full_name);
+ ResolveDependencies(&resolved_dependencies);
+ 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->GetContexts()->begin();
+ context != dependency->GetContexts()->end(); ++context) {
+ if (*context != Feature::BLESSED_EXTENSION_CONTEXT)
+ return false;
+ }
+ }
+ return true;
}
- // Get the schema now to populate |completely_unprivileged_apis_|.
- const DictionaryValue* schema = GetSchema(api_name);
// If this API hasn't been converted yet, fall back to the old system.
if (completely_unprivileged_apis_.count(api_name))
return false;
+ const DictionaryValue* schema = GetSchema(api_name);
if (partially_unprivileged_apis_.count(api_name))
return IsChildNamePrivileged(schema, child_name);
@@ -537,8 +549,6 @@
Feature::Context context,
const Extension* extension,
const GURL& url) {
- // Make sure schema is loaded.
- GetSchema(name);
switch (context) {
case Feature::UNSPECIFIED_CONTEXT:
break;
@@ -587,6 +597,36 @@
return result;
}
+Feature* ExtensionAPI::GetFeature(const std::string& full_name) {
+ // Ensure it's loaded.
+ GetSchema(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())
+ 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();
+ } else {
+ FeatureMap::iterator parent_feature = feature_map->second->find("");
+ CHECK(parent_feature != feature_map->second->end());
+ result = parent_feature->second.get();
+ }
+
+ if (result->GetContexts()->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) {
std::string feature_type;
std::string feature_name;
@@ -594,16 +634,11 @@
FeatureProviderMap::iterator provider =
dependency_providers_.find(feature_type);
- if (provider == dependency_providers_.end())
- return NULL;
+ CHECK(provider != dependency_providers_.end()) << full_name;
Feature* feature = provider->second->GetFeature(feature_name);
- // Try getting the feature for the parent API, if this was a child.
- if (!feature) {
- std::string child_name;
- feature = provider->second->GetFeature(
- GetAPINameFromFullName(feature_name, &child_name));
- }
+ CHECK(feature) << full_name;
+
return feature;
}
@@ -643,6 +678,47 @@
extension->optional_permission_set()->HasAnyAccessToAPI(name);
}
+void ExtensionAPI::ResolveDependencies(std::set<std::string>* out) {
+ std::set<std::string> missing_dependencies;
+ for (std::set<std::string>::iterator i = out->begin(); i != out->end(); ++i)
+ GetMissingDependencies(*i, *out, &missing_dependencies);
+
+ while (missing_dependencies.size()) {
+ std::string next = *missing_dependencies.begin();
+ missing_dependencies.erase(next);
+ out->insert(next);
+ GetMissingDependencies(next, *out, &missing_dependencies);
+ }
+}
+
+void ExtensionAPI::GetMissingDependencies(
+ const std::string& api_name,
+ const std::set<std::string>& excluding,
+ std::set<std::string>* out) {
+ std::string feature_type;
+ std::string feature_name;
+ SplitDependencyName(api_name, &feature_type, &feature_name);
+
+ // Only API features can have dependencies for now.
+ if (feature_type != "api")
+ return;
+
+ const DictionaryValue* schema = GetSchema(feature_name);
+ CHECK(schema) << "Schema for " << feature_name << " not found";
+
+ const ListValue* dependencies = NULL;
+ if (!schema->GetList("dependencies", &dependencies))
+ return;
+
+ for (size_t i = 0; i < dependencies->GetSize(); ++i) {
+ std::string dependency_name;
+ if (dependencies->GetString(i, &dependency_name) &&
+ !excluding.count(dependency_name)) {
+ out->insert(dependency_name);
+ }
+ }
+}
+
bool ExtensionAPI::IsPrivilegedAPI(const std::string& name) {
return completely_unprivileged_apis_.count(name) ||
partially_unprivileged_apis_.count(name);

Powered by Google App Engine
This is Rietveld 408576698