Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(857)

Side by Side Diff: extensions/common/features/simple_feature.cc

Issue 2255613003: Introduce session type parameter to extension features (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Introduce session type parameter to extension features Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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::INITIAL:
213 return "user-less";
214 case FeatureSessionType::UNKNOWN:
215 return "unknown";
216 case FeatureSessionType::KIOSK:
217 return "kiosk app";
218 case FeatureSessionType::REGULAR:
219 return "regular user";
220 default:
221 return "";
222 }
223 }
224
210 // Gets a human-readable list of the display names (pluralized, comma separated 225 // 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|. 226 // with the "and" in the correct place) for each of |enum_types|.
212 template <typename EnumType> 227 template <typename EnumType>
213 std::string ListDisplayNames(const std::vector<EnumType>& enum_types) { 228 std::string ListDisplayNames(const std::vector<EnumType>& enum_types) {
214 std::string display_name_list; 229 std::string display_name_list;
215 for (size_t i = 0; i < enum_types.size(); ++i) { 230 for (size_t i = 0; i < enum_types.size(); ++i) {
216 // Pluralize type name. 231 // Pluralize type name.
217 display_name_list += GetDisplayName(enum_types[i]) + "s"; 232 display_name_list += GetDisplayName(enum_types[i]) + "s";
218 // Comma-separate entries, with an Oxford comma if there is more than 2 233 // Comma-separate entries, with an Oxford comma if there is more than 2
219 // total entries. 234 // total entries.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 platforms["chromeos"] = Feature::CHROMEOS_PLATFORM; 305 platforms["chromeos"] = Feature::CHROMEOS_PLATFORM;
291 platforms["linux"] = Feature::LINUX_PLATFORM; 306 platforms["linux"] = Feature::LINUX_PLATFORM;
292 platforms["mac"] = Feature::MACOSX_PLATFORM; 307 platforms["mac"] = Feature::MACOSX_PLATFORM;
293 platforms["win"] = Feature::WIN_PLATFORM; 308 platforms["win"] = Feature::WIN_PLATFORM;
294 309
295 channels["trunk"] = version_info::Channel::UNKNOWN; 310 channels["trunk"] = version_info::Channel::UNKNOWN;
296 channels["canary"] = version_info::Channel::CANARY; 311 channels["canary"] = version_info::Channel::CANARY;
297 channels["dev"] = version_info::Channel::DEV; 312 channels["dev"] = version_info::Channel::DEV;
298 channels["beta"] = version_info::Channel::BETA; 313 channels["beta"] = version_info::Channel::BETA;
299 channels["stable"] = version_info::Channel::STABLE; 314 channels["stable"] = version_info::Channel::STABLE;
315
316 session_types["regular"] = FeatureSessionType::REGULAR;
317 session_types["kiosk"] = FeatureSessionType::KIOSK;
300 } 318 }
301 319
302 std::map<std::string, Manifest::Type> extension_types; 320 std::map<std::string, Manifest::Type> extension_types;
303 std::map<std::string, Feature::Context> contexts; 321 std::map<std::string, Feature::Context> contexts;
304 std::map<std::string, SimpleFeature::Location> locations; 322 std::map<std::string, SimpleFeature::Location> locations;
305 std::map<std::string, Feature::Platform> platforms; 323 std::map<std::string, Feature::Platform> platforms;
306 std::map<std::string, version_info::Channel> channels; 324 std::map<std::string, version_info::Channel> channels;
325 std::map<std::string, FeatureSessionType> session_types;
307 }; 326 };
308 327
309 SimpleFeature::SimpleFeature() 328 SimpleFeature::SimpleFeature()
310 : location_(UNSPECIFIED_LOCATION), 329 : session_types_set_(false),
330 location_(UNSPECIFIED_LOCATION),
311 min_manifest_version_(0), 331 min_manifest_version_(0),
312 max_manifest_version_(0), 332 max_manifest_version_(0),
313 component_extensions_auto_granted_(true), 333 component_extensions_auto_granted_(true),
314 is_internal_(false) {} 334 is_internal_(false) {}
315 335
316 SimpleFeature::~SimpleFeature() {} 336 SimpleFeature::~SimpleFeature() {}
317 337
318 void SimpleFeature::Parse(const base::DictionaryValue* dictionary) { 338 void SimpleFeature::Parse(const base::DictionaryValue* dictionary) {
Devlin 2016/08/23 20:49:06 This badly needs to be rebased.
319 static base::LazyInstance<SimpleFeature::Mappings> mappings = 339 static base::LazyInstance<SimpleFeature::Mappings> mappings =
320 LAZY_INSTANCE_INITIALIZER; 340 LAZY_INSTANCE_INITIALIZER;
321 341
322 no_parent_ = false; 342 no_parent_ = false;
323 for (base::DictionaryValue::Iterator it(*dictionary); 343 for (base::DictionaryValue::Iterator it(*dictionary);
324 !it.IsAtEnd(); 344 !it.IsAtEnd();
325 it.Advance()) { 345 it.Advance()) {
326 const std::string& key = it.key(); 346 const std::string& key = it.key();
327 const base::Value* value = &it.value(); 347 const base::Value* value = &it.value();
328 if (key == "matches") { 348 if (key == "matches") {
329 ParseURLPatterns(dictionary, "matches", &matches_); 349 ParseURLPatterns(dictionary, "matches", &matches_);
330 } else if (key == "blacklist") { 350 } else if (key == "blacklist") {
331 ParseVector(value, &blacklist_); 351 ParseVector(value, &blacklist_);
332 } else if (key == "whitelist") { 352 } else if (key == "whitelist") {
333 ParseVector(value, &whitelist_); 353 ParseVector(value, &whitelist_);
334 } else if (key == "dependencies") { 354 } else if (key == "dependencies") {
335 ParseVector(value, &dependencies_); 355 ParseVector(value, &dependencies_);
336 } else if (key == "extension_types") { 356 } else if (key == "extension_types") {
337 ParseEnumVector<Manifest::Type>(value, &extension_types_, 357 ParseEnumVector<Manifest::Type>(value, &extension_types_,
338 mappings.Get().extension_types); 358 mappings.Get().extension_types);
339 } else if (key == "contexts") { 359 } else if (key == "contexts") {
340 ParseEnumVector<Context>(value, &contexts_, 360 ParseEnumVector<Context>(value, &contexts_,
341 mappings.Get().contexts); 361 mappings.Get().contexts);
362 } else if (key == "session_types") {
363 session_types_set_ = true;
364 ParseEnumVector<FeatureSessionType>(value, &session_types_,
365 mappings.Get().session_types);
342 } else if (key == "location") { 366 } else if (key == "location") {
343 ParseEnum<Location>(value, &location_, mappings.Get().locations); 367 ParseEnum<Location>(value, &location_, mappings.Get().locations);
344 } else if (key == "platforms") { 368 } else if (key == "platforms") {
345 ParseEnumVector<Platform>(value, &platforms_, 369 ParseEnumVector<Platform>(value, &platforms_,
346 mappings.Get().platforms); 370 mappings.Get().platforms);
347 } else if (key == "min_manifest_version") { 371 } else if (key == "min_manifest_version") {
348 dictionary->GetInteger("min_manifest_version", &min_manifest_version_); 372 dictionary->GetInteger("min_manifest_version", &min_manifest_version_);
349 } else if (key == "max_manifest_version") { 373 } else if (key == "max_manifest_version") {
350 dictionary->GetInteger("max_manifest_version", &max_manifest_version_); 374 dictionary->GetInteger("max_manifest_version", &max_manifest_version_);
351 } else if (key == "noparent") { 375 } else if (key == "noparent") {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 return CreateAvailability(INVALID_MAX_MANIFEST_VERSION, type); 455 return CreateAvailability(INVALID_MAX_MANIFEST_VERSION, type);
432 456
433 if (!command_line_switch_.empty() && 457 if (!command_line_switch_.empty() &&
434 !IsCommandLineSwitchEnabled(command_line_switch_)) { 458 !IsCommandLineSwitchEnabled(command_line_switch_)) {
435 return CreateAvailability(MISSING_COMMAND_LINE_SWITCH, type); 459 return CreateAvailability(MISSING_COMMAND_LINE_SWITCH, type);
436 } 460 }
437 461
438 if (channel_ && *channel_ < GetCurrentChannel()) 462 if (channel_ && *channel_ < GetCurrentChannel())
439 return CreateAvailability(UNSUPPORTED_CHANNEL, *channel_); 463 return CreateAvailability(UNSUPPORTED_CHANNEL, *channel_);
440 464
465 FeatureSessionType session = GetCurrentFeatureSessionType();
466 if (session_types_set_ && !base::ContainsValue(session_types_, session)) {
467 return CreateAvailability(INVALID_SESSION_TYPE, session);
468 }
469
441 return CheckDependencies(base::Bind(&IsAvailableToManifestForBind, 470 return CheckDependencies(base::Bind(&IsAvailableToManifestForBind,
442 extension_id, 471 extension_id,
443 type, 472 type,
444 location, 473 location,
445 manifest_version, 474 manifest_version,
446 platform)); 475 platform));
447 } 476 }
448 477
449 Feature::Availability SimpleFeature::IsAvailableToContext( 478 Feature::Availability SimpleFeature::IsAvailableToContext(
450 const Extension* extension, 479 const Extension* extension,
451 SimpleFeature::Context context, 480 Feature::Context context,
452 const GURL& url, 481 const GURL& url,
453 SimpleFeature::Platform platform) const { 482 SimpleFeature::Platform platform) const {
454 if (extension) { 483 if (extension) {
455 Availability result = IsAvailableToManifest(extension->id(), 484 Availability result = IsAvailableToManifest(extension->id(),
456 extension->GetType(), 485 extension->GetType(),
457 extension->location(), 486 extension->location(),
458 extension->manifest_version(), 487 extension->manifest_version(),
459 platform); 488 platform);
460 if (!result.is_available()) 489 if (!result.is_available())
461 return result; 490 return result;
462 } 491 }
463 492
464 // TODO(lazyboy): This isn't quite right for Extension Service Worker 493 // TODO(lazyboy): This isn't quite right for Extension Service Worker
465 // extension API calls, since there's no guarantee that the extension is 494 // extension API calls, since there's no guarantee that the extension is
466 // "active" in current renderer process when the API permission check is 495 // "active" in current renderer process when the API permission check is
467 // done. 496 // done.
468 if (!contexts_.empty() && !base::ContainsValue(contexts_, context)) 497 if (!contexts_.empty() && !base::ContainsValue(contexts_, context))
469 return CreateAvailability(INVALID_CONTEXT, context); 498 return CreateAvailability(INVALID_CONTEXT, context);
470 499
471 // TODO(kalman): Consider checking |matches_| regardless of context type. 500 // TODO(kalman): Consider checking |matches_| regardless of context type.
472 // Fewer surprises, and if the feature configuration wants to isolate 501 // Fewer surprises, and if the feature configuration wants to isolate
473 // "matches" from say "blessed_extension" then they can use complex features. 502 // "matches" from say "blessed_extension" then they can use complex features.
474 if ((context == WEB_PAGE_CONTEXT || context == WEBUI_CONTEXT) && 503 if ((context == WEB_PAGE_CONTEXT || context == WEBUI_CONTEXT) &&
475 !matches_.MatchesURL(url)) { 504 !matches_.MatchesURL(url)) {
476 return CreateAvailability(INVALID_URL, url); 505 return CreateAvailability(INVALID_URL, url);
477 } 506 }
478 507
508 FeatureSessionType session = GetCurrentFeatureSessionType();
509 if (session_types_set_ && !base::ContainsValue(session_types_, session)) {
510 return CreateAvailability(INVALID_SESSION_TYPE, session);
511 }
512
479 // TODO(kalman): Assert that if the context was a webpage or WebUI context 513 // TODO(kalman): Assert that if the context was a webpage or WebUI context
480 // then at some point a "matches" restriction was checked. 514 // then at some point a "matches" restriction was checked.
481 return CheckDependencies(base::Bind( 515 return CheckDependencies(base::Bind(&IsAvailableToContextForBind, extension,
482 &IsAvailableToContextForBind, extension, context, url, platform)); 516 context, url, platform));
483 } 517 }
484 518
485 std::string SimpleFeature::GetAvailabilityMessage( 519 std::string SimpleFeature::GetAvailabilityMessage(
486 AvailabilityResult result, 520 AvailabilityResult result,
487 Manifest::Type type, 521 Manifest::Type type,
488 const GURL& url, 522 const GURL& url,
489 Context context, 523 Context context,
490 version_info::Channel channel) const { 524 version_info::Channel channel,
525 FeatureSessionType session_type) const {
491 switch (result) { 526 switch (result) {
492 case IS_AVAILABLE: 527 case IS_AVAILABLE:
493 return std::string(); 528 return std::string();
494 case NOT_FOUND_IN_WHITELIST: 529 case NOT_FOUND_IN_WHITELIST:
495 case FOUND_IN_BLACKLIST: 530 case FOUND_IN_BLACKLIST:
496 return base::StringPrintf( 531 return base::StringPrintf(
497 "'%s' is not allowed for specified extension ID.", 532 "'%s' is not allowed for specified extension ID.",
498 name().c_str()); 533 name().c_str());
499 case INVALID_URL: 534 case INVALID_URL:
500 return base::StringPrintf("'%s' is not allowed on %s.", 535 return base::StringPrintf("'%s' is not allowed on %s.",
(...skipping 23 matching lines...) Expand all
524 case INVALID_MIN_MANIFEST_VERSION: 559 case INVALID_MIN_MANIFEST_VERSION:
525 return base::StringPrintf( 560 return base::StringPrintf(
526 "'%s' requires manifest version of at least %d.", 561 "'%s' requires manifest version of at least %d.",
527 name().c_str(), 562 name().c_str(),
528 min_manifest_version_); 563 min_manifest_version_);
529 case INVALID_MAX_MANIFEST_VERSION: 564 case INVALID_MAX_MANIFEST_VERSION:
530 return base::StringPrintf( 565 return base::StringPrintf(
531 "'%s' requires manifest version of %d or lower.", 566 "'%s' requires manifest version of %d or lower.",
532 name().c_str(), 567 name().c_str(),
533 max_manifest_version_); 568 max_manifest_version_);
569 case INVALID_SESSION_TYPE:
570 return base::StringPrintf(
571 "'%s' is not allowed in %s session", name().c_str(),
Devlin 2016/08/23 20:49:06 Let's structure this in the fashion of the other w
tbarzic 2016/09/08 18:48:55 Isn't it already (except of missing trailing .)?
Devlin 2016/09/12 22:33:07 Follow the style of e.g. invalid context errors so
tbarzic 2016/09/12 23:05:10 Done.
572 GetSessionTypeDisplayName(session_type).c_str());
534 case NOT_PRESENT: 573 case NOT_PRESENT:
535 return base::StringPrintf( 574 return base::StringPrintf(
536 "'%s' requires a different Feature that is not present.", 575 "'%s' requires a different Feature that is not present.",
537 name().c_str()); 576 name().c_str());
538 case UNSUPPORTED_CHANNEL: 577 case UNSUPPORTED_CHANNEL:
539 return base::StringPrintf( 578 return base::StringPrintf(
540 "'%s' requires %s channel or newer, but this is the %s channel.", 579 "'%s' requires %s channel or newer, but this is the %s channel.",
541 name().c_str(), GetDisplayName(channel).c_str(), 580 name().c_str(), GetDisplayName(channel).c_str(),
542 GetDisplayName(GetCurrentChannel()).c_str()); 581 GetDisplayName(GetCurrentChannel()).c_str());
543 case MISSING_COMMAND_LINE_SWITCH: 582 case MISSING_COMMAND_LINE_SWITCH:
544 return base::StringPrintf( 583 return base::StringPrintf(
545 "'%s' requires the '%s' command line switch to be enabled.", 584 "'%s' requires the '%s' command line switch to be enabled.",
546 name().c_str(), command_line_switch_.c_str()); 585 name().c_str(), command_line_switch_.c_str());
547 } 586 }
548 587
549 NOTREACHED(); 588 NOTREACHED();
550 return std::string(); 589 return std::string();
551 } 590 }
552 591
553 Feature::Availability SimpleFeature::CreateAvailability( 592 Feature::Availability SimpleFeature::CreateAvailability(
554 AvailabilityResult result) const { 593 AvailabilityResult result) const {
555 return Availability( 594 return Availability(
556 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), 595 result, GetAvailabilityMessage(
557 UNSPECIFIED_CONTEXT, 596 result, Manifest::TYPE_UNKNOWN, GURL(), UNSPECIFIED_CONTEXT,
558 version_info::Channel::UNKNOWN)); 597 version_info::Channel::UNKNOWN, FeatureSessionType::UNKNOWN));
559 } 598 }
560 599
561 Feature::Availability SimpleFeature::CreateAvailability( 600 Feature::Availability SimpleFeature::CreateAvailability(
562 AvailabilityResult result, Manifest::Type type) const { 601 AvailabilityResult result, Manifest::Type type) const {
563 return Availability( 602 return Availability(
564 result, GetAvailabilityMessage(result, type, GURL(), UNSPECIFIED_CONTEXT, 603 result, GetAvailabilityMessage(result, type, GURL(), UNSPECIFIED_CONTEXT,
565 version_info::Channel::UNKNOWN)); 604 version_info::Channel::UNKNOWN,
605 FeatureSessionType::UNKNOWN));
566 } 606 }
567 607
568 Feature::Availability SimpleFeature::CreateAvailability( 608 Feature::Availability SimpleFeature::CreateAvailability(
569 AvailabilityResult result, 609 AvailabilityResult result,
570 const GURL& url) const { 610 const GURL& url) const {
571 return Availability( 611 return Availability(
572 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, url, 612 result, GetAvailabilityMessage(
573 UNSPECIFIED_CONTEXT, 613 result, Manifest::TYPE_UNKNOWN, url, UNSPECIFIED_CONTEXT,
574 version_info::Channel::UNKNOWN)); 614 version_info::Channel::UNKNOWN, FeatureSessionType::UNKNOWN));
575 } 615 }
576 616
577 Feature::Availability SimpleFeature::CreateAvailability( 617 Feature::Availability SimpleFeature::CreateAvailability(
578 AvailabilityResult result, 618 AvailabilityResult result,
579 Context context) const { 619 Context context) const {
580 return Availability( 620 return Availability(
581 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), 621 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(),
582 context, version_info::Channel::UNKNOWN)); 622 context, version_info::Channel::UNKNOWN,
623 FeatureSessionType::UNKNOWN));
583 } 624 }
584 625
585 Feature::Availability SimpleFeature::CreateAvailability( 626 Feature::Availability SimpleFeature::CreateAvailability(
586 AvailabilityResult result, 627 AvailabilityResult result,
587 version_info::Channel channel) const { 628 version_info::Channel channel) const {
588 return Availability( 629 return Availability(
589 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(), 630 result, GetAvailabilityMessage(result, Manifest::TYPE_UNKNOWN, GURL(),
590 UNSPECIFIED_CONTEXT, channel)); 631 UNSPECIFIED_CONTEXT, channel,
632 FeatureSessionType::UNKNOWN));
633 }
634
635 Feature::Availability SimpleFeature::CreateAvailability(
636 AvailabilityResult result,
637 FeatureSessionType session_type) const {
638 return Availability(
639 result, GetAvailabilityMessage(
640 result, Manifest::TYPE_UNKNOWN, GURL(), UNSPECIFIED_CONTEXT,
641 version_info::Channel::UNKNOWN, session_type));
591 } 642 }
592 643
593 bool SimpleFeature::IsInternal() const { 644 bool SimpleFeature::IsInternal() const {
594 return is_internal_; 645 return is_internal_;
595 } 646 }
596 647
597 bool SimpleFeature::IsIdInBlacklist(const std::string& extension_id) const { 648 bool SimpleFeature::IsIdInBlacklist(const std::string& extension_id) const {
598 return IsIdInList(extension_id, blacklist_); 649 return IsIdInList(extension_id, blacklist_);
599 } 650 }
600 651
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
684 void SimpleFeature::set_dependencies( 735 void SimpleFeature::set_dependencies(
685 std::initializer_list<const char* const> dependencies) { 736 std::initializer_list<const char* const> dependencies) {
686 dependencies_.assign(dependencies.begin(), dependencies.end()); 737 dependencies_.assign(dependencies.begin(), dependencies.end());
687 } 738 }
688 739
689 void SimpleFeature::set_extension_types( 740 void SimpleFeature::set_extension_types(
690 std::initializer_list<Manifest::Type> types) { 741 std::initializer_list<Manifest::Type> types) {
691 extension_types_ = types; 742 extension_types_ = types;
692 } 743 }
693 744
745 void SimpleFeature::set_session_types(
746 std::initializer_list<FeatureSessionType> types) {
747 session_types_ = types;
748 session_types_set_ = true;
749 }
750
694 void SimpleFeature::set_matches( 751 void SimpleFeature::set_matches(
695 std::initializer_list<const char* const> matches) { 752 std::initializer_list<const char* const> matches) {
696 matches_.ClearPatterns(); 753 matches_.ClearPatterns();
697 for (const auto* pattern : matches) 754 for (const auto* pattern : matches)
698 matches_.AddPattern(URLPattern(URLPattern::SCHEME_ALL, pattern)); 755 matches_.AddPattern(URLPattern(URLPattern::SCHEME_ALL, pattern));
699 } 756 }
700 757
701 void SimpleFeature::set_platforms(std::initializer_list<Platform> platforms) { 758 void SimpleFeature::set_platforms(std::initializer_list<Platform> platforms) {
702 platforms_ = platforms; 759 platforms_ = platforms;
703 } 760 }
704 761
705 void SimpleFeature::set_whitelist( 762 void SimpleFeature::set_whitelist(
706 std::initializer_list<const char* const> whitelist) { 763 std::initializer_list<const char* const> whitelist) {
707 whitelist_.assign(whitelist.begin(), whitelist.end()); 764 whitelist_.assign(whitelist.begin(), whitelist.end());
708 } 765 }
709 766
710 } // namespace extensions 767 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698