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(); |
+} |