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

Side by Side Diff: content/browser/site_per_process_browsertest.cc

Issue 1409693009: Fix leaking of RenderFrames. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased on ToT and couple of more nits fixes. Created 5 years 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
« no previous file with comments | « content/browser/frame_host/render_frame_host_impl.cc ('k') | content/common/frame_messages.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <algorithm> 7 #include <algorithm>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 11 matching lines...) Expand all
22 #include "content/browser/frame_host/render_widget_host_view_child_frame.h" 22 #include "content/browser/frame_host/render_widget_host_view_child_frame.h"
23 #include "content/browser/gpu/compositor_util.h" 23 #include "content/browser/gpu/compositor_util.h"
24 #include "content/browser/renderer_host/render_view_host_impl.h" 24 #include "content/browser/renderer_host/render_view_host_impl.h"
25 #include "content/browser/renderer_host/render_widget_host_input_event_router.h" 25 #include "content/browser/renderer_host/render_widget_host_input_event_router.h"
26 #include "content/browser/web_contents/web_contents_impl.h" 26 #include "content/browser/web_contents/web_contents_impl.h"
27 #include "content/common/frame_messages.h" 27 #include "content/common/frame_messages.h"
28 #include "content/common/view_messages.h" 28 #include "content/common/view_messages.h"
29 #include "content/public/browser/notification_observer.h" 29 #include "content/public/browser/notification_observer.h"
30 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/notification_types.h" 31 #include "content/public/browser/notification_types.h"
32 #include "content/public/browser/resource_dispatcher_host.h"
32 #include "content/public/common/content_switches.h" 33 #include "content/public/common/content_switches.h"
33 #include "content/public/test/browser_test_utils.h" 34 #include "content/public/test/browser_test_utils.h"
34 #include "content/public/test/content_browser_test_utils.h" 35 #include "content/public/test/content_browser_test_utils.h"
35 #include "content/public/test/test_navigation_observer.h" 36 #include "content/public/test/test_navigation_observer.h"
36 #include "content/public/test/test_utils.h" 37 #include "content/public/test/test_utils.h"
37 #include "content/shell/browser/shell.h" 38 #include "content/shell/browser/shell.h"
38 #include "content/test/content_browser_test_utils_internal.h" 39 #include "content/test/content_browser_test_utils_internal.h"
39 #include "content/test/test_frame_navigation_observer.h" 40 #include "content/test/test_frame_navigation_observer.h"
40 #include "ipc/ipc_security_test_util.h" 41 #include "ipc/ipc_security_test_util.h"
41 #include "net/dns/mock_host_resolver.h" 42 #include "net/dns/mock_host_resolver.h"
(...skipping 4318 matching lines...) Expand 10 before | Expand all | Expand 10 after
4360 4361
4361 // Make sure the a.com renderer does not crash. 4362 // Make sure the a.com renderer does not crash.
4362 int child_count = 0; 4363 int child_count = 0;
4363 EXPECT_TRUE(ExecuteScriptAndExtractInt( 4364 EXPECT_TRUE(ExecuteScriptAndExtractInt(
4364 root->current_frame_host(), 4365 root->current_frame_host(),
4365 "domAutomationController.send(frames.length)", 4366 "domAutomationController.send(frames.length)",
4366 &child_count)); 4367 &child_count));
4367 EXPECT_EQ(1, child_count); 4368 EXPECT_EQ(1, child_count);
4368 } 4369 }
4369 4370
4371 // This test ensures that the RenderFrame isn't leaked in the renderer process
4372 // if a pending cross-process navigation is cancelled. The test works by trying
4373 // to create a new RenderFrame with the same routing id. If there is an
4374 // entry with the same routing ID, a CHECK is hit and the process crashes.
4375 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
4376 SubframePendingAndBackToSameSiteInstance) {
4377 GURL main_url(embedded_test_server()->GetURL(
4378 "a.com", "/cross_site_iframe_factory.html?a(b)"));
4379 NavigateToURL(shell(), main_url);
4380
4381 // Capture the FrameTreeNode this test will be navigating.
4382 FrameTreeNode* node = static_cast<WebContentsImpl*>(shell()->web_contents())
4383 ->GetFrameTree()
4384 ->root()
4385 ->child_at(0);
4386 EXPECT_TRUE(node);
4387 EXPECT_NE(node->current_frame_host()->GetSiteInstance(),
4388 node->parent()->current_frame_host()->GetSiteInstance());
4389
4390 // Navigate to the site of the parent, but to a page that will not commit.
4391 GURL same_site_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
4392 NavigationStallDelegate stall_delegate(same_site_url);
4393 ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
4394 {
4395 NavigationController::LoadURLParams params(same_site_url);
4396 params.transition_type = ui::PAGE_TRANSITION_LINK;
4397 params.frame_tree_node_id = node->frame_tree_node_id();
4398 node->navigator()->GetController()->LoadURLWithParams(params);
4399 }
4400
4401 // Grab the routing id of the pending RenderFrameHost and set up a process
4402 // observer to ensure there is no crash when a new RenderFrame creation is
4403 // attempted.
4404 RenderProcessHost* process =
4405 node->render_manager()->pending_frame_host()->GetProcess();
4406 RenderProcessHostWatcher watcher(
4407 process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
4408 int frame_routing_id =
4409 node->render_manager()->pending_frame_host()->GetRoutingID();
4410 int proxy_routing_id =
4411 node->render_manager()->GetProxyToParent()->GetRoutingID();
4412
4413 // Now go to c.com so the navigation to a.com is cancelled and send an IPC
4414 // to create a new RenderFrame with the routing id of the previously pending
4415 // one.
4416 NavigateFrameToURL(node,
4417 embedded_test_server()->GetURL("c.com", "/title2.html"));
4418 {
4419 FrameMsg_NewFrame_Params params;
4420 params.routing_id = frame_routing_id;
4421 params.proxy_routing_id = proxy_routing_id;
4422 params.opener_routing_id = MSG_ROUTING_NONE;
4423 params.parent_routing_id =
4424 shell()->web_contents()->GetMainFrame()->GetRoutingID();
4425 params.previous_sibling_routing_id = MSG_ROUTING_NONE;
4426 params.widget_params.routing_id = MSG_ROUTING_NONE;
4427 params.widget_params.hidden = true;
4428
4429 process->Send(new FrameMsg_NewFrame(params));
4430 }
4431
4432 // The test must wait for the process to exit, but if there is no leak, the
4433 // RenderFrame will be properly created and there will be no crash.
4434 // Therefore, navigate the main frame to completely different site, which
4435 // will cause the original process to exit cleanly.
4436 EXPECT_TRUE(NavigateToURL(
4437 shell(), embedded_test_server()->GetURL("d.com", "/title3.html")));
4438 watcher.Wait();
4439 EXPECT_TRUE(watcher.did_exit_normally());
4440
4441 ResourceDispatcherHost::Get()->SetDelegate(nullptr);
4442 }
4443
4444 // This test ensures that the RenderFrame isn't leaked in the renderer process
4445 // when a remote parent detaches a child frame. The test works by trying
4446 // to create a new RenderFrame with the same routing id. If there is an
4447 // entry with the same routing ID, a CHECK is hit and the process crashes.
4448 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ParentDetachRemoteChild) {
4449 GURL main_url(embedded_test_server()->GetURL(
4450 "a.com", "/cross_site_iframe_factory.html?a(b,b)"));
4451 NavigateToURL(shell(), main_url);
4452
4453 WebContentsImpl* web_contents =
4454 static_cast<WebContentsImpl*>(shell()->web_contents());
4455 EXPECT_EQ(2U, web_contents->GetFrameTree()->root()->child_count());
4456
4457 // Capture the FrameTreeNode this test will be navigating.
4458 FrameTreeNode* node = web_contents->GetFrameTree()->root()->child_at(0);
4459 EXPECT_TRUE(node);
4460 EXPECT_NE(node->current_frame_host()->GetSiteInstance(),
4461 node->parent()->current_frame_host()->GetSiteInstance());
4462
4463 // Grab the routing id of the first child RenderFrameHost and set up a process
4464 // observer to ensure there is no crash when a new RenderFrame creation is
4465 // attempted.
4466 RenderProcessHost* process = node->current_frame_host()->GetProcess();
4467 RenderProcessHostWatcher watcher(
4468 process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
4469 int frame_routing_id = node->current_frame_host()->GetRoutingID();
4470 int widget_routing_id =
4471 node->current_frame_host()->GetRenderWidgetHost()->GetRoutingID();
4472 int parent_routing_id =
4473 node->parent()->render_manager()->GetRoutingIdForSiteInstance(
4474 node->current_frame_host()->GetSiteInstance());
4475
4476 // Have the parent frame remove the child frame from its DOM. This should
4477 // result in the child RenderFrame being deleted in the remote process.
4478 EXPECT_TRUE(ExecuteScript(web_contents,
4479 "document.body.removeChild("
4480 "document.querySelectorAll('iframe')[0])"));
4481 EXPECT_EQ(1U, web_contents->GetFrameTree()->root()->child_count());
4482
4483 {
4484 FrameMsg_NewFrame_Params params;
4485 params.routing_id = frame_routing_id;
4486 params.proxy_routing_id = MSG_ROUTING_NONE;
4487 params.opener_routing_id = MSG_ROUTING_NONE;
4488 params.parent_routing_id = parent_routing_id;
4489 params.previous_sibling_routing_id = MSG_ROUTING_NONE;
4490 params.widget_params.routing_id = widget_routing_id;
4491 params.widget_params.hidden = true;
4492
4493 process->Send(new FrameMsg_NewFrame(params));
4494 }
4495
4496 // The test must wait for the process to exit, but if there is no leak, the
4497 // RenderFrame will be properly created and there will be no crash.
4498 // Therefore, navigate the remaining subframe to completely different site,
4499 // which will cause the original process to exit cleanly.
4500 NavigateFrameToURL(
4501 web_contents->GetFrameTree()->root()->child_at(0),
4502 embedded_test_server()->GetURL("d.com", "/title3.html"));
4503 watcher.Wait();
4504 EXPECT_TRUE(watcher.did_exit_normally());
4505 }
4506
4370 } // namespace content 4507 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/frame_host/render_frame_host_impl.cc ('k') | content/common/frame_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698