Index: chrome/browser/extensions/extension_message_bubble_controller.cc |
diff --git a/chrome/browser/extensions/extension_message_bubble_controller.cc b/chrome/browser/extensions/extension_message_bubble_controller.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6dcfa81d2c2f8dafb434f87a83610774a5e7f99a |
--- /dev/null |
+++ b/chrome/browser/extensions/extension_message_bubble_controller.cc |
@@ -0,0 +1,256 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/extensions/extension_message_bubble_controller.h" |
+ |
+#include "base/bind.h" |
+#include "base/metrics/histogram.h" |
+#include "base/strings/utf_string_conversions.h" |
+#include "chrome/browser/extensions/extension_message_bubble.h" |
+#include "chrome/browser/extensions/extension_prefs.h" |
+#include "chrome/browser/extensions/extension_service.h" |
+#include "chrome/browser/ui/browser.h" |
+#include "chrome/browser/ui/browser_finder.h" |
+#include "chrome/common/url_constants.h" |
+#include "content/public/browser/user_metrics.h" |
+#include "grit/chromium_strings.h" |
+#include "grit/generated_resources.h" |
+#include "ui/base/l10n/l10n_util.h" |
+ |
+namespace { |
+ |
+// All the different titles we know about. |
+static const int kTitleIds[extensions::NUM_BUBBLE_TYPES] = { |
+ IDS_EXTENSIONS_SUSPICIOUS_DISABLED_TITLE, |
+ IDS_EXTENSIONS_DISABLE_DEVELOPER_MODE_TITLE, |
+}; |
+ |
+// All the different message bodies we know about. See also kBodyInjectIds. |
+static const int kBodyIds[extensions::NUM_BUBBLE_TYPES] = { |
+ IDS_EXTENSIONS_SUSPICIOUS_DISABLED_BODY, |
+ IDS_EXTENSIONS_DISABLE_DEVELOPER_MODE_BODY, |
+}; |
+ |
+// Sometimes we substitute a param in one of the kBodyIds, this specifies the |
+// value to use to replace the param. A 0 value means Accept no substitutes! |
+static const int kBodyInjectIds[extensions::NUM_BUBBLE_TYPES] = { |
+ IDS_EXTENSION_WEB_STORE_TITLE, |
+ 0, |
+}; |
+ |
+// All the labels we use for the Accept button. A 0 value means the bubble has |
+// no Accept button. |
+static const int kAcceptIds[extensions::NUM_BUBBLE_TYPES] = { |
+ 0, |
+ IDS_DISABLE, |
+}; |
+ |
+// All the labels we use for the Dismiss button. |
+static const int kDismissIds[extensions::NUM_BUBBLE_TYPES] = { |
+ IDS_EXTENSIONS_SUSPICIOUS_DISABLED_BUTTON, |
+ IDS_CANCEL, |
+}; |
+ |
+static const char* kLearnMoreLikeIds[extensions::NUM_BUBBLE_TYPES] = { |
+ chrome::kRemoveNonCWSExtensionURL, |
+ chrome::kChromeUIExtensionsURL, |
+}; |
+ |
+static const bool kShowExtensionList[extensions::NUM_BUBBLE_TYPES] = { |
+ true, |
+ false, |
+}; |
+ |
+} // namespace |
+ |
+namespace extensions { |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// ExtensionMessageBubbleController |
+ |
+ExtensionMessageBubbleController::ExtensionMessageBubbleController( |
+ ExtensionListType type, Profile* profile) |
+ : service_(extensions::ExtensionSystem::Get(profile)->extension_service()), |
+ profile_(profile), |
+ user_action_(ACTION_BOUNDARY), |
+ type_(type), |
+ has_notified_(false), |
+ showing_bubble_(false) { |
+} |
+ |
+ExtensionMessageBubbleController::~ExtensionMessageBubbleController() { |
+} |
+ |
+bool ExtensionMessageBubbleController::HasExtensionList() { |
+ if (has_notified_) |
+ return false; |
+ |
+ scoped_ptr<const ExtensionSet> extension_set( |
+ service_->GenerateInstalledExtensionsSet()); |
+ for (ExtensionSet::const_iterator it = extension_set->begin(); |
+ it != extension_set->end(); ++it) { |
+ std::string id = (*it)->id(); |
+ if (!ShouldIncludeExtension(id)) |
+ continue; |
+ extension_list_.push_back(id); |
+ } |
+ |
+ // Log the UMA histogram. |
+ switch (type_) { |
+ case SUSPICIOUS_EXTENSIONS: |
+ UMA_HISTOGRAM_COUNTS_100( |
+ "ExtensionWipeoutBubble.ExtensionWipeoutCount", |
+ extension_list_.size()); |
+ break; |
+ case DEV_MODE_EXTENSIONS: |
+ UMA_HISTOGRAM_COUNTS_100( |
+ "DevModeExtensionBubble.ExtensionsInDevModeCount", |
+ extension_list_.size()); |
+ break; |
+ case NUM_BUBBLE_TYPES: |
+ NOTREACHED(); |
+ break; |
+ } |
+ |
+ has_notified_ = true; |
+ return !extension_list_.empty(); |
+} |
+ |
+std::vector<string16> |
+ExtensionMessageBubbleController::GetExtensionList() const { |
+ if (extension_list_.empty()) |
+ return std::vector<string16>(); |
+ |
+ std::vector<string16> return_value; |
+ for (ExtensionIdList::const_iterator it = extension_list_.begin(); |
+ it != extension_list_.end(); ++it) { |
+ const Extension* extension = service_->GetInstalledExtension(*it); |
+ if (extension) { |
+ return_value.push_back(UTF8ToUTF16(extension->name())); |
+ } else { |
+ return_value.push_back( |
+ ASCIIToUTF16(std::string("(unknown name) ") + *it)); |
+ // TODO(finnur): Add this as a string to the grd, for next milestone. |
+ } |
+ } |
+ return return_value; |
+} |
+ |
+void ExtensionMessageBubbleController::Show(ExtensionMessageBubble* bubble) { |
+ // Wire up all the callbacks, to get notified what actions the user took. |
+ base::Closure dismiss_button_callback = |
+ base::Bind(&ExtensionMessageBubbleController::OnBubbleDismiss, |
+ base::Unretained(this)); |
+ base::Closure action_button_callback = |
+ base::Bind(&ExtensionMessageBubbleController::OnBubbleAction, |
+ base::Unretained(this)); |
+ base::Closure link_callback = |
+ base::Bind(&ExtensionMessageBubbleController::OnLinkClicked, |
+ base::Unretained(this)); |
+ bubble->OnActionButtonClicked(action_button_callback); |
+ bubble->OnDismissButtonClicked(dismiss_button_callback); |
+ bubble->OnLinkClicked(link_callback); |
+ |
+ showing_bubble_ = true; |
+ bubble->Show(); |
+} |
+ |
+string16 ExtensionMessageBubbleController::GetTitle() const { |
+ return l10n_util::GetStringUTF16(kTitleIds[type_]); |
+} |
+ |
+string16 ExtensionMessageBubbleController::GetMessageBody() const { |
+ if (kBodyInjectIds[type_] == 0) |
+ return l10n_util::GetStringUTF16(kBodyIds[type_]); |
+ |
+ return l10n_util::GetStringFUTF16(kBodyIds[type_], |
+ l10n_util::GetStringUTF16(kBodyInjectIds[type_])); |
+} |
+ |
+string16 ExtensionMessageBubbleController::GetOverflowText( |
+ const string16& overflow_count) const { |
+ return l10n_util::GetStringFUTF16( |
+ IDS_EXTENSIONS_SUSPICIOUS_DISABLED_AND_N_MORE, |
+ overflow_count); |
+} |
+ |
+string16 ExtensionMessageBubbleController::GetLearnMoreLabel() const { |
+ return l10n_util::GetStringUTF16(IDS_LEARN_MORE); |
+} |
+ |
+string16 ExtensionMessageBubbleController::GetActionButtonLabel() const { |
+ if (!kAcceptIds[type_]) |
+ return string16(); |
+ |
+ return l10n_util::GetStringUTF16(kAcceptIds[type_]); |
+} |
+ |
+string16 ExtensionMessageBubbleController::GetDismissButtonLabel() const { |
+ return l10n_util::GetStringUTF16(kDismissIds[type_]); |
+} |
+ |
+bool ExtensionMessageBubbleController::ShouldShowExtensionList() const { |
+ return kShowExtensionList[type_]; |
+} |
+ |
+void ExtensionMessageBubbleController::OnBubbleAction() { |
+ DCHECK_EQ(ACTION_BOUNDARY, user_action_); |
+ user_action_ = ACTION_EXECUTE; |
+ |
+ RecordAction(ACTION_EXECUTE); |
+ PerformAction(); |
+ AcknowledgeExtensions(); |
+} |
+ |
+void ExtensionMessageBubbleController::OnBubbleDismiss() { |
+ DCHECK_EQ(ACTION_BOUNDARY, user_action_); |
+ user_action_ = ACTION_DISMISS; |
+ |
+ RecordAction(ACTION_DISMISS); |
+ AcknowledgeExtensions(); |
+} |
+ |
+void ExtensionMessageBubbleController::OnLinkClicked() { |
+ DCHECK_EQ(ACTION_BOUNDARY, user_action_); |
+ user_action_ = ACTION_LEARN_MORE; |
+ |
+ RecordAction(ACTION_LEARN_MORE); |
+ Browser* browser = |
+ chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop()); |
+ if (browser) { |
+ browser->OpenURL( |
+ content::OpenURLParams(GURL(kLearnMoreLikeIds[type_]), |
+ content::Referrer(), |
+ NEW_FOREGROUND_TAB, |
+ content::PAGE_TRANSITION_LINK, |
+ false)); |
+ } |
+ AcknowledgeExtensions(); |
+} |
+ |
+void ExtensionMessageBubbleController::AcknowledgeExtensions() { |
+ for (ExtensionIdList::const_iterator it = extension_list_.begin(); |
+ it != extension_list_.end(); ++it) |
+ AcknowledgeExtension(*it); |
+ showing_bubble_ = false; |
+} |
+ |
+void ExtensionMessageBubbleController::RecordAction( |
+ UmaExtensionListHistogramOptions action) { |
+ switch (type_) { |
+ case SUSPICIOUS_EXTENSIONS: |
+ UMA_HISTOGRAM_ENUMERATION("ExtensionWipeoutBubble.UserSelection", |
+ action, ACTION_BOUNDARY); |
+ break; |
+ case DEV_MODE_EXTENSIONS: |
+ UMA_HISTOGRAM_ENUMERATION("DevModeExtensionBubble.UserSelection", |
+ action, ACTION_BOUNDARY); |
+ break; |
+ case NUM_BUBBLE_TYPES: |
+ NOTREACHED(); |
+ break; |
+ } |
+} |
+ |
+} // namespace extensions |