| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/browser/extensions/extensions_service.h" | 5 #include "chrome/browser/extensions/extensions_service.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/file_util.h" | 11 #include "base/file_util.h" |
| 12 #include "base/histogram.h" | 12 #include "base/histogram.h" |
| 13 #include "base/stl_util-inl.h" | 13 #include "base/stl_util-inl.h" |
| 14 #include "base/string16.h" | 14 #include "base/string16.h" |
| 15 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
| 16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 17 #include "base/stringprintf.h" | 17 #include "base/stringprintf.h" |
| 18 #include "base/time.h" | 18 #include "base/time.h" |
| 19 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
| 20 #include "base/values.h" | 20 #include "base/values.h" |
| 21 #include "base/version.h" | 21 #include "base/version.h" |
| 22 #include "chrome/browser/browser_process.h" | 22 #include "chrome/browser/browser_process.h" |
| 23 #include "chrome/browser/chrome_thread.h" | 23 #include "chrome/browser/chrome_thread.h" |
| 24 #include "chrome/browser/debugger/devtools_manager.h" | 24 #include "chrome/browser/debugger/devtools_manager.h" |
| 25 #include "chrome/browser/extensions/crx_installer.h" | 25 #include "chrome/browser/extensions/crx_installer.h" |
| 26 #include "chrome/browser/extensions/default_apps.h" |
| 26 #include "chrome/browser/extensions/extension_accessibility_api.h" | 27 #include "chrome/browser/extensions/extension_accessibility_api.h" |
| 27 #include "chrome/browser/extensions/extension_bookmarks_module.h" | 28 #include "chrome/browser/extensions/extension_bookmarks_module.h" |
| 28 #include "chrome/browser/extensions/extension_browser_event_router.h" | 29 #include "chrome/browser/extensions/extension_browser_event_router.h" |
| 29 #include "chrome/browser/extensions/extension_cookies_api.h" | 30 #include "chrome/browser/extensions/extension_cookies_api.h" |
| 30 #include "chrome/browser/extensions/extension_data_deleter.h" | 31 #include "chrome/browser/extensions/extension_data_deleter.h" |
| 31 #include "chrome/browser/extensions/extension_dom_ui.h" | 32 #include "chrome/browser/extensions/extension_dom_ui.h" |
| 32 #include "chrome/browser/extensions/extension_error_reporter.h" | 33 #include "chrome/browser/extensions/extension_error_reporter.h" |
| 33 #include "chrome/browser/extensions/extension_history_api.h" | 34 #include "chrome/browser/extensions/extension_history_api.h" |
| 34 #include "chrome/browser/extensions/extension_host.h" | 35 #include "chrome/browser/extensions/extension_host.h" |
| 35 #include "chrome/browser/extensions/extension_management_api.h" | 36 #include "chrome/browser/extensions/extension_management_api.h" |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 } | 123 } |
| 123 | 124 |
| 124 } // namespace | 125 } // namespace |
| 125 | 126 |
| 126 PendingExtensionInfo::PendingExtensionInfo( | 127 PendingExtensionInfo::PendingExtensionInfo( |
| 127 const GURL& update_url, | 128 const GURL& update_url, |
| 128 PendingExtensionInfo::ExpectedCrxType expected_crx_type, | 129 PendingExtensionInfo::ExpectedCrxType expected_crx_type, |
| 129 bool is_from_sync, | 130 bool is_from_sync, |
| 130 bool install_silently, | 131 bool install_silently, |
| 131 bool enable_on_install, | 132 bool enable_on_install, |
| 132 bool enable_incognito_on_install) | 133 bool enable_incognito_on_install, |
| 134 Extension::Location location) |
| 133 : update_url(update_url), | 135 : update_url(update_url), |
| 134 expected_crx_type(expected_crx_type), | 136 expected_crx_type(expected_crx_type), |
| 135 is_from_sync(is_from_sync), | 137 is_from_sync(is_from_sync), |
| 136 install_silently(install_silently), | 138 install_silently(install_silently), |
| 137 enable_on_install(enable_on_install), | 139 enable_on_install(enable_on_install), |
| 138 enable_incognito_on_install(enable_incognito_on_install) {} | 140 enable_incognito_on_install(enable_incognito_on_install), |
| 141 install_source(location) {} |
| 139 | 142 |
| 140 PendingExtensionInfo::PendingExtensionInfo() | 143 PendingExtensionInfo::PendingExtensionInfo() |
| 141 : update_url(), | 144 : update_url(), |
| 142 expected_crx_type(PendingExtensionInfo::UNKNOWN), | 145 expected_crx_type(PendingExtensionInfo::UNKNOWN), |
| 143 is_from_sync(true), | 146 is_from_sync(true), |
| 144 install_silently(false), | 147 install_silently(false), |
| 145 enable_on_install(false), | 148 enable_on_install(false), |
| 146 enable_incognito_on_install(false) {} | 149 enable_incognito_on_install(false), |
| 150 install_source(Extension::INVALID) {} |
| 147 | 151 |
| 148 // ExtensionsService. | 152 // ExtensionsService. |
| 149 | 153 |
| 150 const char* ExtensionsService::kInstallDirectoryName = "Extensions"; | 154 const char* ExtensionsService::kInstallDirectoryName = "Extensions"; |
| 151 const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; | 155 const char* ExtensionsService::kCurrentVersionFileName = "Current Version"; |
| 152 | 156 |
| 153 // Implements IO for the ExtensionsService. | 157 // Implements IO for the ExtensionsService. |
| 154 | 158 |
| 155 class ExtensionsServiceBackend | 159 class ExtensionsServiceBackend |
| 156 : public base::RefCountedThreadSafe<ExtensionsServiceBackend>, | 160 : public base::RefCountedThreadSafe<ExtensionsServiceBackend>, |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 554 const CommandLine* command_line, | 558 const CommandLine* command_line, |
| 555 const FilePath& install_directory, | 559 const FilePath& install_directory, |
| 556 bool autoupdate_enabled) | 560 bool autoupdate_enabled) |
| 557 : profile_(profile), | 561 : profile_(profile), |
| 558 extension_prefs_(new ExtensionPrefs(profile->GetPrefs(), | 562 extension_prefs_(new ExtensionPrefs(profile->GetPrefs(), |
| 559 install_directory)), | 563 install_directory)), |
| 560 install_directory_(install_directory), | 564 install_directory_(install_directory), |
| 561 extensions_enabled_(true), | 565 extensions_enabled_(true), |
| 562 show_extensions_prompts_(true), | 566 show_extensions_prompts_(true), |
| 563 ready_(false), | 567 ready_(false), |
| 564 ALLOW_THIS_IN_INITIALIZER_LIST(toolbar_model_(this)) { | 568 ALLOW_THIS_IN_INITIALIZER_LIST(toolbar_model_(this)), |
| 569 default_apps_(profile->GetPrefs()) { |
| 565 // Figure out if extension installation should be enabled. | 570 // Figure out if extension installation should be enabled. |
| 566 if (command_line->HasSwitch(switches::kDisableExtensions)) { | 571 if (command_line->HasSwitch(switches::kDisableExtensions)) { |
| 567 extensions_enabled_ = false; | 572 extensions_enabled_ = false; |
| 568 } else if (profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { | 573 } else if (profile->GetPrefs()->GetBoolean(prefs::kDisableExtensions)) { |
| 569 extensions_enabled_ = false; | 574 extensions_enabled_ = false; |
| 570 } | 575 } |
| 571 | 576 |
| 572 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED, | 577 registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED, |
| 573 NotificationService::AllSources()); | 578 NotificationService::AllSources()); |
| 574 pref_change_registrar_.Init(profile->GetPrefs()); | 579 pref_change_registrar_.Init(profile->GetPrefs()); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 // pending extensions that have install_silently set. | 680 // pending extensions that have install_silently set. |
| 676 ExtensionInstallUI* client = | 681 ExtensionInstallUI* client = |
| 677 (!is_pending_extension || it->second.install_silently) ? | 682 (!is_pending_extension || it->second.install_silently) ? |
| 678 NULL : new ExtensionInstallUI(profile_); | 683 NULL : new ExtensionInstallUI(profile_); |
| 679 | 684 |
| 680 scoped_refptr<CrxInstaller> installer( | 685 scoped_refptr<CrxInstaller> installer( |
| 681 new CrxInstaller(install_directory_, | 686 new CrxInstaller(install_directory_, |
| 682 this, // frontend | 687 this, // frontend |
| 683 client)); | 688 client)); |
| 684 installer->set_expected_id(id); | 689 installer->set_expected_id(id); |
| 685 if (is_pending_extension && !it->second.is_from_sync) | 690 installer->set_install_source(it->second.install_source); |
| 686 installer->set_install_source(Extension::EXTERNAL_PREF_DOWNLOAD); | |
| 687 installer->set_delete_source(true); | 691 installer->set_delete_source(true); |
| 688 installer->set_original_url(download_url); | 692 installer->set_original_url(download_url); |
| 689 installer->InstallCrx(extension_path); | 693 installer->InstallCrx(extension_path); |
| 690 } | 694 } |
| 691 | 695 |
| 692 void ExtensionsService::AddPendingExtensionFromSync( | 696 void ExtensionsService::AddPendingExtensionFromSync( |
| 693 const std::string& id, const GURL& update_url, | 697 const std::string& id, const GURL& update_url, |
| 694 PendingExtensionInfo::ExpectedCrxType expected_crx_type, | 698 PendingExtensionInfo::ExpectedCrxType expected_crx_type, |
| 695 bool install_silently, bool enable_on_install, | 699 bool install_silently, bool enable_on_install, |
| 696 bool enable_incognito_on_install) { | 700 bool enable_incognito_on_install) { |
| 697 if (GetExtensionByIdInternal(id, true, true)) { | 701 if (GetExtensionByIdInternal(id, true, true)) { |
| 698 LOG(DFATAL) << "Trying to add pending extension " << id | 702 LOG(DFATAL) << "Trying to add pending extension " << id |
| 699 << " which already exists"; | 703 << " which already exists"; |
| 700 return; | 704 return; |
| 701 } | 705 } |
| 702 AddPendingExtensionInternal( | 706 |
| 703 id, update_url, expected_crx_type, true, install_silently, | 707 AddPendingExtensionInternal(id, update_url, expected_crx_type, true, |
| 704 enable_on_install, enable_incognito_on_install); | 708 install_silently, enable_on_install, |
| 709 enable_incognito_on_install, |
| 710 Extension::INTERNAL); |
| 705 } | 711 } |
| 706 | 712 |
| 707 void ExtensionsService::AddPendingExtensionFromExternalUpdateUrl( | 713 void ExtensionsService::AddPendingExtensionFromExternalUpdateUrl( |
| 708 const std::string& id, const GURL& update_url) { | 714 const std::string& id, const GURL& update_url) { |
| 709 // Add the extension to this list of extensions to update. | 715 // Add the extension to this list of extensions to update. |
| 710 // We do not know if the id refers to a theme, so make is_theme unknown. | |
| 711 const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType = | 716 const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType = |
| 712 PendingExtensionInfo::UNKNOWN; | 717 PendingExtensionInfo::UNKNOWN; |
| 713 const bool kIsFromSync = false; | 718 const bool kIsFromSync = false; |
| 714 const bool kInstallSilently = true; | 719 const bool kInstallSilently = true; |
| 715 const bool kEnableOnInstall = true; | 720 const bool kEnableOnInstall = true; |
| 716 const bool kEnableIncognitoOnInstall = false; | 721 const bool kEnableIncognitoOnInstall = false; |
| 717 | 722 |
| 718 if (GetExtensionByIdInternal(id, true, true)) { | 723 if (GetExtensionByIdInternal(id, true, true)) { |
| 719 LOG(DFATAL) << "Trying to add extension " << id | 724 LOG(DFATAL) << "Trying to add extension " << id |
| 720 << " by external update, but it is already installed."; | 725 << " by external update, but it is already installed."; |
| 721 return; | 726 return; |
| 722 } | 727 } |
| 723 | 728 |
| 724 AddPendingExtensionInternal(id, update_url, kExpectedCrxType, kIsFromSync, | 729 AddPendingExtensionInternal(id, update_url, kExpectedCrxType, kIsFromSync, |
| 725 kInstallSilently, kEnableOnInstall, | 730 kInstallSilently, kEnableOnInstall, |
| 726 kEnableIncognitoOnInstall); | 731 kEnableIncognitoOnInstall, |
| 732 Extension::EXTERNAL_PREF_DOWNLOAD); |
| 733 } |
| 734 |
| 735 void ExtensionsService::AddPendingExtensionFromDefaultAppList( |
| 736 const std::string& id) { |
| 737 // Add the extension to this list of extensions to update. |
| 738 const PendingExtensionInfo::ExpectedCrxType kExpectedCrxType = |
| 739 PendingExtensionInfo::APP; |
| 740 const bool kIsFromSync = false; |
| 741 const bool kInstallSilently = true; |
| 742 const bool kEnableOnInstall = true; |
| 743 const bool kEnableIncognitoOnInstall = true; |
| 744 |
| 745 // This can legitimately happen if the user manually installed one of the |
| 746 // default apps before this code ran. |
| 747 if (GetExtensionByIdInternal(id, true, true)) |
| 748 return; |
| 749 |
| 750 AddPendingExtensionInternal(id, GURL(), kExpectedCrxType, kIsFromSync, |
| 751 kInstallSilently, kEnableOnInstall, |
| 752 kEnableIncognitoOnInstall, |
| 753 Extension::INTERNAL); |
| 727 } | 754 } |
| 728 | 755 |
| 729 void ExtensionsService::AddPendingExtensionInternal( | 756 void ExtensionsService::AddPendingExtensionInternal( |
| 730 const std::string& id, const GURL& update_url, | 757 const std::string& id, const GURL& update_url, |
| 731 PendingExtensionInfo::ExpectedCrxType expected_crx_type, | 758 PendingExtensionInfo::ExpectedCrxType expected_crx_type, |
| 732 bool is_from_sync, bool install_silently, | 759 bool is_from_sync, bool install_silently, |
| 733 bool enable_on_install, bool enable_incognito_on_install) { | 760 bool enable_on_install, bool enable_incognito_on_install, |
| 761 Extension::Location install_source) { |
| 734 pending_extensions_[id] = | 762 pending_extensions_[id] = |
| 735 PendingExtensionInfo(update_url, expected_crx_type, is_from_sync, | 763 PendingExtensionInfo(update_url, expected_crx_type, is_from_sync, |
| 736 install_silently, enable_on_install, | 764 install_silently, enable_on_install, |
| 737 enable_incognito_on_install); | 765 enable_incognito_on_install, install_source); |
| 738 } | 766 } |
| 739 | 767 |
| 740 void ExtensionsService::ReloadExtension(const std::string& extension_id) { | 768 void ExtensionsService::ReloadExtension(const std::string& extension_id) { |
| 741 FilePath path; | 769 FilePath path; |
| 742 Extension* current_extension = GetExtensionById(extension_id, false); | 770 Extension* current_extension = GetExtensionById(extension_id, false); |
| 743 | 771 |
| 744 // Disable the extension if it's loaded. It might not be loaded if it crashed. | 772 // Disable the extension if it's loaded. It might not be loaded if it crashed. |
| 745 if (current_extension) { | 773 if (current_extension) { |
| 746 // If the extension has an inspector open for its background page, detach | 774 // If the extension has an inspector open for its background page, detach |
| 747 // the inspector and hang onto a cookie for it, so that we can reattach | 775 // the inspector and hang onto a cookie for it, so that we can reattach |
| (...skipping 726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1474 if (it != pending_extensions_.end()) { | 1502 if (it != pending_extensions_.end()) { |
| 1475 PendingExtensionInfo pending_extension_info = it->second; | 1503 PendingExtensionInfo pending_extension_info = it->second; |
| 1476 PendingExtensionInfo::ExpectedCrxType expected_crx_type = | 1504 PendingExtensionInfo::ExpectedCrxType expected_crx_type = |
| 1477 pending_extension_info.expected_crx_type; | 1505 pending_extension_info.expected_crx_type; |
| 1478 bool is_from_sync = pending_extension_info.is_from_sync; | 1506 bool is_from_sync = pending_extension_info.is_from_sync; |
| 1479 pending_extensions_.erase(it); | 1507 pending_extensions_.erase(it); |
| 1480 it = pending_extensions_.end(); | 1508 it = pending_extensions_.end(); |
| 1481 | 1509 |
| 1482 // Set initial state from pending extension data. | 1510 // Set initial state from pending extension data. |
| 1483 PendingExtensionInfo::ExpectedCrxType actual_crx_type = | 1511 PendingExtensionInfo::ExpectedCrxType actual_crx_type = |
| 1484 (extension->is_theme() ? PendingExtensionInfo::THEME | 1512 PendingExtensionInfo::EXTENSION; |
| 1485 : PendingExtensionInfo::EXTENSION); | 1513 if (extension->is_app()) |
| 1514 actual_crx_type = PendingExtensionInfo::APP; |
| 1515 else if (extension->is_theme()) |
| 1516 actual_crx_type = PendingExtensionInfo::THEME; |
| 1486 | 1517 |
| 1487 if (expected_crx_type != PendingExtensionInfo::UNKNOWN && | 1518 if (expected_crx_type != PendingExtensionInfo::UNKNOWN && |
| 1488 expected_crx_type != actual_crx_type) { | 1519 expected_crx_type != actual_crx_type) { |
| 1489 LOG(WARNING) | 1520 LOG(WARNING) |
| 1490 << "Not installing pending extension " << extension->id() | 1521 << "Not installing pending extension " << extension->id() |
| 1491 << " with is_theme = " << extension->is_theme(); | 1522 << " with is_theme = " << extension->is_theme(); |
| 1492 // Delete the extension directory since we're not going to | 1523 // Delete the extension directory since we're not going to |
| 1493 // load it. | 1524 // load it. |
| 1494 ChromeThread::PostTask( | 1525 ChromeThread::PostTask( |
| 1495 ChromeThread::FILE, FROM_HERE, | 1526 ChromeThread::FILE, FROM_HERE, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1584 NotificationType::THEME_INSTALLED, | 1615 NotificationType::THEME_INSTALLED, |
| 1585 Source<Profile>(profile_), | 1616 Source<Profile>(profile_), |
| 1586 Details<Extension>(extension)); | 1617 Details<Extension>(extension)); |
| 1587 } else { | 1618 } else { |
| 1588 NotificationService::current()->Notify( | 1619 NotificationService::current()->Notify( |
| 1589 NotificationType::EXTENSION_INSTALLED, | 1620 NotificationType::EXTENSION_INSTALLED, |
| 1590 Source<Profile>(profile_), | 1621 Source<Profile>(profile_), |
| 1591 Details<Extension>(extension)); | 1622 Details<Extension>(extension)); |
| 1592 } | 1623 } |
| 1593 | 1624 |
| 1625 if (extension->is_app()) { |
| 1626 ExtensionIdSet installed_ids = GetAppIds(); |
| 1627 installed_ids.insert(extension->id()); |
| 1628 default_apps_.DidInstallApp(installed_ids); |
| 1629 } |
| 1630 |
| 1594 // Transfer ownership of |extension| to OnExtensionLoaded. | 1631 // Transfer ownership of |extension| to OnExtensionLoaded. |
| 1595 OnExtensionLoaded(scoped_extension.release(), allow_privilege_increase); | 1632 OnExtensionLoaded(scoped_extension.release(), allow_privilege_increase); |
| 1596 } | 1633 } |
| 1597 | 1634 |
| 1598 Extension* ExtensionsService::GetExtensionByIdInternal(const std::string& id, | 1635 Extension* ExtensionsService::GetExtensionByIdInternal(const std::string& id, |
| 1599 bool include_enabled, | 1636 bool include_enabled, |
| 1600 bool include_disabled) { | 1637 bool include_disabled) { |
| 1601 std::string lowercase_id = StringToLowerASCII(id); | 1638 std::string lowercase_id = StringToLowerASCII(id); |
| 1602 if (include_enabled) { | 1639 if (include_enabled) { |
| 1603 for (ExtensionList::const_iterator iter = extensions_.begin(); | 1640 for (ExtensionList::const_iterator iter = extensions_.begin(); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1783 *pref_name == prefs::kExtensionInstallDenyList); | 1820 *pref_name == prefs::kExtensionInstallDenyList); |
| 1784 CheckAdminBlacklist(); | 1821 CheckAdminBlacklist(); |
| 1785 break; | 1822 break; |
| 1786 } | 1823 } |
| 1787 | 1824 |
| 1788 default: | 1825 default: |
| 1789 NOTREACHED() << "Unexpected notification type."; | 1826 NOTREACHED() << "Unexpected notification type."; |
| 1790 } | 1827 } |
| 1791 } | 1828 } |
| 1792 | 1829 |
| 1793 bool ExtensionsService::HasApps() { | 1830 bool ExtensionsService::HasApps() const { |
| 1794 if (!extensions_enabled_) | 1831 return !GetAppIds().empty(); |
| 1795 return false; | 1832 } |
| 1796 | 1833 |
| 1834 ExtensionIdSet ExtensionsService::GetAppIds() const { |
| 1835 ExtensionIdSet result; |
| 1797 for (ExtensionList::const_iterator it = extensions_.begin(); | 1836 for (ExtensionList::const_iterator it = extensions_.begin(); |
| 1798 it != extensions_.end(); ++it) { | 1837 it != extensions_.end(); ++it) { |
| 1799 if ((*it)->is_app()) | 1838 if ((*it)->is_app() && (*it)->location() != Extension::COMPONENT) |
| 1800 return true; | 1839 result.insert((*it)->id()); |
| 1801 } | 1840 } |
| 1802 | 1841 |
| 1803 return false; | 1842 return result; |
| 1804 } | 1843 } |
| OLD | NEW |