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 |