summaryrefslogtreecommitdiffstats
path: root/chrome/common/extensions/api/extension_api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/common/extensions/api/extension_api.cc')
-rw-r--r--chrome/common/extensions/api/extension_api.cc168
1 files changed, 112 insertions, 56 deletions
diff --git a/chrome/common/extensions/api/extension_api.cc b/chrome/common/extensions/api/extension_api.cc
index f8909b0..a36989d 100644
--- a/chrome/common/extensions/api/extension_api.cc
+++ b/chrome/common/extensions/api/extension_api.cc
@@ -15,6 +15,7 @@
#include "base/values.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_permission_set.h"
+#include "googleurl/src/gurl.h"
#include "grit/common_resources.h"
#include "ui/base/resource/resource_bundle.h"
@@ -22,22 +23,6 @@ namespace extensions {
namespace {
-// Adds any APIs listed in "dependencies" found in |schema| but not in
-// |reference| to |out|.
-void GetMissingDependencies(
- const DictionaryValue& schema,
- const ExtensionAPI::SchemaMap& reference,
- std::set<std::string>* out) {
- ListValue* dependencies = NULL;
- if (!schema.GetList("dependencies", &dependencies))
- return;
- for (size_t i = 0; i < dependencies->GetSize(); ++i) {
- std::string api_name;
- if (dependencies->GetString(i, &api_name) && !reference.count(api_name))
- out->insert(api_name);
- }
-}
-
// 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,
@@ -95,6 +80,7 @@ void ExtensionAPI::LoadSchemaFromResource(int resource_id) {
ExtensionAPI::ExtensionAPI() {
static int kJsonApiResourceIds[] = {
+ IDR_EXTENSION_API_JSON_APP,
IDR_EXTENSION_API_JSON_BOOKMARKS,
IDR_EXTENSION_API_JSON_BROWSERACTION,
IDR_EXTENSION_API_JSON_BROWSING_DATA,
@@ -179,6 +165,27 @@ ExtensionAPI::ExtensionAPI() {
partially_unprivileged_apis_.insert(it->first);
}
}
+
+ // Populate |url_matching_apis_|.
+ for (SchemaMap::const_iterator it = schemas_.begin();
+ it != schemas_.end(); ++it) {
+ ListValue* matches = NULL;
+ {
+ Value* matches_value = NULL;
+ if (!it->second->Get("matches", &matches_value))
+ continue;
+ CHECK_EQ(Value::TYPE_LIST, matches_value->GetType());
+ matches = static_cast<ListValue*>(matches_value);
+ }
+ URLPatternSet pattern_set;
+ for (size_t i = 0; i < matches->GetSize(); ++i) {
+ std::string pattern;
+ CHECK(matches->GetString(i, &pattern));
+ pattern_set.AddPattern(
+ URLPattern(UserScript::kValidUserScriptSchemes, pattern));
+ }
+ url_matching_apis_[it->first] = pattern_set;
+ }
}
ExtensionAPI::~ExtensionAPI() {
@@ -258,59 +265,108 @@ const base::DictionaryValue* ExtensionAPI::GetSchema(
return maybe_schema != schemas_.end() ? maybe_schema->second.get() : NULL;
}
-void ExtensionAPI::GetSchemasForExtension(const Extension& extension,
- GetSchemasFilter filter,
- SchemaMap* out) const {
- // Check both required_permissions and optional_permissions since we need
- // to return all schemas that might be needed.
- GetSchemasForPermissions(*extension.required_permission_set(), filter, out);
- GetSchemasForPermissions(*extension.optional_permission_set(), filter, out);
-
- // Note that dependency resolution might introduce APIs outside of the filter
- // (for example, "extensions" has unprivileged componenents but relies on
- // "tabs" which doesn't). It doesn't matter because schema_generated_bindings
- // does individual function/event based checking anyway, but it's a shame.
- ResolveDependencies(out);
+scoped_ptr<std::set<std::string> > ExtensionAPI::GetAPIsForContext(
+ Feature::Context context,
+ const Extension* extension,
+ const GURL& url) const {
+ scoped_ptr<std::set<std::string> > result(new std::set<std::string>());
+
+ switch (context) {
+ case Feature::UNSPECIFIED_CONTEXT:
+ break;
+
+ case Feature::PRIVILEGED_CONTEXT:
+ // Availability is determined by the permissions of the extension.
+ CHECK(extension);
+ GetAllowedAPIs(extension, result.get());
+ ResolveDependencies(result.get());
+ break;
+
+ case Feature::UNPRIVILEGED_CONTEXT:
+ case Feature::CONTENT_SCRIPT_CONTEXT:
+ // Same as PRIVILEGED_CONTEXT, but only those APIs that are unprivileged.
+ CHECK(extension);
+ GetAllowedAPIs(extension, result.get());
+ // Resolving dependencies before removing unprivileged APIs means that
+ // some unprivileged APIs may have unrealised dependencies. Too bad!
+ ResolveDependencies(result.get());
+ RemovePrivilegedAPIs(result.get());
+ break;
+
+ case Feature::WEB_PAGE_CONTEXT:
+ // Availablility is determined by the url.
+ CHECK(url.is_valid());
+ GetAPIsMatchingURL(url, result.get());
+ break;
+ }
+
+ return result.Pass();
+}
+
+void ExtensionAPI::GetAllowedAPIs(
+ const Extension* extension, std::set<std::string>* out) const {
+ for (SchemaMap::const_iterator i = schemas_.begin(); i != schemas_.end();
+ ++i) {
+ if (extension->required_permission_set()->HasAnyAccessToAPI(i->first) ||
+ extension->optional_permission_set()->HasAnyAccessToAPI(i->first)) {
+ out->insert(i->first);
+ }
+ }
}
-void ExtensionAPI::ResolveDependencies(SchemaMap* out) const {
+void ExtensionAPI::ResolveDependencies(std::set<std::string>* out) const {
std::set<std::string> missing_dependencies;
- for (SchemaMap::const_iterator i = out->begin(); i != out->end(); ++i)
- GetMissingDependencies(*i->second, *out, &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 api_name = *missing_dependencies.begin();
- missing_dependencies.erase(api_name);
- linked_ptr<const DictionaryValue> schema = schemas_.find(api_name)->second;
- (*out)[api_name] = schema;
- GetMissingDependencies(*schema, *out, &missing_dependencies);
+ std::string next = *missing_dependencies.begin();
+ missing_dependencies.erase(next);
+ out->insert(next);
+ GetMissingDependencies(next, *out, &missing_dependencies);
}
}
-void ExtensionAPI::GetDefaultSchemas(GetSchemasFilter filter,
- SchemaMap* out) const {
- scoped_refptr<ExtensionPermissionSet> default_permissions(
- new ExtensionPermissionSet());
- GetSchemasForPermissions(*default_permissions, filter, out);
- ResolveDependencies(out);
+void ExtensionAPI::GetMissingDependencies(
+ const std::string& api_name,
+ const std::set<std::string>& excluding,
+ std::set<std::string>* out) const {
+ const base::DictionaryValue* schema = GetSchema(api_name);
+ CHECK(schema) << "Schema for " << api_name << " not found";
+
+ ListValue* dependencies = NULL;
+ if (!schema->GetList("dependencies", &dependencies))
+ return;
+
+ for (size_t i = 0; i < dependencies->GetSize(); ++i) {
+ std::string api_name;
+ if (dependencies->GetString(i, &api_name) && !excluding.count(api_name))
+ out->insert(api_name);
+ }
}
-void ExtensionAPI::GetSchemasForPermissions(
- const ExtensionPermissionSet& permissions,
- GetSchemasFilter filter,
- SchemaMap* out) const {
- for (SchemaMap::const_iterator it = schemas_.begin(); it != schemas_.end();
- ++it) {
- if (filter == ONLY_UNPRIVILEGED && IsWholeAPIPrivileged(it->first))
- continue;
- if (permissions.HasAnyAccessToAPI(it->first))
- (*out)[it->first] = it->second;
+void ExtensionAPI::RemovePrivilegedAPIs(std::set<std::string>* apis) const {
+ std::set<std::string> privileged_apis;
+ for (std::set<std::string>::iterator i = apis->begin(); i != apis->end();
+ ++i) {
+ if (!completely_unprivileged_apis_.count(*i) &&
+ !partially_unprivileged_apis_.count(*i)) {
+ privileged_apis.insert(*i);
+ }
+ }
+ for (std::set<std::string>::iterator i = privileged_apis.begin();
+ i != privileged_apis.end(); ++i) {
+ apis->erase(*i);
}
}
-bool ExtensionAPI::IsWholeAPIPrivileged(const std::string& api_name) const {
- return !completely_unprivileged_apis_.count(api_name) &&
- !partially_unprivileged_apis_.count(api_name);
+void ExtensionAPI::GetAPIsMatchingURL(const GURL& url,
+ std::set<std::string>* out) const {
+ for (std::map<std::string, URLPatternSet>::const_iterator i =
+ url_matching_apis_.begin(); i != url_matching_apis_.end(); ++i) {
+ if (i->second.MatchesURL(url))
+ out->insert(i->first);
+ }
}
} // namespace extensions