| Index: chrome/browser/views/browser_actions_container.cc
|
| diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc
|
| index 5dbf6ad31be80cb5c88d082f6806081418c0572f..2c9d79011cbc75a92675e15027c38f6c681298ba 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"
|
| @@ -43,34 +44,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() {
|
| @@ -90,29 +77,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();
|
| }
|
|
|
| @@ -120,14 +117,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() {
|
| @@ -190,11 +187,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() {
|
| @@ -203,8 +201,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));
|
| }
|
|
|
|
|
| @@ -219,6 +225,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,
|
| @@ -228,7 +237,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);
|
| }
|
|
|
| @@ -237,26 +248,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() {
|
| @@ -301,7 +336,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?
|
| @@ -321,7 +356,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);
|
| @@ -332,7 +367,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() {
|
| @@ -359,20 +394,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";
|
| }
|
| }
|
|
|
|
|