| 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 be02b20bfefd4b567bf6c666e4e3194ea53ffd12..78899fc022f333894216abd21623f7fcf36497c7 100644
|
| --- a/chrome/common/extensions/api/extension_api.cc
|
| +++ b/chrome/common/extensions/api/extension_api.cc
|
| @@ -37,48 +37,11 @@ using api::GeneratedSchemas;
|
|
|
| namespace {
|
|
|
| -const char kUnavailableMessage[] = "You do not have permission to access this "
|
| - "API. Ensure that the required permission "
|
| - "or manifest property is included in your "
|
| - "manifest.json.";
|
| const char* kChildKinds[] = {
|
| "functions",
|
| "events"
|
| };
|
|
|
| -// Returns true if |dict| has an unprivileged "true" property.
|
| -bool IsUnprivileged(const DictionaryValue* dict) {
|
| - bool unprivileged = false;
|
| - return dict->GetBoolean("unprivileged", &unprivileged) && unprivileged;
|
| -}
|
| -
|
| -// Returns whether the list at |name_space_node|.|child_kind| contains any
|
| -// children with an { "unprivileged": true } property.
|
| -bool HasUnprivilegedChild(const DictionaryValue* name_space_node,
|
| - const std::string& child_kind) {
|
| - const ListValue* child_list = NULL;
|
| - const DictionaryValue* child_dict = NULL;
|
| -
|
| - if (name_space_node->GetList(child_kind, &child_list)) {
|
| - for (size_t i = 0; i < child_list->GetSize(); ++i) {
|
| - const DictionaryValue* item = NULL;
|
| - CHECK(child_list->GetDictionary(i, &item));
|
| - if (IsUnprivileged(item))
|
| - return true;
|
| - }
|
| - } else if (name_space_node->GetDictionary(child_kind, &child_dict)) {
|
| - for (DictionaryValue::Iterator it(*child_dict); !it.IsAtEnd();
|
| - it.Advance()) {
|
| - const DictionaryValue* item = NULL;
|
| - CHECK(it.value().GetAsDictionary(&item));
|
| - if (IsUnprivileged(item))
|
| - return true;
|
| - }
|
| - }
|
| -
|
| - return false;
|
| -}
|
| -
|
| base::StringPiece ReadFromResource(int resource_id) {
|
| return ResourceBundle::GetSharedInstance().GetRawDataResource(
|
| resource_id);
|
| @@ -252,25 +215,12 @@ void ExtensionAPI::LoadSchema(const std::string& name,
|
| CHECK(schema->GetString("namespace", &schema_namespace));
|
| PrefixWithNamespace(schema_namespace, schema);
|
| schemas_[schema_namespace] = make_linked_ptr(schema);
|
| - CHECK_EQ(1u, unloaded_schemas_.erase(schema_namespace));
|
| -
|
| - // Populate |{completely,partially}_unprivileged_apis_|.
|
| -
|
| - // For "partially", only need to look at functions/events; even though
|
| - // there are unprivileged properties (e.g. in extensions), access to those
|
| - // never reaches C++ land.
|
| - bool unprivileged = false;
|
| - if (schema->GetBoolean("unprivileged", &unprivileged) && unprivileged) {
|
| - completely_unprivileged_apis_.insert(schema_namespace);
|
| - } else if (HasUnprivilegedChild(schema, "functions") ||
|
| - HasUnprivilegedChild(schema, "events") ||
|
| - HasUnprivilegedChild(schema, "properties")) {
|
| - partially_unprivileged_apis_.insert(schema_namespace);
|
| - }
|
| + if (!GeneratedSchemas::IsGenerated(schema_namespace))
|
| + CHECK_EQ(1u, unloaded_schemas_.erase(schema_namespace));
|
| }
|
| }
|
|
|
| -ExtensionAPI::ExtensionAPI() {
|
| +ExtensionAPI::ExtensionAPI() : default_configuration_initialized_(false) {
|
| }
|
|
|
| ExtensionAPI::~ExtensionAPI() {
|
| @@ -286,66 +236,49 @@ void ExtensionAPI::InitDefaultConfiguration() {
|
|
|
| // Schemas to be loaded from resources.
|
| CHECK(unloaded_schemas_.empty());
|
| - RegisterSchema("app", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_APP));
|
| - RegisterSchema("browserAction", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_BROWSERACTION));
|
| - RegisterSchema("browsingData", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_BROWSINGDATA));
|
| - RegisterSchema("commands", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_COMMANDS));
|
| - RegisterSchema("declarativeContent", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_DECLARATIVE_CONTENT));
|
| - RegisterSchema("declarativeWebRequest", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_DECLARATIVE_WEBREQUEST));
|
| - RegisterSchema("experimental.input.virtualKeyboard", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_VIRTUALKEYBOARD));
|
| - RegisterSchema("experimental.processes", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_EXPERIMENTAL_PROCESSES));
|
| - RegisterSchema("experimental.rlz", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_EXPERIMENTAL_RLZ));
|
| - RegisterSchema("runtime", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_RUNTIME));
|
| - RegisterSchema("fileBrowserHandler", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER));
|
| - RegisterSchema("fileBrowserPrivate", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_FILEBROWSERPRIVATE));
|
| - RegisterSchema("input.ime", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_INPUT_IME));
|
| - RegisterSchema("inputMethodPrivate", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE));
|
| - RegisterSchema("pageAction", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_PAGEACTION));
|
| - RegisterSchema("pageActions", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_PAGEACTIONS));
|
| - RegisterSchema("privacy", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_PRIVACY));
|
| - RegisterSchema("proxy", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_PROXY));
|
| - RegisterSchema("scriptBadge", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_SCRIPTBADGE));
|
| - RegisterSchema("streamsPrivate", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_STREAMSPRIVATE));
|
| - RegisterSchema("ttsEngine", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_TTSENGINE));
|
| - RegisterSchema("tts", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_TTS));
|
| - RegisterSchema("types", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_TYPES));
|
| - RegisterSchema("webRequestInternal", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_WEBREQUESTINTERNAL));
|
| - RegisterSchema("webstore", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_WEBSTORE));
|
| - RegisterSchema("webstorePrivate", ReadFromResource(
|
| - IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE));
|
| -
|
| - // Schemas to be loaded via JSON generated from IDL files.
|
| - GeneratedSchemas::Get(&unloaded_schemas_);
|
| + RegisterSchemaResource("app", IDR_EXTENSION_API_JSON_APP);
|
| + RegisterSchemaResource("browserAction", IDR_EXTENSION_API_JSON_BROWSERACTION);
|
| + RegisterSchemaResource("browsingData", IDR_EXTENSION_API_JSON_BROWSINGDATA);
|
| + RegisterSchemaResource("commands", IDR_EXTENSION_API_JSON_COMMANDS);
|
| + RegisterSchemaResource("declarativeContent",
|
| + IDR_EXTENSION_API_JSON_DECLARATIVE_CONTENT);
|
| + RegisterSchemaResource("declarativeWebRequest",
|
| + IDR_EXTENSION_API_JSON_DECLARATIVE_WEBREQUEST);
|
| + RegisterSchemaResource("experimental.input.virtualKeyboard",
|
| + IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_VIRTUALKEYBOARD);
|
| + RegisterSchemaResource("experimental.processes",
|
| + IDR_EXTENSION_API_JSON_EXPERIMENTAL_PROCESSES);
|
| + RegisterSchemaResource("experimental.rlz",
|
| + IDR_EXTENSION_API_JSON_EXPERIMENTAL_RLZ);
|
| + RegisterSchemaResource("runtime", IDR_EXTENSION_API_JSON_RUNTIME);
|
| + RegisterSchemaResource("fileBrowserHandler",
|
| + IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER);
|
| + RegisterSchemaResource("fileBrowserPrivate",
|
| + IDR_EXTENSION_API_JSON_FILEBROWSERPRIVATE);
|
| + RegisterSchemaResource("input.ime", IDR_EXTENSION_API_JSON_INPUT_IME);
|
| + RegisterSchemaResource("inputMethodPrivate",
|
| + IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE);
|
| + RegisterSchemaResource("pageAction", IDR_EXTENSION_API_JSON_PAGEACTION);
|
| + RegisterSchemaResource("pageActions", IDR_EXTENSION_API_JSON_PAGEACTIONS);
|
| + RegisterSchemaResource("privacy", IDR_EXTENSION_API_JSON_PRIVACY);
|
| + RegisterSchemaResource("proxy", IDR_EXTENSION_API_JSON_PROXY);
|
| + RegisterSchemaResource("scriptBadge", IDR_EXTENSION_API_JSON_SCRIPTBADGE);
|
| + RegisterSchemaResource("streamsPrivate",
|
| + IDR_EXTENSION_API_JSON_STREAMSPRIVATE);
|
| + RegisterSchemaResource("ttsEngine", IDR_EXTENSION_API_JSON_TTSENGINE);
|
| + RegisterSchemaResource("tts", IDR_EXTENSION_API_JSON_TTS);
|
| + RegisterSchemaResource("types", IDR_EXTENSION_API_JSON_TYPES);
|
| + RegisterSchemaResource("webRequestInternal",
|
| + IDR_EXTENSION_API_JSON_WEBREQUESTINTERNAL);
|
| + RegisterSchemaResource("webstore", IDR_EXTENSION_API_JSON_WEBSTORE);
|
| + RegisterSchemaResource("webstorePrivate",
|
| + IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE);
|
| + default_configuration_initialized_ = true;
|
| }
|
|
|
| -void ExtensionAPI::RegisterSchema(const std::string& name,
|
| - const base::StringPiece& source) {
|
| - unloaded_schemas_[name] = source;
|
| +void ExtensionAPI::RegisterSchemaResource(const std::string& name,
|
| + int resource_id) {
|
| + unloaded_schemas_[name] = resource_id;
|
| }
|
|
|
| void ExtensionAPI::RegisterDependencyProvider(const std::string& name,
|
| @@ -358,11 +291,12 @@ bool ExtensionAPI::IsAnyFeatureAvailableToContext(const std::string& api_name,
|
| const GURL& url) {
|
| FeatureProviderMap::iterator provider = dependency_providers_.find("api");
|
| CHECK(provider != dependency_providers_.end());
|
| - std::set<std::string> features = provider->second->GetAllFeatureNames();
|
| + const std::vector<std::string>& features =
|
| + provider->second->GetAllFeatureNames();
|
|
|
| // Check to see if there are any parts of this API that are allowed in this
|
| // context.
|
| - for (std::set<std::string>::iterator i = features.begin();
|
| + for (std::vector<std::string>::const_iterator i = features.begin();
|
| i != features.end(); ++i) {
|
| const std::string& feature_name = *i;
|
| if (feature_name != api_name && feature_name.find(api_name + ".") == 0) {
|
| @@ -381,19 +315,8 @@ Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name,
|
| 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 (!feature) {
|
| - return IsNonFeatureAPIAvailable(api_name, context, extension, url)
|
| - ? Feature::CreateAvailability(Feature::IS_AVAILABLE,
|
| - std::string())
|
| - : Feature::CreateAvailability(Feature::INVALID_CONTEXT,
|
| - kUnavailableMessage);
|
| - }
|
| + CHECK(feature) << full_name;
|
|
|
| Feature::Availability availability =
|
| feature->IsAvailableToContext(extension, context, url);
|
| @@ -412,37 +335,12 @@ 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.
|
| - 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);
|
| - }
|
| -
|
| - // 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;
|
| -
|
| - if (partially_unprivileged_apis_.count(api_name))
|
| - return IsChildNamePrivileged(schema, child_name);
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ExtensionAPI::IsChildNamePrivileged(const DictionaryValue* name_space_node,
|
| - const std::string& child_name) {
|
| - bool unprivileged = false;
|
| - const DictionaryValue* child = GetSchemaChild(name_space_node, child_name);
|
| - if (!child || !child->GetBoolean("unprivileged", &unprivileged))
|
| - return true;
|
| -
|
| - return !unprivileged;
|
| + CHECK(feature);
|
| + DCHECK(!feature->GetContexts()->empty());
|
| + // 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);
|
| }
|
|
|
| const DictionaryValue* ExtensionAPI::GetSchema(const std::string& full_name) {
|
| @@ -455,12 +353,18 @@ const DictionaryValue* ExtensionAPI::GetSchema(const std::string& full_name) {
|
| result = maybe_schema->second.get();
|
| } else {
|
| // Might not have loaded yet; or might just not exist.
|
| - std::map<std::string, base::StringPiece>::iterator maybe_schema_resource =
|
| + UnloadedSchemaMap::iterator maybe_schema_resource =
|
| unloaded_schemas_.find(api_name);
|
| - if (maybe_schema_resource == unloaded_schemas_.end())
|
| + if (maybe_schema_resource != unloaded_schemas_.end()) {
|
| + LoadSchema(maybe_schema_resource->first,
|
| + ReadFromResource(maybe_schema_resource->second));
|
| + } else if (default_configuration_initialized_ &&
|
| + GeneratedSchemas::IsGenerated(api_name)) {
|
| + LoadSchema(api_name, GeneratedSchemas::Get(api_name));
|
| + } else {
|
| return NULL;
|
| + }
|
|
|
| - LoadSchema(maybe_schema_resource->first, maybe_schema_resource->second);
|
| maybe_schema = schemas_.find(api_name);
|
| CHECK(schemas_.end() != maybe_schema);
|
| result = maybe_schema->second.get();
|
| @@ -472,80 +376,6 @@ const DictionaryValue* ExtensionAPI::GetSchema(const std::string& full_name) {
|
| return result;
|
| }
|
|
|
| -namespace {
|
| -
|
| -const char* kDisallowedPlatformAppFeatures[] = {
|
| - // "app" refers to the the legacy app namespace for hosted apps.
|
| - "app",
|
| - "extension",
|
| - "tabs",
|
| - "windows"
|
| -};
|
| -
|
| -bool IsFeatureAllowedForExtension(const std::string& feature,
|
| - const extensions::Extension& extension) {
|
| - if (extension.is_platform_app()) {
|
| - for (size_t i = 0; i < arraysize(kDisallowedPlatformAppFeatures); ++i) {
|
| - if (feature == kDisallowedPlatformAppFeatures[i])
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -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;
|
| -
|
| - case Feature::BLESSED_EXTENSION_CONTEXT:
|
| - if (extension) {
|
| - // Availability is determined by the permissions of the extension.
|
| - if (!IsAPIAllowed(name, extension))
|
| - return false;
|
| - if (!IsFeatureAllowedForExtension(name, *extension))
|
| - return false;
|
| - }
|
| - break;
|
| -
|
| - case Feature::UNBLESSED_EXTENSION_CONTEXT:
|
| - case Feature::CONTENT_SCRIPT_CONTEXT:
|
| - if (extension) {
|
| - // Same as BLESSED_EXTENSION_CONTEXT, but only those APIs that are
|
| - // unprivileged.
|
| - if (!IsAPIAllowed(name, extension))
|
| - return false;
|
| - if (!IsPrivilegedAPI(name))
|
| - return false;
|
| - }
|
| - break;
|
| -
|
| - case Feature::WEB_PAGE_CONTEXT:
|
| - return false;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -std::set<std::string> ExtensionAPI::GetAllAPINames() {
|
| - std::set<std::string> result;
|
| - for (SchemaMap::iterator i = schemas_.begin(); i != schemas_.end(); ++i)
|
| - result.insert(i->first);
|
| - for (UnloadedSchemaMap::iterator i = unloaded_schemas_.begin();
|
| - i != unloaded_schemas_.end(); ++i) {
|
| - result.insert(i->first);
|
| - }
|
| - return result;
|
| -}
|
| -
|
| Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) {
|
| std::string feature_type;
|
| std::string feature_name;
|
| @@ -571,6 +401,7 @@ std::string ExtensionAPI::GetAPINameFromFullName(const std::string& full_name,
|
| std::string api_name_candidate = full_name;
|
| while (true) {
|
| if (schemas_.find(api_name_candidate) != schemas_.end() ||
|
| + GeneratedSchemas::IsGenerated(api_name_candidate) ||
|
| unloaded_schemas_.find(api_name_candidate) != unloaded_schemas_.end()) {
|
| std::string result = api_name_candidate;
|
|
|
| @@ -595,17 +426,4 @@ std::string ExtensionAPI::GetAPINameFromFullName(const std::string& full_name,
|
| return std::string();
|
| }
|
|
|
| -bool ExtensionAPI::IsAPIAllowed(const std::string& name,
|
| - const Extension* extension) {
|
| - return PermissionsData::GetRequiredPermissions(extension)->
|
| - HasAnyAccessToAPI(name) ||
|
| - PermissionsData::GetOptionalPermissions(extension)->
|
| - HasAnyAccessToAPI(name);
|
| -}
|
| -
|
| -bool ExtensionAPI::IsPrivilegedAPI(const std::string& name) {
|
| - return completely_unprivileged_apis_.count(name) ||
|
| - partially_unprivileged_apis_.count(name);
|
| -}
|
| -
|
| } // namespace extensions
|
|
|