OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/common/features/simple_feature.h" | 5 #include "extensions/common/features/simple_feature.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
200 return "dev"; | 200 return "dev"; |
201 case version_info::Channel::BETA: | 201 case version_info::Channel::BETA: |
202 return "beta"; | 202 return "beta"; |
203 case version_info::Channel::STABLE: | 203 case version_info::Channel::STABLE: |
204 return "stable"; | 204 return "stable"; |
205 } | 205 } |
206 NOTREACHED(); | 206 NOTREACHED(); |
207 return ""; | 207 return ""; |
208 } | 208 } |
209 | 209 |
| 210 std::string GetSessionTypeDisplayName(FeatureSessionType session_type) { |
| 211 switch (session_type) { |
| 212 case FeatureSessionType::UNKNOWN: |
| 213 return "unknown"; |
| 214 case FeatureSessionType::KIOSK: |
| 215 return "kiosk app"; |
| 216 case FeatureSessionType::REGULAR: |
| 217 return "regular user"; |
| 218 default: |
| 219 return ""; |
| 220 } |
| 221 } |
| 222 |
210 // Gets a human-readable list of the display names (pluralized, comma separated | 223 // Gets a human-readable list of the display names (pluralized, comma separated |
211 // with the "and" in the correct place) for each of |enum_types|. | 224 // with the "and" in the correct place) for each of |enum_types|. |
212 template <typename EnumType> | 225 template <typename EnumType> |
213 std::string ListDisplayNames(const std::vector<EnumType>& enum_types) { | 226 std::string ListDisplayNames(const std::vector<EnumType>& enum_types) { |
214 std::string display_name_list; | 227 std::string display_name_list; |
215 for (size_t i = 0; i < enum_types.size(); ++i) { | 228 for (size_t i = 0; i < enum_types.size(); ++i) { |
216 // Pluralize type name. | 229 // Pluralize type name. |
217 display_name_list += GetDisplayName(enum_types[i]) + "s"; | 230 display_name_list += GetDisplayName(enum_types[i]) + "s"; |
218 // Comma-separate entries, with an Oxford comma if there is more than 2 | 231 // Comma-separate entries, with an Oxford comma if there is more than 2 |
219 // total entries. | 232 // total entries. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 platforms["chromeos"] = Feature::CHROMEOS_PLATFORM; | 303 platforms["chromeos"] = Feature::CHROMEOS_PLATFORM; |
291 platforms["linux"] = Feature::LINUX_PLATFORM; | 304 platforms["linux"] = Feature::LINUX_PLATFORM; |
292 platforms["mac"] = Feature::MACOSX_PLATFORM; | 305 platforms["mac"] = Feature::MACOSX_PLATFORM; |
293 platforms["win"] = Feature::WIN_PLATFORM; | 306 platforms["win"] = Feature::WIN_PLATFORM; |
294 | 307 |
295 channels["trunk"] = version_info::Channel::UNKNOWN; | 308 channels["trunk"] = version_info::Channel::UNKNOWN; |
296 channels["canary"] = version_info::Channel::CANARY; | 309 channels["canary"] = version_info::Channel::CANARY; |
297 channels["dev"] = version_info::Channel::DEV; | 310 channels["dev"] = version_info::Channel::DEV; |
298 channels["beta"] = version_info::Channel::BETA; | 311 channels["beta"] = version_info::Channel::BETA; |
299 channels["stable"] = version_info::Channel::STABLE; | 312 channels["stable"] = version_info::Channel::STABLE; |
| 313 |
| 314 session_types["regular"] = FeatureSessionType::REGULAR; |
| 315 session_types["kiosk"] = FeatureSessionType::KIOSK; |
300 } | 316 } |
301 | 317 |
302 std::map<std::string, Manifest::Type> extension_types; | 318 std::map<std::string, Manifest::Type> extension_types; |
303 std::map<std::string, Feature::Context> contexts; | 319 std::map<std::string, Feature::Context> contexts; |
304 std::map<std::string, SimpleFeature::Location> locations; | 320 std::map<std::string, SimpleFeature::Location> locations; |
305 std::map<std::string, Feature::Platform> platforms; | 321 std::map<std::string, Feature::Platform> platforms; |
306 std::map<std::string, version_info::Channel> channels; | 322 std::map<std::string, version_info::Channel> channels; |
| 323 std::map<std::string, FeatureSessionType> session_types; |
307 }; | 324 }; |
308 | 325 |
309 SimpleFeature::SimpleFeature() | 326 SimpleFeature::SimpleFeature() |
310 : location_(UNSPECIFIED_LOCATION), | 327 : location_(UNSPECIFIED_LOCATION), |
311 min_manifest_version_(0), | 328 min_manifest_version_(0), |
312 max_manifest_version_(0), | 329 max_manifest_version_(0), |
313 component_extensions_auto_granted_(true), | 330 component_extensions_auto_granted_(true), |
314 is_internal_(false) {} | 331 is_internal_(false) {} |
315 | 332 |
316 SimpleFeature::~SimpleFeature() {} | 333 SimpleFeature::~SimpleFeature() {} |
(...skipping 15 matching lines...) Expand all Loading... |
332 } else if (key == "whitelist") { | 349 } else if (key == "whitelist") { |
333 ParseVector(value, &whitelist_); | 350 ParseVector(value, &whitelist_); |
334 } else if (key == "dependencies") { | 351 } else if (key == "dependencies") { |
335 ParseVector(value, &dependencies_); | 352 ParseVector(value, &dependencies_); |
336 } else if (key == "extension_types") { | 353 } else if (key == "extension_types") { |
337 ParseEnumVector<Manifest::Type>(value, &extension_types_, | 354 ParseEnumVector<Manifest::Type>(value, &extension_types_, |
338 mappings.Get().extension_types); | 355 mappings.Get().extension_types); |
339 } else if (key == "contexts") { | 356 } else if (key == "contexts") { |
340 ParseEnumVector<Context>(value, &contexts_, | 357 ParseEnumVector<Context>(value, &contexts_, |
341 mappings.Get().contexts); | 358 mappings.Get().contexts); |
| 359 } else if (key == "session_types") { |
| 360 ParseEnumVector<FeatureSessionType>(value, &session_types_, |
| 361 mappings.Get().session_types); |
342 } else if (key == "location") { | 362 } else if (key == "location") { |
343 ParseEnum<Location>(value, &location_, mappings.Get().locations); | 363 ParseEnum<Location>(value, &location_, mappings.Get().locations); |
344 } else if (key == "platforms") { | 364 } else if (key == "platforms") { |
345 ParseEnumVector<Platform>(value, &platforms_, | 365 ParseEnumVector<Platform>(value, &platforms_, |
346 mappings.Get().platforms); | 366 mappings.Get().platforms); |
347 } else if (key == "min_manifest_version") { | 367 } else if (key == "min_manifest_version") { |
348 dictionary->GetInteger("min_manifest_version", &min_manifest_version_); | 368 dictionary->GetInteger("min_manifest_version", &min_manifest_version_); |
349 } else if (key == "max_manifest_version") { | 369 } else if (key == "max_manifest_version") { |
350 dictionary->GetInteger("max_manifest_version", &max_manifest_version_); | 370 dictionary->GetInteger("max_manifest_version", &max_manifest_version_); |
351 } else if (key == "noparent") { | 371 } else if (key == "noparent") { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 return CheckDependencies(base::Bind(&IsAvailableToManifestForBind, | 461 return CheckDependencies(base::Bind(&IsAvailableToManifestForBind, |
442 extension_id, | 462 extension_id, |
443 type, | 463 type, |
444 location, | 464 location, |
445 manifest_version, | 465 manifest_version, |
446 platform)); | 466 platform)); |
447 } | 467 } |
448 | 468 |
449 Feature::Availability SimpleFeature::IsAvailableToContext( | 469 Feature::Availability SimpleFeature::IsAvailableToContext( |
450 const Extension* extension, | 470 const Extension* extension, |
451 SimpleFeature::Context context, | 471 Feature::Context context, |
452 const GURL& url, | 472 const GURL& url, |
453 SimpleFeature::Platform platform) const { | 473 SimpleFeature::Platform platform) const { |
454 if (extension) { | 474 if (extension) { |
455 Availability result = IsAvailableToManifest(extension->id(), | 475 Availability result = IsAvailableToManifest(extension->id(), |
456 extension->GetType(), | 476 extension->GetType(), |
457 extension->location(), | 477 extension->location(), |
458 extension->manifest_version(), | 478 extension->manifest_version(), |
459 platform); | 479 platform); |
460 if (!result.is_available()) | 480 if (!result.is_available()) |
461 return result; | 481 return result; |
462 } | 482 } |
463 | 483 |
464 // TODO(lazyboy): This isn't quite right for Extension Service Worker | 484 // TODO(lazyboy): This isn't quite right for Extension Service Worker |
465 // extension API calls, since there's no guarantee that the extension is | 485 // extension API calls, since there's no guarantee that the extension is |
466 // "active" in current renderer process when the API permission check is | 486 // "active" in current renderer process when the API permission check is |
467 // done. | 487 // done. |
468 if (!contexts_.empty() && !base::ContainsValue(contexts_, context)) | 488 if (!contexts_.empty() && !base::ContainsValue(contexts_, context)) |
469 return CreateAvailability(INVALID_CONTEXT, context); | 489 return CreateAvailability(INVALID_CONTEXT, context); |
470 | 490 |
471 // TODO(kalman): Consider checking |matches_| regardless of context type. | 491 // TODO(kalman): Consider checking |matches_| regardless of context type. |
472 // Fewer surprises, and if the feature configuration wants to isolate | 492 // Fewer surprises, and if the feature configuration wants to isolate |
473 // "matches" from say "blessed_extension" then they can use complex features. | 493 // "matches" from say "blessed_extension" then they can use complex features. |
474 if ((context == WEB_PAGE_CONTEXT || context == WEBUI_CONTEXT) && | 494 if ((context == WEB_PAGE_CONTEXT || context == WEBUI_CONTEXT) && |
475 !matches_.MatchesURL(url)) { | 495 !matches_.MatchesURL(url)) { |
476 return CreateAvailability(INVALID_URL, url); | 496 return CreateAvailability(INVALID_URL, url); |
477 } | 497 } |
478 | 498 |
| 499 FeatureSessionType session_type = GetCurrentFeatureSessionType(); |
| 500 if (!session_types_.empty() && |
| 501 !base::ContainsValue(session_types_, session_type)) { |
| 502 return CreateAvailability(INVALID_SESSION_TYPE, session_type); |
| 503 } |
| 504 |
479 // TODO(kalman): Assert that if the context was a webpage or WebUI context | 505 // TODO(kalman): Assert that if the context was a webpage or WebUI context |
480 // then at some point a "matches" restriction was checked. | 506 // then at some point a "matches" restriction was checked. |
481 return CheckDependencies(base::Bind( | 507 return CheckDependencies(base::Bind(&IsAvailableToContextForBind, extension, |
482 &IsAvailableToContextForBind, extension, context, url, platform)); | 508 context, url, platform)); |
483 } | 509 } |
484 | 510 |
485 std::string SimpleFeature::GetAvailabilityMessage( | 511 std::string SimpleFeature::GetAvailabilityMessage( |
486 AvailabilityResult result, | 512 AvailabilityResult result, |
487 Manifest::Type type, | 513 Manifest::Type type, |
488 const GURL& url, | 514 const GURL& url, |
489 Context context, | 515 Context context, |
490 version_info::Channel channel) const { | 516 version_info::Channel channel, |
| 517 FeatureSessionType session_type) const { |
491 switch (result) { | 518 switch (result) { |
492 case IS_AVAILABLE: | 519 case IS_AVAILABLE: |
493 return std::string(); | 520 return std::string(); |
494 case NOT_FOUND_IN_WHITELIST: | 521 case NOT_FOUND_IN_WHITELIST: |
495 case FOUND_IN_BLACKLIST: | 522 case FOUND_IN_BLACKLIST: |
496 return base::StringPrintf( | 523 return base::StringPrintf( |
497 "'%s' is not allowed for specified extension ID.", | 524 "'%s' is not allowed for specified extension ID.", |
498 name().c_str()); | 525 name().c_str()); |
499 case INVALID_URL: | 526 case INVALID_URL: |
500 return base::StringPrintf("'%s' is not allowed on %s.", | 527 return base::StringPrintf("'%s' is not allowed on %s.", |
(...skipping 23 matching lines...) Expand all Loading... |
524 case INVALID_MIN_MANIFEST_VERSION: | 551 case INVALID_MIN_MANIFEST_VERSION: |
525 return base::StringPrintf( | 552 return base::StringPrintf( |
526 "'%s' requires manifest version of at least %d.", | 553 "'%s' requires manifest version of at least %d.", |
527 name().c_str(), | 554 name().c_str(), |
528 min_manifest_version_); | 555 min_manifest_version_); |
529 case INVALID_MAX_MANIFEST_VERSION: | 556 case INVALID_MAX_MANIFEST_VERSION: |
530 return base::StringPrintf( | 557 return base::StringPrintf( |
531 "'%s' requires manifest version of %d or lower.", | 558 "'%s' requires manifest version of %d or lower.", |
532 name().c_str(), | 559 name().c_str(), |
533 max_manifest_version_); | 560 max_manifest_version_); |
| 561 case INVALID_SESSION_TYPE: |
| 562 return base::StringPrintf( |
| 563 "'%s' is not allowed in %s session", name().c_str(), |
| 564 GetSessionTypeDisplayName(session_type).c_str()); |
534 case NOT_PRESENT: | 565 case NOT_PRESENT: |
535 return base::StringPrintf( | 566 return base::StringPrintf( |
536 "'%s' requires a different Feature that is not present.", | 567 "'%s' requires a different Feature that is not present.", |
537 name().c_str()); | 568 name().c_str()); |
538 case UNSUPPORTED_CHANNEL: | 569 case UNSUPPORTED_CHANNEL: |
539 return base::StringPrintf( | 570 return base::StringPrintf( |
540 "'%s' requires %s channel or newer, but this is the %s channel.", | 571 "'%s' requires %s channel or newer, but this is the %s channel.", |
541 name().c_str(), GetDisplayName(channel).c_str(), | 572 name().c_str(), GetDisplayName(channel).c_str(), |
542 GetDisplayName(GetCurrentChannel()).c_str()); | 573 GetDisplayName(GetCurrentChannel()).c_str()); |
543 case MISSING_COMMAND_LINE_SWITCH: | 574 case MISSING_COMMAND_LINE_SWITCH: |
544 return base::StringPrintf( | 575 return base::StringPrintf( |
545 "'%s' requires the '%s' command line switch to be enabled.", | 576 "'%s' requires the '%s' command line switch to be enabled.", |
546 name().c_str(), command_line_switch_.c_str()); | 577 name().c_str(), command_line_switch_.c_str()); |
547 } | 578 } |
548 | 579 |
549 NOTREACHED(); | 580 NOTREACHED(); |
550 return std::string(); | 581 return std::string(); |
551 } | 582 } |
552 | 583 |
553 Feature::Availability SimpleFeature::CreateAvailability( | 584 Feature::Availability SimpleFeature::CreateAvailability( |
554 AvailabilityResult result) const { | 585 AvailabilityResult result) const { |
555 return Availability( | 586 return Availability( |
556 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), | 587 result, GetAvailabilityMessage( |
557 UNSPECIFIED_CONTEXT, | 588 result, Manifest::TYPE_UNKNOWN, GURL(), UNSPECIFIED_CONTEXT, |
558 version_info::Channel::UNKNOWN)); | 589 version_info::Channel::UNKNOWN, FeatureSessionType::UNKNOWN)); |
559 } | 590 } |
560 | 591 |
561 Feature::Availability SimpleFeature::CreateAvailability( | 592 Feature::Availability SimpleFeature::CreateAvailability( |
562 AvailabilityResult result, Manifest::Type type) const { | 593 AvailabilityResult result, Manifest::Type type) const { |
563 return Availability( | 594 return Availability( |
564 result, GetAvailabilityMessage(result, type, GURL(), UNSPECIFIED_CONTEXT, | 595 result, GetAvailabilityMessage(result, type, GURL(), UNSPECIFIED_CONTEXT, |
565 version_info::Channel::UNKNOWN)); | 596 version_info::Channel::UNKNOWN, |
| 597 FeatureSessionType::UNKNOWN)); |
566 } | 598 } |
567 | 599 |
568 Feature::Availability SimpleFeature::CreateAvailability( | 600 Feature::Availability SimpleFeature::CreateAvailability( |
569 AvailabilityResult result, | 601 AvailabilityResult result, |
570 const GURL& url) const { | 602 const GURL& url) const { |
571 return Availability( | 603 return Availability( |
572 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, url, | 604 result, GetAvailabilityMessage( |
573 UNSPECIFIED_CONTEXT, | 605 result, Manifest::TYPE_UNKNOWN, url, UNSPECIFIED_CONTEXT, |
574 version_info::Channel::UNKNOWN)); | 606 version_info::Channel::UNKNOWN, FeatureSessionType::UNKNOWN)); |
575 } | 607 } |
576 | 608 |
577 Feature::Availability SimpleFeature::CreateAvailability( | 609 Feature::Availability SimpleFeature::CreateAvailability( |
578 AvailabilityResult result, | 610 AvailabilityResult result, |
579 Context context) const { | 611 Context context) const { |
580 return Availability( | 612 return Availability( |
581 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), | 613 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), |
582 context, version_info::Channel::UNKNOWN)); | 614 context, version_info::Channel::UNKNOWN, |
| 615 FeatureSessionType::UNKNOWN)); |
583 } | 616 } |
584 | 617 |
585 Feature::Availability SimpleFeature::CreateAvailability( | 618 Feature::Availability SimpleFeature::CreateAvailability( |
586 AvailabilityResult result, | 619 AvailabilityResult result, |
587 version_info::Channel channel) const { | 620 version_info::Channel channel) const { |
588 return Availability( | 621 return Availability( |
589 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), | 622 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), |
590 UNSPECIFIED_CONTEXT, channel)); | 623 UNSPECIFIED_CONTEXT, channel, |
| 624 FeatureSessionType::UNKNOWN)); |
| 625 } |
| 626 |
| 627 Feature::Availability SimpleFeature::CreateAvailability( |
| 628 AvailabilityResult result, |
| 629 FeatureSessionType session_type) const { |
| 630 return Availability( |
| 631 result, GetAvailabilityMessage( |
| 632 result, Manifest::TYPE_UNKNOWN, GURL(), UNSPECIFIED_CONTEXT, |
| 633 version_info::Channel::UNKNOWN, session_type)); |
591 } | 634 } |
592 | 635 |
593 bool SimpleFeature::IsInternal() const { | 636 bool SimpleFeature::IsInternal() const { |
594 return is_internal_; | 637 return is_internal_; |
595 } | 638 } |
596 | 639 |
597 bool SimpleFeature::IsIdInBlacklist(const std::string& extension_id) const { | 640 bool SimpleFeature::IsIdInBlacklist(const std::string& extension_id) const { |
598 return IsIdInList(extension_id, blacklist_); | 641 return IsIdInList(extension_id, blacklist_); |
599 } | 642 } |
600 | 643 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 void SimpleFeature::set_dependencies( | 727 void SimpleFeature::set_dependencies( |
685 std::initializer_list<const char* const> dependencies) { | 728 std::initializer_list<const char* const> dependencies) { |
686 dependencies_.assign(dependencies.begin(), dependencies.end()); | 729 dependencies_.assign(dependencies.begin(), dependencies.end()); |
687 } | 730 } |
688 | 731 |
689 void SimpleFeature::set_extension_types( | 732 void SimpleFeature::set_extension_types( |
690 std::initializer_list<Manifest::Type> types) { | 733 std::initializer_list<Manifest::Type> types) { |
691 extension_types_ = types; | 734 extension_types_ = types; |
692 } | 735 } |
693 | 736 |
| 737 void SimpleFeature::set_session_types( |
| 738 std::initializer_list<FeatureSessionType> types) { |
| 739 session_types_ = types; |
| 740 } |
| 741 |
694 void SimpleFeature::set_matches( | 742 void SimpleFeature::set_matches( |
695 std::initializer_list<const char* const> matches) { | 743 std::initializer_list<const char* const> matches) { |
696 matches_.ClearPatterns(); | 744 matches_.ClearPatterns(); |
697 for (const auto* pattern : matches) | 745 for (const auto* pattern : matches) |
698 matches_.AddPattern(URLPattern(URLPattern::SCHEME_ALL, pattern)); | 746 matches_.AddPattern(URLPattern(URLPattern::SCHEME_ALL, pattern)); |
699 } | 747 } |
700 | 748 |
701 void SimpleFeature::set_platforms(std::initializer_list<Platform> platforms) { | 749 void SimpleFeature::set_platforms(std::initializer_list<Platform> platforms) { |
702 platforms_ = platforms; | 750 platforms_ = platforms; |
703 } | 751 } |
704 | 752 |
705 void SimpleFeature::set_whitelist( | 753 void SimpleFeature::set_whitelist( |
706 std::initializer_list<const char* const> whitelist) { | 754 std::initializer_list<const char* const> whitelist) { |
707 whitelist_.assign(whitelist.begin(), whitelist.end()); | 755 whitelist_.assign(whitelist.begin(), whitelist.end()); |
708 } | 756 } |
709 | 757 |
710 } // namespace extensions | 758 } // namespace extensions |
OLD | NEW |