1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#ifndef CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <map>
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <set>
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <string>
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <vector>
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/callback.h"
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/compiler_specific.h"
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/scoped_observer.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/extension_registry_observer.h"
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/permissions/permissions_data.h"
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/user_script.h"
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace content {
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class WebContents;
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace IPC {
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class Message;
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class ExtensionAction;
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace extensions {
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class Extension;
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ExtensionRegistry;
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// The provider for ExtensionActions corresponding to scripts which are actively
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// running or need permission.
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(rdevlin.cronin): This isn't really a controller, but it has good parity
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// with LocationBar"Controller".
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ActiveScriptController : public content::WebContentsObserver,
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                               public ExtensionRegistryObserver {
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) public:
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  explicit ActiveScriptController(content::WebContents* web_contents);
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual ~ActiveScriptController();
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Returns the ActiveScriptController for the given |web_contents|, or NULL
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // if one does not exist.
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static ActiveScriptController* GetForWebContents(
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      content::WebContents* web_contents);
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Notifies the ActiveScriptController that an extension has been granted
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // active tab permissions. This will run any pending injections for that
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // extension.
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void OnActiveTabPermissionGranted(const Extension* extension);
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Notifies the ActiveScriptController of detected ad injection.
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void OnAdInjectionDetected(const std::set<std::string>& ad_injectors);
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Adds the visible origin to |extension|'s active permissions, granting
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // |extension| permission to always run script injections on the origin.
606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void AlwaysRunOnVisibleOrigin(const Extension* extension);
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Notifies the ActiveScriptController that the action for |extension| has
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // been clicked, running any pending tasks that were previously shelved.
641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void OnClicked(const Extension* extension);
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Returns true if the given |extension| has a pending script that wants to
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // run.
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool WantsToRun(const Extension* extension);
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(UNIT_TEST)
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Only used in tests.
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PermissionsData::AccessType RequiresUserConsentForScriptInjectionForTesting(
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const Extension* extension,
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UserScript::InjectionType type) {
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return RequiresUserConsentForScriptInjection(extension, type);
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void RequestScriptInjectionForTesting(const Extension* extension,
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                        const base::Closure& callback) {
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return RequestScriptInjection(extension, callback);
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif  // defined(UNIT_TEST)
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) private:
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  typedef std::vector<base::Closure> PendingRequestList;
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  typedef std::map<std::string, PendingRequestList> PendingRequestMap;
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Returns true if the extension requesting script injection requires
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // user consent. If this is true, the caller should then register a request
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // via RequestScriptInjection().
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PermissionsData::AccessType RequiresUserConsentForScriptInjection(
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const Extension* extension,
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UserScript::InjectionType type);
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // |callback|. The only assumption that can be made about when (or if)
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // |callback| is run is that, if it is run, it will run on the current page.
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void RequestScriptInjection(const Extension* extension,
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                              const base::Closure& callback);
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Runs any pending injections for the corresponding extension.
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  void RunPendingForExtension(const Extension* extension);
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Handle the RequestScriptInjectionPermission message.
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void OnRequestScriptInjectionPermission(
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      const std::string& extension_id,
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      UserScript::InjectionType script_type,
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      int64 request_id);
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Grants permission for the given request to run.
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void PermitScriptInjection(int64 request_id);
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Log metrics.
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void LogUMA() const;
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // content::WebContentsObserver implementation.
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void DidNavigateMainFrame(
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const content::LoadCommittedDetails& details,
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const content::FrameNavigateParams& params) OVERRIDE;
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // ExtensionRegistryObserver:
1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual void OnExtensionUnloaded(
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      content::BrowserContext* browser_context,
1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      const Extension* extension,
1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      UnloadedExtensionInfo::Reason reason) OVERRIDE;
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Whether or not the ActiveScriptController is enabled (corresponding to the
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // kActiveScriptEnforcement switch). If it is not, it acts as an empty shell,
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // always allowing scripts to run and never displaying actions.
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool enabled_;
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The map of extension_id:pending_request of all pending requests.
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PendingRequestMap pending_requests_;
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The extensions which have been granted permission to run on the given page.
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(rdevlin.cronin): Right now, this just keeps track of extensions that
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // have been permitted to run on the page via this interface. Instead, it
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // should incorporate more fully with ActiveTab.
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::set<std::string> permitted_extensions_;
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      extension_registry_observer_;
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ActiveScriptController);
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)};
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace extensions
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif  // CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_
149