| Index: chrome/browser/extensions/active_script_controller_browsertest.cc
|
| diff --git a/chrome/browser/extensions/active_script_controller_browsertest.cc b/chrome/browser/extensions/active_script_controller_browsertest.cc
|
| index 5be5b714ebf3ed821a0e460ea20e349849c76832..f81b332af8dbb8cd73000b8da17cf6a64e460990 100644
|
| --- a/chrome/browser/extensions/active_script_controller_browsertest.cc
|
| +++ b/chrome/browser/extensions/active_script_controller_browsertest.cc
|
| @@ -18,6 +18,23 @@
|
|
|
| namespace extensions {
|
|
|
| +namespace {
|
| +
|
| +const char kInjectAttempted[] = "inject attempted";
|
| +const char kInjectSucceeded[] = "inject succeeded";
|
| +
|
| +enum InjectionType {
|
| + CONTENT_SCRIPT,
|
| + EXECUTE_SCRIPT
|
| +};
|
| +
|
| +enum RequiresConsent {
|
| + REQUIRES_CONSENT,
|
| + DOES_NOT_REQUIRE_CONSENT
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| class ActiveScriptControllerBrowserTest : public ExtensionBrowserTest {
|
| public:
|
| ActiveScriptControllerBrowserTest()
|
| @@ -31,100 +48,211 @@ class ActiveScriptTester {
|
| public:
|
| ActiveScriptTester(const std::string& name,
|
| const Extension* extension,
|
| - bool expect_has_action);
|
| + Browser* browser,
|
| + RequiresConsent requires_consent,
|
| + InjectionType type);
|
| ~ActiveScriptTester();
|
|
|
| - testing::AssertionResult Verify(Browser* browser);
|
| + testing::AssertionResult Verify();
|
|
|
| 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.
|
| + ActiveScriptController* GetActiveScriptController();
|
| +
|
| + // Get the ExtensionAction for this extension, or NULL if one does not exist.
|
| + ExtensionAction* GetAction();
|
| +
|
| // The name of the extension, and also the message it sends.
|
| std::string name_;
|
|
|
| // The extension associated with this tester.
|
| const Extension* extension_;
|
|
|
| - // Whether or not we expect the extension to have an action for script
|
| - // injection.
|
| - bool expect_has_action_;
|
| + // The browser the tester is running in.
|
| + Browser* browser_;
|
| +
|
| + // Whether or not the extension has permission to run the script without
|
| + // asking the user.
|
| + RequiresConsent requires_consent_;
|
| +
|
| + // The type of injection this tester uses.
|
| + InjectionType type_;
|
|
|
| // All of these extensions should inject a script (either through content
|
| // scripts or through chrome.tabs.executeScript()) that sends a message with
|
| - // their names (for verification).
|
| - // Be prepared to wait for each extension to inject the script.
|
| - linked_ptr<ExtensionTestMessageListener> listener_;
|
| + // the |kInjectSucceeded| message.
|
| + linked_ptr<ExtensionTestMessageListener> inject_attempt_listener_;
|
| +
|
| + // After trying to inject the script, extensions sending the script via
|
| + // chrome.tabs.executeScript() send a |kInjectAttempted| message.
|
| + linked_ptr<ExtensionTestMessageListener> inject_success_listener_;
|
| };
|
|
|
| ActiveScriptTester::ActiveScriptTester(const std::string& name,
|
| const Extension* extension,
|
| - bool expect_has_action)
|
| + Browser* browser,
|
| + RequiresConsent requires_consent,
|
| + InjectionType type)
|
| : name_(name),
|
| extension_(extension),
|
| - expect_has_action_(expect_has_action),
|
| - listener_(
|
| - new ExtensionTestMessageListener(name, false /* won't reply */)) {
|
| + browser_(browser),
|
| + requires_consent_(requires_consent),
|
| + type_(type),
|
| + inject_attempt_listener_(
|
| + new ExtensionTestMessageListener(kInjectAttempted,
|
| + false /* won't reply */)),
|
| + inject_success_listener_(
|
| + new ExtensionTestMessageListener(kInjectSucceeded,
|
| + false /* won't reply */)) {
|
| + inject_attempt_listener_->set_extension_id(extension->id());
|
| + inject_success_listener_->set_extension_id(extension->id());
|
| }
|
|
|
| ActiveScriptTester::~ActiveScriptTester() {
|
| }
|
|
|
| -testing::AssertionResult ActiveScriptTester::Verify(Browser* browser) {
|
| +testing::AssertionResult ActiveScriptTester::Verify() {
|
| if (!extension_)
|
| return testing::AssertionFailure() << "Could not load extension: " << name_;
|
|
|
| - listener_->WaitUntilSatisfied();
|
| - content::WebContents* web_contents =
|
| - browser ? browser->tab_strip_model()->GetActiveWebContents() : NULL;
|
| + // If it's not a content script, the Extension lets us know when it has
|
| + // attempted to inject the script.
|
| + // This means there is a potential for a race condition with content scripts;
|
| + // however, since they are all injected at document_start, this shouldn't be
|
| + // a problem. If these tests start failing, though, that might be it.
|
| + if (type_ == EXECUTE_SCRIPT)
|
| + inject_attempt_listener_->WaitUntilSatisfied();
|
|
|
| - if (!web_contents)
|
| - return testing::AssertionFailure() << "Could not find web contents.";
|
| + // Make sure all running tasks are complete.
|
| + content::RunAllPendingInMessageLoop();
|
|
|
| - TabHelper* tab_helper = TabHelper::FromWebContents(web_contents);
|
| - if (!tab_helper)
|
| - return testing::AssertionFailure() << "Could not find tab helper.";
|
| + LocationBarController* location_bar_controller = GetLocationBarController();
|
| + if (!location_bar_controller) {
|
| + return testing::AssertionFailure()
|
| + << "Could not find location bar controller";
|
| + }
|
|
|
| ActiveScriptController* controller =
|
| - tab_helper->location_bar_controller()->active_script_controller();
|
| + location_bar_controller->active_script_controller();
|
| if (!controller)
|
| return testing::AssertionFailure() << "Could not find controller.";
|
|
|
| - bool has_action = controller->GetActionForExtension(extension_) != NULL;
|
| - if (expect_has_action_ != has_action) {
|
| + ExtensionAction* action = GetAction();
|
| + bool has_action = action != NULL;
|
| +
|
| + // An extension should have an action displayed iff it requires user consent.
|
| + if ((requires_consent_ == REQUIRES_CONSENT && !has_action) ||
|
| + (requires_consent_ == DOES_NOT_REQUIRE_CONSENT && has_action)) {
|
| return testing::AssertionFailure()
|
| - << "Improper action status: expected " << expect_has_action_
|
| - << ", found " << has_action;
|
| + << "Improper action status for " << name_ << ": expected "
|
| + << (requires_consent_ == REQUIRES_CONSENT) << ", found " << has_action;
|
| + }
|
| +
|
| + // If the extension has permission, we should be able to simply wait for it
|
| + // to execute.
|
| + if (requires_consent_ == DOES_NOT_REQUIRE_CONSENT) {
|
| + inject_success_listener_->WaitUntilSatisfied();
|
| + return testing::AssertionSuccess();
|
| + }
|
| +
|
| + // Otherwise, we don't have permission, and have to grant it. Ensure the
|
| + // script has *not* already executed.
|
| + // Currently, it's okay for content scripts to execute, because we don't
|
| + // block them.
|
| + // TODO(rdevlin.cronin): Fix this.
|
| + if (inject_success_listener_->was_satisfied() && type_ != CONTENT_SCRIPT) {
|
| + return testing::AssertionFailure() <<
|
| + name_ << "'s script ran without permission.";
|
| + }
|
| +
|
| + // If we reach this point, we should always have an action.
|
| + DCHECK(action);
|
| +
|
| + // Grant permission by clicking on the extension action.
|
| + location_bar_controller->OnClicked(action);
|
| +
|
| + // Now, the extension should be able to inject the script.
|
| + inject_success_listener_->WaitUntilSatisfied();
|
| +
|
| + // The Action should have disappeared.
|
| + has_action = GetAction() != NULL;
|
| + if (has_action) {
|
| + return testing::AssertionFailure()
|
| + << "Extension " << name_ << " has lingering action.";
|
| }
|
|
|
| return testing::AssertionSuccess();
|
| }
|
|
|
| +LocationBarController* ActiveScriptTester::GetLocationBarController() {
|
| + content::WebContents* web_contents =
|
| + browser_ ? browser_->tab_strip_model()->GetActiveWebContents() : NULL;
|
| +
|
| + if (!web_contents)
|
| + return NULL;
|
| +
|
| + TabHelper* tab_helper = TabHelper::FromWebContents(web_contents);
|
| + return tab_helper ? tab_helper->location_bar_controller() : NULL;
|
| +}
|
| +
|
| +ActiveScriptController* ActiveScriptTester::GetActiveScriptController() {
|
| + LocationBarController* location_bar_controller = GetLocationBarController();
|
| + return location_bar_controller ?
|
| + location_bar_controller->active_script_controller() : NULL;
|
| +}
|
| +
|
| +ExtensionAction* ActiveScriptTester::GetAction() {
|
| + ActiveScriptController* controller = GetActiveScriptController();
|
| + return controller ? controller->GetActionForExtension(extension_) : NULL;
|
| +}
|
| +
|
| IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest,
|
| ActiveScriptsAreDisplayed) {
|
| base::FilePath active_script_path =
|
| test_data_dir_.AppendASCII("active_script");
|
|
|
| const char* kExtensionNames[] = {
|
| - "content_scripts_all_hosts",
|
| "inject_scripts_all_hosts",
|
| + "inject_scripts_explicit_hosts",
|
| + "content_scripts_all_hosts",
|
| "content_scripts_explicit_hosts"
|
| };
|
|
|
| // First, we load up three extensions:
|
| - // - An extension with a content script that runs on all hosts,
|
| // - An extension that injects scripts into all hosts,
|
| + // - An extension that injects scripts into explicit hosts,
|
| + // - An extension with a content script that runs on all hosts,
|
| // - An extension with a content script that runs on explicit hosts.
|
| + // The extensions that operate on explicit hosts have permission; the ones
|
| + // that request all hosts require user consent.
|
| ActiveScriptTester testers[] = {
|
| ActiveScriptTester(
|
| kExtensionNames[0],
|
| LoadExtension(active_script_path.AppendASCII(kExtensionNames[0])),
|
| - true /* expect action */),
|
| + browser(),
|
| + REQUIRES_CONSENT,
|
| + EXECUTE_SCRIPT),
|
| ActiveScriptTester(
|
| kExtensionNames[1],
|
| LoadExtension(active_script_path.AppendASCII(kExtensionNames[1])),
|
| - true /* expect action */),
|
| + browser(),
|
| + DOES_NOT_REQUIRE_CONSENT,
|
| + EXECUTE_SCRIPT),
|
| ActiveScriptTester(
|
| kExtensionNames[2],
|
| LoadExtension(active_script_path.AppendASCII(kExtensionNames[2])),
|
| - false /* expect action */)
|
| + browser(),
|
| + REQUIRES_CONSENT,
|
| + CONTENT_SCRIPT),
|
| + ActiveScriptTester(
|
| + kExtensionNames[3],
|
| + LoadExtension(active_script_path.AppendASCII(kExtensionNames[3])),
|
| + browser(),
|
| + DOES_NOT_REQUIRE_CONSENT,
|
| + CONTENT_SCRIPT),
|
| };
|
|
|
| // Navigate to an URL (which matches the explicit host specified in the
|
| @@ -135,7 +263,7 @@ IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest,
|
| browser(), embedded_test_server()->GetURL("/extensions/test_file.html"));
|
|
|
| for (size_t i = 0u; i < arraysize(testers); ++i)
|
| - ASSERT_TRUE(testers[i].Verify(browser())) << kExtensionNames[i];
|
| + EXPECT_TRUE(testers[i].Verify()) << kExtensionNames[i];
|
| }
|
|
|
| } // namespace extensions
|
|
|