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 <stddef.h> | 5 #include <stddef.h> |
6 #include <stdint.h> | 6 #include <stdint.h> |
7 | 7 |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 30 matching lines...) Expand all Loading... |
41 #include "content/public/common/file_chooser_params.h" | 41 #include "content/public/common/file_chooser_params.h" |
42 #include "content/public/common/page_state.h" | 42 #include "content/public/common/page_state.h" |
43 #include "content/public/common/url_constants.h" | 43 #include "content/public/common/url_constants.h" |
44 #include "content/public/test/browser_test_utils.h" | 44 #include "content/public/test/browser_test_utils.h" |
45 #include "content/public/test/content_browser_test.h" | 45 #include "content/public/test/content_browser_test.h" |
46 #include "content/public/test/content_browser_test_utils.h" | 46 #include "content/public/test/content_browser_test_utils.h" |
47 #include "content/public/test/test_navigation_observer.h" | 47 #include "content/public/test/test_navigation_observer.h" |
48 #include "content/public/test/test_utils.h" | 48 #include "content/public/test/test_utils.h" |
49 #include "content/shell/browser/shell.h" | 49 #include "content/shell/browser/shell.h" |
50 #include "content/test/content_browser_test_utils_internal.h" | 50 #include "content/test/content_browser_test_utils_internal.h" |
| 51 #include "content/test/test_frame_navigation_observer.h" |
51 #include "net/dns/mock_host_resolver.h" | 52 #include "net/dns/mock_host_resolver.h" |
52 #include "net/test/embedded_test_server/embedded_test_server.h" | 53 #include "net/test/embedded_test_server/embedded_test_server.h" |
53 #include "net/test/embedded_test_server/request_handler_util.h" | 54 #include "net/test/embedded_test_server/request_handler_util.h" |
54 | 55 |
55 using base::ASCIIToUTF16; | 56 using base::ASCIIToUTF16; |
56 | 57 |
57 namespace content { | 58 namespace content { |
58 | 59 |
59 namespace { | 60 namespace { |
60 | 61 |
(...skipping 2289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2350 EXPECT_FALSE( | 2351 EXPECT_FALSE( |
2351 popup_root->current_frame_host()->render_view_host()->IsRenderViewLive()); | 2352 popup_root->current_frame_host()->render_view_host()->IsRenderViewLive()); |
2352 | 2353 |
2353 // Navigate the main tab to the site of the popup. This will cause the | 2354 // Navigate the main tab to the site of the popup. This will cause the |
2354 // RenderView for b.com in the main tab to be recreated. If the issue | 2355 // RenderView for b.com in the main tab to be recreated. If the issue |
2355 // is not fixed, this will result in process crash and failing test. | 2356 // is not fixed, this will result in process crash and failing test. |
2356 EXPECT_TRUE(NavigateToURL( | 2357 EXPECT_TRUE(NavigateToURL( |
2357 shell(), embedded_test_server()->GetURL("b.com", "/title3.html"))); | 2358 shell(), embedded_test_server()->GetURL("b.com", "/title3.html"))); |
2358 } | 2359 } |
2359 | 2360 |
| 2361 // Ensure that we don't crash the renderer in CreateRenderView if a proxy goes |
| 2362 // away between swapout and the next navigation. See https://crbug.com/581912. |
| 2363 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, |
| 2364 CreateRenderViewAfterProcessKillAndClosedProxy) { |
| 2365 StartEmbeddedServer(); |
| 2366 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 2367 ->GetFrameTree() |
| 2368 ->root(); |
| 2369 |
| 2370 // Give an initial page an unload handler that never completes. |
| 2371 EXPECT_TRUE(NavigateToURL( |
| 2372 shell(), embedded_test_server()->GetURL("a.com", "/title1.html"))); |
| 2373 EXPECT_TRUE(ExecuteScript(root->current_frame_host(), |
| 2374 "window.onunload=function(e){ while(1); };\n")); |
| 2375 |
| 2376 // Open a popup in the same process. |
| 2377 Shell* new_shell = |
| 2378 OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo"); |
| 2379 FrameTreeNode* popup_root = |
| 2380 static_cast<WebContentsImpl*>(new_shell->web_contents()) |
| 2381 ->GetFrameTree() |
| 2382 ->root(); |
| 2383 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(), |
| 2384 new_shell->web_contents()->GetSiteInstance()); |
| 2385 |
| 2386 // Navigate the first tab to a different site, and only wait for commit, not |
| 2387 // load stop. |
| 2388 RenderFrameHostImpl* rfh_a = root->current_frame_host(); |
| 2389 SiteInstanceImpl* site_instance_a = rfh_a->GetSiteInstance(); |
| 2390 TestFrameNavigationObserver commit_observer(root); |
| 2391 shell()->LoadURL(embedded_test_server()->GetURL("b.com", "/title2.html")); |
| 2392 commit_observer.WaitForCommit(); |
| 2393 rfh_a->ResetSwapOutTimerForTesting(); |
| 2394 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), |
| 2395 new_shell->web_contents()->GetSiteInstance()); |
| 2396 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(site_instance_a)); |
| 2397 |
| 2398 // The previous RFH should still be pending deletion, as we wait for either |
| 2399 // the SwapOut ACK or a timeout. |
| 2400 ASSERT_TRUE(root->render_manager()->IsPendingDeletion(rfh_a)); |
| 2401 |
| 2402 // The corresponding RVH should not be pending deletion due to the proxy. |
| 2403 EXPECT_FALSE(root->render_manager()->IsViewPendingDeletion( |
| 2404 rfh_a->render_view_host())); |
| 2405 |
| 2406 // Kill the old process. |
| 2407 RenderProcessHost* process = rfh_a->GetProcess(); |
| 2408 RenderProcessHostWatcher crash_observer( |
| 2409 process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
| 2410 process->Shutdown(0, false); |
| 2411 crash_observer.Wait(); |
| 2412 EXPECT_FALSE(popup_root->current_frame_host()->IsRenderFrameLive()); |
| 2413 // |rfh_a| is now deleted, thanks to the bug fix. |
| 2414 |
| 2415 // Close the popup so there is no proxy for a.com in the original tab. |
| 2416 new_shell->Close(); |
| 2417 EXPECT_FALSE( |
| 2418 root->render_manager()->GetRenderFrameProxyHost(site_instance_a)); |
| 2419 |
| 2420 // Go back in the main frame from b.com to a.com. In https://crbug.com/581912, |
| 2421 // the browser process would crash here because there was no main frame |
| 2422 // routing ID or proxy in RVHI::CreateRenderView. |
| 2423 { |
| 2424 TestNavigationObserver back_nav_load_observer(shell()->web_contents()); |
| 2425 shell()->web_contents()->GetController().GoBack(); |
| 2426 back_nav_load_observer.Wait(); |
| 2427 } |
| 2428 } |
| 2429 |
| 2430 // Ensure that we don't crash in RenderViewImpl::Init if a proxy is created |
| 2431 // after swapout and before navigation. See https://crbug.com/544755. |
| 2432 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, |
| 2433 RenderViewInitAfterNewProxyAndProcessKill) { |
| 2434 StartEmbeddedServer(); |
| 2435 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 2436 ->GetFrameTree() |
| 2437 ->root(); |
| 2438 |
| 2439 // Give an initial page an unload handler that never completes. |
| 2440 EXPECT_TRUE(NavigateToURL( |
| 2441 shell(), embedded_test_server()->GetURL("a.com", "/title1.html"))); |
| 2442 EXPECT_TRUE(ExecuteScript(root->current_frame_host(), |
| 2443 "window.onunload=function(e){ while(1); };\n")); |
| 2444 |
| 2445 // Navigate the tab to a different site, and only wait for commit, not load |
| 2446 // stop. |
| 2447 RenderFrameHostImpl* rfh_a = root->current_frame_host(); |
| 2448 SiteInstanceImpl* site_instance_a = rfh_a->GetSiteInstance(); |
| 2449 TestFrameNavigationObserver commit_observer(root); |
| 2450 shell()->LoadURL(embedded_test_server()->GetURL("b.com", "/title2.html")); |
| 2451 commit_observer.WaitForCommit(); |
| 2452 rfh_a->ResetSwapOutTimerForTesting(); |
| 2453 EXPECT_NE(site_instance_a, shell()->web_contents()->GetSiteInstance()); |
| 2454 |
| 2455 // The previous RFH and RVH should still be pending deletion, as we wait for |
| 2456 // either the SwapOut ACK or a timeout. |
| 2457 ASSERT_TRUE(root->render_manager()->IsPendingDeletion(rfh_a)); |
| 2458 EXPECT_TRUE(root->render_manager()->IsViewPendingDeletion( |
| 2459 rfh_a->render_view_host())); |
| 2460 |
| 2461 // Open a popup in the new B process. |
| 2462 Shell* new_shell = |
| 2463 OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo"); |
| 2464 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(), |
| 2465 new_shell->web_contents()->GetSiteInstance()); |
| 2466 |
| 2467 // Navigate the popup to the original site, but don't wait for commit (which |
| 2468 // won't happen). This creates a proxy in the original tab, alongside the |
| 2469 // RFH and RVH pending deletion. |
| 2470 new_shell->LoadURL(embedded_test_server()->GetURL("a.com", "/title2.html")); |
| 2471 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(site_instance_a)); |
| 2472 |
| 2473 // Kill the old process. |
| 2474 RenderProcessHost* process = rfh_a->GetProcess(); |
| 2475 RenderProcessHostWatcher crash_observer( |
| 2476 process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
| 2477 process->Shutdown(0, false); |
| 2478 crash_observer.Wait(); |
| 2479 // |rfh_a| is now deleted, thanks to the bug fix. |
| 2480 |
| 2481 // Go back in the main frame from b.com to a.com. |
| 2482 { |
| 2483 TestNavigationObserver back_nav_load_observer(shell()->web_contents()); |
| 2484 shell()->web_contents()->GetController().GoBack(); |
| 2485 back_nav_load_observer.Wait(); |
| 2486 } |
| 2487 |
| 2488 // In https://crbug.com/581912, the renderer process would crash here because |
| 2489 // there was a frame, view, and proxy (and is_swapped_out was true). |
| 2490 EXPECT_EQ(site_instance_a, root->current_frame_host()->GetSiteInstance()); |
| 2491 EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive()); |
| 2492 EXPECT_TRUE(new_shell->web_contents()->GetMainFrame()->IsRenderFrameLive()); |
| 2493 } |
| 2494 |
2360 // Ensure that we use the same pending RenderFrameHost if a second navigation to | 2495 // Ensure that we use the same pending RenderFrameHost if a second navigation to |
2361 // its site occurs before it commits. Otherwise the renderer process will have | 2496 // its site occurs before it commits. Otherwise the renderer process will have |
2362 // two competing pending RenderFrames that both try to swap with the same | 2497 // two competing pending RenderFrames that both try to swap with the same |
2363 // RenderFrameProxy. See https://crbug.com/545900. | 2498 // RenderFrameProxy. See https://crbug.com/545900. |
2364 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, | 2499 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, |
2365 ConsecutiveNavigationsToSite) { | 2500 ConsecutiveNavigationsToSite) { |
2366 StartEmbeddedServer(); | 2501 StartEmbeddedServer(); |
2367 EXPECT_TRUE(NavigateToURL( | 2502 EXPECT_TRUE(NavigateToURL( |
2368 shell(), embedded_test_server()->GetURL("a.com", "/title1.html"))); | 2503 shell(), embedded_test_server()->GetURL("a.com", "/title1.html"))); |
2369 | 2504 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2407 web_contents->GetRenderManagerForTesting()->speculative_frame_host()); | 2542 web_contents->GetRenderManagerForTesting()->speculative_frame_host()); |
2408 } else { | 2543 } else { |
2409 EXPECT_FALSE( | 2544 EXPECT_FALSE( |
2410 web_contents->GetRenderManagerForTesting()->pending_frame_host()); | 2545 web_contents->GetRenderManagerForTesting()->pending_frame_host()); |
2411 } | 2546 } |
2412 | 2547 |
2413 ResourceDispatcherHost::Get()->SetDelegate(nullptr); | 2548 ResourceDispatcherHost::Get()->SetDelegate(nullptr); |
2414 } | 2549 } |
2415 | 2550 |
2416 } // namespace content | 2551 } // namespace content |
OLD | NEW |