| Index: chrome/browser/gtk/extension_installed_bubble_gtk.cc
|
| ===================================================================
|
| --- chrome/browser/gtk/extension_installed_bubble_gtk.cc (revision 71352)
|
| +++ chrome/browser/gtk/extension_installed_bubble_gtk.cc (working copy)
|
| @@ -1,314 +0,0 @@
|
| -// Copyright (c) 2010 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/gtk/extension_installed_bubble_gtk.h"
|
| -
|
| -#include <string>
|
| -
|
| -#include "app/l10n_util.h"
|
| -#include "app/resource_bundle.h"
|
| -#include "base/i18n/rtl.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "chrome/browser/gtk/browser_actions_toolbar_gtk.h"
|
| -#include "chrome/browser/gtk/browser_toolbar_gtk.h"
|
| -#include "chrome/browser/gtk/browser_window_gtk.h"
|
| -#include "chrome/browser/gtk/gtk_theme_provider.h"
|
| -#include "chrome/browser/gtk/gtk_util.h"
|
| -#include "chrome/browser/gtk/location_bar_view_gtk.h"
|
| -#include "chrome/browser/ui/browser.h"
|
| -#include "chrome/common/extensions/extension.h"
|
| -#include "chrome/common/extensions/extension_action.h"
|
| -#include "chrome/common/notification_details.h"
|
| -#include "chrome/common/notification_source.h"
|
| -#include "chrome/common/notification_type.h"
|
| -#include "gfx/gtk_util.h"
|
| -#include "grit/generated_resources.h"
|
| -#include "grit/theme_resources.h"
|
| -
|
| -namespace {
|
| -
|
| -const int kHorizontalColumnSpacing = 10;
|
| -const int kIconPadding = 3;
|
| -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;
|
| -
|
| -// Padding between content and edge of info bubble.
|
| -const int kContentBorder = 7;
|
| -
|
| -} // namespace
|
| -
|
| -void ExtensionInstalledBubbleGtk::Show(const Extension* extension,
|
| - Browser* browser,
|
| - SkBitmap icon) {
|
| - new ExtensionInstalledBubbleGtk(extension, browser, icon);
|
| -}
|
| -
|
| -ExtensionInstalledBubbleGtk::ExtensionInstalledBubbleGtk(
|
| - const Extension* extension, Browser *browser, SkBitmap icon)
|
| - : extension_(extension),
|
| - browser_(browser),
|
| - icon_(icon),
|
| - animation_wait_retries_(kAnimationWaitRetries) {
|
| - AddRef(); // Balanced in Close().
|
| -
|
| - if (!extension_->omnibox_keyword().empty()) {
|
| - type_ = OMNIBOX_KEYWORD;
|
| - } else if (extension_->browser_action()) {
|
| - type_ = BROWSER_ACTION;
|
| - } else if (extension->page_action() &&
|
| - !extension->page_action()->default_icon_path().empty()) {
|
| - 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, NotificationType::EXTENSION_LOADED,
|
| - Source<Profile>(browser->profile()));
|
| - registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
|
| - Source<Profile>(browser->profile()));
|
| -}
|
| -
|
| -ExtensionInstalledBubbleGtk::~ExtensionInstalledBubbleGtk() {}
|
| -
|
| -void ExtensionInstalledBubbleGtk::Observe(NotificationType type,
|
| - const NotificationSource& source,
|
| - const NotificationDetails& details) {
|
| - if (type == NotificationType::EXTENSION_LOADED) {
|
| - const Extension* extension = Details<const Extension>(details).ptr();
|
| - if (extension == extension_) {
|
| - // PostTask to ourself to allow all EXTENSION_LOADED Observers to run.
|
| - MessageLoopForUI::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
|
| - &ExtensionInstalledBubbleGtk::ShowInternal));
|
| - }
|
| - } else if (type == NotificationType::EXTENSION_UNLOADED) {
|
| - const Extension* extension =
|
| - Details<UnloadedExtensionInfo>(details)->extension;
|
| - if (extension == extension_)
|
| - extension_ = NULL;
|
| - } else {
|
| - NOTREACHED() << L"Received unexpected notification";
|
| - }
|
| -}
|
| -
|
| -void ExtensionInstalledBubbleGtk::ShowInternal() {
|
| - BrowserWindowGtk* browser_window =
|
| - BrowserWindowGtk::GetBrowserWindowForNativeWindow(
|
| - browser_->window()->GetNativeHandle());
|
| -
|
| - GtkWidget* reference_widget = NULL;
|
| -
|
| - if (type_ == BROWSER_ACTION) {
|
| - BrowserActionsToolbarGtk* toolbar =
|
| - browser_window->GetToolbar()->GetBrowserActionsToolbar();
|
| -
|
| - if (toolbar->animating() && animation_wait_retries_-- > 0) {
|
| - MessageLoopForUI::current()->PostDelayedTask(
|
| - FROM_HERE,
|
| - NewRunnableMethod(this, &ExtensionInstalledBubbleGtk::ShowInternal),
|
| - kAnimationWaitMS);
|
| - return;
|
| - }
|
| -
|
| - reference_widget = toolbar->GetBrowserActionWidget(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(
|
| - browser_window->GetToolbar()->widget()));
|
| - // If the widget is not visible then browser_window could be incognito
|
| - // with this extension disabled. Try showing it on the chevron.
|
| - // If that fails, fall back to default position.
|
| - if (reference_widget && !GTK_WIDGET_VISIBLE(reference_widget)) {
|
| - reference_widget = GTK_WIDGET_VISIBLE(toolbar->chevron()) ?
|
| - toolbar->chevron() : NULL;
|
| - }
|
| - } else if (type_ == PAGE_ACTION) {
|
| - LocationBarViewGtk* location_bar_view =
|
| - browser_window->GetToolbar()->GetLocationBarView();
|
| - location_bar_view->SetPreviewEnabledPageAction(extension_->page_action(),
|
| - true); // preview_enabled
|
| - reference_widget = location_bar_view->GetPageActionWidget(
|
| - extension_->page_action());
|
| - // glib delays recalculating layout, but we need reference_widget to know
|
| - // it's coordinates, so we force a check_resize here.
|
| - gtk_container_check_resize(GTK_CONTAINER(
|
| - browser_window->GetToolbar()->widget()));
|
| - DCHECK(reference_widget);
|
| - } else if (type_ == OMNIBOX_KEYWORD) {
|
| - LocationBarViewGtk* location_bar_view =
|
| - browser_window->GetToolbar()->GetLocationBarView();
|
| - reference_widget = location_bar_view->location_entry_widget();
|
| - DCHECK(reference_widget);
|
| - }
|
| -
|
| - // Default case.
|
| - if (reference_widget == NULL)
|
| - reference_widget = browser_window->GetToolbar()->GetAppMenuButton();
|
| -
|
| - GtkThemeProvider* theme_provider = GtkThemeProvider::GetFrom(
|
| - browser_->profile());
|
| -
|
| - // Setup the InfoBubble content.
|
| - GtkWidget* bubble_content = gtk_hbox_new(FALSE, kHorizontalColumnSpacing);
|
| - gtk_container_set_border_width(GTK_CONTAINER(bubble_content), kContentBorder);
|
| -
|
| - if (!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());
|
| - if (size.width() > kIconSize || size.height() > kIconSize) {
|
| - if (size.width() > size.height()) {
|
| - size.set_height(size.height() * kIconSize / size.width());
|
| - size.set_width(kIconSize);
|
| - } else {
|
| - size.set_width(size.width() * kIconSize / size.height());
|
| - size.set_height(kIconSize);
|
| - }
|
| -
|
| - GdkPixbuf* old = pixbuf;
|
| - pixbuf = gdk_pixbuf_scale_simple(pixbuf, size.width(), size.height(),
|
| - GDK_INTERP_BILINEAR);
|
| - g_object_unref(old);
|
| - }
|
| -
|
| - // Put Icon in top of the left column.
|
| - GtkWidget* icon_column = gtk_vbox_new(FALSE, 0);
|
| - // Use 3 pixel padding to get visual balance with InfoBubble border on the
|
| - // left.
|
| - gtk_box_pack_start(GTK_BOX(bubble_content), icon_column, FALSE, FALSE,
|
| - kIconPadding);
|
| - GtkWidget* image = gtk_image_new_from_pixbuf(pixbuf);
|
| - g_object_unref(pixbuf);
|
| - gtk_box_pack_start(GTK_BOX(icon_column), image, FALSE, FALSE, 0);
|
| - }
|
| -
|
| - // Center text column.
|
| - GtkWidget* text_column = gtk_vbox_new(FALSE, kTextColumnVerticalSpacing);
|
| - gtk_box_pack_start(GTK_BOX(bubble_content), text_column, FALSE, FALSE, 0);
|
| -
|
| - // Heading label
|
| - GtkWidget* heading_label = gtk_label_new(NULL);
|
| - string16 extension_name = UTF8ToUTF16(extension_->name());
|
| - base::i18n::AdjustStringForLocaleDirection(&extension_name);
|
| - std::string heading_text = l10n_util::GetStringFUTF8(
|
| - IDS_EXTENSION_INSTALLED_HEADING, extension_name);
|
| - char* markup = g_markup_printf_escaped("<span size=\"larger\">%s</span>",
|
| - heading_text.c_str());
|
| - gtk_label_set_markup(GTK_LABEL(heading_label), markup);
|
| - g_free(markup);
|
| -
|
| - gtk_label_set_line_wrap(GTK_LABEL(heading_label), TRUE);
|
| - gtk_widget_set_size_request(heading_label, kTextColumnWidth, -1);
|
| - gtk_box_pack_start(GTK_BOX(text_column), heading_label, FALSE, FALSE, 0);
|
| -
|
| - // Page action label
|
| - if (type_ == PAGE_ACTION) {
|
| - GtkWidget* info_label = gtk_label_new(l10n_util::GetStringUTF8(
|
| - IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO).c_str());
|
| - gtk_label_set_line_wrap(GTK_LABEL(info_label), TRUE);
|
| - gtk_widget_set_size_request(info_label, kTextColumnWidth, -1);
|
| - gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
|
| - }
|
| -
|
| - // Omnibox keyword label
|
| - if (type_ == OMNIBOX_KEYWORD) {
|
| - GtkWidget* info_label = gtk_label_new(l10n_util::GetStringFUTF8(
|
| - IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO,
|
| - UTF8ToUTF16(extension_->omnibox_keyword())).c_str());
|
| - gtk_label_set_line_wrap(GTK_LABEL(info_label), TRUE);
|
| - gtk_widget_set_size_request(info_label, kTextColumnWidth, -1);
|
| - gtk_box_pack_start(GTK_BOX(text_column), info_label, FALSE, FALSE, 0);
|
| - }
|
| -
|
| - // Manage label
|
| - GtkWidget* manage_label = gtk_label_new(
|
| - l10n_util::GetStringUTF8(IDS_EXTENSION_INSTALLED_MANAGE_INFO).c_str());
|
| - gtk_label_set_line_wrap(GTK_LABEL(manage_label), TRUE);
|
| - gtk_widget_set_size_request(manage_label, kTextColumnWidth, -1);
|
| - gtk_box_pack_start(GTK_BOX(text_column), manage_label, FALSE, FALSE, 0);
|
| -
|
| - // Create and pack the close button.
|
| - GtkWidget* close_column = gtk_vbox_new(FALSE, 0);
|
| - gtk_box_pack_start(GTK_BOX(bubble_content), close_column, FALSE, FALSE, 0);
|
| - close_button_.reset(CustomDrawButton::CloseButton(theme_provider));
|
| - g_signal_connect(close_button_->widget(), "clicked",
|
| - G_CALLBACK(OnButtonClick), this);
|
| - gtk_box_pack_start(GTK_BOX(close_column), close_button_->widget(),
|
| - FALSE, FALSE, 0);
|
| -
|
| - InfoBubbleGtk::ArrowLocationGtk arrow_location =
|
| - !base::i18n::IsRTL() ?
|
| - InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT :
|
| - InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT;
|
| -
|
| - gfx::Rect bounds = gtk_util::WidgetBounds(reference_widget);
|
| - if (type_ == 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.
|
| - arrow_location =
|
| - !base::i18n::IsRTL() ?
|
| - InfoBubbleGtk::ARROW_LOCATION_TOP_LEFT :
|
| - InfoBubbleGtk::ARROW_LOCATION_TOP_RIGHT;
|
| - if (base::i18n::IsRTL())
|
| - bounds.Offset(bounds.width(), 0);
|
| - bounds.set_width(0);
|
| - }
|
| -
|
| - info_bubble_ = InfoBubbleGtk::Show(reference_widget,
|
| - &bounds,
|
| - bubble_content,
|
| - arrow_location,
|
| - true, // match_system_theme
|
| - true, // grab_input
|
| - theme_provider,
|
| - this);
|
| -}
|
| -
|
| -// static
|
| -void ExtensionInstalledBubbleGtk::OnButtonClick(GtkWidget* button,
|
| - ExtensionInstalledBubbleGtk* bubble) {
|
| - if (button == bubble->close_button_->widget()) {
|
| - bubble->info_bubble_->Close();
|
| - } else {
|
| - NOTREACHED();
|
| - }
|
| -}
|
| -// InfoBubbleDelegate
|
| -void ExtensionInstalledBubbleGtk::InfoBubbleClosing(InfoBubbleGtk* info_bubble,
|
| - bool closed_by_escape) {
|
| - if (extension_ && type_ == PAGE_ACTION) {
|
| - // Turn the page action preview off.
|
| - BrowserWindowGtk* browser_window =
|
| - BrowserWindowGtk::GetBrowserWindowForNativeWindow(
|
| - browser_->window()->GetNativeHandle());
|
| - LocationBarViewGtk* location_bar_view =
|
| - browser_window->GetToolbar()->GetLocationBarView();
|
| - location_bar_view->SetPreviewEnabledPageAction(extension_->page_action(),
|
| - false); // preview_enabled
|
| - }
|
| -
|
| - // We need to allow the info bubble to close and remove the widgets from
|
| - // the window before we call Release() because close_button_ depends
|
| - // on all references being cleared before it is destroyed.
|
| - MessageLoopForUI::current()->PostTask(FROM_HERE, NewRunnableMethod(this,
|
| - &ExtensionInstalledBubbleGtk::Close));
|
| -}
|
| -
|
| -void ExtensionInstalledBubbleGtk::Close() {
|
| - Release(); // Balanced in ctor.
|
| - info_bubble_ = NULL;
|
| -}
|
|
|