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

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: Remove TODO 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 // Kill the old process.
2403 RenderProcessHost* process = rfh_a->GetProcess();
2404 RenderProcessHostWatcher crash_observer(
2405 process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
2406 process->Shutdown(0, false);
2407 crash_observer.Wait();
2408 EXPECT_FALSE(popup_root->current_frame_host()->IsRenderFrameLive());
2409 // |rfh_a| is now deleted, thanks to the bug fix.
2410
2411 // Close the popup so there is no proxy for a.com in the original tab.
2412 new_shell->Close();
2413 EXPECT_FALSE(
2414 root->render_manager()->GetRenderFrameProxyHost(site_instance_a));
2415
2416 // Go back in the main frame from b.com to a.com. In https://crbug.com/581912,
2417 // the browser process would crash here because there was no main frame
2418 // routing ID or proxy in RVHI::CreateRenderView.
2419 {
2420 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
2421 shell()->web_contents()->GetController().GoBack();
2422 back_nav_load_observer.Wait();
2423 }
2424 }
2425
2426 // Ensure that we don't create in RenderViewImpl::Init if a proxy is created
alexmos 2016/03/29 18:43:01 nit: word missing after "don't create"?
Charlie Reis 2016/03/29 20:29:02 Heh, s/create/crash/. Thanks for catching it.
2427 // after swapout and before navigation. See https://crbug.com/544755.
2428 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
2429 RenderViewInitAfterNewProxyAndProcessKill) {
2430 StartEmbeddedServer();
2431 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
2432 ->GetFrameTree()
2433 ->root();
2434
2435 // Give an initial page an unload handler that never completes.
2436 EXPECT_TRUE(NavigateToURL(
2437 shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
2438 EXPECT_TRUE(ExecuteScript(root->current_frame_host(),
2439 "window.onunload=function(e){ while(1); };\n"));
2440
2441 // Navigate the tab to a different site, and only wait for commit, not load
2442 // stop.
2443 RenderFrameHostImpl* rfh_a = root->current_frame_host();
2444 SiteInstanceImpl* site_instance_a = rfh_a->GetSiteInstance();
2445 TestFrameNavigationObserver commit_observer(root);
2446 shell()->LoadURL(embedded_test_server()->GetURL("b.com", "/title2.html"));
2447 commit_observer.WaitForCommit();
2448 rfh_a->ResetSwapOutTimerForTesting();
2449 EXPECT_NE(site_instance_a, shell()->web_contents()->GetSiteInstance());
2450
2451 // The previous RFH should still be pending deletion, as we wait for either
2452 // the SwapOut ACK or a timeout.
2453 ASSERT_TRUE(root->render_manager()->IsPendingDeletion(rfh_a));
alexmos 2016/03/29 18:43:02 Is it worth checking that the view is pending dele
Charlie Reis 2016/03/29 20:29:02 Good idea. Done. (I made them EXPECT rather than
2454
2455 // Open a popup in the new B process.
2456 Shell* new_shell =
2457 OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
2458 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
2459 new_shell->web_contents()->GetSiteInstance());
2460
2461 // Navigate the popup to the original site, but don't wait for commit (which
2462 // won't happen). This creates a proxy in the original tab, alongside the
2463 // RFH and RVH pending deletion.
2464 new_shell->LoadURL(embedded_test_server()->GetURL("a.com", "/title2.html"));
2465 if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
alexmos 2016/03/29 18:43:02 Is this the right thing to use? (As opposed to Are
Charlie Reis 2016/03/29 20:29:02 Actually, I don't remember why I needed to guard t
2466 EXPECT_TRUE(
2467 root->render_manager()->GetRenderFrameProxyHost(site_instance_a));
2468 }
2469
2470 // Kill the old process.
2471 RenderProcessHost* process = rfh_a->GetProcess();
2472 RenderProcessHostWatcher crash_observer(
2473 process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
2474 process->Shutdown(0, false);
2475 crash_observer.Wait();
2476 // |rfh_a| is now deleted, thanks to the bug fix.
2477
2478 // Go back in the main frame from b.com to a.com.
2479 {
2480 TestNavigationObserver back_nav_load_observer(shell()->web_contents());
2481 shell()->web_contents()->GetController().GoBack();
2482 back_nav_load_observer.Wait();
2483 }
2484
2485 // In https://crbug.com/581912, the renderer process would crash here because
2486 // there was a frame, view, and proxy (and is_swapped_out was true).
2487 EXPECT_EQ(site_instance_a, root->current_frame_host()->GetSiteInstance());
2488 EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
2489 EXPECT_TRUE(new_shell->web_contents()->GetMainFrame()->IsRenderFrameLive());
2490 }
2491
2360 // Ensure that we use the same pending RenderFrameHost if a second navigation to 2492 // 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 2493 // 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 2494 // two competing pending RenderFrames that both try to swap with the same
2363 // RenderFrameProxy. See https://crbug.com/545900. 2495 // RenderFrameProxy. See https://crbug.com/545900.
2364 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, 2496 IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
2365 ConsecutiveNavigationsToSite) { 2497 ConsecutiveNavigationsToSite) {
2366 StartEmbeddedServer(); 2498 StartEmbeddedServer();
2367 EXPECT_TRUE(NavigateToURL( 2499 EXPECT_TRUE(NavigateToURL(
2368 shell(), embedded_test_server()->GetURL("a.com", "/title1.html"))); 2500 shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
2369 2501
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2407 web_contents->GetRenderManagerForTesting()->speculative_frame_host()); 2539 web_contents->GetRenderManagerForTesting()->speculative_frame_host());
2408 } else { 2540 } else {
2409 EXPECT_FALSE( 2541 EXPECT_FALSE(
2410 web_contents->GetRenderManagerForTesting()->pending_frame_host()); 2542 web_contents->GetRenderManagerForTesting()->pending_frame_host());
2411 } 2543 }
2412 2544
2413 ResourceDispatcherHost::Get()->SetDelegate(nullptr); 2545 ResourceDispatcherHost::Get()->SetDelegate(nullptr);
2414 } 2546 }
2415 2547
2416 } // namespace content 2548 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698