Commit 699ca6ff authored by rdevlin.cronin's avatar rdevlin.cronin Committed by Commit bot

Introduce an "ExtensionWantsToAct" method

Add an ExtensionWantsToAct() method on ExtensionActionAPI.
Even though we're not quite sure what we want the UI to look
like for an extension desiring to act, we can start a little
bit of the plumbing now. For instance, exposing a method that
allows a caller to check if an extension wants to act on a
given page.

BUG=417441

Review URL: https://codereview.chromium.org/597413003

Cr-Commit-Position: refs/heads/master@{#297309}
parent 6b328f3d
......@@ -60,11 +60,11 @@ bool ShouldRecordExtension(const Extension* extension) {
ActiveScriptController::ActiveScriptController(
content::WebContents* web_contents)
: content::WebContentsObserver(web_contents),
browser_context_(web_contents->GetBrowserContext()),
enabled_(FeatureSwitch::scripts_require_action()->IsEnabled()),
extension_registry_observer_(this) {
CHECK(web_contents);
extension_registry_observer_.Add(
ExtensionRegistry::Get(web_contents->GetBrowserContext()));
extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
}
ActiveScriptController::~ActiveScriptController() {
......@@ -130,8 +130,8 @@ void ActiveScriptController::AlwaysRunOnVisibleOrigin(
// permissions and granted permissions.
// TODO(devlin): Make sure that the permission is removed from
// withheld_permissions if appropriate.
PermissionsUpdater(web_contents()->GetBrowserContext())
.AddPermissions(extension, new_permissions.get());
PermissionsUpdater(browser_context_).AddPermissions(extension,
new_permissions.get());
// Allow current tab to run injection.
OnClicked(extension);
......@@ -183,12 +183,10 @@ void ActiveScriptController::RequestScriptInjection(
PendingRequestList& list = pending_requests_[extension->id()];
list.push_back(callback);
// If this was the first entry, notify the location bar that there's a new
// icon.
if (list.size() == 1u) {
ExtensionActionAPI::Get(web_contents()->GetBrowserContext())->
NotifyPageActionsChanged(web_contents());
}
// If this was the first entry, we need to notify that a new extension wants
// to run.
if (list.size() == 1u)
NotifyChange(extension);
}
void ActiveScriptController::RunPendingForExtension(
......@@ -229,9 +227,9 @@ void ActiveScriptController::RunPendingForExtension(
request->Run();
}
// Inform the location bar that the action is now gone.
ExtensionActionAPI::Get(web_contents()->GetBrowserContext())->
NotifyPageActionsChanged(web_contents());
// The extension ran, so we need to update the ExtensionActionAPI that we no
// longer want to act.
NotifyChange(extension);
}
void ActiveScriptController::OnRequestScriptInjectionPermission(
......@@ -244,7 +242,7 @@ void ActiveScriptController::OnRequestScriptInjectionPermission(
}
const Extension* extension =
ExtensionRegistry::Get(web_contents()->GetBrowserContext())
ExtensionRegistry::Get(browser_context_)
->enabled_extensions().GetByID(extension_id);
// We shouldn't allow extensions which are no longer enabled to run any
// scripts. Ignore the request.
......@@ -294,6 +292,22 @@ void ActiveScriptController::PermitScriptInjection(int64 request_id) {
}
}
void ActiveScriptController::NotifyChange(const Extension* extension) {
ExtensionActionAPI* extension_action_api =
ExtensionActionAPI::Get(browser_context_);
ExtensionAction* extension_action =
ExtensionActionManager::Get(browser_context_)->
GetExtensionAction(*extension);
// If the extension has an action, we need to notify that it's updated.
if (extension_action) {
extension_action_api->NotifyChange(
extension_action, web_contents(), browser_context_);
}
// We also notify that page actions may have changed.
extension_action_api->NotifyPageActionsChanged(web_contents());
}
void ActiveScriptController::LogUMA() const {
UMA_HISTOGRAM_COUNTS_100(
"Extensions.ActiveScriptController.ShownActiveScriptsOnPage",
......@@ -339,7 +353,7 @@ void ActiveScriptController::OnExtensionUnloaded(
PendingRequestMap::iterator iter = pending_requests_.find(extension->id());
if (iter != pending_requests_.end()) {
pending_requests_.erase(iter);
ExtensionActionAPI::Get(web_contents()->GetBrowserContext())->
ExtensionActionAPI::Get(browser_context_)->
NotifyPageActionsChanged(web_contents());
}
}
......
......@@ -19,6 +19,7 @@
#include "extensions/common/user_script.h"
namespace content {
class BrowserContext;
class WebContents;
}
......@@ -108,6 +109,10 @@ class ActiveScriptController : public content::WebContentsObserver,
// 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;
......@@ -123,6 +128,9 @@ class ActiveScriptController : public content::WebContentsObserver,
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.
......
......@@ -7,6 +7,7 @@
#include "base/values.h"
#include "chrome/browser/extensions/active_script_controller.h"
#include "chrome/browser/extensions/active_tab_permission_granter.h"
#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/permissions_updater.h"
#include "chrome/browser/extensions/tab_helper.h"
......@@ -182,6 +183,11 @@ TEST_F(ActiveScriptControllerUnitTest, RequestPermissionAndExecute) {
ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id()));
ASSERT_FALSE(controller()->WantsToRun(extension));
ExtensionActionAPI* extension_action_api =
ExtensionActionAPI::Get(profile());
ASSERT_FALSE(extension_action_api->ExtensionWantsToRun(extension,
web_contents()));
// Since the extension requests all_hosts, we should require user consent.
EXPECT_TRUE(RequiresUserConsent(extension));
......@@ -189,6 +195,8 @@ TEST_F(ActiveScriptControllerUnitTest, RequestPermissionAndExecute) {
// executed.
RequestInjection(extension);
EXPECT_TRUE(controller()->WantsToRun(extension));
EXPECT_TRUE(extension_action_api->ExtensionWantsToRun(extension,
web_contents()));
EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));
// Click to accept the extension executing.
......@@ -197,6 +205,8 @@ TEST_F(ActiveScriptControllerUnitTest, RequestPermissionAndExecute) {
// The extension should execute, and the extension shouldn't want to run.
EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id()));
EXPECT_FALSE(controller()->WantsToRun(extension));
EXPECT_FALSE(extension_action_api->ExtensionWantsToRun(extension,
web_contents()));
// Since we already executed on the given page, we shouldn't need permission
// for a second time.
......
......@@ -230,6 +230,26 @@ bool ExtensionActionAPI::ShowExtensionActionPopup(
}
}
bool ExtensionActionAPI::ExtensionWantsToRun(
const Extension* extension, content::WebContents* web_contents) {
// An extension wants to act if it has a visible page action on the given
// page...
ExtensionAction* page_action =
ExtensionActionManager::Get(browser_context_)->GetPageAction(*extension);
if (page_action &&
page_action->GetIsVisible(SessionTabHelper::IdForTab(web_contents)))
return true;
// ... Or if it has pending scripts that need approval for execution.
ActiveScriptController* active_script_controller =
ActiveScriptController::GetForWebContents(web_contents);
if (active_script_controller &&
active_script_controller->WantsToRun(extension))
return true;
return false;
}
void ExtensionActionAPI::NotifyChange(ExtensionAction* extension_action,
content::WebContents* web_contents,
content::BrowserContext* context) {
......@@ -255,9 +275,7 @@ void ExtensionActionAPI::ClearAllValuesForTab(
for (ExtensionSet::const_iterator iter = enabled_extensions.begin();
iter != enabled_extensions.end(); ++iter) {
ExtensionAction* extension_action =
action_manager->GetBrowserAction(*iter->get());
if (!extension_action)
extension_action = action_manager->GetPageAction(*iter->get());
action_manager->GetExtensionAction(**iter);
if (extension_action) {
extension_action->ClearAllValuesForTab(tab_id);
NotifyChange(extension_action, web_contents, browser_context);
......
......@@ -91,6 +91,11 @@ class ExtensionActionAPI : public BrowserContextKeyedAPI {
Browser* browser,
bool grant_active_tab_permissions);
// Returns true if the given |extension| wants to run on the tab pointed to
// by |web_contents|.
bool ExtensionWantsToRun(const Extension* extension,
content::WebContents* web_contents);
// Notifies that there has been a change in the given |extension_action|.
void NotifyChange(ExtensionAction* extension_action,
content::WebContents* web_contents,
......
......@@ -8,6 +8,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/extensions/active_script_controller.h"
#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_service.h"
......@@ -159,6 +160,17 @@ TEST_F(LocationBarControllerUnitTest, NavigationClearsState) {
page_action.SetTitle(tab_id(), "Goodbye");
page_action.SetPopupUrl(tab_id(), extension->GetResourceURL("popup.html"));
ExtensionActionAPI* extension_action_api =
ExtensionActionAPI::Get(profile());
// By default, extensions shouldn't want to act on a page.
EXPECT_FALSE(extension_action_api->ExtensionWantsToRun(extension,
web_contents()));
// Showing the page action should indicate that an extension *does* want to
// run on the page.
page_action.SetIsVisible(tab_id(), true);
EXPECT_TRUE(extension_action_api->ExtensionWantsToRun(extension,
web_contents()));
EXPECT_EQ("Goodbye", page_action.GetTitle(tab_id()));
EXPECT_EQ(extension->GetResourceURL("popup.html"),
page_action.GetPopupUrl(tab_id()));
......@@ -169,12 +181,16 @@ TEST_F(LocationBarControllerUnitTest, NavigationClearsState) {
EXPECT_EQ("Goodbye", page_action.GetTitle(tab_id()));
EXPECT_EQ(extension->GetResourceURL("popup.html"),
page_action.GetPopupUrl(tab_id()));
EXPECT_TRUE(extension_action_api->ExtensionWantsToRun(extension,
web_contents()));
// Should discard the settings, and go back to the defaults.
NavigateAndCommit(GURL("http://www.yahoo.com"));
EXPECT_EQ("Hello", page_action.GetTitle(tab_id()));
EXPECT_EQ(GURL(), page_action.GetPopupUrl(tab_id()));
EXPECT_FALSE(extension_action_api->ExtensionWantsToRun(extension,
web_contents()));
}
} // namespace
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment