active_script_controller_browsertest.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Copyright 2014 The Chromium Authors. All rights reserved.
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Use of this source code is governed by a BSD-style license that can be
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// found in the LICENSE file.
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/files/file_path.h"
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/macros.h"
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "base/strings/stringprintf.h"
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/extensions/active_script_controller.h"
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/extensions/extension_action.h"
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/extensions/extension_browsertest.h"
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/extensions/extension_test_message_listener.h"
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/extensions/location_bar_controller.h"
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/extensions/tab_helper.h"
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/extensions/test_extension_dir.h"
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/ui/browser.h"
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/browser/ui/tabs/tab_strip_model.h"
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "chrome/test/base/ui_test_utils.h"
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "content/public/test/browser_test_utils.h"
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "extensions/common/feature_switch.h"
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "extensions/common/switches.h"
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "net/test/embedded_test_server/embedded_test_server.h"
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "testing/gtest/include/gtest/gtest.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgnamespace extensions {
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgnamespace {
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char kAllHostsScheme[] = "*://*/*";
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char kExplicitHostsScheme[] = "http://127.0.0.1/*";
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char kBackgroundScript[] =
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "\"background\": {\"scripts\": [\"script.js\"]}";
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char kBackgroundScriptSource[] =
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "var listener = function(tabId) {\n"
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "  chrome.tabs.onUpdated.removeListener(listener);\n"
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "  chrome.tabs.executeScript(tabId, {\n"
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "    code: \"chrome.test.sendMessage('inject succeeded');\"\n"
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "  });"
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "  chrome.test.sendMessage('inject attempted');\n"
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "};\n"
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "chrome.tabs.onUpdated.addListener(listener);";
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char kContentScriptSource[] =
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "chrome.test.sendMessage('inject succeeded');";
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char kInjectAttempted[] = "inject attempted";
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst char kInjectSucceeded[] = "inject succeeded";
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenum InjectionType {
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  CONTENT_SCRIPT,
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  EXECUTE_SCRIPT
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenum HostType {
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ALL_HOSTS,
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  EXPLICIT_HOSTS
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenum RequiresConsent {
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  REQUIRES_CONSENT,
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  DOES_NOT_REQUIRE_CONSENT
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}  // namespace
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass ActiveScriptControllerBrowserTest : public ExtensionBrowserTest {
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org public:
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ActiveScriptControllerBrowserTest() {}
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE;
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  virtual void CleanUpOnMainThread() OVERRIDE;
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Returns an extension with the given |host_type| and |injection_type|. If
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // one already exists, the existing extension will be returned. Othewrwise,
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // one will be created.
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // This could potentially return NULL if LoadExtension() fails.
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  const Extension* CreateExtension(HostType host_type,
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                   InjectionType injection_type);
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org private:
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ScopedVector<TestExtensionDir> test_extension_dirs_;
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  std::vector<const Extension*> extensions_;
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid ActiveScriptControllerBrowserTest::SetUpCommandLine(
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    base::CommandLine* command_line) {
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ExtensionBrowserTest::SetUpCommandLine(command_line);
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // We append the actual switch to the commandline because it needs to be
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // passed over to the renderer, which a FeatureSwitch::ScopedOverride will
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // not do.
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  command_line->AppendSwitch(switches::kEnableScriptsRequireAction);
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid ActiveScriptControllerBrowserTest::CleanUpOnMainThread() {
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  test_extension_dirs_.clear();
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst Extension* ActiveScriptControllerBrowserTest::CreateExtension(
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    HostType host_type, InjectionType injection_type) {
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  std::string name =
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      base::StringPrintf(
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          "%s %s",
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          injection_type == CONTENT_SCRIPT ?
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              "content_script" : "execute_script",
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          host_type == ALL_HOSTS ? "all_hosts" : "explicit_hosts");
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  const char* permission_scheme =
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      host_type == ALL_HOSTS ? kAllHostsScheme : kExplicitHostsScheme;
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  std::string permissions = base::StringPrintf(
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      "\"permissions\": [\"tabs\", \"%s\"]", permission_scheme);
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  std::string scripts;
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  std::string script_source;
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (injection_type == CONTENT_SCRIPT) {
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    scripts = base::StringPrintf(
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        "\"content_scripts\": ["
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        " {"
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        "  \"matches\": [\"%s\"],"
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        "  \"js\": [\"script.js\"],"
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        "  \"run_at\": \"document_start\""
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        " }"
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        "]",
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        permission_scheme);
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  } else {
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    scripts = kBackgroundScript;
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  std::string manifest = base::StringPrintf(
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      "{"
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      " \"name\": \"%s\","
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      " \"version\": \"1.0\","
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      " \"manifest_version\": 2,"
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      " %s,"
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      " %s"
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      "}",
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      name.c_str(),
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      permissions.c_str(),
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      scripts.c_str());
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  scoped_ptr<TestExtensionDir> dir(new TestExtensionDir);
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  dir->WriteManifest(manifest);
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  dir->WriteFile(FILE_PATH_LITERAL("script.js"),
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                 injection_type == CONTENT_SCRIPT ? kContentScriptSource :
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                                    kBackgroundScriptSource);
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  const Extension* extension = LoadExtension(dir->unpacked_path());
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (extension) {
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    test_extension_dirs_.push_back(dir.release());
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    extensions_.push_back(extension);
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // If extension is NULL here, it will be caught later in the test.
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  return extension;
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass ActiveScriptTester {
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org public:
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ActiveScriptTester(const std::string& name,
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     const Extension* extension,
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     Browser* browser,
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     RequiresConsent requires_consent,
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     InjectionType type);
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ~ActiveScriptTester();
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  testing::AssertionResult Verify();
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org private:
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Returns the location bar controller, or NULL if one does not exist.
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  LocationBarController* GetLocationBarController();
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Returns the active script controller, or NULL if one does not exist.
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ActiveScriptController* GetActiveScriptController();
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Get the ExtensionAction for this extension, or NULL if one does not exist.
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ExtensionAction* GetAction();
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // The name of the extension, and also the message it sends.
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  std::string name_;
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // The extension associated with this tester.
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  const Extension* extension_;
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // The browser the tester is running in.
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  Browser* browser_;
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Whether or not the extension has permission to run the script without
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // asking the user.
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  RequiresConsent requires_consent_;
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // The type of injection this tester uses.
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  InjectionType type_;
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // All of these extensions should inject a script (either through content
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // scripts or through chrome.tabs.executeScript()) that sends a message with
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // the |kInjectSucceeded| message.
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  linked_ptr<ExtensionTestMessageListener> inject_attempt_listener_;
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // After trying to inject the script, extensions sending the script via
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // chrome.tabs.executeScript() send a |kInjectAttempted| message.
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  linked_ptr<ExtensionTestMessageListener> inject_success_listener_;
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgActiveScriptTester::ActiveScriptTester(const std::string& name,
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                       const Extension* extension,
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                       Browser* browser,
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                       RequiresConsent requires_consent,
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                       InjectionType type)
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    : name_(name),
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      extension_(extension),
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      browser_(browser),
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      requires_consent_(requires_consent),
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      type_(type),
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      inject_attempt_listener_(
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          new ExtensionTestMessageListener(kInjectAttempted,
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                           false /* won't reply */)),
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      inject_success_listener_(
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          new ExtensionTestMessageListener(kInjectSucceeded,
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                           false /* won't reply */)) {
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  inject_attempt_listener_->set_extension_id(extension->id());
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  inject_success_listener_->set_extension_id(extension->id());
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgActiveScriptTester::~ActiveScriptTester() {
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtesting::AssertionResult ActiveScriptTester::Verify() {
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (!extension_)
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return testing::AssertionFailure() << "Could not load extension: " << name_;
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // If it's not a content script, the Extension lets us know when it has
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // attempted to inject the script.
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // This means there is a potential for a race condition with content scripts;
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // however, since they are all injected at document_start, this shouldn't be
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // a problem. If these tests start failing, though, that might be it.
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (type_ == EXECUTE_SCRIPT)
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    inject_attempt_listener_->WaitUntilSatisfied();
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Make sure all running tasks are complete.
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  content::RunAllPendingInMessageLoop();
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  LocationBarController* location_bar_controller = GetLocationBarController();
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (!location_bar_controller) {
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return testing::AssertionFailure()
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        << "Could not find location bar controller";
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ActiveScriptController* controller =
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      location_bar_controller->active_script_controller();
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (!controller)
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return testing::AssertionFailure() << "Could not find controller.";
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ExtensionAction* action = GetAction();
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  bool has_action = action != NULL;
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // An extension should have an action displayed iff it requires user consent.
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if ((requires_consent_ == REQUIRES_CONSENT && !has_action) ||
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      (requires_consent_ == DOES_NOT_REQUIRE_CONSENT && has_action)) {
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return testing::AssertionFailure()
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        << "Improper action status for " << name_ << ": expected "
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        << (requires_consent_ == REQUIRES_CONSENT) << ", found " << has_action;
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // If the extension has permission, we should be able to simply wait for it
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // to execute.
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (requires_consent_ == DOES_NOT_REQUIRE_CONSENT) {
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    inject_success_listener_->WaitUntilSatisfied();
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return testing::AssertionSuccess();
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Otherwise, we don't have permission, and have to grant it. Ensure the
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // script has *not* already executed.
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (inject_success_listener_->was_satisfied()) {
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return testing::AssertionFailure() <<
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        name_ << "'s script ran without permission.";
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // If we reach this point, we should always have an action.
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  DCHECK(action);
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Grant permission by clicking on the extension action.
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  location_bar_controller->OnClicked(action);
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Now, the extension should be able to inject the script.
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  inject_success_listener_->WaitUntilSatisfied();
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // The Action should have disappeared.
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  has_action = GetAction() != NULL;
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (has_action) {
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return testing::AssertionFailure()
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        << "Extension " << name_ << " has lingering action.";
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  return testing::AssertionSuccess();
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocationBarController* ActiveScriptTester::GetLocationBarController() {
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  content::WebContents* web_contents =
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      browser_ ? browser_->tab_strip_model()->GetActiveWebContents() : NULL;
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (!web_contents)
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return NULL;
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  TabHelper* tab_helper = TabHelper::FromWebContents(web_contents);
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  return tab_helper ? tab_helper->location_bar_controller() : NULL;
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgActiveScriptController* ActiveScriptTester::GetActiveScriptController() {
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  LocationBarController* location_bar_controller = GetLocationBarController();
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  return location_bar_controller ?
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      location_bar_controller->active_script_controller() : NULL;
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgExtensionAction* ActiveScriptTester::GetAction() {
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ActiveScriptController* controller = GetActiveScriptController();
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  return controller ? controller->GetActionForExtension(extension_) : NULL;
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgIN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest,
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       ActiveScriptsAreDisplayedAndDelayExecution) {
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  base::FilePath active_script_path =
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      test_data_dir_.AppendASCII("active_script");
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  const char* kExtensionNames[] = {
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      "inject_scripts_all_hosts",
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      "inject_scripts_explicit_hosts",
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      "content_scripts_all_hosts",
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      "content_scripts_explicit_hosts"
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  };
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // First, we load up three extensions:
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // - An extension that injects scripts into all hosts,
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // - An extension that injects scripts into explicit hosts,
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // - An extension with a content script that runs on all hosts,
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // - An extension with a content script that runs on explicit hosts.
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // The extensions that operate on explicit hosts have permission; the ones
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // that request all hosts require user consent.
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ActiveScriptTester testers[] = {
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      ActiveScriptTester(
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          kExtensionNames[0],
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          CreateExtension(ALL_HOSTS, EXECUTE_SCRIPT),
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          browser(),
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          REQUIRES_CONSENT,
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          EXECUTE_SCRIPT),
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      ActiveScriptTester(
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          kExtensionNames[1],
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          CreateExtension(EXPLICIT_HOSTS, EXECUTE_SCRIPT),
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          browser(),
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          DOES_NOT_REQUIRE_CONSENT,
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          EXECUTE_SCRIPT),
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      ActiveScriptTester(
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          kExtensionNames[2],
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          CreateExtension(ALL_HOSTS, CONTENT_SCRIPT),
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          browser(),
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          REQUIRES_CONSENT,
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          CONTENT_SCRIPT),
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      ActiveScriptTester(
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          kExtensionNames[3],
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          CreateExtension(EXPLICIT_HOSTS, CONTENT_SCRIPT),
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          browser(),
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          DOES_NOT_REQUIRE_CONSENT,
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          CONTENT_SCRIPT),
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  };
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Navigate to an URL (which matches the explicit host specified in the
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // extension content_scripts_explicit_hosts). All four extensions should
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // inject the script.
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ui_test_utils::NavigateToURL(
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      browser(), embedded_test_server()->GetURL("/extensions/test_file.html"));
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  for (size_t i = 0u; i < arraysize(testers); ++i)
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    EXPECT_TRUE(testers[i].Verify()) << kExtensionNames[i];
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Test that removing an extension with pending injections a) removes the
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// pending injections for that extension, and b) does not affect pending
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// injections for other extensions.
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgIN_PROC_BROWSER_TEST_F(ActiveScriptControllerBrowserTest,
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       RemoveExtensionWithPendingInjections) {
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Load up two extensions, each with content scripts.
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  const Extension* extension1 = CreateExtension(ALL_HOSTS, CONTENT_SCRIPT);
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ASSERT_TRUE(extension1);
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  const Extension* extension2 = CreateExtension(ALL_HOSTS, CONTENT_SCRIPT);
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ASSERT_TRUE(extension2);
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ASSERT_NE(extension1->id(), extension2->id());
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  content::WebContents* web_contents =
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      browser()->tab_strip_model()->GetActiveWebContents();
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ASSERT_TRUE(web_contents);
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ActiveScriptController* active_script_controller =
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      ActiveScriptController::GetForWebContents(web_contents);
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ASSERT_TRUE(active_script_controller);
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ui_test_utils::NavigateToURL(
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      browser(), embedded_test_server()->GetURL("/extensions/test_file.html"));
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Both extensions should have pending requests.
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  EXPECT_TRUE(active_script_controller->GetActionForExtension(extension1));
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  EXPECT_TRUE(active_script_controller->GetActionForExtension(extension2));
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Unload one of the extensions.
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  UnloadExtension(extension2->id());
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // This is slight hack to achieve a RunPendingInRenderer() method. Since IPCs
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // are sent synchronously, the renderer will be notified of the extension
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // being unloaded before the script is executed, and, since ExecuteScript() is
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // synchronous, the renderer is guaranteed to be done updating scripts.
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  EXPECT_TRUE(content::ExecuteScript(web_contents, "1 == 1;"));
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // We should have pending requests for extension1, but not the removed
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // extension2.
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  EXPECT_TRUE(active_script_controller->GetActionForExtension(extension1));
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  EXPECT_FALSE(active_script_controller->GetActionForExtension(extension2));
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // We should still be able to run the request for extension1.
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ExtensionTestMessageListener inject_success_listener(
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      new ExtensionTestMessageListener(kInjectSucceeded,
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                       false /* won't reply */));
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  inject_success_listener.set_extension_id(extension1->id());
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  active_script_controller->OnClicked(extension1);
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  inject_success_listener.WaitUntilSatisfied();
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// A version of the test with the flag off, in order to test that everything
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// still works as expected.
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass FlagOffActiveScriptControllerBrowserTest
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    : public ActiveScriptControllerBrowserTest {
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org private:
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  // Simply don't append the flag.
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ExtensionBrowserTest::SetUpCommandLine(command_line);
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgIN_PROC_BROWSER_TEST_F(FlagOffActiveScriptControllerBrowserTest,
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                       ScriptsExecuteWhenFlagAbsent) {
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  const char* kExtensionNames[] = {
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "content_scripts_all_hosts",
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    "inject_scripts_all_hosts",
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  };
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ActiveScriptTester testers[] = {
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ActiveScriptTester(
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          kExtensionNames[0],
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          CreateExtension(ALL_HOSTS, CONTENT_SCRIPT),
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          browser(),
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          DOES_NOT_REQUIRE_CONSENT,
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          CONTENT_SCRIPT),
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      ActiveScriptTester(
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          kExtensionNames[1],
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          CreateExtension(ALL_HOSTS, EXECUTE_SCRIPT),
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          browser(),
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          DOES_NOT_REQUIRE_CONSENT,
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          EXECUTE_SCRIPT),
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  };
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  ui_test_utils::NavigateToURL(
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      browser(), embedded_test_server()->GetURL("/extensions/test_file.html"));
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  for (size_t i = 0u; i < arraysize(testers); ++i)
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    EXPECT_TRUE(testers[i].Verify()) << kExtensionNames[i];
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}  // namespace extensions
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org