| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "chrome/common/extensions/extension.h" | 5 #include "chrome/common/extensions/extension.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/basictypes.h" | 8 #include "base/basictypes.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 current_whitelist->push_back(*it); | 398 current_whitelist->push_back(*it); |
| 399 } | 399 } |
| 400 } | 400 } |
| 401 | 401 |
| 402 // static | 402 // static |
| 403 const Extension::ScriptingWhitelist* Extension::GetScriptingWhitelist() { | 403 const Extension::ScriptingWhitelist* Extension::GetScriptingWhitelist() { |
| 404 return ExtensionConfig::GetInstance()->whitelist(); | 404 return ExtensionConfig::GetInstance()->whitelist(); |
| 405 } | 405 } |
| 406 | 406 |
| 407 bool Extension::HasAPIPermission(APIPermission::ID permission) const { | 407 bool Extension::HasAPIPermission(APIPermission::ID permission) const { |
| 408 base::AutoLock auto_lock(runtime_data_lock_); | 408 return PermissionsData::HasAPIPermission(this, permission); |
| 409 return runtime_data_.GetActivePermissions()->HasAPIPermission(permission); | |
| 410 } | 409 } |
| 411 | 410 |
| 412 bool Extension::HasAPIPermission(const std::string& function_name) const { | 411 bool Extension::HasAPIPermission(const std::string& function_name) const { |
| 413 base::AutoLock auto_lock(runtime_data_lock_); | 412 return PermissionsData::HasAPIPermission(this, function_name); |
| 414 return runtime_data_.GetActivePermissions()-> | |
| 415 HasAccessToFunction(function_name, true); | |
| 416 } | |
| 417 | |
| 418 bool Extension::HasAPIPermissionForTab(int tab_id, | |
| 419 APIPermission::ID permission) const { | |
| 420 base::AutoLock auto_lock(runtime_data_lock_); | |
| 421 if (runtime_data_.GetActivePermissions()->HasAPIPermission(permission)) | |
| 422 return true; | |
| 423 scoped_refptr<const PermissionSet> tab_specific_permissions = | |
| 424 runtime_data_.GetTabSpecificPermissions(tab_id); | |
| 425 return tab_specific_permissions.get() && | |
| 426 tab_specific_permissions->HasAPIPermission(permission); | |
| 427 } | |
| 428 | |
| 429 bool Extension::CheckAPIPermissionWithParam(APIPermission::ID permission, | |
| 430 const APIPermission::CheckParam* param) const { | |
| 431 base::AutoLock auto_lock(runtime_data_lock_); | |
| 432 return runtime_data_.GetActivePermissions()-> | |
| 433 CheckAPIPermissionWithParam(permission, param); | |
| 434 } | |
| 435 | |
| 436 const URLPatternSet& Extension::GetEffectiveHostPermissions() const { | |
| 437 base::AutoLock auto_lock(runtime_data_lock_); | |
| 438 return runtime_data_.GetActivePermissions()->effective_hosts(); | |
| 439 } | |
| 440 | |
| 441 bool Extension::CanSilentlyIncreasePermissions() const { | |
| 442 return location() != Manifest::INTERNAL; | |
| 443 } | |
| 444 | |
| 445 bool Extension::HasHostPermission(const GURL& url) const { | |
| 446 base::AutoLock auto_lock(runtime_data_lock_); | |
| 447 return runtime_data_.GetActivePermissions()-> | |
| 448 HasExplicitAccessToOrigin(url); | |
| 449 } | |
| 450 | |
| 451 bool Extension::HasEffectiveAccessToAllHosts() const { | |
| 452 base::AutoLock auto_lock(runtime_data_lock_); | |
| 453 return runtime_data_.GetActivePermissions()->HasEffectiveAccessToAllHosts(); | |
| 454 } | |
| 455 | |
| 456 bool Extension::HasFullPermissions() const { | |
| 457 base::AutoLock auto_lock(runtime_data_lock_); | |
| 458 return runtime_data_.GetActivePermissions()->HasEffectiveFullAccess(); | |
| 459 } | |
| 460 | |
| 461 PermissionMessages Extension::GetPermissionMessages() const { | |
| 462 base::AutoLock auto_lock(runtime_data_lock_); | |
| 463 if (IsTrustedId(id())) { | |
| 464 return PermissionMessages(); | |
| 465 } else { | |
| 466 return runtime_data_.GetActivePermissions()->GetPermissionMessages( | |
| 467 GetType()); | |
| 468 } | |
| 469 } | |
| 470 | |
| 471 std::vector<string16> Extension::GetPermissionMessageStrings() const { | |
| 472 base::AutoLock auto_lock(runtime_data_lock_); | |
| 473 if (IsTrustedId(id())) | |
| 474 return std::vector<string16>(); | |
| 475 else | |
| 476 return runtime_data_.GetActivePermissions()->GetWarningMessages(GetType()); | |
| 477 } | |
| 478 | |
| 479 bool Extension::ShouldSkipPermissionWarnings() const { | |
| 480 return IsTrustedId(id()); | |
| 481 } | |
| 482 | |
| 483 void Extension::SetActivePermissions(const PermissionSet* permissions) const { | |
| 484 base::AutoLock auto_lock(runtime_data_lock_); | |
| 485 runtime_data_.SetActivePermissions(permissions); | |
| 486 } | 413 } |
| 487 | 414 |
| 488 scoped_refptr<const PermissionSet> Extension::GetActivePermissions() const { | 415 scoped_refptr<const PermissionSet> Extension::GetActivePermissions() const { |
| 489 base::AutoLock auto_lock(runtime_data_lock_); | 416 return PermissionsData::GetActivePermissions(this); |
| 490 return runtime_data_.GetActivePermissions(); | |
| 491 } | 417 } |
| 492 | 418 |
| 493 bool Extension::ShowConfigureContextMenus() const { | 419 bool Extension::ShowConfigureContextMenus() const { |
| 494 // Don't show context menu for component extensions. We might want to show | 420 // Don't show context menu for component extensions. We might want to show |
| 495 // options for component extension button but now there is no component | 421 // options for component extension button but now there is no component |
| 496 // extension with options. All other menu items like uninstall have | 422 // extension with options. All other menu items like uninstall have |
| 497 // no sense for component extensions. | 423 // no sense for component extensions. |
| 498 return location() != Manifest::COMPONENT; | 424 return location() != Manifest::COMPONENT; |
| 499 } | 425 } |
| 500 | 426 |
| 501 GURL Extension::GetFullLaunchURL() const { | 427 GURL Extension::GetFullLaunchURL() const { |
| 502 return launch_local_path().empty() ? GURL(launch_web_url()) : | 428 return launch_local_path().empty() ? GURL(launch_web_url()) : |
| 503 url().Resolve(launch_local_path()); | 429 url().Resolve(launch_local_path()); |
| 504 } | 430 } |
| 505 | 431 |
| 506 bool Extension::CanExecuteScriptOnPage(const GURL& document_url, | |
| 507 const GURL& top_frame_url, | |
| 508 int tab_id, | |
| 509 const UserScript* script, | |
| 510 std::string* error) const { | |
| 511 base::AutoLock auto_lock(runtime_data_lock_); | |
| 512 // The gallery is special-cased as a restricted URL for scripting to prevent | |
| 513 // access to special JS bindings we expose to the gallery (and avoid things | |
| 514 // like extensions removing the "report abuse" link). | |
| 515 // TODO(erikkay): This seems like the wrong test. Shouldn't we we testing | |
| 516 // against the store app extent? | |
| 517 GURL store_url(extension_urls::GetWebstoreLaunchURL()); | |
| 518 if ((document_url.host() == store_url.host()) && | |
| 519 !CanExecuteScriptEverywhere() && | |
| 520 !CommandLine::ForCurrentProcess()->HasSwitch( | |
| 521 switches::kAllowScriptingGallery)) { | |
| 522 if (error) | |
| 523 *error = errors::kCannotScriptGallery; | |
| 524 return false; | |
| 525 } | |
| 526 | |
| 527 if (!CommandLine::ForCurrentProcess()->HasSwitch( | |
| 528 switches::kExtensionsOnChromeURLs)) { | |
| 529 if (document_url.SchemeIs(chrome::kChromeUIScheme) && | |
| 530 !CanExecuteScriptEverywhere()) { | |
| 531 if (error) | |
| 532 *error = errors::kCannotAccessChromeUrl; | |
| 533 return false; | |
| 534 } | |
| 535 } | |
| 536 | |
| 537 if (top_frame_url.SchemeIs(extensions::kExtensionScheme) && | |
| 538 top_frame_url.GetOrigin() != | |
| 539 GetBaseURLFromExtensionId(id()).GetOrigin() && | |
| 540 !CanExecuteScriptEverywhere()) { | |
| 541 if (error) | |
| 542 *error = errors::kCannotAccessExtensionUrl; | |
| 543 return false; | |
| 544 } | |
| 545 | |
| 546 // If a tab ID is specified, try the tab-specific permissions. | |
| 547 if (tab_id >= 0) { | |
| 548 scoped_refptr<const PermissionSet> tab_permissions = | |
| 549 runtime_data_.GetTabSpecificPermissions(tab_id); | |
| 550 if (tab_permissions.get() && | |
| 551 tab_permissions->explicit_hosts().MatchesSecurityOrigin(document_url)) { | |
| 552 return true; | |
| 553 } | |
| 554 } | |
| 555 | |
| 556 bool can_access = false; | |
| 557 | |
| 558 if (script) { | |
| 559 // If a script is specified, use its matches. | |
| 560 can_access = script->MatchesURL(document_url); | |
| 561 } else { | |
| 562 // Otherwise, see if this extension has permission to execute script | |
| 563 // programmatically on pages. | |
| 564 can_access = runtime_data_.GetActivePermissions()-> | |
| 565 HasExplicitAccessToOrigin(document_url); | |
| 566 } | |
| 567 | |
| 568 if (!can_access && error) { | |
| 569 *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage, | |
| 570 document_url.spec()); | |
| 571 } | |
| 572 | |
| 573 return can_access; | |
| 574 } | |
| 575 | |
| 576 bool Extension::CanExecuteScriptEverywhere() const { | |
| 577 if (location() == Manifest::COMPONENT) | |
| 578 return true; | |
| 579 | |
| 580 ScriptingWhitelist* whitelist = ExtensionConfig::GetInstance()->whitelist(); | |
| 581 | |
| 582 for (ScriptingWhitelist::const_iterator it = whitelist->begin(); | |
| 583 it != whitelist->end(); ++it) { | |
| 584 if (id() == *it) { | |
| 585 return true; | |
| 586 } | |
| 587 } | |
| 588 | |
| 589 return false; | |
| 590 } | |
| 591 | |
| 592 bool Extension::CanCaptureVisiblePage(const GURL& page_url, | |
| 593 int tab_id, | |
| 594 std::string* error) const { | |
| 595 if (tab_id >= 0) { | |
| 596 scoped_refptr<const PermissionSet> tab_permissions = | |
| 597 GetTabSpecificPermissions(tab_id); | |
| 598 if (tab_permissions.get() && | |
| 599 tab_permissions->explicit_hosts().MatchesSecurityOrigin(page_url)) { | |
| 600 return true; | |
| 601 } | |
| 602 } | |
| 603 | |
| 604 if (HasHostPermission(page_url) || page_url.GetOrigin() == url()) | |
| 605 return true; | |
| 606 | |
| 607 if (error) { | |
| 608 *error = ErrorUtils::FormatErrorMessage(errors::kCannotAccessPage, | |
| 609 page_url.spec()); | |
| 610 } | |
| 611 return false; | |
| 612 } | |
| 613 | |
| 614 bool Extension::UpdatesFromGallery() const { | 432 bool Extension::UpdatesFromGallery() const { |
| 615 return extension_urls::IsWebstoreUpdateUrl(ManifestURL::GetUpdateURL(this)); | 433 return extension_urls::IsWebstoreUpdateUrl(ManifestURL::GetUpdateURL(this)); |
| 616 } | 434 } |
| 617 | 435 |
| 618 bool Extension::OverlapsWithOrigin(const GURL& origin) const { | 436 bool Extension::OverlapsWithOrigin(const GURL& origin) const { |
| 619 if (url() == origin) | 437 if (url() == origin) |
| 620 return true; | 438 return true; |
| 621 | 439 |
| 622 if (web_extent().is_empty()) | 440 if (web_extent().is_empty()) |
| 623 return false; | 441 return false; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 // show packaged apps and platform apps because there are some pieces of | 543 // show packaged apps and platform apps because there are some pieces of |
| 726 // functionality that are only available in chrome://extensions/ but which | 544 // functionality that are only available in chrome://extensions/ but which |
| 727 // are needed for packaged and platform apps. For example, inspecting | 545 // are needed for packaged and platform apps. For example, inspecting |
| 728 // background pages. See http://crbug.com/116134. | 546 // background pages. See http://crbug.com/116134. |
| 729 if (is_hosted_app()) | 547 if (is_hosted_app()) |
| 730 return false; | 548 return false; |
| 731 | 549 |
| 732 return true; | 550 return true; |
| 733 } | 551 } |
| 734 | 552 |
| 735 scoped_refptr<const PermissionSet> Extension::GetTabSpecificPermissions( | |
| 736 int tab_id) const { | |
| 737 base::AutoLock auto_lock(runtime_data_lock_); | |
| 738 return runtime_data_.GetTabSpecificPermissions(tab_id); | |
| 739 } | |
| 740 | |
| 741 void Extension::UpdateTabSpecificPermissions( | |
| 742 int tab_id, | |
| 743 scoped_refptr<const PermissionSet> permissions) const { | |
| 744 base::AutoLock auto_lock(runtime_data_lock_); | |
| 745 runtime_data_.UpdateTabSpecificPermissions(tab_id, permissions); | |
| 746 } | |
| 747 | |
| 748 void Extension::ClearTabSpecificPermissions(int tab_id) const { | |
| 749 base::AutoLock auto_lock(runtime_data_lock_); | |
| 750 runtime_data_.ClearTabSpecificPermissions(tab_id); | |
| 751 } | |
| 752 | |
| 753 Extension::ManifestData* Extension::GetManifestData(const std::string& key) | 553 Extension::ManifestData* Extension::GetManifestData(const std::string& key) |
| 754 const { | 554 const { |
| 755 DCHECK(finished_parsing_manifest_ || thread_checker_.CalledOnValidThread()); | 555 DCHECK(finished_parsing_manifest_ || thread_checker_.CalledOnValidThread()); |
| 756 ManifestDataMap::const_iterator iter = manifest_data_.find(key); | 556 ManifestDataMap::const_iterator iter = manifest_data_.find(key); |
| 757 if (iter != manifest_data_.end()) | 557 if (iter != manifest_data_.end()) |
| 758 return iter->second.get(); | 558 return iter->second.get(); |
| 759 return NULL; | 559 return NULL; |
| 760 } | 560 } |
| 761 | 561 |
| 762 void Extension::SetManifestData(const std::string& key, | 562 void Extension::SetManifestData(const std::string& key, |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 } | 613 } |
| 814 | 614 |
| 815 void Extension::AddWebExtentPattern(const URLPattern& pattern) { | 615 void Extension::AddWebExtentPattern(const URLPattern& pattern) { |
| 816 extent_.AddPattern(pattern); | 616 extent_.AddPattern(pattern); |
| 817 } | 617 } |
| 818 | 618 |
| 819 bool Extension::is_theme() const { | 619 bool Extension::is_theme() const { |
| 820 return manifest()->is_theme(); | 620 return manifest()->is_theme(); |
| 821 } | 621 } |
| 822 | 622 |
| 823 Extension::RuntimeData::RuntimeData() {} | |
| 824 Extension::RuntimeData::RuntimeData(const PermissionSet* active) | |
| 825 : active_permissions_(active) {} | |
| 826 Extension::RuntimeData::~RuntimeData() {} | |
| 827 | |
| 828 void Extension::RuntimeData::SetActivePermissions( | |
| 829 const PermissionSet* active) { | |
| 830 active_permissions_ = active; | |
| 831 } | |
| 832 | |
| 833 scoped_refptr<const PermissionSet> | |
| 834 Extension::RuntimeData::GetActivePermissions() const { | |
| 835 return active_permissions_; | |
| 836 } | |
| 837 | |
| 838 scoped_refptr<const PermissionSet> | |
| 839 Extension::RuntimeData::GetTabSpecificPermissions(int tab_id) const { | |
| 840 CHECK_GE(tab_id, 0); | |
| 841 TabPermissionsMap::const_iterator it = tab_specific_permissions_.find(tab_id); | |
| 842 return (it != tab_specific_permissions_.end()) ? it->second : NULL; | |
| 843 } | |
| 844 | |
| 845 void Extension::RuntimeData::UpdateTabSpecificPermissions( | |
| 846 int tab_id, | |
| 847 scoped_refptr<const PermissionSet> permissions) { | |
| 848 CHECK_GE(tab_id, 0); | |
| 849 if (tab_specific_permissions_.count(tab_id)) { | |
| 850 tab_specific_permissions_[tab_id] = PermissionSet::CreateUnion( | |
| 851 tab_specific_permissions_[tab_id], | |
| 852 permissions.get()); | |
| 853 } else { | |
| 854 tab_specific_permissions_[tab_id] = permissions; | |
| 855 } | |
| 856 } | |
| 857 | |
| 858 void Extension::RuntimeData::ClearTabSpecificPermissions(int tab_id) { | |
| 859 CHECK_GE(tab_id, 0); | |
| 860 tab_specific_permissions_.erase(tab_id); | |
| 861 } | |
| 862 | |
| 863 // static | 623 // static |
| 864 bool Extension::InitExtensionID(extensions::Manifest* manifest, | 624 bool Extension::InitExtensionID(extensions::Manifest* manifest, |
| 865 const base::FilePath& path, | 625 const base::FilePath& path, |
| 866 const std::string& explicit_id, | 626 const std::string& explicit_id, |
| 867 int creation_flags, | 627 int creation_flags, |
| 868 string16* error) { | 628 string16* error) { |
| 869 if (!explicit_id.empty()) { | 629 if (!explicit_id.empty()) { |
| 870 manifest->set_extension_id(explicit_id); | 630 manifest->set_extension_id(explicit_id); |
| 871 return true; | 631 return true; |
| 872 } | 632 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 894 std::string extension_id = id_util::GenerateIdForPath(path); | 654 std::string extension_id = id_util::GenerateIdForPath(path); |
| 895 if (extension_id.empty()) { | 655 if (extension_id.empty()) { |
| 896 NOTREACHED() << "Could not create ID from path."; | 656 NOTREACHED() << "Could not create ID from path."; |
| 897 return false; | 657 return false; |
| 898 } | 658 } |
| 899 manifest->set_extension_id(extension_id); | 659 manifest->set_extension_id(extension_id); |
| 900 return true; | 660 return true; |
| 901 } | 661 } |
| 902 } | 662 } |
| 903 | 663 |
| 904 // static | |
| 905 bool Extension::IsTrustedId(const std::string& id) { | |
| 906 // See http://b/4946060 for more details. | |
| 907 return id == std::string("nckgahadagoaajjgafhacjanaoiihapd"); | |
| 908 } | |
| 909 | |
| 910 Extension::Extension(const base::FilePath& path, | 664 Extension::Extension(const base::FilePath& path, |
| 911 scoped_ptr<extensions::Manifest> manifest) | 665 scoped_ptr<extensions::Manifest> manifest) |
| 912 : manifest_version_(0), | 666 : manifest_version_(0), |
| 913 converted_from_user_script_(false), | 667 converted_from_user_script_(false), |
| 914 manifest_(manifest.release()), | 668 manifest_(manifest.release()), |
| 915 finished_parsing_manifest_(false), | 669 finished_parsing_manifest_(false), |
| 916 launch_container_(extension_misc::LAUNCH_TAB), | 670 launch_container_(extension_misc::LAUNCH_TAB), |
| 917 launch_width_(0), | 671 launch_width_(0), |
| 918 launch_height_(0), | 672 launch_height_(0), |
| 919 display_in_launcher_(true), | 673 display_in_launcher_(true), |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 956 if (is_app() && !LoadAppFeatures(error)) | 710 if (is_app() && !LoadAppFeatures(error)) |
| 957 return false; | 711 return false; |
| 958 | 712 |
| 959 permissions_data_.reset(new PermissionsData); | 713 permissions_data_.reset(new PermissionsData); |
| 960 if (!permissions_data_->ParsePermissions(this, error)) | 714 if (!permissions_data_->ParsePermissions(this, error)) |
| 961 return false; | 715 return false; |
| 962 | 716 |
| 963 if (!LoadSharedFeatures(error)) | 717 if (!LoadSharedFeatures(error)) |
| 964 return false; | 718 return false; |
| 965 | 719 |
| 966 if (manifest_->HasKey(keys::kConvertedFromUserScript)) | 720 if (manifest_->HasKey(keys::kConvertedFromUserScript)) { |
| 967 manifest_->GetBoolean(keys::kConvertedFromUserScript, | 721 manifest_->GetBoolean(keys::kConvertedFromUserScript, |
| 968 &converted_from_user_script_); | 722 &converted_from_user_script_); |
| 723 } |
| 969 | 724 |
| 970 if (HasMultipleUISurfaces()) { | 725 if (HasMultipleUISurfaces()) { |
| 971 *error = ASCIIToUTF16(errors::kOneUISurfaceOnly); | 726 *error = ASCIIToUTF16(errors::kOneUISurfaceOnly); |
| 972 return false; | 727 return false; |
| 973 } | 728 } |
| 974 | 729 |
| 975 finished_parsing_manifest_ = true; | 730 finished_parsing_manifest_ = true; |
| 976 | 731 |
| 977 permissions_data_->FinalizePermissions(this); | 732 permissions_data_->FinalizePermissions(this); |
| 978 | 733 |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1484 | 1239 |
| 1485 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( | 1240 UpdatedExtensionPermissionsInfo::UpdatedExtensionPermissionsInfo( |
| 1486 const Extension* extension, | 1241 const Extension* extension, |
| 1487 const PermissionSet* permissions, | 1242 const PermissionSet* permissions, |
| 1488 Reason reason) | 1243 Reason reason) |
| 1489 : reason(reason), | 1244 : reason(reason), |
| 1490 extension(extension), | 1245 extension(extension), |
| 1491 permissions(permissions) {} | 1246 permissions(permissions) {} |
| 1492 | 1247 |
| 1493 } // namespace extensions | 1248 } // namespace extensions |
| OLD | NEW |