| Index: chrome/browser/gtk/browser_actions_toolbar_gtk.cc
|
| diff --git a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
|
| index 85ea7692fe3f24f30645c9dfd6086543e9431c90..b1d10166c1f48874da0287918b61567d34a5bcba 100644
|
| --- a/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
|
| +++ b/chrome/browser/gtk/browser_actions_toolbar_gtk.cc
|
| @@ -17,7 +17,9 @@
|
| #include "chrome/browser/gtk/gtk_chrome_button.h"
|
| #include "chrome/browser/gtk/gtk_theme_provider.h"
|
| #include "chrome/browser/profile.h"
|
| +#include "chrome/browser/tab_contents/tab_contents.h"
|
| #include "chrome/common/extensions/extension.h"
|
| +#include "chrome/common/extensions/extension_action2.h"
|
| #include "chrome/common/notification_details.h"
|
| #include "chrome/common/notification_service.h"
|
| #include "chrome/common/notification_source.h"
|
| @@ -29,28 +31,30 @@ static const int kButtonSize = 29;
|
| class BrowserActionButton : public NotificationObserver,
|
| public ImageLoadingTracker::Observer {
|
| public:
|
| - BrowserActionButton(Browser* browser, Extension* extension)
|
| - : browser_(browser),
|
| + BrowserActionButton(BrowserActionsToolbarGtk* toolbar,
|
| + Extension* extension)
|
| + : toolbar_(toolbar),
|
| extension_(extension),
|
| button_(gtk_chrome_button_new()),
|
| - gdk_icon_(NULL) {
|
| + tracker_(NULL),
|
| + tab_specific_icon_(NULL),
|
| + default_icon_(NULL) {
|
| DCHECK(extension_->browser_action());
|
|
|
| gtk_widget_set_size_request(button_.get(), kButtonSize, kButtonSize);
|
|
|
| - browser_action_icons_.resize(
|
| - extension->browser_action()->icon_paths().size());
|
| - tracker_ = new ImageLoadingTracker(this, browser_action_icons_.size());
|
| - for (size_t i = 0; i < extension->browser_action()->icon_paths().size();
|
| - ++i) {
|
| - tracker_->PostLoadImageTask(
|
| - extension->GetResource(extension->browser_action()->icon_paths()[i]),
|
| + UpdateState();
|
| +
|
| + // The Browser Action API does not allow the default icon path to be
|
| + // changed at runtime, so we can load this now and cache it.
|
| + std::string path = extension_->browser_action()->GetDefaultIconPath();
|
| + if (!path.empty()) {
|
| + tracker_ = new ImageLoadingTracker(this, 1);
|
| + tracker_->PostLoadImageTask(extension_->GetResource(path),
|
| gfx::Size(Extension::kBrowserActionIconMaxSize,
|
| Extension::kBrowserActionIconMaxSize));
|
| }
|
|
|
| - OnStateUpdated();
|
| -
|
| // We need to hook up extension popups here. http://crbug.com/23897
|
| g_signal_connect(button_.get(), "clicked",
|
| G_CALLBACK(OnButtonClicked), this);
|
| @@ -58,7 +62,7 @@ class BrowserActionButton : public NotificationObserver,
|
| G_CALLBACK(OnExposeEvent), this);
|
|
|
| registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED,
|
| - Source<ExtensionAction>(extension->browser_action()));
|
| + Source<ExtensionAction2>(extension->browser_action()));
|
| registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED,
|
| NotificationService::AllSources());
|
|
|
| @@ -66,11 +70,16 @@ class BrowserActionButton : public NotificationObserver,
|
| }
|
|
|
| ~BrowserActionButton() {
|
| - if (gdk_icon_)
|
| - g_object_unref(gdk_icon_);
|
| + if (tab_specific_icon_)
|
| + g_object_unref(tab_specific_icon_);
|
| +
|
| + if (default_icon_)
|
| + g_object_unref(default_icon_);
|
|
|
| button_.Destroy();
|
| - tracker_->StopTrackingImageLoad();
|
| +
|
| + if (tracker_)
|
| + tracker_->StopTrackingImageLoad();
|
| }
|
|
|
| GtkWidget* widget() { return button_.get(); }
|
| @@ -79,7 +88,7 @@ class BrowserActionButton : public NotificationObserver,
|
| const NotificationSource& source,
|
| const NotificationDetails& details) {
|
| if (type == NotificationType::EXTENSION_BROWSER_ACTION_UPDATED)
|
| - OnStateUpdated();
|
| + UpdateState();
|
| else if (type == NotificationType::BROWSER_THEME_CHANGED)
|
| OnThemeChanged();
|
| else
|
| @@ -88,70 +97,78 @@ class BrowserActionButton : public NotificationObserver,
|
|
|
| // ImageLoadingTracker::Observer implementation.
|
| void OnImageLoaded(SkBitmap* image, size_t index) {
|
| - DCHECK(index < browser_action_icons_.size());
|
| - browser_action_icons_[index] = image ? *image : SkBitmap();
|
| -
|
| - OnStateUpdated();
|
| + default_icon_ = gfx::GdkPixbufFromSkBitmap(image);
|
| + UpdateState();
|
| }
|
|
|
| - private:
|
| - // Called when the tooltip has changed or an image has loaded.
|
| - void OnStateUpdated() {
|
| + // Updates the button based on the latest state from the associated
|
| + // browser action.
|
| + void UpdateState() {
|
| + int tab_id = toolbar_->GetCurrentTabId();
|
| + if (tab_id < 0)
|
| + return;
|
| +
|
| gtk_widget_set_tooltip_text(button_.get(),
|
| - extension_->browser_action_state()->title().c_str());
|
| -
|
| - SkBitmap* image = extension_->browser_action_state()->icon();
|
| - if (!image) {
|
| - if (static_cast<size_t>(
|
| - extension_->browser_action_state()->icon_index()) <
|
| - browser_action_icons_.size()) {
|
| - image = &browser_action_icons_[
|
| - extension_->browser_action_state()->icon_index()];
|
| - }
|
| + extension_->browser_action()->GetTitle(tab_id).c_str());
|
| +
|
| + SkBitmap image = extension_->browser_action()->GetIcon(tab_id);
|
| + if (!image.isNull()) {
|
| + GdkPixbuf* previous_gdk_icon = tab_specific_icon_;
|
| + tab_specific_icon_ = gfx::GdkPixbufFromSkBitmap(&image);
|
| + SetImage(tab_specific_icon_);
|
| + if (previous_gdk_icon)
|
| + g_object_unref(previous_gdk_icon);
|
| + } else if (default_icon_) {
|
| + SetImage(default_icon_);
|
| }
|
| + }
|
|
|
| - if (image && !image->empty()) {
|
| - GdkPixbuf* current_gdk_icon = gdk_icon_;
|
| - gdk_icon_ = gfx::GdkPixbufFromSkBitmap(image);
|
| - gtk_button_set_image(GTK_BUTTON(button_.get()),
|
| - gtk_image_new_from_pixbuf(gdk_icon_));
|
| - if (current_gdk_icon)
|
| - g_object_unref(current_gdk_icon);
|
| - }
|
| + private:
|
| + void SetImage(GdkPixbuf* image) {
|
| + gtk_button_set_image(GTK_BUTTON(button_.get()),
|
| + gtk_image_new_from_pixbuf(image));
|
| }
|
|
|
| void OnThemeChanged() {
|
| gtk_chrome_button_set_use_gtk_rendering(GTK_CHROME_BUTTON(button_.get()),
|
| - GtkThemeProvider::GetFrom(browser_->profile())->UseGtkTheme());
|
| + GtkThemeProvider::GetFrom(
|
| + toolbar_->browser()->profile())->UseGtkTheme());
|
| }
|
|
|
| static void OnButtonClicked(GtkWidget* widget, BrowserActionButton* action) {
|
| - if (action->extension_->browser_action()->is_popup()) {
|
| - ExtensionPopupGtk::Show(action->extension_->browser_action()->popup_url(),
|
| - action->browser_, gfx::Rect(widget->allocation));
|
| -
|
| - } else {
|
| - ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
|
| - action->browser_->profile(), action->extension_->id(),
|
| - action->browser_);
|
| - }
|
| + if (action->extension_->browser_action()->has_popup()) {
|
| + ExtensionPopupGtk::Show(action->extension_->browser_action()->popup_url(),
|
| + action->toolbar_->browser(),
|
| + gfx::Rect(widget->allocation));
|
| + } else {
|
| + ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted(
|
| + action->toolbar_->browser()->profile(), action->extension_->id(),
|
| + action->toolbar_->browser());
|
| + }
|
| }
|
|
|
| static gboolean OnExposeEvent(GtkWidget* widget,
|
| GdkEventExpose* event,
|
| - BrowserActionButton* action) {
|
| - if (action->extension_->browser_action_state()->badge_text().empty())
|
| + BrowserActionButton* button) {
|
| + int tab_id = button->toolbar_->GetCurrentTabId();
|
| + if (tab_id < 0)
|
| + return FALSE;
|
| +
|
| + ExtensionAction2* action = button->extension_->browser_action();
|
| + if (action->GetBadgeText(tab_id).empty())
|
| return FALSE;
|
|
|
| gfx::CanvasPaint canvas(event, false);
|
| gfx::Rect bounding_rect(widget->allocation);
|
| - action->extension_->browser_action_state()->PaintBadge(&canvas,
|
| - bounding_rect);
|
| + ExtensionActionState::PaintBadge(&canvas, bounding_rect,
|
| + action->GetBadgeText(tab_id),
|
| + action->GetBadgeTextColor(tab_id),
|
| + action->GetBadgeBackgroundColor(tab_id));
|
| return FALSE;
|
| }
|
|
|
| - // The Browser that executes a command when the button is pressed.
|
| - Browser* browser_;
|
| + // The toolbar containing this button.
|
| + BrowserActionsToolbarGtk* toolbar_;
|
|
|
| // The extension that contains this browser action.
|
| Extension* extension_;
|
| @@ -162,13 +179,11 @@ class BrowserActionButton : public NotificationObserver,
|
| // Loads the button's icons for us on the file thread.
|
| ImageLoadingTracker* tracker_;
|
|
|
| - // Icons for all the different states the button can be in. These will be
|
| - // empty while they are loading.
|
| - std::vector<SkBitmap> browser_action_icons_;
|
| + // If we are displaying a tab-specific icon, it will be here.
|
| + GdkPixbuf* tab_specific_icon_;
|
|
|
| - // SkBitmap must be converted to GdkPixbuf before assignment to the button.
|
| - // This stores the current icon while it is in use.
|
| - GdkPixbuf* gdk_icon_;
|
| + // If the browser action has a default icon, it will be here.
|
| + GdkPixbuf* default_icon_;
|
|
|
| NotificationRegistrar registrar_;
|
| };
|
| @@ -192,6 +207,21 @@ BrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() {
|
| hbox_.Destroy();
|
| }
|
|
|
| +int BrowserActionsToolbarGtk::GetCurrentTabId() {
|
| + TabContents* selected_tab = browser_->GetSelectedTabContents();
|
| + if (!selected_tab)
|
| + return -1;
|
| +
|
| + return selected_tab->controller().session_id().id();
|
| +}
|
| +
|
| +void BrowserActionsToolbarGtk::Update() {
|
| + for (ExtensionButtonMap::iterator iter = extension_button_map_.begin();
|
| + iter != extension_button_map_.end(); ++iter) {
|
| + iter->second->UpdateState();
|
| + }
|
| +}
|
| +
|
| void BrowserActionsToolbarGtk::Observe(NotificationType type,
|
| const NotificationSource& source,
|
| const NotificationDetails& details) {
|
| @@ -212,27 +242,21 @@ void BrowserActionsToolbarGtk::CreateAllButtons() {
|
| if (!extension_service) // The |extension_service| can be NULL in Incognito.
|
| return;
|
|
|
| - // Get all browser actions, including those with popups.
|
| - std::vector<ExtensionAction*> browser_actions =
|
| - extension_service->GetBrowserActions(true);
|
| -
|
| - for (size_t i = 0; i < browser_actions.size(); ++i) {
|
| + for (size_t i = 0; i < extension_service->extensions()->size(); ++i) {
|
| Extension* extension = extension_service->GetExtensionById(
|
| - browser_actions[i]->extension_id());
|
| + extension_service->extensions()->at(i)->id());
|
| CreateButtonForExtension(extension);
|
| }
|
| }
|
|
|
| void BrowserActionsToolbarGtk::CreateButtonForExtension(Extension* extension) {
|
| - // Only show extensions with browser actions and that have an icon.
|
| - if (!extension->browser_action() ||
|
| - extension->browser_action()->icon_paths().empty()) {
|
| + // Only show extensions with browser actions.
|
| + if (!extension->browser_action())
|
| return;
|
| - }
|
|
|
| RemoveButtonForExtension(extension);
|
| linked_ptr<BrowserActionButton> button(
|
| - new BrowserActionButton(browser_, extension));
|
| + new BrowserActionButton(this, extension));
|
| gtk_box_pack_end(GTK_BOX(hbox_.get()), button->widget(), FALSE, FALSE, 0);
|
| gtk_widget_show(button->widget());
|
| extension_button_map_[extension->id()] = button;
|
|
|