| 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 |