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/browser/extensions/extension_service.h" | 5 #include "chrome/browser/extensions/extension_service.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <iterator> | 8 #include <iterator> |
9 #include <set> | 9 #include <set> |
10 | 10 |
(...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 FROM_HERE, | 558 FROM_HERE, |
559 base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()), | 559 base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()), |
560 base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay)); | 560 base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay)); |
561 | 561 |
562 if (extension_prefs_->NeedsStorageGarbageCollection()) { | 562 if (extension_prefs_->NeedsStorageGarbageCollection()) { |
563 GarbageCollectIsolatedStorage(); | 563 GarbageCollectIsolatedStorage(); |
564 extension_prefs_->SetNeedsStorageGarbageCollection(false); | 564 extension_prefs_->SetNeedsStorageGarbageCollection(false); |
565 } | 565 } |
566 system_->management_policy()->RegisterProvider( | 566 system_->management_policy()->RegisterProvider( |
567 shared_module_policy_provider_.get()); | 567 shared_module_policy_provider_.get()); |
| 568 |
| 569 LoadGreylistFromPrefs(); |
568 } | 570 } |
569 | 571 |
570 UMA_HISTOGRAM_TIMES("Extensions.ExtensionServiceInitTime", | 572 UMA_HISTOGRAM_TIMES("Extensions.ExtensionServiceInitTime", |
571 base::Time::Now() - begin_time); | 573 base::Time::Now() - begin_time); |
572 } | 574 } |
573 | 575 |
| 576 void ExtensionService::LoadGreylistFromPrefs() { |
| 577 scoped_ptr<ExtensionSet> all_extensions = GenerateInstalledExtensionsSet(); |
| 578 |
| 579 for (ExtensionSet::const_iterator it = all_extensions->begin(); |
| 580 it != all_extensions->end(); ++it) { |
| 581 extensions::BlacklistState state = |
| 582 extension_prefs_->GetExtensionBlacklistState((*it)->id()); |
| 583 if (state == extensions::BLACKLISTED_SECURITY_VULNERABILITY || |
| 584 state == extensions::BLACKLISTED_POTENTIALLY_UNWANTED || |
| 585 state == extensions::BLACKLISTED_CWS_POLICY_VIOLATION) |
| 586 greylist_.Insert(*it); |
| 587 } |
| 588 } |
| 589 |
574 void ExtensionService::VerifyAllExtensions() { | 590 void ExtensionService::VerifyAllExtensions() { |
575 ExtensionIdSet to_add; | 591 ExtensionIdSet to_add; |
576 scoped_ptr<ExtensionSet> all_extensions = GenerateInstalledExtensionsSet(); | 592 scoped_ptr<ExtensionSet> all_extensions = GenerateInstalledExtensionsSet(); |
577 | 593 |
578 for (ExtensionSet::const_iterator i = all_extensions->begin(); | 594 for (ExtensionSet::const_iterator i = all_extensions->begin(); |
579 i != all_extensions->end(); ++i) { | 595 i != all_extensions->end(); ++i) { |
580 const Extension& extension = **i; | 596 const Extension& extension = **i; |
581 | 597 |
582 if (InstallVerifier::NeedsVerification(extension)) | 598 if (InstallVerifier::NeedsVerification(extension)) |
583 to_add.insert(extension.id()); | 599 to_add.insert(extension.id()); |
(...skipping 2132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2716 to_be_installed.push_back((*it)->id()); | 2732 to_be_installed.push_back((*it)->id()); |
2717 } | 2733 } |
2718 for (std::vector<std::string>::const_iterator it = to_be_installed.begin(); | 2734 for (std::vector<std::string>::const_iterator it = to_be_installed.begin(); |
2719 it != to_be_installed.end(); | 2735 it != to_be_installed.end(); |
2720 ++it) { | 2736 ++it) { |
2721 MaybeFinishDelayedInstallation(*it); | 2737 MaybeFinishDelayedInstallation(*it); |
2722 } | 2738 } |
2723 } | 2739 } |
2724 | 2740 |
2725 void ExtensionService::OnBlacklistUpdated() { | 2741 void ExtensionService::OnBlacklistUpdated() { |
2726 blacklist_->GetMalwareIDs( | 2742 blacklist_->GetBlacklistedIDs( |
2727 GenerateInstalledExtensionsSet()->GetIDs(), | 2743 GenerateInstalledExtensionsSet()->GetIDs(), |
2728 base::Bind(&ExtensionService::ManageBlacklist, AsWeakPtr())); | 2744 base::Bind(&ExtensionService::ManageBlacklist, AsWeakPtr())); |
2729 } | 2745 } |
2730 | 2746 |
2731 void ExtensionService::ManageBlacklist(const std::set<std::string>& updated) { | 2747 void ExtensionService::ManageBlacklist( |
| 2748 const extensions::Blacklist::BlacklistStateMap& state_map) { |
2732 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2749 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2733 | 2750 |
2734 std::set<std::string> before = registry_->blacklisted_extensions().GetIDs(); | 2751 std::set<std::string> blocked; |
2735 std::set<std::string> no_longer_blacklisted = | 2752 ExtensionIdSet greylist; |
2736 base::STLSetDifference<std::set<std::string> >(before, updated); | 2753 ExtensionIdSet unchanged; |
2737 std::set<std::string> not_yet_blacklisted = | 2754 for (extensions::Blacklist::BlacklistStateMap::const_iterator it = |
2738 base::STLSetDifference<std::set<std::string> >(updated, before); | 2755 state_map.begin(); |
| 2756 it != state_map.end(); |
| 2757 ++it) { |
| 2758 switch (it->second) { |
| 2759 case extensions::NOT_BLACKLISTED: |
| 2760 break; |
2739 | 2761 |
2740 for (std::set<std::string>::iterator it = no_longer_blacklisted.begin(); | 2762 case extensions::BLACKLISTED_MALWARE: |
2741 it != no_longer_blacklisted.end(); ++it) { | 2763 blocked.insert(it->first); |
| 2764 break; |
| 2765 |
| 2766 case extensions::BLACKLISTED_SECURITY_VULNERABILITY: |
| 2767 case extensions::BLACKLISTED_CWS_POLICY_VIOLATION: |
| 2768 case extensions::BLACKLISTED_POTENTIALLY_UNWANTED: |
| 2769 greylist.insert(it->first); |
| 2770 break; |
| 2771 |
| 2772 case extensions::BLACKLISTED_UNKNOWN: |
| 2773 unchanged.insert(it->first); |
| 2774 break; |
| 2775 } |
| 2776 } |
| 2777 |
| 2778 UpdateBlockedExtensions(blocked, unchanged); |
| 2779 UpdateGreylistedExtensions(greylist, unchanged, state_map); |
| 2780 |
| 2781 IdentifyAlertableExtensions(); |
| 2782 } |
| 2783 |
| 2784 namespace { |
| 2785 void Partition(const ExtensionIdSet& before, |
| 2786 const ExtensionIdSet& after, |
| 2787 const ExtensionIdSet& unchanged, |
| 2788 ExtensionIdSet* no_longer, |
| 2789 ExtensionIdSet* not_yet) { |
| 2790 *not_yet = base::STLSetDifference<ExtensionIdSet>(after, before); |
| 2791 *no_longer = base::STLSetDifference<ExtensionIdSet>(before, after); |
| 2792 *no_longer = base::STLSetDifference<ExtensionIdSet>(*no_longer, unchanged); |
| 2793 } |
| 2794 } // namespace |
| 2795 |
| 2796 void ExtensionService::UpdateBlockedExtensions( |
| 2797 const ExtensionIdSet& blocked, |
| 2798 const ExtensionIdSet& unchanged) { |
| 2799 ExtensionIdSet not_yet_blocked, no_longer_blocked; |
| 2800 Partition(registry_->blacklisted_extensions().GetIDs(), |
| 2801 blocked, unchanged, |
| 2802 &no_longer_blocked, ¬_yet_blocked); |
| 2803 |
| 2804 for (ExtensionIdSet::iterator it = no_longer_blocked.begin(); |
| 2805 it != no_longer_blocked.end(); ++it) { |
2742 scoped_refptr<const Extension> extension = | 2806 scoped_refptr<const Extension> extension = |
2743 registry_->blacklisted_extensions().GetByID(*it); | 2807 registry_->blacklisted_extensions().GetByID(*it); |
2744 if (!extension.get()) { | 2808 if (!extension.get()) { |
2745 NOTREACHED() << "Extension " << *it << " no longer blacklisted, " | 2809 NOTREACHED() << "Extension " << *it << " no longer blocked, " |
2746 << "but it was never blacklisted."; | 2810 << "but it was never blocked."; |
2747 continue; | 2811 continue; |
2748 } | 2812 } |
2749 registry_->RemoveBlacklisted(*it); | 2813 registry_->RemoveBlacklisted(*it); |
2750 extension_prefs_->SetExtensionBlacklisted(extension->id(), false); | 2814 extension_prefs_->SetExtensionBlacklisted(extension->id(), false); |
2751 AddExtension(extension.get()); | 2815 AddExtension(extension.get()); |
2752 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.UnblacklistInstalled", | 2816 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.UnblacklistInstalled", |
2753 extension->location(), | 2817 extension->location(), |
2754 Manifest::NUM_LOCATIONS); | 2818 Manifest::NUM_LOCATIONS); |
2755 } | 2819 } |
2756 | 2820 |
2757 for (std::set<std::string>::iterator it = not_yet_blacklisted.begin(); | 2821 for (ExtensionIdSet::iterator it = not_yet_blocked.begin(); |
2758 it != not_yet_blacklisted.end(); ++it) { | 2822 it != not_yet_blocked.end(); ++it) { |
2759 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); | 2823 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); |
2760 if (!extension.get()) { | 2824 if (!extension.get()) { |
2761 NOTREACHED() << "Extension " << *it << " needs to be " | 2825 NOTREACHED() << "Extension " << *it << " needs to be " |
2762 << "blacklisted, but it's not installed."; | 2826 << "blacklisted, but it's not installed."; |
2763 continue; | 2827 continue; |
2764 } | 2828 } |
2765 registry_->AddBlacklisted(extension); | 2829 registry_->AddBlacklisted(extension); |
2766 extension_prefs_->SetExtensionBlacklisted(extension->id(), true); | 2830 extension_prefs_->SetExtensionBlacklistState( |
| 2831 extension->id(), extensions::BLACKLISTED_MALWARE); |
2767 UnloadExtension(*it, UnloadedExtensionInfo::REASON_BLACKLIST); | 2832 UnloadExtension(*it, UnloadedExtensionInfo::REASON_BLACKLIST); |
2768 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlacklistInstalled", | 2833 UMA_HISTOGRAM_ENUMERATION("ExtensionBlacklist.BlacklistInstalled", |
2769 extension->location(), Manifest::NUM_LOCATIONS); | 2834 extension->location(), Manifest::NUM_LOCATIONS); |
2770 } | 2835 } |
| 2836 } |
2771 | 2837 |
2772 IdentifyAlertableExtensions(); | 2838 // TODO(oleg): UMA logging |
| 2839 void ExtensionService::UpdateGreylistedExtensions( |
| 2840 const ExtensionIdSet& greylist, |
| 2841 const ExtensionIdSet& unchanged, |
| 2842 const extensions::Blacklist::BlacklistStateMap& state_map) { |
| 2843 ExtensionIdSet not_yet_greylisted, no_longer_greylisted; |
| 2844 Partition(greylist_.GetIDs(), |
| 2845 greylist, unchanged, |
| 2846 &no_longer_greylisted, ¬_yet_greylisted); |
| 2847 |
| 2848 for (ExtensionIdSet::iterator it = no_longer_greylisted.begin(); |
| 2849 it != no_longer_greylisted.end(); ++it) { |
| 2850 scoped_refptr<const Extension> extension = greylist_.GetByID(*it); |
| 2851 if (!extension.get()) { |
| 2852 NOTREACHED() << "Extension " << *it << " no longer greylisted, " |
| 2853 << "but it was not marked as greylisted."; |
| 2854 continue; |
| 2855 } |
| 2856 |
| 2857 greylist_.Remove(*it); |
| 2858 extension_prefs_->SetExtensionBlacklistState(extension->id(), |
| 2859 extensions::NOT_BLACKLISTED); |
| 2860 if (extension_prefs_->GetDisableReasons(extension->id()) & |
| 2861 extensions::Extension::DISABLE_GREYLIST) |
| 2862 EnableExtension(*it); |
| 2863 } |
| 2864 |
| 2865 for (ExtensionIdSet::iterator it = not_yet_greylisted.begin(); |
| 2866 it != not_yet_greylisted.end(); ++it) { |
| 2867 scoped_refptr<const Extension> extension = GetInstalledExtension(*it); |
| 2868 if (!extension.get()) { |
| 2869 NOTREACHED() << "Extension " << *it << " needs to be " |
| 2870 << "disabled, but it's not installed."; |
| 2871 continue; |
| 2872 } |
| 2873 greylist_.Insert(extension); |
| 2874 extension_prefs_->SetExtensionBlacklistState(extension->id(), |
| 2875 state_map.find(*it)->second); |
| 2876 if (registry_->enabled_extensions().Contains(extension->id())) |
| 2877 DisableExtension(*it, extensions::Extension::DISABLE_GREYLIST); |
| 2878 } |
2773 } | 2879 } |
2774 | 2880 |
2775 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { | 2881 void ExtensionService::AddUpdateObserver(extensions::UpdateObserver* observer) { |
2776 update_observers_.AddObserver(observer); | 2882 update_observers_.AddObserver(observer); |
2777 } | 2883 } |
2778 | 2884 |
2779 void ExtensionService::RemoveUpdateObserver( | 2885 void ExtensionService::RemoveUpdateObserver( |
2780 extensions::UpdateObserver* observer) { | 2886 extensions::UpdateObserver* observer) { |
2781 update_observers_.RemoveObserver(observer); | 2887 update_observers_.RemoveObserver(observer); |
2782 } | 2888 } |
2783 | 2889 |
2784 // Used only by test code. | 2890 // Used only by test code. |
2785 void ExtensionService::UnloadAllExtensionsInternal() { | 2891 void ExtensionService::UnloadAllExtensionsInternal() { |
2786 profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions(); | 2892 profile_->GetExtensionSpecialStoragePolicy()->RevokeRightsForAllExtensions(); |
2787 | 2893 |
2788 registry_->ClearAll(); | 2894 registry_->ClearAll(); |
2789 system_->runtime_data()->ClearAll(); | 2895 system_->runtime_data()->ClearAll(); |
2790 | 2896 |
2791 // TODO(erikkay) should there be a notification for this? We can't use | 2897 // TODO(erikkay) should there be a notification for this? We can't use |
2792 // EXTENSION_UNLOADED since that implies that the extension has been disabled | 2898 // EXTENSION_UNLOADED since that implies that the extension has been disabled |
2793 // or uninstalled. | 2899 // or uninstalled. |
2794 } | 2900 } |
OLD | NEW |