Home | History | Annotate | Download | only in frame_host
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <set>
      6 
      7 #include "base/json/json_reader.h"
      8 #include "base/memory/ref_counted.h"
      9 #include "base/path_service.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "base/values.h"
     12 #include "content/browser/child_process_security_policy_impl.h"
     13 #include "content/browser/renderer_host/render_view_host_impl.h"
     14 #include "content/browser/site_instance_impl.h"
     15 #include "content/browser/web_contents/web_contents_impl.h"
     16 #include "content/browser/webui/web_ui_impl.h"
     17 #include "content/common/content_constants_internal.h"
     18 #include "content/public/browser/navigation_controller.h"
     19 #include "content/public/browser/navigation_entry.h"
     20 #include "content/public/browser/notification_details.h"
     21 #include "content/public/browser/notification_observer.h"
     22 #include "content/public/browser/notification_registrar.h"
     23 #include "content/public/browser/notification_types.h"
     24 #include "content/public/browser/render_process_host.h"
     25 #include "content/public/browser/web_contents.h"
     26 #include "content/public/browser/web_contents_observer.h"
     27 #include "content/public/common/url_constants.h"
     28 #include "content/public/test/browser_test_utils.h"
     29 #include "content/public/test/test_navigation_observer.h"
     30 #include "content/public/test/test_utils.h"
     31 #include "content/shell/browser/shell.h"
     32 #include "content/test/content_browser_test.h"
     33 #include "content/test/content_browser_test_utils.h"
     34 #include "net/base/net_util.h"
     35 #include "net/test/spawned_test_server/spawned_test_server.h"
     36 
     37 namespace content {
     38 
     39 class RenderFrameHostManagerTest : public ContentBrowserTest {
     40  public:
     41   RenderFrameHostManagerTest() {}
     42 
     43   static bool GetFilePathWithHostAndPortReplacement(
     44       const std::string& original_file_path,
     45       const net::HostPortPair& host_port_pair,
     46       std::string* replacement_path) {
     47     std::vector<net::SpawnedTestServer::StringPair> replacement_text;
     48     replacement_text.push_back(
     49         make_pair("REPLACE_WITH_HOST_AND_PORT", host_port_pair.ToString()));
     50     return net::SpawnedTestServer::GetFilePathWithReplacements(
     51         original_file_path, replacement_text, replacement_path);
     52   }
     53 };
     54 
     55 // Web pages should not have script access to the swapped out page.
     56 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
     57                        DISABLED_NoScriptAccessAfterSwapOut) {
     58   // Start two servers with different sites.
     59   ASSERT_TRUE(test_server()->Start());
     60   net::SpawnedTestServer https_server(
     61       net::SpawnedTestServer::TYPE_HTTPS,
     62       net::SpawnedTestServer::kLocalhost,
     63       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
     64   ASSERT_TRUE(https_server.Start());
     65 
     66   // Load a page with links that open in a new window.
     67   std::string replacement_path;
     68   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
     69       "files/click-noreferrer-links.html",
     70       https_server.host_port_pair(),
     71       &replacement_path));
     72   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
     73 
     74   // Get the original SiteInstance for later comparison.
     75   scoped_refptr<SiteInstance> orig_site_instance(
     76       shell()->web_contents()->GetSiteInstance());
     77   EXPECT_TRUE(orig_site_instance.get() != NULL);
     78 
     79   // Open a same-site link in a new window.
     80   ShellAddedObserver new_shell_observer;
     81   bool success = false;
     82   EXPECT_TRUE(ExecuteScriptAndExtractBool(
     83       shell()->web_contents(),
     84       "window.domAutomationController.send(clickSameSiteTargetedLink());",
     85       &success));
     86   EXPECT_TRUE(success);
     87   Shell* new_shell = new_shell_observer.GetShell();
     88 
     89   // Wait for the navigation in the new window to finish, if it hasn't.
     90   WaitForLoadStop(new_shell->web_contents());
     91   EXPECT_EQ("/files/navigate_opener.html",
     92             new_shell->web_contents()->GetLastCommittedURL().path());
     93 
     94   // Should have the same SiteInstance.
     95   scoped_refptr<SiteInstance> blank_site_instance(
     96       new_shell->web_contents()->GetSiteInstance());
     97   EXPECT_EQ(orig_site_instance, blank_site_instance);
     98 
     99   // We should have access to the opened window's location.
    100   success = false;
    101   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    102       shell()->web_contents(),
    103       "window.domAutomationController.send(testScriptAccessToWindow());",
    104       &success));
    105   EXPECT_TRUE(success);
    106 
    107   // Now navigate the new window to a different site.
    108   NavigateToURL(new_shell, https_server.GetURL("files/title1.html"));
    109   scoped_refptr<SiteInstance> new_site_instance(
    110       new_shell->web_contents()->GetSiteInstance());
    111   EXPECT_NE(orig_site_instance, new_site_instance);
    112 
    113   // We should no longer have script access to the opened window's location.
    114   success = false;
    115   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    116       shell()->web_contents(),
    117       "window.domAutomationController.send(testScriptAccessToWindow());",
    118       &success));
    119   EXPECT_FALSE(success);
    120 }
    121 
    122 // Test for crbug.com/24447.  Following a cross-site link with rel=noreferrer
    123 // and target=_blank should create a new SiteInstance.
    124 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
    125                        SwapProcessWithRelNoreferrerAndTargetBlank) {
    126   // Start two servers with different sites.
    127   ASSERT_TRUE(test_server()->Start());
    128   net::SpawnedTestServer https_server(
    129       net::SpawnedTestServer::TYPE_HTTPS,
    130       net::SpawnedTestServer::kLocalhost,
    131       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    132   ASSERT_TRUE(https_server.Start());
    133 
    134   // Load a page with links that open in a new window.
    135   std::string replacement_path;
    136   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    137       "files/click-noreferrer-links.html",
    138       https_server.host_port_pair(),
    139       &replacement_path));
    140   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    141 
    142   // Get the original SiteInstance for later comparison.
    143   scoped_refptr<SiteInstance> orig_site_instance(
    144       shell()->web_contents()->GetSiteInstance());
    145   EXPECT_TRUE(orig_site_instance.get() != NULL);
    146 
    147   // Test clicking a rel=noreferrer + target=blank link.
    148   ShellAddedObserver new_shell_observer;
    149   bool success = false;
    150   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    151       shell()->web_contents(),
    152       "window.domAutomationController.send(clickNoRefTargetBlankLink());",
    153       &success));
    154   EXPECT_TRUE(success);
    155 
    156   // Wait for the window to open.
    157   Shell* new_shell = new_shell_observer.GetShell();
    158 
    159   EXPECT_EQ("/files/title2.html",
    160             new_shell->web_contents()->GetVisibleURL().path());
    161 
    162   // Wait for the cross-site transition in the new tab to finish.
    163   WaitForLoadStop(new_shell->web_contents());
    164   WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
    165       new_shell->web_contents());
    166   EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->
    167       pending_render_view_host());
    168 
    169   // Should have a new SiteInstance.
    170   scoped_refptr<SiteInstance> noref_blank_site_instance(
    171       new_shell->web_contents()->GetSiteInstance());
    172   EXPECT_NE(orig_site_instance, noref_blank_site_instance);
    173 }
    174 
    175 // As of crbug.com/69267, we create a new BrowsingInstance (and SiteInstance)
    176 // for rel=noreferrer links in new windows, even to same site pages and named
    177 // targets.
    178 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
    179                        SwapProcessWithSameSiteRelNoreferrer) {
    180   // Start two servers with different sites.
    181   ASSERT_TRUE(test_server()->Start());
    182   net::SpawnedTestServer https_server(
    183       net::SpawnedTestServer::TYPE_HTTPS,
    184       net::SpawnedTestServer::kLocalhost,
    185       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    186   ASSERT_TRUE(https_server.Start());
    187 
    188   // Load a page with links that open in a new window.
    189   std::string replacement_path;
    190   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    191       "files/click-noreferrer-links.html",
    192       https_server.host_port_pair(),
    193       &replacement_path));
    194   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    195 
    196   // Get the original SiteInstance for later comparison.
    197   scoped_refptr<SiteInstance> orig_site_instance(
    198       shell()->web_contents()->GetSiteInstance());
    199   EXPECT_TRUE(orig_site_instance.get() != NULL);
    200 
    201   // Test clicking a same-site rel=noreferrer + target=foo link.
    202   ShellAddedObserver new_shell_observer;
    203   bool success = false;
    204   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    205       shell()->web_contents(),
    206       "window.domAutomationController.send(clickSameSiteNoRefTargetedLink());",
    207       &success));
    208   EXPECT_TRUE(success);
    209 
    210   // Wait for the window to open.
    211   Shell* new_shell = new_shell_observer.GetShell();
    212 
    213   // Opens in new window.
    214   EXPECT_EQ("/files/title2.html",
    215             new_shell->web_contents()->GetVisibleURL().path());
    216 
    217   // Wait for the cross-site transition in the new tab to finish.
    218   WaitForLoadStop(new_shell->web_contents());
    219   WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
    220       new_shell->web_contents());
    221   EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->
    222       pending_render_view_host());
    223 
    224   // Should have a new SiteInstance (in a new BrowsingInstance).
    225   scoped_refptr<SiteInstance> noref_blank_site_instance(
    226       new_shell->web_contents()->GetSiteInstance());
    227   EXPECT_NE(orig_site_instance, noref_blank_site_instance);
    228 }
    229 
    230 // Test for crbug.com/24447.  Following a cross-site link with just
    231 // target=_blank should not create a new SiteInstance.
    232 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
    233                        DontSwapProcessWithOnlyTargetBlank) {
    234   // Start two servers with different sites.
    235   ASSERT_TRUE(test_server()->Start());
    236   net::SpawnedTestServer https_server(
    237       net::SpawnedTestServer::TYPE_HTTPS,
    238       net::SpawnedTestServer::kLocalhost,
    239       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    240   ASSERT_TRUE(https_server.Start());
    241 
    242   // Load a page with links that open in a new window.
    243   std::string replacement_path;
    244   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    245       "files/click-noreferrer-links.html",
    246       https_server.host_port_pair(),
    247       &replacement_path));
    248   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    249 
    250   // Get the original SiteInstance for later comparison.
    251   scoped_refptr<SiteInstance> orig_site_instance(
    252       shell()->web_contents()->GetSiteInstance());
    253   EXPECT_TRUE(orig_site_instance.get() != NULL);
    254 
    255   // Test clicking a target=blank link.
    256   ShellAddedObserver new_shell_observer;
    257   bool success = false;
    258   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    259       shell()->web_contents(),
    260       "window.domAutomationController.send(clickTargetBlankLink());",
    261       &success));
    262   EXPECT_TRUE(success);
    263 
    264   // Wait for the window to open.
    265   Shell* new_shell = new_shell_observer.GetShell();
    266 
    267   // Wait for the cross-site transition in the new tab to finish.
    268   WaitForLoadStop(new_shell->web_contents());
    269   EXPECT_EQ("/files/title2.html",
    270             new_shell->web_contents()->GetLastCommittedURL().path());
    271 
    272   // Should have the same SiteInstance.
    273   scoped_refptr<SiteInstance> blank_site_instance(
    274       new_shell->web_contents()->GetSiteInstance());
    275   EXPECT_EQ(orig_site_instance, blank_site_instance);
    276 }
    277 
    278 // Test for crbug.com/24447.  Following a cross-site link with rel=noreferrer
    279 // and no target=_blank should not create a new SiteInstance.
    280 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
    281                        DontSwapProcessWithOnlyRelNoreferrer) {
    282   // Start two servers with different sites.
    283   ASSERT_TRUE(test_server()->Start());
    284   net::SpawnedTestServer https_server(
    285       net::SpawnedTestServer::TYPE_HTTPS,
    286       net::SpawnedTestServer::kLocalhost,
    287       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    288   ASSERT_TRUE(https_server.Start());
    289 
    290   // Load a page with links that open in a new window.
    291   std::string replacement_path;
    292   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    293       "files/click-noreferrer-links.html",
    294       https_server.host_port_pair(),
    295       &replacement_path));
    296   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    297 
    298   // Get the original SiteInstance for later comparison.
    299   scoped_refptr<SiteInstance> orig_site_instance(
    300       shell()->web_contents()->GetSiteInstance());
    301   EXPECT_TRUE(orig_site_instance.get() != NULL);
    302 
    303   // Test clicking a rel=noreferrer link.
    304   bool success = false;
    305   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    306       shell()->web_contents(),
    307       "window.domAutomationController.send(clickNoRefLink());",
    308       &success));
    309   EXPECT_TRUE(success);
    310 
    311   // Wait for the cross-site transition in the current tab to finish.
    312   WaitForLoadStop(shell()->web_contents());
    313 
    314   // Opens in same window.
    315   EXPECT_EQ(1u, Shell::windows().size());
    316   EXPECT_EQ("/files/title2.html",
    317             shell()->web_contents()->GetLastCommittedURL().path());
    318 
    319   // Should have the same SiteInstance.
    320   scoped_refptr<SiteInstance> noref_site_instance(
    321       shell()->web_contents()->GetSiteInstance());
    322   EXPECT_EQ(orig_site_instance, noref_site_instance);
    323 }
    324 
    325 // Test for crbug.com/116192.  Targeted links should still work after the
    326 // named target window has swapped processes.
    327 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
    328                        AllowTargetedNavigationsAfterSwap) {
    329   // Start two servers with different sites.
    330   ASSERT_TRUE(test_server()->Start());
    331   net::SpawnedTestServer https_server(
    332       net::SpawnedTestServer::TYPE_HTTPS,
    333       net::SpawnedTestServer::kLocalhost,
    334       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    335   ASSERT_TRUE(https_server.Start());
    336 
    337   // Load a page with links that open in a new window.
    338   std::string replacement_path;
    339   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    340       "files/click-noreferrer-links.html",
    341       https_server.host_port_pair(),
    342       &replacement_path));
    343   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    344 
    345   // Get the original SiteInstance for later comparison.
    346   scoped_refptr<SiteInstance> orig_site_instance(
    347       shell()->web_contents()->GetSiteInstance());
    348   EXPECT_TRUE(orig_site_instance.get() != NULL);
    349 
    350   // Test clicking a target=foo link.
    351   ShellAddedObserver new_shell_observer;
    352   bool success = false;
    353   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    354       shell()->web_contents(),
    355       "window.domAutomationController.send(clickSameSiteTargetedLink());",
    356       &success));
    357   EXPECT_TRUE(success);
    358   Shell* new_shell = new_shell_observer.GetShell();
    359 
    360   // Wait for the navigation in the new tab to finish, if it hasn't.
    361   WaitForLoadStop(new_shell->web_contents());
    362   EXPECT_EQ("/files/navigate_opener.html",
    363             new_shell->web_contents()->GetLastCommittedURL().path());
    364 
    365   // Should have the same SiteInstance.
    366   scoped_refptr<SiteInstance> blank_site_instance(
    367       new_shell->web_contents()->GetSiteInstance());
    368   EXPECT_EQ(orig_site_instance, blank_site_instance);
    369 
    370   // Now navigate the new tab to a different site.
    371   NavigateToURL(new_shell, https_server.GetURL("files/title1.html"));
    372   scoped_refptr<SiteInstance> new_site_instance(
    373       new_shell->web_contents()->GetSiteInstance());
    374   EXPECT_NE(orig_site_instance, new_site_instance);
    375 
    376   // Clicking the original link in the first tab should cause us to swap back.
    377   TestNavigationObserver navigation_observer(new_shell->web_contents());
    378   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    379       shell()->web_contents(),
    380       "window.domAutomationController.send(clickSameSiteTargetedLink());",
    381       &success));
    382   EXPECT_TRUE(success);
    383   navigation_observer.Wait();
    384 
    385   // Should have swapped back and shown the new window again.
    386   scoped_refptr<SiteInstance> revisit_site_instance(
    387       new_shell->web_contents()->GetSiteInstance());
    388   EXPECT_EQ(orig_site_instance, revisit_site_instance);
    389 
    390   // If it navigates away to another process, the original window should
    391   // still be able to close it (using a cross-process close message).
    392   NavigateToURL(new_shell, https_server.GetURL("files/title1.html"));
    393   EXPECT_EQ(new_site_instance,
    394             new_shell->web_contents()->GetSiteInstance());
    395   WebContentsDestroyedWatcher close_watcher(new_shell->web_contents());
    396   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    397       shell()->web_contents(),
    398       "window.domAutomationController.send(testCloseWindow());",
    399       &success));
    400   EXPECT_TRUE(success);
    401   close_watcher.Wait();
    402 }
    403 
    404 // Test that setting the opener to null in a window affects cross-process
    405 // navigations, including those to existing entries.  http://crbug.com/156669.
    406 // Flaky on windows: http://crbug.com/291249
    407 #if defined(OS_WIN)
    408 #define MAYBE_DisownOpener DISABLED_DisownOpener
    409 #else
    410 #define MAYBE_DisownOpener DisownOpener
    411 #endif
    412 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_DisownOpener) {
    413   // Start two servers with different sites.
    414   ASSERT_TRUE(test_server()->Start());
    415   net::SpawnedTestServer https_server(
    416       net::SpawnedTestServer::TYPE_HTTPS,
    417       net::SpawnedTestServer::kLocalhost,
    418       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    419   ASSERT_TRUE(https_server.Start());
    420 
    421   // Load a page with links that open in a new window.
    422   std::string replacement_path;
    423   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    424       "files/click-noreferrer-links.html",
    425       https_server.host_port_pair(),
    426       &replacement_path));
    427   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    428 
    429   // Get the original SiteInstance for later comparison.
    430   scoped_refptr<SiteInstance> orig_site_instance(
    431       shell()->web_contents()->GetSiteInstance());
    432   EXPECT_TRUE(orig_site_instance.get() != NULL);
    433 
    434   // Test clicking a target=_blank link.
    435   ShellAddedObserver new_shell_observer;
    436   bool success = false;
    437   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    438       shell()->web_contents(),
    439       "window.domAutomationController.send(clickSameSiteTargetBlankLink());",
    440       &success));
    441   EXPECT_TRUE(success);
    442   Shell* new_shell = new_shell_observer.GetShell();
    443 
    444   // Wait for the navigation in the new tab to finish, if it hasn't.
    445   WaitForLoadStop(new_shell->web_contents());
    446   EXPECT_EQ("/files/title2.html",
    447             new_shell->web_contents()->GetLastCommittedURL().path());
    448 
    449   // Should have the same SiteInstance.
    450   scoped_refptr<SiteInstance> blank_site_instance(
    451       new_shell->web_contents()->GetSiteInstance());
    452   EXPECT_EQ(orig_site_instance, blank_site_instance);
    453 
    454   // Now navigate the new tab to a different site.
    455   NavigateToURL(new_shell, https_server.GetURL("files/title1.html"));
    456   scoped_refptr<SiteInstance> new_site_instance(
    457       new_shell->web_contents()->GetSiteInstance());
    458   EXPECT_NE(orig_site_instance, new_site_instance);
    459 
    460   // Now disown the opener.
    461   EXPECT_TRUE(ExecuteScript(new_shell->web_contents(),
    462                             "window.opener = null;"));
    463 
    464   // Go back and ensure the opener is still null.
    465   {
    466     TestNavigationObserver back_nav_load_observer(new_shell->web_contents());
    467     new_shell->web_contents()->GetController().GoBack();
    468     back_nav_load_observer.Wait();
    469   }
    470   success = false;
    471   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    472       new_shell->web_contents(),
    473       "window.domAutomationController.send(window.opener == null);",
    474       &success));
    475   EXPECT_TRUE(success);
    476 
    477   // Now navigate forward again (creating a new process) and check opener.
    478   NavigateToURL(new_shell, https_server.GetURL("files/title1.html"));
    479   success = false;
    480   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    481       new_shell->web_contents(),
    482       "window.domAutomationController.send(window.opener == null);",
    483       &success));
    484   EXPECT_TRUE(success);
    485 }
    486 
    487 // Test that subframes can disown their openers.  http://crbug.com/225528.
    488 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, DisownSubframeOpener) {
    489   const GURL frame_url("data:text/html,<iframe name=\"foo\"></iframe>");
    490   NavigateToURL(shell(), frame_url);
    491 
    492   // Give the frame an opener using window.open.
    493   EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
    494                             "window.open('about:blank','foo');"));
    495 
    496   // Now disown the frame's opener.  Shouldn't crash.
    497   EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
    498                             "window.frames[0].opener = null;"));
    499 }
    500 
    501 // Test for crbug.com/99202.  PostMessage calls should still work after
    502 // navigating the source and target windows to different sites.
    503 // Specifically:
    504 // 1) Create 3 windows (opener, "foo", and _blank) and send "foo" cross-process.
    505 // 2) Fail to post a message from "foo" to opener with the wrong target origin.
    506 // 3) Post a message from "foo" to opener, which replies back to "foo".
    507 // 4) Post a message from _blank to "foo".
    508 // 5) Post a message from "foo" to a subframe of opener, which replies back.
    509 // 6) Post a message from _blank to a subframe of "foo".
    510 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
    511                        SupportCrossProcessPostMessage) {
    512   // Start two servers with different sites.
    513   ASSERT_TRUE(test_server()->Start());
    514   net::SpawnedTestServer https_server(
    515       net::SpawnedTestServer::TYPE_HTTPS,
    516       net::SpawnedTestServer::kLocalhost,
    517       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    518   ASSERT_TRUE(https_server.Start());
    519 
    520   // Load a page with links that open in a new window.
    521   std::string replacement_path;
    522   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    523       "files/click-noreferrer-links.html",
    524       https_server.host_port_pair(),
    525       &replacement_path));
    526   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    527 
    528   // Get the original SiteInstance and RVHM for later comparison.
    529   WebContents* opener_contents = shell()->web_contents();
    530   scoped_refptr<SiteInstance> orig_site_instance(
    531       opener_contents->GetSiteInstance());
    532   EXPECT_TRUE(orig_site_instance.get() != NULL);
    533   RenderFrameHostManager* opener_manager = static_cast<WebContentsImpl*>(
    534       opener_contents)->GetRenderManagerForTesting();
    535 
    536   // 1) Open two more windows, one named.  These initially have openers but no
    537   // reference to each other.  We will later post a message between them.
    538 
    539   // First, a named target=foo window.
    540   ShellAddedObserver new_shell_observer;
    541   bool success = false;
    542   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    543       opener_contents,
    544       "window.domAutomationController.send(clickSameSiteTargetedLink());",
    545       &success));
    546   EXPECT_TRUE(success);
    547   Shell* new_shell = new_shell_observer.GetShell();
    548 
    549   // Wait for the navigation in the new window to finish, if it hasn't, then
    550   // send it to post_message.html on a different site.
    551   WebContents* foo_contents = new_shell->web_contents();
    552   WaitForLoadStop(foo_contents);
    553   EXPECT_EQ("/files/navigate_opener.html",
    554             foo_contents->GetLastCommittedURL().path());
    555   NavigateToURL(new_shell, https_server.GetURL("files/post_message.html"));
    556   scoped_refptr<SiteInstance> foo_site_instance(
    557       foo_contents->GetSiteInstance());
    558   EXPECT_NE(orig_site_instance, foo_site_instance);
    559 
    560   // Second, a target=_blank window.
    561   ShellAddedObserver new_shell_observer2;
    562   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    563       shell()->web_contents(),
    564       "window.domAutomationController.send(clickSameSiteTargetBlankLink());",
    565       &success));
    566   EXPECT_TRUE(success);
    567 
    568   // Wait for the navigation in the new window to finish, if it hasn't, then
    569   // send it to post_message.html on the original site.
    570   Shell* new_shell2 = new_shell_observer2.GetShell();
    571   WebContents* new_contents = new_shell2->web_contents();
    572   WaitForLoadStop(new_contents);
    573   EXPECT_EQ("/files/title2.html", new_contents->GetLastCommittedURL().path());
    574   NavigateToURL(new_shell2, test_server()->GetURL("files/post_message.html"));
    575   EXPECT_EQ(orig_site_instance, new_contents->GetSiteInstance());
    576   RenderFrameHostManager* new_manager =
    577       static_cast<WebContentsImpl*>(new_contents)->GetRenderManagerForTesting();
    578 
    579   // We now have three windows.  The opener should have a swapped out RVH
    580   // for the new SiteInstance, but the _blank window should not.
    581   EXPECT_EQ(3u, Shell::windows().size());
    582   EXPECT_TRUE(
    583       opener_manager->GetSwappedOutRenderViewHost(foo_site_instance.get()));
    584   EXPECT_FALSE(
    585       new_manager->GetSwappedOutRenderViewHost(foo_site_instance.get()));
    586 
    587   // 2) Fail to post a message from the foo window to the opener if the target
    588   // origin is wrong.  We won't see an error, but we can check for the right
    589   // number of received messages below.
    590   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    591       foo_contents,
    592       "window.domAutomationController.send(postToOpener('msg',"
    593       "    'http://google.com'));",
    594       &success));
    595   EXPECT_TRUE(success);
    596   ASSERT_FALSE(
    597       opener_manager->GetSwappedOutRenderViewHost(orig_site_instance.get()));
    598 
    599   // 3) Post a message from the foo window to the opener.  The opener will
    600   // reply, causing the foo window to update its own title.
    601   base::string16 expected_title = ASCIIToUTF16("msg");
    602   TitleWatcher title_watcher(foo_contents, expected_title);
    603   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    604       foo_contents,
    605       "window.domAutomationController.send(postToOpener('msg','*'));",
    606       &success));
    607   EXPECT_TRUE(success);
    608   ASSERT_FALSE(
    609       opener_manager->GetSwappedOutRenderViewHost(orig_site_instance.get()));
    610   ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
    611 
    612   // We should have received only 1 message in the opener and "foo" tabs,
    613   // and updated the title.
    614   int opener_received_messages = 0;
    615   EXPECT_TRUE(ExecuteScriptAndExtractInt(
    616       opener_contents,
    617       "window.domAutomationController.send(window.receivedMessages);",
    618       &opener_received_messages));
    619   int foo_received_messages = 0;
    620   EXPECT_TRUE(ExecuteScriptAndExtractInt(
    621       foo_contents,
    622       "window.domAutomationController.send(window.receivedMessages);",
    623       &foo_received_messages));
    624   EXPECT_EQ(1, foo_received_messages);
    625   EXPECT_EQ(1, opener_received_messages);
    626   EXPECT_EQ(ASCIIToUTF16("msg"), foo_contents->GetTitle());
    627 
    628   // 4) Now post a message from the _blank window to the foo window.  The
    629   // foo window will update its title and will not reply.
    630   expected_title = ASCIIToUTF16("msg2");
    631   TitleWatcher title_watcher2(foo_contents, expected_title);
    632   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    633       new_contents,
    634       "window.domAutomationController.send(postToFoo('msg2'));",
    635       &success));
    636   EXPECT_TRUE(success);
    637   ASSERT_EQ(expected_title, title_watcher2.WaitAndGetTitle());
    638 
    639   // This postMessage should have created a swapped out RVH for the new
    640   // SiteInstance in the target=_blank window.
    641   EXPECT_TRUE(
    642       new_manager->GetSwappedOutRenderViewHost(foo_site_instance.get()));
    643 
    644   // TODO(nasko): Test subframe targeting of postMessage once
    645   // http://crbug.com/153701 is fixed.
    646 }
    647 
    648 // Test for crbug.com/278336. MessagePorts should work cross-process. I.e.,
    649 // messages which contain Transferables and get intercepted by
    650 // RenderViewImpl::willCheckAndDispatchMessageEvent (because the RenderView is
    651 // swapped out) should work.
    652 // Specifically:
    653 // 1) Create 2 windows (opener and "foo") and send "foo" cross-process.
    654 // 2) Post a message containing a message port from opener to "foo".
    655 // 3) Post a message from "foo" back to opener via the passed message port.
    656 // The test will be enabled when the feature implementation lands.
    657 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
    658                        SupportCrossProcessPostMessageWithMessagePort) {
    659   // Start two servers with different sites.
    660   ASSERT_TRUE(test_server()->Start());
    661   net::SpawnedTestServer https_server(
    662       net::SpawnedTestServer::TYPE_HTTPS,
    663       net::SpawnedTestServer::kLocalhost,
    664       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    665   ASSERT_TRUE(https_server.Start());
    666 
    667   // Load a page with links that open in a new window.
    668   std::string replacement_path;
    669   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    670       "files/click-noreferrer-links.html",
    671       https_server.host_port_pair(),
    672       &replacement_path));
    673   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    674 
    675   // Get the original SiteInstance and RVHM for later comparison.
    676   WebContents* opener_contents = shell()->web_contents();
    677   scoped_refptr<SiteInstance> orig_site_instance(
    678       opener_contents->GetSiteInstance());
    679   EXPECT_TRUE(orig_site_instance.get() != NULL);
    680   RenderFrameHostManager* opener_manager = static_cast<WebContentsImpl*>(
    681       opener_contents)->GetRenderManagerForTesting();
    682 
    683   // 1) Open a named target=foo window. We will later post a message between the
    684   // opener and the new window.
    685   ShellAddedObserver new_shell_observer;
    686   bool success = false;
    687   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    688       opener_contents,
    689       "window.domAutomationController.send(clickSameSiteTargetedLink());",
    690       &success));
    691   EXPECT_TRUE(success);
    692   Shell* new_shell = new_shell_observer.GetShell();
    693 
    694   // Wait for the navigation in the new window to finish, if it hasn't, then
    695   // send it to post_message.html on a different site.
    696   WebContents* foo_contents = new_shell->web_contents();
    697   WaitForLoadStop(foo_contents);
    698   EXPECT_EQ("/files/navigate_opener.html",
    699             foo_contents->GetLastCommittedURL().path());
    700   NavigateToURL(
    701       new_shell,
    702       https_server.GetURL("files/post_message.html"));
    703   scoped_refptr<SiteInstance> foo_site_instance(
    704       foo_contents->GetSiteInstance());
    705   EXPECT_NE(orig_site_instance, foo_site_instance);
    706 
    707   // We now have two windows. The opener should have a swapped out RVH
    708   // for the new SiteInstance.
    709   EXPECT_EQ(2u, Shell::windows().size());
    710   EXPECT_TRUE(
    711       opener_manager->GetSwappedOutRenderViewHost(foo_site_instance.get()));
    712 
    713   // 2) Post a message containing a MessagePort from opener to the the foo
    714   // window. The foo window will reply via the passed port, causing the opener
    715   // to update its own title.
    716   WindowedNotificationObserver title_observer(
    717       NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
    718       Source<WebContents>(opener_contents));
    719   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    720       opener_contents,
    721       "window.domAutomationController.send(postWithPortToFoo());",
    722       &success));
    723   EXPECT_TRUE(success);
    724   ASSERT_FALSE(
    725       opener_manager->GetSwappedOutRenderViewHost(orig_site_instance.get()));
    726   title_observer.Wait();
    727 
    728   // Check message counts.
    729   int opener_received_messages_via_port = 0;
    730   EXPECT_TRUE(ExecuteScriptAndExtractInt(
    731       opener_contents,
    732       "window.domAutomationController.send(window.receivedMessagesViaPort);",
    733       &opener_received_messages_via_port));
    734   int foo_received_messages = 0;
    735   EXPECT_TRUE(ExecuteScriptAndExtractInt(
    736       foo_contents,
    737       "window.domAutomationController.send(window.receivedMessages);",
    738       &foo_received_messages));
    739   int foo_received_messages_with_port = 0;
    740   EXPECT_TRUE(ExecuteScriptAndExtractInt(
    741       foo_contents,
    742       "window.domAutomationController.send(window.receivedMessagesWithPort);",
    743       &foo_received_messages_with_port));
    744   EXPECT_EQ(1, foo_received_messages);
    745   EXPECT_EQ(1, foo_received_messages_with_port);
    746   EXPECT_EQ(1, opener_received_messages_via_port);
    747   EXPECT_EQ(ASCIIToUTF16("msg-with-port"), foo_contents->GetTitle());
    748   EXPECT_EQ(ASCIIToUTF16("msg-back-via-port"), opener_contents->GetTitle());
    749 }
    750 
    751 // Test for crbug.com/116192.  Navigations to a window's opener should
    752 // still work after a process swap.
    753 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
    754                        AllowTargetedNavigationsInOpenerAfterSwap) {
    755   // Start two servers with different sites.
    756   ASSERT_TRUE(test_server()->Start());
    757   net::SpawnedTestServer https_server(
    758       net::SpawnedTestServer::TYPE_HTTPS,
    759       net::SpawnedTestServer::kLocalhost,
    760       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    761   ASSERT_TRUE(https_server.Start());
    762 
    763   // Load a page with links that open in a new window.
    764   std::string replacement_path;
    765   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    766       "files/click-noreferrer-links.html",
    767       https_server.host_port_pair(),
    768       &replacement_path));
    769   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    770 
    771   // Get the original tab and SiteInstance for later comparison.
    772   WebContents* orig_contents = shell()->web_contents();
    773   scoped_refptr<SiteInstance> orig_site_instance(
    774       orig_contents->GetSiteInstance());
    775   EXPECT_TRUE(orig_site_instance.get() != NULL);
    776 
    777   // Test clicking a target=foo link.
    778   ShellAddedObserver new_shell_observer;
    779   bool success = false;
    780   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    781       orig_contents,
    782       "window.domAutomationController.send(clickSameSiteTargetedLink());",
    783       &success));
    784   EXPECT_TRUE(success);
    785   Shell* new_shell = new_shell_observer.GetShell();
    786 
    787   // Wait for the navigation in the new window to finish, if it hasn't.
    788   WaitForLoadStop(new_shell->web_contents());
    789   EXPECT_EQ("/files/navigate_opener.html",
    790             new_shell->web_contents()->GetLastCommittedURL().path());
    791 
    792   // Should have the same SiteInstance.
    793   scoped_refptr<SiteInstance> blank_site_instance(
    794       new_shell->web_contents()->GetSiteInstance());
    795   EXPECT_EQ(orig_site_instance, blank_site_instance);
    796 
    797   // Now navigate the original (opener) tab to a different site.
    798   NavigateToURL(shell(), https_server.GetURL("files/title1.html"));
    799   scoped_refptr<SiteInstance> new_site_instance(
    800       shell()->web_contents()->GetSiteInstance());
    801   EXPECT_NE(orig_site_instance, new_site_instance);
    802 
    803   // The opened tab should be able to navigate the opener back to its process.
    804   TestNavigationObserver navigation_observer(orig_contents);
    805   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    806       new_shell->web_contents(),
    807       "window.domAutomationController.send(navigateOpener());",
    808       &success));
    809   EXPECT_TRUE(success);
    810   navigation_observer.Wait();
    811 
    812   // Should have swapped back into this process.
    813   scoped_refptr<SiteInstance> revisit_site_instance(
    814       shell()->web_contents()->GetSiteInstance());
    815   EXPECT_EQ(orig_site_instance, revisit_site_instance);
    816 }
    817 
    818 // Test that opening a new window in the same SiteInstance and then navigating
    819 // both windows to a different SiteInstance allows the first process to exit.
    820 // See http://crbug.com/126333.
    821 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
    822                        ProcessExitWithSwappedOutViews) {
    823   // Start two servers with different sites.
    824   ASSERT_TRUE(test_server()->Start());
    825   net::SpawnedTestServer https_server(
    826       net::SpawnedTestServer::TYPE_HTTPS,
    827       net::SpawnedTestServer::kLocalhost,
    828       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    829   ASSERT_TRUE(https_server.Start());
    830 
    831   // Load a page with links that open in a new window.
    832   std::string replacement_path;
    833   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    834       "files/click-noreferrer-links.html",
    835       https_server.host_port_pair(),
    836       &replacement_path));
    837   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    838 
    839   // Get the original SiteInstance for later comparison.
    840   scoped_refptr<SiteInstance> orig_site_instance(
    841       shell()->web_contents()->GetSiteInstance());
    842   EXPECT_TRUE(orig_site_instance.get() != NULL);
    843 
    844   // Test clicking a target=foo link.
    845   ShellAddedObserver new_shell_observer;
    846   bool success = false;
    847   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    848       shell()->web_contents(),
    849       "window.domAutomationController.send(clickSameSiteTargetedLink());",
    850       &success));
    851   EXPECT_TRUE(success);
    852   Shell* new_shell = new_shell_observer.GetShell();
    853 
    854   // Wait for the navigation in the new window to finish, if it hasn't.
    855   WaitForLoadStop(new_shell->web_contents());
    856   EXPECT_EQ("/files/navigate_opener.html",
    857             new_shell->web_contents()->GetLastCommittedURL().path());
    858 
    859   // Should have the same SiteInstance.
    860   scoped_refptr<SiteInstance> opened_site_instance(
    861       new_shell->web_contents()->GetSiteInstance());
    862   EXPECT_EQ(orig_site_instance, opened_site_instance);
    863 
    864   // Now navigate the opened window to a different site.
    865   NavigateToURL(new_shell, https_server.GetURL("files/title1.html"));
    866   scoped_refptr<SiteInstance> new_site_instance(
    867       new_shell->web_contents()->GetSiteInstance());
    868   EXPECT_NE(orig_site_instance, new_site_instance);
    869 
    870   // The original process should still be alive, since it is still used in the
    871   // first window.
    872   RenderProcessHost* orig_process = orig_site_instance->GetProcess();
    873   EXPECT_TRUE(orig_process->HasConnection());
    874 
    875   // Navigate the first window to a different site as well.  The original
    876   // process should exit, since all of its views are now swapped out.
    877   WindowedNotificationObserver exit_observer(
    878       NOTIFICATION_RENDERER_PROCESS_TERMINATED,
    879       Source<RenderProcessHost>(orig_process));
    880   NavigateToURL(shell(), https_server.GetURL("files/title1.html"));
    881   exit_observer.Wait();
    882   scoped_refptr<SiteInstance> new_site_instance2(
    883       shell()->web_contents()->GetSiteInstance());
    884   EXPECT_EQ(new_site_instance, new_site_instance2);
    885 }
    886 
    887 // Test for crbug.com/76666.  A cross-site navigation that fails with a 204
    888 // error should not make us ignore future renderer-initiated navigations.
    889 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ClickLinkAfter204Error) {
    890   // Start two servers with different sites.
    891   ASSERT_TRUE(test_server()->Start());
    892   net::SpawnedTestServer https_server(
    893       net::SpawnedTestServer::TYPE_HTTPS,
    894       net::SpawnedTestServer::kLocalhost,
    895       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
    896   ASSERT_TRUE(https_server.Start());
    897 
    898   // Load a page with links that open in a new window.
    899   // The links will point to the HTTPS server.
    900   std::string replacement_path;
    901   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
    902       "files/click-noreferrer-links.html",
    903       https_server.host_port_pair(),
    904       &replacement_path));
    905   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
    906 
    907   // Get the original SiteInstance for later comparison.
    908   scoped_refptr<SiteInstance> orig_site_instance(
    909       shell()->web_contents()->GetSiteInstance());
    910   EXPECT_TRUE(orig_site_instance.get() != NULL);
    911 
    912   // Load a cross-site page that fails with a 204 error.
    913   NavigateToURL(shell(), https_server.GetURL("nocontent"));
    914 
    915   // We should still be looking at the normal page.  The typed URL will
    916   // still be visible until the user clears it manually, but the last
    917   // committed URL will be the previous page.
    918   scoped_refptr<SiteInstance> post_nav_site_instance(
    919       shell()->web_contents()->GetSiteInstance());
    920   EXPECT_EQ(orig_site_instance, post_nav_site_instance);
    921   EXPECT_EQ("/nocontent",
    922             shell()->web_contents()->GetVisibleURL().path());
    923   EXPECT_EQ("/files/click-noreferrer-links.html",
    924             shell()->web_contents()->GetController().
    925                 GetLastCommittedEntry()->GetVirtualURL().path());
    926 
    927   // Renderer-initiated navigations should work.
    928   bool success = false;
    929   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    930       shell()->web_contents(),
    931       "window.domAutomationController.send(clickNoRefLink());",
    932       &success));
    933   EXPECT_TRUE(success);
    934 
    935   // Wait for the cross-site transition in the current tab to finish.
    936   WaitForLoadStop(shell()->web_contents());
    937 
    938   // Opens in same tab.
    939   EXPECT_EQ(1u, Shell::windows().size());
    940   EXPECT_EQ("/files/title2.html",
    941             shell()->web_contents()->GetLastCommittedURL().path());
    942 
    943   // Should have the same SiteInstance.
    944   scoped_refptr<SiteInstance> noref_site_instance(
    945       shell()->web_contents()->GetSiteInstance());
    946   EXPECT_EQ(orig_site_instance, noref_site_instance);
    947 }
    948 
    949 // Test for crbug.com/9682.  We should show the URL for a pending renderer-
    950 // initiated navigation in a new tab, until the content of the initial
    951 // about:blank page is modified by another window.  At that point, we should
    952 // revert to showing about:blank to prevent a URL spoof.
    953 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ShowLoadingURLUntilSpoof) {
    954   ASSERT_TRUE(test_server()->Start());
    955 
    956   // Load a page that can open a URL that won't commit in a new window.
    957   NavigateToURL(
    958       shell(), test_server()->GetURL("files/click-nocontent-link.html"));
    959   WebContents* orig_contents = shell()->web_contents();
    960 
    961   // Click a /nocontent link that opens in a new window but never commits.
    962   ShellAddedObserver new_shell_observer;
    963   bool success = false;
    964   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    965       orig_contents,
    966       "window.domAutomationController.send(clickNoContentTargetedLink());",
    967       &success));
    968   EXPECT_TRUE(success);
    969 
    970   // Wait for the window to open.
    971   Shell* new_shell = new_shell_observer.GetShell();
    972 
    973   // Ensure the destination URL is visible, because it is considered the
    974   // initial navigation.
    975   WebContents* contents = new_shell->web_contents();
    976   EXPECT_TRUE(contents->GetController().IsInitialNavigation());
    977   EXPECT_EQ("/nocontent",
    978             contents->GetController().GetVisibleEntry()->GetURL().path());
    979 
    980   // Now modify the contents of the new window from the opener.  This will also
    981   // modify the title of the document to give us something to listen for.
    982   base::string16 expected_title = ASCIIToUTF16("Modified Title");
    983   TitleWatcher title_watcher(contents, expected_title);
    984   success = false;
    985   EXPECT_TRUE(ExecuteScriptAndExtractBool(
    986       orig_contents,
    987       "window.domAutomationController.send(modifyNewWindow());",
    988       &success));
    989   EXPECT_TRUE(success);
    990   ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
    991 
    992   // At this point, we should no longer be showing the destination URL.
    993   // The visible entry should be null, resulting in about:blank in the address
    994   // bar.
    995   EXPECT_FALSE(contents->GetController().GetVisibleEntry());
    996 }
    997 
    998 // Test for crbug.com/9682.  We should not show the URL for a pending renderer-
    999 // initiated navigation in a new tab if it is not the initial navigation.  In
   1000 // this case, the renderer will not notify us of a modification, so we cannot
   1001 // show the pending URL without allowing a spoof.
   1002 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
   1003                        DontShowLoadingURLIfNotInitialNav) {
   1004   ASSERT_TRUE(test_server()->Start());
   1005 
   1006   // Load a page that can open a URL that won't commit in a new window.
   1007   NavigateToURL(
   1008       shell(), test_server()->GetURL("files/click-nocontent-link.html"));
   1009   WebContents* orig_contents = shell()->web_contents();
   1010 
   1011   // Click a /nocontent link that opens in a new window but never commits.
   1012   // By using an onclick handler that first creates the window, the slow
   1013   // navigation is not considered an initial navigation.
   1014   ShellAddedObserver new_shell_observer;
   1015   bool success = false;
   1016   EXPECT_TRUE(ExecuteScriptAndExtractBool(
   1017       orig_contents,
   1018       "window.domAutomationController.send("
   1019       "clickNoContentScriptedTargetedLink());",
   1020       &success));
   1021   EXPECT_TRUE(success);
   1022 
   1023   // Wait for the window to open.
   1024   Shell* new_shell = new_shell_observer.GetShell();
   1025 
   1026   // Ensure the destination URL is not visible, because it is not the initial
   1027   // navigation.
   1028   WebContents* contents = new_shell->web_contents();
   1029   EXPECT_FALSE(contents->GetController().IsInitialNavigation());
   1030   EXPECT_FALSE(contents->GetController().GetVisibleEntry());
   1031 }
   1032 
   1033 // Test for http://crbug.com/93427.  Ensure that cross-site navigations
   1034 // do not cause back/forward navigations to be considered stale by the
   1035 // renderer.
   1036 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, BackForwardNotStale) {
   1037   NavigateToURL(shell(), GURL(kAboutBlankURL));
   1038 
   1039   // Start two servers with different sites.
   1040   ASSERT_TRUE(test_server()->Start());
   1041   net::SpawnedTestServer https_server(
   1042       net::SpawnedTestServer::TYPE_HTTPS,
   1043       net::SpawnedTestServer::kLocalhost,
   1044       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   1045   ASSERT_TRUE(https_server.Start());
   1046 
   1047   // Visit a page on first site.
   1048   std::string replacement_path_a1;
   1049   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
   1050       "files/title1.html",
   1051       test_server()->host_port_pair(),
   1052       &replacement_path_a1));
   1053   NavigateToURL(shell(), test_server()->GetURL(replacement_path_a1));
   1054 
   1055   // Visit three pages on second site.
   1056   std::string replacement_path_b1;
   1057   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
   1058       "files/title1.html",
   1059       https_server.host_port_pair(),
   1060       &replacement_path_b1));
   1061   NavigateToURL(shell(), https_server.GetURL(replacement_path_b1));
   1062   std::string replacement_path_b2;
   1063   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
   1064       "files/title2.html",
   1065       https_server.host_port_pair(),
   1066       &replacement_path_b2));
   1067   NavigateToURL(shell(), https_server.GetURL(replacement_path_b2));
   1068   std::string replacement_path_b3;
   1069   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
   1070       "files/title3.html",
   1071       https_server.host_port_pair(),
   1072       &replacement_path_b3));
   1073   NavigateToURL(shell(), https_server.GetURL(replacement_path_b3));
   1074 
   1075   // History is now [blank, A1, B1, B2, *B3].
   1076   WebContents* contents = shell()->web_contents();
   1077   EXPECT_EQ(5, contents->GetController().GetEntryCount());
   1078 
   1079   // Open another window in same process to keep this process alive.
   1080   Shell* new_shell = CreateBrowser();
   1081   NavigateToURL(new_shell, https_server.GetURL(replacement_path_b1));
   1082 
   1083   // Go back three times to first site.
   1084   {
   1085     TestNavigationObserver back_nav_load_observer(shell()->web_contents());
   1086     shell()->web_contents()->GetController().GoBack();
   1087     back_nav_load_observer.Wait();
   1088   }
   1089   {
   1090     TestNavigationObserver back_nav_load_observer(shell()->web_contents());
   1091     shell()->web_contents()->GetController().GoBack();
   1092     back_nav_load_observer.Wait();
   1093   }
   1094   {
   1095     TestNavigationObserver back_nav_load_observer(shell()->web_contents());
   1096     shell()->web_contents()->GetController().GoBack();
   1097     back_nav_load_observer.Wait();
   1098   }
   1099 
   1100   // Now go forward twice to B2.  Shouldn't be left spinning.
   1101   {
   1102     TestNavigationObserver forward_nav_load_observer(shell()->web_contents());
   1103     shell()->web_contents()->GetController().GoForward();
   1104     forward_nav_load_observer.Wait();
   1105   }
   1106   {
   1107     TestNavigationObserver forward_nav_load_observer(shell()->web_contents());
   1108     shell()->web_contents()->GetController().GoForward();
   1109     forward_nav_load_observer.Wait();
   1110   }
   1111 
   1112   // Go back twice to first site.
   1113   {
   1114     TestNavigationObserver back_nav_load_observer(shell()->web_contents());
   1115     shell()->web_contents()->GetController().GoBack();
   1116     back_nav_load_observer.Wait();
   1117   }
   1118   {
   1119     TestNavigationObserver back_nav_load_observer(shell()->web_contents());
   1120     shell()->web_contents()->GetController().GoBack();
   1121     back_nav_load_observer.Wait();
   1122   }
   1123 
   1124   // Now go forward directly to B3.  Shouldn't be left spinning.
   1125   {
   1126     TestNavigationObserver forward_nav_load_observer(shell()->web_contents());
   1127     shell()->web_contents()->GetController().GoToIndex(4);
   1128     forward_nav_load_observer.Wait();
   1129   }
   1130 }
   1131 
   1132 // Test for http://crbug.com/130016.
   1133 // Swapping out a render view should update its visiblity state.
   1134 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
   1135                        SwappedOutViewHasCorrectVisibilityState) {
   1136   // Start two servers with different sites.
   1137   ASSERT_TRUE(test_server()->Start());
   1138   net::SpawnedTestServer https_server(
   1139       net::SpawnedTestServer::TYPE_HTTPS,
   1140       net::SpawnedTestServer::kLocalhost,
   1141       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   1142   ASSERT_TRUE(https_server.Start());
   1143 
   1144   // Load a page with links that open in a new window.
   1145   std::string replacement_path;
   1146   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
   1147       "files/click-noreferrer-links.html",
   1148       https_server.host_port_pair(),
   1149       &replacement_path));
   1150   NavigateToURL(shell(), test_server()->GetURL(replacement_path));
   1151 
   1152   // Open a same-site link in a new widnow.
   1153   ShellAddedObserver new_shell_observer;
   1154   bool success = false;
   1155   EXPECT_TRUE(ExecuteScriptAndExtractBool(
   1156       shell()->web_contents(),
   1157       "window.domAutomationController.send(clickSameSiteTargetedLink());",
   1158       &success));
   1159   EXPECT_TRUE(success);
   1160   Shell* new_shell = new_shell_observer.GetShell();
   1161 
   1162   // Wait for the navigation in the new tab to finish, if it hasn't.
   1163   WaitForLoadStop(new_shell->web_contents());
   1164   EXPECT_EQ("/files/navigate_opener.html",
   1165             new_shell->web_contents()->GetLastCommittedURL().path());
   1166 
   1167   RenderViewHost* rvh = new_shell->web_contents()->GetRenderViewHost();
   1168 
   1169   EXPECT_TRUE(ExecuteScriptAndExtractBool(
   1170       rvh,
   1171       "window.domAutomationController.send("
   1172       "    document.visibilityState == 'visible');",
   1173       &success));
   1174   EXPECT_TRUE(success);
   1175 
   1176   // Now navigate the new window to a different site. This should swap out the
   1177   // tab's existing RenderView, causing it become hidden.
   1178   NavigateToURL(new_shell, https_server.GetURL("files/title1.html"));
   1179 
   1180   EXPECT_TRUE(ExecuteScriptAndExtractBool(
   1181       rvh,
   1182       "window.domAutomationController.send("
   1183       "    document.visibilityState == 'hidden');",
   1184       &success));
   1185   EXPECT_TRUE(success);
   1186 
   1187   // Going back should make the previously swapped-out view to become visible
   1188   // again.
   1189   {
   1190     TestNavigationObserver back_nav_load_observer(new_shell->web_contents());
   1191     new_shell->web_contents()->GetController().GoBack();
   1192     back_nav_load_observer.Wait();
   1193   }
   1194 
   1195   EXPECT_EQ("/files/navigate_opener.html",
   1196             new_shell->web_contents()->GetLastCommittedURL().path());
   1197 
   1198   EXPECT_EQ(rvh, new_shell->web_contents()->GetRenderViewHost());
   1199 
   1200   EXPECT_TRUE(ExecuteScriptAndExtractBool(
   1201       rvh,
   1202       "window.domAutomationController.send("
   1203       "    document.visibilityState == 'visible');",
   1204       &success));
   1205   EXPECT_TRUE(success);
   1206 }
   1207 
   1208 // This class ensures that all the given RenderViewHosts have properly been
   1209 // shutdown.
   1210 class RenderViewHostDestructionObserver : public WebContentsObserver {
   1211  public:
   1212   explicit RenderViewHostDestructionObserver(WebContents* web_contents)
   1213       : WebContentsObserver(web_contents) {}
   1214   virtual ~RenderViewHostDestructionObserver() {}
   1215   void EnsureRVHGetsDestructed(RenderViewHost* rvh) {
   1216     watched_render_view_hosts_.insert(rvh);
   1217   }
   1218   size_t GetNumberOfWatchedRenderViewHosts() const {
   1219     return watched_render_view_hosts_.size();
   1220   }
   1221 
   1222  private:
   1223   // WebContentsObserver implementation:
   1224   virtual void RenderViewDeleted(RenderViewHost* rvh) OVERRIDE {
   1225     watched_render_view_hosts_.erase(rvh);
   1226   }
   1227 
   1228   std::set<RenderViewHost*> watched_render_view_hosts_;
   1229 };
   1230 
   1231 // Test for crbug.com/90867. Make sure we don't leak render view hosts since
   1232 // they may cause crashes or memory corruptions when trying to call dead
   1233 // delegate_. This test also verifies crbug.com/117420 and crbug.com/143255 to
   1234 // ensure that a separate SiteInstance is created when navigating to view-source
   1235 // URLs, regardless of current URL.
   1236 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, LeakingRenderViewHosts) {
   1237   // Start two servers with different sites.
   1238   ASSERT_TRUE(test_server()->Start());
   1239   net::SpawnedTestServer https_server(
   1240       net::SpawnedTestServer::TYPE_HTTPS,
   1241       net::SpawnedTestServer::kLocalhost,
   1242       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   1243   ASSERT_TRUE(https_server.Start());
   1244 
   1245   // Observe the created render_view_host's to make sure they will not leak.
   1246   RenderViewHostDestructionObserver rvh_observers(shell()->web_contents());
   1247 
   1248   GURL navigated_url(test_server()->GetURL("files/title2.html"));
   1249   GURL view_source_url(kViewSourceScheme + std::string(":") +
   1250                        navigated_url.spec());
   1251 
   1252   // Let's ensure that when we start with a blank window, navigating away to a
   1253   // view-source URL, we create a new SiteInstance.
   1254   RenderViewHost* blank_rvh = shell()->web_contents()->GetRenderViewHost();
   1255   SiteInstance* blank_site_instance = blank_rvh->GetSiteInstance();
   1256   EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), GURL::EmptyGURL());
   1257   EXPECT_EQ(blank_site_instance->GetSiteURL(), GURL::EmptyGURL());
   1258   rvh_observers.EnsureRVHGetsDestructed(blank_rvh);
   1259 
   1260   // Now navigate to the view-source URL and ensure we got a different
   1261   // SiteInstance and RenderViewHost.
   1262   NavigateToURL(shell(), view_source_url);
   1263   EXPECT_NE(blank_rvh, shell()->web_contents()->GetRenderViewHost());
   1264   EXPECT_NE(blank_site_instance, shell()->web_contents()->
   1265       GetRenderViewHost()->GetSiteInstance());
   1266   rvh_observers.EnsureRVHGetsDestructed(
   1267       shell()->web_contents()->GetRenderViewHost());
   1268 
   1269   // Load a random page and then navigate to view-source: of it.
   1270   // This used to cause two RVH instances for the same SiteInstance, which
   1271   // was a problem.  This is no longer the case.
   1272   NavigateToURL(shell(), navigated_url);
   1273   SiteInstance* site_instance1 = shell()->web_contents()->
   1274       GetRenderViewHost()->GetSiteInstance();
   1275   rvh_observers.EnsureRVHGetsDestructed(
   1276       shell()->web_contents()->GetRenderViewHost());
   1277 
   1278   NavigateToURL(shell(), view_source_url);
   1279   rvh_observers.EnsureRVHGetsDestructed(
   1280       shell()->web_contents()->GetRenderViewHost());
   1281   SiteInstance* site_instance2 = shell()->web_contents()->
   1282       GetRenderViewHost()->GetSiteInstance();
   1283 
   1284   // Ensure that view-source navigations force a new SiteInstance.
   1285   EXPECT_NE(site_instance1, site_instance2);
   1286 
   1287   // Now navigate to a different instance so that we swap out again.
   1288   NavigateToURL(shell(), https_server.GetURL("files/title2.html"));
   1289   rvh_observers.EnsureRVHGetsDestructed(
   1290       shell()->web_contents()->GetRenderViewHost());
   1291 
   1292   // This used to leak a render view host.
   1293   shell()->Close();
   1294 
   1295   RunAllPendingInMessageLoop();  // Needed on ChromeOS.
   1296 
   1297   EXPECT_EQ(0U, rvh_observers.GetNumberOfWatchedRenderViewHosts());
   1298 }
   1299 
   1300 // Test for crbug.com/143155.  Frame tree updates during unload should not
   1301 // interrupt the intended navigation and show swappedout:// instead.
   1302 // Specifically:
   1303 // 1) Open 2 tabs in an HTTP SiteInstance, with a subframe in the opener.
   1304 // 2) Send the second tab to a different HTTPS SiteInstance.
   1305 //    This creates a swapped out opener for the first tab in the HTTPS process.
   1306 // 3) Navigate the first tab to the HTTPS SiteInstance, and have the first
   1307 //    tab's unload handler remove its frame.
   1308 // This used to cause an update to the frame tree of the swapped out RV,
   1309 // just as it was navigating to a real page.  That pre-empted the real
   1310 // navigation and visibly sent the tab to swappedout://.
   1311 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
   1312                        DontPreemptNavigationWithFrameTreeUpdate) {
   1313   // Start two servers with different sites.
   1314   ASSERT_TRUE(test_server()->Start());
   1315   net::SpawnedTestServer https_server(
   1316       net::SpawnedTestServer::TYPE_HTTPS,
   1317       net::SpawnedTestServer::kLocalhost,
   1318       base::FilePath(FILE_PATH_LITERAL("content/test/data")));
   1319   ASSERT_TRUE(https_server.Start());
   1320 
   1321   // 1. Load a page that deletes its iframe during unload.
   1322   NavigateToURL(shell(),
   1323                 test_server()->GetURL("files/remove_frame_on_unload.html"));
   1324 
   1325   // Get the original SiteInstance for later comparison.
   1326   scoped_refptr<SiteInstance> orig_site_instance(
   1327       shell()->web_contents()->GetSiteInstance());
   1328 
   1329   // Open a same-site page in a new window.
   1330   ShellAddedObserver new_shell_observer;
   1331   bool success = false;
   1332   EXPECT_TRUE(ExecuteScriptAndExtractBool(
   1333       shell()->web_contents(),
   1334       "window.domAutomationController.send(openWindow());",
   1335       &success));
   1336   EXPECT_TRUE(success);
   1337   Shell* new_shell = new_shell_observer.GetShell();
   1338 
   1339   // Wait for the navigation in the new window to finish, if it hasn't.
   1340   WaitForLoadStop(new_shell->web_contents());
   1341   EXPECT_EQ("/files/title1.html",
   1342             new_shell->web_contents()->GetLastCommittedURL().path());
   1343 
   1344   // Should have the same SiteInstance.
   1345   EXPECT_EQ(orig_site_instance, new_shell->web_contents()->GetSiteInstance());
   1346 
   1347   // 2. Send the second tab to a different process.
   1348   NavigateToURL(new_shell, https_server.GetURL("files/title1.html"));
   1349   scoped_refptr<SiteInstance> new_site_instance(
   1350       new_shell->web_contents()->GetSiteInstance());
   1351   EXPECT_NE(orig_site_instance, new_site_instance);
   1352 
   1353   // 3. Send the first tab to the second tab's process.
   1354   NavigateToURL(shell(), https_server.GetURL("files/title1.html"));
   1355 
   1356   // Make sure it ends up at the right page.
   1357   WaitForLoadStop(shell()->web_contents());
   1358   EXPECT_EQ(https_server.GetURL("files/title1.html"),
   1359             shell()->web_contents()->GetLastCommittedURL());
   1360   EXPECT_EQ(new_site_instance, shell()->web_contents()->GetSiteInstance());
   1361 }
   1362 
   1363 // Ensure that renderer-side debug URLs do not cause a process swap, since they
   1364 // are meant to run in the current page.  We had a bug where we expected a
   1365 // BrowsingInstance swap to occur on pages like view-source and extensions,
   1366 // which broke chrome://crash and javascript: URLs.
   1367 // See http://crbug.com/335503.
   1368 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, RendererDebugURLsDontSwap) {
   1369   ASSERT_TRUE(test_server()->Start());
   1370 
   1371   GURL original_url(test_server()->GetURL("files/title2.html"));
   1372   GURL view_source_url(kViewSourceScheme + std::string(":") +
   1373                        original_url.spec());
   1374 
   1375   NavigateToURL(shell(), view_source_url);
   1376 
   1377   // Check that javascript: URLs work.
   1378   base::string16 expected_title = ASCIIToUTF16("msg");
   1379   TitleWatcher title_watcher(shell()->web_contents(), expected_title);
   1380   shell()->LoadURL(GURL("javascript:document.title='msg'"));
   1381   ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
   1382 
   1383   // Crash the renderer of the view-source page.
   1384   RenderProcessHost* process = shell()->web_contents()->GetRenderProcessHost();
   1385   WindowedNotificationObserver crash_observer(
   1386       NOTIFICATION_RENDERER_PROCESS_CLOSED,
   1387       Source<RenderProcessHost>(process));
   1388   NavigateToURL(shell(), GURL(kChromeUICrashURL));
   1389   crash_observer.Wait();
   1390 }
   1391 
   1392 // Ensure that renderer-side debug URLs don't take effect on crashed renderers.
   1393 // Otherwise, we might try to load an unprivileged about:blank page into a
   1394 // WebUI-enabled RenderProcessHost, failing a safety check in InitRenderView.
   1395 // See http://crbug.com/334214.
   1396 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
   1397                        IgnoreRendererDebugURLsWhenCrashed) {
   1398   // Visit a WebUI page with bindings.
   1399   GURL webui_url = GURL(std::string(chrome::kChromeUIScheme) + "://" +
   1400                         std::string(kChromeUIGpuHost));
   1401   NavigateToURL(shell(), webui_url);
   1402   RenderProcessHost* process = shell()->web_contents()->GetRenderProcessHost();
   1403   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
   1404                   process->GetID()));
   1405 
   1406   // Crash the renderer of the WebUI page.
   1407   WindowedNotificationObserver crash_observer(
   1408       NOTIFICATION_RENDERER_PROCESS_CLOSED,
   1409       Source<RenderProcessHost>(process));
   1410   NavigateToURL(shell(), GURL(kChromeUICrashURL));
   1411   crash_observer.Wait();
   1412 
   1413   // Load the crash URL again but don't wait for any action.  If it is not
   1414   // ignored this time, we will fail the WebUI CHECK in InitRenderView.
   1415   shell()->LoadURL(GURL(kChromeUICrashURL));
   1416 
   1417   // Ensure that such URLs can still work as the initial navigation of a tab.
   1418   // We postpone the initial navigation of the tab using an empty GURL, so that
   1419   // we can add a watcher for crashes.
   1420   Shell* shell2 = Shell::CreateNewWindow(
   1421       shell()->web_contents()->GetBrowserContext(), GURL(), NULL,
   1422       MSG_ROUTING_NONE, gfx::Size());
   1423   RenderProcessHost* process2 = shell2->web_contents()->GetRenderProcessHost();
   1424   WindowedNotificationObserver crash_observer2(
   1425       NOTIFICATION_RENDERER_PROCESS_CLOSED,
   1426       Source<RenderProcessHost>(process2));
   1427   NavigateToURL(shell2, GURL(kChromeUIKillURL));
   1428   crash_observer2.Wait();
   1429 }
   1430 
   1431 // Ensure that pending_and_current_web_ui_ is cleared when a URL commits.
   1432 // Otherwise it might get picked up by InitRenderView when granting bindings
   1433 // to other RenderViewHosts.  See http://crbug.com/330811.
   1434 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, ClearPendingWebUIOnCommit) {
   1435   // Visit a WebUI page with bindings.
   1436   GURL webui_url(GURL(std::string(chrome::kChromeUIScheme) + "://" +
   1437                       std::string(kChromeUIGpuHost)));
   1438   NavigateToURL(shell(), webui_url);
   1439   EXPECT_TRUE(ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
   1440                   shell()->web_contents()->GetRenderProcessHost()->GetID()));
   1441   WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
   1442       shell()->web_contents());
   1443   WebUIImpl* webui = web_contents->GetRenderManagerForTesting()->web_ui();
   1444   EXPECT_TRUE(webui);
   1445   EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->pending_web_ui());
   1446 
   1447   // Navigate to another WebUI URL that reuses the WebUI object.  Make sure we
   1448   // clear pending_web_ui() when it commits.
   1449   GURL webui_url2(webui_url.spec() + "#foo");
   1450   NavigateToURL(shell(), webui_url2);
   1451   EXPECT_EQ(webui, web_contents->GetRenderManagerForTesting()->web_ui());
   1452   EXPECT_FALSE(web_contents->GetRenderManagerForTesting()->pending_web_ui());
   1453 }
   1454 
   1455 }  // namespace content
   1456