Chromium Code Reviews| 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) { |
|
ncarter (slow)
2015/04/03 22:03:33
Note that in the latest patch set I've changed thi
| |
| 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 ASSERT_EQ(host1, GetPendingFrameHost(iframe1)); | |
| 1899 ASSERT_EQ(host2, GetPendingFrameHost(iframe2)); | |
| 1900 ASSERT_TRUE(RenderFrameHostImpl::IsRFHStateActive( | |
| 1901 GetPendingFrameHost(iframe1)->rfh_state())); | |
| 1902 ASSERT_TRUE(RenderFrameHostImpl::IsRFHStateActive( | |
| 1903 GetPendingFrameHost(iframe2)->rfh_state())); | |
| 1904 ASSERT_NE(GetPendingFrameHost(iframe1), GetPendingFrameHost(iframe2)); | |
| 1905 ASSERT_EQ(GetPendingFrameHost(iframe1)->GetSiteInstance(), | |
| 1906 GetPendingFrameHost(iframe2)->GetSiteInstance()); | |
| 1907 ASSERT_NE(iframe1->current_frame_host(), GetPendingFrameHost(iframe1)); | |
| 1908 ASSERT_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 ASSERT_EQ(contents1->GetSiteInstance(), contents2->GetSiteInstance()); |
| 1847 contents()->GetMainFrame()->OnCreateChildFrame( | 1986 |
| 1848 contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(), | 1987 // Reload |contents1|. |
| 1988 contents1->NavigateAndCommit(kUrl1); | |
| 1989 ASSERT_TRUE(contents1->GetMainFrame()->IsRenderFrameLive()); | |
| 1990 ASSERT_FALSE(contents2->GetMainFrame()->IsRenderFrameLive()); | |
| 1991 ASSERT_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 ASSERT_NE(cross_site->GetSiteInstance(), contents1->GetSiteInstance()); |
| 1856 ui::PAGE_TRANSITION_TYPED, | 2010 ASSERT_NE(nullptr, |
| 1857 false /* is_renderer_init */); | 2011 iframe->GetRenderFrameProxyHost(contents1->GetSiteInstance())); |
| 1858 host = GetFrameHostForNavigation(manager, entry1); | 2012 ASSERT_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 ASSERT_FALSE(contents2->GetMainFrame()->IsRenderFrameLive()); |
| 1864 // Commit. | 2019 contents2->NavigateAndCommit(kUrl3); |
| 1865 manager->DidNavigateFrame(host, true); | 2020 ASSERT_TRUE(contents2->GetMainFrame()->IsRenderFrameLive()); |
| 1866 // Commit to SiteInstance should be delayed until RenderFrame commit. | 2021 ASSERT_NE(nullptr, |
| 1867 EXPECT_TRUE(host == manager->current_frame_host()); | 2022 iframe->GetRenderFrameProxyHost(contents1->GetSiteInstance())); |
| 1868 ASSERT_TRUE(host); | 2023 ASSERT_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 |