active_script_controller_browsertest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// found in the LICENSE file. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/files/file_path.h" 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/macros.h" 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/stringprintf.h" 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/extensions/active_script_controller.h" 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/extensions/extension_action.h" 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/extensions/extension_browsertest.h" 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/extensions/test_extension_dir.h" 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/ui/browser.h" 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "chrome/test/base/ui_test_utils.h" 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/test/browser_test_utils.h" 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "extensions/common/feature_switch.h" 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "extensions/common/switches.h" 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "extensions/test/extension_test_message_listener.h" 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h" 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace extensions { 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace { 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char kAllHostsScheme[] = "*://*/*"; 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char kExplicitHostsScheme[] = "http://127.0.0.1/*"; 2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)const char kBackgroundScript[] = 30d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) "\"background\": {\"scripts\": [\"script.js\"]}"; 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)const char kBackgroundScriptSource[] = 3209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) "var listener = function(tabId) {\n" 3310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch " chrome.tabs.onUpdated.removeListener(listener);\n" 3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) " chrome.tabs.executeScript(tabId, {\n" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) " code: \"chrome.test.sendMessage('inject succeeded');\"\n" 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) " });" 37c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) "};\n" 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "chrome.tabs.onUpdated.addListener(listener);"; 397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochconst char kContentScriptSource[] = 401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) "chrome.test.sendMessage('inject succeeded');"; 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const char kInjectSucceeded[] = "inject succeeded"; 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 44197021e6b966cfb06891637935ef33fff06433d1Ben Murdochenum InjectionType { 455d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) CONTENT_SCRIPT, 467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci EXECUTE_SCRIPT 47d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)}; 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 495d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)enum HostType { 5009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ALL_HOSTS, 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) EXPLICIT_HOSTS 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 535d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 545d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)enum RequiresConsent { 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) REQUIRES_CONSENT, 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) DOES_NOT_REQUIRE_CONSENT 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}; 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Runs all pending tasks in the renderer associated with |web_contents|. 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Returns true on success. 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RunAllPendingInRenderer(content::WebContents* web_contents) { 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This is slight hack to achieve a RunPendingInRenderer() method. Since IPCs 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // are sent synchronously, anything started prior to this method will finish 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // before this method returns (as content::ExecuteScript() is synchronous). 657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return content::ExecuteScript(web_contents, "1 == 1;"); 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class ActiveScriptControllerBrowserTest : public ExtensionBrowserTest { 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) public: 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ActiveScriptControllerBrowserTest() {} 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE; 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) virtual void TearDownOnMainThread() OVERRIDE; 765d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 775d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) // Returns an extension with the given |host_type| and |injection_type|. If 78a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // one already exists, the existing extension will be returned. Othewrwise, 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // one will be created. 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This could potentially return NULL if LoadExtension() fails. 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const Extension* CreateExtension(HostType host_type, 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) InjectionType injection_type); 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) private: 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ScopedVector<TestExtensionDir> test_extension_dirs_; 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) std::vector<const Extension*> extensions_; 8707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch}; 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ActiveScriptControllerBrowserTest::SetUpCommandLine( 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) base::CommandLine* command_line) { 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ExtensionBrowserTest::SetUpCommandLine(command_line); 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // We append the actual switch to the commandline because it needs to be 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // passed over to the renderer, which a FeatureSwitch::ScopedOverride will 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // not do. 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) command_line->AppendSwitch(switches::kEnableScriptsRequireAction); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void ActiveScriptControllerBrowserTest::TearDownOnMainThread() { 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) test_extension_dirs_.clear(); 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 102d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)const Extension* ActiveScriptControllerBrowserTest::CreateExtension( 10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) HostType host_type, InjectionType injection_type) { 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) std::string name = 1051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) base::StringPrintf( 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "%s %s", 1075d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) injection_type == CONTENT_SCRIPT ? 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "content_script" : "execute_script", 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) host_type == ALL_HOSTS ? "all_hosts" : "explicit_hosts"); 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const char* permission_scheme = 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) host_type == ALL_HOSTS ? kAllHostsScheme : kExplicitHostsScheme; 1135d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) std::string permissions = base::StringPrintf( 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "\"permissions\": [\"tabs\", \"%s\"]", permission_scheme); 116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1175d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) std::string scripts; 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) std::string script_source; 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (injection_type == CONTENT_SCRIPT) { 120c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) scripts = base::StringPrintf( 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) "\"content_scripts\": [" 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) " {" 123 " \"matches\": [\"%s\"]," 124 " \"js\": [\"script.js\"]," 125 " \"run_at\": \"document_start\"" 126 " }" 127 "]", 128 permission_scheme); 129 } else { 130 scripts = kBackgroundScript; 131 } 132 133 std::string manifest = base::StringPrintf( 134 "{" 135 " \"name\": \"%s\"," 136 " \"version\": \"1.0\"," 137 " \"manifest_version\": 2," 138 " %s," 139 " %s" 140 "}", 141 name.c_str(), 142 permissions.c_str(), 143 scripts.c_str()); 144 145 scoped_ptr<TestExtensionDir> dir(new TestExtensionDir); 146 dir->WriteManifest(manifest); 147 dir->WriteFile(FILE_PATH_LITERAL("script.js"), 148 injection_type == CONTENT_SCRIPT ? kContentScriptSource : 149 kBackgroundScriptSource); 150 151 const Extension* extension = LoadExtension(dir->unpacked_path()); 152 if (extension) { 153 test_extension_dirs_.push_back(dir.release()); 154 extensions_.push_back(extension); 155 } 156 157 // If extension is NULL here, it will be caught later in the test. 158 return extension; 159} 160 161class ActiveScriptTester { 162 public: 163 ActiveScriptTester(const std::string& name, 164 const Extension* extension, 165 Browser* browser, 166 RequiresConsent requires_consent, 167 InjectionType type); 168 ~ActiveScriptTester(); 169 170 testing::AssertionResult Verify(); 171 172 private: 173 // Returns the active script controller, or NULL if one does not exist. 174 ActiveScriptController* GetActiveScriptController(); 175 176 // Returns true if the extension has a pending request with the active script 177 // controller. 178 bool WantsToRun(); 179 180 // The name of the extension, and also the message it sends. 181 std::string name_; 182 183 // The extension associated with this tester. 184 const Extension* extension_; 185 186 // The browser the tester is running in. 187 Browser* browser_; 188 189 // Whether or not the extension has permission to run the script without 190 // asking the user. 191 RequiresConsent requires_consent_; 192 193 // The type of injection this tester uses. 194 InjectionType type_; 195 196 // All of these extensions should inject a script (either through content 197 // scripts or through chrome.tabs.executeScript()) that sends a message with 198 // the |kInjectSucceeded| message. 199 linked_ptr<ExtensionTestMessageListener> inject_success_listener_; 200}; 201 202ActiveScriptTester::ActiveScriptTester(const std::string& name, 203 const Extension* extension, 204 Browser* browser, 205 RequiresConsent requires_consent, 206 InjectionType type) 207 : name_(name), 208 extension_(extension), 209 browser_(browser), 210 requires_consent_(requires_consent), 211 type_(type), 212 inject_success_listener_( 213 new ExtensionTestMessageListener(kInjectSucceeded, 214 false /* won't reply */)) { 215 inject_success_listener_->set_extension_id(extension->id()); 216} 217 218ActiveScriptTester::~ActiveScriptTester() { 219} 220 221testing::AssertionResult ActiveScriptTester::Verify() { 222 if (!extension_) 223 return testing::AssertionFailure() << "Could not load extension: " << name_; 224 225 content::WebContents* web_contents = 226 browser_ ? browser_->tab_strip_model()->GetActiveWebContents() : NULL; 227 if (!web_contents) 228 return testing::AssertionFailure() << "No web contents."; 229 230 // Give the extension plenty of time to inject. 231 if (!RunAllPendingInRenderer(web_contents)) 232 return testing::AssertionFailure() << "Could not run pending in renderer."; 233 234 // Make sure all running tasks are complete. 235 content::RunAllPendingInMessageLoop(); 236 237 ActiveScriptController* controller = GetActiveScriptController(); 238 if (!controller) 239 return testing::AssertionFailure() << "Could not find controller."; 240 241 bool wants_to_run = WantsToRun(); 242 243 // An extension should have an action displayed iff it requires user consent. 244 if ((requires_consent_ == REQUIRES_CONSENT && !wants_to_run) || 245 (requires_consent_ == DOES_NOT_REQUIRE_CONSENT && wants_to_run)) { 246 return testing::AssertionFailure() 247 << "Improper wants to run for " << name_ << ": expected " 248 << (requires_consent_ == REQUIRES_CONSENT) << ", found " 249 << wants_to_run; 250 } 251 252 // If the extension has permission, we should be able to simply wait for it 253 // to execute. 254 if (requires_consent_ == DOES_NOT_REQUIRE_CONSENT) { 255 inject_success_listener_->WaitUntilSatisfied(); 256 return testing::AssertionSuccess(); 257 } 258 259 // Otherwise, we don't have permission, and have to grant it. Ensure the 260 // script has *not* already executed. 261 if (inject_success_listener_->was_satisfied()) { 262 return testing::AssertionFailure() << 263 name_ << "'s script ran without permission."; 264 } 265 266 // If we reach this point, we should always want to run. 267 DCHECK(wants_to_run); 268 269 // Grant permission by clicking on the extension action. 270 controller->OnClicked(extension_); 271 272 // Now, the extension should be able to inject the script. 273 inject_success_listener_->WaitUntilSatisfied(); 274 275 // The extension should no longer want to run. 276 wants_to_run = WantsToRun(); 277 if (wants_to_run) { 278 return testing::AssertionFailure() 279 << "Extension " << name_ << " still wants to run after injecting."; 280 } 281 282 return testing::AssertionSuccess(); 283} 284 285ActiveScriptController* ActiveScriptTester::GetActiveScriptController() { 286 content::WebContents* web_contents = 287 browser_ ? browser_->tab_strip_model()->GetActiveWebContents() : NULL; 288 289 if (!web_contents) 290 return NULL; 291 292 TabHelper* tab_helper = TabHelper::FromWebContents(web_contents); 293 return tab_helper ? tab_helper->active_script_controller() : NULL; 294} 295 296bool ActiveScriptTester::WantsToRun() { 297 ActiveScriptController* controller = GetActiveScriptController(); 298 return controller ? controller->WantsToRun(extension_) : false; 299} 300 301IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest, 302 ActiveScriptsAreDisplayedAndDelayExecution) { 303 base::FilePath active_script_path = 304 test_data_dir_.AppendASCII("active_script"); 305 306 const char* kExtensionNames[] = { 307 "inject_scripts_all_hosts", 308 "inject_scripts_explicit_hosts", 309 "content_scripts_all_hosts", 310 "content_scripts_explicit_hosts" 311 }; 312 313 // First, we load up three extensions: 314 // - An extension that injects scripts into all hosts, 315 // - An extension that injects scripts into explicit hosts, 316 // - An extension with a content script that runs on all hosts, 317 // - An extension with a content script that runs on explicit hosts. 318 // The extensions that operate on explicit hosts have permission; the ones 319 // that request all hosts require user consent. 320 ActiveScriptTester testers[] = { 321 ActiveScriptTester( 322 kExtensionNames[0], 323 CreateExtension(ALL_HOSTS, EXECUTE_SCRIPT), 324 browser(), 325 REQUIRES_CONSENT, 326 EXECUTE_SCRIPT), 327 ActiveScriptTester( 328 kExtensionNames[1], 329 CreateExtension(EXPLICIT_HOSTS, EXECUTE_SCRIPT), 330 browser(), 331 DOES_NOT_REQUIRE_CONSENT, 332 EXECUTE_SCRIPT), 333 ActiveScriptTester( 334 kExtensionNames[2], 335 CreateExtension(ALL_HOSTS, CONTENT_SCRIPT), 336 browser(), 337 REQUIRES_CONSENT, 338 CONTENT_SCRIPT), 339 ActiveScriptTester( 340 kExtensionNames[3], 341 CreateExtension(EXPLICIT_HOSTS, CONTENT_SCRIPT), 342 browser(), 343 DOES_NOT_REQUIRE_CONSENT, 344 CONTENT_SCRIPT), 345 }; 346 347 // Navigate to an URL (which matches the explicit host specified in the 348 // extension content_scripts_explicit_hosts). All four extensions should 349 // inject the script. 350 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 351 ui_test_utils::NavigateToURL( 352 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); 353 354 for (size_t i = 0u; i < arraysize(testers); ++i) 355 EXPECT_TRUE(testers[i].Verify()) << kExtensionNames[i]; 356} 357 358// Test that removing an extension with pending injections a) removes the 359// pending injections for that extension, and b) does not affect pending 360// injections for other extensions. 361IN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest, 362 RemoveExtensionWithPendingInjections) { 363 // Load up two extensions, each with content scripts. 364 const Extension* extension1 = CreateExtension(ALL_HOSTS, CONTENT_SCRIPT); 365 ASSERT_TRUE(extension1); 366 const Extension* extension2 = CreateExtension(ALL_HOSTS, CONTENT_SCRIPT); 367 ASSERT_TRUE(extension2); 368 369 ASSERT_NE(extension1->id(), extension2->id()); 370 371 content::WebContents* web_contents = 372 browser()->tab_strip_model()->GetActiveWebContents(); 373 ASSERT_TRUE(web_contents); 374 ActiveScriptController* active_script_controller = 375 ActiveScriptController::GetForWebContents(web_contents); 376 ASSERT_TRUE(active_script_controller); 377 378 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 379 ui_test_utils::NavigateToURL( 380 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); 381 382 // Both extensions should have pending requests. 383 EXPECT_TRUE(active_script_controller->WantsToRun(extension1)); 384 EXPECT_TRUE(active_script_controller->WantsToRun(extension2)); 385 386 // Unload one of the extensions. 387 UnloadExtension(extension2->id()); 388 389 EXPECT_TRUE(RunAllPendingInRenderer(web_contents)); 390 391 // We should have pending requests for extension1, but not the removed 392 // extension2. 393 EXPECT_TRUE(active_script_controller->WantsToRun(extension1)); 394 EXPECT_FALSE(active_script_controller->WantsToRun(extension2)); 395 396 // We should still be able to run the request for extension1. 397 ExtensionTestMessageListener inject_success_listener( 398 new ExtensionTestMessageListener(kInjectSucceeded, 399 false /* won't reply */)); 400 inject_success_listener.set_extension_id(extension1->id()); 401 active_script_controller->OnClicked(extension1); 402 inject_success_listener.WaitUntilSatisfied(); 403} 404 405// A version of the test with the flag off, in order to test that everything 406// still works as expected. 407class FlagOffActiveScriptControllerBrowserTest 408 : public ActiveScriptControllerBrowserTest { 409 private: 410 // Simply don't append the flag. 411 virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE { 412 ExtensionBrowserTest::SetUpCommandLine(command_line); 413 } 414}; 415 416IN_PROC_BROWSER_TEST_F(FlagOffActiveScriptControllerBrowserTest, 417 ScriptsExecuteWhenFlagAbsent) { 418 const char* kExtensionNames[] = { 419 "content_scripts_all_hosts", 420 "inject_scripts_all_hosts", 421 }; 422 ActiveScriptTester testers[] = { 423 ActiveScriptTester( 424 kExtensionNames[0], 425 CreateExtension(ALL_HOSTS, CONTENT_SCRIPT), 426 browser(), 427 DOES_NOT_REQUIRE_CONSENT, 428 CONTENT_SCRIPT), 429 ActiveScriptTester( 430 kExtensionNames[1], 431 CreateExtension(ALL_HOSTS, EXECUTE_SCRIPT), 432 browser(), 433 DOES_NOT_REQUIRE_CONSENT, 434 EXECUTE_SCRIPT), 435 }; 436 437 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 438 ui_test_utils::NavigateToURL( 439 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); 440 441 for (size_t i = 0u; i < arraysize(testers); ++i) 442 EXPECT_TRUE(testers[i].Verify()) << kExtensionNames[i]; 443} 444 445} // namespace extensions 446