summaryrefslogtreecommitdiffstats
path: root/chrome/common/extensions/api
diff options
context:
space:
mode:
authorkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-18 08:22:22 +0000
committerkalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-18 08:22:22 +0000
commitcdb3a8bffd314443da88ae89bc87dc34f43a0e66 (patch)
tree4be9af79bfe8add68961d54f3677b14b8a5413fc /chrome/common/extensions/api
parent4e167479b6eab4c9bb6aaf2284478bc009909851 (diff)
downloadchromium_src-cdb3a8bffd314443da88ae89bc87dc34f43a0e66.zip
chromium_src-cdb3a8bffd314443da88ae89bc87dc34f43a0e66.tar.gz
chromium_src-cdb3a8bffd314443da88ae89bc87dc34f43a0e66.tar.bz2
Revert 127391 - Convert app_bindings.js to the schema_generated_bindings.js infrastructure.
This involves opening up *all* custom bindings to web pages, where access is controlled content-script style using a URL-matches property in the API schema. Reverted due to performance regression. BUG=104100,117282 TEST=unit_tests,browser_tests Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=125811 Review URL: http://codereview.chromium.org/9460002 TBR=kalman@chromium.org Review URL: https://chromiumcodereview.appspot.com/9718023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@127402 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common/extensions/api')
-rw-r--r--chrome/common/extensions/api/app.json70
-rw-r--r--chrome/common/extensions/api/extension_api.cc169
-rw-r--r--chrome/common/extensions/api/extension_api.h68
-rw-r--r--chrome/common/extensions/api/extension_api_unittest.cc144
4 files changed, 118 insertions, 333 deletions
diff --git a/chrome/common/extensions/api/app.json b/chrome/common/extensions/api/app.json
deleted file mode 100644
index 0e813e6..0000000
--- a/chrome/common/extensions/api/app.json
+++ /dev/null
@@ -1,70 +0,0 @@
-[
- {
- "namespace": "app",
- "nodoc": true,
- "unprivileged": true,
- "matches": [ "<all_urls>" ],
- "types": [
- {
- "id": "Details",
- "description": "TODO (it's a manifest)",
- "type": "object",
- "properties": {},
- "additionalProperties": { "type": "any" }
- },
- {
- "id": "DOMWindow",
- "type": "object",
- "properties": {},
- "additionalProperties": { "type": "any" }
- }
- ],
- "functions": [
- {
- "name": "getIsInstalled",
- "description": "TODO",
- "type": "function",
- "parameters": [],
- "returns": {
- "name": "isInstalled",
- "description": "TODO",
- "type": "boolean"
- }
- },
- {
- "name": "install",
- "description": "TODO",
- "type": "function",
- "parameters": []
- },
- {
- "name": "getDetails",
- "description": "TODO",
- "type": "function",
- "parameters": [],
- "returns": {
- "$ref": "Details",
- "optional": true,
- "description": "TODO"
- }
- },
- {
- "name": "getDetailsForFrame",
- "description": "TODO",
- "type": "function",
- "parameters": [
- {
- "name": "frame",
- "description": "TODO",
- "$ref": "DOMWindow"
- }
- ],
- "returns": {
- "$ref": "Details",
- "optional": true,
- "description": "TODO"
- }
- }
- ]
- }
-]
diff --git a/chrome/common/extensions/api/extension_api.cc b/chrome/common/extensions/api/extension_api.cc
index 5bd45f9..f8909b0 100644
--- a/chrome/common/extensions/api/extension_api.cc
+++ b/chrome/common/extensions/api/extension_api.cc
@@ -15,7 +15,6 @@
#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"
@@ -23,6 +22,22 @@ 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,
@@ -80,7 +95,6 @@ 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,
@@ -165,27 +179,6 @@ 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() {
@@ -265,109 +258,59 @@ const base::DictionaryValue* ExtensionAPI::GetSchema(
return maybe_schema != schemas_.end() ? maybe_schema->second.get() : NULL;
}
-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:
- // Availability is determined by the permissions of the extension
- // (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::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);
}
-void ExtensionAPI::ResolveDependencies(std::set<std::string>* out) const {
+void ExtensionAPI::ResolveDependencies(SchemaMap* out) const {
std::set<std::string> missing_dependencies;
- for (std::set<std::string>::iterator i = out->begin(); i != out->end(); ++i)
- GetMissingDependencies(*i, *out, &missing_dependencies);
+ for (SchemaMap::const_iterator i = out->begin(); i != out->end(); ++i)
+ GetMissingDependencies(*i->second, *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);
+ 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);
}
}
-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::GetDefaultSchemas(GetSchemasFilter filter,
+ SchemaMap* out) const {
+ scoped_refptr<ExtensionPermissionSet> default_permissions(
+ new ExtensionPermissionSet());
+ GetSchemasForPermissions(*default_permissions, filter, out);
+ ResolveDependencies(out);
}
-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);
+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::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);
- }
+bool ExtensionAPI::IsWholeAPIPrivileged(const std::string& api_name) const {
+ return !completely_unprivileged_apis_.count(api_name) &&
+ !partially_unprivileged_apis_.count(api_name);
}
} // namespace extensions
diff --git a/chrome/common/extensions/api/extension_api.h b/chrome/common/extensions/api/extension_api.h
index 6e2c604..25ac679 100644
--- a/chrome/common/extensions/api/extension_api.h
+++ b/chrome/common/extensions/api/extension_api.h
@@ -12,11 +12,8 @@
#include "base/basictypes.h"
#include "base/memory/linked_ptr.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/values.h"
-#include "chrome/common/extensions/feature.h"
-#include "chrome/common/extensions/url_pattern_set.h"
namespace base {
class DictionaryValue;
@@ -24,7 +21,6 @@ class ListValue;
class Value;
}
-class GURL;
class Extension;
class ExtensionPermissionSet;
@@ -33,6 +29,18 @@ namespace extensions {
// C++ Wrapper for the JSON API definitions in chrome/common/extensions/api/.
class ExtensionAPI {
public:
+ // Filtering option for the GetSchemas functions.
+ enum GetSchemasFilter {
+ // Returns all schemas that an extension has permission for.
+ ALL,
+
+ // Returns schemas for only APIs with unprivileged components (i.e. those
+ // where !IsWholeAPIPrivileged).
+ ONLY_UNPRIVILEGED
+ };
+
+ typedef std::map<std::string, linked_ptr<const DictionaryValue> > SchemaMap;
+
// Returns the single instance of this class.
static ExtensionAPI* GetInstance();
@@ -42,17 +50,26 @@ class ExtensionAPI {
// content scripts, or other low-privileged contexts.
bool IsPrivileged(const std::string& name) const;
+ // Returns whether *every* path in the API is privileged. This will be false
+ // for APIs such as "storage" which is entirely unprivileged, and "test"
+ // which has unprivileged components.
+ bool IsWholeAPIPrivileged(const std::string& api_name) const;
+
+ // Gets a map of API name (aka namespace) to API schema.
+ const SchemaMap& schemas() { return schemas_; }
+
// Gets the schema for the extension API with namespace |api_name|.
// Ownership remains with this object.
const base::DictionaryValue* GetSchema(const std::string& api_name) const;
- // Gets the APIs available to |context| given an |extension| and |url|. The
- // extension or URL may not be relevant to all contexts, and may be left
- // NULL/empty.
- scoped_ptr<std::set<std::string> > GetAPIsForContext(
- Feature::Context context,
- const Extension* extension,
- const GURL& url) const;
+ // Gets the API schemas that are available to an Extension.
+ void GetSchemasForExtension(const Extension& extension,
+ GetSchemasFilter filter,
+ SchemaMap* out) const;
+
+ // Gets the schemas for the default set of APIs that are available to every
+ // extension.
+ void GetDefaultSchemas(GetSchemasFilter filter, SchemaMap* out) const;
private:
friend struct DefaultSingletonTraits<ExtensionAPI>;
@@ -76,34 +93,18 @@ class ExtensionAPI {
const std::string& child_kind,
const std::string& child_name) const;
- // Adds all APIs to |out| that |extension| has any permission (required or
- // optional) to use.
- void GetAllowedAPIs(
- const Extension* extension, std::set<std::string>* out) const;
+ // Gets the schemas for the APIs that are allowed by a permission set.
+ void GetSchemasForPermissions(const ExtensionPermissionSet& permissions,
+ GetSchemasFilter filter,
+ SchemaMap* out) const;
// Adds dependent schemas to |out| as determined by the "dependencies"
// property.
- void ResolveDependencies(std::set<std::string>* out) const;
-
- // Adds any APIs listed in "dependencies" found in the schema for |api_name|
- // but not in |excluding| to |out|.
- void GetMissingDependencies(
- const std::string& api_name,
- const std::set<std::string>& excluding,
- std::set<std::string>* out) const;
-
- // Removes all APIs from |apis| which are *entirely* privileged. This won't
- // include APIs such as "storage" which is entirely unprivileged, nor
- // "extension" which has unprivileged components.
- void RemovePrivilegedAPIs(std::set<std::string>* apis) const;
-
- // Adds an APIs that match |url| to |out|.
- void GetAPIsMatchingURL(const GURL& url, std::set<std::string>* out) const;
+ void ResolveDependencies(SchemaMap* out) const;
static ExtensionAPI* instance_;
// Schemas for each namespace.
- typedef std::map<std::string, linked_ptr<const DictionaryValue> > SchemaMap;
SchemaMap schemas_;
// APIs that are entirely unprivileged.
@@ -112,9 +113,6 @@ class ExtensionAPI {
// APIs that are not entirely unprivileged, but have unprivileged components.
std::set<std::string> partially_unprivileged_apis_;
- // APIs that have URL matching permissions.
- std::map<std::string, URLPatternSet> url_matching_apis_;
-
DISALLOW_COPY_AND_ASSIGN(ExtensionAPI);
};
diff --git a/chrome/common/extensions/api/extension_api_unittest.cc b/chrome/common/extensions/api/extension_api_unittest.cc
index 3f4a0af..70982f7 100644
--- a/chrome/common/extensions/api/extension_api_unittest.cc
+++ b/chrome/common/extensions/api/extension_api_unittest.cc
@@ -13,10 +13,7 @@
#include "chrome/common/extensions/extension.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace {
-
using extensions::ExtensionAPI;
-using extensions::Feature;
TEST(ExtensionAPI, IsPrivileged) {
ExtensionAPI* extension_api = ExtensionAPI::GetInstance();
@@ -36,8 +33,6 @@ TEST(ExtensionAPI, IsPrivileged) {
EXPECT_TRUE(extension_api->IsPrivileged("history.search"));
// Whole APIs that are unprivileged.
- EXPECT_FALSE(extension_api->IsPrivileged("app.getDetails"));
- EXPECT_FALSE(extension_api->IsPrivileged("app.isInstalled"));
EXPECT_FALSE(extension_api->IsPrivileged("storage.local"));
EXPECT_FALSE(extension_api->IsPrivileged("storage.local.onChanged"));
EXPECT_FALSE(extension_api->IsPrivileged("storage.local.set"));
@@ -45,18 +40,34 @@ TEST(ExtensionAPI, IsPrivileged) {
EXPECT_FALSE(extension_api->IsPrivileged("storage.set"));
}
-scoped_refptr<Extension> CreateExtensionWithPermissions(
- const std::set<std::string>& permissions) {
+TEST(ExtensionAPI, IsWholeAPIPrivileged) {
+ ExtensionAPI* extension_api = ExtensionAPI::GetInstance();
+
+ // Completely unprivileged.
+ EXPECT_FALSE(extension_api->IsWholeAPIPrivileged("storage"));
+
+ // Partially unprivileged.
+ EXPECT_FALSE(extension_api->IsWholeAPIPrivileged("extension"));
+ EXPECT_FALSE(extension_api->IsWholeAPIPrivileged("test"));
+
+ // Nothing unprivileged.
+ EXPECT_TRUE(extension_api->IsWholeAPIPrivileged("history"));
+
+ // Paranoid above... paranoid here, too.
+ EXPECT_TRUE(extension_api->IsWholeAPIPrivileged(""));
+ EXPECT_TRUE(extension_api->IsWholeAPIPrivileged("<unknown-namespace>"));
+}
+
+TEST(ExtensionAPI, Depends) {
+ // Fake extension with the "ttsEngine" permission but not the "tts"
+ // permission; it must load TTS.
DictionaryValue manifest;
- manifest.SetString("name", "extension");
+ manifest.SetString("name", "test extension");
manifest.SetString("version", "1.0");
{
- scoped_ptr<ListValue> permissions_list(new ListValue());
- for (std::set<std::string>::const_iterator i = permissions.begin();
- i != permissions.end(); ++i) {
- permissions_list->Append(Value::CreateStringValue(*i));
- }
- manifest.Set("permissions", permissions_list.release());
+ scoped_ptr<ListValue> permissions(new ListValue());
+ permissions->Append(Value::CreateStringValue("ttsEngine"));
+ manifest.Set("permissions", permissions.release());
}
std::string error;
@@ -65,105 +76,8 @@ scoped_refptr<Extension> CreateExtensionWithPermissions(
CHECK(extension.get());
CHECK(error.empty());
- return extension;
-}
-
-scoped_refptr<Extension> CreateExtensionWithPermission(
- const std::string& permission) {
- std::set<std::string> permissions;
- permissions.insert(permission);
- return CreateExtensionWithPermissions(permissions);
-}
-
-TEST(ExtensionAPI, ExtensionWithUnprivilegedAPIs) {
- scoped_refptr<Extension> extension;
- {
- std::set<std::string> permissions;
- permissions.insert("storage");
- permissions.insert("history");
- extension = CreateExtensionWithPermissions(permissions);
- }
-
- scoped_ptr<std::set<std::string> > privileged_apis =
- ExtensionAPI::GetInstance()->GetAPIsForContext(
- Feature::PRIVILEGED_CONTEXT, extension.get(), GURL());
-
- scoped_ptr<std::set<std::string> > unprivileged_apis =
- ExtensionAPI::GetInstance()->GetAPIsForContext(
- Feature::UNPRIVILEGED_CONTEXT, extension.get(), GURL());
-
- scoped_ptr<std::set<std::string> > content_script_apis =
- ExtensionAPI::GetInstance()->GetAPIsForContext(
- Feature::CONTENT_SCRIPT_CONTEXT, extension.get(), GURL());
-
- // "storage" is completely unprivileged.
- EXPECT_EQ(1u, privileged_apis->count("storage"));
- EXPECT_EQ(1u, unprivileged_apis->count("storage"));
- EXPECT_EQ(1u, content_script_apis->count("storage"));
-
- // "extension" is partially unprivileged.
- EXPECT_EQ(1u, privileged_apis->count("extension"));
- EXPECT_EQ(1u, unprivileged_apis->count("extension"));
- EXPECT_EQ(1u, content_script_apis->count("extension"));
-
- // "history" is entirely privileged.
- EXPECT_EQ(1u, privileged_apis->count("history"));
- EXPECT_EQ(0u, unprivileged_apis->count("history"));
- EXPECT_EQ(0u, content_script_apis->count("history"));
-}
-
-TEST(ExtensionAPI, ExtensionWithDependencies) {
- // Extension with the "ttsEngine" permission but not the "tts" permission; it
- // must load TTS.
- {
- scoped_refptr<Extension> extension =
- CreateExtensionWithPermission("ttsEngine");
- scoped_ptr<std::set<std::string> > apis =
- ExtensionAPI::GetInstance()->GetAPIsForContext(
- Feature::PRIVILEGED_CONTEXT, extension.get(), GURL());
- EXPECT_EQ(1u, apis->count("ttsEngine"));
- EXPECT_EQ(1u, apis->count("tts"));
- }
-
- // Conversely, extension with the "tts" permission but not the "ttsEngine"
- // permission shouldn't get the "ttsEngine" permission.
- {
- scoped_refptr<Extension> extension =
- CreateExtensionWithPermission("tts");
- scoped_ptr<std::set<std::string> > apis =
- ExtensionAPI::GetInstance()->GetAPIsForContext(
- Feature::PRIVILEGED_CONTEXT, extension.get(), GURL());
- EXPECT_EQ(0u, apis->count("ttsEngine"));
- EXPECT_EQ(1u, apis->count("tts"));
- }
-}
-
-bool MatchesURL(const std::string& api_name, const std::string& url) {
- scoped_ptr<std::set<std::string> > apis =
- ExtensionAPI::GetInstance()->GetAPIsForContext(
- Feature::WEB_PAGE_CONTEXT, NULL, GURL(url));
- return apis->count(api_name);
-}
-
-TEST(ExtensionAPI, URLMatching) {
- // "app" API is available to all URLs that content scripts can be injected.
- EXPECT_TRUE(MatchesURL("app", "http://example.com/example.html"));
- EXPECT_TRUE(MatchesURL("app", "https://blah.net"));
- EXPECT_TRUE(MatchesURL("app", "file://somefile.html"));
-
- // But not internal URLs (for chrome-extension:// the app API is injected by
- // GetSchemasForExtension).
- EXPECT_FALSE(MatchesURL("app", "about:flags"));
- EXPECT_FALSE(MatchesURL("app", "chrome://flags"));
- EXPECT_FALSE(MatchesURL("app", "chrome-extension://fakeextension"));
-
- // "storage" API (for example) isn't available to any URLs.
- EXPECT_FALSE(MatchesURL("storage", "http://example.com/example.html"));
- EXPECT_FALSE(MatchesURL("storage", "https://blah.net"));
- EXPECT_FALSE(MatchesURL("storage", "file://somefile.html"));
- EXPECT_FALSE(MatchesURL("storage", "about:flags"));
- EXPECT_FALSE(MatchesURL("storage", "chrome://flags"));
- EXPECT_FALSE(MatchesURL("storage", "chrome-extension://fakeextension"));
+ ExtensionAPI::SchemaMap schemas;
+ ExtensionAPI::GetInstance()->GetSchemasForExtension(
+ *extension, ExtensionAPI::ALL, &schemas);
+ EXPECT_EQ(1u, schemas.count("tts"));
}
-
-} // namespace