Commit 91f162a1 authored by rdevlin.cronin's avatar rdevlin.cronin Committed by Commit bot

Uncouple ActiveScriptController from LocationBarController

Since the indication of an active script running won't always be tied to the
location bar, it doesn't make sense for ActiveScriptController to be owned by
LocationBarController.

Since the "generated" actions were also only used for display
in the location bar, move that logic to the LocationBarController.

And, since we're there, also add a bit more testing for LocationBarController.

BUG=408676
TBR=avi@chromium.org (for method name change in cocoa)

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

Cr-Commit-Position: refs/heads/master@{#293153}
parent 3bd985e9
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "chrome/browser/extensions/extension_action.h" #include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h" #include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/location_bar_controller.h"
#include "chrome/browser/extensions/permissions_updater.h" #include "chrome/browser/extensions/permissions_updater.h"
#include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
...@@ -78,13 +77,7 @@ ActiveScriptController* ActiveScriptController::GetForWebContents( ...@@ -78,13 +77,7 @@ ActiveScriptController* ActiveScriptController::GetForWebContents(
if (!web_contents) if (!web_contents)
return NULL; return NULL;
TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); TabHelper* tab_helper = TabHelper::FromWebContents(web_contents);
if (!tab_helper) return tab_helper ? tab_helper->active_script_controller() : NULL;
return NULL;
LocationBarController* location_bar_controller =
tab_helper->location_bar_controller();
// This should never be NULL.
DCHECK(location_bar_controller);
return location_bar_controller->active_script_controller();
} }
void ActiveScriptController::OnActiveTabPermissionGranted( void ActiveScriptController::OnActiveTabPermissionGranted(
...@@ -149,29 +142,10 @@ void ActiveScriptController::OnClicked(const Extension* extension) { ...@@ -149,29 +142,10 @@ void ActiveScriptController::OnClicked(const Extension* extension) {
RunPendingForExtension(extension); RunPendingForExtension(extension);
} }
bool ActiveScriptController::HasActiveScriptAction(const Extension* extension) { bool ActiveScriptController::WantsToRun(const Extension* extension) {
return enabled_ && pending_requests_.count(extension->id()) > 0; return enabled_ && pending_requests_.count(extension->id()) > 0;
} }
ExtensionAction* ActiveScriptController::GetActionForExtension(
const Extension* extension) {
if (!enabled_ || pending_requests_.count(extension->id()) == 0)
return NULL; // No action for this extension.
ActiveScriptMap::iterator existing =
active_script_actions_.find(extension->id());
if (existing != active_script_actions_.end())
return existing->second.get();
linked_ptr<ExtensionAction> action(ExtensionActionManager::Get(
Profile::FromBrowserContext(web_contents()->GetBrowserContext()))
->GetBestFitAction(*extension, ActionInfo::TYPE_PAGE).release());
action->SetIsVisible(ExtensionAction::kDefaultTabId, true);
active_script_actions_[extension->id()] = action;
return action.get();
}
PermissionsData::AccessType PermissionsData::AccessType
ActiveScriptController::RequiresUserConsentForScriptInjection( ActiveScriptController::RequiresUserConsentForScriptInjection(
const Extension* extension, const Extension* extension,
......
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/memory/linked_ptr.h" #include "base/scoped_observer.h"
#include "chrome/browser/extensions/location_bar_controller.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "extensions/browser/extension_registry_observer.h" #include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/permissions/permissions_data.h" #include "extensions/common/permissions/permissions_data.h"
...@@ -64,12 +63,9 @@ class ActiveScriptController : public content::WebContentsObserver, ...@@ -64,12 +63,9 @@ class ActiveScriptController : public content::WebContentsObserver,
// been clicked, running any pending tasks that were previously shelved. // been clicked, running any pending tasks that were previously shelved.
void OnClicked(const Extension* extension); void OnClicked(const Extension* extension);
// Returns true if there is an active script injection action for |extension|. // Returns true if the given |extension| has a pending script that wants to
bool HasActiveScriptAction(const Extension* extension); // run.
bool WantsToRun(const Extension* extension);
// Returns the action to display for the given |extension|, or NULL if no
// action should be displayed.
ExtensionAction* GetActionForExtension(const Extension* extension);
#if defined(UNIT_TEST) #if defined(UNIT_TEST)
// Only used in tests. // Only used in tests.
...@@ -141,12 +137,6 @@ class ActiveScriptController : public content::WebContentsObserver, ...@@ -141,12 +137,6 @@ class ActiveScriptController : public content::WebContentsObserver,
// should incorporate more fully with ActiveTab. // should incorporate more fully with ActiveTab.
std::set<std::string> permitted_extensions_; std::set<std::string> permitted_extensions_;
// Script badges that have been generated for extensions. This is both those
// with actions already declared that are copied and normalised, and actions
// that get generated for extensions that haven't declared anything.
typedef std::map<std::string, linked_ptr<ExtensionAction> > ActiveScriptMap;
ActiveScriptMap active_script_actions_;
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_; extension_registry_observer_;
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "chrome/browser/extensions/extension_action.h" #include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_test_message_listener.h" #include "chrome/browser/extensions/extension_test_message_listener.h"
#include "chrome/browser/extensions/location_bar_controller.h"
#include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/extensions/test_extension_dir.h" #include "chrome/browser/extensions/test_extension_dir.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
...@@ -171,14 +170,12 @@ class ActiveScriptTester { ...@@ -171,14 +170,12 @@ class ActiveScriptTester {
testing::AssertionResult Verify(); testing::AssertionResult Verify();
private: private:
// Returns the location bar controller, or NULL if one does not exist.
LocationBarController* GetLocationBarController();
// Returns the active script controller, or NULL if one does not exist. // Returns the active script controller, or NULL if one does not exist.
ActiveScriptController* GetActiveScriptController(); ActiveScriptController* GetActiveScriptController();
// Get the ExtensionAction for this extension, or NULL if one does not exist. // Returns true if the extension has a pending request with the active script
ExtensionAction* GetAction(); // controller.
bool WantsToRun();
// The name of the extension, and also the message it sends. // The name of the extension, and also the message it sends.
std::string name_; std::string name_;
...@@ -237,26 +234,19 @@ testing::AssertionResult ActiveScriptTester::Verify() { ...@@ -237,26 +234,19 @@ testing::AssertionResult ActiveScriptTester::Verify() {
// Make sure all running tasks are complete. // Make sure all running tasks are complete.
content::RunAllPendingInMessageLoop(); content::RunAllPendingInMessageLoop();
LocationBarController* location_bar_controller = GetLocationBarController(); ActiveScriptController* controller = GetActiveScriptController();
if (!location_bar_controller) {
return testing::AssertionFailure()
<< "Could not find location bar controller";
}
ActiveScriptController* controller =
location_bar_controller->active_script_controller();
if (!controller) if (!controller)
return testing::AssertionFailure() << "Could not find controller."; return testing::AssertionFailure() << "Could not find controller.";
ExtensionAction* action = GetAction(); bool wants_to_run = WantsToRun();
bool has_action = action != NULL;
// An extension should have an action displayed iff it requires user consent. // An extension should have an action displayed iff it requires user consent.
if ((requires_consent_ == REQUIRES_CONSENT && !has_action) || if ((requires_consent_ == REQUIRES_CONSENT && !wants_to_run) ||
(requires_consent_ == DOES_NOT_REQUIRE_CONSENT && has_action)) { (requires_consent_ == DOES_NOT_REQUIRE_CONSENT && wants_to_run)) {
return testing::AssertionFailure() return testing::AssertionFailure()
<< "Improper action status for " << name_ << ": expected " << "Improper wants to run for " << name_ << ": expected "
<< (requires_consent_ == REQUIRES_CONSENT) << ", found " << has_action; << (requires_consent_ == REQUIRES_CONSENT) << ", found "
<< wants_to_run;
} }
// If the extension has permission, we should be able to simply wait for it // If the extension has permission, we should be able to simply wait for it
...@@ -273,8 +263,8 @@ testing::AssertionResult ActiveScriptTester::Verify() { ...@@ -273,8 +263,8 @@ testing::AssertionResult ActiveScriptTester::Verify() {
name_ << "'s script ran without permission."; name_ << "'s script ran without permission.";
} }
// If we reach this point, we should always have an action. // If we reach this point, we should always want to run.
DCHECK(action); DCHECK(wants_to_run);
// Grant permission by clicking on the extension action. // Grant permission by clicking on the extension action.
controller->OnClicked(extension_); controller->OnClicked(extension_);
...@@ -282,17 +272,17 @@ testing::AssertionResult ActiveScriptTester::Verify() { ...@@ -282,17 +272,17 @@ testing::AssertionResult ActiveScriptTester::Verify() {
// Now, the extension should be able to inject the script. // Now, the extension should be able to inject the script.
inject_success_listener_->WaitUntilSatisfied(); inject_success_listener_->WaitUntilSatisfied();
// The Action should have disappeared. // The extension should no longer want to run.
has_action = GetAction() != NULL; wants_to_run = WantsToRun();
if (has_action) { if (wants_to_run) {
return testing::AssertionFailure() return testing::AssertionFailure()
<< "Extension " << name_ << " has lingering action."; << "Extension " << name_ << " still wants to run after injecting.";
} }
return testing::AssertionSuccess(); return testing::AssertionSuccess();
} }
LocationBarController* ActiveScriptTester::GetLocationBarController() { ActiveScriptController* ActiveScriptTester::GetActiveScriptController() {
content::WebContents* web_contents = content::WebContents* web_contents =
browser_ ? browser_->tab_strip_model()->GetActiveWebContents() : NULL; browser_ ? browser_->tab_strip_model()->GetActiveWebContents() : NULL;
...@@ -300,18 +290,12 @@ LocationBarController* ActiveScriptTester::GetLocationBarController() { ...@@ -300,18 +290,12 @@ LocationBarController* ActiveScriptTester::GetLocationBarController() {
return NULL; return NULL;
TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); TabHelper* tab_helper = TabHelper::FromWebContents(web_contents);
return tab_helper ? tab_helper->location_bar_controller() : NULL; return tab_helper ? tab_helper->active_script_controller() : NULL;
}
ActiveScriptController* ActiveScriptTester::GetActiveScriptController() {
LocationBarController* location_bar_controller = GetLocationBarController();
return location_bar_controller ?
location_bar_controller->active_script_controller() : NULL;
} }
ExtensionAction* ActiveScriptTester::GetAction() { bool ActiveScriptTester::WantsToRun() {
ActiveScriptController* controller = GetActiveScriptController(); ActiveScriptController* controller = GetActiveScriptController();
return controller ? controller->GetActionForExtension(extension_) : NULL; return controller ? controller->WantsToRun(extension_) : false;
} }
IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest, IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest,
...@@ -396,8 +380,8 @@ IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest, ...@@ -396,8 +380,8 @@ IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest,
browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); browser(), embedded_test_server()->GetURL("/extensions/test_file.html"));
// Both extensions should have pending requests. // Both extensions should have pending requests.
EXPECT_TRUE(active_script_controller->GetActionForExtension(extension1)); EXPECT_TRUE(active_script_controller->WantsToRun(extension1));
EXPECT_TRUE(active_script_controller->GetActionForExtension(extension2)); EXPECT_TRUE(active_script_controller->WantsToRun(extension2));
// Unload one of the extensions. // Unload one of the extensions.
UnloadExtension(extension2->id()); UnloadExtension(extension2->id());
...@@ -406,8 +390,8 @@ IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest, ...@@ -406,8 +390,8 @@ IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest,
// We should have pending requests for extension1, but not the removed // We should have pending requests for extension1, but not the removed
// extension2. // extension2.
EXPECT_TRUE(active_script_controller->GetActionForExtension(extension1)); EXPECT_TRUE(active_script_controller->WantsToRun(extension1));
EXPECT_FALSE(active_script_controller->GetActionForExtension(extension2)); EXPECT_FALSE(active_script_controller->WantsToRun(extension2));
// We should still be able to run the request for extension1. // We should still be able to run the request for extension1.
ExtensionTestMessageListener inject_success_listener( ExtensionTestMessageListener inject_success_listener(
......
...@@ -164,11 +164,9 @@ void ActiveScriptControllerUnitTest::SetUp() { ...@@ -164,11 +164,9 @@ void ActiveScriptControllerUnitTest::SetUp() {
TabHelper::CreateForWebContents(web_contents()); TabHelper::CreateForWebContents(web_contents());
TabHelper* tab_helper = TabHelper::FromWebContents(web_contents()); TabHelper* tab_helper = TabHelper::FromWebContents(web_contents());
// None of these should ever be NULL. // These should never be NULL.
DCHECK(tab_helper); DCHECK(tab_helper);
DCHECK(tab_helper->location_bar_controller()); active_script_controller_ = tab_helper->active_script_controller();
active_script_controller_ =
tab_helper->location_bar_controller()->active_script_controller();
DCHECK(active_script_controller_); DCHECK(active_script_controller_);
} }
...@@ -182,22 +180,23 @@ TEST_F(ActiveScriptControllerUnitTest, RequestPermissionAndExecute) { ...@@ -182,22 +180,23 @@ TEST_F(ActiveScriptControllerUnitTest, RequestPermissionAndExecute) {
// Ensure that there aren't any executions pending. // Ensure that there aren't any executions pending.
ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id())); ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id()));
ASSERT_FALSE(controller()->GetActionForExtension(extension)); ASSERT_FALSE(controller()->WantsToRun(extension));
// Since the extension requests all_hosts, we should require user consent. // Since the extension requests all_hosts, we should require user consent.
EXPECT_TRUE(RequiresUserConsent(extension)); EXPECT_TRUE(RequiresUserConsent(extension));
// Request an injection. There should be an action visible, but no executions. // Request an injection. The extension should want to run, but should not have
// executed.
RequestInjection(extension); RequestInjection(extension);
EXPECT_TRUE(controller()->GetActionForExtension(extension)); EXPECT_TRUE(controller()->WantsToRun(extension));
EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));
// Click to accept the extension executing. // Click to accept the extension executing.
controller()->OnClicked(extension); controller()->OnClicked(extension);
// The extension should execute, and the action should go away. // The extension should execute, and the extension shouldn't want to run.
EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id()));
EXPECT_FALSE(controller()->GetActionForExtension(extension)); EXPECT_FALSE(controller()->WantsToRun(extension));
// Since we already executed on the given page, we shouldn't need permission // Since we already executed on the given page, we shouldn't need permission
// for a second time. // for a second time.
...@@ -220,7 +219,7 @@ TEST_F(ActiveScriptControllerUnitTest, RequestPermissionAndExecute) { ...@@ -220,7 +219,7 @@ TEST_F(ActiveScriptControllerUnitTest, RequestPermissionAndExecute) {
RequestInjection(extension); RequestInjection(extension);
controller()->OnClicked(extension); controller()->OnClicked(extension);
EXPECT_EQ(2u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(2u, GetExecutionCountForExtension(extension->id()));
EXPECT_FALSE(controller()->GetActionForExtension(extension)); EXPECT_FALSE(controller()->WantsToRun(extension));
// Navigating to another site should also clear the permissions. // Navigating to another site should also clear the permissions.
NavigateAndCommit(GURL("https://www.foo.com")); NavigateAndCommit(GURL("https://www.foo.com"));
...@@ -237,15 +236,15 @@ TEST_F(ActiveScriptControllerUnitTest, PendingInjectionsRemovedAtNavigation) { ...@@ -237,15 +236,15 @@ TEST_F(ActiveScriptControllerUnitTest, PendingInjectionsRemovedAtNavigation) {
ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id())); ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id()));
// Request an injection. There should be an action visible, but no executions. // Request an injection. The extension should want to run, but not execute.
RequestInjection(extension); RequestInjection(extension);
EXPECT_TRUE(controller()->GetActionForExtension(extension)); EXPECT_TRUE(controller()->WantsToRun(extension));
EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));
// Reload. This should remove the pending injection, and we should not // Reload. This should remove the pending injection, and we should not
// execute anything. // execute anything.
Reload(); Reload();
EXPECT_FALSE(controller()->GetActionForExtension(extension)); EXPECT_FALSE(controller()->WantsToRun(extension));
EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));
// Request and accept a new injection. // Request and accept a new injection.
...@@ -255,7 +254,7 @@ TEST_F(ActiveScriptControllerUnitTest, PendingInjectionsRemovedAtNavigation) { ...@@ -255,7 +254,7 @@ TEST_F(ActiveScriptControllerUnitTest, PendingInjectionsRemovedAtNavigation) {
// The extension should only have executed once, even though a grand total // The extension should only have executed once, even though a grand total
// of two executions were requested. // of two executions were requested.
EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id()));
EXPECT_FALSE(controller()->GetActionForExtension(extension)); EXPECT_FALSE(controller()->WantsToRun(extension));
} }
// Test that queueing multiple pending injections, and then accepting, triggers // Test that queueing multiple pending injections, and then accepting, triggers
...@@ -278,7 +277,7 @@ TEST_F(ActiveScriptControllerUnitTest, MultiplePendingInjection) { ...@@ -278,7 +277,7 @@ TEST_F(ActiveScriptControllerUnitTest, MultiplePendingInjection) {
// All pending injections should have executed. // All pending injections should have executed.
EXPECT_EQ(kNumInjections, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(kNumInjections, GetExecutionCountForExtension(extension->id()));
EXPECT_FALSE(controller()->GetActionForExtension(extension)); EXPECT_FALSE(controller()->WantsToRun(extension));
} }
TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsUseActiveTabPermissions) { TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsUseActiveTabPermissions) {
...@@ -315,7 +314,7 @@ TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsUseActiveTabPermissions) { ...@@ -315,7 +314,7 @@ TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsUseActiveTabPermissions) {
EXPECT_TRUE(RequiresUserConsent(extension)); EXPECT_TRUE(RequiresUserConsent(extension));
RequestInjection(extension); RequestInjection(extension);
EXPECT_TRUE(controller()->GetActionForExtension(extension)); EXPECT_TRUE(controller()->WantsToRun(extension));
EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));
// Grant active tab. // Grant active tab.
...@@ -324,7 +323,7 @@ TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsUseActiveTabPermissions) { ...@@ -324,7 +323,7 @@ TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsUseActiveTabPermissions) {
// The pending injections should have run since active tab permission was // The pending injections should have run since active tab permission was
// granted. // granted.
EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id()));
EXPECT_FALSE(controller()->GetActionForExtension(extension)); EXPECT_FALSE(controller()->WantsToRun(extension));
} }
TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsCanHaveAllUrlsPref) { TEST_F(ActiveScriptControllerUnitTest, ActiveScriptsCanHaveAllUrlsPref) {
...@@ -359,22 +358,22 @@ TEST_F(ActiveScriptControllerUnitTest, TestAlwaysRun) { ...@@ -359,22 +358,22 @@ TEST_F(ActiveScriptControllerUnitTest, TestAlwaysRun) {
// Ensure that there aren't any executions pending. // Ensure that there aren't any executions pending.
ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id())); ASSERT_EQ(0u, GetExecutionCountForExtension(extension->id()));
ASSERT_FALSE(controller()->GetActionForExtension(extension)); ASSERT_FALSE(controller()->WantsToRun(extension));
// Since the extension requests all_hosts, we should require user consent. // Since the extension requests all_hosts, we should require user consent.
EXPECT_TRUE(RequiresUserConsent(extension)); EXPECT_TRUE(RequiresUserConsent(extension));
// Request an injection. There should be an action visible, but no executions. // Request an injection. The extension should want to run, but not execute.
RequestInjection(extension); RequestInjection(extension);
EXPECT_TRUE(controller()->GetActionForExtension(extension)); EXPECT_TRUE(controller()->WantsToRun(extension));
EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(0u, GetExecutionCountForExtension(extension->id()));
// Allow the extension to always run on this origin. // Allow the extension to always run on this origin.
controller()->AlwaysRunOnVisibleOrigin(extension); controller()->AlwaysRunOnVisibleOrigin(extension);
// The extension should execute, and the action should go away. // The extension should execute, and the extension shouldn't want to run.
EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id())); EXPECT_EQ(1u, GetExecutionCountForExtension(extension->id()));
EXPECT_FALSE(controller()->GetActionForExtension(extension)); EXPECT_FALSE(controller()->WantsToRun(extension));
// Since we already executed on the given page, we shouldn't need permission // Since we already executed on the given page, we shouldn't need permission
// for a second time. // for a second time.
......
...@@ -175,7 +175,7 @@ ExtensionAction::ShowAction ExtensionActionAPI::ExecuteExtensionAction( ...@@ -175,7 +175,7 @@ ExtensionAction::ShowAction ExtensionActionAPI::ExecuteExtensionAction(
ActiveScriptController::GetForWebContents(web_contents); ActiveScriptController::GetForWebContents(web_contents);
bool has_pending_scripts = false; bool has_pending_scripts = false;
if (active_script_controller && if (active_script_controller &&
active_script_controller->GetActionForExtension(extension)) { active_script_controller->WantsToRun(extension)) {
has_pending_scripts = true; has_pending_scripts = true;
} }
......
...@@ -283,7 +283,7 @@ void ExtensionContextMenuModel::InitMenu(const Extension* extension) { ...@@ -283,7 +283,7 @@ void ExtensionContextMenuModel::InitMenu(const Extension* extension) {
WebContents* web_contents = GetActiveWebContents(); WebContents* web_contents = GetActiveWebContents();
if (web_contents && if (web_contents &&
extensions::ActiveScriptController::GetForWebContents(web_contents) extensions::ActiveScriptController::GetForWebContents(web_contents)
->HasActiveScriptAction(extension)) { ->WantsToRun(extension)) {
AddItemWithStringId(ALWAYS_RUN, IDS_EXTENSIONS_ALWAYS_RUN); AddItemWithStringId(ALWAYS_RUN, IDS_EXTENSIONS_ALWAYS_RUN);
} }
......
...@@ -20,7 +20,6 @@ LocationBarController::LocationBarController( ...@@ -20,7 +20,6 @@ LocationBarController::LocationBarController(
action_manager_(ExtensionActionManager::Get(browser_context_)), action_manager_(ExtensionActionManager::Get(browser_context_)),
should_show_page_actions_( should_show_page_actions_(
!FeatureSwitch::extension_action_redesign()->IsEnabled()), !FeatureSwitch::extension_action_redesign()->IsEnabled()),
active_script_controller_(new ActiveScriptController(web_contents_)),
extension_registry_observer_(this) { extension_registry_observer_(this) {
if (should_show_page_actions_) if (should_show_page_actions_)
extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
...@@ -36,6 +35,8 @@ std::vector<ExtensionAction*> LocationBarController::GetCurrentActions() { ...@@ -36,6 +35,8 @@ std::vector<ExtensionAction*> LocationBarController::GetCurrentActions() {
if (!should_show_page_actions_) if (!should_show_page_actions_)
return current_actions; return current_actions;
ActiveScriptController* active_script_controller =
ActiveScriptController::GetForWebContents(web_contents_);
for (ExtensionSet::const_iterator iter = extensions.begin(); for (ExtensionSet::const_iterator iter = extensions.begin();
iter != extensions.end(); iter != extensions.end();
++iter) { ++iter) {
...@@ -43,8 +44,22 @@ std::vector<ExtensionAction*> LocationBarController::GetCurrentActions() { ...@@ -43,8 +44,22 @@ std::vector<ExtensionAction*> LocationBarController::GetCurrentActions() {
// one action per extension. If clicking on an active script action ever // one action per extension. If clicking on an active script action ever
// has a response, then we will need to split the actions. // has a response, then we will need to split the actions.
ExtensionAction* action = action_manager_->GetPageAction(**iter); ExtensionAction* action = action_manager_->GetPageAction(**iter);
if (!action) if (!action && active_script_controller->WantsToRun(*iter)) {
action = active_script_controller_->GetActionForExtension(iter->get()); ExtensionActionMap::iterator existing =
active_script_actions_.find((*iter)->id());
if (existing != active_script_actions_.end()) {
action = existing->second.get();
} else {
linked_ptr<ExtensionAction> active_script_action(
ExtensionActionManager::Get(browser_context_)->
GetBestFitAction(**iter, ActionInfo::TYPE_PAGE).release());
active_script_action->SetIsVisible(
ExtensionAction::kDefaultTabId, true);
active_script_actions_[(*iter)->id()] = active_script_action;
action = active_script_action.get();
}
}
if (action) if (action)
current_actions.push_back(action); current_actions.push_back(action);
} }
...@@ -55,8 +70,7 @@ std::vector<ExtensionAction*> LocationBarController::GetCurrentActions() { ...@@ -55,8 +70,7 @@ std::vector<ExtensionAction*> LocationBarController::GetCurrentActions() {
void LocationBarController::OnExtensionLoaded( void LocationBarController::OnExtensionLoaded(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
const Extension* extension) { const Extension* extension) {
if (action_manager_->GetPageAction(*extension) || if (action_manager_->GetPageAction(*extension)) {
active_script_controller_->GetActionForExtension(extension)) {
ExtensionActionAPI::Get(browser_context)-> ExtensionActionAPI::Get(browser_context)->
NotifyPageActionsChanged(web_contents_); NotifyPageActionsChanged(web_contents_);
} }
......
...@@ -5,10 +5,11 @@ ...@@ -5,10 +5,11 @@
#ifndef CHROME_BROWSER_EXTENSIONS_LOCATION_BAR_CONTROLLER_H_ #ifndef CHROME_BROWSER_EXTENSIONS_LOCATION_BAR_CONTROLLER_H_
#define CHROME_BROWSER_EXTENSIONS_LOCATION_BAR_CONTROLLER_H_ #define CHROME_BROWSER_EXTENSIONS_LOCATION_BAR_CONTROLLER_H_
#include <map>
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/linked_ptr.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "extensions/browser/extension_registry_observer.h" #include "extensions/browser/extension_registry_observer.h"
...@@ -20,8 +21,6 @@ class BrowserContext; ...@@ -20,8 +21,6 @@ class BrowserContext;
} }
namespace extensions { namespace extensions {
class ActiveScriptController;
class Extension; class Extension;
class ExtensionActionManager; class ExtensionActionManager;
class ExtensionRegistry; class ExtensionRegistry;
...@@ -36,15 +35,11 @@ class LocationBarController : public ExtensionRegistryObserver { ...@@ -36,15 +35,11 @@ class LocationBarController : public ExtensionRegistryObserver {
// Returns the actions which should be displayed in the location bar. // Returns the actions which should be displayed in the location bar.
std::vector<ExtensionAction*> GetCurrentActions(); std::vector<ExtensionAction*> GetCurrentActions();
ActiveScriptController* active_script_controller() {
return active_script_controller_.get();
}
private: private:
// ExtensionRegistryObserver implementation. // ExtensionRegistryObserver implementation.
virtual void OnExtensionLoaded( virtual void OnExtensionLoaded(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
const Extension* extnesion) OVERRIDE; const Extension* extension) OVERRIDE;
virtual void OnExtensionUnloaded( virtual void OnExtensionUnloaded(
content::BrowserContext* browser_context, content::BrowserContext* browser_context,
const Extension* extension, const Extension* extension,
...@@ -63,9 +58,11 @@ class LocationBarController : public ExtensionRegistryObserver { ...@@ -63,9 +58,11 @@ class LocationBarController : public ExtensionRegistryObserver {
// false with the toolbar redesign enabled.) // false with the toolbar redesign enabled.)
bool should_show_page_actions_; bool should_show_page_actions_;
// The ActiveScriptController, which could also add actions for extensions if // Manufactured page actions that have been generated for extensions that want
// they have a pending script. // to run a script, but were blocked.
scoped_ptr<ActiveScriptController> active_script_controller_; typedef std::map<std::string, linked_ptr<ExtensionAction> >
ExtensionActionMap;
ExtensionActionMap active_script_actions_;
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_; extension_registry_observer_;
......
...@@ -7,16 +7,20 @@ ...@@ -7,16 +7,20 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "chrome/browser/extensions/active_script_controller.h"
#include "chrome/browser/extensions/extension_action.h" #include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h" #include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/location_bar_controller.h"
#include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "components/crx_file/id_util.h"
#include "extensions/common/extension.h" #include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h" #include "extensions/common/extension_builder.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/value_builder.h" #include "extensions/common/value_builder.h"
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
...@@ -31,6 +35,9 @@ namespace { ...@@ -31,6 +35,9 @@ namespace {
class LocationBarControllerUnitTest : public ChromeRenderViewHostTestHarness { class LocationBarControllerUnitTest : public ChromeRenderViewHostTestHarness {
protected: protected:
virtual void SetUp() OVERRIDE { virtual void SetUp() OVERRIDE {
active_script_override_.reset(new FeatureSwitch::ScopedOverride(
FeatureSwitch::scripts_require_action(), true));
ChromeRenderViewHostTestHarness::SetUp(); ChromeRenderViewHostTestHarness::SetUp();
#if defined OS_CHROMEOS #if defined OS_CHROMEOS
test_user_manager_.reset(new chromeos::ScopedTestUserManager()); test_user_manager_.reset(new chromeos::ScopedTestUserManager());
...@@ -57,6 +64,25 @@ class LocationBarControllerUnitTest : public ChromeRenderViewHostTestHarness { ...@@ -57,6 +64,25 @@ class LocationBarControllerUnitTest : public ChromeRenderViewHostTestHarness {
return SessionTabHelper::IdForTab(web_contents()); return SessionTabHelper::IdForTab(web_contents());
} }
const Extension* AddExtension(bool has_page_actions,
const std::string& name) {
DictionaryBuilder manifest;
manifest.Set("name", name)
.Set("version", "1.0.0")
.Set("manifest_version", 2)
.Set("permissions", ListBuilder().Append("tabs"));
if (has_page_actions) {
manifest.Set("page_action", DictionaryBuilder()
.Set("default_title", "Hello"));
}
scoped_refptr<const Extension> extension =
ExtensionBuilder().SetManifest(manifest.Pass())
.SetID(crx_file::id_util::GenerateId(name))
.Build();
extension_service_->AddExtension(extension.get());
return extension;
}
ExtensionService* extension_service_; ExtensionService* extension_service_;
private: private:
...@@ -65,30 +91,73 @@ class LocationBarControllerUnitTest : public ChromeRenderViewHostTestHarness { ...@@ -65,30 +91,73 @@ class LocationBarControllerUnitTest : public ChromeRenderViewHostTestHarness {
chromeos::ScopedTestCrosSettings test_cros_settings_; chromeos::ScopedTestCrosSettings test_cros_settings_;
scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_; scoped_ptr<chromeos::ScopedTestUserManager> test_user_manager_;
#endif #endif
// Since we also test that we show page actions for pending script requests,
// we need to enable that feature.
scoped_ptr<FeatureSwitch::ScopedOverride> active_script_override_;
}; };
// Test that the location bar gets the proper current actions.
TEST_F(LocationBarControllerUnitTest, LocationBarDisplaysPageActions) {
// Load up two extensions, one with a page action and one without.
const Extension* page_action = AddExtension(true, "page_actions");
const Extension* no_action = AddExtension(false, "no_actions");
TabHelper* tab_helper = TabHelper::FromWebContents(web_contents());
ASSERT_TRUE(tab_helper);
LocationBarController* controller = tab_helper->location_bar_controller();
ASSERT_TRUE(controller);
// There should only be one action - the action for the extension with a
// page action.
std::vector<ExtensionAction*> current_actions =
controller->GetCurrentActions();
ASSERT_EQ(1u, current_actions.size());
EXPECT_EQ(page_action->id(), current_actions[0]->extension_id());
// If we request a script injection, then the location bar controller should
// also show a page action for that extension.
ActiveScriptController* active_script_controller =
ActiveScriptController::GetForWebContents(web_contents());
ASSERT_TRUE(active_script_controller);
active_script_controller->RequestScriptInjectionForTesting(no_action,
base::Closure());
current_actions = controller->GetCurrentActions();
ASSERT_EQ(2u, current_actions.size());
// Check that each extension is present in the vector.
EXPECT_TRUE(current_actions[0]->extension_id() == no_action->id() ||
current_actions[1]->extension_id() == no_action->id());
EXPECT_TRUE(current_actions[0]->extension_id() == page_action->id() ||
current_actions[1]->extension_id() == page_action->id());
// If we request a script injection for an extension that already has a
// page action, only one action should be visible.
active_script_controller->RequestScriptInjectionForTesting(page_action,
base::Closure());
current_actions = controller->GetCurrentActions();
ASSERT_EQ(2u, current_actions.size());
EXPECT_TRUE(current_actions[0]->extension_id() == no_action->id() ||
current_actions[1]->extension_id() == no_action->id());
EXPECT_TRUE(current_actions[0]->extension_id() == page_action->id() ||
current_actions[1]->extension_id() == page_action->id());
// Navigating away means that only page actions are shown again.
NavigateAndCommit(GURL("http://google.com"));
current_actions = controller->GetCurrentActions();
ASSERT_EQ(1u, current_actions.size());
EXPECT_EQ(page_action->id(), current_actions[0]->extension_id());
}
// Test that navigating clears all state in a page action. // Test that navigating clears all state in a page action.
TEST_F(LocationBarControllerUnitTest, NavigationClearsState) { TEST_F(LocationBarControllerUnitTest, NavigationClearsState) {
scoped_refptr<const Extension> extension = const Extension* extension = AddExtension(true, "page_actions");
ExtensionBuilder()
.SetManifest(DictionaryBuilder()
.Set("name", "Extension with page action")
.Set("version", "1.0.0")
.Set("manifest_version", 2)
.Set("permissions", ListBuilder()
.Append("tabs"))
.Set("page_action", DictionaryBuilder()
.Set("default_title", "Hello")))
.Build();
extension_service_->AddExtension(extension.get());
NavigateAndCommit(GURL("http://www.google.com")); NavigateAndCommit(GURL("http://www.google.com"));
ExtensionAction& page_action = ExtensionAction& page_action =
*ExtensionActionManager::Get(profile())->GetPageAction(*extension.get()); *ExtensionActionManager::Get(profile())->GetPageAction(*extension);
page_action.SetTitle(tab_id(), "Goodbye"); page_action.SetTitle(tab_id(), "Goodbye");
page_action.SetPopupUrl( page_action.SetPopupUrl(tab_id(), extension->GetResourceURL("popup.html"));
tab_id(), extension->GetResourceURL("popup.html"));
EXPECT_EQ("Goodbye", page_action.GetTitle(tab_id())); EXPECT_EQ("Goodbye", page_action.GetTitle(tab_id()));
EXPECT_EQ(extension->GetResourceURL("popup.html"), EXPECT_EQ(extension->GetResourceURL("popup.html"),
...@@ -106,12 +175,7 @@ TEST_F(LocationBarControllerUnitTest, NavigationClearsState) { ...@@ -106,12 +175,7 @@ TEST_F(LocationBarControllerUnitTest, NavigationClearsState) {
EXPECT_EQ("Hello", page_action.GetTitle(tab_id())); EXPECT_EQ("Hello", page_action.GetTitle(tab_id()));
EXPECT_EQ(GURL(), page_action.GetPopupUrl(tab_id())); EXPECT_EQ(GURL(), page_action.GetPopupUrl(tab_id()));
}; }
// TODO(devlin): We should really have more tests for this.
// NavigationClearsState doesn't test at all that the LocationBarController
// actually *returns* the proper PageActions in GetCurrentActions. Do we do
// this elsewhere?
} // namespace } // namespace
} // namespace extensions } // namespace extensions
...@@ -88,6 +88,7 @@ TabHelper::TabHelper(content::WebContents* web_contents) ...@@ -88,6 +88,7 @@ TabHelper::TabHelper(content::WebContents* web_contents)
script_executor_( script_executor_(
new ScriptExecutor(web_contents, &script_execution_observers_)), new ScriptExecutor(web_contents, &script_execution_observers_)),
location_bar_controller_(new LocationBarController(web_contents)), location_bar_controller_(new LocationBarController(web_contents)),
active_script_controller_(new ActiveScriptController(web_contents)),
image_loader_ptr_factory_(this), image_loader_ptr_factory_(this),
webstore_inline_installer_factory_(new WebstoreInlineInstallerFactory()) { webstore_inline_installer_factory_(new WebstoreInlineInstallerFactory()) {
// The ActiveTabPermissionManager requires a session ID; ensure this // The ActiveTabPermissionManager requires a session ID; ensure this
......
...@@ -38,6 +38,7 @@ class Image; ...@@ -38,6 +38,7 @@ class Image;
} }
namespace extensions { namespace extensions {
class ActiveScriptController;
class BookmarkAppHelper; class BookmarkAppHelper;
class Extension; class Extension;
class LocationBarController; class LocationBarController;
...@@ -109,6 +110,10 @@ class TabHelper : public content::WebContentsObserver, ...@@ -109,6 +110,10 @@ class TabHelper : public content::WebContentsObserver,
return location_bar_controller_.get(); return location_bar_controller_.get();
} }
ActiveScriptController* active_script_controller() {
return active_script_controller_.get();
}
ActiveTabPermissionGranter* active_tab_permission_granter() { ActiveTabPermissionGranter* active_tab_permission_granter() {
return active_tab_permission_granter_.get(); return active_tab_permission_granter_.get();
} }
...@@ -245,6 +250,8 @@ class TabHelper : public content::WebContentsObserver, ...@@ -245,6 +250,8 @@ class TabHelper : public content::WebContentsObserver,
scoped_ptr<LocationBarController> location_bar_controller_; scoped_ptr<LocationBarController> location_bar_controller_;
scoped_ptr<ActiveScriptController> active_script_controller_;
scoped_ptr<ActiveTabPermissionGranter> active_tab_permission_granter_; scoped_ptr<ActiveTabPermissionGranter> active_tab_permission_granter_;
scoped_ptr<BookmarkAppHelper> bookmark_app_helper_; scoped_ptr<BookmarkAppHelper> bookmark_app_helper_;
......
...@@ -120,7 +120,7 @@ class AsyncUninstaller : public extensions::ExtensionUninstallDialog::Delegate { ...@@ -120,7 +120,7 @@ class AsyncUninstaller : public extensions::ExtensionUninstallDialog::Delegate {
browser_->tab_strip_model()->GetActiveWebContents(); browser_->tab_strip_model()->GetActiveWebContents();
if (activeTab && if (activeTab &&
extensions::ActiveScriptController::GetForWebContents(activeTab) extensions::ActiveScriptController::GetForWebContents(activeTab)
->HasActiveScriptAction(extension_)) { ->WantsToRun(extension_)) {
item = [menu addItemWithTitle: item = [menu addItemWithTitle:
l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_ALWAYS_RUN) l10n_util::GetNSStringWithFixup(IDS_EXTENSIONS_ALWAYS_RUN)
action:@selector(onAlwaysRun:) action:@selector(onAlwaysRun:)
......
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