1 // Copyright 2014 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.
5 #ifndef CHROME_BROWSER_UI_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_
6 #define CHROME_BROWSER_UI_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_
8 #include "base/memory/weak_ptr.h"
9 #include "base/scoped_observer.h"
10 #include "chrome/browser/extensions/extension_action_icon_factory.h"
11 #include "chrome/browser/extensions/extension_context_menu_model.h"
12 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
13 #include "extensions/browser/extension_host_observer.h"
14 #include "ui/gfx/image/image.h"
17 class ExtensionAction
;
18 class ExtensionActionPlatformDelegate
;
20 class IconWithBadgeImageSource
;
21 class ToolbarActionsBar
;
23 namespace extensions
{
26 class ExtensionRegistry
;
27 class ExtensionViewHost
;
30 // The platform-independent controller for an ExtensionAction that is shown on
31 // the toolbar (such as a page or browser action).
32 // Since this class doesn't own the extension or extension action in question,
33 // be sure to check for validity using ExtensionIsValid() before using those
34 // members (see also comments above ExtensionIsValid()).
35 class ExtensionActionViewController
36 : public ToolbarActionViewController
,
37 public ExtensionActionIconFactory::Observer
,
38 public extensions::ExtensionContextMenuModel::PopupDelegate
,
39 public extensions::ExtensionHostObserver
{
41 // The different options for showing a popup.
42 enum PopupShowAction
{ SHOW_POPUP
, SHOW_POPUP_AND_INSPECT
};
44 ExtensionActionViewController(const extensions::Extension
* extension
,
46 ExtensionAction
* extension_action
,
47 ToolbarActionsBar
* toolbar_actions_bar
);
48 ~ExtensionActionViewController() override
;
50 // ToolbarActionViewController:
51 std::string
GetId() const override
;
52 void SetDelegate(ToolbarActionViewDelegate
* delegate
) override
;
53 gfx::Image
GetIcon(content::WebContents
* web_contents
,
54 const gfx::Size
& size
) override
;
55 base::string16
GetActionName() const override
;
56 base::string16
GetAccessibleName(content::WebContents
* web_contents
) const
58 base::string16
GetTooltip(content::WebContents
* web_contents
) const override
;
59 bool IsEnabled(content::WebContents
* web_contents
) const override
;
60 bool WantsToRun(content::WebContents
* web_contents
) const override
;
61 bool HasPopup(content::WebContents
* web_contents
) const override
;
62 void HidePopup() override
;
63 gfx::NativeView
GetPopupNativeView() override
;
64 ui::MenuModel
* GetContextMenu() override
;
65 void OnContextMenuClosed() override
;
66 bool ExecuteAction(bool by_user
) override
;
67 void UpdateState() override
;
68 void RegisterCommand() override
;
69 bool DisabledClickOpensMenu() const override
;
71 // ExtensionContextMenuModel::PopupDelegate:
72 void InspectPopup() override
;
74 // Closes the active popup (whether it was this action's popup or not).
75 void HideActivePopup();
77 // Populates |command| with the command associated with |extension|, if one
78 // exists. Returns true if |command| was populated.
79 bool GetExtensionCommand(extensions::Command
* command
);
81 const extensions::Extension
* extension() const { return extension_
.get(); }
82 Browser
* browser() { return browser_
; }
83 ExtensionAction
* extension_action() { return extension_action_
; }
84 const ExtensionAction
* extension_action() const { return extension_action_
; }
85 ToolbarActionViewDelegate
* view_delegate() { return view_delegate_
; }
86 bool is_showing_popup() const { return popup_host_
!= nullptr; }
88 void set_icon_observer(ExtensionActionIconFactory::Observer
* icon_observer
) {
89 icon_observer_
= icon_observer
;
92 scoped_ptr
<IconWithBadgeImageSource
> GetIconImageSourceForTesting(
93 content::WebContents
* web_contents
,
94 const gfx::Size
& size
);
97 // ExtensionActionIconFactory::Observer:
98 void OnIconUpdated() override
;
100 // ExtensionHostObserver:
101 void OnExtensionHostDestroyed(const extensions::ExtensionHost
* host
) override
;
103 // Checks if the associated |extension| is still valid by checking its
104 // status in the registry. Since the OnExtensionUnloaded() notifications are
105 // not in a deterministic order, it's possible that the view tries to refresh
106 // itself before we're notified to remove it.
107 bool ExtensionIsValid() const;
109 // In some cases (such as when an action is shown in a menu), a substitute
110 // ToolbarActionViewController should be used for showing popups. This
111 // returns the preferred controller.
112 ExtensionActionViewController
* GetPreferredPopupViewController();
114 // Executes the extension action with |show_action|. If
115 // |grant_tab_permissions| is true, this will grant the extension active tab
116 // permissions. Only do this if this was done through a user action (and not
117 // e.g. an API). Returns true if a popup is shown.
118 bool ExecuteAction(PopupShowAction show_action
, bool grant_tab_permissions
);
120 // Begins the process of showing the popup for the extension action, given the
121 // associated |popup_url|. |grant_tab_permissions| is true if active tab
122 // permissions should be given to the extension; this is only true if the
123 // popup is opened through a user action.
124 // The popup may not be shown synchronously if the extension is hidden and
125 // first needs to slide itself out.
126 // Returns true if a popup will be shown.
127 bool TriggerPopupWithUrl(PopupShowAction show_action
,
128 const GURL
& popup_url
,
129 bool grant_tab_permissions
);
131 // Shows the popup with the given |host|.
132 void ShowPopup(scoped_ptr
<extensions::ExtensionViewHost
> host
,
133 bool grant_tab_permissions
,
134 PopupShowAction show_action
);
136 // Handles cleanup after the popup closes.
137 void OnPopupClosed();
139 // Returns the image source for the icon.
140 scoped_ptr
<IconWithBadgeImageSource
> GetIconImageSource(
141 content::WebContents
* web_contents
,
142 const gfx::Size
& size
);
144 // The extension associated with the action we're displaying.
145 scoped_refptr
<const extensions::Extension
> extension_
;
147 // The corresponding browser.
150 // The browser action this view represents. The ExtensionAction is not owned
152 ExtensionAction
* extension_action_
;
154 // The owning ToolbarActionsBar, if any. This will be null if this is a
155 // page action without the toolbar redesign turned on.
156 // TODO(devlin): Would this be better behind a delegate interface? On the one
157 // hand, it's odd for this class to know about ToolbarActionsBar, but on the
158 // other, yet-another-delegate-class might just confuse things.
159 ToolbarActionsBar
* toolbar_actions_bar_
;
161 // The extension popup's host if the popup is visible; null otherwise.
162 extensions::ExtensionViewHost
* popup_host_
;
164 // The context menu model for the extension.
165 scoped_ptr
<extensions::ExtensionContextMenuModel
> context_menu_model_
;
167 // Our view delegate.
168 ToolbarActionViewDelegate
* view_delegate_
;
170 // The delegate to handle platform-specific implementations.
171 scoped_ptr
<ExtensionActionPlatformDelegate
> platform_delegate_
;
173 // The object that will be used to get the browser action icon for us.
174 // It may load the icon asynchronously (in which case the initial icon
175 // returned by the factory will be transparent), so we have to observe it for
176 // updates to the icon.
177 ExtensionActionIconFactory icon_factory_
;
179 // An additional observer that we need to notify when the icon of the button
181 ExtensionActionIconFactory::Observer
* icon_observer_
;
183 // The associated ExtensionRegistry; cached for quick checking.
184 extensions::ExtensionRegistry
* extension_registry_
;
186 ScopedObserver
<extensions::ExtensionHost
, extensions::ExtensionHostObserver
>
187 popup_host_observer_
;
189 base::WeakPtrFactory
<ExtensionActionViewController
> weak_factory_
;
191 DISALLOW_COPY_AND_ASSIGN(ExtensionActionViewController
);
194 #endif // CHROME_BROWSER_UI_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_