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