Chromium Code Reviews| 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..8a8dc5b743ce5b68785c66ab17e78811be807e82 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,12 +48,10 @@ const int kBorderInset = 4; |
| BrowserActionView::BrowserActionView(const Extension* extension, |
| Browser* browser, |
| BrowserActionView::Delegate* delegate) |
| - : browser_(browser), |
| - delegate_(delegate), |
| - button_(NULL), |
| - extension_(extension) { |
| + : delegate_(delegate), |
| + button_(NULL) { |
| set_id(VIEW_ID_BROWSER_ACTION); |
| - button_ = new BrowserActionButton(extension_, browser_, delegate_); |
| + button_ = new BrowserActionButton(extension, browser, delegate_); |
| button_->set_drag_controller(delegate_); |
| button_->set_owned_by_client(); |
| AddChildView(button_); |
| @@ -66,7 +59,7 @@ BrowserActionView::BrowserActionView(const Extension* extension, |
| } |
| BrowserActionView::~BrowserActionView() { |
| - button_->Destroy(); |
| + delete button_; |
| } |
| gfx::ImageSkia BrowserActionView::GetIconWithBadge() { |
| @@ -91,8 +84,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_->extension_action_view()->GetCurrentTabId(); |
| if (tab_id >= 0) |
| action->PaintBadge(canvas, GetLocalBounds(), tab_id); |
| } |
| @@ -104,27 +97,26 @@ BrowserActionButton::BrowserActionButton(const Extension* extension, |
| Browser* browser, |
| BrowserActionView::Delegate* delegate) |
| : MenuButton(this, base::string16(), NULL, false), |
| - browser_(browser), |
| - browser_action_( |
| + extension_action_view_(new ExtensionActionView( |
| + 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(extension_action_view_.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 +133,11 @@ BrowserActionButton::BrowserActionButton(const Extension* extension, |
| ThemeServiceFactory::GetForProfile(browser->profile()))); |
| } |
| -void BrowserActionButton::Destroy() { |
|
Devlin
2014/08/05 20:08:57
Pretty sure we don't need this - when menu_runner_
|
| - 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(); |
| + extension_action_view_->RegisterCommand(); |
| called_registered_extension_command_ = true; |
| } |
| @@ -181,56 +162,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(); |
| + extension_action_view_->ExecuteActionByUser(); |
| } |
| void BrowserActionButton::UpdateState() { |
| - int tab_id = delegate_->GetCurrentTabId(); |
| + int tab_id = extension_action_view_->GetCurrentTabId(); |
| if (tab_id < 0) |
| return; |
| @@ -242,14 +178,15 @@ void BrowserActionButton::UpdateState() { |
| views::CustomButton::STATE_NORMAL); |
| } |
| - gfx::ImageSkia icon = *icon_factory_.GetIcon(tab_id).ToImageSkia(); |
| + gfx::ImageSkia icon = *extension_action_view_->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()); |
| + ThemeServiceFactory::GetForProfile( |
| + extension_action_view_->browser()->profile()); |
| gfx::ImageSkia bg = *theme->GetImageSkiaNamed(IDR_BROWSER_ACTION); |
| SetImage(views::Button::STATE_NORMAL, |
| @@ -257,7 +194,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 +204,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 = extension_action_view_->GetCurrentTabId(); |
| + return (tab_id < 0) ? false : extension_action()->HasPopup(tab_id); |
| } |
| void BrowserActionButton::Observe(int type, |
| @@ -340,13 +223,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(); |
| + extension_action_view_->RegisterCommand(); |
| else |
| - MaybeUnregisterExtensionCommand(true); |
| + extension_action_view_->UnregisterCommand(true); |
| } |
| break; |
| } |
| @@ -359,17 +242,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(); |
| + extension_action_view_->ExecuteActionByUser(); |
| // TODO(erikkay): Run a nested modal loop while the mouse is down to |
| // enable menu-like drag-select behavior. |
| @@ -397,7 +274,7 @@ bool BrowserActionButton::OnMousePressed(const ui::MouseEvent& event) { |
| } |
| void BrowserActionButton::OnMouseReleased(const ui::MouseEvent& event) { |
| - if (IsPopup() || menu_runner_) { |
| + if (IsPopup() || extension_action_view_->is_menu_running()) { |
| // TODO(erikkay) this never actually gets called (probably because of the |
| // loss of focus). |
| MenuButton::OnMouseReleased(event); |
| @@ -407,7 +284,7 @@ void BrowserActionButton::OnMouseReleased(const ui::MouseEvent& event) { |
| } |
| void BrowserActionButton::OnMouseExited(const ui::MouseEvent& event) { |
| - if (IsPopup() || menu_runner_) |
| + if (IsPopup() || extension_action_view_->is_menu_running()) |
| MenuButton::OnMouseExited(event); |
| else |
| LabelButton::OnMouseExited(event); |
| @@ -434,14 +311,7 @@ scoped_ptr<LabelButtonBorder> BrowserActionButton::CreateDefaultBorder() const { |
| 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; |
| + return extension_action_view_->AcceleratorPressed(accelerator); |
| } |
| void BrowserActionButton::SetButtonPushed() { |
| @@ -455,16 +325,16 @@ void BrowserActionButton::SetButtonNotPushed() { |
| } |
| bool BrowserActionButton::IsEnabled(int tab_id) const { |
| - return browser_action_->GetIsVisible(tab_id); |
| + return extension_action_view_->extension_action()->GetIsVisible(tab_id); |
| } |
| gfx::ImageSkia BrowserActionButton::GetIconWithBadge() { |
| - int tab_id = delegate_->GetCurrentTabId(); |
| + int tab_id = extension_action_view_->GetCurrentTabId(); |
| gfx::Size spacing(0, ToolbarView::kVertSpacing); |
| - gfx::ImageSkia icon = *icon_factory_.GetIcon(tab_id).ToImageSkia(); |
| + gfx::ImageSkia icon = *extension_action_view_->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 +344,68 @@ 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::IsNestedView() { |
| + return delegate_->ShownInsideMenu(); |
| +} |
| + |
| +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( |
| + extension_action_view_->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(bool close_widget) { |
| - DCHECK(popup_); |
| +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(); |
| +} |