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

Unified Diff: chrome/browser/ui/views/extensions/extension_message_bubble_view.cc

Issue 1081113002: Revert of [Extensions] Make extension message bubble factory platform-abstract (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
diff --git a/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
index a2b70d479088a19c95ada0f5f36d95aad2d49982..578d693c599f3c1b9db7b2fdcbd6200f058d8c29 100644
--- a/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
@@ -7,9 +7,24 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/dev_mode_bubble_controller.h"
+#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_message_bubble_controller.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_toolbar_model.h"
+#include "chrome/browser/extensions/proxy_overridden_bubble_controller.h"
+#include "chrome/browser/extensions/settings_api_bubble_controller.h"
+#include "chrome/browser/extensions/settings_api_helpers.h"
+#include "chrome/browser/extensions/suspicious_extension_bubble_controller.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/view_ids.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
+#include "chrome/browser/ui/views/toolbar/browser_actions_container_observer.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "chrome/grit/locale_settings.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_system.h"
#include "ui/accessibility/ax_view_state.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/controls/button/label_button.h"
@@ -20,6 +35,9 @@
#include "ui/views/widget/widget.h"
namespace {
+
+base::LazyInstance<std::set<Profile*> > g_profiles_evaluated =
+ LAZY_INSTANCE_INITIALIZER;
// Layout constants.
const int kExtensionListPadding = 10;
@@ -61,6 +79,21 @@
set_anchor_view_insets(gfx::Insets(5, 0, 5, 0));
}
+void ExtensionMessageBubbleView::OnActionButtonClicked(
+ const base::Closure& callback) {
+ action_callback_ = callback;
+}
+
+void ExtensionMessageBubbleView::OnDismissButtonClicked(
+ const base::Closure& callback) {
+ dismiss_callback_ = callback;
+}
+
+void ExtensionMessageBubbleView::OnLinkClicked(
+ const base::Closure& callback) {
+ link_callback_ = callback;
+}
+
void ExtensionMessageBubbleView::Show() {
// Not showing the bubble right away (during startup) has a few benefits:
// We don't have to worry about focus being lost due to the Omnibox (or to
@@ -81,7 +114,7 @@
// To catch Esc, we monitor destroy message. Unless the link has been clicked,
// we assume Dismiss was the action taken.
if (!link_clicked_ && !action_taken_)
- controller_->OnBubbleDismiss();
+ dismiss_callback_.Run();
}
////////////////////////////////////////////////////////////////////////////////
@@ -208,7 +241,7 @@
const ui::Event& event) {
if (sender == action_button_) {
action_taken_ = true;
- controller_->OnBubbleAction();
+ action_callback_.Run();
} else {
DCHECK_EQ(dismiss_button_, sender);
}
@@ -219,7 +252,7 @@
int event_flags) {
DCHECK_EQ(learn_more_, source);
link_clicked_ = true;
- controller_->OnLinkClicked();
+ link_callback_.Run();
GetWidget()->Close();
}
@@ -234,4 +267,243 @@
NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
}
+////////////////////////////////////////////////////////////////////////////////
+// ExtensionMessageBubbleFactory
+
+ExtensionMessageBubbleFactory::ExtensionMessageBubbleFactory(
+ Profile* profile,
+ ToolbarView* toolbar_view)
+ : profile_(profile),
+ toolbar_view_(toolbar_view),
+ shown_suspicious_extensions_bubble_(false),
+ shown_startup_override_extensions_bubble_(false),
+ shown_proxy_override_extensions_bubble_(false),
+ shown_dev_mode_extensions_bubble_(false),
+ is_observing_(false),
+ stage_(STAGE_START),
+ container_(NULL),
+ anchor_view_(NULL) {}
+
+ExtensionMessageBubbleFactory::~ExtensionMessageBubbleFactory() {
+ MaybeStopObserving();
+}
+
+void ExtensionMessageBubbleFactory::MaybeShow(views::View* anchor_view) {
+#if defined(OS_WIN)
+ bool is_initial_check = IsInitialProfileCheck(profile_->GetOriginalProfile());
+ RecordProfileCheck(profile_->GetOriginalProfile());
+
+ // The list of suspicious extensions takes priority over the dev mode bubble
+ // and the settings API bubble, since that needs to be shown as soon as we
+ // disable something. The settings API bubble is shown on first startup after
+ // an extension has changed the startup pages and it is acceptable if that
+ // waits until the next startup because of the suspicious extension bubble.
+ // The dev mode bubble is not time sensitive like the other two so we'll catch
+ // the dev mode extensions on the next startup/next window that opens. That
+ // way, we're not too spammy with the bubbles.
+ if (!shown_suspicious_extensions_bubble_ &&
+ MaybeShowSuspiciousExtensionsBubble(anchor_view))
+ return;
+
+ if (!shown_startup_override_extensions_bubble_ &&
+ is_initial_check &&
+ MaybeShowStartupOverrideExtensionsBubble(anchor_view))
+ return;
+
+ if (!shown_proxy_override_extensions_bubble_ &&
+ MaybeShowProxyOverrideExtensionsBubble(anchor_view))
+ return;
+
+ if (!shown_dev_mode_extensions_bubble_)
+ MaybeShowDevModeExtensionsBubble(anchor_view);
+#endif // OS_WIN
+}
+
+bool ExtensionMessageBubbleFactory::MaybeShowSuspiciousExtensionsBubble(
+ views::View* anchor_view) {
+ DCHECK(!shown_suspicious_extensions_bubble_);
+
+ scoped_ptr<SuspiciousExtensionBubbleController> suspicious_extensions(
+ new SuspiciousExtensionBubbleController(profile_));
+ if (!suspicious_extensions->ShouldShow())
+ return false;
+
+ shown_suspicious_extensions_bubble_ = true;
+ SuspiciousExtensionBubbleController* weak_controller =
+ suspicious_extensions.get();
+ ExtensionMessageBubbleView* bubble_delegate =
+ new ExtensionMessageBubbleView(anchor_view,
+ views::BubbleBorder::TOP_RIGHT,
+ suspicious_extensions.Pass());
+
+ views::BubbleDelegateView::CreateBubble(bubble_delegate);
+ weak_controller->Show(bubble_delegate);
+
+ return true;
+}
+
+bool ExtensionMessageBubbleFactory::MaybeShowStartupOverrideExtensionsBubble(
+ views::View* anchor_view) {
+#if !defined(OS_WIN)
+ return false;
+#else
+ DCHECK(!shown_startup_override_extensions_bubble_);
+
+ const Extension* extension = GetExtensionOverridingStartupPages(profile_);
+ if (!extension)
+ return false;
+
+ scoped_ptr<SettingsApiBubbleController> settings_api_bubble(
+ new SettingsApiBubbleController(profile_,
+ BUBBLE_TYPE_STARTUP_PAGES));
+ if (!settings_api_bubble->ShouldShow(extension->id()))
+ return false;
+
+ shown_startup_override_extensions_bubble_ = true;
+ PrepareToHighlightExtensions(settings_api_bubble.Pass(), anchor_view);
+ return true;
+#endif
+}
+
+bool ExtensionMessageBubbleFactory::MaybeShowProxyOverrideExtensionsBubble(
+ views::View* anchor_view) {
+#if !defined(OS_WIN)
+ return false;
+#else
+ DCHECK(!shown_proxy_override_extensions_bubble_);
+
+ const Extension* extension = GetExtensionOverridingProxy(profile_);
+ if (!extension)
+ return false;
+
+ scoped_ptr<ProxyOverriddenBubbleController> proxy_bubble(
+ new ProxyOverriddenBubbleController(profile_));
+ if (!proxy_bubble->ShouldShow(extension->id()))
+ return false;
+
+ shown_proxy_override_extensions_bubble_ = true;
+ PrepareToHighlightExtensions(proxy_bubble.Pass(), anchor_view);
+ return true;
+#endif
+}
+
+bool ExtensionMessageBubbleFactory::MaybeShowDevModeExtensionsBubble(
+ views::View* anchor_view) {
+ DCHECK(!shown_dev_mode_extensions_bubble_);
+
+ // Check the Developer Mode extensions.
+ scoped_ptr<DevModeBubbleController> dev_mode_extensions(
+ new DevModeBubbleController(profile_));
+
+ // Return early if we have none to show.
+ if (!dev_mode_extensions->ShouldShow())
+ return false;
+
+ shown_dev_mode_extensions_bubble_ = true;
+ PrepareToHighlightExtensions(dev_mode_extensions.Pass(), anchor_view);
+ return true;
+}
+
+void ExtensionMessageBubbleFactory::MaybeObserve() {
+ if (!is_observing_) {
+ is_observing_ = true;
+ container_->AddObserver(this);
+ }
+}
+
+void ExtensionMessageBubbleFactory::MaybeStopObserving() {
+ if (is_observing_) {
+ is_observing_ = false;
+ container_->RemoveObserver(this);
+ }
+}
+
+void ExtensionMessageBubbleFactory::RecordProfileCheck(Profile* profile) {
+ g_profiles_evaluated.Get().insert(profile);
+}
+
+bool ExtensionMessageBubbleFactory::IsInitialProfileCheck(Profile* profile) {
+ return g_profiles_evaluated.Get().count(profile) == 0;
+}
+
+void ExtensionMessageBubbleFactory::OnBrowserActionsContainerAnimationEnded() {
+ MaybeStopObserving();
+ if (stage_ == STAGE_START) {
+ HighlightExtensions();
+ } else if (stage_ == STAGE_HIGHLIGHTED) {
+ ShowHighlightingBubble();
+ } else { // We shouldn't be observing if we've completed the process.
+ NOTREACHED();
+ Finish();
+ }
+}
+
+void ExtensionMessageBubbleFactory::OnBrowserActionsContainerDestroyed() {
+ // If the container associated with the bubble is destroyed, abandon the
+ // process.
+ Finish();
+}
+
+void ExtensionMessageBubbleFactory::PrepareToHighlightExtensions(
+ scoped_ptr<ExtensionMessageBubbleController> controller,
+ views::View* anchor_view) {
+ // We should be in the start stage (i.e., should not have a pending attempt to
+ // show a bubble).
+ DCHECK_EQ(stage_, STAGE_START);
+
+ // Prepare to display and highlight the extensions before showing the bubble.
+ // Since this is an asynchronous process, set member variables for later use.
+ controller_ = controller.Pass();
+ anchor_view_ = anchor_view;
+ container_ = toolbar_view_->browser_actions();
+
+ if (container_->animating())
+ MaybeObserve();
+ else
+ HighlightExtensions();
+}
+
+void ExtensionMessageBubbleFactory::HighlightExtensions() {
+ DCHECK_EQ(STAGE_START, stage_);
+ stage_ = STAGE_HIGHLIGHTED;
+
+ const ExtensionIdList extension_list = controller_->GetExtensionIdList();
+ DCHECK(!extension_list.empty());
+ ExtensionToolbarModel::Get(profile_)->HighlightExtensions(extension_list);
+ if (container_->animating())
+ MaybeObserve();
+ else
+ ShowHighlightingBubble();
+}
+
+void ExtensionMessageBubbleFactory::ShowHighlightingBubble() {
+ DCHECK_EQ(stage_, STAGE_HIGHLIGHTED);
+ stage_ = STAGE_COMPLETE;
+
+ views::View* reference_view = NULL;
+ if (container_->num_toolbar_actions() > 0u)
+ reference_view = container_->GetToolbarActionViewAt(0);
+ if (reference_view && reference_view->visible())
+ anchor_view_ = reference_view;
+
+ ExtensionMessageBubbleController* weak_controller = controller_.get();
+ ExtensionMessageBubbleView* bubble_delegate =
+ new ExtensionMessageBubbleView(
+ anchor_view_,
+ views::BubbleBorder::TOP_RIGHT,
+ scoped_ptr<ExtensionMessageBubbleController>(
+ controller_.release()));
+ views::BubbleDelegateView::CreateBubble(bubble_delegate);
+ weak_controller->Show(bubble_delegate);
+
+ Finish();
+}
+
+void ExtensionMessageBubbleFactory::Finish() {
+ MaybeStopObserving();
+ controller_.reset();
+ anchor_view_ = NULL;
+ container_ = NULL;
+}
+
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698