Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: content/browser/frame_host/render_frame_host_manager_browsertest.cc

Issue 1835833002: Fix 3 crashes related to navigations after a process dies. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixes from review Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/frame_host/render_frame_host_manager.cc ('k') | content/browser/renderer_host/render_view_host_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698