| 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" |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |