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_message_bubble_controller.h" | 5 #include "chrome/browser/extensions/extension_message_bubble_controller.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/lazy_instance.h" | |
9 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
10 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
11 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
12 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
13 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
14 #include "chrome/browser/ui/browser.h" | 13 #include "chrome/browser/ui/browser.h" |
15 #include "chrome/browser/ui/browser_finder.h" | 14 #include "chrome/browser/ui/browser_finder.h" |
16 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" | 15 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" |
17 #include "chrome/common/url_constants.h" | 16 #include "chrome/common/url_constants.h" |
18 #include "content/public/browser/user_metrics.h" | 17 #include "content/public/browser/user_metrics.h" |
19 #include "extensions/browser/extension_prefs.h" | 18 #include "extensions/browser/extension_prefs.h" |
20 #include "extensions/browser/extension_registry.h" | 19 #include "extensions/browser/extension_registry.h" |
21 #include "extensions/browser/extension_system.h" | 20 #include "extensions/browser/extension_system.h" |
22 #include "grit/components_strings.h" | 21 #include "grit/components_strings.h" |
23 #include "ui/base/l10n/l10n_util.h" | 22 #include "ui/base/l10n/l10n_util.h" |
24 | 23 |
25 namespace extensions { | 24 namespace extensions { |
26 | 25 |
27 namespace { | 26 namespace { |
28 | |
29 // How many extensions to show in the bubble (max). | 27 // How many extensions to show in the bubble (max). |
30 const int kMaxExtensionsToShow = 7; | 28 const int kMaxExtensionsToShow = 7; |
31 | 29 |
32 // Whether or not to ignore the learn more link navigation for testing. | 30 // Whether or not to ignore the learn more link navigation for testing. |
33 bool g_should_ignore_learn_more_for_testing = false; | 31 bool g_should_ignore_learn_more_for_testing = false; |
34 | 32 } |
35 using ProfileSetMap = std::map<std::string, std::set<Profile*>>; | |
36 base::LazyInstance<ProfileSetMap> g_shown_for_profiles = | |
37 LAZY_INSTANCE_INITIALIZER; | |
38 | |
39 } // namespace | |
40 | 33 |
41 //////////////////////////////////////////////////////////////////////////////// | 34 //////////////////////////////////////////////////////////////////////////////// |
42 // ExtensionMessageBubbleController::Delegate | 35 // ExtensionMessageBubbleController::Delegate |
43 | 36 |
44 ExtensionMessageBubbleController::Delegate::Delegate(Profile* profile) | 37 ExtensionMessageBubbleController::Delegate::Delegate(Profile* profile) |
45 : profile_(profile), | 38 : profile_(profile), |
46 service_(ExtensionSystem::Get(profile)->extension_service()), | 39 service_(ExtensionSystem::Get(profile)->extension_service()), |
47 registry_(ExtensionRegistry::Get(profile)) { | 40 registry_(ExtensionRegistry::Get(profile)) { |
48 } | 41 } |
49 | 42 |
50 ExtensionMessageBubbleController::Delegate::~Delegate() { | 43 ExtensionMessageBubbleController::Delegate::~Delegate() { |
51 } | 44 } |
52 | 45 |
53 base::string16 ExtensionMessageBubbleController::Delegate::GetLearnMoreLabel() | 46 base::string16 ExtensionMessageBubbleController::Delegate::GetLearnMoreLabel() |
54 const { | 47 const { |
55 return l10n_util::GetStringUTF16(IDS_LEARN_MORE); | 48 return l10n_util::GetStringUTF16(IDS_LEARN_MORE); |
56 } | 49 } |
57 | 50 |
58 bool ExtensionMessageBubbleController::Delegate::ClearProfileSetAfterAction() { | |
59 return true; | |
60 } | |
61 | |
62 bool ExtensionMessageBubbleController::Delegate::HasBubbleInfoBeenAcknowledged( | 51 bool ExtensionMessageBubbleController::Delegate::HasBubbleInfoBeenAcknowledged( |
63 const std::string& extension_id) { | 52 const std::string& extension_id) { |
64 std::string pref_name = get_acknowledged_flag_pref_name(); | 53 std::string pref_name = get_acknowledged_flag_pref_name(); |
65 if (pref_name.empty()) | 54 if (pref_name.empty()) |
66 return false; | 55 return false; |
67 bool pref_state = false; | 56 bool pref_state = false; |
68 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); | 57 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); |
69 prefs->ReadPrefAsBoolean(extension_id, pref_name, &pref_state); | 58 prefs->ReadPrefAsBoolean(extension_id, pref_name, &pref_state); |
70 return pref_state; | 59 return pref_state; |
71 } | 60 } |
72 | 61 |
73 void ExtensionMessageBubbleController::Delegate::SetBubbleInfoBeenAcknowledged( | 62 void ExtensionMessageBubbleController::Delegate::SetBubbleInfoBeenAcknowledged( |
74 const std::string& extension_id, | 63 const std::string& extension_id, |
75 bool value) { | 64 bool value) { |
76 std::string pref_name = get_acknowledged_flag_pref_name(); | 65 std::string pref_name = get_acknowledged_flag_pref_name(); |
77 if (pref_name.empty()) | 66 if (pref_name.empty()) |
78 return; | 67 return; |
79 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); | 68 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); |
80 prefs->UpdateExtensionPref(extension_id, | 69 prefs->UpdateExtensionPref(extension_id, |
81 pref_name, | 70 pref_name, |
82 value ? new base::FundamentalValue(value) : NULL); | 71 value ? new base::FundamentalValue(value) : NULL); |
83 } | 72 } |
84 | 73 |
| 74 std::set<Profile*>* |
| 75 ExtensionMessageBubbleController::Delegate::GetProfileSet() { |
| 76 return nullptr; |
| 77 } |
| 78 |
85 std::string | 79 std::string |
86 ExtensionMessageBubbleController::Delegate::get_acknowledged_flag_pref_name() | 80 ExtensionMessageBubbleController::Delegate::get_acknowledged_flag_pref_name() |
87 const { | 81 const { |
88 return acknowledged_pref_name_; | 82 return acknowledged_pref_name_; |
89 } | 83 } |
90 | 84 |
91 void ExtensionMessageBubbleController::Delegate:: | 85 void ExtensionMessageBubbleController::Delegate:: |
92 set_acknowledged_flag_pref_name(const std::string& pref_name) { | 86 set_acknowledged_flag_pref_name(const std::string& pref_name) { |
93 acknowledged_pref_name_ = pref_name; | 87 acknowledged_pref_name_ = pref_name; |
94 } | 88 } |
(...skipping 12 matching lines...) Expand all Loading... |
107 } | 101 } |
108 | 102 |
109 ExtensionMessageBubbleController::~ExtensionMessageBubbleController() { | 103 ExtensionMessageBubbleController::~ExtensionMessageBubbleController() { |
110 } | 104 } |
111 | 105 |
112 Profile* ExtensionMessageBubbleController::profile() { | 106 Profile* ExtensionMessageBubbleController::profile() { |
113 return browser_->profile(); | 107 return browser_->profile(); |
114 } | 108 } |
115 | 109 |
116 bool ExtensionMessageBubbleController::ShouldShow() { | 110 bool ExtensionMessageBubbleController::ShouldShow() { |
117 std::set<Profile*>* profiles = GetProfileSet(); | 111 std::set<Profile*>* profiles = delegate_->GetProfileSet(); |
118 return !profiles->count(profile()->GetOriginalProfile()) && | 112 return (!profiles || !profiles->count(profile()->GetOriginalProfile())) && |
119 !GetExtensionList().empty(); | 113 !GetExtensionList().empty(); |
120 } | 114 } |
121 | 115 |
122 std::vector<base::string16> | 116 std::vector<base::string16> |
123 ExtensionMessageBubbleController::GetExtensionList() { | 117 ExtensionMessageBubbleController::GetExtensionList() { |
124 ExtensionIdList* list = GetOrCreateExtensionList(); | 118 ExtensionIdList* list = GetOrCreateExtensionList(); |
125 if (list->empty()) | 119 if (list->empty()) |
126 return std::vector<base::string16>(); | 120 return std::vector<base::string16>(); |
127 | 121 |
128 ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); | 122 ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 if (delegate_->ShouldHighlightExtensions() && !did_highlight_) { | 163 if (delegate_->ShouldHighlightExtensions() && !did_highlight_) { |
170 did_highlight_ = true; | 164 did_highlight_ = true; |
171 const ExtensionIdList& extension_ids = GetExtensionIdList(); | 165 const ExtensionIdList& extension_ids = GetExtensionIdList(); |
172 DCHECK(!extension_ids.empty()); | 166 DCHECK(!extension_ids.empty()); |
173 ToolbarActionsModel::Get(profile())->HighlightActions( | 167 ToolbarActionsModel::Get(profile())->HighlightActions( |
174 extension_ids, ToolbarActionsModel::HIGHLIGHT_WARNING); | 168 extension_ids, ToolbarActionsModel::HIGHLIGHT_WARNING); |
175 } | 169 } |
176 } | 170 } |
177 | 171 |
178 void ExtensionMessageBubbleController::OnShown() { | 172 void ExtensionMessageBubbleController::OnShown() { |
179 GetProfileSet()->insert(profile()->GetOriginalProfile()); | 173 std::set<Profile*>* profiles = delegate_->GetProfileSet(); |
| 174 if (profiles) |
| 175 profiles->insert(profile()->GetOriginalProfile()); |
180 } | 176 } |
181 | 177 |
182 void ExtensionMessageBubbleController::OnBubbleAction() { | 178 void ExtensionMessageBubbleController::OnBubbleAction() { |
183 DCHECK_EQ(ACTION_BOUNDARY, user_action_); | 179 DCHECK_EQ(ACTION_BOUNDARY, user_action_); |
184 user_action_ = ACTION_EXECUTE; | 180 user_action_ = ACTION_EXECUTE; |
185 | 181 |
186 delegate_->LogAction(ACTION_EXECUTE); | 182 delegate_->LogAction(ACTION_EXECUTE); |
187 delegate_->PerformAction(*GetOrCreateExtensionList()); | 183 delegate_->PerformAction(*GetOrCreateExtensionList()); |
188 | 184 |
189 OnClose(); | 185 OnClose(); |
190 } | 186 } |
191 | 187 |
192 void ExtensionMessageBubbleController::OnBubbleDismiss( | 188 void ExtensionMessageBubbleController::OnBubbleDismiss() { |
193 bool closed_by_deactivation) { | |
194 // OnBubbleDismiss() can be called twice when we receive multiple | 189 // OnBubbleDismiss() can be called twice when we receive multiple |
195 // "OnWidgetDestroying" notifications (this can at least happen when we close | 190 // "OnWidgetDestroying" notifications (this can at least happen when we close |
196 // a window with a notification open). Handle this gracefully. | 191 // a window with a notification open). Handle this gracefully. |
197 if (user_action_ != ACTION_BOUNDARY) { | 192 if (user_action_ != ACTION_BOUNDARY) { |
198 DCHECK(user_action_ == ACTION_DISMISS_USER_ACTION || | 193 DCHECK(user_action_ == ACTION_DISMISS); |
199 user_action_ == ACTION_DISMISS_DEACTIVATION); | |
200 return; | 194 return; |
201 } | 195 } |
202 | 196 |
203 user_action_ = closed_by_deactivation ? ACTION_DISMISS_DEACTIVATION | 197 user_action_ = ACTION_DISMISS; |
204 : ACTION_DISMISS_USER_ACTION; | |
205 | 198 |
206 delegate_->LogAction(user_action_); | 199 delegate_->LogAction(ACTION_DISMISS); |
207 | 200 |
208 OnClose(); | 201 OnClose(); |
209 } | 202 } |
210 | 203 |
211 void ExtensionMessageBubbleController::OnLinkClicked() { | 204 void ExtensionMessageBubbleController::OnLinkClicked() { |
212 DCHECK_EQ(ACTION_BOUNDARY, user_action_); | 205 DCHECK_EQ(ACTION_BOUNDARY, user_action_); |
213 user_action_ = ACTION_LEARN_MORE; | 206 user_action_ = ACTION_LEARN_MORE; |
214 | 207 |
215 delegate_->LogAction(ACTION_LEARN_MORE); | 208 delegate_->LogAction(ACTION_LEARN_MORE); |
216 if (!g_should_ignore_learn_more_for_testing) { | 209 if (!g_should_ignore_learn_more_for_testing) { |
217 browser_->OpenURL( | 210 browser_->OpenURL( |
218 content::OpenURLParams(delegate_->GetLearnMoreUrl(), | 211 content::OpenURLParams(delegate_->GetLearnMoreUrl(), |
219 content::Referrer(), | 212 content::Referrer(), |
220 NEW_FOREGROUND_TAB, | 213 NEW_FOREGROUND_TAB, |
221 ui::PAGE_TRANSITION_LINK, | 214 ui::PAGE_TRANSITION_LINK, |
222 false)); | 215 false)); |
223 } | 216 } |
224 OnClose(); | 217 OnClose(); |
225 } | 218 } |
226 | 219 |
227 void ExtensionMessageBubbleController::ClearProfileListForTesting() { | |
228 GetProfileSet()->clear(); | |
229 } | |
230 | |
231 // static | 220 // static |
232 void ExtensionMessageBubbleController::set_should_ignore_learn_more_for_testing( | 221 void ExtensionMessageBubbleController::set_should_ignore_learn_more_for_testing( |
233 bool should_ignore) { | 222 bool should_ignore) { |
234 g_should_ignore_learn_more_for_testing = should_ignore; | 223 g_should_ignore_learn_more_for_testing = should_ignore; |
235 } | 224 } |
236 | 225 |
237 void ExtensionMessageBubbleController::AcknowledgeExtensions() { | 226 void ExtensionMessageBubbleController::AcknowledgeExtensions() { |
238 ExtensionIdList* list = GetOrCreateExtensionList(); | 227 ExtensionIdList* list = GetOrCreateExtensionList(); |
239 for (ExtensionIdList::const_iterator it = list->begin(); | 228 for (ExtensionIdList::const_iterator it = list->begin(); |
240 it != list->end(); ++it) | 229 it != list->end(); ++it) |
(...skipping 15 matching lines...) Expand all Loading... |
256 } | 245 } |
257 | 246 |
258 delegate_->LogExtensionCount(extension_list_.size()); | 247 delegate_->LogExtensionCount(extension_list_.size()); |
259 initialized_ = true; | 248 initialized_ = true; |
260 } | 249 } |
261 | 250 |
262 return &extension_list_; | 251 return &extension_list_; |
263 } | 252 } |
264 | 253 |
265 void ExtensionMessageBubbleController::OnClose() { | 254 void ExtensionMessageBubbleController::OnClose() { |
266 DCHECK_NE(ACTION_BOUNDARY, user_action_); | 255 AcknowledgeExtensions(); |
267 // If the bubble was closed due to deactivation, don't treat it as | |
268 // acknowledgment so that the user will see the bubble again (until they | |
269 // explicitly take an action). | |
270 if (user_action_ != ACTION_DISMISS_DEACTIVATION) { | |
271 AcknowledgeExtensions(); | |
272 if (delegate_->ClearProfileSetAfterAction()) | |
273 GetProfileSet()->clear(); | |
274 } | |
275 | |
276 if (did_highlight_) | 256 if (did_highlight_) |
277 ToolbarActionsModel::Get(profile())->StopHighlighting(); | 257 ToolbarActionsModel::Get(profile())->StopHighlighting(); |
278 } | 258 } |
279 | 259 |
280 std::set<Profile*>* ExtensionMessageBubbleController::GetProfileSet() { | |
281 return &g_shown_for_profiles.Get()[delegate_->GetKey()]; | |
282 } | |
283 | |
284 } // namespace extensions | 260 } // namespace extensions |
OLD | NEW |