Home | History | Annotate | Download | only in features
      1 // Copyright (c) 2012 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.
      4 
      5 #include "chrome/common/extensions/features/base_feature_provider.h"
      6 
      7 #include "chrome/common/extensions/features/feature_channel.h"
      8 #include "chrome/common/extensions/features/permission_feature.h"
      9 #include "chrome/common/extensions/value_builder.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 
     12 using chrome::VersionInfo;
     13 
     14 namespace extensions {
     15 
     16 TEST(BaseFeatureProviderTest, ManifestFeatures) {
     17   FeatureProvider* provider = BaseFeatureProvider::GetByName("manifest");
     18   SimpleFeature* feature =
     19       static_cast<SimpleFeature*>(provider->GetFeature("description"));
     20   ASSERT_TRUE(feature);
     21   EXPECT_EQ(6u, feature->extension_types()->size());
     22   EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_EXTENSION));
     23   EXPECT_EQ(1u,
     24       feature->extension_types()->count(Manifest::TYPE_LEGACY_PACKAGED_APP));
     25   EXPECT_EQ(1u,
     26             feature->extension_types()->count(Manifest::TYPE_PLATFORM_APP));
     27   EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_HOSTED_APP));
     28   EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_THEME));
     29   EXPECT_EQ(1u,
     30             feature->extension_types()->count(Manifest::TYPE_SHARED_MODULE));
     31 
     32   base::DictionaryValue manifest;
     33   manifest.SetString("name", "test extension");
     34   manifest.SetString("version", "1");
     35   manifest.SetString("description", "hello there");
     36 
     37   std::string error;
     38   scoped_refptr<const Extension> extension(Extension::Create(
     39       base::FilePath(), Manifest::INTERNAL, manifest, Extension::NO_FLAGS,
     40       &error));
     41 
     42   ASSERT_TRUE(extension.get());
     43   EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToContext(
     44       extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
     45 
     46   feature =
     47     static_cast<SimpleFeature*>(provider->GetFeature("theme"));
     48   ASSERT_TRUE(feature);
     49   EXPECT_EQ(Feature::INVALID_TYPE, feature->IsAvailableToContext(
     50       extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
     51 
     52   feature =
     53     static_cast<SimpleFeature*>(provider->GetFeature("devtools_page"));
     54   ASSERT_TRUE(feature);
     55   EXPECT_EQ(Feature::NOT_PRESENT, feature->IsAvailableToContext(
     56       extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
     57 }
     58 
     59 TEST(BaseFeatureProviderTest, PermissionFeatures) {
     60   FeatureProvider* provider = BaseFeatureProvider::GetByName("permission");
     61   SimpleFeature* feature =
     62       static_cast<SimpleFeature*>(provider->GetFeature("contextMenus"));
     63   ASSERT_TRUE(feature);
     64   EXPECT_EQ(3u, feature->extension_types()->size());
     65   EXPECT_EQ(1u, feature->extension_types()->count(Manifest::TYPE_EXTENSION));
     66   EXPECT_EQ(1u,
     67       feature->extension_types()->count(Manifest::TYPE_LEGACY_PACKAGED_APP));
     68   EXPECT_EQ(1u,
     69             feature->extension_types()->count(Manifest::TYPE_PLATFORM_APP));
     70 
     71   base::DictionaryValue manifest;
     72   manifest.SetString("name", "test extension");
     73   manifest.SetString("version", "1");
     74   base::ListValue* permissions = new base::ListValue();
     75   manifest.Set("permissions", permissions);
     76   permissions->Append(new base::StringValue("contextMenus"));
     77 
     78   std::string error;
     79   scoped_refptr<const Extension> extension(Extension::Create(
     80       base::FilePath(), Manifest::INTERNAL, manifest, Extension::NO_FLAGS,
     81       &error));
     82 
     83   ASSERT_TRUE(extension.get());
     84   EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToContext(
     85       extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
     86 
     87   feature =
     88     static_cast<SimpleFeature*>(provider->GetFeature("chromePrivate"));
     89   ASSERT_TRUE(feature);
     90   EXPECT_EQ(Feature::NOT_FOUND_IN_WHITELIST, feature->IsAvailableToContext(
     91       extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
     92 
     93   feature =
     94     static_cast<SimpleFeature*>(provider->GetFeature("clipboardWrite"));
     95   ASSERT_TRUE(feature);
     96   EXPECT_EQ(Feature::NOT_PRESENT, feature->IsAvailableToContext(
     97       extension.get(), Feature::UNSPECIFIED_CONTEXT).result());
     98 }
     99 
    100 SimpleFeature* CreatePermissionFeature() {
    101   return new PermissionFeature();
    102 }
    103 
    104 TEST(BaseFeatureProviderTest, Validation) {
    105   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
    106 
    107   base::DictionaryValue* feature1 = new base::DictionaryValue();
    108   feature1->SetString("channel", "trunk");
    109   value->Set("feature1", feature1);
    110 
    111   base::DictionaryValue* feature2 = new base::DictionaryValue();
    112   feature2->SetString("channel", "trunk");
    113   base::ListValue* extension_types = new base::ListValue();
    114   extension_types->Append(new base::StringValue("extension"));
    115   feature2->Set("extension_types", extension_types);
    116   base::ListValue* contexts = new base::ListValue();
    117   contexts->Append(new base::StringValue("blessed_extension"));
    118   feature2->Set("contexts", contexts);
    119   value->Set("feature2", feature2);
    120 
    121   scoped_ptr<BaseFeatureProvider> provider(
    122       new BaseFeatureProvider(*value, CreatePermissionFeature));
    123 
    124   // feature1 won't validate because it lacks an extension type.
    125   EXPECT_FALSE(provider->GetFeature("feature1"));
    126 
    127   // If we add one, it works.
    128   feature1->Set("extension_types", extension_types->DeepCopy());
    129   provider.reset(new BaseFeatureProvider(*value, CreatePermissionFeature));
    130   EXPECT_TRUE(provider->GetFeature("feature1"));
    131 
    132   // Remove the channel, and feature1 won't validate.
    133   feature1->Remove("channel", NULL);
    134   provider.reset(new BaseFeatureProvider(*value, CreatePermissionFeature));
    135   EXPECT_FALSE(provider->GetFeature("feature1"));
    136 
    137   // feature2 won't validate because of the presence of "contexts".
    138   EXPECT_FALSE(provider->GetFeature("feature2"));
    139 
    140   // If we remove it, it works.
    141   feature2->Remove("contexts", NULL);
    142   provider.reset(new BaseFeatureProvider(*value, CreatePermissionFeature));
    143   EXPECT_TRUE(provider->GetFeature("feature2"));
    144 }
    145 
    146 TEST(BaseFeatureProviderTest, ComplexFeatures) {
    147   scoped_ptr<base::DictionaryValue> rule(
    148       DictionaryBuilder()
    149       .Set("feature1",
    150            ListBuilder().Append(DictionaryBuilder()
    151                                 .Set("channel", "beta")
    152                                 .Set("extension_types",
    153                                      ListBuilder().Append("extension")))
    154                         .Append(DictionaryBuilder()
    155                                 .Set("channel", "beta")
    156                                 .Set("extension_types",
    157                                      ListBuilder().Append("packaged_app"))))
    158       .Build());
    159 
    160   scoped_ptr<BaseFeatureProvider> provider(
    161       new BaseFeatureProvider(*rule, NULL));
    162 
    163   Feature* feature = provider->GetFeature("feature1");
    164   EXPECT_TRUE(feature);
    165 
    166   // Make sure both rules are applied correctly.
    167   {
    168     ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_BETA);
    169     EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
    170         "1",
    171         Manifest::TYPE_EXTENSION,
    172         Feature::UNSPECIFIED_LOCATION,
    173         Feature::UNSPECIFIED_PLATFORM).result());
    174     EXPECT_EQ(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
    175         "2",
    176         Manifest::TYPE_LEGACY_PACKAGED_APP,
    177         Feature::UNSPECIFIED_LOCATION,
    178         Feature::UNSPECIFIED_PLATFORM).result());
    179   }
    180   {
    181     ScopedCurrentChannel current_channel(VersionInfo::CHANNEL_STABLE);
    182     EXPECT_NE(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
    183         "1",
    184         Manifest::TYPE_EXTENSION,
    185         Feature::UNSPECIFIED_LOCATION,
    186         Feature::UNSPECIFIED_PLATFORM).result());
    187     EXPECT_NE(Feature::IS_AVAILABLE, feature->IsAvailableToManifest(
    188         "2",
    189         Manifest::TYPE_LEGACY_PACKAGED_APP,
    190         Feature::UNSPECIFIED_LOCATION,
    191         Feature::UNSPECIFIED_PLATFORM).result());
    192   }
    193 }
    194 
    195 }  // namespace extensions
    196