• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_VIEW_H_
6 #define CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_VIEW_H_
7 
8 #include <string>
9 
10 #include "chrome/browser/extensions/extension_action_icon_factory.h"
11 #include "chrome/browser/extensions/extension_context_menu_model.h"
12 #include "content/public/browser/notification_observer.h"
13 #include "content/public/browser/notification_registrar.h"
14 #include "ui/views/context_menu_controller.h"
15 #include "ui/views/controls/button/menu_button.h"
16 #include "ui/views/controls/button/menu_button_listener.h"
17 #include "ui/views/drag_controller.h"
18 #include "ui/views/view.h"
19 
20 class Browser;
21 class BrowserActionButton;
22 class ExtensionAction;
23 
24 namespace extensions {
25 class Extension;
26 }
27 
28 namespace gfx {
29 class Image;
30 }
31 
32 namespace views {
33 class MenuItemView;
34 class MenuRunner;
35 }
36 
37 ////////////////////////////////////////////////////////////////////////////////
38 // BrowserActionView
39 // A single entry in the browser action container. This contains the actual
40 // BrowserActionButton, as well as the logic to paint the badge.
41 class BrowserActionView : public views::View {
42  public:
43   // Need DragController here because BrowserActionView could be
44   // dragged/dropped.
45   class Delegate : public views::DragController,
46                    public ExtensionContextMenuModel::PopupDelegate {
47    public:
48     // Returns the current tab's ID, or -1 if there is no current tab.
49     virtual int GetCurrentTabId() const = 0;
50 
51     // Called when the user clicks on the browser action icon.
52     virtual void OnBrowserActionExecuted(BrowserActionButton* button) = 0;
53 
54     // Called when a browser action becomes visible/hidden.
55     virtual void OnBrowserActionVisibilityChanged() = 0;
56 
57    protected:
~Delegate()58     virtual ~Delegate() {}
59   };
60 
61   BrowserActionView(const extensions::Extension* extension,
62                     Browser* browser,
63                     Delegate* delegate);
64   virtual ~BrowserActionView();
65 
button()66   BrowserActionButton* button() { return button_; }
67 
68   // Gets browser action button icon with the badge.
69   gfx::ImageSkia GetIconWithBadge();
70 
71   // Overridden from views::View:
72   virtual void Layout() OVERRIDE;
73   virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
74   virtual gfx::Size GetPreferredSize() const OVERRIDE;
75 
76  protected:
77   // Overridden from views::View to paint the badge on top of children.
78   virtual void PaintChildren(gfx::Canvas* canvas,
79                              const views::CullSet& cull_set) OVERRIDE;
80 
81  private:
82   // The Browser object this view is associated with.
83   Browser* browser_;
84 
85   // Usually a container for this view.
86   Delegate* delegate_;
87 
88   // The button this view contains.
89   BrowserActionButton* button_;
90 
91   // Extension this view associated with.
92   const extensions::Extension* extension_;
93 
94   DISALLOW_COPY_AND_ASSIGN(BrowserActionView);
95 };
96 
97 ////////////////////////////////////////////////////////////////////////////////
98 // BrowserActionButton
99 
100 // The BrowserActionButton is a specialization of the MenuButton class.
101 // It acts on a ExtensionAction, in this case a BrowserAction and handles
102 // loading the image for the button asynchronously on the file thread.
103 class BrowserActionButton : public views::MenuButton,
104                             public views::ButtonListener,
105                             public views::ContextMenuController,
106                             public content::NotificationObserver,
107                             public ExtensionActionIconFactory::Observer {
108  public:
109   // The IconObserver will receive a notification when the button's icon has
110   // been updated.
111   class IconObserver {
112    public:
113     virtual void OnIconUpdated(const gfx::ImageSkia& icon) = 0;
114 
115    protected:
~IconObserver()116     virtual ~IconObserver() {}
117   };
118 
119   BrowserActionButton(const extensions::Extension* extension,
120                       Browser* browser_,
121                       BrowserActionView::Delegate* delegate);
122 
123   // Call this instead of delete.
124   void Destroy();
125 
browser_action()126   ExtensionAction* browser_action() const { return browser_action_; }
extension()127   const extensions::Extension* extension() { return extension_; }
128 
set_icon_observer(IconObserver * icon_observer)129   void set_icon_observer(IconObserver* icon_observer) {
130     icon_observer_ = icon_observer;
131   }
132 
133   // Called to update the display to match the browser action's state.
134   void UpdateState();
135 
136   // Does this button's action have a popup?
137   virtual bool IsPopup();
138   virtual GURL GetPopupUrl();
139 
140   // Overridden from views::View:
141   virtual bool CanHandleAccelerators() const OVERRIDE;
142   virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
143 
144   // Overridden from views::ButtonListener:
145   virtual void ButtonPressed(views::Button* sender,
146                              const ui::Event& event) OVERRIDE;
147 
148   // Overridden from views::ContextMenuController.
149   virtual void ShowContextMenuForView(View* source,
150                                       const gfx::Point& point,
151                                       ui::MenuSourceType source_type) OVERRIDE;
152 
153   // Overridden from content::NotificationObserver:
154   virtual void Observe(int type,
155                        const content::NotificationSource& source,
156                        const content::NotificationDetails& details) OVERRIDE;
157 
158   // Overriden from ExtensionActionIconFactory::Observer.
159   virtual void OnIconUpdated() OVERRIDE;
160 
161   // MenuButton behavior overrides.  These methods all default to TextButton
162   // behavior unless this button is a popup.  In that case, it uses MenuButton
163   // behavior.  MenuButton has the notion of a child popup being shown where the
164   // button will stay in the pushed state until the "menu" (a popup in this
165   // case) is dismissed.
166   virtual bool Activate() OVERRIDE;
167   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
168   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
169   virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
170   virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE;
171   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
172 
173   // Overridden from ui::AcceleratorTarget.
174   virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
175 
176   // Notifications when to set button state to pushed/not pushed (for when the
177   // popup/context menu is hidden or shown by the container).
178   void SetButtonPushed();
179   void SetButtonNotPushed();
180 
181   // Whether the browser action is enabled on this tab. Note that we cannot use
182   // the built-in views enabled/SetEnabled because disabled views do not
183   // receive drag events.
184   bool IsEnabled(int tab_id) const;
185 
186   // Returns icon factory for the button.
icon_factory()187   ExtensionActionIconFactory& icon_factory() { return icon_factory_; }
188 
189   // Gets the icon of this button and its badge.
190   gfx::ImageSkia GetIconWithBadge();
191 
192   // Returns button icon so it can be accessed during tests.
193   gfx::ImageSkia GetIconForTest();
194 
195  protected:
196   // Overridden from views::View:
197   virtual void ViewHierarchyChanged(
198       const ViewHierarchyChangedDetails& details) OVERRIDE;
199 
200  private:
201   virtual ~BrowserActionButton();
202 
203   // Register an extension command if the extension has an active one.
204   void MaybeRegisterExtensionCommand();
205 
206   // Unregisters an extension command, if the extension has registered one and
207   // it is active.
208   void MaybeUnregisterExtensionCommand(bool only_if_active);
209 
210   // The Browser object this button is associated with.
211   Browser* browser_;
212 
213   // The browser action this view represents. The ExtensionAction is not owned
214   // by this class.
215   ExtensionAction* browser_action_;
216 
217   // The extension associated with the browser action we're displaying.
218   const extensions::Extension* extension_;
219 
220   // The object that will be used to get the browser action icon for us.
221   // It may load the icon asynchronously (in which case the initial icon
222   // returned by the factory will be transparent), so we have to observe it for
223   // updates to the icon.
224   ExtensionActionIconFactory icon_factory_;
225 
226   // Delegate that usually represents a container for BrowserActionView.
227   BrowserActionView::Delegate* delegate_;
228 
229   // The context menu.  This member is non-NULL only when the menu is shown.
230   views::MenuItemView* context_menu_;
231 
232   // Used to make sure MaybeRegisterExtensionCommand() is called only once
233   // from ViewHierarchyChanged().
234   bool called_registered_extension_command_;
235 
236   content::NotificationRegistrar registrar_;
237 
238   // The extension key binding accelerator this browser action is listening for
239   // (to show the popup).
240   scoped_ptr<ui::Accelerator> keybinding_;
241 
242   // Responsible for running the menu.
243   scoped_ptr<views::MenuRunner> menu_runner_;
244 
245   // The observer that we need to notify when the icon of the button has been
246   // updated.
247   IconObserver* icon_observer_;
248 
249   friend class base::DeleteHelper<BrowserActionButton>;
250 
251   DISALLOW_COPY_AND_ASSIGN(BrowserActionButton);
252 };
253 
254 #endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_VIEW_H_
255