summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authoryoz@chromium.org <yoz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-28 19:49:29 +0000
committeryoz@chromium.org <yoz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-28 19:49:29 +0000
commitdcedc59e236944e301a290c961fb85b33c905079 (patch)
treedd22c110a0dd8718c04f7e1a48cd0a89e89d4bde /extensions
parent85e3239645ccf4ac61bba6fb7313d61336175b79 (diff)
downloadchromium_src-dcedc59e236944e301a290c961fb85b33c905079.zip
chromium_src-dcedc59e236944e301a290c961fb85b33c905079.tar.gz
chromium_src-dcedc59e236944e301a290c961fb85b33c905079.tar.bz2
Split feature definitions into extensions and chrome features.
Features defined in _*_features.json are split into chrome/common/extensions/api and extensions/common/api, according to where those features are implemented. This also creates extensions_resources.pak. With support for more than one features source, we can eliminate the AppShell dependency on Chrome features. BUG=339301 TBR=sergeyberezin@chromium.org Review URL: https://codereview.chromium.org/246423002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@266634 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'extensions')
-rw-r--r--extensions/common/api/_api_features.json43
-rw-r--r--extensions/common/api/_manifest_features.json118
-rw-r--r--extensions/common/api/_permission_features.json57
-rw-r--r--extensions/common/extensions_client.h10
-rw-r--r--extensions/common/features/base_feature_provider.cc79
-rw-r--r--extensions/common/features/base_feature_provider.h3
-rw-r--r--extensions/common/features/base_feature_provider_unittest.cc32
-rw-r--r--extensions/common/features/feature_provider.cc39
-rw-r--r--extensions/common/features/json_feature_provider_source.cc54
-rw-r--r--extensions/common/features/json_feature_provider_source.h37
-rw-r--r--extensions/extensions.gyp2
-rw-r--r--extensions/extensions_resources.grd16
-rw-r--r--extensions/extensions_resources.gyp31
-rw-r--r--extensions/test/test_extensions_client.cc9
-rw-r--r--extensions/test/test_extensions_client.h3
15 files changed, 426 insertions, 107 deletions
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
new file mode 100644
index 0000000..cae93b1
--- /dev/null
+++ b/extensions/common/api/_api_features.json
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This features file defines extension APIs implemented under src/extensions.
+// See extensions/common/features/* to understand this file, in particular
+// feature.h, simple_feature.h, and base_feature_provider.h.
+//
+// Note that specifying "web_page", "blessed_web_page", or "all" as a context
+// type will require manually updating chrome/renderer/resources/dispatcher.cc.
+
+{
+ "dns": {
+ "dependencies": ["permission:dns"],
+ "contexts": ["blessed_extension"]
+ },
+ "socket": {
+ "dependencies": ["permission:socket"],
+ "contexts": ["blessed_extension"]
+ },
+ "sockets.tcp": {
+ "dependencies": ["manifest:sockets"],
+ "contexts": ["blessed_extension"]
+ },
+ "sockets.tcpServer": {
+ "dependencies": ["manifest:sockets"],
+ "contexts": ["blessed_extension"]
+ },
+ "sockets.udp": {
+ "dependencies": ["manifest:sockets"],
+ "contexts": ["blessed_extension"]
+ },
+ "storage": {
+ "dependencies": ["permission:storage"],
+ "contexts": ["blessed_extension", "unblessed_extension", "content_script"]
+ },
+ "test": {
+ "internal": true,
+ "channel": "stable",
+ "extension_types": "all",
+ "contexts": ["blessed_extension", "unblessed_extension", "content_script"]
+ }
+}
diff --git a/extensions/common/api/_manifest_features.json b/extensions/common/api/_manifest_features.json
new file mode 100644
index 0000000..60d0a2d
--- /dev/null
+++ b/extensions/common/api/_manifest_features.json
@@ -0,0 +1,118 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This features file defines manifest keys implemented under src/extensions.
+// See extensions/common/features/* to understand this file, in particular
+// feature.h, simple_feature.h, and base_feature_provider.h.
+
+{
+ // The default platform app CSP can only be overridden by whitelisted apps.
+ // This is a separate key from the top-level content_security_policy one since
+ // we can't combine type restrictions with whitelisted ID restrictions. If
+ // there is a need for additional whitelisted entries, the feature system
+ // should instead be extended to support OR-ing of restrictions.
+ "app.content_security_policy": {
+ "channel": "stable",
+ "extension_types": ["platform_app"],
+ "min_manifest_version": 2,
+ "whitelist": [
+ "nckgahadagoaajjgafhacjanaoiihapd", // Google Talk prod
+ "eggnbpckecmjlblplehfpjjdhhidfdoj", // Google Talk beta
+ "ppleadejekpmccmnpjdimmlfljlkdfej", // Google Talk alpha
+ "ljclpkphhpbpinifbeabbhlfddcpfdde", // Google Talk debug
+ "lphgohfeebnhcpiohjndkgbhhkoapkjc" // Apps Debugger
+ ]
+ },
+ "app.background": {
+ "channel": "stable",
+ "extension_types": ["platform_app"],
+ "min_manifest_version": 2
+ },
+ "background": {
+ "channel": "stable",
+ "extension_types": [
+ // Platform apps specify their background page via app.background.
+ "extension", "legacy_packaged_app", "hosted_app"
+ ]
+ },
+ "background.persistent": {
+ "channel": "stable",
+ "extension_types": [
+ "extension", "legacy_packaged_app"
+ ],
+ "min_manifest_version": 2
+ },
+ "background_page": {
+ "channel": "stable",
+ "extension_types": [
+ "extension", "legacy_packaged_app", "hosted_app"
+ ],
+ "max_manifest_version": 1
+ },
+ "content_security_policy": {
+ "channel": "stable",
+ // Platform apps have a restricted content security policy that cannot be
+ // overriden (except for a whitelist of exceptions, see the
+ // app.content_security_policy whitelist).
+ "extension_types": ["extension", "legacy_packaged_app"]
+ },
+ "incognito": [
+ {
+ "channel": "stable",
+ "extension_types": ["extension", "legacy_packaged_app"]
+ },
+ {
+ "channel": "stable",
+ "extension_types": ["platform_app"],
+ "location": "component"
+ }
+ ],
+ "kiosk_enabled": {
+ "channel": "stable",
+ "extension_types": [
+ "platform_app"
+ ]
+ },
+ "kiosk_only": {
+ "channel": "dev",
+ "extension_types": [
+ "platform_app"
+ ]
+ },
+ "offline_enabled": {
+ "channel": "stable",
+ "extension_types": [
+ "extension", "legacy_packaged_app", "hosted_app", "platform_app"
+ ]
+ },
+ "sandbox": {
+ "channel": "stable",
+ "extension_types": [
+ "extension", "platform_app", "legacy_packaged_app"
+ ],
+ "min_manifest_version": 2
+ },
+ "sockets": {
+ "channel": "stable",
+ "extension_types": ["platform_app"]
+ },
+ "web_accessible_resources": [
+ {
+ "channel": "stable",
+ "extension_types": [
+ "extension", "legacy_packaged_app", "hosted_app"
+ ]
+ },
+ {
+ "channel": "stable",
+ "extension_types": ["platform_app"],
+ "location": "component"
+ }
+ ],
+ "webview": {
+ "channel": "stable",
+ "extension_types": ["platform_app"],
+ "min_manifest_version": 2
+ }
+}
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json
new file mode 100644
index 0000000..a1e975b
--- /dev/null
+++ b/extensions/common/api/_permission_features.json
@@ -0,0 +1,57 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This features file defines permissions for extension APIs implemented
+// under src/extensions.
+
+// See extensions/common/features/* to understand this file, in particular
+// feature.h, simple_feature.h, and base_feature_provider.h.
+
+// To add a new whitelisted ID, SHA-1 it and force it to uppercase. In Bash:
+//
+// $ echo -n "aaaabbbbccccddddeeeeffffgggghhhh" | \
+// sha1sum | tr '[:lower:]' '[:upper:]'
+// 9A0417016F345C934A1A88F55CA17C05014EEEBA -
+//
+// Google employees: please update http://go/chrome-api-whitelist to map
+// hashes back to ids.
+
+{
+ "dns": [
+ {
+ "channel": "dev",
+ "extension_types": ["extension", "platform_app"]
+ },
+ {
+ "channel": "stable",
+ "extension_types": ["extension", "platform_app"],
+ "whitelist": [
+ "7AE714FFD394E073F0294CFA134C9F91DB5FBAA4", // CCD Development
+ "C7DA3A55C2355F994D3FDDAD120B426A0DF63843", // CCD Testing
+ "75E3CFFFC530582C583E4690EF97C70B9C8423B7" // CCD Release
+ ]
+ }
+ ],
+ "socket": [
+ {
+ "channel": "stable",
+ "extension_types": ["platform_app"]
+ },
+ {
+ "channel": "stable",
+ "extension_types": ["extension"],
+ "whitelist": [
+ // The connectivity diagnostic utility is a component extension that is
+ // used to try to provide suggestions on how to fix connection issues.
+ // It should be the only non-app allowed to use the socket API.
+ "32A1BA997F8AB8DE29ED1BA94AAF00CF2A3FEFA7"
+ ]
+ }
+ ],
+ "storage": {
+ "channel": "stable",
+ "extension_types": ["extension", "legacy_packaged_app", "platform_app"],
+ "min_manifest_version": 2
+ }
+}
diff --git a/extensions/common/extensions_client.h b/extensions/common/extensions_client.h
index e9fb200..8207895 100644
--- a/extensions/common/extensions_client.h
+++ b/extensions/common/extensions_client.h
@@ -9,6 +9,7 @@
#include <string>
#include <vector>
+#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
class GURL;
@@ -46,9 +47,9 @@ class ExtensionsClient {
virtual const PermissionMessageProvider& GetPermissionMessageProvider()
const = 0;
- // Gets a feature provider for a specific feature type.
- virtual FeatureProvider* GetFeatureProviderByName(const std::string& name)
- const = 0;
+ // Create a FeatureProvider for a specific feature type, e.g. "permission".
+ virtual scoped_ptr<FeatureProvider> CreateFeatureProvider(
+ const std::string& name) const = 0;
// Takes the list of all hosts and filters out those with special
// permission strings. Adds the regular hosts to |new_hosts|,
@@ -80,9 +81,6 @@ class ExtensionsClient {
// Gets the API schema named |name|.
virtual base::StringPiece GetAPISchema(const std::string& name) const = 0;
- // Appends extra filters to any Features created by the features system.
- virtual void AddExtraFeatureFilters(SimpleFeature* feature) const = 0;
-
// Determines if certain fatal extensions errors should be surpressed
// (i.e., only logged) or allowed (i.e., logged before crashing).
virtual bool ShouldSuppressFatalErrors() const = 0;
diff --git a/extensions/common/features/base_feature_provider.cc b/extensions/common/features/base_feature_provider.cc
index 57ee652..4b03fd0 100644
--- a/extensions/common/features/base_feature_provider.cc
+++ b/extensions/common/features/base_feature_provider.cc
@@ -6,84 +6,16 @@
#include <stack>
-#include "base/json/json_reader.h"
-#include "base/lazy_instance.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "extensions/common/extensions_client.h"
-#include "extensions/common/features/api_feature.h"
#include "extensions/common/features/complex_feature.h"
-#include "extensions/common/features/manifest_feature.h"
-#include "extensions/common/features/permission_feature.h"
-#include "grit/common_resources.h"
-#include "ui/base/resource/resource_bundle.h"
+#include "extensions/common/features/simple_feature.h"
namespace extensions {
namespace {
-template<class FeatureClass>
-SimpleFeature* CreateFeature() {
- SimpleFeature* feature = new FeatureClass();
- ExtensionsClient::Get()->AddExtraFeatureFilters(feature);
- return feature;
-}
-
-static BaseFeatureProvider* LoadProvider(
- const std::string& name,
- BaseFeatureProvider::FeatureFactory factory,
- int resource_id) {
- const std::string& features_file =
- ResourceBundle::GetSharedInstance().GetRawDataResource(
- resource_id).as_string();
- int error_code = 0;
- std::string error_message;
- scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
- features_file, base::JSON_PARSE_RFC,
- &error_code, &error_message));
- DCHECK(value) << "Could not load features: " << name << " "
- << error_message;
- scoped_ptr<base::DictionaryValue> value_as_dict;
- if (value) {
- CHECK(value->IsType(base::Value::TYPE_DICTIONARY)) << name;
- value_as_dict.reset(static_cast<base::DictionaryValue*>(value.release()));
- } else {
- // http://crbug.com/176381
- value_as_dict.reset(new base::DictionaryValue());
- }
- return new BaseFeatureProvider(*value_as_dict, factory);
-}
-
-struct Static {
- Static() {
- feature_providers["api"] = make_linked_ptr(
- LoadProvider("api",
- &CreateFeature<APIFeature>,
- IDR_EXTENSION_API_FEATURES));
- feature_providers["permission"] = make_linked_ptr(
- LoadProvider("permission",
- &CreateFeature<PermissionFeature>,
- IDR_EXTENSION_PERMISSION_FEATURES));
- feature_providers["manifest"] = make_linked_ptr(
- LoadProvider("manifest",
- &CreateFeature<ManifestFeature>,
- IDR_EXTENSION_MANIFEST_FEATURES));
- }
-
- typedef std::map<std::string, linked_ptr<FeatureProvider> >
- FeatureProviderMap;
-
- FeatureProvider* GetFeatures(const std::string& name) const {
- FeatureProviderMap::const_iterator it = feature_providers.find(name);
- CHECK(it != feature_providers.end());
- return it->second.get();
- }
-
- FeatureProviderMap feature_providers;
-};
-
-base::LazyInstance<Static> g_static = LAZY_INSTANCE_INITIALIZER;
-
bool ParseFeature(const base::DictionaryValue* value,
const std::string& name,
SimpleFeature* feature) {
@@ -98,8 +30,7 @@ bool ParseFeature(const base::DictionaryValue* value,
BaseFeatureProvider::BaseFeatureProvider(const base::DictionaryValue& root,
FeatureFactory factory)
- : factory_(factory ? factory :
- static_cast<FeatureFactory>(&CreateFeature<SimpleFeature>)) {
+ : factory_(factory) {
for (base::DictionaryValue::Iterator iter(root); !iter.IsAtEnd();
iter.Advance()) {
if (iter.value().GetType() == base::Value::TYPE_DICTIONARY) {
@@ -185,12 +116,6 @@ BaseFeatureProvider::BaseFeatureProvider(const base::DictionaryValue& root,
BaseFeatureProvider::~BaseFeatureProvider() {
}
-// static
-FeatureProvider* BaseFeatureProvider::GetByName(
- const std::string& name) {
- return g_static.Get().GetFeatures(name);
-}
-
const std::vector<std::string>& BaseFeatureProvider::GetAllFeatureNames()
const {
if (feature_names_.empty()) {
diff --git a/extensions/common/features/base_feature_provider.h b/extensions/common/features/base_feature_provider.h
index 4defdc2..acb8df3 100644
--- a/extensions/common/features/base_feature_provider.h
+++ b/extensions/common/features/base_feature_provider.h
@@ -27,9 +27,6 @@ class BaseFeatureProvider : public FeatureProvider {
FeatureFactory factory);
virtual ~BaseFeatureProvider();
- // Gets a feature provider for a specific feature type, like "permission".
- static FeatureProvider* GetByName(const std::string& name);
-
// Gets the feature |feature_name|, if it exists.
virtual Feature* GetFeature(const std::string& feature_name) const OVERRIDE;
virtual Feature* GetParent(Feature* feature) const OVERRIDE;
diff --git a/extensions/common/features/base_feature_provider_unittest.cc b/extensions/common/features/base_feature_provider_unittest.cc
index f856b35..0d19fd4 100644
--- a/extensions/common/features/base_feature_provider_unittest.cc
+++ b/extensions/common/features/base_feature_provider_unittest.cc
@@ -14,6 +14,18 @@ using chrome::VersionInfo;
namespace extensions {
+namespace {
+
+template <class FeatureClass>
+SimpleFeature* CreateFeature() {
+ SimpleFeature* feature = new FeatureClass();
+ feature->AddFilter(
+ scoped_ptr<SimpleFeatureFilter>(new ChromeChannelFeatureFilter(feature)));
+ return feature;
+}
+
+} // namespace
+
TEST(BaseFeatureProviderTest, ManifestFeatures) {
FeatureProvider* provider = BaseFeatureProvider::GetByName("manifest");
SimpleFeature* feature =
@@ -98,13 +110,6 @@ TEST(BaseFeatureProviderTest, PermissionFeatures) {
extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
}
-SimpleFeature* CreatePermissionFeature() {
- SimpleFeature* feature = new PermissionFeature();
- feature->AddFilter(
- scoped_ptr<SimpleFeatureFilter>(new ChromeChannelFeatureFilter(feature)));
- return feature;
-}
-
TEST(BaseFeatureProviderTest, Validation) {
scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
@@ -123,19 +128,21 @@ TEST(BaseFeatureProviderTest, Validation) {
value->Set("feature2", feature2);
scoped_ptr<BaseFeatureProvider> provider(
- new BaseFeatureProvider(*value, CreatePermissionFeature));
+ new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>));
// feature1 won't validate because it lacks an extension type.
EXPECT_FALSE(provider->GetFeature("feature1"));
// If we add one, it works.
feature1->Set("extension_types", extension_types->DeepCopy());
- provider.reset(new BaseFeatureProvider(*value, CreatePermissionFeature));
+ provider.reset(
+ new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>));
EXPECT_TRUE(provider->GetFeature("feature1"));
// Remove the channel, and feature1 won't validate.
feature1->Remove("channel", NULL);
- provider.reset(new BaseFeatureProvider(*value, CreatePermissionFeature));
+ provider.reset(
+ new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>));
EXPECT_FALSE(provider->GetFeature("feature1"));
// feature2 won't validate because of the presence of "contexts".
@@ -143,7 +150,8 @@ TEST(BaseFeatureProviderTest, Validation) {
// If we remove it, it works.
feature2->Remove("contexts", NULL);
- provider.reset(new BaseFeatureProvider(*value, CreatePermissionFeature));
+ provider.reset(
+ new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>));
EXPECT_TRUE(provider->GetFeature("feature2"));
}
@@ -162,7 +170,7 @@ TEST(BaseFeatureProviderTest, ComplexFeatures) {
.Build());
scoped_ptr<BaseFeatureProvider> provider(
- new BaseFeatureProvider(*rule, NULL));
+ new BaseFeatureProvider(*rule, CreateFeature<SimpleFeature>));
Feature* feature = provider->GetFeature("feature1");
EXPECT_TRUE(feature);
diff --git a/extensions/common/features/feature_provider.cc b/extensions/common/features/feature_provider.cc
index d5357f1..b8f21f3 100644
--- a/extensions/common/features/feature_provider.cc
+++ b/extensions/common/features/feature_provider.cc
@@ -4,14 +4,51 @@
#include "extensions/common/features/feature_provider.h"
+#include <map>
+
#include "base/basictypes.h"
+#include "base/lazy_instance.h"
+#include "base/memory/linked_ptr.h"
#include "extensions/common/extensions_client.h"
namespace extensions {
+namespace {
+
+class Static {
+ public:
+ FeatureProvider* GetFeatures(const std::string& name) const {
+ FeatureProviderMap::const_iterator it = feature_providers_.find(name);
+ CHECK(it != feature_providers_.end());
+ return it->second.get();
+ }
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<Static>;
+
+ Static() {
+ ExtensionsClient* client = ExtensionsClient::Get();
+ feature_providers_["api"] =
+ make_linked_ptr(client->CreateFeatureProvider("api").release());
+ feature_providers_["manifest"] =
+ make_linked_ptr(client->CreateFeatureProvider("manifest").release());
+ feature_providers_["permission"] =
+ make_linked_ptr(client->CreateFeatureProvider("permission").release());
+ }
+
+ typedef std::map<std::string, linked_ptr<FeatureProvider> >
+ FeatureProviderMap;
+
+ FeatureProviderMap feature_providers_;
+};
+
+base::LazyInstance<Static> g_static = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
// static
FeatureProvider* FeatureProvider::GetByName(const std::string& name) {
- return ExtensionsClient::Get()->GetFeatureProviderByName(name);
+ return g_static.Get().GetFeatures(name);
}
// static
diff --git a/extensions/common/features/json_feature_provider_source.cc b/extensions/common/features/json_feature_provider_source.cc
new file mode 100644
index 0000000..0a46f3f8
--- /dev/null
+++ b/extensions/common/features/json_feature_provider_source.cc
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/features/json_feature_provider_source.h"
+
+#include <string>
+
+#include "base/json/json_reader.h"
+#include "base/logging.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace extensions {
+
+JSONFeatureProviderSource::JSONFeatureProviderSource(const std::string& name)
+ : name_(name) {
+}
+
+JSONFeatureProviderSource::~JSONFeatureProviderSource() {
+}
+
+void JSONFeatureProviderSource::LoadJSON(int resource_id) {
+ const std::string& features_file = ResourceBundle::GetSharedInstance()
+ .GetRawDataResource(resource_id)
+ .as_string();
+ int error_code = 0;
+ std::string error_message;
+ scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
+ features_file, base::JSON_PARSE_RFC, &error_code, &error_message));
+ DCHECK(value) << "Could not load features: " << name_ << " " << error_message;
+
+ scoped_ptr<base::DictionaryValue> value_as_dict;
+ if (value) {
+ CHECK(value->IsType(base::Value::TYPE_DICTIONARY)) << name_;
+ value_as_dict.reset(static_cast<base::DictionaryValue*>(value.release()));
+ } else {
+ // There was some error loading the features file.
+ // http://crbug.com/176381
+ value_as_dict.reset(new base::DictionaryValue());
+ }
+
+ // Ensure there are no key collisions.
+ for (base::DictionaryValue::Iterator iter(*value_as_dict); !iter.IsAtEnd();
+ iter.Advance()) {
+ if (dictionary_.GetWithoutPathExpansion(iter.key(), NULL))
+ LOG(FATAL) << "Key " << iter.key() << " is defined in " << name_
+ << " JSON feature files more than once.";
+ }
+
+ // Merge.
+ dictionary_.MergeDictionary(value_as_dict.get());
+}
+
+} // namespace
diff --git a/extensions/common/features/json_feature_provider_source.h b/extensions/common/features/json_feature_provider_source.h
new file mode 100644
index 0000000..506b06f
--- /dev/null
+++ b/extensions/common/features/json_feature_provider_source.h
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_FEATURE_JSON_FEATURE_PROVIDER_SOURCE_H_
+#define EXTENSIONS_COMMON_FEATURE_JSON_FEATURE_PROVIDER_SOURCE_H_
+
+#include "base/values.h"
+
+namespace extensions {
+
+// A JSONFeatureProviderSource loads JSON dictionary files that
+// define features.
+class JSONFeatureProviderSource {
+ public:
+ explicit JSONFeatureProviderSource(const std::string& name);
+ ~JSONFeatureProviderSource();
+
+ // Adds the JSON dictionary file to this provider, merging its values with
+ // the current dictionary. Key collisions are treated as errors.
+ void LoadJSON(int resource_id);
+
+ // Returns the parsed dictionary.
+ const base::DictionaryValue& dictionary() { return dictionary_; }
+
+ private:
+ // The name of this feature type; only used for debugging.
+ const std::string name_;
+
+ base::DictionaryValue dictionary_;
+
+ DISALLOW_COPY_AND_ASSIGN(JSONFeatureProviderSource);
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_COMMON_FEATURE_JSON_FEATURE_PROVIDER_SOURCE_H_
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index 4e6afb8..43cf863 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -96,6 +96,8 @@
'common/features/feature.h',
'common/features/feature_provider.cc',
'common/features/feature_provider.h',
+ 'common/features/json_feature_provider_source.cc',
+ 'common/features/json_feature_provider_source.h',
'common/features/manifest_feature.cc',
'common/features/manifest_feature.h',
'common/features/permission_feature.cc',
diff --git a/extensions/extensions_resources.grd b/extensions/extensions_resources.grd
new file mode 100644
index 0000000..de5d4b5
--- /dev/null
+++ b/extensions/extensions_resources.grd
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1">
+ <outputs>
+ <output filename="grit/extensions_resources.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="extensions_resources.pak" type="data_package" />
+ </outputs>
+ <release seq="1">
+ <includes>
+ <include name="IDR_EXTENSION_API_FEATURES" file="common\api\_api_features.json" type="BINDATA" />
+ <include name="IDR_EXTENSION_MANIFEST_FEATURES" file="common\api\_manifest_features.json" type="BINDATA" />
+ <include name="IDR_EXTENSION_PERMISSION_FEATURES" file="common\api\_permission_features.json" type="BINDATA" />
+ </includes>
+ </release>
+</grit>
diff --git a/extensions/extensions_resources.gyp b/extensions/extensions_resources.gyp
new file mode 100644
index 0000000..dcbf26f
--- /dev/null
+++ b/extensions/extensions_resources.gyp
@@ -0,0 +1,31 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/extensions',
+ },
+ 'targets': [
+ {
+ 'target_name': 'extensions_resources',
+ 'type': 'none',
+ 'actions': [
+ # Data resources.
+ {
+ 'action_name': 'extensions_resources',
+ 'variables': {
+ 'grit_grd_file': 'extensions_resources.grd',
+ },
+ 'includes': [ '../build/grit_action.gypi' ],
+ },
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)/extensions',
+ ],
+ },
+ 'hard_dependency': 1,
+ }
+ ]
+}
diff --git a/extensions/test/test_extensions_client.cc b/extensions/test/test_extensions_client.cc
index ed31ce7..c597e5a 100644
--- a/extensions/test/test_extensions_client.cc
+++ b/extensions/test/test_extensions_client.cc
@@ -39,9 +39,10 @@ TestExtensionsClient::GetPermissionMessageProvider() const {
return provider;
}
-FeatureProvider* TestExtensionsClient::GetFeatureProviderByName(
+// TODO(yoz): Implement something reasonable here.
+scoped_ptr<FeatureProvider> TestExtensionsClient::CreateFeatureProvider(
const std::string& name) const {
- return BaseFeatureProvider::GetByName(name);
+ return scoped_ptr<FeatureProvider>();
}
void TestExtensionsClient::FilterHostPermissions(
@@ -82,10 +83,6 @@ base::StringPiece TestExtensionsClient::GetAPISchema(
return base::StringPiece();
}
-void TestExtensionsClient::AddExtraFeatureFilters(
- SimpleFeature* feature) const {
-}
-
bool TestExtensionsClient::ShouldSuppressFatalErrors() const {
return true;
}
diff --git a/extensions/test/test_extensions_client.h b/extensions/test/test_extensions_client.h
index 23b6940..afe9475 100644
--- a/extensions/test/test_extensions_client.h
+++ b/extensions/test/test_extensions_client.h
@@ -20,7 +20,7 @@ class TestExtensionsClient : public ExtensionsClient {
virtual const PermissionsProvider& GetPermissionsProvider() const OVERRIDE;
virtual const PermissionMessageProvider& GetPermissionMessageProvider() const
OVERRIDE;
- virtual FeatureProvider* GetFeatureProviderByName(
+ virtual scoped_ptr<FeatureProvider> CreateFeatureProvider(
const std::string& name) const OVERRIDE;
virtual void FilterHostPermissions(
const URLPatternSet& hosts,
@@ -37,7 +37,6 @@ class TestExtensionsClient : public ExtensionsClient {
virtual bool IsAPISchemaGenerated(const std::string& name) const OVERRIDE;
virtual base::StringPiece GetAPISchema(
const std::string& name) const OVERRIDE;
- virtual void AddExtraFeatureFilters(SimpleFeature* feature) const OVERRIDE;
virtual bool ShouldSuppressFatalErrors() const OVERRIDE;
// A whitelist of extensions that can script anywhere. Do not add to this