blob: f29a0d778b89af4749a3064cd1cdb52b7fdb6d43 [file] [log] [blame]
[email protected]39ef0a7c52014-05-11 01:40:001// 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
rdevlin.cronin8408b4f92016-03-15 19:14:145#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_RUNNER_H_
6#define CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_RUNNER_H_
[email protected]39ef0a7c52014-05-11 01:40:007
avia2f4804a2015-12-24 23:11:138#include <stdint.h>
9
[email protected]39ef0a7c52014-05-11 01:40:0010#include <map>
11#include <set>
12#include <string>
[email protected]ac02ac52014-05-20 01:11:2613#include <vector>
[email protected]39ef0a7c52014-05-11 01:40:0014
[email protected]ac02ac52014-05-20 01:11:2615#include "base/callback.h"
[email protected]39ef0a7c52014-05-11 01:40:0016#include "base/compiler_specific.h"
avia2f4804a2015-12-24 23:11:1317#include "base/macros.h"
rdevlin.cronin4a78c48b2016-03-24 00:02:2918#include "base/memory/weak_ptr.h"
rdevlin.cronin91f162a12014-09-03 16:48:4019#include "base/scoped_observer.h"
rdevlin.cronin343fd102016-03-17 00:24:5420#include "chrome/browser/extensions/extension_action.h"
rdevlin.cronin4a78c48b2016-03-24 00:02:2921#include "chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h"
[email protected]39ef0a7c52014-05-11 01:40:0022#include "content/public/browser/web_contents_observer.h"
rdevlin.cronin8d034e52016-02-02 22:46:3223#include "extensions/browser/blocked_action_type.h"
rdevlin.cronin6e7e5edc2014-08-29 16:23:2324#include "extensions/browser/extension_registry_observer.h"
[email protected]23a85362014-07-07 23:26:1925#include "extensions/common/permissions/permissions_data.h"
26#include "extensions/common/user_script.h"
[email protected]39ef0a7c52014-05-11 01:40:0027
28namespace content {
rdevlin.cronin699ca6ff2014-09-29 23:59:5729class BrowserContext;
[email protected]39ef0a7c52014-05-11 01:40:0030class WebContents;
31}
32
33namespace IPC {
34class Message;
35}
36
[email protected]39ef0a7c52014-05-11 01:40:0037namespace extensions {
38class Extension;
rdevlin.cronin6e7e5edc2014-08-29 16:23:2339class ExtensionRegistry;
[email protected]39ef0a7c52014-05-11 01:40:0040
41// The provider for ExtensionActions corresponding to scripts which are actively
42// running or need permission.
rdevlin.cronin8408b4f92016-03-15 19:14:1443class ExtensionActionRunner : public content::WebContentsObserver,
44 public ExtensionRegistryObserver {
[email protected]39ef0a7c52014-05-11 01:40:0045 public:
rdevlin.cronin8408b4f92016-03-15 19:14:1446 explicit ExtensionActionRunner(content::WebContents* web_contents);
47 ~ExtensionActionRunner() override;
[email protected]39ef0a7c52014-05-11 01:40:0048
rdevlin.cronin343fd102016-03-17 00:24:5449 // Returns the ExtensionActionRunner for the given |web_contents|, or null
[email protected]eac223a2014-05-13 17:39:5750 // if one does not exist.
rdevlin.cronin8408b4f92016-03-15 19:14:1451 static ExtensionActionRunner* GetForWebContents(
[email protected]eac223a2014-05-13 17:39:5752 content::WebContents* web_contents);
53
rdevlin.cronin343fd102016-03-17 00:24:5454 // Executes the action for the given |extension| and returns any further
55 // action (like showing a popup) that should be taken. If
56 // |grant_tab_permissions| is true, this will also grant activeTab to the
57 // extension (so this should only be done if this is through a direct user
58 // action).
59 ExtensionAction::ShowAction RunAction(const Extension* extension,
60 bool grant_tab_permissions);
61
62 // Runs any actions that were blocked for the given |extension|. As a
63 // requirement, this will grant activeTab permission to the extension.
64 void RunBlockedActions(const Extension* extension);
65
rdevlin.cronin8408b4f92016-03-15 19:14:1466 // Notifies the ExtensionActionRunner that an extension has been granted
[email protected]11814f52014-05-23 06:50:3567 // active tab permissions. This will run any pending injections for that
68 // extension.
69 void OnActiveTabPermissionGranted(const Extension* extension);
70
rdevlin.cronin8d034e52016-02-02 22:46:3271 // Called when a webRequest event for the given |extension| was blocked.
72 void OnWebRequestBlocked(const Extension* extension);
73
74 // Returns a bitmask of BlockedActionType for the actions that have been
75 // blocked for the given extension.
76 int GetBlockedActions(const Extension* extension);
77
78 // Returns true if the given |extension| has any blocked actions.
rdevlin.cronin91f162a12014-09-03 16:48:4079 bool WantsToRun(const Extension* extension);
rdevlin.cronin50942232014-08-27 17:40:5680
rdevlin.cronin4a78c48b2016-03-24 00:02:2981 // Runs any blocked actions the extension has, but does not handle any page
82 // refreshes for document_start/webRequest.
83 void RunForTesting(const Extension* extension);
84
rdevlin.cronin1f877032015-02-20 00:12:4285 int num_page_requests() const { return num_page_requests_; }
86
rdevlin.cronin4a78c48b2016-03-24 00:02:2987 void set_default_bubble_close_action_for_testing(
dchengc963c7142016-04-08 03:55:2288 std::unique_ptr<ToolbarActionsBarBubbleDelegate::CloseAction> action) {
rdevlin.cronin4a78c48b2016-03-24 00:02:2989 default_bubble_close_action_for_testing_ = std::move(action);
90 }
91
[email protected]23a85362014-07-07 23:26:1992#if defined(UNIT_TEST)
93 // Only used in tests.
94 PermissionsData::AccessType RequiresUserConsentForScriptInjectionForTesting(
95 const Extension* extension,
96 UserScript::InjectionType type) {
97 return RequiresUserConsentForScriptInjection(extension, type);
98 }
99 void RequestScriptInjectionForTesting(const Extension* extension,
rdevlin.cronin8d034e52016-02-02 22:46:32100 UserScript::RunLocation run_location,
[email protected]23a85362014-07-07 23:26:19101 const base::Closure& callback) {
rdevlin.cronin8d034e52016-02-02 22:46:32102 return RequestScriptInjection(extension, run_location, callback);
[email protected]23a85362014-07-07 23:26:19103 }
104#endif // defined(UNIT_TEST)
105
[email protected]39ef0a7c52014-05-11 01:40:00106 private:
rdevlin.cronin8d034e52016-02-02 22:46:32107 struct PendingScript {
108 PendingScript(UserScript::RunLocation run_location,
109 const base::Closure& permit_script);
vmpstrb8aacbe2016-02-26 02:00:48110 PendingScript(const PendingScript& other);
rdevlin.cronin8d034e52016-02-02 22:46:32111 ~PendingScript();
112
113 // The run location that the script wants to inject at.
114 UserScript::RunLocation run_location;
115
116 // The callback to run when the script is permitted by the user.
117 base::Closure permit_script;
118 };
119
120 using PendingScriptList = std::vector<PendingScript>;
121 using PendingScriptMap = std::map<std::string, PendingScriptList>;
[email protected]ac02ac52014-05-20 01:11:26122
[email protected]23a85362014-07-07 23:26:19123 // Returns true if the extension requesting script injection requires
124 // user consent. If this is true, the caller should then register a request
125 // via RequestScriptInjection().
126 PermissionsData::AccessType RequiresUserConsentForScriptInjection(
127 const Extension* extension,
128 UserScript::InjectionType type);
129
130 // |callback|. The only assumption that can be made about when (or if)
131 // |callback| is run is that, if it is run, it will run on the current page.
132 void RequestScriptInjection(const Extension* extension,
rdevlin.cronin8d034e52016-02-02 22:46:32133 UserScript::RunLocation run_location,
[email protected]23a85362014-07-07 23:26:19134 const base::Closure& callback);
135
[email protected]11814f52014-05-23 06:50:35136 // Runs any pending injections for the corresponding extension.
rdevlin.croninacb745922016-02-17 20:37:44137 void RunPendingScriptsForExtension(const Extension* extension);
[email protected]11814f52014-05-23 06:50:35138
[email protected]ac2f89372014-06-23 21:44:25139 // Handle the RequestScriptInjectionPermission message.
avia2f4804a2015-12-24 23:11:13140 void OnRequestScriptInjectionPermission(const std::string& extension_id,
141 UserScript::InjectionType script_type,
rdevlin.cronin8d034e52016-02-02 22:46:32142 UserScript::RunLocation run_location,
avia2f4804a2015-12-24 23:11:13143 int64_t request_id);
[email protected]0d8d6972014-06-03 22:41:02144
145 // Grants permission for the given request to run.
avia2f4804a2015-12-24 23:11:13146 void PermitScriptInjection(int64_t request_id);
[email protected]39ef0a7c52014-05-11 01:40:00147
rdevlin.cronin699ca6ff2014-09-29 23:59:57148 // Notifies the ExtensionActionAPI of a change (either that an extension now
149 // wants permission to run, or that it has been run).
150 void NotifyChange(const Extension* extension);
151
rdevlin.cronin6e7e5edc2014-08-29 16:23:23152 // Log metrics.
153 void LogUMA() const;
154
rdevlin.cronin4a78c48b2016-03-24 00:02:29155 // Shows the bubble to prompt the user to refresh the page to run the blocked
156 // actions for the given |extension|.
157 void ShowBlockedActionBubble(const Extension* extension);
158
159 // Called when the blocked actions bubble is closed.
160 void OnBlockedActionBubbleClosed(
161 const std::string& extension_id,
162 ToolbarActionsBarBubbleDelegate::CloseAction action);
163
[email protected]ac02ac52014-05-20 01:11:26164 // content::WebContentsObserver implementation.
rdevlin.cronin45dca7f2015-06-08 19:47:03165 bool OnMessageReceived(const IPC::Message& message,
166 content::RenderFrameHost* render_frame_host) override;
jam29737c42017-02-01 16:26:08167 void DidFinishNavigation(
168 content::NavigationHandle* navigation_handle) override;
[email protected]ac02ac52014-05-20 01:11:26169
rdevlin.cronin6e7e5edc2014-08-29 16:23:23170 // ExtensionRegistryObserver:
dchengae36a4a2014-10-21 12:36:36171 void OnExtensionUnloaded(content::BrowserContext* browser_context,
172 const Extension* extension,
limasdf0deef2042017-05-03 19:17:17173 UnloadedExtensionReason reason) override;
[email protected]39ef0a7c52014-05-11 01:40:00174
rdevlin.cronin1f877032015-02-20 00:12:42175 // The total number of requests from the renderer on the current page,
176 // including any that are pending or were immediately granted.
177 // Right now, used only in tests.
178 int num_page_requests_;
179
rdevlin.cronin699ca6ff2014-09-29 23:59:57180 // The associated browser context.
181 content::BrowserContext* browser_context_;
182
rdevlin.croninb8dffe52015-02-07 00:58:01183 // Whether or not the feature was used for any extensions. This may not be the
184 // case if the user never enabled the scripts-require-action flag.
185 bool was_used_on_page_;
[email protected]39ef0a7c52014-05-11 01:40:00186
rdevlin.cronin8d034e52016-02-02 22:46:32187 // The map of extension_id:pending_request of all pending script requests.
188 PendingScriptMap pending_scripts_;
189
190 // A set of ids for which the webRequest API was blocked on the page.
191 std::set<std::string> web_request_blocked_;
[email protected]39ef0a7c52014-05-11 01:40:00192
[email protected]ac02ac52014-05-20 01:11:26193 // The extensions which have been granted permission to run on the given page.
194 // TODO(rdevlin.cronin): Right now, this just keeps track of extensions that
195 // have been permitted to run on the page via this interface. Instead, it
196 // should incorporate more fully with ActiveTab.
197 std::set<std::string> permitted_extensions_;
[email protected]39ef0a7c52014-05-11 01:40:00198
rdevlin.cronin4a78c48b2016-03-24 00:02:29199 // If true, ignore active tab being granted rather than running pending
200 // actions.
201 bool ignore_active_tab_granted_;
202
203 // If non-null, the bubble action to simulate for testing.
dchengc963c7142016-04-08 03:55:22204 std::unique_ptr<ToolbarActionsBarBubbleDelegate::CloseAction>
rdevlin.cronin4a78c48b2016-03-24 00:02:29205 default_bubble_close_action_for_testing_;
206
rdevlin.cronin6e7e5edc2014-08-29 16:23:23207 ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
208 extension_registry_observer_;
209
rdevlin.cronin4a78c48b2016-03-24 00:02:29210 base::WeakPtrFactory<ExtensionActionRunner> weak_factory_;
211
rdevlin.cronin8408b4f92016-03-15 19:14:14212 DISALLOW_COPY_AND_ASSIGN(ExtensionActionRunner);
[email protected]39ef0a7c52014-05-11 01:40:00213};
214
215} // namespace extensions
216
rdevlin.cronin8408b4f92016-03-15 19:14:14217#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_ACTION_RUNNER_H_