OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/command_line.h" | 5 #include "base/command_line.h" |
6 #include "base/files/file_path.h" | 6 #include "base/files/file_path.h" |
7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
8 #include "base/test/histogram_tester.h" | 8 #include "base/test/histogram_tester.h" |
9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
10 #include "content/browser/frame_host/cross_site_transferring_request.h" | 10 #include "content/browser/frame_host/cross_site_transferring_request.h" |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 // PlzNavigate: returns the speculative RenderFrameHost. | 394 // PlzNavigate: returns the speculative RenderFrameHost. |
395 RenderFrameHostImpl* GetPendingFrameHost( | 395 RenderFrameHostImpl* GetPendingFrameHost( |
396 RenderFrameHostManager* manager) { | 396 RenderFrameHostManager* manager) { |
397 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 397 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
398 switches::kEnableBrowserSideNavigation)) { | 398 switches::kEnableBrowserSideNavigation)) { |
399 return manager->speculative_render_frame_host_.get(); | 399 return manager->speculative_render_frame_host_.get(); |
400 } | 400 } |
401 return manager->pending_frame_host(); | 401 return manager->pending_frame_host(); |
402 } | 402 } |
403 | 403 |
| 404 void CrashFrame(TestRenderFrameHost* frame) { |
| 405 // TODO(nick): Standardize how we simulate crashes in content unittests. The |
| 406 // test method |set_render_view_created| should probably be eliminated |
| 407 // altogether, and maybe there should be a CrashProcess() method on |
| 408 // MockRenderProcessHost. |
| 409 ASSERT_TRUE(frame->IsRenderFrameLive()); |
| 410 frame->OnMessageReceived(FrameHostMsg_RenderProcessGone( |
| 411 0, base::TERMINATION_STATUS_PROCESS_CRASHED, -1)); |
| 412 RenderProcessHost::RendererClosedDetails details( |
| 413 base::TERMINATION_STATUS_PROCESS_CRASHED, 0); |
| 414 NotificationService::current()->Notify( |
| 415 NOTIFICATION_RENDERER_PROCESS_CLOSED, |
| 416 Source<RenderProcessHost>(frame->GetProcess()), |
| 417 Details<RenderProcessHost::RendererClosedDetails>(&details)); |
| 418 frame->GetRenderViewHost()->set_render_view_created(false); |
| 419 ASSERT_FALSE(frame->IsRenderFrameLive()); |
| 420 } |
| 421 |
404 private: | 422 private: |
405 RenderFrameHostManagerTestWebUIControllerFactory factory_; | 423 RenderFrameHostManagerTestWebUIControllerFactory factory_; |
406 }; | 424 }; |
407 | 425 |
408 // Tests that when you navigate from a chrome:// url to another page, and | 426 // Tests that when you navigate from a chrome:// url to another page, and |
409 // then do that same thing in another tab, that the two resulting pages have | 427 // then do that same thing in another tab, that the two resulting pages have |
410 // different SiteInstances, BrowsingInstances, and RenderProcessHosts. This is | 428 // different SiteInstances, BrowsingInstances, and RenderProcessHosts. This is |
411 // a regression test for bug 9364. | 429 // a regression test for bug 9364. |
412 TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) { | 430 TEST_F(RenderFrameHostManagerTest, NewTabPageProcesses) { |
413 set_should_create_webui(true); | 431 set_should_create_webui(true); |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
956 RenderFrameHostImpl* host = GetFrameHostForNavigation(manager, entry); | 974 RenderFrameHostImpl* host = GetFrameHostForNavigation(manager, entry); |
957 | 975 |
958 // We commit the pending RenderFrameHost immediately because the previous | 976 // We commit the pending RenderFrameHost immediately because the previous |
959 // RenderFrameHost was not live. We test a case where it is live in | 977 // RenderFrameHost was not live. We test a case where it is live in |
960 // WebUIInNewTab. | 978 // WebUIInNewTab. |
961 EXPECT_TRUE(host); | 979 EXPECT_TRUE(host); |
962 EXPECT_NE(initial_rfh, host); | 980 EXPECT_NE(initial_rfh, host); |
963 EXPECT_EQ(host, manager->current_frame_host()); | 981 EXPECT_EQ(host, manager->current_frame_host()); |
964 EXPECT_FALSE(GetPendingFrameHost(manager)); | 982 EXPECT_FALSE(GetPendingFrameHost(manager)); |
965 | 983 |
966 // It's important that the site instance get set on the Web UI page as soon | 984 // It's important that the SiteInstance get set on the Web UI page as soon |
967 // as the navigation starts, rather than lazily after it commits, so we don't | 985 // as the navigation starts, rather than lazily after it commits, so we don't |
968 // try to re-use the SiteInstance/process for non Web UI things that may | 986 // try to re-use the SiteInstance/process for non Web UI things that may |
969 // get loaded in between. | 987 // get loaded in between. |
970 EXPECT_TRUE(host->GetSiteInstance()->HasSite()); | 988 EXPECT_TRUE(host->GetSiteInstance()->HasSite()); |
971 EXPECT_EQ(kUrl, host->GetSiteInstance()->GetSiteURL()); | 989 EXPECT_EQ(kUrl, host->GetSiteInstance()->GetSiteURL()); |
972 | 990 |
973 // The Web UI is committed immediately because the RenderViewHost has not been | 991 // The Web UI is committed immediately because the RenderViewHost has not been |
974 // used yet. UpdateStateForNavigate() took the short cut path. | 992 // used yet. UpdateStateForNavigate() took the short cut path. |
975 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 993 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
976 switches::kEnableBrowserSideNavigation)) { | 994 switches::kEnableBrowserSideNavigation)) { |
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1394 } | 1412 } |
1395 | 1413 |
1396 // Test that we clean up swapped out RenderViewHosts when a process hosting | 1414 // Test that we clean up swapped out RenderViewHosts when a process hosting |
1397 // those associated RenderViews crashes. http://crbug.com/258993 | 1415 // those associated RenderViews crashes. http://crbug.com/258993 |
1398 TEST_F(RenderFrameHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) { | 1416 TEST_F(RenderFrameHostManagerTest, CleanUpSwappedOutRVHOnProcessCrash) { |
1399 const GURL kUrl1("http://www.google.com/"); | 1417 const GURL kUrl1("http://www.google.com/"); |
1400 const GURL kUrl2("http://www.chromium.org/"); | 1418 const GURL kUrl2("http://www.chromium.org/"); |
1401 | 1419 |
1402 // Navigate to an initial URL. | 1420 // Navigate to an initial URL. |
1403 contents()->NavigateAndCommit(kUrl1); | 1421 contents()->NavigateAndCommit(kUrl1); |
1404 TestRenderViewHost* rvh1 = test_rvh(); | 1422 TestRenderFrameHost* rfh1 = contents()->GetMainFrame(); |
1405 | 1423 |
1406 // Create a new tab as an opener for the main tab. | 1424 // Create a new tab as an opener for the main tab. |
1407 scoped_ptr<TestWebContents> opener1( | 1425 scoped_ptr<TestWebContents> opener1( |
1408 TestWebContents::Create(browser_context(), rvh1->GetSiteInstance())); | 1426 TestWebContents::Create(browser_context(), rfh1->GetSiteInstance())); |
1409 RenderFrameHostManager* opener1_manager = | 1427 RenderFrameHostManager* opener1_manager = |
1410 opener1->GetRenderManagerForTesting(); | 1428 opener1->GetRenderManagerForTesting(); |
1411 contents()->SetOpener(opener1.get()); | 1429 contents()->SetOpener(opener1.get()); |
1412 | 1430 |
1413 // Make sure the new opener RVH is considered live. | 1431 // Make sure the new opener RVH is considered live. |
1414 opener1_manager->current_host()->CreateRenderView( | 1432 opener1_manager->current_host()->CreateRenderView( |
1415 base::string16(), -1, MSG_ROUTING_NONE, -1, false); | 1433 base::string16(), -1, MSG_ROUTING_NONE, -1, false); |
1416 EXPECT_TRUE(opener1_manager->current_host()->IsRenderViewLive()); | 1434 EXPECT_TRUE(opener1_manager->current_host()->IsRenderViewLive()); |
1417 EXPECT_TRUE(opener1_manager->current_frame_host()->IsRenderFrameLive()); | 1435 EXPECT_TRUE(opener1_manager->current_frame_host()->IsRenderFrameLive()); |
1418 | 1436 |
1419 // Use a cross-process navigation in the opener to swap out the old RVH. | 1437 // Use a cross-process navigation in the opener to swap out the old RVH. |
1420 EXPECT_FALSE(opener1_manager->GetSwappedOutRenderViewHost( | 1438 EXPECT_FALSE( |
1421 rvh1->GetSiteInstance())); | 1439 opener1_manager->GetSwappedOutRenderViewHost(rfh1->GetSiteInstance())); |
1422 opener1->NavigateAndCommit(kUrl2); | 1440 opener1->NavigateAndCommit(kUrl2); |
1423 EXPECT_TRUE(opener1_manager->GetSwappedOutRenderViewHost( | 1441 EXPECT_TRUE( |
1424 rvh1->GetSiteInstance())); | 1442 opener1_manager->GetSwappedOutRenderViewHost(rfh1->GetSiteInstance())); |
1425 | 1443 |
1426 // Fake a process crash. | 1444 // Fake a process crash. |
1427 RenderProcessHost::RendererClosedDetails details( | 1445 CrashFrame(rfh1); |
1428 base::TERMINATION_STATUS_PROCESS_CRASHED, | |
1429 0); | |
1430 // TODO(nasko): Investigate whether this test can be made more realistic by | |
1431 // not faking the notification and just doing the RenderProcessGone. This | |
1432 // should also get rid of faking |set_render_view_created()| call below. | |
1433 NotificationService::current()->Notify( | |
1434 NOTIFICATION_RENDERER_PROCESS_CLOSED, | |
1435 Source<RenderProcessHost>(rvh1->GetProcess()), | |
1436 Details<RenderProcessHost::RendererClosedDetails>(&details)); | |
1437 rvh1->set_render_view_created(false); | |
1438 | 1446 |
1439 // Ensure that the RenderFrameProxyHost stays around and the RenderFrameProxy | 1447 // Ensure that the RenderFrameProxyHost stays around and the RenderFrameProxy |
1440 // is deleted. | 1448 // is deleted. |
1441 RenderFrameProxyHost* render_frame_proxy_host = | 1449 RenderFrameProxyHost* render_frame_proxy_host = |
1442 opener1_manager->GetRenderFrameProxyHost(rvh1->GetSiteInstance()); | 1450 opener1_manager->GetRenderFrameProxyHost(rfh1->GetSiteInstance()); |
1443 EXPECT_TRUE(render_frame_proxy_host); | 1451 EXPECT_TRUE(render_frame_proxy_host); |
1444 EXPECT_FALSE(render_frame_proxy_host->is_render_frame_proxy_live()); | 1452 EXPECT_FALSE(render_frame_proxy_host->is_render_frame_proxy_live()); |
1445 | 1453 |
1446 // Expect the swapped out RVH to exist. | 1454 // Expect the swapped out RVH to exist. |
1447 EXPECT_TRUE(opener1_manager->GetSwappedOutRenderViewHost( | 1455 EXPECT_TRUE( |
1448 rvh1->GetSiteInstance())); | 1456 opener1_manager->GetSwappedOutRenderViewHost(rfh1->GetSiteInstance())); |
1449 | 1457 |
1450 // Reload the initial tab. This should recreate the opener's swapped out RVH | 1458 // Reload the initial tab. This should recreate the opener's swapped out RVH |
1451 // in the original SiteInstance. | 1459 // in the original SiteInstance. |
1452 contents()->GetController().Reload(true); | 1460 contents()->GetController().Reload(true); |
1453 contents()->GetMainFrame()->PrepareForCommit(); | 1461 contents()->GetMainFrame()->PrepareForCommit(); |
1454 EXPECT_EQ(opener1_manager->GetSwappedOutRenderViewHost( | 1462 EXPECT_EQ(opener1_manager->GetSwappedOutRenderViewHost( |
1455 rvh1->GetSiteInstance())->GetRoutingID(), | 1463 rfh1->GetSiteInstance())->GetRoutingID(), |
1456 test_rvh()->opener_route_id()); | 1464 contents()->GetMainFrame()->GetRenderViewHost()->opener_route_id()); |
1457 } | 1465 } |
1458 | 1466 |
1459 // Test that RenderViewHosts created for WebUI navigations are properly | 1467 // Test that RenderViewHosts created for WebUI navigations are properly |
1460 // granted WebUI bindings even if an unprivileged swapped out RenderViewHost | 1468 // granted WebUI bindings even if an unprivileged swapped out RenderViewHost |
1461 // is in the same process (http://crbug.com/79918). | 1469 // is in the same process (http://crbug.com/79918). |
1462 TEST_F(RenderFrameHostManagerTest, EnableWebUIWithSwappedOutOpener) { | 1470 TEST_F(RenderFrameHostManagerTest, EnableWebUIWithSwappedOutOpener) { |
1463 set_should_create_webui(true); | 1471 set_should_create_webui(true); |
1464 const GURL kSettingsUrl("chrome://chrome/settings"); | 1472 const GURL kSettingsUrl("chrome://chrome/settings"); |
1465 const GURL kPluginUrl("chrome://plugins"); | 1473 const GURL kPluginUrl("chrome://plugins"); |
1466 | 1474 |
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 pending_rfh->GetSiteInstance()->increment_active_frame_count(); | 1834 pending_rfh->GetSiteInstance()->increment_active_frame_count(); |
1827 | 1835 |
1828 contents()->GetMainFrame()->OnMessageReceived( | 1836 contents()->GetMainFrame()->OnMessageReceived( |
1829 FrameHostMsg_BeforeUnload_ACK(0, false, now, now)); | 1837 FrameHostMsg_BeforeUnload_ACK(0, false, now, now)); |
1830 EXPECT_FALSE(contents()->cross_navigation_pending()); | 1838 EXPECT_FALSE(contents()->cross_navigation_pending()); |
1831 EXPECT_FALSE(rfh_deleted_observer.deleted()); | 1839 EXPECT_FALSE(rfh_deleted_observer.deleted()); |
1832 } | 1840 } |
1833 } | 1841 } |
1834 | 1842 |
1835 // Test that a pending RenderFrameHost in a non-root frame tree node is properly | 1843 // Test that a pending RenderFrameHost in a non-root frame tree node is properly |
1836 // deleted when the node is detached. Motivated by http://crbug.com/441357 | 1844 // deleted when the node is detached. Motivated by http://crbug.com/441357 and |
| 1845 // http://crbug.com/444955. |
1837 TEST_F(RenderFrameHostManagerTest, DetachPendingChild) { | 1846 TEST_F(RenderFrameHostManagerTest, DetachPendingChild) { |
1838 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 1847 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
1839 switches::kSitePerProcess); | 1848 switches::kSitePerProcess); |
1840 | 1849 |
| 1850 const GURL kUrlA("http://www.google.com/"); |
| 1851 const GURL kUrlB("http://webkit.org/"); |
| 1852 |
| 1853 // Create a page with two child frames. |
| 1854 contents()->NavigateAndCommit(kUrlA); |
| 1855 contents()->GetMainFrame()->OnCreateChildFrame( |
| 1856 contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(), |
| 1857 std::string("frame_name"), SandboxFlags::NONE); |
| 1858 contents()->GetMainFrame()->OnCreateChildFrame( |
| 1859 contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(), |
| 1860 std::string("frame_name"), SandboxFlags::NONE); |
| 1861 RenderFrameHostManager* root_manager = |
| 1862 contents()->GetFrameTree()->root()->render_manager(); |
| 1863 RenderFrameHostManager* iframe1 = |
| 1864 contents()->GetFrameTree()->root()->child_at(0)->render_manager(); |
| 1865 RenderFrameHostManager* iframe2 = |
| 1866 contents()->GetFrameTree()->root()->child_at(1)->render_manager(); |
| 1867 |
| 1868 // 1) The first navigation. |
| 1869 NavigationEntryImpl entryA(NULL /* instance */, -1 /* page_id */, kUrlA, |
| 1870 Referrer(), base::string16() /* title */, |
| 1871 ui::PAGE_TRANSITION_TYPED, |
| 1872 false /* is_renderer_init */); |
| 1873 RenderFrameHostImpl* host1 = GetFrameHostForNavigation(iframe1, entryA); |
| 1874 |
| 1875 // The RenderFrameHost created in Init will be reused. |
| 1876 EXPECT_TRUE(host1 == iframe1->current_frame_host()); |
| 1877 EXPECT_FALSE(GetPendingFrameHost(iframe1)); |
| 1878 |
| 1879 // Commit. |
| 1880 iframe1->DidNavigateFrame(host1, true); |
| 1881 // Commit to SiteInstance should be delayed until RenderFrame commit. |
| 1882 EXPECT_TRUE(host1 == iframe1->current_frame_host()); |
| 1883 ASSERT_TRUE(host1); |
| 1884 EXPECT_TRUE(host1->GetSiteInstance()->HasSite()); |
| 1885 |
| 1886 // 2) Cross-site navigate both frames to next site. |
| 1887 NavigationEntryImpl entryB(NULL /* instance */, -1 /* page_id */, kUrlB, |
| 1888 Referrer(kUrlA, blink::WebReferrerPolicyDefault), |
| 1889 base::string16() /* title */, |
| 1890 ui::PAGE_TRANSITION_LINK, |
| 1891 false /* is_renderer_init */); |
| 1892 host1 = GetFrameHostForNavigation(iframe1, entryB); |
| 1893 RenderFrameHostImpl* host2 = GetFrameHostForNavigation(iframe2, entryB); |
| 1894 |
| 1895 // A new, pending RenderFrameHost should be created in each FrameTreeNode. |
| 1896 EXPECT_TRUE(GetPendingFrameHost(iframe1)); |
| 1897 EXPECT_TRUE(GetPendingFrameHost(iframe2)); |
| 1898 EXPECT_EQ(host1, GetPendingFrameHost(iframe1)); |
| 1899 EXPECT_EQ(host2, GetPendingFrameHost(iframe2)); |
| 1900 EXPECT_TRUE(RenderFrameHostImpl::IsRFHStateActive( |
| 1901 GetPendingFrameHost(iframe1)->rfh_state())); |
| 1902 EXPECT_TRUE(RenderFrameHostImpl::IsRFHStateActive( |
| 1903 GetPendingFrameHost(iframe2)->rfh_state())); |
| 1904 EXPECT_NE(GetPendingFrameHost(iframe1), GetPendingFrameHost(iframe2)); |
| 1905 EXPECT_EQ(GetPendingFrameHost(iframe1)->GetSiteInstance(), |
| 1906 GetPendingFrameHost(iframe2)->GetSiteInstance()); |
| 1907 EXPECT_NE(iframe1->current_frame_host(), GetPendingFrameHost(iframe1)); |
| 1908 EXPECT_NE(iframe2->current_frame_host(), GetPendingFrameHost(iframe2)); |
| 1909 EXPECT_FALSE(contents()->cross_navigation_pending()) |
| 1910 << "There should be no top-level pending navigation."; |
| 1911 |
| 1912 RenderFrameHostDeletedObserver delete_watcher1(GetPendingFrameHost(iframe1)); |
| 1913 RenderFrameHostDeletedObserver delete_watcher2(GetPendingFrameHost(iframe2)); |
| 1914 EXPECT_FALSE(delete_watcher1.deleted()); |
| 1915 EXPECT_FALSE(delete_watcher2.deleted()); |
| 1916 |
| 1917 // Keep the SiteInstance alive for testing. |
| 1918 scoped_refptr<SiteInstanceImpl> site_instance = |
| 1919 GetPendingFrameHost(iframe1)->GetSiteInstance(); |
| 1920 EXPECT_TRUE(site_instance->HasSite()); |
| 1921 EXPECT_NE(site_instance, contents()->GetSiteInstance()); |
| 1922 EXPECT_EQ(2U, site_instance->active_frame_count()); |
| 1923 |
| 1924 // Proxies should exist. |
| 1925 EXPECT_NE(nullptr, |
| 1926 root_manager->GetRenderFrameProxyHost(site_instance.get())); |
| 1927 EXPECT_NE(nullptr, |
| 1928 iframe1->GetRenderFrameProxyHost(site_instance.get())); |
| 1929 EXPECT_NE(nullptr, |
| 1930 iframe2->GetRenderFrameProxyHost(site_instance.get())); |
| 1931 |
| 1932 // Detach the first child FrameTreeNode. This should kill the pending host but |
| 1933 // not yet destroy proxies in |site_instance| since the other child remains. |
| 1934 iframe1->current_frame_host()->OnMessageReceived( |
| 1935 FrameHostMsg_Detach(iframe1->current_frame_host()->GetRoutingID())); |
| 1936 iframe1 = NULL; // Was just destroyed. |
| 1937 |
| 1938 EXPECT_TRUE(delete_watcher1.deleted()); |
| 1939 EXPECT_FALSE(delete_watcher2.deleted()); |
| 1940 EXPECT_EQ(1U, site_instance->active_frame_count()); |
| 1941 |
| 1942 // Proxies should still exist. |
| 1943 EXPECT_NE(nullptr, |
| 1944 root_manager->GetRenderFrameProxyHost(site_instance.get())); |
| 1945 EXPECT_NE(nullptr, |
| 1946 iframe2->GetRenderFrameProxyHost(site_instance.get())); |
| 1947 |
| 1948 // Detach the second child FrameTreeNode. This should trigger cleanup of |
| 1949 // RenderFrameProxyHosts in |site_instance|. |
| 1950 iframe2->current_frame_host()->OnMessageReceived( |
| 1951 FrameHostMsg_Detach(iframe2->current_frame_host()->GetRoutingID())); |
| 1952 iframe2 = NULL; // Was just destroyed. |
| 1953 |
| 1954 EXPECT_TRUE(delete_watcher1.deleted()); |
| 1955 EXPECT_TRUE(delete_watcher2.deleted()); |
| 1956 |
| 1957 EXPECT_EQ(0U, site_instance->active_frame_count()); |
| 1958 EXPECT_EQ(nullptr, |
| 1959 root_manager->GetRenderFrameProxyHost(site_instance.get())) |
| 1960 << "Proxies should have been cleaned up"; |
| 1961 EXPECT_TRUE(site_instance->HasOneRef()) |
| 1962 << "This SiteInstance should be destroyable now."; |
| 1963 } |
| 1964 |
| 1965 // Two tabs in the same process crash. The first tab is reloaded, and the second |
| 1966 // tab navigates away without reloading. The second tab's navigation shouldn't |
| 1967 // mess with the first tab's content. Motivated by http://crbug.com/473714. |
| 1968 TEST_F(RenderFrameHostManagerTest, TwoTabsCrashOneReloadsOneLeaves) { |
| 1969 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 1970 switches::kSitePerProcess); |
| 1971 |
1841 const GURL kUrl1("http://www.google.com/"); | 1972 const GURL kUrl1("http://www.google.com/"); |
1842 const GURL kUrl2("http://webkit.org/"); | 1973 const GURL kUrl2("http://webkit.org/"); |
| 1974 const GURL kUrl3("http://whatwg.org/"); |
1843 | 1975 |
1844 RenderFrameHostImpl* host = NULL; | 1976 // |contents1| and |contents2| navigate to the same page and then crash. |
| 1977 TestWebContents* contents1 = contents(); |
| 1978 scoped_ptr<TestWebContents> contents2( |
| 1979 TestWebContents::Create(browser_context(), contents1->GetSiteInstance())); |
| 1980 contents1->NavigateAndCommit(kUrl1); |
| 1981 contents2->NavigateAndCommit(kUrl1); |
| 1982 CrashFrame(contents1->GetMainFrame()); |
| 1983 CrashFrame(contents2->GetMainFrame()); |
1845 | 1984 |
1846 contents()->NavigateAndCommit(kUrl1); | 1985 EXPECT_EQ(contents1->GetSiteInstance(), contents2->GetSiteInstance()); |
1847 contents()->GetMainFrame()->OnCreateChildFrame( | 1986 |
1848 contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(), | 1987 // Reload |contents1|. |
| 1988 contents1->NavigateAndCommit(kUrl1); |
| 1989 EXPECT_TRUE(contents1->GetMainFrame()->IsRenderFrameLive()); |
| 1990 EXPECT_FALSE(contents2->GetMainFrame()->IsRenderFrameLive()); |
| 1991 EXPECT_EQ(contents1->GetSiteInstance(), contents2->GetSiteInstance()); |
| 1992 |
| 1993 // |contents1| creates an out of process iframe. |
| 1994 contents1->GetMainFrame()->OnCreateChildFrame( |
| 1995 contents1->GetMainFrame()->GetProcess()->GetNextRoutingID(), |
1849 std::string("frame_name"), SandboxFlags::NONE); | 1996 std::string("frame_name"), SandboxFlags::NONE); |
1850 RenderFrameHostManager* manager = | 1997 RenderFrameHostManager* iframe = |
1851 contents()->GetFrameTree()->root()->child_at(0)->render_manager(); | 1998 contents()->GetFrameTree()->root()->child_at(0)->render_manager(); |
| 1999 NavigationEntryImpl entry(NULL /* instance */, -1 /* page_id */, kUrl2, |
| 2000 Referrer(kUrl1, blink::WebReferrerPolicyDefault), |
| 2001 base::string16() /* title */, |
| 2002 ui::PAGE_TRANSITION_LINK, |
| 2003 false /* is_renderer_init */); |
| 2004 RenderFrameHostImpl* cross_site = GetFrameHostForNavigation(iframe, entry); |
| 2005 iframe->DidNavigateFrame(cross_site, true); |
1852 | 2006 |
1853 // 1) The first navigation. -------------------------- | 2007 // A proxy to the iframe should now exist in the SiteInstance of the main |
1854 NavigationEntryImpl entry1(NULL /* instance */, -1 /* page_id */, kUrl1, | 2008 // frames. |
1855 Referrer(), base::string16() /* title */, | 2009 EXPECT_NE(cross_site->GetSiteInstance(), contents1->GetSiteInstance()); |
1856 ui::PAGE_TRANSITION_TYPED, | 2010 EXPECT_NE(nullptr, |
1857 false /* is_renderer_init */); | 2011 iframe->GetRenderFrameProxyHost(contents1->GetSiteInstance())); |
1858 host = GetFrameHostForNavigation(manager, entry1); | 2012 EXPECT_NE(nullptr, |
| 2013 iframe->GetRenderFrameProxyHost(contents2->GetSiteInstance())); |
1859 | 2014 |
1860 // The RenderFrameHost created in Init will be reused. | 2015 // Navigate |contents2| away from the sad tab (and thus away from the |
1861 EXPECT_TRUE(host == manager->current_frame_host()); | 2016 // SiteInstance of |contents1|). This should not destroy the proxies needed by |
1862 EXPECT_FALSE(GetPendingFrameHost(manager)); | 2017 // |contents1| -- that was http://crbug.com/473714. |
1863 | 2018 EXPECT_FALSE(contents2->GetMainFrame()->IsRenderFrameLive()); |
1864 // Commit. | 2019 contents2->NavigateAndCommit(kUrl3); |
1865 manager->DidNavigateFrame(host, true); | 2020 EXPECT_TRUE(contents2->GetMainFrame()->IsRenderFrameLive()); |
1866 // Commit to SiteInstance should be delayed until RenderFrame commit. | 2021 EXPECT_NE(nullptr, |
1867 EXPECT_TRUE(host == manager->current_frame_host()); | 2022 iframe->GetRenderFrameProxyHost(contents1->GetSiteInstance())); |
1868 ASSERT_TRUE(host); | 2023 EXPECT_EQ(nullptr, |
1869 EXPECT_TRUE(host->GetSiteInstance()->HasSite()); | 2024 iframe->GetRenderFrameProxyHost(contents2->GetSiteInstance())); |
1870 | |
1871 // 2) Cross-site navigate to next site. -------------- | |
1872 NavigationEntryImpl entry2(NULL /* instance */, -1 /* page_id */, kUrl2, | |
1873 Referrer(kUrl1, blink::WebReferrerPolicyDefault), | |
1874 base::string16() /* title */, | |
1875 ui::PAGE_TRANSITION_LINK, | |
1876 false /* is_renderer_init */); | |
1877 host = GetFrameHostForNavigation(manager, entry2); | |
1878 | |
1879 // A new RenderFrameHost should be created. | |
1880 EXPECT_TRUE(GetPendingFrameHost(manager)); | |
1881 ASSERT_EQ(host, GetPendingFrameHost(manager)); | |
1882 ASSERT_NE(manager->current_frame_host(), GetPendingFrameHost(manager)); | |
1883 EXPECT_FALSE(contents()->cross_navigation_pending()) | |
1884 << "There should be no top-level pending navigation."; | |
1885 | |
1886 RenderFrameHostDeletedObserver delete_watcher(GetPendingFrameHost(manager)); | |
1887 EXPECT_FALSE(delete_watcher.deleted()); | |
1888 | |
1889 // Extend the lifetime of the child frame's SiteInstance, pretending | |
1890 // that there is another reference to it. | |
1891 scoped_refptr<SiteInstanceImpl> site_instance = | |
1892 GetPendingFrameHost(manager)->GetSiteInstance(); | |
1893 EXPECT_TRUE(site_instance->HasSite()); | |
1894 EXPECT_NE(site_instance, contents()->GetSiteInstance()); | |
1895 EXPECT_EQ(1U, site_instance->active_frame_count()); | |
1896 site_instance->increment_active_frame_count(); | |
1897 EXPECT_EQ(2U, site_instance->active_frame_count()); | |
1898 | |
1899 // Now detach the child FrameTreeNode. This should kill the pending host. | |
1900 manager->current_frame_host()->OnMessageReceived( | |
1901 FrameHostMsg_Detach(manager->current_frame_host()->GetRoutingID())); | |
1902 | |
1903 EXPECT_TRUE(delete_watcher.deleted()); | |
1904 | |
1905 EXPECT_EQ(1U, site_instance->active_frame_count()); | |
1906 site_instance->decrement_active_frame_count(); | |
1907 | |
1908 #if 0 | |
1909 // TODO(nick): Currently a proxy to the removed frame lingers in the parent. | |
1910 // Enable this assert below once the proxies to the subframe are correctly | |
1911 // cleaned up after detach. http://crbug.com/444955. | |
1912 ASSERT_TRUE(site_instance->HasOneRef()) | |
1913 << "This SiteInstance should be destroyable now."; | |
1914 #endif | |
1915 } | 2025 } |
1916 | 2026 |
1917 } // namespace content | 2027 } // namespace content |
OLD | NEW |