Isolating Chrome Web Store app in the transfer (i.e. non-OpenURL) path.

BUG=652708

Review-Url: https://codereview.chromium.org/2400523002
Cr-Commit-Position: refs/heads/master@{#423360}
diff --git a/chrome/browser/extensions/process_management_browsertest.cc b/chrome/browser/extensions/process_management_browsertest.cc
index 759b2305..4adbd2f 100644
--- a/chrome/browser/extensions/process_management_browsertest.cc
+++ b/chrome/browser/extensions/process_management_browsertest.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_process_policy.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -24,6 +25,7 @@
 #include "content/public/test/test_navigation_observer.h"
 #include "extensions/browser/extension_host.h"
 #include "extensions/browser/process_manager.h"
+#include "extensions/browser/process_map.h"
 #include "extensions/common/switches.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -43,6 +45,29 @@
   }
 };
 
+class ChromeWebStoreProcessTest : public ExtensionBrowserTest {
+ public:
+  const GURL& gallery_url() { return gallery_url_; }
+
+ private:
+  // Overrides location of Chrome Web Store gallery to a test controlled URL.
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ExtensionBrowserTest::SetUpCommandLine(command_line);
+
+    ASSERT_TRUE(embedded_test_server()->Start());
+    gallery_url_ =
+        embedded_test_server()->GetURL("chrome.webstore.test.com", "/");
+    command_line->AppendSwitchASCII(switches::kAppsGalleryURL,
+                                    gallery_url_.spec());
+  }
+
+  void SetUpOnMainThread() override {
+    host_resolver()->AddRule("*", "127.0.0.1");
+  }
+
+  GURL gallery_url_;
+};
+
 }  // namespace
 
 
@@ -302,3 +327,55 @@
     EXPECT_NE(old_process_host, new_process_host);
   }
 }
+
+IN_PROC_BROWSER_TEST_F(ChromeWebStoreProcessTest,
+                       NavigateWebTabToChromeWebStoreViaPost) {
+  // Navigate a tab to a web page with a form.
+  GURL web_url = embedded_test_server()->GetURL("foo.com", "/form.html");
+  ui_test_utils::NavigateToURL(browser(), web_url);
+  WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  EXPECT_EQ(web_url, web_contents->GetLastCommittedURL());
+  content::RenderProcessHost* old_process_host =
+      web_contents->GetMainFrame()->GetProcess();
+
+  // Calculate an URL that is 1) relative to the fake (i.e. test-controlled)
+  // Chrome Web Store gallery URL and 2) resolves to something that
+  // embedded_test_server can actually serve (e.g. title1.html test file).
+  GURL::Replacements replace_path;
+  replace_path.SetPathStr("/title1.html");
+  GURL cws_web_url = gallery_url().ReplaceComponents(replace_path);
+
+  // Note that the |setTimeout| call below is needed to make sure
+  // ExecuteScriptAndExtractBool returns *after* a scheduled navigation has
+  // already started.
+  std::string navigation_starting_script =
+      "var form = document.getElementById('form');\n"
+      "form.action = '" + cws_web_url.spec() + "';\n"
+      "form.submit();\n"
+      "setTimeout(\n"
+      "    function() { window.domAutomationController.send(true); },\n"
+      "    0);\n";
+
+  // Trigger a renderer-initiated POST navigation (via the form) to a Chrome Web
+  // Store gallery URL (which will commit into a chrome-extension://cws-app-id).
+  bool ignored_script_result = false;
+  content::TestNavigationObserver nav_observer(web_contents, 1);
+  EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+      web_contents, navigation_starting_script, &ignored_script_result));
+
+  // Verify that the navigation succeeded.
+  nav_observer.Wait();
+  EXPECT_EQ(cws_web_url, web_contents->GetLastCommittedURL());
+
+  // Verify that we really have the Chrome Web Store app loaded in the Web
+  // Contents.
+  content::RenderProcessHost* new_process_host =
+      web_contents->GetMainFrame()->GetProcess();
+  EXPECT_TRUE(extensions::ProcessMap::Get(profile())->Contains(
+      extensions::kWebStoreAppId, new_process_host->GetID()));
+
+  // Verify that Chrome Web Store is isolated in a separate renderer process.
+  if (extensions::IsIsolateExtensionsEnabled())
+    EXPECT_NE(old_process_host, new_process_host);
+}