blob: acbae367994eceb193d573578fa592d54b180981 [file] [log] [blame]
rdevlin.cronin09530742014-11-03 19:23:281// 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.
4
5#ifndef CHROME_BROWSER_UI_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_
6#define CHROME_BROWSER_UI_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_
7
avi655876a2015-12-25 07:18:158#include "base/macros.h"
rdevlin.croninfb6edb42015-04-28 18:23:179#include "base/memory/weak_ptr.h"
rdevlin.cronin42efb7dd2015-02-11 17:50:5210#include "base/scoped_observer.h"
rdevlin.cronin09530742014-11-03 19:23:2811#include "chrome/browser/extensions/extension_action_icon_factory.h"
12#include "chrome/browser/extensions/extension_context_menu_model.h"
13#include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
rdevlin.cronin42efb7dd2015-02-11 17:50:5214#include "extensions/browser/extension_host_observer.h"
rdevlin.cronin09530742014-11-03 19:23:2815#include "ui/gfx/image/image.h"
16
17class Browser;
18class ExtensionAction;
19class ExtensionActionPlatformDelegate;
20class GURL;
rdevlin.croninfbfcca32015-07-09 00:28:3521class IconWithBadgeImageSource;
rdevlin.cronin5eb91b22015-04-23 19:39:0522class ToolbarActionsBar;
rdevlin.cronin09530742014-11-03 19:23:2823
24namespace extensions {
25class Command;
26class Extension;
rdevlin.cronin651153652014-11-15 00:34:4827class ExtensionRegistry;
rdevlin.croninb43d48e2015-01-29 17:51:4128class ExtensionViewHost;
rdevlin.cronin09530742014-11-03 19:23:2829}
30
31// The platform-independent controller for an ExtensionAction that is shown on
32// the toolbar (such as a page or browser action).
rdevlin.cronin651153652014-11-15 00:34:4833// Since this class doesn't own the extension or extension action in question,
34// be sure to check for validity using ExtensionIsValid() before using those
35// members (see also comments above ExtensionIsValid()).
rdevlin.cronin09530742014-11-03 19:23:2836class ExtensionActionViewController
37 : public ToolbarActionViewController,
38 public ExtensionActionIconFactory::Observer,
rdevlin.cronin2b74ad82015-09-17 22:15:5439 public extensions::ExtensionContextMenuModel::PopupDelegate,
rdevlin.cronin42efb7dd2015-02-11 17:50:5240 public extensions::ExtensionHostObserver {
rdevlin.cronin09530742014-11-03 19:23:2841 public:
42 // The different options for showing a popup.
43 enum PopupShowAction { SHOW_POPUP, SHOW_POPUP_AND_INSPECT };
44
45 ExtensionActionViewController(const extensions::Extension* extension,
46 Browser* browser,
rdevlin.cronin5628304c2015-10-14 23:07:0347 ExtensionAction* extension_action,
rdevlin.cronin5eb91b22015-04-23 19:39:0548 ToolbarActionsBar* toolbar_actions_bar);
rdevlin.cronin09530742014-11-03 19:23:2849 ~ExtensionActionViewController() override;
50
51 // ToolbarActionViewController:
apacible3f73e9b32015-08-21 21:21:0852 std::string GetId() const override;
rdevlin.cronin09530742014-11-03 19:23:2853 void SetDelegate(ToolbarActionViewDelegate* delegate) override;
rdevlin.cronin3a57a7f2015-07-06 21:22:4354 gfx::Image GetIcon(content::WebContents* web_contents,
55 const gfx::Size& size) override;
rdevlin.cronin09530742014-11-03 19:23:2856 base::string16 GetActionName() const override;
57 base::string16 GetAccessibleName(content::WebContents* web_contents) const
58 override;
59 base::string16 GetTooltip(content::WebContents* web_contents) const override;
60 bool IsEnabled(content::WebContents* web_contents) const override;
rdevlin.croninf762e8da2014-12-02 20:57:1061 bool WantsToRun(content::WebContents* web_contents) const override;
rdevlin.cronin09530742014-11-03 19:23:2862 bool HasPopup(content::WebContents* web_contents) const override;
63 void HidePopup() override;
64 gfx::NativeView GetPopupNativeView() override;
rdevlin.croninc10ac9e2015-01-16 21:10:0865 ui::MenuModel* GetContextMenu() override;
rdevlin.cronina81394e2015-04-30 20:16:5666 void OnContextMenuClosed() override;
rdevlin.cronin09530742014-11-03 19:23:2867 bool ExecuteAction(bool by_user) override;
rdevlin.cronin1b9a3a12014-11-13 17:15:1168 void UpdateState() override;
rdevlin.cronin09530742014-11-03 19:23:2869 void RegisterCommand() override;
rdevlin.croninac27cf32015-07-09 17:12:3470 bool DisabledClickOpensMenu() const override;
rdevlin.cronin09530742014-11-03 19:23:2871
72 // ExtensionContextMenuModel::PopupDelegate:
73 void InspectPopup() override;
74
rdevlin.cronin5eb91b22015-04-23 19:39:0575 // Closes the active popup (whether it was this action's popup or not).
76 void HideActivePopup();
77
rdevlin.cronin09530742014-11-03 19:23:2878 // Populates |command| with the command associated with |extension|, if one
79 // exists. Returns true if |command| was populated.
80 bool GetExtensionCommand(extensions::Command* command);
81
rdevlin.cronin75c546722015-05-06 00:26:0482 const extensions::Extension* extension() const { return extension_.get(); }
rdevlin.cronin09530742014-11-03 19:23:2883 Browser* browser() { return browser_; }
84 ExtensionAction* extension_action() { return extension_action_; }
85 const ExtensionAction* extension_action() const { return extension_action_; }
86 ToolbarActionViewDelegate* view_delegate() { return view_delegate_; }
rdevlin.croninb43d48e2015-01-29 17:51:4187 bool is_showing_popup() const { return popup_host_ != nullptr; }
rdevlin.cronin09530742014-11-03 19:23:2888
89 void set_icon_observer(ExtensionActionIconFactory::Observer* icon_observer) {
90 icon_observer_ = icon_observer;
91 }
92
rdevlin.croninfbfcca32015-07-09 00:28:3593 scoped_ptr<IconWithBadgeImageSource> GetIconImageSourceForTesting(
94 content::WebContents* web_contents,
95 const gfx::Size& size);
96
rdevlin.cronin09530742014-11-03 19:23:2897 private:
98 // ExtensionActionIconFactory::Observer:
99 void OnIconUpdated() override;
100
rdevlin.cronin42efb7dd2015-02-11 17:50:52101 // ExtensionHostObserver:
102 void OnExtensionHostDestroyed(const extensions::ExtensionHost* host) override;
rdevlin.croninb43d48e2015-01-29 17:51:41103
rdevlin.cronin651153652014-11-15 00:34:48104 // Checks if the associated |extension| is still valid by checking its
105 // status in the registry. Since the OnExtensionUnloaded() notifications are
106 // not in a deterministic order, it's possible that the view tries to refresh
107 // itself before we're notified to remove it.
108 bool ExtensionIsValid() const;
109
rdevlin.cronin5eb91b22015-04-23 19:39:05110 // In some cases (such as when an action is shown in a menu), a substitute
111 // ToolbarActionViewController should be used for showing popups. This
112 // returns the preferred controller.
113 ExtensionActionViewController* GetPreferredPopupViewController();
114
rdevlin.cronin09530742014-11-03 19:23:28115 // Executes the extension action with |show_action|. If
116 // |grant_tab_permissions| is true, this will grant the extension active tab
117 // permissions. Only do this if this was done through a user action (and not
118 // e.g. an API). Returns true if a popup is shown.
119 bool ExecuteAction(PopupShowAction show_action, bool grant_tab_permissions);
120
rdevlin.croninfb6edb42015-04-28 18:23:17121 // Begins the process of showing the popup for the extension action, given the
122 // associated |popup_url|. |grant_tab_permissions| is true if active tab
123 // permissions should be given to the extension; this is only true if the
124 // popup is opened through a user action.
125 // The popup may not be shown synchronously if the extension is hidden and
126 // first needs to slide itself out.
127 // Returns true if a popup will be shown.
128 bool TriggerPopupWithUrl(PopupShowAction show_action,
129 const GURL& popup_url,
130 bool grant_tab_permissions);
131
132 // Shows the popup with the given |host|.
133 void ShowPopup(scoped_ptr<extensions::ExtensionViewHost> host,
134 bool grant_tab_permissions,
135 PopupShowAction show_action);
rdevlin.cronin09530742014-11-03 19:23:28136
rdevlin.croninb43d48e2015-01-29 17:51:41137 // Handles cleanup after the popup closes.
138 void OnPopupClosed();
139
rdevlin.croninfbfcca32015-07-09 00:28:35140 // Returns the image source for the icon.
141 scoped_ptr<IconWithBadgeImageSource> GetIconImageSource(
142 content::WebContents* web_contents,
143 const gfx::Size& size);
144
rdevlin.cronin09530742014-11-03 19:23:28145 // The extension associated with the action we're displaying.
rdevlin.cronin75c546722015-05-06 00:26:04146 scoped_refptr<const extensions::Extension> extension_;
rdevlin.cronin09530742014-11-03 19:23:28147
148 // The corresponding browser.
149 Browser* browser_;
150
151 // The browser action this view represents. The ExtensionAction is not owned
152 // by this class.
153 ExtensionAction* extension_action_;
154
rdevlin.cronin5eb91b22015-04-23 19:39:05155 // The owning ToolbarActionsBar, if any. This will be null if this is a
156 // page action without the toolbar redesign turned on.
157 // TODO(devlin): Would this be better behind a delegate interface? On the one
158 // hand, it's odd for this class to know about ToolbarActionsBar, but on the
159 // other, yet-another-delegate-class might just confuse things.
160 ToolbarActionsBar* toolbar_actions_bar_;
161
rdevlin.croninb43d48e2015-01-29 17:51:41162 // The extension popup's host if the popup is visible; null otherwise.
163 extensions::ExtensionViewHost* popup_host_;
164
rdevlin.croninc10ac9e2015-01-16 21:10:08165 // The context menu model for the extension.
rdevlin.cronin2b74ad82015-09-17 22:15:54166 scoped_ptr<extensions::ExtensionContextMenuModel> context_menu_model_;
rdevlin.croninc10ac9e2015-01-16 21:10:08167
rdevlin.cronin09530742014-11-03 19:23:28168 // Our view delegate.
169 ToolbarActionViewDelegate* view_delegate_;
170
171 // The delegate to handle platform-specific implementations.
172 scoped_ptr<ExtensionActionPlatformDelegate> platform_delegate_;
173
174 // The object that will be used to get the browser action icon for us.
175 // It may load the icon asynchronously (in which case the initial icon
176 // returned by the factory will be transparent), so we have to observe it for
177 // updates to the icon.
178 ExtensionActionIconFactory icon_factory_;
179
180 // An additional observer that we need to notify when the icon of the button
181 // has been updated.
182 ExtensionActionIconFactory::Observer* icon_observer_;
183
rdevlin.cronin651153652014-11-15 00:34:48184 // The associated ExtensionRegistry; cached for quick checking.
185 extensions::ExtensionRegistry* extension_registry_;
186
rdevlin.cronin42efb7dd2015-02-11 17:50:52187 ScopedObserver<extensions::ExtensionHost, extensions::ExtensionHostObserver>
188 popup_host_observer_;
rdevlin.croninb43d48e2015-01-29 17:51:41189
rdevlin.croninfb6edb42015-04-28 18:23:17190 base::WeakPtrFactory<ExtensionActionViewController> weak_factory_;
191
rdevlin.cronin09530742014-11-03 19:23:28192 DISALLOW_COPY_AND_ASSIGN(ExtensionActionViewController);
193};
194
195#endif // CHROME_BROWSER_UI_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_