| Index: chrome/browser/extensions/active_script_controller.cc
|
| diff --git a/chrome/browser/extensions/active_script_controller.cc b/chrome/browser/extensions/active_script_controller.cc
|
| index 906da8ec1d37f32ccda26e75a42be9f4903a5eb9..fa2d6abc542270c5adfaae5007c424eb771fcb3a 100644
|
| --- a/chrome/browser/extensions/active_script_controller.cc
|
| +++ b/chrome/browser/extensions/active_script_controller.cc
|
| @@ -25,11 +25,32 @@
|
| #include "extensions/common/extension_messages.h"
|
| #include "extensions/common/extension_set.h"
|
| #include "extensions/common/feature_switch.h"
|
| +#include "extensions/common/manifest.h"
|
| #include "extensions/common/permissions/permissions_data.h"
|
| #include "ipc/ipc_message_macros.h"
|
|
|
| namespace extensions {
|
|
|
| +namespace {
|
| +
|
| +// Returns true if the extension should be regarded as a "permitted" extension
|
| +// for the case of metrics. We need this because we only actually withhold
|
| +// permissions if the switch is enabled, but want to record metrics in all
|
| +// cases.
|
| +// "ExtensionWouldHaveHadHostPermissionsWithheldIfSwitchWasOn()" would be
|
| +// more accurate, but too long.
|
| +bool ShouldRecordExtension(const Extension* extension) {
|
| + return extension->ShouldDisplayInExtensionSettings() &&
|
| + !Manifest::IsPolicyLocation(extension->location()) &&
|
| + !Manifest::IsComponentLocation(extension->location()) &&
|
| + !PermissionsData::CanExecuteScriptEverywhere(extension) &&
|
| + extension->permissions_data()
|
| + ->active_permissions()
|
| + ->ShouldWarnAllHosts();
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| ActiveScriptController::PendingRequest::PendingRequest() :
|
| page_id(-1) {
|
| }
|
| @@ -70,40 +91,6 @@ ActiveScriptController* ActiveScriptController::GetForWebContents(
|
| return location_bar_controller->active_script_controller();
|
| }
|
|
|
| -bool ActiveScriptController::RequiresUserConsentForScriptInjection(
|
| - const Extension* extension) {
|
| - CHECK(extension);
|
| - if (!extension->permissions_data()->RequiresActionForScriptExecution(
|
| - extension,
|
| - SessionID::IdForTab(web_contents()),
|
| - web_contents()->GetVisibleURL()) ||
|
| - util::AllowedScriptingOnAllUrls(extension->id(),
|
| - web_contents()->GetBrowserContext())) {
|
| - return false;
|
| - }
|
| -
|
| - // If the feature is not enabled, we automatically allow all extensions to
|
| - // run scripts.
|
| - if (!enabled_)
|
| - permitted_extensions_.insert(extension->id());
|
| -
|
| - return permitted_extensions_.count(extension->id()) == 0;
|
| -}
|
| -
|
| -void ActiveScriptController::RequestScriptInjection(
|
| - const Extension* extension,
|
| - int page_id,
|
| - const base::Closure& callback) {
|
| - CHECK(extension);
|
| - PendingRequestList& list = pending_requests_[extension->id()];
|
| - list.push_back(PendingRequest(callback, page_id));
|
| -
|
| - // If this was the first entry, notify the location bar that there's a new
|
| - // icon.
|
| - if (list.size() == 1u)
|
| - LocationBarController::NotifyChange(web_contents());
|
| -}
|
| -
|
| void ActiveScriptController::OnActiveTabPermissionGranted(
|
| const Extension* extension) {
|
| RunPendingForExtension(extension);
|
| @@ -174,13 +161,53 @@ void ActiveScriptController::OnExtensionUnloaded(const Extension* extension) {
|
| pending_requests_.erase(iter);
|
| }
|
|
|
| +PermissionsData::AccessType
|
| +ActiveScriptController::RequiresUserConsentForScriptInjection(
|
| + const Extension* extension,
|
| + UserScript::InjectionType type) {
|
| + CHECK(extension);
|
| +
|
| + // If the feature is not enabled, we automatically allow all extensions to
|
| + // run scripts.
|
| + if (!enabled_)
|
| + permitted_extensions_.insert(extension->id());
|
| +
|
| + // Allow the extension if it's been explicitly granted permission.
|
| + if (permitted_extensions_.count(extension->id()) > 0)
|
| + return PermissionsData::ACCESS_ALLOWED;
|
| +
|
| + GURL url = web_contents()->GetVisibleURL();
|
| + int tab_id = SessionID::IdForTab(web_contents());
|
| + switch (type) {
|
| + case UserScript::CONTENT_SCRIPT:
|
| + return extension->permissions_data()->GetContentScriptAccess(
|
| + extension, url, url, tab_id, -1, NULL);
|
| + case UserScript::PROGRAMMATIC_SCRIPT:
|
| + return extension->permissions_data()->GetPageAccess(
|
| + extension, url, url, tab_id, -1, NULL);
|
| + }
|
| +
|
| + NOTREACHED();
|
| + return PermissionsData::ACCESS_DENIED;
|
| +}
|
| +
|
| +void ActiveScriptController::RequestScriptInjection(
|
| + const Extension* extension,
|
| + int page_id,
|
| + const base::Closure& callback) {
|
| + CHECK(extension);
|
| + PendingRequestList& list = pending_requests_[extension->id()];
|
| + list.push_back(PendingRequest(callback, page_id));
|
| +
|
| + // If this was the first entry, notify the location bar that there's a new
|
| + // icon.
|
| + if (list.size() == 1u)
|
| + LocationBarController::NotifyChange(web_contents());
|
| +}
|
| +
|
| void ActiveScriptController::RunPendingForExtension(
|
| const Extension* extension) {
|
| DCHECK(extension);
|
| - PendingRequestMap::iterator iter =
|
| - pending_requests_.find(extension->id());
|
| - if (iter == pending_requests_.end())
|
| - return;
|
|
|
| content::NavigationEntry* visible_entry =
|
| web_contents()->GetController().GetVisibleEntry();
|
| @@ -195,6 +222,11 @@ void ActiveScriptController::RunPendingForExtension(
|
| // *before* running them to guard against the crazy case where running the
|
| // callbacks adds more entries.
|
| permitted_extensions_.insert(extension->id());
|
| +
|
| + PendingRequestMap::iterator iter = pending_requests_.find(extension->id());
|
| + if (iter == pending_requests_.end())
|
| + return;
|
| +
|
| PendingRequestList requests;
|
| iter->second.swap(requests);
|
| pending_requests_.erase(extension->id());
|
| @@ -221,6 +253,7 @@ void ActiveScriptController::RunPendingForExtension(
|
|
|
| void ActiveScriptController::OnRequestScriptInjectionPermission(
|
| const std::string& extension_id,
|
| + UserScript::InjectionType script_type,
|
| int page_id,
|
| int request_id) {
|
| if (!Extension::IdIsValid(extension_id)) {
|
| @@ -240,26 +273,38 @@ void ActiveScriptController::OnRequestScriptInjectionPermission(
|
| // ran (because this feature is not enabled). Add the extension to the list of
|
| // permitted extensions (for metrics), and return immediately.
|
| if (request_id == -1) {
|
| - DCHECK(!enabled_);
|
| - permitted_extensions_.insert(extension->id());
|
| + if (ShouldRecordExtension(extension)) {
|
| + DCHECK(!enabled_);
|
| + permitted_extensions_.insert(extension->id());
|
| + }
|
| return;
|
| }
|
|
|
| - if (RequiresUserConsentForScriptInjection(extension)) {
|
| - // This base::Unretained() is safe, because the callback is only invoked by
|
| - // this object.
|
| - RequestScriptInjection(
|
| - extension,
|
| - page_id,
|
| - base::Bind(&ActiveScriptController::PermitScriptInjection,
|
| - base::Unretained(this),
|
| - request_id));
|
| - } else {
|
| - PermitScriptInjection(request_id);
|
| + switch (RequiresUserConsentForScriptInjection(extension, script_type)) {
|
| + case PermissionsData::ACCESS_ALLOWED:
|
| + PermitScriptInjection(request_id);
|
| + break;
|
| + case PermissionsData::ACCESS_WITHHELD:
|
| + // This base::Unretained() is safe, because the callback is only invoked
|
| + // by this object.
|
| + RequestScriptInjection(
|
| + extension,
|
| + page_id,
|
| + base::Bind(&ActiveScriptController::PermitScriptInjection,
|
| + base::Unretained(this),
|
| + request_id));
|
| + break;
|
| + case PermissionsData::ACCESS_DENIED:
|
| + // We should usually only get a "deny access" if the page changed (as the
|
| + // renderer wouldn't have requested permission if the answer was always
|
| + // "no"). Just let the request fizzle and die.
|
| + break;
|
| }
|
| }
|
|
|
| void ActiveScriptController::PermitScriptInjection(int request_id) {
|
| + // This only sends the response to the renderer - the process of adding the
|
| + // extension to the list of |permitted_extensions_| is done elsewhere.
|
| content::RenderViewHost* render_view_host =
|
| web_contents()->GetRenderViewHost();
|
| if (render_view_host) {
|
|
|