1 // Copyright 2014 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/proxy_overridden_bubble_controller.h"
6
7 #include "base/metrics/histogram.h"
8 #include "chrome/browser/extensions/extension_service.h"
9 #include "chrome/browser/extensions/extension_toolbar_model.h"
10 #include "chrome/browser/extensions/settings_api_helpers.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/common/url_constants.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "extensions/browser/extension_registry.h"
15 #include "extensions/browser/extension_system.h"
16 #include "grit/components_strings.h"
17 #include "ui/base/l10n/l10n_util.h"
18
19 namespace extensions {
20
21 namespace {
22
23 // The minimum time to wait (since the extension was installed) before notifying
24 // the user about it.
25 const int kDaysSinceInstallMin = 7;
26
27 ////////////////////////////////////////////////////////////////////////////////
28 // ProxyOverriddenBubbleDelegate
29
30 class ProxyOverriddenBubbleDelegate
31 : public ExtensionMessageBubbleController::Delegate {
32 public:
33 ProxyOverriddenBubbleDelegate(ExtensionService* service, Profile* profile);
34 virtual ~ProxyOverriddenBubbleDelegate();
35
36 // ExtensionMessageBubbleController::Delegate methods.
37 virtual bool ShouldIncludeExtension(const std::string& extension_id) OVERRIDE;
38 virtual void AcknowledgeExtension(
39 const std::string& extension_id,
40 ExtensionMessageBubbleController::BubbleAction
41 user_action) OVERRIDE;
42 virtual void PerformAction(const ExtensionIdList& list) OVERRIDE;
43 virtual void OnClose() 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 RestrictToSingleExtension(
55 const std::string& extension_id) OVERRIDE;
56 virtual void LogExtensionCount(size_t count) OVERRIDE;
57 virtual void LogAction(
58 ExtensionMessageBubbleController::BubbleAction
59 action) OVERRIDE;
60
61 private:
62 // Our extension service. Weak, not owned by us.
63 ExtensionService* service_;
64
65 // A weak pointer to the profile we are associated with. Not owned by us.
66 Profile* profile_;
67
68 // The ID of the extension we are showing the bubble for.
69 std::string extension_id_;
70
71 DISALLOW_COPY_AND_ASSIGN(ProxyOverriddenBubbleDelegate);
72 };
73
ProxyOverriddenBubbleDelegate(ExtensionService * service,Profile * profile)74 ProxyOverriddenBubbleDelegate::ProxyOverriddenBubbleDelegate(
75 ExtensionService* service,
76 Profile* profile)
77 : service_(service), profile_(profile) {}
78
~ProxyOverriddenBubbleDelegate()79 ProxyOverriddenBubbleDelegate::~ProxyOverriddenBubbleDelegate() {}
80
ShouldIncludeExtension(const std::string & extension_id)81 bool ProxyOverriddenBubbleDelegate::ShouldIncludeExtension(
82 const std::string& extension_id) {
83 if (!extension_id_.empty() && extension_id_ != extension_id)
84 return false;
85
86 const Extension* extension =
87 ExtensionRegistry::Get(profile_)->enabled_extensions().GetByID(
88 extension_id);
89 if (!extension)
90 return false; // The extension provided is no longer enabled.
91
92 const Extension* overriding = GetExtensionOverridingProxy(profile_);
93 if (!overriding || overriding->id() != extension_id)
94 return false;
95
96 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
97 base::TimeDelta since_install =
98 base::Time::Now() - prefs->GetInstallTime(extension->id());
99 if (since_install.InDays() < kDaysSinceInstallMin)
100 return false;
101
102 if (ExtensionPrefs::Get(profile_)->HasProxyOverriddenBubbleBeenAcknowledged(
103 extension_id))
104 return false;
105
106 return true;
107 }
108
AcknowledgeExtension(const std::string & extension_id,ExtensionMessageBubbleController::BubbleAction user_action)109 void ProxyOverriddenBubbleDelegate::AcknowledgeExtension(
110 const std::string& extension_id,
111 ExtensionMessageBubbleController::BubbleAction user_action) {
112 if (user_action != ExtensionMessageBubbleController::ACTION_EXECUTE) {
113 ExtensionPrefs::Get(profile_)->SetProxyOverriddenBubbleBeenAcknowledged(
114 extension_id, true);
115 }
116 }
117
PerformAction(const ExtensionIdList & list)118 void ProxyOverriddenBubbleDelegate::PerformAction(const ExtensionIdList& list) {
119 for (size_t i = 0; i < list.size(); ++i)
120 service_->DisableExtension(list[i], Extension::DISABLE_USER_ACTION);
121 }
122
OnClose()123 void ProxyOverriddenBubbleDelegate::OnClose() {
124 ExtensionToolbarModel* toolbar_model =
125 ExtensionToolbarModel::Get(profile_);
126 if (toolbar_model)
127 toolbar_model->StopHighlighting();
128 }
129
GetTitle() const130 base::string16 ProxyOverriddenBubbleDelegate::GetTitle() const {
131 return l10n_util::GetStringUTF16(
132 IDS_EXTENSIONS_PROXY_CONTROLLED_TITLE_HOME_PAGE_BUBBLE);
133 }
134
GetMessageBody(bool anchored_to_browser_action) const135 base::string16 ProxyOverriddenBubbleDelegate::GetMessageBody(
136 bool anchored_to_browser_action) const {
137 if (anchored_to_browser_action) {
138 return l10n_util::GetStringUTF16(
139 IDS_EXTENSIONS_PROXY_CONTROLLED_FIRST_LINE_EXTENSION_SPECIFIC);
140 } else {
141 return l10n_util::GetStringUTF16(
142 IDS_EXTENSIONS_PROXY_CONTROLLED_FIRST_LINE);
143 }
144 }
145
GetOverflowText(const base::string16 & overflow_count) const146 base::string16 ProxyOverriddenBubbleDelegate::GetOverflowText(
147 const base::string16& overflow_count) const {
148 // Does not have more than one extension in the list at a time.
149 NOTREACHED();
150 return base::string16();
151 }
152
GetLearnMoreLabel() const153 base::string16 ProxyOverriddenBubbleDelegate::GetLearnMoreLabel() const {
154 return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
155 }
156
GetLearnMoreUrl() const157 GURL ProxyOverriddenBubbleDelegate::GetLearnMoreUrl() const {
158 return GURL(chrome::kExtensionControlledSettingLearnMoreURL);
159 }
160
GetActionButtonLabel() const161 base::string16 ProxyOverriddenBubbleDelegate::GetActionButtonLabel() const {
162 return l10n_util::GetStringUTF16(IDS_EXTENSION_CONTROLLED_RESTORE_SETTINGS);
163 }
164
GetDismissButtonLabel() const165 base::string16 ProxyOverriddenBubbleDelegate::GetDismissButtonLabel() const {
166 return l10n_util::GetStringUTF16(IDS_EXTENSION_CONTROLLED_KEEP_CHANGES);
167 }
168
ShouldShowExtensionList() const169 bool ProxyOverriddenBubbleDelegate::ShouldShowExtensionList() const {
170 return false;
171 }
172
RestrictToSingleExtension(const std::string & extension_id)173 void ProxyOverriddenBubbleDelegate::RestrictToSingleExtension(
174 const std::string& extension_id) {
175 extension_id_ = extension_id;
176 }
177
LogExtensionCount(size_t count)178 void ProxyOverriddenBubbleDelegate::LogExtensionCount(size_t count) {
179 UMA_HISTOGRAM_COUNTS_100("ProxyOverriddenBubble.ExtensionCount", count);
180 }
181
LogAction(ExtensionMessageBubbleController::BubbleAction action)182 void ProxyOverriddenBubbleDelegate::LogAction(
183 ExtensionMessageBubbleController::BubbleAction action) {
184 UMA_HISTOGRAM_ENUMERATION("ProxyOverriddenBubble.UserSelection",
185 action,
186 ExtensionMessageBubbleController::ACTION_BOUNDARY);
187 }
188
189 } // namespace
190
191 ////////////////////////////////////////////////////////////////////////////////
192 // ProxyOverriddenBubbleController
193
ProxyOverriddenBubbleController(Profile * profile)194 ProxyOverriddenBubbleController::ProxyOverriddenBubbleController(
195 Profile* profile)
196 : ExtensionMessageBubbleController(
197 new ProxyOverriddenBubbleDelegate(
198 ExtensionSystem::Get(profile)->extension_service(),
199 profile),
200 profile),
201 profile_(profile) {}
202
~ProxyOverriddenBubbleController()203 ProxyOverriddenBubbleController::~ProxyOverriddenBubbleController() {}
204
ShouldShow(const std::string & extension_id)205 bool ProxyOverriddenBubbleController::ShouldShow(
206 const std::string& extension_id) {
207 if (!delegate()->ShouldIncludeExtension(extension_id))
208 return false;
209
210 delegate()->RestrictToSingleExtension(extension_id);
211 return true;
212 }
213
CloseOnDeactivate()214 bool ProxyOverriddenBubbleController::CloseOnDeactivate() {
215 return false;
216 }
217
218 } // namespace extensions
219