blob: 94f4eee71cf754e0536b13b226fcaafd8d1ecc36 [file] [log] [blame]
Avi Drissman4a8573c2022-09-09 19:35:541// Copyright 2014 The Chromium Authors
rdevlin.cronin09530742014-11-03 19:23:282// 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
Keishi Hattori0e45c022021-11-27 09:25:528#include "base/memory/raw_ptr.h"
rdevlin.croninfb6edb42015-04-28 18:23:179#include "base/memory/weak_ptr.h"
Sigurdur Asgeirsson70fd5db2021-04-28 19:10:3510#include "base/scoped_observation.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"
Emilia Paz04ed53e2022-01-25 03:09:1113#include "chrome/browser/extensions/site_permissions_helper.h"
Emilia Pazc3137242022-08-19 20:44:3214#include "chrome/browser/ui/toolbar/toolbar_action_hover_card_types.h"
rdevlin.cronin09530742014-11-03 19:23:2815#include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
Evan Stade75872a62019-09-06 21:17:3816#include "extensions/browser/extension_host.h"
rdevlin.cronin42efb7dd2015-02-11 17:50:5217#include "extensions/browser/extension_host_observer.h"
Devlin Cronina208ee12021-04-28 20:43:3118#include "extensions/common/extension.h"
19#include "extensions/common/extension_id.h"
rdevlin.cronin09530742014-11-03 19:23:2820
21class Browser;
rdevlin.cronin09530742014-11-03 19:23:2822class ExtensionActionPlatformDelegate;
rdevlin.croninfbfcca32015-07-09 00:28:3523class IconWithBadgeImageSource;
Peter Boström91a80e82019-05-06 16:02:5324class ExtensionsContainer;
Devlin Cronin248ca592022-02-08 21:04:2525enum class PopupShowAction;
rdevlin.cronin09530742014-11-03 19:23:2826
27namespace extensions {
28class Command;
29class Extension;
Devlin Cronin720a0fb2020-07-22 01:31:3830class ExtensionAction;
rdevlin.cronin651153652014-11-15 00:34:4831class ExtensionRegistry;
rdevlin.croninb43d48e2015-01-29 17:51:4132class ExtensionViewHost;
Emilia Paz04ed53e2022-01-25 03:09:1133class SitePermissionsHelper;
Emilia Pazd0b78d842023-02-02 02:47:4634} // namespace extensions
rdevlin.cronin09530742014-11-03 19:23:2835
Emilia Paz15454492023-01-31 00:08:1336namespace ui {
37class ImageModel;
38}
39
rdevlin.cronin09530742014-11-03 19:23:2840// The platform-independent controller for an ExtensionAction that is shown on
41// the toolbar (such as a page or browser action).
rdevlin.cronin651153652014-11-15 00:34:4842// Since this class doesn't own the extension or extension action in question,
43// be sure to check for validity using ExtensionIsValid() before using those
44// members (see also comments above ExtensionIsValid()).
rdevlin.cronin09530742014-11-03 19:23:2845class ExtensionActionViewController
46 : public ToolbarActionViewController,
47 public ExtensionActionIconFactory::Observer,
rdevlin.cronin2b74ad82015-09-17 22:15:5448 public extensions::ExtensionContextMenuModel::PopupDelegate,
rdevlin.cronin42efb7dd2015-02-11 17:50:5249 public extensions::ExtensionHostObserver {
rdevlin.cronin09530742014-11-03 19:23:2850 public:
Devlin Cronina208ee12021-04-28 20:43:3151 static std::unique_ptr<ExtensionActionViewController> Create(
52 const extensions::ExtensionId& extension_id,
53 Browser* browser,
Devlin Cronin1c1b6ef62021-05-04 20:57:3054 ExtensionsContainer* extensions_container);
Devlin Cronina208ee12021-04-28 20:43:3155
Emilia Paz640b8d82021-10-30 04:11:3256 // Returns whether any of `actions` given have access to the `web_contents`.
57 static bool AnyActionHasCurrentSiteAccess(
58 const std::vector<std::unique_ptr<ToolbarActionViewController>>& actions,
59 content::WebContents* web_contents);
60
Peter Boström53c6c5952021-09-17 09:41:2661 ExtensionActionViewController(const ExtensionActionViewController&) = delete;
62 ExtensionActionViewController& operator=(
63 const ExtensionActionViewController&) = delete;
64
rdevlin.cronin09530742014-11-03 19:23:2865 ~ExtensionActionViewController() override;
66
67 // ToolbarActionViewController:
apacible3f73e9b32015-08-21 21:21:0868 std::string GetId() const override;
rdevlin.cronin09530742014-11-03 19:23:2869 void SetDelegate(ToolbarActionViewDelegate* delegate) override;
Emilia Paz15454492023-01-31 00:08:1370 ui::ImageModel GetIcon(content::WebContents* web_contents,
71 const gfx::Size& size) override;
Jan Wilken Dörrie3f97e292021-03-11 18:07:1472 std::u16string GetActionName() const override;
73 std::u16string GetAccessibleName(
74 content::WebContents* web_contents) const override;
75 std::u16string GetTooltip(content::WebContents* web_contents) const override;
Emilia Paz1fccfe62022-09-03 00:27:5976 ToolbarActionViewController::HoverCardState GetHoverCardState(
77 content::WebContents* web_contents) const override;
Emilia Paz04ed53e2022-01-25 03:09:1178 extensions::SitePermissionsHelper::SiteInteraction GetSiteInteraction(
Peter Boström251aebee2019-04-25 18:52:5779 content::WebContents* web_contents) const override;
rdevlin.cronin09530742014-11-03 19:23:2880 bool IsEnabled(content::WebContents* web_contents) const override;
Peter Kasting16ad82b82018-12-26 20:11:4781 bool IsShowingPopup() const override;
Emilia Paz2bf91af22023-03-03 02:13:2482 bool ShouldShowSiteAccessRequestInToolbar(
Emilia Pazb7d2f932022-04-07 00:40:5683 content::WebContents* web_contents) const override;
rdevlin.cronin09530742014-11-03 19:23:2884 void HidePopup() override;
85 gfx::NativeView GetPopupNativeView() override;
Emilia Paz498abfc2022-01-20 17:51:4286 ui::MenuModel* GetContextMenu(
87 extensions::ExtensionContextMenuModel::ContextMenuSource
88 context_menu_source) override;
Caroline Rising9999a612020-02-24 23:41:5089 void OnContextMenuShown() override;
rdevlin.cronina81394e2015-04-30 20:16:5690 void OnContextMenuClosed() override;
Devlin Cronin072b6bf12022-02-08 19:40:2191 void ExecuteUserAction(InvocationSource source) override;
Devlin Cronin1d722572022-02-09 21:19:3292 void TriggerPopupForAPI(ShowPopupCallback callback) override;
rdevlin.cronin1b9a3a12014-11-13 17:15:1193 void UpdateState() override;
Emilia Pazc3137242022-08-19 20:44:3294 void UpdateHoverCard(ToolbarActionView* action_view,
95 ToolbarActionHoverCardUpdateType update_type) override;
rdevlin.cronin09530742014-11-03 19:23:2896 void RegisterCommand() override;
Peter Kasting8ac405b2020-05-25 10:54:1897 void UnregisterCommand() override;
rdevlin.cronin09530742014-11-03 19:23:2898
99 // ExtensionContextMenuModel::PopupDelegate:
100 void InspectPopup() override;
101
rdevlin.cronin09530742014-11-03 19:23:28102 // Populates |command| with the command associated with |extension|, if one
103 // exists. Returns true if |command| was populated.
Devlin Cronin722a1782019-12-27 19:24:46104 bool GetExtensionCommand(extensions::Command* command) const;
105
106 // Returns true if this controller can handle accelerators (i.e., keyboard
107 // commands) on the currently-active WebContents.
108 // This must only be called if the extension has an associated command.
109 // TODO(devlin): Move accelerator logic out of the platform delegate and into
110 // this class.
111 bool CanHandleAccelerators() const;
rdevlin.cronin09530742014-11-03 19:23:28112
rdevlin.cronin75c546722015-05-06 00:26:04113 const extensions::Extension* extension() const { return extension_.get(); }
rdevlin.cronin09530742014-11-03 19:23:28114 Browser* browser() { return browser_; }
Devlin Cronin720a0fb2020-07-22 01:31:38115 extensions::ExtensionAction* extension_action() { return extension_action_; }
116 const extensions::ExtensionAction* extension_action() const {
117 return extension_action_;
118 }
rdevlin.cronin09530742014-11-03 19:23:28119 ToolbarActionViewDelegate* view_delegate() { return view_delegate_; }
rdevlin.cronin09530742014-11-03 19:23:28120
dcheng9603ab92016-04-08 04:17:32121 std::unique_ptr<IconWithBadgeImageSource> GetIconImageSourceForTesting(
rdevlin.croninfbfcca32015-07-09 00:28:35122 content::WebContents* web_contents,
123 const gfx::Size& size);
rdevlin.croninfbfcca32015-07-09 00:28:35124
rdevlin.cronin09530742014-11-03 19:23:28125 private:
Devlin Cronina208ee12021-04-28 20:43:31126 // New instances should be instantiated with Create().
127 ExtensionActionViewController(
128 scoped_refptr<const extensions::Extension> extension,
129 Browser* browser,
130 extensions::ExtensionAction* extension_action,
131 extensions::ExtensionRegistry* extension_registry,
Devlin Cronin1c1b6ef62021-05-04 20:57:30132 ExtensionsContainer* extensions_container);
Devlin Cronina208ee12021-04-28 20:43:31133
rdevlin.cronin09530742014-11-03 19:23:28134 // ExtensionActionIconFactory::Observer:
135 void OnIconUpdated() override;
136
rdevlin.cronin42efb7dd2015-02-11 17:50:52137 // ExtensionHostObserver:
Fabian Sommerfc5b6f052020-06-04 19:39:01138 void OnExtensionHostDestroyed(extensions::ExtensionHost* host) override;
rdevlin.croninb43d48e2015-01-29 17:51:41139
rdevlin.cronin651153652014-11-15 00:34:48140 // Checks if the associated |extension| is still valid by checking its
141 // status in the registry. Since the OnExtensionUnloaded() notifications are
142 // not in a deterministic order, it's possible that the view tries to refresh
143 // itself before we're notified to remove it.
144 bool ExtensionIsValid() const;
145
rdevlin.cronin5eb91b22015-04-23 19:39:05146 // In some cases (such as when an action is shown in a menu), a substitute
147 // ToolbarActionViewController should be used for showing popups. This
148 // returns the preferred controller.
149 ExtensionActionViewController* GetPreferredPopupViewController();
150
Devlin Cronin072b6bf12022-02-08 19:40:21151 // Begins the process of showing the popup for the extension action on the
152 // current web contents. |by_user| is true if popup is being triggered by a
153 // user action.
rdevlin.croninfb6edb42015-04-28 18:23:17154 // The popup may not be shown synchronously if the extension is hidden and
155 // first needs to slide itself out.
Devlin Cronin1d722572022-02-09 21:19:32156 void TriggerPopup(PopupShowAction show_action,
157 bool by_user,
158 ShowPopupCallback callback);
rdevlin.croninfb6edb42015-04-28 18:23:17159
160 // Shows the popup with the given |host|.
dcheng9603ab92016-04-08 04:17:32161 void ShowPopup(std::unique_ptr<extensions::ExtensionViewHost> host,
rdevlin.croninfb6edb42015-04-28 18:23:17162 bool grant_tab_permissions,
Devlin Cronin1d722572022-02-09 21:19:32163 PopupShowAction show_action,
164 ShowPopupCallback callback);
rdevlin.cronin09530742014-11-03 19:23:28165
rdevlin.croninb43d48e2015-01-29 17:51:41166 // Handles cleanup after the popup closes.
167 void OnPopupClosed();
168
rdevlin.croninfbfcca32015-07-09 00:28:35169 // Returns the image source for the icon.
dcheng9603ab92016-04-08 04:17:32170 std::unique_ptr<IconWithBadgeImageSource> GetIconImageSource(
rdevlin.croninfbfcca32015-07-09 00:28:35171 content::WebContents* web_contents,
Karan Bhatiafaee83d2018-07-19 06:20:59172 const gfx::Size& size);
rdevlin.croninfbfcca32015-07-09 00:28:35173
rdevlin.cronin09530742014-11-03 19:23:28174 // The extension associated with the action we're displaying.
rdevlin.cronin75c546722015-05-06 00:26:04175 scoped_refptr<const extensions::Extension> extension_;
rdevlin.cronin09530742014-11-03 19:23:28176
177 // The corresponding browser.
Keishi Hattori0e45c022021-11-27 09:25:52178 const raw_ptr<Browser> browser_;
Peter Boström4d71c392019-04-10 00:21:04179
rdevlin.cronin09530742014-11-03 19:23:28180 // The browser action this view represents. The ExtensionAction is not owned
181 // by this class.
Ali Hijazi4d4e24092022-10-20 22:59:31182 const raw_ptr<extensions::ExtensionAction, DanglingUntriaged>
183 extension_action_;
rdevlin.cronin09530742014-11-03 19:23:28184
Peter Boström91a80e82019-05-06 16:02:53185 // The corresponding ExtensionsContainer on the toolbar.
Keishi Hattori0e45c022021-11-27 09:25:52186 const raw_ptr<ExtensionsContainer> extensions_container_;
rdevlin.cronin5eb91b22015-04-23 19:39:05187
rdevlin.croninb43d48e2015-01-29 17:51:41188 // The extension popup's host if the popup is visible; null otherwise.
Keishi Hattori0e45c022021-11-27 09:25:52189 raw_ptr<extensions::ExtensionViewHost> popup_host_;
rdevlin.croninb43d48e2015-01-29 17:51:41190
Devlin Cronin04f77382022-08-18 00:03:51191 // Whether the toolbar action has opened an active popup. This is unique from
192 // `popup_host_` since `popup_host_` may be non-null even if the popup hasn't
193 // opened yet if we're waiting on other UI to be ready (e.g. the action to
194 // slide out in the toolbar).
195 bool has_opened_popup_ = false;
196
rdevlin.croninc10ac9e2015-01-16 21:10:08197 // The context menu model for the extension.
dcheng9603ab92016-04-08 04:17:32198 std::unique_ptr<extensions::ExtensionContextMenuModel> context_menu_model_;
rdevlin.croninc10ac9e2015-01-16 21:10:08199
rdevlin.cronin09530742014-11-03 19:23:28200 // Our view delegate.
Keishi Hattori0e45c022021-11-27 09:25:52201 raw_ptr<ToolbarActionViewDelegate> view_delegate_;
rdevlin.cronin09530742014-11-03 19:23:28202
203 // The delegate to handle platform-specific implementations.
dcheng9603ab92016-04-08 04:17:32204 std::unique_ptr<ExtensionActionPlatformDelegate> platform_delegate_;
rdevlin.cronin09530742014-11-03 19:23:28205
206 // The object that will be used to get the browser action icon for us.
207 // It may load the icon asynchronously (in which case the initial icon
208 // returned by the factory will be transparent), so we have to observe it for
209 // updates to the icon.
210 ExtensionActionIconFactory icon_factory_;
211
rdevlin.cronin651153652014-11-15 00:34:48212 // The associated ExtensionRegistry; cached for quick checking.
Keishi Hattori0e45c022021-11-27 09:25:52213 raw_ptr<extensions::ExtensionRegistry> extension_registry_;
rdevlin.cronin651153652014-11-15 00:34:48214
Sigurdur Asgeirsson70fd5db2021-04-28 19:10:35215 base::ScopedObservation<extensions::ExtensionHost,
216 extensions::ExtensionHostObserver>
217 popup_host_observation_{this};
rdevlin.croninb43d48e2015-01-29 17:51:41218
Jeremy Roman495db682019-07-12 16:03:24219 base::WeakPtrFactory<ExtensionActionViewController> weak_factory_{this};
rdevlin.cronin09530742014-11-03 19:23:28220};
221
222#endif // CHROME_BROWSER_UI_EXTENSIONS_EXTENSION_ACTION_VIEW_CONTROLLER_H_