// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_ #define CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_ #include <map> #include <set> #include <string> #include <vector> #include "base/callback.h" #include "base/compiler_specific.h" #include "base/memory/linked_ptr.h" #include "chrome/browser/extensions/location_bar_controller.h" #include "content/public/browser/web_contents_observer.h" namespace content { class WebContents; } namespace IPC { class Message; } class ExtensionAction; namespace extensions { class Extension; // The provider for ExtensionActions corresponding to scripts which are actively // running or need permission. // TODO(rdevlin.cronin): This isn't really a controller, but it has good parity // with PageAction"Controller". class ActiveScriptController : public LocationBarController::ActionProvider, public content::WebContentsObserver { public: explicit ActiveScriptController(content::WebContents* web_contents); virtual ~ActiveScriptController(); // Returns the ActiveScriptController for the given |web_contents|, or NULL // if one does not exist. static ActiveScriptController* GetForWebContents( content::WebContents* web_contents); // Returns true if the extension requesting script injection requires // user consent. If this is true, the caller should then register a request // via RequestScriptInjection(). bool RequiresUserConsentForScriptInjection(const Extension* extension); // Register a request for a script injection, to be executed by running // |callback|. The only assumption that can be made about when (or if) // |callback| is run is that, if it is run, it will run on the current page. void RequestScriptInjection(const Extension* extension, int page_id, const base::Closure& callback); // Notifies the ActiveScriptController that an extension has been granted // active tab permissions. This will run any pending injections for that // extension. void OnActiveTabPermissionGranted(const Extension* extension); // Notifies the ActiveScriptController of detected ad injection. void OnAdInjectionDetected(const std::set<std::string>& ad_injectors); // LocationBarControllerProvider implementation. virtual ExtensionAction* GetActionForExtension( const Extension* extension) OVERRIDE; virtual LocationBarController::Action OnClicked( const Extension* extension) OVERRIDE; virtual void OnNavigated() OVERRIDE; virtual void OnExtensionUnloaded(const Extension* extension) OVERRIDE; private: // A single pending request. This could be a pair, but we'd have way too many // stl typedefs, and "request.closure" is nicer than "request.first". struct PendingRequest { PendingRequest(); // For STL. PendingRequest(const base::Closure& closure, int page_id); ~PendingRequest(); base::Closure closure; int page_id; }; typedef std::vector<PendingRequest> PendingRequestList; typedef std::map<std::string, PendingRequestList> PendingRequestMap; // Runs any pending injections for the corresponding extension. void RunPendingForExtension(const Extension* extension); // Handle the RequestContentScriptPermission message. void OnRequestContentScriptPermission(const std::string& extension_id, int page_id, int request_id); // Grants permission for the given request to run. void GrantContentScriptPermission(int request_id); // content::WebContentsObserver implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; // Log metrics. void LogUMA() const; // Whether or not the ActiveScriptController is enabled (corresponding to the // kActiveScriptEnforcement switch). If it is not, it acts as an empty shell, // always allowing scripts to run and never displaying actions. bool enabled_; // The map of extension_id:pending_request of all pending requests. PendingRequestMap pending_requests_; // The extensions which have been granted permission to run on the given page. // TODO(rdevlin.cronin): Right now, this just keeps track of extensions that // have been permitted to run on the page via this interface. Instead, it // should incorporate more fully with ActiveTab. std::set<std::string> permitted_extensions_; // Script badges that have been generated for extensions. This is both those // with actions already declared that are copied and normalised, and actions // that get generated for extensions that haven't declared anything. typedef std::map<std::string, linked_ptr<ExtensionAction> > ActiveScriptMap; ActiveScriptMap active_script_actions_; DISALLOW_COPY_AND_ASSIGN(ActiveScriptController); }; } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_