Disarm LockToOrigin for extensions under --isolate-extensions.

--isolate-extensions actually permits render process reuse, unlike
--site-per-process. This means that "one extension per process" isn't a
valid thing to enforce, which hopefully explains the process kills
we have seen in the wild.

Add a test that exercises this. It fails without the fix.

BUG=600441
TEST=browser_tests
CQ_INCLUDE_TRYBOTS=tryserver.chromium.linux:linux_site_isolation

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

Cr-Commit-Position: refs/heads/master@{#385947}
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc
index 6a01909..3bddd9f 100644
--- a/chrome/browser/extensions/process_manager_browsertest.cc
+++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -21,6 +21,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
@@ -527,4 +528,53 @@
   EXPECT_EQ(baseline_keepalive, pm->GetLazyKeepaliveCount(extension.get()));
 }
 
+IN_PROC_BROWSER_TEST_F(ProcessManagerBrowserTest, ExtensionProcessReuse) {
+  const size_t kNumExtensions = 3;
+  content::RenderProcessHost::SetMaxRendererProcessCount(kNumExtensions - 1);
+  ProcessManager* pm = ProcessManager::Get(profile());
+
+  std::set<int> processes;
+  std::set<const Extension*> installed_extensions;
+
+  // Create 3 extensions, which is more than the process limit.
+  for (int i = 1; i <= static_cast<int>(kNumExtensions); ++i) {
+    const Extension* extension =
+        CreateExtension(base::StringPrintf("Extension %d", i), true);
+    installed_extensions.insert(extension);
+    ExtensionHost* extension_host =
+        pm->GetBackgroundHostForExtension(extension->id());
+
+    EXPECT_EQ(extension->url(),
+              extension_host->host_contents()->GetSiteInstance()->GetSiteURL());
+
+    processes.insert(extension_host->render_process_host()->GetID());
+  }
+
+  EXPECT_EQ(kNumExtensions, installed_extensions.size());
+
+  if (content::AreAllSitesIsolatedForTesting()) {
+    EXPECT_EQ(kNumExtensions, processes.size()) << "Extension process reuse is "
+                                                   "expected to be disabled in "
+                                                   "--site-per-process.";
+  } else {
+    EXPECT_LT(processes.size(), kNumExtensions)
+        << "Expected extension process reuse, but none happened.";
+  }
+
+  // Interact with each extension background page by setting and reading back
+  // the cookie. This would fail for one of the two extensions in a shared
+  // process, if that process is locked to a single origin. This is a regression
+  // test for http://crbug.com/600441.
+  for (const Extension* extension : installed_extensions) {
+    content::DOMMessageQueue queue;
+    ExecuteScriptInBackgroundPageNoWait(
+        extension->id(),
+        "document.cookie = 'extension_cookie';"
+        "window.domAutomationController.send(document.cookie);");
+    std::string message;
+    ASSERT_TRUE(queue.WaitForMessage(&message));
+    EXPECT_EQ(message, "\"extension_cookie\"");
+  }
+}
+
 }  // namespace extensions