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