diff options
Diffstat (limited to 'chrome/browser/views/browser_actions_container.cc')
-rw-r--r-- | chrome/browser/views/browser_actions_container.cc | 201 |
1 files changed, 121 insertions, 80 deletions
diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index d21984b..f3f02f0 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -16,6 +16,7 @@ #include "chrome/browser/views/extensions/extension_popup.h" #include "chrome/browser/views/toolbar_view.h" #include "chrome/common/extensions/extension_action.h" +#include "chrome/common/extensions/extension_action2.h" #include "chrome/common/notification_source.h" #include "chrome/common/notification_type.h" #include "grit/app_resources.h" @@ -48,34 +49,20 @@ static const int kMinimumNumberOfVisibleBrowserActions = 2; //////////////////////////////////////////////////////////////////////////////// // BrowserActionButton -BrowserActionButton::BrowserActionButton( - ExtensionAction* browser_action, Extension* extension, - BrowserActionsContainer* panel) +BrowserActionButton::BrowserActionButton(Extension* extension, + BrowserActionsContainer* panel) : MenuButton(this, L"", NULL, false), - browser_action_(browser_action), - browser_action_state_(extension->browser_action_state()), + browser_action_(extension->browser_action()), + extension_(extension), tracker_(NULL), panel_(panel) { set_alignment(TextButton::ALIGN_CENTER); - // Load the images this view needs asynchronously on the file thread. We'll - // get a call back into OnImageLoaded if the image loads successfully. If not, - // the ImageView will have no image and will not appear in the browser chrome. - if (!browser_action->icon_paths().empty()) { - const std::vector<std::string>& icon_paths = browser_action->icon_paths(); - browser_action_icons_.resize(icon_paths.size()); - tracker_ = new ImageLoadingTracker(this, icon_paths.size()); - for (std::vector<std::string>::const_iterator iter = icon_paths.begin(); - iter != icon_paths.end(); ++iter) { - tracker_->PostLoadImageTask( - extension->GetResource(*iter), - gfx::Size(Extension::kBrowserActionIconMaxSize, - Extension::kBrowserActionIconMaxSize)); - } - } + // No UpdateState() here because View heirarchy not setup yet. Our parent + // should call UpdateState() after creation. registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, - Source<ExtensionAction>(browser_action_)); + Source<ExtensionAction2>(browser_action_)); } BrowserActionButton::~BrowserActionButton() { @@ -95,29 +82,39 @@ void BrowserActionButton::ButtonPressed( panel_->OnBrowserActionExecuted(this); } +void BrowserActionButton::LoadImage() { + // Load the default image from the browser action asynchronously on the file + // thread. We'll get a call back into OnImageLoaded if the image loads + // successfully. + std::string relative_path = browser_action()->GetDefaultIconPath(); + if (relative_path.empty()) + return; + + tracker_ = new ImageLoadingTracker(this, 1); + tracker_->PostLoadImageTask( + extension()->GetResource(relative_path), + gfx::Size(Extension::kBrowserActionIconMaxSize, + Extension::kBrowserActionIconMaxSize)); +} + void BrowserActionButton::OnImageLoaded(SkBitmap* image, size_t index) { - DCHECK(index < browser_action_icons_.size()); - browser_action_icons_[index] = image ? *image : SkBitmap(); - if (index == browser_action_icons_.size() - 1) { - OnStateUpdated(); - tracker_ = NULL; // The tracker object will delete itself when we return. - } + SetIcon(*image); + tracker_ = NULL; // The tracker object will delete itself when we return. + GetParent()->SchedulePaint(); } -void BrowserActionButton::OnStateUpdated() { - SkBitmap* image = browser_action_state_->icon(); - if (!image) { - if (static_cast<size_t>(browser_action_state_->icon_index()) < - browser_action_icons_.size()) { - image = &browser_action_icons_[browser_action_state_->icon_index()]; - } - } +void BrowserActionButton::UpdateState() { + int tab_id = panel_->GetCurrentTabId(); + if (tab_id < 0) + return; - if (image) - SetIcon(*image); + SkBitmap image = browser_action()->GetIcon(tab_id); + if (image.isNull()) + LoadImage(); + else + SetIcon(image); - SetTooltipText(ASCIIToWide(browser_action_state_->title())); - panel_->OnBrowserActionVisibilityChanged(); + SetTooltipText(ASCIIToWide(browser_action()->GetTitle(tab_id))); GetParent()->SchedulePaint(); } @@ -125,14 +122,14 @@ void BrowserActionButton::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { if (type == NotificationType::EXTENSION_BROWSER_ACTION_UPDATED) { - OnStateUpdated(); + UpdateState(); } else { NOTREACHED() << L"Received unexpected notification"; } } bool BrowserActionButton::IsPopup() { - return browser_action_->is_popup(); + return browser_action_->has_popup(); } bool BrowserActionButton::Activate() { @@ -195,11 +192,12 @@ void BrowserActionButton::PopupDidHide() { //////////////////////////////////////////////////////////////////////////////// // BrowserActionView -BrowserActionView::BrowserActionView(ExtensionAction* browser_action, - Extension* extension, - BrowserActionsContainer* panel) { - button_ = new BrowserActionButton(browser_action, extension, panel); +BrowserActionView::BrowserActionView(Extension* extension, + BrowserActionsContainer* panel) + : panel_(panel) { + button_ = new BrowserActionButton(extension, panel); AddChildView(button_); + button_->UpdateState(); } void BrowserActionView::Layout() { @@ -208,8 +206,16 @@ void BrowserActionView::Layout() { void BrowserActionView::PaintChildren(gfx::Canvas* canvas) { View::PaintChildren(canvas); - button_->browser_action_state()->PaintBadge(canvas, - gfx::Rect(width(), height())); + ExtensionAction2* action = button()->browser_action(); + int tab_id = panel_->GetCurrentTabId(); + if (tab_id < 0) + return; + + ExtensionActionState::PaintBadge( + canvas, gfx::Rect(width(), height()), + action->GetBadgeText(tab_id), + action->GetBadgeTextColor(tab_id), + action->GetBadgeBackgroundColor(tab_id)); } @@ -224,6 +230,9 @@ BrowserActionsContainer::BrowserActionsContainer( popup_button_(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { ExtensionsService* extension_service = profile->GetExtensionsService(); + if (!extension_service) // The |extension_service| can be NULL in Incognito. + return; + registrar_.Add(this, NotificationType::EXTENSION_LOADED, Source<ExtensionsService>(extension_service)); registrar_.Add(this, NotificationType::EXTENSION_UNLOADED, @@ -233,7 +242,9 @@ BrowserActionsContainer::BrowserActionsContainer( registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE, Source<Profile>(profile_)); - RefreshBrowserActionViews(); + for (size_t i = 0; i < extension_service->extensions()->size(); ++i) + AddBrowserAction(extension_service->extensions()->at(i)); + SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR); } @@ -242,26 +253,50 @@ BrowserActionsContainer::~BrowserActionsContainer() { DeleteBrowserActionViews(); } +int BrowserActionsContainer::GetCurrentTabId() { + TabContents* tab_contents = toolbar_->browser()->GetSelectedTabContents(); + if (!tab_contents) + return -1; + + return tab_contents->controller().session_id().id(); +} + void BrowserActionsContainer::RefreshBrowserActionViews() { - ExtensionsService* extension_service = profile_->GetExtensionsService(); - if (!extension_service) // The |extension_service| can be NULL in Incognito. + for (size_t i = 0; i < browser_action_views_.size(); ++i) + browser_action_views_[i]->button()->UpdateState(); +} + +void BrowserActionsContainer::AddBrowserAction(Extension* extension) { +#if defined(DEBUG) + for (size_t i = 0; i < browser_action_views_.size(); ++i) { + DCHECK(browser_action_views_[i]->button()->extension() != extension) << + "Asked to add a browser action view for an extension that already " + "exists."; + } +#endif + if (!extension->browser_action()) return; - // Get all browser actions, including those with popups. - std::vector<ExtensionAction*> browser_actions; - browser_actions = extension_service->GetBrowserActions(true); + BrowserActionView* view = new BrowserActionView(extension, this); + browser_action_views_.push_back(view); + AddChildView(view); +} - DeleteBrowserActionViews(); - for (size_t i = 0; i < browser_actions.size(); ++i) { - Extension* extension = extension_service->GetExtensionById( - browser_actions[i]->extension_id()); - DCHECK(extension); - - BrowserActionView* view = - new BrowserActionView(browser_actions[i], extension, this); - browser_action_views_.push_back(view); - AddChildView(view); +void BrowserActionsContainer::RemoveBrowserAction(Extension* extension) { + if (!extension->browser_action()) + return; + + for (std::vector<BrowserActionView*>::iterator iter = + browser_action_views_.begin(); iter != browser_action_views_.end(); + ++iter) { + if ((*iter)->button()->extension() == extension) { + RemoveChildView(*iter); + browser_action_views_.erase(iter); + return; + } } + + NOTREACHED() << "Asked to remove a browser action view that doesn't exist."; } void BrowserActionsContainer::DeleteBrowserActionViews() { @@ -306,7 +341,7 @@ void BrowserActionsContainer::TestExecuteBrowserAction(int index) { void BrowserActionsContainer::OnBrowserActionExecuted( BrowserActionButton* button) { - const ExtensionAction& browser_action = button->browser_action(); + ExtensionAction2* browser_action = button->browser_action(); // Popups just display. No notification to the extension. // TODO(erikkay): should there be? @@ -326,7 +361,7 @@ void BrowserActionsContainer::OnBrowserActionExecuted( gfx::Rect rect = button->bounds(); rect.set_x(origin.x()); rect.set_y(origin.y()); - popup_ = ExtensionPopup::Show(browser_action.popup_url(), + popup_ = ExtensionPopup::Show(browser_action->popup_url(), toolbar_->browser(), rect); popup_->set_delegate(this); @@ -337,7 +372,7 @@ void BrowserActionsContainer::OnBrowserActionExecuted( // Otherwise, we send the action to the extension. ExtensionBrowserEventRouter::GetInstance()->BrowserActionExecuted( - profile_, browser_action.extension_id(), toolbar_->browser()); + profile_, browser_action->extension_id(), toolbar_->browser()); } gfx::Size BrowserActionsContainer::GetPreferredSize() { @@ -367,20 +402,26 @@ void BrowserActionsContainer::Layout() { void BrowserActionsContainer::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { - if (type == NotificationType::EXTENSION_LOADED || - type == NotificationType::EXTENSION_UNLOADED || - type == NotificationType::EXTENSION_UNLOADED_DISABLED) { - RefreshBrowserActionViews(); - - // All these actions may change visibility of BrowserActions. - OnBrowserActionVisibilityChanged(); - } else if (type == NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE) { - if (Details<ExtensionHost>(popup_->host()) != details) - return; - - HidePopup(); - } else { - NOTREACHED() << L"Received unexpected notification"; + switch (type.value) { + case NotificationType::EXTENSION_LOADED: + AddBrowserAction(Details<Extension>(details).ptr()); + OnBrowserActionVisibilityChanged(); + break; + + case NotificationType::EXTENSION_UNLOADED: + case NotificationType::EXTENSION_UNLOADED_DISABLED: + RemoveBrowserAction(Details<Extension>(details).ptr()); + OnBrowserActionVisibilityChanged(); + break; + + case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE: + if (Details<ExtensionHost>(popup_->host()) != details) + return; + + HidePopup(); + + default: + NOTREACHED() << L"Unexpected notification"; } } |