summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/views/extensions/extension_action_view_controller.h
blob: 3799db6ac475d037dc9805715d53617c4be33412 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_
#define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_

#include "chrome/browser/extensions/extension_action_icon_factory.h"
#include "chrome/browser/extensions/extension_context_menu_model.h"
#include "chrome/browser/ui/views/extensions/extension_popup.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/gfx/image/image.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/widget/widget_observer.h"

class Browser;
class ExtensionAction;
class ExtensionActionViewDelegate;

namespace content {
class WebContents;
}

namespace extensions {
class Command;
class Extension;
}

namespace ui {
class Accelerator;
}

namespace views {
class MenuRunner;
class View;
class Widget;
}

// An abstract "View" for an ExtensionAction (either a BrowserAction or a
// PageAction). This contains the logic for showing the action's popup and
// the context menu. This class doesn't subclass View directly, as the
// implementations for page actions/browser actions are different types of
// views.
// All common logic for executing extension actions should go in this class;
// ExtensionActionViewDelegate classes should only have knowledge relating to
// the views::View wrapper.
class ExtensionActionViewController
    : public ExtensionActionIconFactory::Observer,
      public ExtensionContextMenuModel::PopupDelegate,
      public ui::AcceleratorTarget,
      public views::ContextMenuController,
      public views::WidgetObserver {
 public:
  ExtensionActionViewController(const extensions::Extension* extension,
                                Browser* browser,
                                ExtensionAction* extension_action,
                                ExtensionActionViewDelegate* delegate);
  virtual ~ExtensionActionViewController();

  // ExtensionContextMenuModel::PopupDelegate:
  virtual void InspectPopup() OVERRIDE;

  // Executes the default extension action (typically showing the popup), and
  // attributes the action to a user (thus, only use this for actions that
  // *were* done by the user).
  void ExecuteActionByUser();

  // Executes the extension action with |show_action|. If
  // |grant_tab_permissions| is true, this will grant the extension active tab
  // permissions. Only do this if this was done through a user action (and not
  // e.g. an API). Returns true if a popup is shown.
  bool ExecuteAction(ExtensionPopup::ShowAction show_action,
                     bool grant_tab_permissions);

  // Hides the popup, if one is open.
  void HidePopup();

  // Returns the icon from the |icon_factory_|.
  gfx::Image GetIcon(int tab_id);

  // Returns the current tab id.
  int GetCurrentTabId() const;

  // Registers an accelerator for the extension action's command, if one
  // exists.
  void RegisterCommand();

  // Unregisters the accelerator for the extension action's command, if one
  // exists. If |only_if_removed| is true, then this will only unregister if the
  // command has been removed.
  void UnregisterCommand(bool only_if_removed);

  const extensions::Extension* extension() const { return extension_; }
  Browser* browser() { return browser_; }
  ExtensionAction* extension_action() { return extension_action_; }
  const ExtensionAction* extension_action() const { return extension_action_; }
  ExtensionPopup* popup() { return popup_; }
  bool is_menu_running() const { return menu_runner_.get() != NULL; }

 private:
  // ExtensionActionIconFactory::Observer:
  virtual void OnIconUpdated() OVERRIDE;

  // ui::AcceleratorTarget:
  virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
  virtual bool CanHandleAccelerators() const OVERRIDE;

  // views::WidgetObserver:
  virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;

  // views::ContextMenuController:
  virtual void ShowContextMenuForView(views::View* source,
                                      const gfx::Point& point,
                                      ui::MenuSourceType source_type) OVERRIDE;

  // Shows the context menu for extension action.
  void DoShowContextMenu(ui::MenuSourceType source_type);

  // Shows the popup for the extension action, given the associated |popup_url|.
  // Returns true if a popup is successfully shown.
  bool ShowPopupWithUrl(ExtensionPopup::ShowAction show_action,
                        const GURL& popup_url);

  // Populates |command| with the command associated with |extension|, if one
  // exists. Returns true if |command| was populated.
  bool GetExtensionCommand(extensions::Command* command);

  // Closes the currently-active menu, if needed. This is the case when there
  // is an active menu that wouldn't close automatically when a new one is
  // opened.
  // Returns true if a menu was closed, false otherwise.
  bool CloseActiveMenuIfNeeded();

  // Cleans up after the popup. If |close_widget| is true, this will call
  // Widget::Close() on the popup's widget; otherwise it assumes the popup is
  // already closing.
  void CleanupPopup(bool close_widget);

  // The extension associated with the action we're displaying.
  const extensions::Extension* extension_;

  // The corresponding browser.
  Browser* browser_;

  // The browser action this view represents. The ExtensionAction is not owned
  // by this class.
  ExtensionAction* extension_action_;

  // Our delegate.
  ExtensionActionViewDelegate* delegate_;

  // The object that will be used to get the browser action icon for us.
  // It may load the icon asynchronously (in which case the initial icon
  // returned by the factory will be transparent), so we have to observe it for
  // updates to the icon.
  ExtensionActionIconFactory icon_factory_;

  // Responsible for running the menu.
  scoped_ptr<views::MenuRunner> menu_runner_;

  // The browser action's popup, if it is visible; NULL otherwise.
  ExtensionPopup* popup_;

  // The extension key binding accelerator this extension action is listening
  // for (to show the popup).
  scoped_ptr<ui::Accelerator> action_keybinding_;

  // If non-NULL, this is the next ExtensionActionViewController context menu
  // which wants to run once the current owner (this one) is done.
  base::Closure followup_context_menu_task_;

  base::WeakPtrFactory<ExtensionActionViewController> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionActionViewController);
};

#endif  // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_