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 8 #include <map> 9 #include <set> 10 #include <string> 11 #include <vector> 12 13 #include "base/callback.h" 14 #include "base/compiler_specific.h" 15 #include "base/memory/linked_ptr.h" 16 #include "chrome/browser/extensions/location_bar_controller.h" 17 #include "content/public/browser/web_contents_observer.h" 18 19 namespace content { 20 class WebContents; 21 } 22 23 namespace IPC { 24 class Message; 25 } 26 27 class ExtensionAction; 28 29 namespace extensions { 30 class Extension; 31 32 // The provider for ExtensionActions corresponding to scripts which are actively 33 // running or need permission. 34 // TODO(rdevlin.cronin): This isn't really a controller, but it has good parity 35 // with PageAction"Controller". 36 class ActiveScriptController : public LocationBarController::ActionProvider, 37 public content::WebContentsObserver { 38 public: 39 explicit ActiveScriptController(content::WebContents* web_contents); 40 virtual ~ActiveScriptController(); 41 42 // Returns the ActiveScriptController for the given |web_contents|, or NULL 43 // if one does not exist. 44 static ActiveScriptController* GetForWebContents( 45 content::WebContents* web_contents); 46 47 // Returns true if the extension requesting script injection requires 48 // user consent. If this is true, the caller should then register a request 49 // via RequestScriptInjection(). 50 bool RequiresUserConsentForScriptInjection(const Extension* extension); 51 52 // Register a request for a script injection, to be executed by running 53 // |callback|. The only assumption that can be made about when (or if) 54 // |callback| is run is that, if it is run, it will run on the current page. 55 void RequestScriptInjection(const Extension* extension, 56 int page_id, 57 const base::Closure& callback); 58 59 // Notifies the ActiveScriptController that an extension has been granted 60 // active tab permissions. This will run any pending injections for that 61 // extension. 62 void OnActiveTabPermissionGranted(const Extension* extension); 63 64 // Notifies the ActiveScriptController of detected ad injection. 65 void OnAdInjectionDetected(const std::set<std::string>& ad_injectors); 66 67 // LocationBarControllerProvider implementation. 68 virtual ExtensionAction* GetActionForExtension( 69 const Extension* extension) OVERRIDE; 70 virtual LocationBarController::Action OnClicked( 71 const Extension* extension) OVERRIDE; 72 virtual void OnNavigated() OVERRIDE; 73 virtual void OnExtensionUnloaded(const Extension* extension) OVERRIDE; 74 75 private: 76 // A single pending request. This could be a pair, but we'd have way too many 77 // stl typedefs, and "request.closure" is nicer than "request.first". 78 struct PendingRequest { 79 PendingRequest(); // For STL. 80 PendingRequest(const base::Closure& closure, int page_id); 81 ~PendingRequest(); 82 83 base::Closure closure; 84 int page_id; 85 }; 86 typedef std::vector<PendingRequest> PendingRequestList; 87 typedef std::map<std::string, PendingRequestList> PendingRequestMap; 88 89 // Runs any pending injections for the corresponding extension. 90 void RunPendingForExtension(const Extension* extension); 91 92 // Handle the RequestContentScriptPermission message. 93 void OnRequestContentScriptPermission(const std::string& extension_id, 94 int page_id, 95 int request_id); 96 97 // Grants permission for the given request to run. 98 void GrantContentScriptPermission(int request_id); 99 100 // content::WebContentsObserver implementation. 101 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; 102 103 // Log metrics. 104 void LogUMA() const; 105 106 // Whether or not the ActiveScriptController is enabled (corresponding to the 107 // kActiveScriptEnforcement switch). If it is not, it acts as an empty shell, 108 // always allowing scripts to run and never displaying actions. 109 bool enabled_; 110 111 // The map of extension_id:pending_request of all pending requests. 112 PendingRequestMap pending_requests_; 113 114 // The extensions which have been granted permission to run on the given page. 115 // TODO(rdevlin.cronin): Right now, this just keeps track of extensions that 116 // have been permitted to run on the page via this interface. Instead, it 117 // should incorporate more fully with ActiveTab. 118 std::set<std::string> permitted_extensions_; 119 120 // Script badges that have been generated for extensions. This is both those 121 // with actions already declared that are copied and normalised, and actions 122 // that get generated for extensions that haven't declared anything. 123 typedef std::map<std::string, linked_ptr<ExtensionAction> > ActiveScriptMap; 124 ActiveScriptMap active_script_actions_; 125 126 DISALLOW_COPY_AND_ASSIGN(ActiveScriptController); 127 }; 128 129 } // namespace extensions 130 131 #endif // CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_ 132