| 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 c2a9cce97931c24a04b16ad3b7f1e8a911e57e13..d2c2b78d50a18a6c29fe2f72e38bfba67a69b4be 100644
|
| --- a/chrome/common/extensions/api/extension_api.cc
|
| +++ b/chrome/common/extensions/api/extension_api.cc
|
| @@ -234,11 +234,6 @@ void ExtensionAPI::SplitDependencyName(const std::string& full_name,
|
| *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));
|
| @@ -332,10 +327,6 @@ void ExtensionAPI::LoadSchema(const std::string& name,
|
| }
|
|
|
| ExtensionAPI::ExtensionAPI() {
|
| - RegisterDependencyProvider("api", this);
|
| -
|
| - // TODO(aa): Can remove this when all JSON files are converted.
|
| - RegisterDependencyProvider("", this);
|
| }
|
|
|
| ExtensionAPI::~ExtensionAPI() {
|
| @@ -343,6 +334,8 @@ ExtensionAPI::~ExtensionAPI() {
|
|
|
| void ExtensionAPI::InitDefaultConfiguration() {
|
| RegisterDependencyProvider(
|
| + "api", BaseFeatureProvider::GetApiFeatures());
|
| + RegisterDependencyProvider(
|
| "manifest", BaseFeatureProvider::GetManifestFeatures());
|
| RegisterDependencyProvider(
|
| "permission", BaseFeatureProvider::GetPermissionFeatures());
|
| @@ -422,27 +415,34 @@ Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name,
|
| const Extension* extension,
|
| Feature::Context context,
|
| const GURL& url) {
|
| - std::set<std::string> dependency_names;
|
| - dependency_names.insert(full_name);
|
| - ResolveDependencies(&dependency_names);
|
| + std::string feature_type;
|
| + std::string feature_name;
|
| + SplitDependencyName(full_name, &feature_type, &feature_name);
|
| +
|
| + 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 (!UsesFeatureSystem(full_name)) {
|
| - return IsNonFeatureAPIAvailable(full_name, context, extension, url) ?
|
| + if (!feature) {
|
| + return IsNonFeatureAPIAvailable(api_name, context, extension, url) ?
|
| Feature::CreateAvailability(Feature::IS_AVAILABLE, "") :
|
| Feature::CreateAvailability(Feature::INVALID_CONTEXT,
|
| kUnavailableMessage);
|
| }
|
|
|
| - for (std::set<std::string>::iterator iter = dependency_names.begin();
|
| - iter != dependency_names.end(); ++iter) {
|
| - Feature* feature = GetFeatureDependency(*iter);
|
| - CHECK(feature) << *iter;
|
| -
|
| - Feature::Availability availability =
|
| - feature->IsAvailableToContext(extension, context, url);
|
| - if (!availability.is_available())
|
| - return availability;
|
| + Feature::Availability availability =
|
| + feature->IsAvailableToContext(extension, context, url);
|
| + if (!availability.is_available())
|
| + return availability;
|
| +
|
| + 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;
|
| }
|
|
|
| return Feature::CreateAvailability(Feature::IS_AVAILABLE, "");
|
| @@ -451,33 +451,21 @@ Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name,
|
| 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 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;
|
| + // 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);
|
| }
|
|
|
| + // 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);
|
|
|
| @@ -549,6 +537,8 @@ bool ExtensionAPI::IsNonFeatureAPIAvailable(const std::string& name,
|
| Feature::Context context,
|
| const Extension* extension,
|
| const GURL& url) {
|
| + // Make sure schema is loaded.
|
| + GetSchema(name);
|
| switch (context) {
|
| case Feature::UNSPECIFIED_CONTEXT:
|
| break;
|
| @@ -597,36 +587,6 @@ std::set<std::string> ExtensionAPI::GetAllAPINames() {
|
| 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;
|
| @@ -634,11 +594,16 @@ Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) {
|
|
|
| FeatureProviderMap::iterator provider =
|
| dependency_providers_.find(feature_type);
|
| - CHECK(provider != dependency_providers_.end()) << full_name;
|
| + if (provider == dependency_providers_.end())
|
| + return NULL;
|
|
|
| Feature* feature = provider->second->GetFeature(feature_name);
|
| - CHECK(feature) << full_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));
|
| + }
|
| return feature;
|
| }
|
|
|
| @@ -678,47 +643,6 @@ bool ExtensionAPI::IsAPIAllowed(const std::string& name,
|
| 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);
|
|
|