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