1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
// 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/scoped_observer.h"
#include "content/public/browser/web_contents_observer.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/user_script.h"
namespace content {
class BrowserContext;
class WebContents;
}
namespace IPC {
class Message;
}
class ExtensionAction;
namespace extensions {
class Extension;
class ExtensionRegistry;
// 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 LocationBar"Controller".
class ActiveScriptController : public content::WebContentsObserver,
public ExtensionRegistryObserver {
public:
explicit ActiveScriptController(content::WebContents* web_contents);
~ActiveScriptController() override;
// Returns the ActiveScriptController for the given |web_contents|, or NULL
// if one does not exist.
static ActiveScriptController* GetForWebContents(
content::WebContents* web_contents);
// 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);
// Adds the visible origin to |extension|'s active permissions, granting
// |extension| permission to always run script injections on the origin.
void AlwaysRunOnVisibleOrigin(const Extension* extension);
// Notifies the ActiveScriptController that the action for |extension| has
// been clicked, running any pending tasks that were previously shelved.
void OnClicked(const Extension* extension);
// Returns true if the given |extension| has a pending script that wants to
// run.
bool WantsToRun(const Extension* extension);
#if defined(UNIT_TEST)
// Only used in tests.
PermissionsData::AccessType RequiresUserConsentForScriptInjectionForTesting(
const Extension* extension,
UserScript::InjectionType type) {
return RequiresUserConsentForScriptInjection(extension, type);
}
void RequestScriptInjectionForTesting(const Extension* extension,
const base::Closure& callback) {
return RequestScriptInjection(extension, callback);
}
#endif // defined(UNIT_TEST)
private:
typedef std::vector<base::Closure> PendingRequestList;
typedef std::map<std::string, PendingRequestList> PendingRequestMap;
// Returns true if the extension requesting script injection requires
// user consent. If this is true, the caller should then register a request
// via RequestScriptInjection().
PermissionsData::AccessType RequiresUserConsentForScriptInjection(
const Extension* extension,
UserScript::InjectionType type);
// |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,
const base::Closure& callback);
// Runs any pending injections for the corresponding extension.
void RunPendingForExtension(const Extension* extension);
// Handle the RequestScriptInjectionPermission message.
void OnRequestScriptInjectionPermission(
const std::string& extension_id,
UserScript::InjectionType script_type,
int64 request_id);
// Grants permission for the given request to run.
void PermitScriptInjection(int64 request_id);
// Notifies the ExtensionActionAPI of a change (either that an extension now
// wants permission to run, or that it has been run).
void NotifyChange(const Extension* extension);
// Log metrics.
void LogUMA() const;
// content::WebContentsObserver implementation.
bool OnMessageReceived(const IPC::Message& message) override;
void DidNavigateMainFrame(
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) override;
// ExtensionRegistryObserver:
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionInfo::Reason reason) override;
// The associated browser context.
content::BrowserContext* browser_context_;
// 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_;
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_;
DISALLOW_COPY_AND_ASSIGN(ActiveScriptController);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_ACTIVE_SCRIPT_CONTROLLER_H_
|