1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/common/features/base_feature_provider.h"
7 #include "chrome/common/extensions/features/chrome_channel_feature_filter.h"
8 #include "chrome/common/extensions/features/feature_channel.h"
9 #include "extensions/common/features/permission_feature.h"
10 #include "extensions/common/value_builder.h"
11 #include "testing/gtest/include/gtest/gtest.h"
13 using chrome::VersionInfo;
15 namespace extensions {
19 template <class FeatureClass>
20 SimpleFeature* CreateFeature() {
21 SimpleFeature* feature = new FeatureClass();
23 scoped_ptr<SimpleFeatureFilter>(new ChromeChannelFeatureFilter(feature)));
29 TEST(BaseFeatureProviderTest, ManifestFeatures) {
30 FeatureProvider* provider = BaseFeatureProvider::GetByName("manifest");
31 SimpleFeature* feature =
32 static_cast<SimpleFeature*>(provider->GetFeature("description"));
34 EXPECT_EQ(6u, feature->extension_types()->size());
35 EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_EXTENSION));
37 feature->extension_types()->count(Manifest::TYPE_LEGACY_PACKAGED_APP));
39 feature->extension_types()->count(Manifest::TYPE_PLATFORM_APP));
40 EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_HOSTED_APP));
41 EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_THEME));
43 feature->extension_types()->count(Manifest::TYPE_SHARED_MODULE));
45 base::DictionaryValue manifest;
46 manifest.SetString("name", "test extension");
47 manifest.SetString("version", "1");
48 manifest.SetString("description", "hello there");
51 scoped_refptr<const Extension> extension(Extension::Create(
52 base::FilePath(), Manifest::INTERNAL, manifest, Extension::NO_FLAGS,
55 ASSERT_TRUE(extension.get());
56 EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToContext(
57 extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
60 static_cast<SimpleFeature*>(provider->GetFeature("theme"));
62 EXPECT_EQ(Feature::INVALID_TYPE, feature->IsAvailableToContext(
63 extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
66 static_cast<SimpleFeature*>(provider->GetFeature("devtools_page"));
68 EXPECT_EQ(Feature::NOT_PRESENT, feature->IsAvailableToContext(
69 extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
72 TEST(BaseFeatureProviderTest, PermissionFeatures) {
73 FeatureProvider* provider = BaseFeatureProvider::GetByName("permission");
74 SimpleFeature* feature =
75 static_cast<SimpleFeature*>(provider->GetFeature("contextMenus"));
77 EXPECT_EQ(3u, feature->extension_types()->size());
78 EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_EXTENSION));
80 feature->extension_types()->count(Manifest::TYPE_LEGACY_PACKAGED_APP));
82 feature->extension_types()->count(Manifest::TYPE_PLATFORM_APP));
84 base::DictionaryValue manifest;
85 manifest.SetString("name", "test extension");
86 manifest.SetString("version", "1");
87 base::ListValue* permissions = new base::ListValue();
88 manifest.Set("permissions", permissions);
89 permissions->Append(new base::StringValue("contextMenus"));
92 scoped_refptr<const Extension> extension(Extension::Create(
93 base::FilePath(), Manifest::INTERNAL, manifest, Extension::NO_FLAGS,
96 ASSERT_TRUE(extension.get());
97 EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToContext(
98 extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
101 static_cast<SimpleFeature*>(provider->GetFeature("chromePrivate"));
102 ASSERT_TRUE(feature);
103 EXPECT_EQ(Feature::NOT_FOUND_IN_WHITELIST, feature->IsAvailableToContext(
104 extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
107 static_cast<SimpleFeature*>(provider->GetFeature("clipboardWrite"));
108 ASSERT_TRUE(feature);
109 EXPECT_EQ(Feature::NOT_PRESENT, feature->IsAvailableToContext(
110 extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
113 TEST(BaseFeatureProviderTest, Validation) {
114 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
116 base::DictionaryValue* feature1 = new base::DictionaryValue();
117 feature1->SetString("channel", "trunk");
118 value->Set("feature1", feature1);
120 base::DictionaryValue* feature2 = new base::DictionaryValue();
121 feature2->SetString("channel", "trunk");
122 base::ListValue* extension_types = new base::ListValue();
123 extension_types->Append(new base::StringValue("extension"));
124 feature2->Set("extension_types", extension_types);
125 base::ListValue* contexts = new base::ListValue();
126 contexts->Append(new base::StringValue("blessed_extension"));
127 feature2->Set("contexts", contexts);
128 value->Set("feature2", feature2);
130 scoped_ptr<BaseFeatureProvider> provider(
131 new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>));
133 // feature1 won't validate because it lacks an extension type.
134 EXPECT_FALSE(provider->GetFeature("feature1"));
136 // If we add one, it works.
137 feature1->Set("extension_types", extension_types->DeepCopy());
139 new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>));
140 EXPECT_TRUE(provider->GetFeature("feature1"));
142 // Remove the channel, and feature1 won't validate.
143 feature1->Remove("channel", NULL);
145 new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>));
146 EXPECT_FALSE(provider->GetFeature("feature1"));
148 // feature2 won't validate because of the presence of "contexts".
149 EXPECT_FALSE(provider->GetFeature("feature2"));
151 // If we remove it, it works.
152 feature2->Remove("contexts", NULL);
154 new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>));
155 EXPECT_TRUE(provider->GetFeature("feature2"));
158 TEST(BaseFeatureProviderTest, ComplexFeatures) {
159 scoped_ptr<base::DictionaryValue> rule(
161 .Set("feature1", ListBuilder()
162 .Append(DictionaryBuilder()
163 .Set("channel", "beta")
164 .Set("extension_types", ListBuilder()
165 .Append("extension")))
166 .Append(DictionaryBuilder()
167 .Set("channel", "beta")
168 .Set("extension_types", ListBuilder()
169 .Append("legacy_packaged_app"))))
172 scoped_ptr<BaseFeatureProvider> provider(
173 new BaseFeatureProvider(*rule, CreateFeature<SimpleFeature>));
175 Feature* feature = provider->GetFeature("feature1");
176 EXPECT_TRUE(feature);
178 // Make sure both rules are applied correctly.
180 ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
182 Feature::IS_AVAILABLE,
183 feature->IsAvailableToManifest("1",
184 Manifest::TYPE_EXTENSION,
185 Manifest::INVALID_LOCATION,
186 Feature::UNSPECIFIED_PLATFORM).result());
188 Feature::IS_AVAILABLE,
189 feature->IsAvailableToManifest("2",
190 Manifest::TYPE_LEGACY_PACKAGED_APP,
191 Manifest::INVALID_LOCATION,
192 Feature::UNSPECIFIED_PLATFORM).result());
195 ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_STABLE);
197 Feature::IS_AVAILABLE,
198 feature->IsAvailableToManifest("1",
199 Manifest::TYPE_EXTENSION,
200 Manifest::INVALID_LOCATION,
201 Feature::UNSPECIFIED_PLATFORM).result());
203 Feature::IS_AVAILABLE,
204 feature->IsAvailableToManifest("2",
205 Manifest::TYPE_LEGACY_PACKAGED_APP,
206 Manifest::INVALID_LOCATION,
207 Feature::UNSPECIFIED_PLATFORM).result());
211 } // namespace extensions