OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/site_per_process_browsertest.h" | 5 #include "content/browser/site_per_process_browsertest.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 8361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8372 // Navigate the iframe cross-site. | 8372 // Navigate the iframe cross-site. |
8373 NavigationHandleWatcher watcher(shell()->web_contents()); | 8373 NavigationHandleWatcher watcher(shell()->web_contents()); |
8374 TestNavigationObserver load_observer(shell()->web_contents()); | 8374 TestNavigationObserver load_observer(shell()->web_contents()); |
8375 GURL frame_url = embedded_test_server()->GetURL("c.com", "/title1.html"); | 8375 GURL frame_url = embedded_test_server()->GetURL("c.com", "/title1.html"); |
8376 EXPECT_TRUE(ExecuteScript( | 8376 EXPECT_TRUE(ExecuteScript( |
8377 shell()->web_contents(), | 8377 shell()->web_contents(), |
8378 "window.frames[0].location = \"" + frame_url.spec() + "\";")); | 8378 "window.frames[0].location = \"" + frame_url.spec() + "\";")); |
8379 load_observer.Wait(); | 8379 load_observer.Wait(); |
8380 } | 8380 } |
8381 | 8381 |
| 8382 // Test that when canceling a pending RenderFrameHost in the middle of a |
| 8383 // redirect, and then killing the corresponding RenderView's renderer process, |
| 8384 // the RenderViewHost isn't reused in an improper state later. Previously this |
| 8385 // led to a crash in CreateRenderView when recreating the RenderView due to a |
| 8386 // stale main frame routing ID. See https://crbug.com/627400. |
| 8387 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
| 8388 ReuseNonLiveRenderViewHostAfterCancelPending) { |
| 8389 GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| 8390 GURL b_url(embedded_test_server()->GetURL("b.com", "/title2.html")); |
| 8391 GURL c_url(embedded_test_server()->GetURL("c.com", "/title3.html")); |
| 8392 |
| 8393 EXPECT_TRUE(NavigateToURL(shell(), a_url)); |
| 8394 |
| 8395 // Open a popup and navigate it to b.com. |
| 8396 Shell* popup = OpenPopup(shell(), a_url, "popup"); |
| 8397 EXPECT_TRUE(NavigateToURL(popup, b_url)); |
| 8398 |
| 8399 // Open a second popup and navigate it to b.com, which redirects to c.com. |
| 8400 // The navigation to b.com will create a pending RenderFrameHost, which will |
| 8401 // be canceled during the redirect to c.com. Note that NavigateToURL will |
| 8402 // return false because the committed URL won't match the requested URL due |
| 8403 // to the redirect. |
| 8404 Shell* popup2 = OpenPopup(shell(), a_url, "popup2"); |
| 8405 TestNavigationObserver observer(popup2->web_contents()); |
| 8406 GURL redirect_url(embedded_test_server()->GetURL( |
| 8407 "b.com", "/server-redirect?" + c_url.spec())); |
| 8408 EXPECT_FALSE(NavigateToURL(popup2, redirect_url)); |
| 8409 EXPECT_EQ(c_url, observer.last_navigation_url()); |
| 8410 EXPECT_TRUE(observer.last_navigation_succeeded()); |
| 8411 |
| 8412 // Kill the b.com process (which currently hosts a RenderFrameProxy that |
| 8413 // replaced the pending RenderFrame in |popup2|, as well as the RenderFrame |
| 8414 // for |popup|). |
| 8415 RenderProcessHost* b_process = |
| 8416 popup->web_contents()->GetMainFrame()->GetProcess(); |
| 8417 RenderProcessHostWatcher crash_observer( |
| 8418 b_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
| 8419 b_process->Shutdown(0, false); |
| 8420 crash_observer.Wait(); |
| 8421 |
| 8422 // Navigate the second popup to b.com. This used to crash when creating the |
| 8423 // RenderView, because it reused the RenderViewHost created by the canceled |
| 8424 // navigation to b.com, and that RenderViewHost had a stale main frame |
| 8425 // routing ID and active state. |
| 8426 EXPECT_TRUE(NavigateToURL(popup2, b_url)); |
| 8427 } |
| 8428 |
| 8429 // Check that after a pending RFH is canceled and replaced with a proxy (which |
| 8430 // reuses the canceled RFH's RenderViewHost), navigating to a main frame in the |
| 8431 // same site as the canceled RFH doesn't lead to a renderer crash. The steps |
| 8432 // here are similar to ReuseNonLiveRenderViewHostAfterCancelPending, but don't |
| 8433 // involve crashing the renderer. See https://crbug.com/651980. |
| 8434 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
| 8435 RecreateMainFrameAfterCancelPending) { |
| 8436 GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| 8437 GURL b_url(embedded_test_server()->GetURL("b.com", "/title2.html")); |
| 8438 GURL c_url(embedded_test_server()->GetURL("c.com", "/title3.html")); |
| 8439 |
| 8440 EXPECT_TRUE(NavigateToURL(shell(), a_url)); |
| 8441 |
| 8442 // Open a popup and navigate it to b.com. |
| 8443 Shell* popup = OpenPopup(shell(), a_url, "popup"); |
| 8444 EXPECT_TRUE(NavigateToURL(popup, b_url)); |
| 8445 |
| 8446 // Open a second popup and navigate it to b.com, which redirects to c.com. |
| 8447 // The navigation to b.com will create a pending RenderFrameHost, which will |
| 8448 // be canceled during the redirect to c.com. Note that NavigateToURL will |
| 8449 // return false because the committed URL won't match the requested URL due |
| 8450 // to the redirect. |
| 8451 Shell* popup2 = OpenPopup(shell(), a_url, "popup2"); |
| 8452 TestNavigationObserver observer(popup2->web_contents()); |
| 8453 GURL redirect_url(embedded_test_server()->GetURL( |
| 8454 "b.com", "/server-redirect?" + c_url.spec())); |
| 8455 EXPECT_FALSE(NavigateToURL(popup2, redirect_url)); |
| 8456 EXPECT_EQ(c_url, observer.last_navigation_url()); |
| 8457 EXPECT_TRUE(observer.last_navigation_succeeded()); |
| 8458 |
| 8459 // Navigate the second popup to b.com. This used to crash the b.com renderer |
| 8460 // because it failed to delete the canceled RFH's RenderFrame, so this caused |
| 8461 // it to try to create a frame widget which already existed. |
| 8462 EXPECT_TRUE(NavigateToURL(popup2, b_url)); |
| 8463 } |
| 8464 |
| 8465 // Check that when a pending RFH is canceled and a proxy needs to be created in |
| 8466 // its place, the proxy is properly initialized on the renderer side. See |
| 8467 // https://crbug.com/653746. |
| 8468 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
| 8469 CommunicateWithProxyAfterCancelPending) { |
| 8470 GURL a_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| 8471 GURL b_url(embedded_test_server()->GetURL("b.com", "/title2.html")); |
| 8472 GURL c_url(embedded_test_server()->GetURL("c.com", "/title3.html")); |
| 8473 |
| 8474 EXPECT_TRUE(NavigateToURL(shell(), a_url)); |
| 8475 |
| 8476 // Open a popup and navigate it to b.com. |
| 8477 Shell* popup = OpenPopup(shell(), a_url, "popup"); |
| 8478 EXPECT_TRUE(NavigateToURL(popup, b_url)); |
| 8479 |
| 8480 // Open a second popup and navigate it to b.com, which redirects to c.com. |
| 8481 // The navigation to b.com will create a pending RenderFrameHost, which will |
| 8482 // be canceled during the redirect to c.com. Note that NavigateToURL will |
| 8483 // return false because the committed URL won't match the requested URL due |
| 8484 // to the redirect. |
| 8485 Shell* popup2 = OpenPopup(shell(), a_url, "popup2"); |
| 8486 TestNavigationObserver observer(popup2->web_contents()); |
| 8487 GURL redirect_url(embedded_test_server()->GetURL( |
| 8488 "b.com", "/server-redirect?" + c_url.spec())); |
| 8489 EXPECT_FALSE(NavigateToURL(popup2, redirect_url)); |
| 8490 EXPECT_EQ(c_url, observer.last_navigation_url()); |
| 8491 EXPECT_TRUE(observer.last_navigation_succeeded()); |
| 8492 |
| 8493 // Because b.com has other active frames (namely, the frame in |popup|), |
| 8494 // there should be a proxy created for the canceled RFH, and it should be |
| 8495 // live. |
| 8496 SiteInstance* b_instance = popup->web_contents()->GetSiteInstance(); |
| 8497 FrameTreeNode* popup2_root = |
| 8498 static_cast<WebContentsImpl*>(popup2->web_contents()) |
| 8499 ->GetFrameTree() |
| 8500 ->root(); |
| 8501 RenderFrameProxyHost* proxy = |
| 8502 popup2_root->render_manager()->GetRenderFrameProxyHost(b_instance); |
| 8503 EXPECT_TRUE(proxy); |
| 8504 EXPECT_TRUE(proxy->is_render_frame_proxy_live()); |
| 8505 |
| 8506 // Add a postMessage listener in |popup2| (currently at a c.com URL). |
| 8507 EXPECT_TRUE( |
| 8508 ExecuteScript(popup2, |
| 8509 "window.addEventListener('message', function(event) {\n" |
| 8510 " document.title=event.data;\n" |
| 8511 "});")); |
| 8512 |
| 8513 // Check that a postMessage can be sent via |proxy| above. This needs to be |
| 8514 // done from the b.com process. |popup| is currently in b.com, but it can't |
| 8515 // reach the window reference for |popup2| due to a security restriction in |
| 8516 // Blink. So, navigate the main tab to b.com and then send a postMessage to |
| 8517 // |popup2|. This is allowed since the main tab is |popup2|'s opener. |
| 8518 EXPECT_TRUE(NavigateToURL(shell(), b_url)); |
| 8519 |
| 8520 base::string16 expected_title(base::UTF8ToUTF16("foo")); |
| 8521 TitleWatcher title_watcher(popup2->web_contents(), expected_title); |
| 8522 EXPECT_TRUE(ExecuteScript( |
| 8523 shell(), "window.open('','popup2').postMessage('foo', '*');")); |
| 8524 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); |
| 8525 } |
| 8526 |
8382 } // namespace content | 8527 } // namespace content |
OLD | NEW |