Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: chrome/browser/extensions/extension_message_bubble_controller.cc

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

Powered by Google App Engine
This is Rietveld 408576698