| Index: chrome/browser/ui/gtk/extensions/extension_installed_bubble_gtk.cc
|
| diff --git a/chrome/browser/ui/gtk/extensions/extension_installed_bubble_gtk.cc b/chrome/browser/ui/gtk/extensions/extension_installed_bubble_gtk.cc
|
| index b1531060bea3f2b8f66d3477aefa69cd1ca9e752..3a219b956d55607765fdca38ea8082747be83136 100644
|
| --- a/chrome/browser/ui/gtk/extensions/extension_installed_bubble_gtk.cc
|
| +++ b/chrome/browser/ui/gtk/extensions/extension_installed_bubble_gtk.cc
|
| @@ -6,10 +6,7 @@
|
|
|
| #include <string>
|
|
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| #include "base/i18n/rtl.h"
|
| -#include "base/message_loop/message_loop.h"
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| #include "chrome/browser/extensions/api/commands/command_service.h"
|
| @@ -24,7 +21,6 @@
|
| #include "chrome/browser/ui/gtk/gtk_util.h"
|
| #include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
|
| #include "chrome/browser/ui/singleton_tabs.h"
|
| -#include "chrome/common/extensions/api/extension_action/action_info.h"
|
| #include "chrome/common/extensions/api/omnibox/omnibox_handler.h"
|
| #include "chrome/common/extensions/extension.h"
|
| #include "chrome/common/url_constants.h"
|
| @@ -49,12 +45,6 @@ const int kIconSize = 43;
|
| const int kTextColumnVerticalSpacing = 7;
|
| const int kTextColumnWidth = 350;
|
|
|
| -// When showing the bubble for a new browser action, we may have to wait for
|
| -// the toolbar to finish animating to know where the item's final position
|
| -// will be.
|
| -const int kAnimationWaitRetries = 10;
|
| -const int kAnimationWaitMS = 50;
|
| -
|
| } // namespace
|
|
|
| namespace chrome {
|
| @@ -75,94 +65,30 @@ void ExtensionInstalledBubbleGtk::Show(const Extension* extension,
|
|
|
| ExtensionInstalledBubbleGtk::ExtensionInstalledBubbleGtk(
|
| const Extension* extension, Browser *browser, const SkBitmap& icon)
|
| - : extension_(extension),
|
| - browser_(browser),
|
| - icon_(icon),
|
| - animation_wait_retries_(kAnimationWaitRetries),
|
| - bubble_(NULL),
|
| - weak_factory_(this) {
|
| - if (!extensions::OmniboxInfo::GetKeyword(extension_).empty())
|
| - type_ = OMNIBOX_KEYWORD;
|
| - else if (extensions::ActionInfo::GetBrowserActionInfo(extension_))
|
| - type_ = BROWSER_ACTION;
|
| - else if (extensions::ActionInfo::GetPageActionInfo(extension) &&
|
| - extensions::ActionInfo::IsVerboseInstallMessage(extension))
|
| - type_ = PAGE_ACTION;
|
| - else
|
| - type_ = GENERIC;
|
| -
|
| - // |extension| has been initialized but not loaded at this point. We need
|
| - // to wait on showing the Bubble until not only the EXTENSION_LOADED gets
|
| - // fired, but all of the EXTENSION_LOADED Observers have run. Only then can we
|
| - // be sure that a browser action or page action has had views created which we
|
| - // can inspect for the purpose of pointing to them.
|
| - registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
|
| - content::Source<Profile>(browser->profile()));
|
| - registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
|
| - content::Source<Profile>(browser->profile()));
|
| - registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSING,
|
| - content::Source<Browser>(browser));
|
| + : bubble_(this, extension, browser, icon) {
|
| }
|
|
|
| ExtensionInstalledBubbleGtk::~ExtensionInstalledBubbleGtk() {}
|
|
|
| -void ExtensionInstalledBubbleGtk::Observe(
|
| - int type,
|
| - const content::NotificationSource& source,
|
| - const content::NotificationDetails& details) {
|
| - if (type == chrome::NOTIFICATION_EXTENSION_LOADED) {
|
| - const Extension* extension =
|
| - content::Details<const Extension>(details).ptr();
|
| - if (extension == extension_) {
|
| - // PostTask to ourself to allow all EXTENSION_LOADED Observers to run.
|
| - base::MessageLoopForUI::current()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&ExtensionInstalledBubbleGtk::ShowInternal,
|
| - weak_factory_.GetWeakPtr()));
|
| - }
|
| - } else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) {
|
| - const Extension* extension =
|
| - content::Details<extensions::UnloadedExtensionInfo>(details)->extension;
|
| - if (extension == extension_) {
|
| - // Extension is going away, make sure ShowInternal won't be called.
|
| - weak_factory_.InvalidateWeakPtrs();
|
| - extension_ = NULL;
|
| - }
|
| - } else if (type == chrome::NOTIFICATION_BROWSER_CLOSING) {
|
| - // The browser closed before the bubble could be created.
|
| - if (!bubble_)
|
| - delete this;
|
| - } else {
|
| - NOTREACHED() << L"Received unexpected notification";
|
| - }
|
| -}
|
| -
|
| void ExtensionInstalledBubbleGtk::OnDestroy(GtkWidget* widget) {
|
| - bubble_ = NULL;
|
| + gtk_bubble_ = NULL;
|
| delete this;
|
| }
|
|
|
| -void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| +bool ExtensionInstalledBubbleGtk::MaybeShowNow() {
|
| BrowserWindowGtk* browser_window =
|
| BrowserWindowGtk::GetBrowserWindowForNativeWindow(
|
| - browser_->window()->GetNativeWindow());
|
| + bubble_.browser()->window()->GetNativeWindow());
|
|
|
| GtkWidget* reference_widget = NULL;
|
|
|
| - if (type_ == BROWSER_ACTION) {
|
| + if (bubble_.type() == bubble_.BROWSER_ACTION) {
|
| BrowserActionsToolbarGtk* toolbar =
|
| browser_window->GetToolbar()->GetBrowserActionsToolbar();
|
| + if (toolbar->animating())
|
| + return false;
|
|
|
| - if (toolbar->animating() && animation_wait_retries_-- > 0) {
|
| - base::MessageLoopForUI::current()->PostDelayedTask(
|
| - FROM_HERE,
|
| - base::Bind(&ExtensionInstalledBubbleGtk::ShowInternal,
|
| - weak_factory_.GetWeakPtr()),
|
| - base::TimeDelta::FromMilliseconds(kAnimationWaitMS));
|
| - return;
|
| - }
|
| -
|
| - reference_widget = toolbar->GetBrowserActionWidget(extension_);
|
| + reference_widget = toolbar->GetBrowserActionWidget(bubble_.extension());
|
| // glib delays recalculating layout, but we need reference_widget to know
|
| // its coordinates, so we force a check_resize here.
|
| gtk_container_check_resize(GTK_CONTAINER(
|
| @@ -174,12 +100,12 @@ void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| reference_widget = gtk_widget_get_visible(toolbar->chevron()) ?
|
| toolbar->chevron() : NULL;
|
| }
|
| - } else if (type_ == PAGE_ACTION) {
|
| + } else if (bubble_.type() == bubble_.PAGE_ACTION) {
|
| LocationBarViewGtk* location_bar_view =
|
| browser_window->GetToolbar()->GetLocationBarView();
|
| ExtensionAction* page_action =
|
| - ExtensionActionManager::Get(browser_->profile())->
|
| - GetPageAction(*extension_);
|
| + ExtensionActionManager::Get(bubble_.browser()->profile())->
|
| + GetPageAction(*bubble_.extension());
|
| location_bar_view->SetPreviewEnabledPageAction(page_action,
|
| true); // preview_enabled
|
| reference_widget = location_bar_view->GetPageActionWidget(page_action);
|
| @@ -188,7 +114,7 @@ void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| gtk_container_check_resize(GTK_CONTAINER(
|
| browser_window->GetToolbar()->widget()));
|
| DCHECK(reference_widget);
|
| - } else if (type_ == OMNIBOX_KEYWORD) {
|
| + } else if (bubble_.type() == bubble_.OMNIBOX_KEYWORD) {
|
| LocationBarViewGtk* location_bar_view =
|
| browser_window->GetToolbar()->GetLocationBarView();
|
| reference_widget = location_bar_view->location_entry_widget();
|
| @@ -200,17 +126,17 @@ void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| reference_widget = browser_window->GetToolbar()->GetAppMenuButton();
|
|
|
| GtkThemeService* theme_provider = GtkThemeService::GetFrom(
|
| - browser_->profile());
|
| + bubble_.browser()->profile());
|
|
|
| // Setup the BubbleGtk content.
|
| GtkWidget* bubble_content = gtk_hbox_new(FALSE, kHorizontalColumnSpacing);
|
| gtk_container_set_border_width(GTK_CONTAINER(bubble_content),
|
| ui::kContentAreaBorder);
|
|
|
| - if (!icon_.isNull()) {
|
| + if (!bubble_.icon().isNull()) {
|
| // Scale icon down to 43x43, but allow smaller icons (don't scale up).
|
| - GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(icon_);
|
| - gfx::Size size(icon_.width(), icon_.height());
|
| + GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(bubble_.icon());
|
| + gfx::Size size(bubble_.icon().width(), bubble_.icon().height());
|
| if (size.width() > kIconSize || size.height() > kIconSize) {
|
| if (size.width() > size.height()) {
|
| size.set_height(size.height() * kIconSize / size.width());
|
| @@ -243,7 +169,7 @@ void ExtensionInstalledBubbleGtk::ShowInternal() {
|
|
|
| // Heading label.
|
| GtkWidget* heading_label = gtk_label_new(NULL);
|
| - string16 extension_name = UTF8ToUTF16(extension_->name());
|
| + string16 extension_name = UTF8ToUTF16(bubble_.extension()->name());
|
| base::i18n::AdjustStringForLocaleDirection(&extension_name);
|
| std::string heading_text = l10n_util::GetStringFUTF8(
|
| IDS_EXTENSION_INSTALLED_HEADING, extension_name);
|
| @@ -258,13 +184,13 @@ void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| bool has_keybinding = false;
|
|
|
| // Browser action label.
|
| - if (type_ == BROWSER_ACTION) {
|
| + if (bubble_.type() == bubble_.BROWSER_ACTION) {
|
| extensions::CommandService* command_service =
|
| - extensions::CommandService::Get(browser_->profile());
|
| + extensions::CommandService::Get(bubble_.browser()->profile());
|
| extensions::Command browser_action_command;
|
| GtkWidget* info_label;
|
| if (!command_service->GetBrowserActionCommand(
|
| - extension_->id(),
|
| + bubble_.extension()->id(),
|
| extensions::CommandService::ACTIVE_ONLY,
|
| &browser_action_command,
|
| NULL)) {
|
| @@ -281,13 +207,13 @@ void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| }
|
|
|
| // Page action label.
|
| - if (type_ == PAGE_ACTION) {
|
| + if (bubble_.type() == bubble_.PAGE_ACTION) {
|
| extensions::CommandService* command_service =
|
| - extensions::CommandService::Get(browser_->profile());
|
| + extensions::CommandService::Get(bubble_.browser()->profile());
|
| extensions::Command page_action_command;
|
| GtkWidget* info_label;
|
| if (!command_service->GetPageActionCommand(
|
| - extension_->id(),
|
| + bubble_.extension()->id(),
|
| extensions::CommandService::ACTIVE_ONLY,
|
| &page_action_command,
|
| NULL)) {
|
| @@ -304,10 +230,11 @@ void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| }
|
|
|
| // Omnibox keyword label.
|
| - if (type_ == OMNIBOX_KEYWORD) {
|
| + if (bubble_.type() == bubble_.OMNIBOX_KEYWORD) {
|
| GtkWidget* info_label = gtk_label_new(l10n_util::GetStringFUTF8(
|
| IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO,
|
| - UTF8ToUTF16(extensions::OmniboxInfo::GetKeyword(extension_))).c_str());
|
| + UTF8ToUTF16(extensions::OmniboxInfo::GetKeyword(
|
| + bubble_.extension()))).c_str());
|
| gtk_util::SetLabelWidth(info_label, kTextColumnWidth);
|
| gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
|
| }
|
| @@ -341,7 +268,7 @@ void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| BubbleGtk::FrameStyle frame_style = BubbleGtk::ANCHOR_TOP_RIGHT;
|
|
|
| gfx::Rect bounds = gtk_util::WidgetBounds(reference_widget);
|
| - if (type_ == OMNIBOX_KEYWORD) {
|
| + if (bubble_.type() == bubble_.OMNIBOX_KEYWORD) {
|
| // Reverse the arrow for omnibox keywords, since the bubble will be on the
|
| // other side of the window. We also clear the width to avoid centering
|
| // the popup on the URL bar.
|
| @@ -351,52 +278,57 @@ void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| bounds.set_width(0);
|
| }
|
|
|
| - bubble_ = BubbleGtk::Show(reference_widget,
|
| - &bounds,
|
| - bubble_content,
|
| - frame_style,
|
| - BubbleGtk::MATCH_SYSTEM_THEME |
|
| + gtk_bubble_ = BubbleGtk::Show(reference_widget,
|
| + &bounds,
|
| + bubble_content,
|
| + frame_style,
|
| + BubbleGtk::MATCH_SYSTEM_THEME |
|
| BubbleGtk::POPUP_WINDOW |
|
| BubbleGtk::GRAB_INPUT,
|
| - theme_provider,
|
| - this);
|
| + theme_provider,
|
| + this);
|
| g_signal_connect(bubble_content, "destroy",
|
| G_CALLBACK(&OnDestroyThunk), this);
|
| +
|
| + // gtk_bubble_ is now the owner of |this| and deletes it when the bubble
|
| + // goes away.
|
| + bubble_.IgnoreBrowserClosing();
|
| + return true;
|
| }
|
|
|
| // static
|
| void ExtensionInstalledBubbleGtk::OnButtonClick(GtkWidget* button,
|
| ExtensionInstalledBubbleGtk* bubble) {
|
| if (button == bubble->close_button_->widget()) {
|
| - bubble->bubble_->Close();
|
| + bubble->gtk_bubble_->Close();
|
| } else {
|
| NOTREACHED();
|
| }
|
| }
|
|
|
| void ExtensionInstalledBubbleGtk::OnLinkClicked(GtkWidget* widget) {
|
| - bubble_->Close();
|
| + gtk_bubble_->Close();
|
|
|
| std::string configure_url = chrome::kChromeUIExtensionsURL;
|
| configure_url += chrome::kExtensionConfigureCommandsSubPage;
|
| chrome::NavigateParams params(
|
| chrome::GetSingletonTabNavigateParams(
|
| - browser_, GURL(configure_url.c_str())));
|
| + bubble_.browser(), GURL(configure_url.c_str())));
|
| chrome::Navigate(¶ms);
|
| }
|
|
|
| void ExtensionInstalledBubbleGtk::BubbleClosing(BubbleGtk* bubble,
|
| bool closed_by_escape) {
|
| - if (extension_ && type_ == PAGE_ACTION) {
|
| + if (bubble_.extension() && bubble_.type() == bubble_.PAGE_ACTION) {
|
| // Turn the page action preview off.
|
| BrowserWindowGtk* browser_window =
|
| BrowserWindowGtk::GetBrowserWindowForNativeWindow(
|
| - browser_->window()->GetNativeWindow());
|
| + bubble_.browser()->window()->GetNativeWindow());
|
| LocationBarViewGtk* location_bar_view =
|
| browser_window->GetToolbar()->GetLocationBarView();
|
| location_bar_view->SetPreviewEnabledPageAction(
|
| - ExtensionActionManager::Get(browser_->profile())->
|
| - GetPageAction(*extension_),
|
| + ExtensionActionManager::Get(bubble_.browser()->profile())->
|
| + GetPageAction(*bubble_.extension()),
|
| false); // preview_enabled
|
| }
|
| }
|
|
|