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/simple_feature.h"
      6 
      7 #include "chrome/common/extensions/features/feature_channel.h"
      8 #include "extensions/common/value_builder.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 
     11 using chrome::VersionInfo;
     12 using extensions::DictionaryBuilder;
     13 using extensions::Extension;
     14 using extensions::Feature;
     15 using extensions::ListBuilder;
     16 using extensions::Manifest;
     17 using extensions::ScopedCurrentChannel;
     18 using extensions::SimpleFeature;
     19 
     20 namespace {
     21 
     22 struct IsAvailableTestData {
     23   std::string extension_id;
     24   Manifest::Type extension_type;
     25   Feature::Location location;
     26   Feature::Platform platform;
     27   int manifest_version;
     28   Feature::AvailabilityResult expected_result;
     29 };
     30 
     31 class ExtensionSimpleFeatureTest : public testing::Test {
     32  protected:
     33   ExtensionSimpleFeatureTest()
     34       : current_channel_(VersionInfo::CHANNEL_UNKNOWN) {}
     35   virtual ~ExtensionSimpleFeatureTest() {}
     36 
     37  private:
     38   ScopedCurrentChannel current_channel_;
     39 };
     40 
     41 TEST_F(ExtensionSimpleFeatureTest, IsAvailableNullCase) {
     42   const IsAvailableTestData tests[] = {
     43     { "", Manifest::TYPE_UNKNOWN,
     44       Feature::UNSPECIFIED_LOCATION, Feature::UNSPECIFIED_PLATFORM, -1,
     45       Feature::IS_AVAILABLE },
     46     { "random-extension", Manifest::TYPE_UNKNOWN,
     47       Feature::UNSPECIFIED_LOCATION, Feature::UNSPECIFIED_PLATFORM, -1,
     48       Feature::IS_AVAILABLE },
     49     { "", Manifest::TYPE_LEGACY_PACKAGED_APP,
     50       Feature::UNSPECIFIED_LOCATION, Feature::UNSPECIFIED_PLATFORM, -1,
     51       Feature::IS_AVAILABLE },
     52     { "", Manifest::TYPE_UNKNOWN,
     53       Feature::UNSPECIFIED_LOCATION, Feature::UNSPECIFIED_PLATFORM, -1,
     54       Feature::IS_AVAILABLE },
     55     { "", Manifest::TYPE_UNKNOWN,
     56       Feature::COMPONENT_LOCATION, Feature::UNSPECIFIED_PLATFORM, -1,
     57       Feature::IS_AVAILABLE },
     58     { "", Manifest::TYPE_UNKNOWN,
     59       Feature::UNSPECIFIED_LOCATION, Feature::CHROMEOS_PLATFORM, -1,
     60       Feature::IS_AVAILABLE },
     61     { "", Manifest::TYPE_UNKNOWN,
     62       Feature::UNSPECIFIED_LOCATION, Feature::UNSPECIFIED_PLATFORM, 25,
     63       Feature::IS_AVAILABLE }
     64   };
     65 
     66   SimpleFeature feature;
     67   for (size_t i = 0; i < arraysize(tests); ++i) {
     68     const IsAvailableTestData& test = tests[i];
     69     EXPECT_EQ(test.expected_result,
     70               feature.IsAvailableToManifest(test.extension_id,
     71                                             test.extension_type,
     72                                             test.location,
     73                                             test.manifest_version,
     74                                             test.platform).result());
     75   }
     76 }
     77 
     78 TEST_F(ExtensionSimpleFeatureTest, Whitelist) {
     79   const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh");
     80   const std::string kIdBar("barabbbbccccddddeeeeffffgggghhhh");
     81   const std::string kIdBaz("bazabbbbccccddddeeeeffffgggghhhh");
     82   SimpleFeature feature;
     83   feature.whitelist()->insert(kIdFoo);
     84   feature.whitelist()->insert(kIdBar);
     85 
     86   EXPECT_EQ(Feature::IS_AVAILABLE, feature.IsAvailableToManifest(
     87       kIdFoo, Manifest::TYPE_UNKNOWN, Feature::UNSPECIFIED_LOCATION, -1,
     88       Feature::UNSPECIFIED_PLATFORM).result());
     89   EXPECT_EQ(Feature::IS_AVAILABLE, feature.IsAvailableToManifest(
     90       kIdBar, Manifest::TYPE_UNKNOWN, Feature::UNSPECIFIED_LOCATION, -1,
     91       Feature::UNSPECIFIED_PLATFORM).result());
     92 
     93   EXPECT_EQ(Feature::NOT_FOUND_IN_WHITELIST, feature.IsAvailableToManifest(
     94       kIdBaz, Manifest::TYPE_UNKNOWN, Feature::UNSPECIFIED_LOCATION, -1,
     95       Feature::UNSPECIFIED_PLATFORM).result());
     96   EXPECT_EQ(
     97       Feature::NOT_FOUND_IN_WHITELIST,
     98       feature.IsAvailableToManifest(std::string(),
     99                                     Manifest::TYPE_UNKNOWN,
    100                                     Feature::UNSPECIFIED_LOCATION,
    101                                     -1,
    102                                     Feature::UNSPECIFIED_PLATFORM).result());
    103 
    104   feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP);
    105   EXPECT_EQ(Feature::NOT_FOUND_IN_WHITELIST, feature.IsAvailableToManifest(
    106       kIdBaz, Manifest::TYPE_LEGACY_PACKAGED_APP,
    107       Feature::UNSPECIFIED_LOCATION, -1,
    108       Feature::UNSPECIFIED_PLATFORM).result());
    109 }
    110 
    111 TEST_F(ExtensionSimpleFeatureTest, HashedIdWhitelist) {
    112   // echo -n "fooabbbbccccddddeeeeffffgggghhhh" |
    113   //   sha1sum | tr '[:lower:]' '[:upper:]'
    114   const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh");
    115   const std::string kIdFooHashed("55BC7228A0D502A2A48C9BB16B07062A01E62897");
    116   SimpleFeature feature;
    117 
    118   feature.whitelist()->insert(kIdFooHashed);
    119 
    120   EXPECT_EQ(Feature::IS_AVAILABLE, feature.IsAvailableToManifest(
    121       kIdFoo, Manifest::TYPE_UNKNOWN, Feature::UNSPECIFIED_LOCATION, -1,
    122       Feature::UNSPECIFIED_PLATFORM).result());
    123   EXPECT_NE(Feature::IS_AVAILABLE, feature.IsAvailableToManifest(
    124       kIdFooHashed, Manifest::TYPE_UNKNOWN,
    125       Feature::UNSPECIFIED_LOCATION, -1,
    126       Feature::UNSPECIFIED_PLATFORM).result());
    127   EXPECT_EQ(Feature::NOT_FOUND_IN_WHITELIST, feature.IsAvailableToManifest(
    128       "slightlytoooolongforanextensionid", Manifest::TYPE_UNKNOWN,
    129       Feature::UNSPECIFIED_LOCATION, -1,
    130       Feature::UNSPECIFIED_PLATFORM).result());
    131   EXPECT_EQ(Feature::NOT_FOUND_IN_WHITELIST, feature.IsAvailableToManifest(
    132       "tooshortforanextensionid", Manifest::TYPE_UNKNOWN,
    133       Feature::UNSPECIFIED_LOCATION, -1,
    134       Feature::UNSPECIFIED_PLATFORM).result());
    135 }
    136 
    137 TEST_F(ExtensionSimpleFeatureTest, PackageType) {
    138   SimpleFeature feature;
    139   feature.extension_types()->insert(Manifest::TYPE_EXTENSION);
    140   feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP);
    141 
    142   EXPECT_EQ(
    143       Feature::IS_AVAILABLE,
    144       feature.IsAvailableToManifest(std::string(),
    145                                     Manifest::TYPE_EXTENSION,
    146                                     Feature::UNSPECIFIED_LOCATION,
    147                                     -1,
    148                                     Feature::UNSPECIFIED_PLATFORM).result());
    149   EXPECT_EQ(
    150       Feature::IS_AVAILABLE,
    151       feature.IsAvailableToManifest(std::string(),
    152                                     Manifest::TYPE_LEGACY_PACKAGED_APP,
    153                                     Feature::UNSPECIFIED_LOCATION,
    154                                     -1,
    155                                     Feature::UNSPECIFIED_PLATFORM).result());
    156 
    157   EXPECT_EQ(
    158       Feature::INVALID_TYPE,
    159       feature.IsAvailableToManifest(std::string(),
    160                                     Manifest::TYPE_UNKNOWN,
    161                                     Feature::UNSPECIFIED_LOCATION,
    162                                     -1,
    163                                     Feature::UNSPECIFIED_PLATFORM).result());
    164   EXPECT_EQ(
    165       Feature::INVALID_TYPE,
    166       feature.IsAvailableToManifest(std::string(),
    167                                     Manifest::TYPE_THEME,
    168                                     Feature::UNSPECIFIED_LOCATION,
    169                                     -1,
    170                                     Feature::UNSPECIFIED_PLATFORM).result());
    171 }
    172 
    173 TEST_F(ExtensionSimpleFeatureTest, Context) {
    174   SimpleFeature feature;
    175   feature.set_name("somefeature");
    176   feature.GetContexts()->insert(Feature::BLESSED_EXTENSION_CONTEXT);
    177   feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP);
    178   feature.platforms()->insert(Feature::CHROMEOS_PLATFORM);
    179   feature.set_min_manifest_version(21);
    180   feature.set_max_manifest_version(25);
    181 
    182   base::DictionaryValue manifest;
    183   manifest.SetString("name", "test");
    184   manifest.SetString("version", "1");
    185   manifest.SetInteger("manifest_version", 21);
    186   manifest.SetString("app.launch.local_path", "foo.html");
    187 
    188   std::string error;
    189   scoped_refptr<const Extension> extension(Extension::Create(
    190       base::FilePath(), Manifest::INTERNAL, manifest, Extension::NO_FLAGS,
    191       &error));
    192   EXPECT_EQ("", error);
    193   ASSERT_TRUE(extension.get());
    194 
    195   feature.whitelist()->insert("monkey");
    196   EXPECT_EQ(Feature::NOT_FOUND_IN_WHITELIST, feature.IsAvailableToContext(
    197       extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
    198       Feature::CHROMEOS_PLATFORM).result());
    199   feature.whitelist()->clear();
    200 
    201   feature.extension_types()->clear();
    202   feature.extension_types()->insert(Manifest::TYPE_THEME);
    203   {
    204     Feature::Availability availability = feature.IsAvailableToContext(
    205         extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
    206         Feature::CHROMEOS_PLATFORM);
    207     EXPECT_EQ(Feature::INVALID_TYPE, availability.result());
    208     EXPECT_EQ("'somefeature' is only allowed for themes, "
    209               "but this is a legacy packaged app.",
    210               availability.message());
    211   }
    212 
    213   feature.extension_types()->clear();
    214   feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP);
    215   feature.GetContexts()->clear();
    216   feature.GetContexts()->insert(Feature::UNBLESSED_EXTENSION_CONTEXT);
    217   feature.GetContexts()->insert(Feature::CONTENT_SCRIPT_CONTEXT);
    218   {
    219     Feature::Availability availability = feature.IsAvailableToContext(
    220         extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
    221         Feature::CHROMEOS_PLATFORM);
    222     EXPECT_EQ(Feature::INVALID_CONTEXT, availability.result());
    223     EXPECT_EQ("'somefeature' is only allowed to run in extension iframes and "
    224               "content scripts, but this is a privileged page",
    225               availability.message());
    226   }
    227 
    228   feature.GetContexts()->insert(Feature::WEB_PAGE_CONTEXT);
    229   {
    230     Feature::Availability availability = feature.IsAvailableToContext(
    231         extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
    232         Feature::CHROMEOS_PLATFORM);
    233     EXPECT_EQ(Feature::INVALID_CONTEXT, availability.result());
    234     EXPECT_EQ("'somefeature' is only allowed to run in extension iframes, "
    235               "content scripts, and web pages, but this is a privileged page",
    236               availability.message());
    237   }
    238 
    239   feature.GetContexts()->clear();
    240   feature.GetContexts()->insert(Feature::BLESSED_EXTENSION_CONTEXT);
    241   feature.set_location(Feature::COMPONENT_LOCATION);
    242   EXPECT_EQ(Feature::INVALID_LOCATION, feature.IsAvailableToContext(
    243       extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
    244       Feature::CHROMEOS_PLATFORM).result());
    245   feature.set_location(Feature::UNSPECIFIED_LOCATION);
    246 
    247   EXPECT_EQ(Feature::INVALID_PLATFORM, feature.IsAvailableToContext(
    248       extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
    249       Feature::UNSPECIFIED_PLATFORM).result());
    250 
    251   feature.set_min_manifest_version(22);
    252   EXPECT_EQ(Feature::INVALID_MIN_MANIFEST_VERSION, feature.IsAvailableToContext(
    253       extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
    254       Feature::CHROMEOS_PLATFORM).result());
    255   feature.set_min_manifest_version(21);
    256 
    257   feature.set_max_manifest_version(18);
    258   EXPECT_EQ(Feature::INVALID_MAX_MANIFEST_VERSION, feature.IsAvailableToContext(
    259       extension.get(), Feature::BLESSED_EXTENSION_CONTEXT,
    260       Feature::CHROMEOS_PLATFORM).result());
    261   feature.set_max_manifest_version(25);
    262 }
    263 
    264 TEST_F(ExtensionSimpleFeatureTest, Location) {
    265   SimpleFeature feature;
    266 
    267   // If the feature specifies "component" as its location, then only component
    268   // extensions can access it.
    269   feature.set_location(Feature::COMPONENT_LOCATION);
    270   EXPECT_EQ(
    271       Feature::IS_AVAILABLE,
    272       feature.IsAvailableToManifest(std::string(),
    273                                     Manifest::TYPE_UNKNOWN,
    274                                     Feature::COMPONENT_LOCATION,
    275                                     -1,
    276                                     Feature::UNSPECIFIED_PLATFORM).result());
    277   EXPECT_EQ(
    278       Feature::INVALID_LOCATION,
    279       feature.IsAvailableToManifest(std::string(),
    280                                     Manifest::TYPE_UNKNOWN,
    281                                     Feature::UNSPECIFIED_LOCATION,
    282                                     -1,
    283                                     Feature::UNSPECIFIED_PLATFORM).result());
    284 
    285   // But component extensions can access anything else, whatever their location.
    286   feature.set_location(Feature::UNSPECIFIED_LOCATION);
    287   EXPECT_EQ(
    288       Feature::IS_AVAILABLE,
    289       feature.IsAvailableToManifest(std::string(),
    290                                     Manifest::TYPE_UNKNOWN,
    291                                     Feature::COMPONENT_LOCATION,
    292                                     -1,
    293                                     Feature::UNSPECIFIED_PLATFORM).result());
    294 }
    295 
    296 TEST_F(ExtensionSimpleFeatureTest, Platform) {
    297   SimpleFeature feature;
    298   feature.platforms()->insert(Feature::CHROMEOS_PLATFORM);
    299   EXPECT_EQ(Feature::IS_AVAILABLE,
    300             feature.IsAvailableToManifest(std::string(),
    301                                           Manifest::TYPE_UNKNOWN,
    302                                           Feature::UNSPECIFIED_LOCATION,
    303                                           -1,
    304                                           Feature::CHROMEOS_PLATFORM).result());
    305   EXPECT_EQ(
    306       Feature::INVALID_PLATFORM,
    307       feature.IsAvailableToManifest(std::string(),
    308                                     Manifest::TYPE_UNKNOWN,
    309                                     Feature::UNSPECIFIED_LOCATION,
    310                                     -1,
    311                                     Feature::UNSPECIFIED_PLATFORM).result());
    312 }
    313 
    314 TEST_F(ExtensionSimpleFeatureTest, Version) {
    315   SimpleFeature feature;
    316   feature.set_min_manifest_version(5);
    317 
    318   EXPECT_EQ(
    319       Feature::INVALID_MIN_MANIFEST_VERSION,
    320       feature.IsAvailableToManifest(std::string(),
    321                                     Manifest::TYPE_UNKNOWN,
    322                                     Feature::UNSPECIFIED_LOCATION,
    323                                     0,
    324                                     Feature::UNSPECIFIED_PLATFORM).result());
    325   EXPECT_EQ(
    326       Feature::INVALID_MIN_MANIFEST_VERSION,
    327       feature.IsAvailableToManifest(std::string(),
    328                                     Manifest::TYPE_UNKNOWN,
    329                                     Feature::UNSPECIFIED_LOCATION,
    330                                     4,
    331                                     Feature::UNSPECIFIED_PLATFORM).result());
    332 
    333   EXPECT_EQ(
    334       Feature::IS_AVAILABLE,
    335       feature.IsAvailableToManifest(std::string(),
    336                                     Manifest::TYPE_UNKNOWN,
    337                                     Feature::UNSPECIFIED_LOCATION,
    338                                     5,
    339                                     Feature::UNSPECIFIED_PLATFORM).result());
    340   EXPECT_EQ(
    341       Feature::IS_AVAILABLE,
    342       feature.IsAvailableToManifest(std::string(),
    343                                     Manifest::TYPE_UNKNOWN,
    344                                     Feature::UNSPECIFIED_LOCATION,
    345                                     10,
    346                                     Feature::UNSPECIFIED_PLATFORM).result());
    347 
    348   feature.set_max_manifest_version(8);
    349 
    350   EXPECT_EQ(
    351       Feature::INVALID_MAX_MANIFEST_VERSION,
    352       feature.IsAvailableToManifest(std::string(),
    353                                     Manifest::TYPE_UNKNOWN,
    354                                     Feature::UNSPECIFIED_LOCATION,
    355                                     10,
    356                                     Feature::UNSPECIFIED_PLATFORM).result());
    357   EXPECT_EQ(
    358       Feature::IS_AVAILABLE,
    359       feature.IsAvailableToManifest(std::string(),
    360                                     Manifest::TYPE_UNKNOWN,
    361                                     Feature::UNSPECIFIED_LOCATION,
    362                                     8,
    363                                     Feature::UNSPECIFIED_PLATFORM).result());
    364   EXPECT_EQ(
    365       Feature::IS_AVAILABLE,
    366       feature.IsAvailableToManifest(std::string(),
    367                                     Manifest::TYPE_UNKNOWN,
    368                                     Feature::UNSPECIFIED_LOCATION,
    369                                     7,
    370                                     Feature::UNSPECIFIED_PLATFORM).result());
    371 }
    372 
    373 TEST_F(ExtensionSimpleFeatureTest, ParseNull) {
    374   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
    375   scoped_ptr<SimpleFeature> feature(new SimpleFeature());
    376   feature->Parse(value.get());
    377   EXPECT_TRUE(feature->whitelist()->empty());
    378   EXPECT_TRUE(feature->extension_types()->empty());
    379   EXPECT_TRUE(feature->GetContexts()->empty());
    380   EXPECT_EQ(Feature::UNSPECIFIED_LOCATION, feature->location());
    381   EXPECT_TRUE(feature->platforms()->empty());
    382   EXPECT_EQ(0, feature->min_manifest_version());
    383   EXPECT_EQ(0, feature->max_manifest_version());
    384 }
    385 
    386 TEST_F(ExtensionSimpleFeatureTest, ParseWhitelist) {
    387   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
    388   base::ListValue* whitelist = new base::ListValue();
    389   whitelist->Append(new base::StringValue("foo"));
    390   whitelist->Append(new base::StringValue("bar"));
    391   value->Set("whitelist", whitelist);
    392   scoped_ptr<SimpleFeature> feature(new SimpleFeature());
    393   feature->Parse(value.get());
    394   EXPECT_EQ(2u, feature->whitelist()->size());
    395   EXPECT_TRUE(feature->whitelist()->count("foo"));
    396   EXPECT_TRUE(feature->whitelist()->count("bar"));
    397 }
    398 
    399 TEST_F(ExtensionSimpleFeatureTest, ParsePackageTypes) {
    400   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
    401   base::ListValue* extension_types = new base::ListValue();
    402   extension_types->Append(new base::StringValue("extension"));
    403   extension_types->Append(new base::StringValue("theme"));
    404   extension_types->Append(new base::StringValue("legacy_packaged_app"));
    405   extension_types->Append(new base::StringValue("hosted_app"));
    406   extension_types->Append(new base::StringValue("platform_app"));
    407   extension_types->Append(new base::StringValue("shared_module"));
    408   value->Set("extension_types", extension_types);
    409   scoped_ptr<SimpleFeature> feature(new SimpleFeature());
    410   feature->Parse(value.get());
    411   EXPECT_EQ(6u, feature->extension_types()->size());
    412   EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_EXTENSION));
    413   EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_THEME));
    414   EXPECT_TRUE(feature->extension_types()->count(
    415       Manifest::TYPE_LEGACY_PACKAGED_APP));
    416   EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_HOSTED_APP));
    417   EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_PLATFORM_APP));
    418   EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_SHARED_MODULE));
    419 
    420   value->SetString("extension_types", "all");
    421   scoped_ptr<SimpleFeature> feature2(new SimpleFeature());
    422   feature2->Parse(value.get());
    423   EXPECT_EQ(*(feature->extension_types()), *(feature2->extension_types()));
    424 }
    425 
    426 TEST_F(ExtensionSimpleFeatureTest, ParseContexts) {
    427   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
    428   base::ListValue* contexts = new base::ListValue();
    429   contexts->Append(new base::StringValue("blessed_extension"));
    430   contexts->Append(new base::StringValue("unblessed_extension"));
    431   contexts->Append(new base::StringValue("content_script"));
    432   contexts->Append(new base::StringValue("web_page"));
    433   contexts->Append(new base::StringValue("blessed_web_page"));
    434   value->Set("contexts", contexts);
    435   scoped_ptr<SimpleFeature> feature(new SimpleFeature());
    436   feature->Parse(value.get());
    437   EXPECT_EQ(5u, feature->GetContexts()->size());
    438   EXPECT_TRUE(
    439       feature->GetContexts()->count(Feature::BLESSED_EXTENSION_CONTEXT));
    440   EXPECT_TRUE(
    441       feature->GetContexts()->count(Feature::UNBLESSED_EXTENSION_CONTEXT));
    442   EXPECT_TRUE(
    443       feature->GetContexts()->count(Feature::CONTENT_SCRIPT_CONTEXT));
    444   EXPECT_TRUE(
    445       feature->GetContexts()->count(Feature::WEB_PAGE_CONTEXT));
    446   EXPECT_TRUE(
    447       feature->GetContexts()->count(Feature::BLESSED_WEB_PAGE_CONTEXT));
    448 
    449   value->SetString("contexts", "all");
    450   scoped_ptr<SimpleFeature> feature2(new SimpleFeature());
    451   feature2->Parse(value.get());
    452   EXPECT_EQ(*(feature->GetContexts()), *(feature2->GetContexts()));
    453 }
    454 
    455 TEST_F(ExtensionSimpleFeatureTest, ParseLocation) {
    456   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
    457   value->SetString("location", "component");
    458   scoped_ptr<SimpleFeature> feature(new SimpleFeature());
    459   feature->Parse(value.get());
    460   EXPECT_EQ(Feature::COMPONENT_LOCATION, feature->location());
    461 }
    462 
    463 TEST_F(ExtensionSimpleFeatureTest, ParsePlatforms) {
    464   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
    465   scoped_ptr<SimpleFeature> feature(new SimpleFeature());
    466   base::ListValue* platforms = new base::ListValue();
    467   value->Set("platforms", platforms);
    468   feature->Parse(value.get());
    469   EXPECT_TRUE(feature->platforms()->empty());
    470 
    471   platforms->AppendString("chromeos");
    472   feature->Parse(value.get());
    473   EXPECT_FALSE(feature->platforms()->empty());
    474   EXPECT_EQ(Feature::CHROMEOS_PLATFORM, *feature->platforms()->begin());
    475 
    476   platforms->Clear();
    477   platforms->AppendString("win");
    478   feature->Parse(value.get());
    479   EXPECT_FALSE(feature->platforms()->empty());
    480   EXPECT_EQ(Feature::WIN_PLATFORM, *feature->platforms()->begin());
    481 
    482   platforms->Clear();
    483   platforms->AppendString("win");
    484   platforms->AppendString("chromeos");
    485   feature->Parse(value.get());
    486   std::set<Feature::Platform> expected_platforms;
    487   expected_platforms.insert(Feature::CHROMEOS_PLATFORM);
    488   expected_platforms.insert(Feature::WIN_PLATFORM);
    489 
    490   EXPECT_FALSE(feature->platforms()->empty());
    491   EXPECT_EQ(expected_platforms, *feature->platforms());
    492 }
    493 
    494 TEST_F(ExtensionSimpleFeatureTest, ManifestVersion) {
    495   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
    496   value->SetInteger("min_manifest_version", 1);
    497   value->SetInteger("max_manifest_version", 5);
    498   scoped_ptr<SimpleFeature> feature(new SimpleFeature());
    499   feature->Parse(value.get());
    500   EXPECT_EQ(1, feature->min_manifest_version());
    501   EXPECT_EQ(5, feature->max_manifest_version());
    502 }
    503 
    504 TEST_F(ExtensionSimpleFeatureTest, Inheritance) {
    505   SimpleFeature feature;
    506   feature.whitelist()->insert("foo");
    507   feature.extension_types()->insert(Manifest::TYPE_THEME);
    508   feature.GetContexts()->insert(Feature::BLESSED_EXTENSION_CONTEXT);
    509   feature.set_location(Feature::COMPONENT_LOCATION);
    510   feature.platforms()->insert(Feature::CHROMEOS_PLATFORM);
    511   feature.set_min_manifest_version(1);
    512   feature.set_max_manifest_version(2);
    513 
    514   SimpleFeature feature2 = feature;
    515   EXPECT_TRUE(feature2.Equals(feature));
    516 
    517   base::DictionaryValue definition;
    518   feature2.Parse(&definition);
    519   EXPECT_TRUE(feature2.Equals(feature));
    520 
    521   base::ListValue* whitelist = new base::ListValue();
    522   base::ListValue* extension_types = new base::ListValue();
    523   base::ListValue* contexts = new base::ListValue();
    524   whitelist->Append(new base::StringValue("bar"));
    525   extension_types->Append(new base::StringValue("extension"));
    526   contexts->Append(new base::StringValue("unblessed_extension"));
    527   definition.Set("whitelist", whitelist);
    528   definition.Set("extension_types", extension_types);
    529   definition.Set("contexts", contexts);
    530   // Can't test location or platform because we only have one value so far.
    531   definition.Set("min_manifest_version", new base::FundamentalValue(2));
    532   definition.Set("max_manifest_version", new base::FundamentalValue(3));
    533 
    534   feature2.Parse(&definition);
    535   EXPECT_FALSE(feature2.Equals(feature));
    536   EXPECT_EQ(1u, feature2.whitelist()->size());
    537   EXPECT_EQ(1u, feature2.extension_types()->size());
    538   EXPECT_EQ(1u, feature2.GetContexts()->size());
    539   EXPECT_EQ(1u, feature2.whitelist()->count("bar"));
    540   EXPECT_EQ(1u, feature2.extension_types()->count(Manifest::TYPE_EXTENSION));
    541   EXPECT_EQ(1u, feature2.GetContexts()->count(
    542       Feature::UNBLESSED_EXTENSION_CONTEXT));
    543   EXPECT_EQ(2, feature2.min_manifest_version());
    544   EXPECT_EQ(3, feature2.max_manifest_version());
    545 }
    546 
    547 TEST_F(ExtensionSimpleFeatureTest, Equals) {
    548   SimpleFeature feature;
    549   feature.whitelist()->insert("foo");
    550   feature.extension_types()->insert(Manifest::TYPE_THEME);
    551   feature.GetContexts()->insert(Feature::UNBLESSED_EXTENSION_CONTEXT);
    552   feature.set_location(Feature::COMPONENT_LOCATION);
    553   feature.platforms()->insert(Feature::CHROMEOS_PLATFORM);
    554   feature.set_min_manifest_version(18);
    555   feature.set_max_manifest_version(25);
    556 
    557   SimpleFeature feature2(feature);
    558   EXPECT_TRUE(feature2.Equals(feature));
    559 
    560   feature2.whitelist()->clear();
    561   EXPECT_FALSE(feature2.Equals(feature));
    562 
    563   feature2 = feature;
    564   feature2.extension_types()->clear();
    565   EXPECT_FALSE(feature2.Equals(feature));
    566 
    567   feature2 = feature;
    568   feature2.GetContexts()->clear();
    569   EXPECT_FALSE(feature2.Equals(feature));
    570 
    571   feature2 = feature;
    572   feature2.set_location(Feature::UNSPECIFIED_LOCATION);
    573   EXPECT_FALSE(feature2.Equals(feature));
    574 
    575   feature2 = feature;
    576   feature.platforms()->insert(Feature::UNSPECIFIED_PLATFORM);
    577   EXPECT_FALSE(feature2.Equals(feature));
    578 
    579   feature2 = feature;
    580   feature2.set_min_manifest_version(0);
    581   EXPECT_FALSE(feature2.Equals(feature));
    582 
    583   feature2 = feature;
    584   feature2.set_max_manifest_version(0);
    585   EXPECT_FALSE(feature2.Equals(feature));
    586 }
    587 
    588 Feature::AvailabilityResult IsAvailableInChannel(
    589     const std::string& channel, VersionInfo::Channel channel_for_testing) {
    590   ScopedCurrentChannel current_channel(channel_for_testing);
    591 
    592   SimpleFeature feature;
    593   if (!channel.empty()) {
    594     base::DictionaryValue feature_value;
    595     feature_value.SetString("channel", channel);
    596     feature.Parse(&feature_value);
    597   }
    598 
    599   return feature.IsAvailableToManifest(
    600       "random-extension",
    601       Manifest::TYPE_UNKNOWN,
    602       Feature::UNSPECIFIED_LOCATION,
    603       -1,
    604       Feature::GetCurrentPlatform()).result();
    605 }
    606 
    607 TEST_F(ExtensionSimpleFeatureTest, SupportedChannel) {
    608   // stable supported.
    609   EXPECT_EQ(Feature::IS_AVAILABLE,
    610       IsAvailableInChannel("stable", VersionInfo::CHANNEL_UNKNOWN));
    611   EXPECT_EQ(Feature::IS_AVAILABLE,
    612       IsAvailableInChannel("stable", VersionInfo::CHANNEL_CANARY));
    613   EXPECT_EQ(Feature::IS_AVAILABLE,
    614       IsAvailableInChannel("stable", VersionInfo::CHANNEL_DEV));
    615   EXPECT_EQ(Feature::IS_AVAILABLE,
    616       IsAvailableInChannel("stable", VersionInfo::CHANNEL_BETA));
    617   EXPECT_EQ(Feature::IS_AVAILABLE,
    618       IsAvailableInChannel("stable", VersionInfo::CHANNEL_STABLE));
    619 
    620   // beta supported.
    621   EXPECT_EQ(Feature::IS_AVAILABLE,
    622       IsAvailableInChannel("beta", VersionInfo::CHANNEL_UNKNOWN));
    623   EXPECT_EQ(Feature::IS_AVAILABLE,
    624       IsAvailableInChannel("beta", VersionInfo::CHANNEL_CANARY));
    625   EXPECT_EQ(Feature::IS_AVAILABLE,
    626       IsAvailableInChannel("beta", VersionInfo::CHANNEL_DEV));
    627   EXPECT_EQ(Feature::IS_AVAILABLE,
    628       IsAvailableInChannel("beta", VersionInfo::CHANNEL_BETA));
    629   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    630       IsAvailableInChannel("beta", VersionInfo::CHANNEL_STABLE));
    631 
    632   // dev supported.
    633   EXPECT_EQ(Feature::IS_AVAILABLE,
    634       IsAvailableInChannel("dev", VersionInfo::CHANNEL_UNKNOWN));
    635   EXPECT_EQ(Feature::IS_AVAILABLE,
    636       IsAvailableInChannel("dev", VersionInfo::CHANNEL_CANARY));
    637   EXPECT_EQ(Feature::IS_AVAILABLE,
    638       IsAvailableInChannel("dev", VersionInfo::CHANNEL_DEV));
    639   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    640       IsAvailableInChannel("dev", VersionInfo::CHANNEL_BETA));
    641   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    642       IsAvailableInChannel("dev", VersionInfo::CHANNEL_STABLE));
    643 
    644   // canary supported.
    645   EXPECT_EQ(Feature::IS_AVAILABLE,
    646       IsAvailableInChannel("canary", VersionInfo::CHANNEL_UNKNOWN));
    647   EXPECT_EQ(Feature::IS_AVAILABLE,
    648       IsAvailableInChannel("canary", VersionInfo::CHANNEL_CANARY));
    649   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    650       IsAvailableInChannel("canary", VersionInfo::CHANNEL_DEV));
    651   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    652       IsAvailableInChannel("canary", VersionInfo::CHANNEL_BETA));
    653   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    654       IsAvailableInChannel("canary", VersionInfo::CHANNEL_STABLE));
    655 
    656   // trunk supported.
    657   EXPECT_EQ(Feature::IS_AVAILABLE,
    658       IsAvailableInChannel("trunk", VersionInfo::CHANNEL_UNKNOWN));
    659   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    660       IsAvailableInChannel("trunk", VersionInfo::CHANNEL_CANARY));
    661   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    662       IsAvailableInChannel("trunk", VersionInfo::CHANNEL_DEV));
    663   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    664       IsAvailableInChannel("trunk", VersionInfo::CHANNEL_BETA));
    665   EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL,
    666       IsAvailableInChannel("trunk", VersionInfo::CHANNEL_STABLE));
    667 }
    668 
    669 }  // namespace
    670