| Index: chrome/browser/ui/views/toolbar/browser_action_view.cc
|
| diff --git a/chrome/browser/ui/views/toolbar/browser_action_view.cc b/chrome/browser/ui/views/toolbar/browser_action_view.cc
|
| index 28185ab00f48c2ea7e41e5cb84d04bc1af3b538c..0b4a4c5880575b74722e84e9ec96796ac3ba5b59 100644
|
| --- a/chrome/browser/ui/views/toolbar/browser_action_view.cc
|
| +++ b/chrome/browser/ui/views/toolbar/browser_action_view.cc
|
| @@ -8,15 +8,12 @@
|
|
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "chrome/browser/chrome_notification_types.h"
|
| -#include "chrome/browser/extensions/api/commands/command_service.h"
|
| #include "chrome/browser/extensions/extension_action.h"
|
| #include "chrome/browser/extensions/extension_action_manager.h"
|
| -#include "chrome/browser/extensions/extension_context_menu_model.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "chrome/browser/themes/theme_service.h"
|
| #include "chrome/browser/themes/theme_service_factory.h"
|
| #include "chrome/browser/ui/browser.h"
|
| -#include "chrome/browser/ui/extensions/accelerator_priority.h"
|
| #include "chrome/browser/ui/view_ids.h"
|
| #include "chrome/browser/ui/views/frame/browser_view.h"
|
| #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
|
| @@ -33,8 +30,6 @@
|
| #include "ui/gfx/image/image_skia_operations.h"
|
| #include "ui/gfx/image/image_skia_source.h"
|
| #include "ui/views/controls/button/label_button_border.h"
|
| -#include "ui/views/controls/menu/menu_item_view.h"
|
| -#include "ui/views/controls/menu/menu_runner.h"
|
|
|
| using extensions::Extension;
|
| using views::LabelButtonBorder;
|
| @@ -53,20 +48,16 @@ const int kBorderInset = 4;
|
| BrowserActionView::BrowserActionView(const Extension* extension,
|
| Browser* browser,
|
| BrowserActionView::Delegate* delegate)
|
| - : browser_(browser),
|
| - delegate_(delegate),
|
| - button_(NULL),
|
| - extension_(extension) {
|
| + : delegate_(delegate) {
|
| set_id(VIEW_ID_BROWSER_ACTION);
|
| - button_ = new BrowserActionButton(extension_, browser_, delegate_);
|
| + button_.reset(new BrowserActionButton(extension, browser, delegate_));
|
| button_->set_drag_controller(delegate_);
|
| button_->set_owned_by_client();
|
| - AddChildView(button_);
|
| + AddChildView(button_.get());
|
| button_->UpdateState();
|
| }
|
|
|
| BrowserActionView::~BrowserActionView() {
|
| - button_->Destroy();
|
| }
|
|
|
| gfx::ImageSkia BrowserActionView::GetIconWithBadge() {
|
| @@ -91,8 +82,8 @@ gfx::Size BrowserActionView::GetPreferredSize() const {
|
| void BrowserActionView::PaintChildren(gfx::Canvas* canvas,
|
| const views::CullSet& cull_set) {
|
| View::PaintChildren(canvas, cull_set);
|
| - ExtensionAction* action = button()->browser_action();
|
| - int tab_id = delegate_->GetCurrentTabId();
|
| + ExtensionAction* action = button_->extension_action();
|
| + int tab_id = button_->view_controller()->GetCurrentTabId();
|
| if (tab_id >= 0)
|
| action->PaintBadge(canvas, GetLocalBounds(), tab_id);
|
| }
|
| @@ -104,27 +95,26 @@ BrowserActionButton::BrowserActionButton(const Extension* extension,
|
| Browser* browser,
|
| BrowserActionView::Delegate* delegate)
|
| : MenuButton(this, base::string16(), NULL, false),
|
| - browser_(browser),
|
| - browser_action_(
|
| + view_controller_(new ExtensionActionViewController(
|
| + extension,
|
| + browser,
|
| extensions::ExtensionActionManager::Get(browser->profile())->
|
| - GetBrowserAction(*extension)),
|
| - extension_(extension),
|
| - icon_factory_(browser->profile(), extension, browser_action_, this),
|
| + GetBrowserAction(*extension),
|
| + this)),
|
| delegate_(delegate),
|
| called_registered_extension_command_(false),
|
| - popup_(NULL),
|
| icon_observer_(NULL) {
|
| SetHorizontalAlignment(gfx::ALIGN_CENTER);
|
| - set_context_menu_controller(this);
|
| + set_context_menu_controller(view_controller_.get());
|
|
|
| // No UpdateState() here because View hierarchy not setup yet. Our parent
|
| // should call UpdateState() after creation.
|
|
|
| content::NotificationSource notification_source =
|
| - content::Source<Profile>(browser_->profile()->GetOriginalProfile());
|
| + content::Source<Profile>(browser->profile()->GetOriginalProfile());
|
| registrar_.Add(this,
|
| extensions::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED,
|
| - content::Source<ExtensionAction>(browser_action_));
|
| + content::Source<ExtensionAction>(extension_action()));
|
| registrar_.Add(this,
|
| extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED,
|
| notification_source);
|
| @@ -141,22 +131,11 @@ BrowserActionButton::BrowserActionButton(const Extension* extension,
|
| ThemeServiceFactory::GetForProfile(browser->profile())));
|
| }
|
|
|
| -void BrowserActionButton::Destroy() {
|
| - MaybeUnregisterExtensionCommand(false);
|
| - HidePopup();
|
| - if (menu_runner_) {
|
| - menu_runner_->Cancel();
|
| - base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
|
| - } else {
|
| - delete this;
|
| - }
|
| -}
|
| -
|
| void BrowserActionButton::ViewHierarchyChanged(
|
| const ViewHierarchyChangedDetails& details) {
|
| if (details.is_add && !called_registered_extension_command_ &&
|
| GetFocusManager()) {
|
| - MaybeRegisterExtensionCommand();
|
| + view_controller_->RegisterCommand();
|
| called_registered_extension_command_ = true;
|
| }
|
|
|
| @@ -167,13 +146,6 @@ void BrowserActionButton::OnDragDone() {
|
| delegate_->OnBrowserActionViewDragDone();
|
| }
|
|
|
| -bool BrowserActionButton::CanHandleAccelerators() const {
|
| - // View::CanHandleAccelerators() checks to see if the view is visible before
|
| - // allowing it to process accelerators. This is not appropriate for browser
|
| - // actions buttons, which can be hidden inside the overflow area.
|
| - return true;
|
| -}
|
| -
|
| void BrowserActionButton::GetAccessibleState(ui::AXViewState* state) {
|
| views::MenuButton::GetAccessibleState(state);
|
| state->role = ui::AX_ROLE_BUTTON;
|
| @@ -181,56 +153,11 @@ void BrowserActionButton::GetAccessibleState(ui::AXViewState* state) {
|
|
|
| void BrowserActionButton::ButtonPressed(views::Button* sender,
|
| const ui::Event& event) {
|
| - ExecuteBrowserAction();
|
| -}
|
| -
|
| -void BrowserActionButton::ShowContextMenuForView(
|
| - View* source,
|
| - const gfx::Point& point,
|
| - ui::MenuSourceType source_type) {
|
| - if (!extension()->ShowConfigureContextMenus())
|
| - return;
|
| -
|
| - SetButtonPushed();
|
| -
|
| - // Reconstructs the menu every time because the menu's contents are dynamic.
|
| - scoped_refptr<ExtensionContextMenuModel> context_menu_contents(
|
| - new ExtensionContextMenuModel(extension(), browser_, this));
|
| - gfx::Point screen_loc;
|
| - views::View::ConvertPointToScreen(this, &screen_loc);
|
| -
|
| - views::Widget* parent = NULL;
|
| - int run_types = views::MenuRunner::HAS_MNEMONICS |
|
| - views::MenuRunner::CONTEXT_MENU;
|
| - if (delegate_->ShownInsideMenu()) {
|
| - run_types |= views::MenuRunner::IS_NESTED;
|
| - // RunMenuAt expects a nested menu to be parented by the same widget as the
|
| - // already visible menu, in this case the Chrome menu.
|
| - parent = BrowserView::GetBrowserViewForBrowser(browser_)->toolbar()
|
| - ->app_menu()
|
| - ->GetWidget();
|
| - } else {
|
| - parent = GetWidget();
|
| - }
|
| -
|
| - menu_runner_.reset(
|
| - new views::MenuRunner(context_menu_contents.get(), run_types));
|
| -
|
| - if (menu_runner_->RunMenuAt(parent,
|
| - NULL,
|
| - gfx::Rect(screen_loc, size()),
|
| - views::MENU_ANCHOR_TOPLEFT,
|
| - source_type) ==
|
| - views::MenuRunner::MENU_DELETED) {
|
| - return;
|
| - }
|
| -
|
| - menu_runner_.reset();
|
| - SetButtonNotPushed();
|
| + view_controller_->ExecuteActionByUser();
|
| }
|
|
|
| void BrowserActionButton::UpdateState() {
|
| - int tab_id = delegate_->GetCurrentTabId();
|
| + int tab_id = view_controller_->GetCurrentTabId();
|
| if (tab_id < 0)
|
| return;
|
|
|
| @@ -242,14 +169,14 @@ void BrowserActionButton::UpdateState() {
|
| views::CustomButton::STATE_NORMAL);
|
| }
|
|
|
| - gfx::ImageSkia icon = *icon_factory_.GetIcon(tab_id).ToImageSkia();
|
| + gfx::ImageSkia icon = *view_controller_->GetIcon(tab_id).ToImageSkia();
|
|
|
| if (!icon.isNull()) {
|
| - if (!browser_action()->GetIsVisible(tab_id))
|
| + if (!extension_action()->GetIsVisible(tab_id))
|
| icon = gfx::ImageSkiaOperations::CreateTransparentImage(icon, .25);
|
|
|
| - ThemeService* theme =
|
| - ThemeServiceFactory::GetForProfile(browser_->profile());
|
| + ThemeService* theme = ThemeServiceFactory::GetForProfile(
|
| + view_controller_->browser()->profile());
|
|
|
| gfx::ImageSkia bg = *theme->GetImageSkiaNamed(IDR_BROWSER_ACTION);
|
| SetImage(views::Button::STATE_NORMAL,
|
| @@ -257,7 +184,7 @@ void BrowserActionButton::UpdateState() {
|
| }
|
|
|
| // If the browser action name is empty, show the extension name instead.
|
| - std::string title = browser_action()->GetTitle(tab_id);
|
| + std::string title = extension_action()->GetTitle(tab_id);
|
| base::string16 name =
|
| base::UTF8ToUTF16(title.empty() ? extension()->name() : title);
|
| SetTooltipText(name);
|
| @@ -267,62 +194,8 @@ void BrowserActionButton::UpdateState() {
|
| }
|
|
|
| bool BrowserActionButton::IsPopup() {
|
| - int tab_id = delegate_->GetCurrentTabId();
|
| - return (tab_id < 0) ? false : browser_action_->HasPopup(tab_id);
|
| -}
|
| -
|
| -GURL BrowserActionButton::GetPopupUrl() {
|
| - int tab_id = delegate_->GetCurrentTabId();
|
| - return (tab_id < 0) ? GURL() : browser_action_->GetPopupUrl(tab_id);
|
| -}
|
| -
|
| -bool BrowserActionButton::ShowPopup(
|
| - ExtensionPopup::ShowAction show_action,
|
| - bool grant_tab_permissions) {
|
| - GURL popup_url;
|
| - if (delegate_->GetModel()->ExecuteBrowserAction(
|
| - extension_, browser_, &popup_url, grant_tab_permissions) ==
|
| - extensions::ExtensionToolbarModel::ACTION_NONE) {
|
| - return false;
|
| - }
|
| -
|
| - // If we're already showing the popup for this browser action, just hide it
|
| - // and return.
|
| - bool already_showing = popup_ != NULL;
|
| -
|
| - // Always hide the current popup, even if it's not the same.
|
| - // Only one popup should be visible at a time.
|
| - delegate_->HideActivePopup();
|
| - if (already_showing)
|
| - return false;
|
| -
|
| - // Browser actions in the overflow menu can still show popups, so we may need
|
| - // a reference view other than this button's parent. If so, use the overflow
|
| - // view.
|
| - views::View* reference_view =
|
| - parent()->visible() ? this : delegate_->GetOverflowReferenceView();
|
| -
|
| - popup_ = ExtensionPopup::ShowPopup(popup_url,
|
| - browser_,
|
| - reference_view,
|
| - views::BubbleBorder::TOP_RIGHT,
|
| - show_action);
|
| - popup_->GetWidget()->AddObserver(this);
|
| - delegate_->SetPopupOwner(this);
|
| -
|
| - // Only set button as pushed if it was triggered by a user click.
|
| - if (grant_tab_permissions)
|
| - SetButtonPushed();
|
| - return true;
|
| -}
|
| -
|
| -void BrowserActionButton::HidePopup() {
|
| - if (popup_)
|
| - CleanupPopup(true);
|
| -}
|
| -
|
| -void BrowserActionButton::ExecuteBrowserAction() {
|
| - ShowPopup(ExtensionPopup::SHOW, true);
|
| + int tab_id = view_controller_->GetCurrentTabId();
|
| + return (tab_id < 0) ? false : extension_action()->HasPopup(tab_id);
|
| }
|
|
|
| void BrowserActionButton::Observe(int type,
|
| @@ -340,13 +213,13 @@ void BrowserActionButton::Observe(int type,
|
| std::pair<const std::string, const std::string>* payload =
|
| content::Details<std::pair<const std::string, const std::string> >(
|
| details).ptr();
|
| - if (extension_->id() == payload->first &&
|
| + if (extension()->id() == payload->first &&
|
| payload->second ==
|
| extensions::manifest_values::kBrowserActionCommandEvent) {
|
| if (type == extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED)
|
| - MaybeRegisterExtensionCommand();
|
| + view_controller_->RegisterCommand();
|
| else
|
| - MaybeUnregisterExtensionCommand(true);
|
| + view_controller_->UnregisterCommand(true);
|
| }
|
| break;
|
| }
|
| @@ -359,17 +232,11 @@ void BrowserActionButton::Observe(int type,
|
| }
|
| }
|
|
|
| -void BrowserActionButton::OnIconUpdated() {
|
| - UpdateState();
|
| - if (icon_observer_)
|
| - icon_observer_->OnIconUpdated(GetIconWithBadge());
|
| -}
|
| -
|
| bool BrowserActionButton::Activate() {
|
| if (!IsPopup())
|
| return true;
|
|
|
| - ExecuteBrowserAction();
|
| + view_controller_->ExecuteActionByUser();
|
|
|
| // TODO(erikkay): Run a nested modal loop while the mouse is down to
|
| // enable menu-like drag-select behavior.
|
| @@ -397,7 +264,7 @@ bool BrowserActionButton::OnMousePressed(const ui::MouseEvent& event) {
|
| }
|
|
|
| void BrowserActionButton::OnMouseReleased(const ui::MouseEvent& event) {
|
| - if (IsPopup() || menu_runner_) {
|
| + if (IsPopup() || view_controller_->is_menu_running()) {
|
| // TODO(erikkay) this never actually gets called (probably because of the
|
| // loss of focus).
|
| MenuButton::OnMouseReleased(event);
|
| @@ -407,7 +274,7 @@ void BrowserActionButton::OnMouseReleased(const ui::MouseEvent& event) {
|
| }
|
|
|
| void BrowserActionButton::OnMouseExited(const ui::MouseEvent& event) {
|
| - if (IsPopup() || menu_runner_)
|
| + if (IsPopup() || view_controller_->is_menu_running())
|
| MenuButton::OnMouseExited(event);
|
| else
|
| LabelButton::OnMouseExited(event);
|
| @@ -432,18 +299,6 @@ scoped_ptr<LabelButtonBorder> BrowserActionButton::CreateDefaultBorder() const {
|
| return border.Pass();
|
| }
|
|
|
| -bool BrowserActionButton::AcceleratorPressed(
|
| - const ui::Accelerator& accelerator) {
|
| - // Normal priority shortcuts must be handled via standard browser commands to
|
| - // be processed at the proper time.
|
| - if (GetAcceleratorPriority(accelerator, extension_) ==
|
| - ui::AcceleratorManager::kNormalPriority)
|
| - return false;
|
| -
|
| - ExecuteBrowserAction();
|
| - return true;
|
| -}
|
| -
|
| void BrowserActionButton::SetButtonPushed() {
|
| SetState(views::CustomButton::STATE_PRESSED);
|
| menu_visible_ = true;
|
| @@ -455,16 +310,16 @@ void BrowserActionButton::SetButtonNotPushed() {
|
| }
|
|
|
| bool BrowserActionButton::IsEnabled(int tab_id) const {
|
| - return browser_action_->GetIsVisible(tab_id);
|
| + return view_controller_->extension_action()->GetIsVisible(tab_id);
|
| }
|
|
|
| gfx::ImageSkia BrowserActionButton::GetIconWithBadge() {
|
| - int tab_id = delegate_->GetCurrentTabId();
|
| + int tab_id = view_controller_->GetCurrentTabId();
|
| gfx::Size spacing(0, ToolbarView::kVertSpacing);
|
| - gfx::ImageSkia icon = *icon_factory_.GetIcon(tab_id).ToImageSkia();
|
| + gfx::ImageSkia icon = *view_controller_->GetIcon(tab_id).ToImageSkia();
|
| if (!IsEnabled(tab_id))
|
| icon = gfx::ImageSkiaOperations::CreateTransparentImage(icon, .25);
|
| - return browser_action_->GetIconWithBadge(icon, tab_id, spacing);
|
| + return extension_action()->GetIconWithBadge(icon, tab_id, spacing);
|
| }
|
|
|
| gfx::ImageSkia BrowserActionButton::GetIconForTest() {
|
| @@ -474,63 +329,67 @@ gfx::ImageSkia BrowserActionButton::GetIconForTest() {
|
| BrowserActionButton::~BrowserActionButton() {
|
| }
|
|
|
| -void BrowserActionButton::InspectPopup() {
|
| - ShowPopup(ExtensionPopup::SHOW_AND_INSPECT, true);
|
| -}
|
| -
|
| -void BrowserActionButton::OnWidgetDestroying(views::Widget* widget) {
|
| - DCHECK(popup_);
|
| - DCHECK_EQ(popup_->GetWidget(), widget);
|
| - CleanupPopup(false);
|
| -}
|
| -
|
| -void BrowserActionButton::MaybeRegisterExtensionCommand() {
|
| - extensions::CommandService* command_service =
|
| - extensions::CommandService::Get(browser_->profile());
|
| - extensions::Command browser_action_command;
|
| - if (command_service->GetBrowserActionCommand(
|
| - extension_->id(),
|
| - extensions::CommandService::ACTIVE_ONLY,
|
| - &browser_action_command,
|
| - NULL)) {
|
| - keybinding_.reset(new ui::Accelerator(
|
| - browser_action_command.accelerator()));
|
| - GetFocusManager()->RegisterAccelerator(
|
| - *keybinding_.get(),
|
| - GetAcceleratorPriority(browser_action_command.accelerator(),
|
| - extension_),
|
| - this);
|
| - }
|
| +void BrowserActionButton::OnIconUpdated() {
|
| + UpdateState();
|
| + if (icon_observer_)
|
| + icon_observer_->OnIconUpdated(GetIconWithBadge());
|
| }
|
|
|
| -void BrowserActionButton::MaybeUnregisterExtensionCommand(bool only_if_active) {
|
| - if (!keybinding_.get() || !GetFocusManager())
|
| - return;
|
| +views::View* BrowserActionButton::GetAsView() {
|
| + return this;
|
| +}
|
|
|
| - extensions::CommandService* command_service =
|
| - extensions::CommandService::Get(browser_->profile());
|
| -
|
| - extensions::Command browser_action_command;
|
| - if (!only_if_active || !command_service->GetBrowserActionCommand(
|
| - extension_->id(),
|
| - extensions::CommandService::ACTIVE_ONLY,
|
| - &browser_action_command,
|
| - NULL)) {
|
| - GetFocusManager()->UnregisterAccelerator(*keybinding_.get(), this);
|
| - keybinding_.reset(NULL);
|
| - }
|
| +bool BrowserActionButton::IsShownInMenu() {
|
| + return delegate_->ShownInsideMenu();
|
| }
|
|
|
| -void BrowserActionButton::CleanupPopup(bool close_widget) {
|
| - DCHECK(popup_);
|
| +views::FocusManager* BrowserActionButton::GetFocusManagerForAccelerator() {
|
| + return GetFocusManager();
|
| +}
|
| +
|
| +views::Widget* BrowserActionButton::GetParentForContextMenu() {
|
| + // RunMenuAt expects a nested menu to be parented by the same widget as the
|
| + // already visible menu, in this case the Chrome menu.
|
| + return delegate_->ShownInsideMenu() ?
|
| + BrowserView::GetBrowserViewForBrowser(view_controller_->browser())
|
| + ->toolbar()->app_menu()->GetWidget() :
|
| + GetWidget();
|
| +}
|
| +
|
| +views::View* BrowserActionButton::GetReferenceViewForPopup() {
|
| + // Browser actions in the overflow menu can still show popups, so we may need
|
| + // a reference view other than this button's parent. If so, use the overflow
|
| + // view.
|
| + return parent()->visible() ? this : delegate_->GetOverflowReferenceView();
|
| +}
|
| +
|
| +content::WebContents* BrowserActionButton::GetCurrentWebContents() {
|
| + return delegate_->GetCurrentWebContents();
|
| +}
|
| +
|
| +void BrowserActionButton::HideActivePopup() {
|
| + delegate_->HideActivePopup();
|
| +}
|
| +
|
| +void BrowserActionButton::OnPopupShown(bool grant_tab_permissions) {
|
| + delegate_->SetPopupOwner(this);
|
| + if (grant_tab_permissions)
|
| + SetButtonPushed();
|
| +}
|
| +
|
| +void BrowserActionButton::CleanupPopup() {
|
| // We need to do these actions synchronously (instead of closing and then
|
| // performing the rest of the cleanup in OnWidgetDestroyed()) because
|
| // OnWidgetDestroyed() can be called asynchronously from Close(), and we need
|
| // to keep the delegate's popup owner up-to-date.
|
| - popup_->GetWidget()->RemoveObserver(this);
|
| - if (close_widget)
|
| - popup_->GetWidget()->Close();
|
| - popup_ = NULL;
|
| SetButtonNotPushed();
|
| delegate_->SetPopupOwner(NULL);
|
| }
|
| +
|
| +void BrowserActionButton::OnWillShowContextMenus() {
|
| + SetButtonPushed();
|
| +}
|
| +
|
| +void BrowserActionButton::OnContextMenuDone() {
|
| + SetButtonNotPushed();
|
| +}
|
|
|