simple_feature_unittest.cc revision 010d83a9304c5a91596085d917d248abff47903a
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
12using chrome::VersionInfo;
13using extensions::DictionaryBuilder;
14using extensions::Extension;
15using extensions::Feature;
16using extensions::ListBuilder;
17using extensions::Manifest;
18using extensions::ScopedCurrentChannel;
19using extensions::SimpleFeature;
20
21namespace extensions {
22
23namespace {
24
25struct 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
36class 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
59TEST_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
88TEST_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
136TEST_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
175TEST_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
214TEST_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
253TEST_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
289TEST_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
380TEST_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
416TEST_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
434TEST_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
493TEST_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
506TEST_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
519TEST_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
546TEST_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
575TEST_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
583TEST_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
614TEST_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
624TEST_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
673Feature::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
693TEST_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