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_
|