Chromium Code Reviews| Index: extensions/common/features/base_feature_provider_unittest.cc |
| diff --git a/extensions/common/features/base_feature_provider_unittest.cc b/extensions/common/features/base_feature_provider_unittest.cc |
| index 28c8dedad51ae4436930e1482ffe9605e0c13ba2..974ee76f711952858b457450b104e9ef40150752 100644 |
| --- a/extensions/common/features/base_feature_provider_unittest.cc |
| +++ b/extensions/common/features/base_feature_provider_unittest.cc |
| @@ -4,209 +4,135 @@ |
| #include "extensions/common/features/base_feature_provider.h" |
| -#include "chrome/common/extensions/features/chrome_channel_feature_filter.h" |
| -#include "chrome/common/extensions/features/feature_channel.h" |
| -#include "extensions/common/features/permission_feature.h" |
| +#include <set> |
| +#include <string> |
| + |
| +#include "extensions/common/extension_builder.h" |
| +#include "extensions/common/features/feature.h" |
| +#include "extensions/common/features/simple_feature.h" |
| +#include "extensions/common/manifest.h" |
| #include "extensions/common/value_builder.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| -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) { |
| +// Tests that a real manifest feature is available for the correct types of |
| +// extensions and apps. |
| +TEST(BaseFeatureProviderTest, ManifestFeatureTypes) { |
| const FeatureProvider* provider = BaseFeatureProvider::GetByName("manifest"); |
| + // NOTE: This feature cannot have multiple rules, otherwise it is not a |
| + // SimpleFeature. |
| SimpleFeature* feature = |
| static_cast<SimpleFeature*>(provider->GetFeature("description")); |
| ASSERT_TRUE(feature); |
| - EXPECT_EQ(6u, feature->extension_types()->size()); |
| - EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_EXTENSION)); |
| - EXPECT_EQ(1u, |
| - feature->extension_types()->count(Manifest::TYPE_LEGACY_PACKAGED_APP)); |
| - EXPECT_EQ(1u, |
| - feature->extension_types()->count(Manifest::TYPE_PLATFORM_APP)); |
| - EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_HOSTED_APP)); |
| - EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_THEME)); |
| - EXPECT_EQ(1u, |
| - feature->extension_types()->count(Manifest::TYPE_SHARED_MODULE)); |
| - |
| - base::DictionaryValue manifest; |
| - manifest.SetString("name", "test extension"); |
| - manifest.SetString("version", "1"); |
| - manifest.SetString("description", "hello there"); |
| - |
| - std::string error; |
| - scoped_refptr<const Extension> extension(Extension::Create( |
| - base::FilePath(), Manifest::INTERNAL, manifest, Extension::NO_FLAGS, |
| - &error)); |
| + std::set<Manifest::Type>* extension_types = feature->extension_types(); |
| + EXPECT_EQ(6u, extension_types->size()); |
| + EXPECT_EQ(1u, extension_types->count(Manifest::TYPE_EXTENSION)); |
| + EXPECT_EQ(1u, extension_types->count(Manifest::TYPE_LEGACY_PACKAGED_APP)); |
| + EXPECT_EQ(1u, extension_types->count(Manifest::TYPE_PLATFORM_APP)); |
| + EXPECT_EQ(1u, extension_types->count(Manifest::TYPE_HOSTED_APP)); |
| + EXPECT_EQ(1u, extension_types->count(Manifest::TYPE_THEME)); |
| + EXPECT_EQ(1u, extension_types->count(Manifest::TYPE_SHARED_MODULE)); |
| +} |
| + |
| +// Tests that real manifest features have the correct availability for an |
| +// extension. |
| +TEST(BaseFeatureProviderTest, ManifestFeatureAvailability) { |
|
James Cook
2014/09/11 23:32:31
The important changes here are switching to descri
|
| + const FeatureProvider* provider = BaseFeatureProvider::GetByName("manifest"); |
| + scoped_refptr<const Extension> extension = |
| + ExtensionBuilder() |
| + .SetManifest(DictionaryBuilder() |
| + .Set("name", "test extension") |
| + .Set("version", "1") |
| + .Set("description", "hello there")) |
| + .Build(); |
| ASSERT_TRUE(extension.get()); |
| - EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToContext( |
| - extension.get(), Feature::UNSPECIFIED_CONTEXT).result()); |
| - feature = |
| - static_cast<SimpleFeature*>(provider->GetFeature("theme")); |
| + Feature* feature = provider->GetFeature("description"); |
| + EXPECT_EQ(Feature::IS_AVAILABLE, |
| + feature->IsAvailableToContext(extension.get(), |
| + Feature::UNSPECIFIED_CONTEXT, |
| + GURL()).result()); |
| + |
| + // This is a generic extension, so an app-only feature isn't allowed. |
| + feature = provider->GetFeature("app.background"); |
| ASSERT_TRUE(feature); |
| - EXPECT_EQ(Feature::INVALID_TYPE, feature->IsAvailableToContext( |
| - extension.get(), Feature::UNSPECIFIED_CONTEXT).result()); |
| + EXPECT_EQ(Feature::INVALID_TYPE, |
| + feature->IsAvailableToContext(extension.get(), |
| + Feature::UNSPECIFIED_CONTEXT, |
| + GURL()).result()); |
| - feature = |
| - static_cast<SimpleFeature*>(provider->GetFeature("devtools_page")); |
| + // A feature not listed in the manifest isn't allowed. |
| + feature = provider->GetFeature("background"); |
| ASSERT_TRUE(feature); |
| - EXPECT_EQ(Feature::NOT_PRESENT, feature->IsAvailableToContext( |
| - extension.get(), Feature::UNSPECIFIED_CONTEXT).result()); |
| + EXPECT_EQ(Feature::NOT_PRESENT, |
| + feature->IsAvailableToContext(extension.get(), |
| + Feature::UNSPECIFIED_CONTEXT, |
| + GURL()).result()); |
| } |
| -TEST(BaseFeatureProviderTest, PermissionFeatures) { |
| +// Tests that a real permission feature is available for the correct types of |
| +// extensions and apps. |
| +TEST(BaseFeatureProviderTest, PermissionFeatureTypes) { |
| const FeatureProvider* provider = |
| BaseFeatureProvider::GetByName("permission"); |
| + // NOTE: This feature cannot have multiple rules, otherwise it is not a |
| + // SimpleFeature. |
| SimpleFeature* feature = |
| - static_cast<SimpleFeature*>(provider->GetFeature("contextMenus")); |
| + static_cast<SimpleFeature*>(provider->GetFeature("power")); |
| ASSERT_TRUE(feature); |
| - EXPECT_EQ(3u, feature->extension_types()->size()); |
| - EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_EXTENSION)); |
| - EXPECT_EQ(1u, |
| - feature->extension_types()->count(Manifest::TYPE_LEGACY_PACKAGED_APP)); |
| - EXPECT_EQ(1u, |
| - feature->extension_types()->count(Manifest::TYPE_PLATFORM_APP)); |
| - |
| - base::DictionaryValue manifest; |
| - manifest.SetString("name", "test extension"); |
| - manifest.SetString("version", "1"); |
| - base::ListValue* permissions = new base::ListValue(); |
| - manifest.Set("permissions", permissions); |
| - permissions->Append(new base::StringValue("contextMenus")); |
| - |
| - std::string error; |
| - scoped_refptr<const Extension> extension(Extension::Create( |
| - base::FilePath(), Manifest::INTERNAL, manifest, Extension::NO_FLAGS, |
| - &error)); |
| + std::set<Manifest::Type>* extension_types = feature->extension_types(); |
| + EXPECT_EQ(3u, extension_types->size()); |
| + EXPECT_EQ(1u, extension_types->count(Manifest::TYPE_EXTENSION)); |
| + EXPECT_EQ(1u, extension_types->count(Manifest::TYPE_LEGACY_PACKAGED_APP)); |
| + EXPECT_EQ(1u, extension_types->count(Manifest::TYPE_PLATFORM_APP)); |
| +} |
| - ASSERT_TRUE(extension.get()); |
| - EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToContext( |
| - extension.get(), Feature::UNSPECIFIED_CONTEXT).result()); |
| +// Tests that real permission features have the correct availability for an app. |
| +TEST(BaseFeatureProviderTest, PermissionFeatureAvailability) { |
|
James Cook
2014/09/11 23:32:31
Same thing here:
* SimpleFeature -> Feature
* cont
|
| + const FeatureProvider* provider = |
| + BaseFeatureProvider::GetByName("permission"); |
| - feature = |
| - static_cast<SimpleFeature*>(provider->GetFeature("chromePrivate")); |
| + scoped_refptr<const Extension> app = |
| + ExtensionBuilder() |
| + .SetManifest(DictionaryBuilder() |
| + .Set("name", "test app") |
| + .Set("version", "1") |
| + .Set("app", |
| + DictionaryBuilder().Set( |
| + "background", |
| + DictionaryBuilder().Set( |
| + "scripts", |
| + ListBuilder().Append("background.js")))) |
| + .Set("permissions", ListBuilder().Append("power"))) |
| + .Build(); |
| + ASSERT_TRUE(app.get()); |
| + ASSERT_TRUE(app->is_platform_app()); |
| + |
| + // A permission requested in the manifest is available. |
| + Feature* feature = provider->GetFeature("power"); |
| + EXPECT_EQ( |
| + Feature::IS_AVAILABLE, |
| + feature->IsAvailableToContext( |
| + app.get(), Feature::UNSPECIFIED_CONTEXT, GURL()).result()); |
| + |
| + // A permission only available to whitelisted extensions returns availability |
| + // NOT_FOUND_IN_WHITELIST. |
| + feature = provider->GetFeature("bluetoothPrivate"); |
| ASSERT_TRUE(feature); |
| - EXPECT_EQ(Feature::NOT_FOUND_IN_WHITELIST, feature->IsAvailableToContext( |
| - extension.get(), Feature::UNSPECIFIED_CONTEXT).result()); |
| + EXPECT_EQ( |
| + Feature::NOT_FOUND_IN_WHITELIST, |
| + feature->IsAvailableToContext( |
| + app.get(), Feature::UNSPECIFIED_CONTEXT, GURL()).result()); |
| - feature = |
| - static_cast<SimpleFeature*>(provider->GetFeature("clipboardWrite")); |
| + // A permission that isn't part of the manifest returns NOT_PRESENT. |
| + feature = provider->GetFeature("serial"); |
| ASSERT_TRUE(feature); |
| - EXPECT_EQ(Feature::NOT_PRESENT, feature->IsAvailableToContext( |
| - extension.get(), Feature::UNSPECIFIED_CONTEXT).result()); |
| -} |
| - |
| -TEST(BaseFeatureProviderTest, Validation) { |
| - scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); |
| - |
| - base::DictionaryValue* feature1 = new base::DictionaryValue(); |
| - feature1->SetString("channel", "trunk"); |
| - value->Set("feature1", feature1); |
| - |
| - base::DictionaryValue* feature2 = new base::DictionaryValue(); |
| - feature2->SetString("channel", "trunk"); |
| - base::ListValue* extension_types = new base::ListValue(); |
| - extension_types->Append(new base::StringValue("extension")); |
| - feature2->Set("extension_types", extension_types); |
| - base::ListValue* contexts = new base::ListValue(); |
| - contexts->Append(new base::StringValue("blessed_extension")); |
| - feature2->Set("contexts", contexts); |
| - value->Set("feature2", feature2); |
| - |
| - scoped_ptr<BaseFeatureProvider> provider( |
| - 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, CreateFeature<PermissionFeature>)); |
| - EXPECT_TRUE(provider->GetFeature("feature1")); |
| - |
| - // Remove the channel, and feature1 won't validate. |
| - feature1->Remove("channel", NULL); |
| - provider.reset( |
| - new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>)); |
| - EXPECT_FALSE(provider->GetFeature("feature1")); |
| - |
| - // feature2 won't validate because of the presence of "contexts". |
| - EXPECT_FALSE(provider->GetFeature("feature2")); |
| - |
| - // If we remove it, it works. |
| - feature2->Remove("contexts", NULL); |
| - provider.reset( |
| - new BaseFeatureProvider(*value, CreateFeature<PermissionFeature>)); |
| - EXPECT_TRUE(provider->GetFeature("feature2")); |
| -} |
| - |
| -TEST(BaseFeatureProviderTest, ComplexFeatures) { |
| - scoped_ptr<base::DictionaryValue> rule( |
| - DictionaryBuilder() |
| - .Set("feature1", ListBuilder() |
| - .Append(DictionaryBuilder() |
| - .Set("channel", "beta") |
| - .Set("extension_types", ListBuilder() |
| - .Append("extension"))) |
| - .Append(DictionaryBuilder() |
| - .Set("channel", "beta") |
| - .Set("extension_types", ListBuilder() |
| - .Append("legacy_packaged_app")))) |
| - .Build()); |
| - |
| - scoped_ptr<BaseFeatureProvider> provider( |
| - new BaseFeatureProvider(*rule, CreateFeature<SimpleFeature>)); |
| - |
| - Feature* feature = provider->GetFeature("feature1"); |
| - EXPECT_TRUE(feature); |
| - |
| - // Make sure both rules are applied correctly. |
| - { |
| - ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA); |
| - EXPECT_EQ( |
| - Feature::IS_AVAILABLE, |
| - feature->IsAvailableToManifest("1", |
| - Manifest::TYPE_EXTENSION, |
| - Manifest::INVALID_LOCATION, |
| - Feature::UNSPECIFIED_PLATFORM).result()); |
| - EXPECT_EQ( |
| - Feature::IS_AVAILABLE, |
| - feature->IsAvailableToManifest("2", |
| - Manifest::TYPE_LEGACY_PACKAGED_APP, |
| - Manifest::INVALID_LOCATION, |
| - Feature::UNSPECIFIED_PLATFORM).result()); |
| - } |
| - { |
| - ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_STABLE); |
| - EXPECT_NE( |
| - Feature::IS_AVAILABLE, |
| - feature->IsAvailableToManifest("1", |
| - Manifest::TYPE_EXTENSION, |
| - Manifest::INVALID_LOCATION, |
| - Feature::UNSPECIFIED_PLATFORM).result()); |
| - EXPECT_NE( |
| - Feature::IS_AVAILABLE, |
| - feature->IsAvailableToManifest("2", |
| - Manifest::TYPE_LEGACY_PACKAGED_APP, |
| - Manifest::INVALID_LOCATION, |
| - Feature::UNSPECIFIED_PLATFORM).result()); |
| - } |
| + EXPECT_EQ( |
| + Feature::NOT_PRESENT, |
| + feature->IsAvailableToContext( |
| + app.get(), Feature::UNSPECIFIED_CONTEXT, GURL()).result()); |
| } |
| } // namespace extensions |