1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/browser_action_view.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/profiles/profile.h" 13558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/themes/theme_service.h" 14558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/browser/themes/theme_service_factory.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 1646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/ui/view_ids.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/ui/views/frame/browser_view.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/browser_actions_container.h" 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/toolbar_view.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h" 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "extensions/common/manifest_constants.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_operations.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_source.h" 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/views/controls/button/label_button_border.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing views::LabelButtonBorder; 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// We have smaller insets than normal STYLE_TEXTBUTTON buttons so that we can 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// fit user supplied icons in without clipping them. 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kBorderInset = 4; 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserActionView 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserActionView::BrowserActionView(const Extension* extension, 4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionAction* extension_action, 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionView::Delegate* delegate) 51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : MenuButton(this, base::string16(), NULL, false), 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) view_controller_(new ExtensionActionViewController( 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extension, 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) browser, 5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extension_action, 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this)), 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_(delegate), 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) called_registered_extension_command_(false), 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) icon_observer_(NULL) { 606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_id(VIEW_ID_BROWSER_ACTION); 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SetHorizontalAlignment(gfx::ALIGN_CENTER); 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) set_context_menu_controller(view_controller_.get()); 636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) set_drag_controller(delegate_); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationSource notification_source = 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content::Source<Profile>(browser->profile()->GetOriginalProfile()); 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) registrar_.Add(this, 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notification_source); 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) registrar_.Add(this, 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extensions::NOTIFICATION_EXTENSION_COMMAND_REMOVED, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notification_source); 73558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 74558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // We also listen for browser theme changes on linux because a switch from or 75558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // to GTK requires that we regrab our browser action images. 76558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch registrar_.Add( 77558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch this, 78558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch chrome::NOTIFICATION_BROWSER_THEME_CHANGED, 79558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch content::Source<ThemeService>( 80558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ThemeServiceFactory::GetForProfile(browser->profile()))); 816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) UpdateState(); 836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)BrowserActionView::~BrowserActionView() { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::ViewHierarchyChanged( 89a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const ViewHierarchyChangedDetails& details) { 90a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (details.is_add && !called_registered_extension_command_ && 91a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) GetFocusManager()) { 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) view_controller_->RegisterCommand(); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) called_registered_extension_command_ = true; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 96a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) MenuButton::ViewHierarchyChanged(details); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::OnDragDone() { 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_->OnBrowserActionViewDragDone(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)gfx::Size BrowserActionView::GetPreferredSize() const { 1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return gfx::Size(BrowserActionsContainer::IconWidth(false), 1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BrowserActionsContainer::IconHeight()); 1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::PaintChildren(gfx::Canvas* canvas, 1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const views::CullSet& cull_set) { 1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) View::PaintChildren(canvas, cull_set); 1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) int tab_id = view_controller_->GetCurrentTabId(); 1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (tab_id >= 0) 1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) extension_action()->PaintBadge(canvas, GetLocalBounds(), tab_id); 1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::GetAccessibleState(ui::AXViewState* state) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::MenuButton::GetAccessibleState(state); 1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) state->name = l10n_util::GetStringUTF16( 1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) IDS_ACCNAME_EXTENSIONS_BROWSER_ACTION); 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->role = ui::AX_ROLE_BUTTON; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::ButtonPressed(views::Button* sender, 1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const ui::Event& event) { 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) view_controller_->ExecuteActionByUser(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::UpdateState() { 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int tab_id = view_controller_->GetCurrentTabId(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_id < 0) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!IsEnabled(tab_id)) 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetState(views::CustomButton::STATE_DISABLED); 135e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch else if (state() == views::CustomButton::STATE_DISABLED) 136e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch SetState(views::CustomButton::STATE_NORMAL); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::ImageSkia icon = *view_controller_->GetIcon(tab_id).ToImageSkia(); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!icon.isNull()) { 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!extension_action()->GetIsVisible(tab_id)) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon = gfx::ImageSkiaOperations::CreateTransparentImage(icon, .25); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ThemeService* theme = ThemeServiceFactory::GetForProfile( 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) view_controller_->browser()->profile()); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch gfx::ImageSkia bg = *theme->GetImageSkiaNamed(IDR_BROWSER_ACTION); 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SetImage(views::Button::STATE_NORMAL, 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) gfx::ImageSkiaOperations::CreateSuperimposedImage(bg, icon)); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the browser action name is empty, show the extension name instead. 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string title = extension_action()->GetTitle(tab_id); 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 name = 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::UTF8ToUTF16(title.empty() ? extension()->name() : title); 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SetTooltipText(name); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetAccessibleName(name); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 159e4256316f8b5e8d1ec0df1f7762771622a53fa63Ben Murdoch Layout(); // We need to layout since we may have added an icon as a result. 1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SchedulePaint(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool BrowserActionView::IsPopup() { 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int tab_id = view_controller_->GetCurrentTabId(); 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (tab_id < 0) ? false : extension_action()->HasPopup(tab_id); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::Observe(int type, 1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const content::NotificationSource& source, 1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) const content::NotificationDetails& details) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED: 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) case extensions::NOTIFICATION_EXTENSION_COMMAND_REMOVED: { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<const std::string, const std::string>* payload = 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Details<std::pair<const std::string, const std::string> >( 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details).ptr(); 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (extension()->id() == payload->first && 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload->second == 179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) extensions::manifest_values::kBrowserActionCommandEvent) { 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (type == extensions::NOTIFICATION_EXTENSION_COMMAND_ADDED) 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) view_controller_->RegisterCommand(); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) view_controller_->UnregisterCommand(true); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 187558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch case chrome::NOTIFICATION_BROWSER_THEME_CHANGED: 188558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch UpdateState(); 189558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch break; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool BrowserActionView::Activate() { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsPopup()) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) view_controller_->ExecuteActionByUser(); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(erikkay): Run a nested modal loop while the mouse is down to 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // enable menu-like drag-select behavior. 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The return value of this method is returned via OnMousePressed. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to return false here since we're handing off focus to another 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // widget/view, and true will grab it right back and try to send events 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to us. 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool BrowserActionView::OnMousePressed(const ui::MouseEvent& event) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!event.IsRightMouseButton()) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsPopup() ? MenuButton::OnMousePressed(event) : 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LabelButton::OnMousePressed(event); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::OnMouseReleased(const ui::MouseEvent& event) { 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (IsPopup() || view_controller_->is_menu_running()) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(erikkay) this never actually gets called (probably because of the 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loss of focus). 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuButton::OnMouseReleased(event); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LabelButton::OnMouseReleased(event); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::OnMouseExited(const ui::MouseEvent& event) { 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (IsPopup() || view_controller_->is_menu_running()) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuButton::OnMouseExited(event); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LabelButton::OnMouseExited(event); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool BrowserActionView::OnKeyReleased(const ui::KeyEvent& event) { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsPopup() ? MenuButton::OnKeyReleased(event) : 239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LabelButton::OnKeyReleased(event); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::OnGestureEvent(ui::GestureEvent* event) { 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsPopup()) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MenuButton::OnGestureEvent(event); 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LabelButton::OnGestureEvent(event); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)scoped_ptr<LabelButtonBorder> BrowserActionView::CreateDefaultBorder() const { 250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<LabelButtonBorder> border = LabelButton::CreateDefaultBorder(); 251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch border->set_insets(gfx::Insets(kBorderInset, kBorderInset, 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch kBorderInset, kBorderInset)); 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return border.Pass(); 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 255116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool BrowserActionView::IsEnabled(int tab_id) const { 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return view_controller_->extension_action()->GetIsVisible(tab_id); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)gfx::ImageSkia BrowserActionView::GetIconWithBadge() { 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int tab_id = view_controller_->GetCurrentTabId(); 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Size spacing(0, ToolbarView::kVertSpacing); 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::ImageSkia icon = *view_controller_->GetIcon(tab_id).ToImageSkia(); 264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!IsEnabled(tab_id)) 265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) icon = gfx::ImageSkiaOperations::CreateTransparentImage(icon, .25); 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return extension_action()->GetIconWithBadge(icon, tab_id, spacing); 267a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 268a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)gfx::ImageSkia BrowserActionView::GetIconForTest() { 270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return GetImage(views::Button::STATE_NORMAL); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::OnIconUpdated() { 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) UpdateState(); 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (icon_observer_) 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) icon_observer_->OnIconUpdated(GetIconWithBadge()); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)views::View* BrowserActionView::GetAsView() { 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return this; 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool BrowserActionView::IsShownInMenu() { 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return delegate_->ShownInsideMenu(); 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)views::FocusManager* BrowserActionView::GetFocusManagerForAccelerator() { 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return GetFocusManager(); 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)views::Widget* BrowserActionView::GetParentForContextMenu() { 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // RunMenuAt expects a nested menu to be parented by the same widget as the 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // already visible menu, in this case the Chrome menu. 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return delegate_->ShownInsideMenu() ? 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) BrowserView::GetBrowserViewForBrowser(view_controller_->browser()) 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ->toolbar()->app_menu()->GetWidget() : 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GetWidget(); 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciExtensionActionViewController* 3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBrowserActionView::GetPreferredPopupViewController() { 3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return delegate_->ShownInsideMenu() ? 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delegate_->GetMainViewForExtension(extension())->view_controller() : 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci view_controller(); 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)views::View* BrowserActionView::GetReferenceViewForPopup() { 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Browser actions in the overflow menu can still show popups, so we may need 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // a reference view other than this button's parent. If so, use the overflow 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // view. 3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return visible() ? this : delegate_->GetOverflowReferenceView(); 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciviews::MenuButton* BrowserActionView::GetContextMenuButton() { 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(visible()); // We should never show a context menu for a hidden item. 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return this; 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)content::WebContents* BrowserActionView::GetCurrentWebContents() { 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return delegate_->GetCurrentWebContents(); 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::HideActivePopup() { 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_->HideActivePopup(); 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::OnPopupShown(bool grant_tab_permissions) { 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_->SetPopupOwner(this); 3291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If this was through direct user action, we press the menu button. 3301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (grant_tab_permissions) { 3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We set the state of the menu button we're using as a reference view, 3321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // which is either this or the overflow reference view. 3331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This cast is safe because GetReferenceViewForPopup returns either |this| 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // or delegate_->GetOverflowReferenceView(), which returns a MenuButton. 3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci views::MenuButton* reference_view = 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<views::MenuButton*>(GetReferenceViewForPopup()); 3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pressed_lock_.reset(new views::MenuButton::PressedLock(reference_view)); 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionView::CleanupPopup() { 3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We need to do these actions synchronously (instead of closing and then 3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // performing the rest of the cleanup in OnWidgetDestroyed()) because 3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // OnWidgetDestroyed() can be called asynchronously from Close(), and we need 3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // to keep the delegate's popup owner up-to-date. 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_->SetPopupOwner(NULL); 3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pressed_lock_.reset(); // Unpress the menu button if it was pressed. 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 349