[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 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. |
| 4 | |
| 5 | #ifndef CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_ |
| 6 | #define CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_ |
| 7 | |
avi | a2f4804a | 2015-12-24 23:11:13 | [diff] [blame] | 8 | #include <stdint.h> |
| 9 | |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 10 | #include <map> |
| 11 | #include <set> |
| 12 | #include <string> |
[email protected] | ac02ac5 | 2014-05-20 01:11:26 | [diff] [blame] | 13 | #include <vector> |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 14 | |
[email protected] | ac02ac5 | 2014-05-20 01:11:26 | [diff] [blame] | 15 | #include "base/callback.h" |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 16 | #include "base/compiler_specific.h" |
avi | a2f4804a | 2015-12-24 23:11:13 | [diff] [blame] | 17 | #include "base/macros.h" |
rdevlin.cronin | 91f162a1 | 2014-09-03 16:48:40 | [diff] [blame] | 18 | #include "base/scoped_observer.h" |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 19 | #include "content/public/browser/web_contents_observer.h" |
rdevlin.cronin | 8d034e5 | 2016-02-02 22:46:32 | [diff] [blame] | 20 | #include "extensions/browser/blocked_action_type.h" |
rdevlin.cronin | 6e7e5edc | 2014-08-29 16:23:23 | [diff] [blame] | 21 | #include "extensions/browser/extension_registry_observer.h" |
[email protected] | 23a8536 | 2014-07-07 23:26:19 | [diff] [blame] | 22 | #include "extensions/common/permissions/permissions_data.h" |
| 23 | #include "extensions/common/user_script.h" |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 24 | |
| 25 | namespace content { |
rdevlin.cronin | 699ca6ff | 2014-09-29 23:59:57 | [diff] [blame] | 26 | class BrowserContext; |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 27 | class WebContents; |
| 28 | } |
| 29 | |
| 30 | namespace IPC { |
| 31 | class Message; |
| 32 | } |
| 33 | |
| 34 | class ExtensionAction; |
| 35 | |
| 36 | namespace extensions { |
| 37 | class Extension; |
rdevlin.cronin | 6e7e5edc | 2014-08-29 16:23:23 | [diff] [blame] | 38 | class ExtensionRegistry; |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 39 | |
| 40 | // The provider for ExtensionActions corresponding to scripts which are actively |
| 41 | // running or need permission. |
| 42 | // TODO(rdevlin.cronin): This isn't really a controller, but it has good parity |
rdevlin.cronin | 5094223 | 2014-08-27 17:40:56 | [diff] [blame] | 43 | // with LocationBar"Controller". |
rdevlin.cronin | 6e7e5edc | 2014-08-29 16:23:23 | [diff] [blame] | 44 | class ActiveScriptController : public content::WebContentsObserver, |
| 45 | public ExtensionRegistryObserver { |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 46 | public: |
| 47 | explicit ActiveScriptController(content::WebContents* web_contents); |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 48 | ~ActiveScriptController() override; |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 49 | |
[email protected] | eac223a | 2014-05-13 17:39:57 | [diff] [blame] | 50 | // Returns the ActiveScriptController for the given |web_contents|, or NULL |
| 51 | // if one does not exist. |
| 52 | static ActiveScriptController* GetForWebContents( |
| 53 | content::WebContents* web_contents); |
| 54 | |
[email protected] | 11814f5 | 2014-05-23 06:50:35 | [diff] [blame] | 55 | // Notifies the ActiveScriptController that an extension has been granted |
| 56 | // active tab permissions. This will run any pending injections for that |
| 57 | // extension. |
| 58 | void OnActiveTabPermissionGranted(const Extension* extension); |
| 59 | |
rdevlin.cronin | e9c7112 | 2014-08-25 23:47:21 | [diff] [blame] | 60 | // Notifies the ActiveScriptController that the action for |extension| has |
| 61 | // been clicked, running any pending tasks that were previously shelved. |
| 62 | void OnClicked(const Extension* extension); |
| 63 | |
rdevlin.cronin | 8d034e5 | 2016-02-02 22:46:32 | [diff] [blame] | 64 | // Called when a webRequest event for the given |extension| was blocked. |
| 65 | void OnWebRequestBlocked(const Extension* extension); |
| 66 | |
| 67 | // Returns a bitmask of BlockedActionType for the actions that have been |
| 68 | // blocked for the given extension. |
| 69 | int GetBlockedActions(const Extension* extension); |
| 70 | |
| 71 | // Returns true if the given |extension| has any blocked actions. |
rdevlin.cronin | 91f162a1 | 2014-09-03 16:48:40 | [diff] [blame] | 72 | bool WantsToRun(const Extension* extension); |
rdevlin.cronin | 5094223 | 2014-08-27 17:40:56 | [diff] [blame] | 73 | |
rdevlin.cronin | 1f87703 | 2015-02-20 00:12:42 | [diff] [blame] | 74 | int num_page_requests() const { return num_page_requests_; } |
| 75 | |
[email protected] | 23a8536 | 2014-07-07 23:26:19 | [diff] [blame] | 76 | #if defined(UNIT_TEST) |
| 77 | // Only used in tests. |
| 78 | PermissionsData::AccessType RequiresUserConsentForScriptInjectionForTesting( |
| 79 | const Extension* extension, |
| 80 | UserScript::InjectionType type) { |
| 81 | return RequiresUserConsentForScriptInjection(extension, type); |
| 82 | } |
| 83 | void RequestScriptInjectionForTesting(const Extension* extension, |
rdevlin.cronin | 8d034e5 | 2016-02-02 22:46:32 | [diff] [blame] | 84 | UserScript::RunLocation run_location, |
[email protected] | 23a8536 | 2014-07-07 23:26:19 | [diff] [blame] | 85 | const base::Closure& callback) { |
rdevlin.cronin | 8d034e5 | 2016-02-02 22:46:32 | [diff] [blame] | 86 | return RequestScriptInjection(extension, run_location, callback); |
[email protected] | 23a8536 | 2014-07-07 23:26:19 | [diff] [blame] | 87 | } |
| 88 | #endif // defined(UNIT_TEST) |
| 89 | |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 90 | private: |
rdevlin.cronin | 8d034e5 | 2016-02-02 22:46:32 | [diff] [blame] | 91 | struct PendingScript { |
| 92 | PendingScript(UserScript::RunLocation run_location, |
| 93 | const base::Closure& permit_script); |
| 94 | ~PendingScript(); |
| 95 | |
| 96 | // The run location that the script wants to inject at. |
| 97 | UserScript::RunLocation run_location; |
| 98 | |
| 99 | // The callback to run when the script is permitted by the user. |
| 100 | base::Closure permit_script; |
| 101 | }; |
| 102 | |
| 103 | using PendingScriptList = std::vector<PendingScript>; |
| 104 | using PendingScriptMap = std::map<std::string, PendingScriptList>; |
[email protected] | ac02ac5 | 2014-05-20 01:11:26 | [diff] [blame] | 105 | |
[email protected] | 23a8536 | 2014-07-07 23:26:19 | [diff] [blame] | 106 | // Returns true if the extension requesting script injection requires |
| 107 | // user consent. If this is true, the caller should then register a request |
| 108 | // via RequestScriptInjection(). |
| 109 | PermissionsData::AccessType RequiresUserConsentForScriptInjection( |
| 110 | const Extension* extension, |
| 111 | UserScript::InjectionType type); |
| 112 | |
| 113 | // |callback|. The only assumption that can be made about when (or if) |
| 114 | // |callback| is run is that, if it is run, it will run on the current page. |
| 115 | void RequestScriptInjection(const Extension* extension, |
rdevlin.cronin | 8d034e5 | 2016-02-02 22:46:32 | [diff] [blame] | 116 | UserScript::RunLocation run_location, |
[email protected] | 23a8536 | 2014-07-07 23:26:19 | [diff] [blame] | 117 | const base::Closure& callback); |
| 118 | |
[email protected] | 11814f5 | 2014-05-23 06:50:35 | [diff] [blame] | 119 | // Runs any pending injections for the corresponding extension. |
rdevlin.cronin | acb74592 | 2016-02-17 20:37:44 | [diff] [blame^] | 120 | void RunPendingScriptsForExtension(const Extension* extension); |
[email protected] | 11814f5 | 2014-05-23 06:50:35 | [diff] [blame] | 121 | |
[email protected] | ac2f8937 | 2014-06-23 21:44:25 | [diff] [blame] | 122 | // Handle the RequestScriptInjectionPermission message. |
avi | a2f4804a | 2015-12-24 23:11:13 | [diff] [blame] | 123 | void OnRequestScriptInjectionPermission(const std::string& extension_id, |
| 124 | UserScript::InjectionType script_type, |
rdevlin.cronin | 8d034e5 | 2016-02-02 22:46:32 | [diff] [blame] | 125 | UserScript::RunLocation run_location, |
avi | a2f4804a | 2015-12-24 23:11:13 | [diff] [blame] | 126 | int64_t request_id); |
[email protected] | 0d8d697 | 2014-06-03 22:41:02 | [diff] [blame] | 127 | |
| 128 | // Grants permission for the given request to run. |
avi | a2f4804a | 2015-12-24 23:11:13 | [diff] [blame] | 129 | void PermitScriptInjection(int64_t request_id); |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 130 | |
rdevlin.cronin | 699ca6ff | 2014-09-29 23:59:57 | [diff] [blame] | 131 | // Notifies the ExtensionActionAPI of a change (either that an extension now |
| 132 | // wants permission to run, or that it has been run). |
| 133 | void NotifyChange(const Extension* extension); |
| 134 | |
rdevlin.cronin | 6e7e5edc | 2014-08-29 16:23:23 | [diff] [blame] | 135 | // Log metrics. |
| 136 | void LogUMA() const; |
| 137 | |
[email protected] | ac02ac5 | 2014-05-20 01:11:26 | [diff] [blame] | 138 | // content::WebContentsObserver implementation. |
rdevlin.cronin | 45dca7f | 2015-06-08 19:47:03 | [diff] [blame] | 139 | bool OnMessageReceived(const IPC::Message& message, |
| 140 | content::RenderFrameHost* render_frame_host) override; |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 141 | void DidNavigateMainFrame( |
rdevlin.cronin | 5094223 | 2014-08-27 17:40:56 | [diff] [blame] | 142 | const content::LoadCommittedDetails& details, |
mostynb | a15bee1 | 2014-10-04 00:40:32 | [diff] [blame] | 143 | const content::FrameNavigateParams& params) override; |
[email protected] | ac02ac5 | 2014-05-20 01:11:26 | [diff] [blame] | 144 | |
rdevlin.cronin | 6e7e5edc | 2014-08-29 16:23:23 | [diff] [blame] | 145 | // ExtensionRegistryObserver: |
dcheng | ae36a4a | 2014-10-21 12:36:36 | [diff] [blame] | 146 | void OnExtensionUnloaded(content::BrowserContext* browser_context, |
| 147 | const Extension* extension, |
| 148 | UnloadedExtensionInfo::Reason reason) override; |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 149 | |
rdevlin.cronin | 1f87703 | 2015-02-20 00:12:42 | [diff] [blame] | 150 | // The total number of requests from the renderer on the current page, |
| 151 | // including any that are pending or were immediately granted. |
| 152 | // Right now, used only in tests. |
| 153 | int num_page_requests_; |
| 154 | |
rdevlin.cronin | 699ca6ff | 2014-09-29 23:59:57 | [diff] [blame] | 155 | // The associated browser context. |
| 156 | content::BrowserContext* browser_context_; |
| 157 | |
rdevlin.cronin | b8dffe5 | 2015-02-07 00:58:01 | [diff] [blame] | 158 | // Whether or not the feature was used for any extensions. This may not be the |
| 159 | // case if the user never enabled the scripts-require-action flag. |
| 160 | bool was_used_on_page_; |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 161 | |
rdevlin.cronin | 8d034e5 | 2016-02-02 22:46:32 | [diff] [blame] | 162 | // The map of extension_id:pending_request of all pending script requests. |
| 163 | PendingScriptMap pending_scripts_; |
| 164 | |
| 165 | // A set of ids for which the webRequest API was blocked on the page. |
| 166 | std::set<std::string> web_request_blocked_; |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 167 | |
[email protected] | ac02ac5 | 2014-05-20 01:11:26 | [diff] [blame] | 168 | // The extensions which have been granted permission to run on the given page. |
| 169 | // TODO(rdevlin.cronin): Right now, this just keeps track of extensions that |
| 170 | // have been permitted to run on the page via this interface. Instead, it |
| 171 | // should incorporate more fully with ActiveTab. |
| 172 | std::set<std::string> permitted_extensions_; |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 173 | |
rdevlin.cronin | 6e7e5edc | 2014-08-29 16:23:23 | [diff] [blame] | 174 | ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> |
| 175 | extension_registry_observer_; |
| 176 | |
[email protected] | 39ef0a7c5 | 2014-05-11 01:40:00 | [diff] [blame] | 177 | DISALLOW_COPY_AND_ASSIGN(ActiveScriptController); |
| 178 | }; |
| 179 | |
| 180 | } // namespace extensions |
| 181 | |
| 182 | #endif // CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_ |