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