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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/extensions/suspicious_extension_bubble_controller.h" 6 7 #include "base/lazy_instance.h" 8 #include "base/metrics/histogram.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "chrome/browser/extensions/extension_message_bubble.h" 11 #include "chrome/browser/extensions/extension_service.h" 12 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/ui/browser.h" 14 #include "chrome/common/url_constants.h" 15 #include "chrome/grit/chromium_strings.h" 16 #include "chrome/grit/generated_resources.h" 17 #include "extensions/browser/extension_prefs.h" 18 #include "extensions/browser/extension_system.h" 19 #include "extensions/common/extension.h" 20 #include "grit/components_strings.h" 21 #include "ui/base/l10n/l10n_util.h" 22 23 using extensions::ExtensionMessageBubbleController; 24 25 namespace { 26 27 base::LazyInstance<std::set<Profile*> > g_shown_for_profiles = 28 LAZY_INSTANCE_INITIALIZER; 29 30 //////////////////////////////////////////////////////////////////////////////// 31 // SuspiciousExtensionBubbleDelegate 32 33 class SuspiciousExtensionBubbleDelegate 34 : public ExtensionMessageBubbleController::Delegate { 35 public: 36 explicit SuspiciousExtensionBubbleDelegate(Profile* profile); 37 virtual ~SuspiciousExtensionBubbleDelegate(); 38 39 // ExtensionMessageBubbleController::Delegate methods. 40 virtual bool ShouldIncludeExtension(const std::string& extension_id) OVERRIDE; 41 virtual void AcknowledgeExtension( 42 const std::string& extension_id, 43 ExtensionMessageBubbleController::BubbleAction user_action) OVERRIDE; 44 virtual void PerformAction(const extensions::ExtensionIdList& list) OVERRIDE; 45 virtual base::string16 GetTitle() const OVERRIDE; 46 virtual base::string16 GetMessageBody( 47 bool anchored_to_browser_action) const OVERRIDE; 48 virtual base::string16 GetOverflowText( 49 const base::string16& overflow_count) const OVERRIDE; 50 virtual base::string16 GetLearnMoreLabel() const OVERRIDE; 51 virtual GURL GetLearnMoreUrl() const OVERRIDE; 52 virtual base::string16 GetActionButtonLabel() const OVERRIDE; 53 virtual base::string16 GetDismissButtonLabel() const OVERRIDE; 54 virtual bool ShouldShowExtensionList() const OVERRIDE; 55 virtual void LogExtensionCount(size_t count) OVERRIDE; 56 virtual void LogAction( 57 ExtensionMessageBubbleController::BubbleAction action) OVERRIDE; 58 59 private: 60 // Our profile. Weak, not owned by us. 61 Profile* profile_; 62 63 DISALLOW_COPY_AND_ASSIGN(SuspiciousExtensionBubbleDelegate); 64 }; 65 66 SuspiciousExtensionBubbleDelegate::SuspiciousExtensionBubbleDelegate( 67 Profile* profile) 68 : profile_(profile) {} 69 70 SuspiciousExtensionBubbleDelegate::~SuspiciousExtensionBubbleDelegate() { 71 } 72 73 bool SuspiciousExtensionBubbleDelegate::ShouldIncludeExtension( 74 const std::string& extension_id) { 75 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); 76 if (!prefs->IsExtensionDisabled(extension_id)) 77 return false; 78 79 int disble_reasons = prefs->GetDisableReasons(extension_id); 80 if (disble_reasons & extensions::Extension::DISABLE_NOT_VERIFIED) 81 return !prefs->HasWipeoutBeenAcknowledged(extension_id); 82 83 return false; 84 } 85 86 void SuspiciousExtensionBubbleDelegate::AcknowledgeExtension( 87 const std::string& extension_id, 88 ExtensionMessageBubbleController::BubbleAction user_action) { 89 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); 90 prefs->SetWipeoutAcknowledged(extension_id, true); 91 } 92 93 void SuspiciousExtensionBubbleDelegate::PerformAction( 94 const extensions::ExtensionIdList& list) { 95 // This bubble solicits no action from the user. Or as Nimoy would have it: 96 // "Well, my work here is done". 97 } 98 99 base::string16 SuspiciousExtensionBubbleDelegate::GetTitle() const { 100 return l10n_util::GetStringUTF16(IDS_EXTENSIONS_UNSUPPORTED_DISABLED_TITLE); 101 } 102 103 base::string16 SuspiciousExtensionBubbleDelegate::GetMessageBody( 104 bool anchored_to_browser_action) const { 105 return l10n_util::GetStringFUTF16(IDS_EXTENSIONS_UNSUPPORTED_DISABLED_BODY, 106 l10n_util::GetStringUTF16(IDS_EXTENSION_WEB_STORE_TITLE)); 107 } 108 109 base::string16 SuspiciousExtensionBubbleDelegate::GetOverflowText( 110 const base::string16& overflow_count) const { 111 return l10n_util::GetStringFUTF16( 112 IDS_EXTENSIONS_DISABLED_AND_N_MORE, 113 overflow_count); 114 } 115 116 base::string16 117 SuspiciousExtensionBubbleDelegate::GetLearnMoreLabel() const { 118 return l10n_util::GetStringUTF16(IDS_LEARN_MORE); 119 } 120 121 GURL SuspiciousExtensionBubbleDelegate::GetLearnMoreUrl() const { 122 return GURL(chrome::kRemoveNonCWSExtensionURL); 123 } 124 125 base::string16 126 SuspiciousExtensionBubbleDelegate::GetActionButtonLabel() const { 127 return base::string16(); 128 } 129 130 base::string16 131 SuspiciousExtensionBubbleDelegate::GetDismissButtonLabel() const { 132 return l10n_util::GetStringUTF16(IDS_EXTENSIONS_UNSUPPORTED_DISABLED_BUTTON); 133 } 134 135 bool 136 SuspiciousExtensionBubbleDelegate::ShouldShowExtensionList() const { 137 return true; 138 } 139 140 void SuspiciousExtensionBubbleDelegate::LogExtensionCount( 141 size_t count) { 142 UMA_HISTOGRAM_COUNTS_100( 143 "ExtensionBubble.ExtensionWipeoutCount", count); 144 } 145 146 void SuspiciousExtensionBubbleDelegate::LogAction( 147 ExtensionMessageBubbleController::BubbleAction action) { 148 UMA_HISTOGRAM_ENUMERATION( 149 "ExtensionBubble.WipeoutUserSelection", 150 action, ExtensionMessageBubbleController::ACTION_BOUNDARY); 151 } 152 153 } // namespace 154 155 namespace extensions { 156 157 //////////////////////////////////////////////////////////////////////////////// 158 // SuspiciousExtensionBubbleController 159 160 // static 161 void SuspiciousExtensionBubbleController::ClearProfileListForTesting() { 162 g_shown_for_profiles.Get().clear(); 163 } 164 165 SuspiciousExtensionBubbleController::SuspiciousExtensionBubbleController( 166 Profile* profile) 167 : ExtensionMessageBubbleController( 168 new SuspiciousExtensionBubbleDelegate(profile), 169 profile), 170 profile_(profile) {} 171 172 SuspiciousExtensionBubbleController::~SuspiciousExtensionBubbleController() { 173 } 174 175 bool SuspiciousExtensionBubbleController::ShouldShow() { 176 return !g_shown_for_profiles.Get().count(profile_->GetOriginalProfile()) && 177 !GetExtensionList().empty(); 178 } 179 180 void SuspiciousExtensionBubbleController::Show(ExtensionMessageBubble* bubble) { 181 g_shown_for_profiles.Get().insert(profile_->GetOriginalProfile()); 182 ExtensionMessageBubbleController::Show(bubble); 183 } 184 185 } // namespace extensions 186