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
{
17 TEST(BaseFeatureProviderTest
, ManifestFeatures
) {
18 FeatureProvider
* provider
= BaseFeatureProvider::GetByName("manifest");
19 SimpleFeature
* feature
=
20 static_cast<SimpleFeature
*>(provider
->GetFeature("description"));
22 EXPECT_EQ(6u, feature
->extension_types()->size());
23 EXPECT_EQ(1u, feature
->extension_types()->count(Manifest::TYPE_EXTENSION
));
25 feature
->extension_types()->count(Manifest::TYPE_LEGACY_PACKAGED_APP
));
27 feature
->extension_types()->count(Manifest::TYPE_PLATFORM_APP
));
28 EXPECT_EQ(1u, feature
->extension_types()->count(Manifest::TYPE_HOSTED_APP
));
29 EXPECT_EQ(1u, feature
->extension_types()->count(Manifest::TYPE_THEME
));
31 feature
->extension_types()->count(Manifest::TYPE_SHARED_MODULE
));
33 base::DictionaryValue manifest
;
34 manifest
.SetString("name", "test extension");
35 manifest
.SetString("version", "1");
36 manifest
.SetString("description", "hello there");
39 scoped_refptr
<const Extension
> extension(Extension::Create(
40 base::FilePath(), Manifest::INTERNAL
, manifest
, Extension::NO_FLAGS
,
43 ASSERT_TRUE(extension
.get());
44 EXPECT_EQ(Feature::IS_AVAILABLE
, feature
->IsAvailableToContext(
45 extension
.get(), Feature::UNSPECIFIED_CONTEXT
).result());
48 static_cast<SimpleFeature
*>(provider
->GetFeature("theme"));
50 EXPECT_EQ(Feature::INVALID_TYPE
, feature
->IsAvailableToContext(
51 extension
.get(), Feature::UNSPECIFIED_CONTEXT
).result());
54 static_cast<SimpleFeature
*>(provider
->GetFeature("devtools_page"));
56 EXPECT_EQ(Feature::NOT_PRESENT
, feature
->IsAvailableToContext(
57 extension
.get(), Feature::UNSPECIFIED_CONTEXT
).result());
60 TEST(BaseFeatureProviderTest
, PermissionFeatures
) {
61 FeatureProvider
* provider
= BaseFeatureProvider::GetByName("permission");
62 SimpleFeature
* feature
=
63 static_cast<SimpleFeature
*>(provider
->GetFeature("contextMenus"));
65 EXPECT_EQ(3u, feature
->extension_types()->size());
66 EXPECT_EQ(1u, feature
->extension_types()->count(Manifest::TYPE_EXTENSION
));
68 feature
->extension_types()->count(Manifest::TYPE_LEGACY_PACKAGED_APP
));
70 feature
->extension_types()->count(Manifest::TYPE_PLATFORM_APP
));
72 base::DictionaryValue manifest
;
73 manifest
.SetString("name", "test extension");
74 manifest
.SetString("version", "1");
75 base::ListValue
* permissions
= new base::ListValue();
76 manifest
.Set("permissions", permissions
);
77 permissions
->Append(new base::StringValue("contextMenus"));
80 scoped_refptr
<const Extension
> extension(Extension::Create(
81 base::FilePath(), Manifest::INTERNAL
, manifest
, Extension::NO_FLAGS
,
84 ASSERT_TRUE(extension
.get());
85 EXPECT_EQ(Feature::IS_AVAILABLE
, feature
->IsAvailableToContext(
86 extension
.get(), Feature::UNSPECIFIED_CONTEXT
).result());
89 static_cast<SimpleFeature
*>(provider
->GetFeature("chromePrivate"));
91 EXPECT_EQ(Feature::NOT_FOUND_IN_WHITELIST
, feature
->IsAvailableToContext(
92 extension
.get(), Feature::UNSPECIFIED_CONTEXT
).result());
95 static_cast<SimpleFeature
*>(provider
->GetFeature("clipboardWrite"));
97 EXPECT_EQ(Feature::NOT_PRESENT
, feature
->IsAvailableToContext(
98 extension
.get(), Feature::UNSPECIFIED_CONTEXT
).result());
101 SimpleFeature
* CreatePermissionFeature() {
102 SimpleFeature
* feature
= new PermissionFeature();
104 scoped_ptr
<SimpleFeatureFilter
>(new ChromeChannelFeatureFilter(feature
)));
108 TEST(BaseFeatureProviderTest
, Validation
) {
109 scoped_ptr
<base::DictionaryValue
> value(new base::DictionaryValue());
111 base::DictionaryValue
* feature1
= new base::DictionaryValue();
112 feature1
->SetString("channel", "trunk");
113 value
->Set("feature1", feature1
);
115 base::DictionaryValue
* feature2
= new base::DictionaryValue();
116 feature2
->SetString("channel", "trunk");
117 base::ListValue
* extension_types
= new base::ListValue();
118 extension_types
->Append(new base::StringValue("extension"));
119 feature2
->Set("extension_types", extension_types
);
120 base::ListValue
* contexts
= new base::ListValue();
121 contexts
->Append(new base::StringValue("blessed_extension"));
122 feature2
->Set("contexts", contexts
);
123 value
->Set("feature2", feature2
);
125 scoped_ptr
<BaseFeatureProvider
> provider(
126 new BaseFeatureProvider(*value
, CreatePermissionFeature
));
128 // feature1 won't validate because it lacks an extension type.
129 EXPECT_FALSE(provider
->GetFeature("feature1"));
131 // If we add one, it works.
132 feature1
->Set("extension_types", extension_types
->DeepCopy());
133 provider
.reset(new BaseFeatureProvider(*value
, CreatePermissionFeature
));
134 EXPECT_TRUE(provider
->GetFeature("feature1"));
136 // Remove the channel, and feature1 won't validate.
137 feature1
->Remove("channel", NULL
);
138 provider
.reset(new BaseFeatureProvider(*value
, CreatePermissionFeature
));
139 EXPECT_FALSE(provider
->GetFeature("feature1"));
141 // feature2 won't validate because of the presence of "contexts".
142 EXPECT_FALSE(provider
->GetFeature("feature2"));
144 // If we remove it, it works.
145 feature2
->Remove("contexts", NULL
);
146 provider
.reset(new BaseFeatureProvider(*value
, CreatePermissionFeature
));
147 EXPECT_TRUE(provider
->GetFeature("feature2"));
150 TEST(BaseFeatureProviderTest
, ComplexFeatures
) {
151 scoped_ptr
<base::DictionaryValue
> rule(
153 .Set("feature1", ListBuilder()
154 .Append(DictionaryBuilder()
155 .Set("channel", "beta")
156 .Set("extension_types", ListBuilder()
157 .Append("extension")))
158 .Append(DictionaryBuilder()
159 .Set("channel", "beta")
160 .Set("extension_types", ListBuilder()
161 .Append("legacy_packaged_app"))))
164 scoped_ptr
<BaseFeatureProvider
> provider(
165 new BaseFeatureProvider(*rule
, NULL
));
167 Feature
* feature
= provider
->GetFeature("feature1");
168 EXPECT_TRUE(feature
);
170 // Make sure both rules are applied correctly.
172 ScopedCurrentChannel
current_channel(VersionInfo::CHANNEL_BETA
);
173 EXPECT_EQ(Feature::IS_AVAILABLE
, feature
->IsAvailableToManifest(
175 Manifest::TYPE_EXTENSION
,
176 Feature::UNSPECIFIED_LOCATION
,
177 Feature::UNSPECIFIED_PLATFORM
).result());
178 EXPECT_EQ(Feature::IS_AVAILABLE
, feature
->IsAvailableToManifest(
180 Manifest::TYPE_LEGACY_PACKAGED_APP
,
181 Feature::UNSPECIFIED_LOCATION
,
182 Feature::UNSPECIFIED_PLATFORM
).result());
185 ScopedCurrentChannel
current_channel(VersionInfo::CHANNEL_STABLE
);
186 EXPECT_NE(Feature::IS_AVAILABLE
, feature
->IsAvailableToManifest(
188 Manifest::TYPE_EXTENSION
,
189 Feature::UNSPECIFIED_LOCATION
,
190 Feature::UNSPECIFIED_PLATFORM
).result());
191 EXPECT_NE(Feature::IS_AVAILABLE
, feature
->IsAvailableToManifest(
193 Manifest::TYPE_LEGACY_PACKAGED_APP
,
194 Feature::UNSPECIFIED_LOCATION
,
195 Feature::UNSPECIFIED_PLATFORM
).result());
199 } // namespace extensions