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 "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "content/browser/frame_host/cross_process_frame_connector.h" | 10 #include "content/browser/frame_host/cross_process_frame_connector.h" |
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 | 371 |
372 // Navigate back to the parent's origin and ensure we return to the | 372 // Navigate back to the parent's origin and ensure we return to the |
373 // parent's process. | 373 // parent's process. |
374 NavigateFrameToURL(child, http_url); | 374 NavigateFrameToURL(child, http_url); |
375 EXPECT_EQ(http_url, observer.navigation_url()); | 375 EXPECT_EQ(http_url, observer.navigation_url()); |
376 EXPECT_TRUE(observer.navigation_succeeded()); | 376 EXPECT_TRUE(observer.navigation_succeeded()); |
377 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(), | 377 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(), |
378 child->current_frame_host()->GetSiteInstance()); | 378 child->current_frame_host()->GetSiteInstance()); |
379 } | 379 } |
380 | 380 |
381 // This test checks that killing a renderer process of a remote frame | |
382 // and then navigating some other frame to the same SiteInstance of the killed | |
383 // process works properly. | |
384 // This can be illustrated as follows, | |
385 // where 1/2/3 are FrameTreeNode-s and A/B are processes and B* is the killed | |
386 // B process: | |
387 // | |
388 // 1 A A A | |
389 // / \ -> / \ -> Kill B -> / \ -> Navigate 3 to B -> / \ . | |
390 // 2 3 B A B* A B* B | |
391 // | |
392 // Initially, node1.proxy_hosts_ = {B} | |
393 // After we kill B, we make sure B stays in node1.proxy_hosts_, then we navigate | |
394 // 3 to B and we expect that to complete normally. | |
395 // See http://crbug.com/432107. | |
396 // | |
397 // Note that due to http://crbug.com/450681, node2 cannot be re-navigated to | |
398 // site B and stays in not rendered state. | |
399 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
400 NavigateRemoteFrameToKilledProcess) { | |
401 GURL main_url(embedded_test_server()->GetURL( | |
402 "/frame_tree/page_with_two_frames.html")); | |
403 NavigateToURL(shell(), main_url); | |
404 | |
405 // It is safe to obtain the root frame tree node here, as it doesn't change. | |
406 FrameTreeNode* root = | |
407 static_cast<WebContentsImpl*>(shell()->web_contents())-> | |
408 GetFrameTree()->root(); | |
409 | |
410 SitePerProcessWebContentsObserver observer(shell()->web_contents()); | |
411 ASSERT_EQ(2U, root->child_count()); | |
412 | |
413 // Make sure node2 points to the correct cross-site page. | |
414 GURL site_b_url = embedded_test_server()->GetURL("bar.com", "/title1.html"); | |
415 FrameTreeNode* node2 = root->child_at(0); | |
416 EXPECT_EQ(site_b_url, node2->current_url()); | |
417 | |
418 // Kill that cross-site renderer. | |
419 RenderProcessHost* child_process = | |
420 node2->current_frame_host()->GetProcess(); | |
421 RenderProcessHostWatcher crash_observer( | |
422 child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | |
423 child_process->Shutdown(0, false); | |
424 crash_observer.Wait(); | |
425 | |
426 // Now navigate the second iframe (node3) to the same site as the node2. | |
427 FrameTreeNode* node3 = root->child_at(1); | |
428 NavigateFrameToURL(node3, site_b_url); | |
429 EXPECT_TRUE(observer.navigation_succeeded()); | |
430 EXPECT_EQ(site_b_url, observer.navigation_url()); | |
431 } | |
432 | |
433 // This test is similar to | |
434 // SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcess with | |
435 // addition that node2 also has a cross-origin frame to site C. | |
436 // | |
437 // 1 A A A | |
438 // / \ / \ / \ / \ . | |
439 // 2 3 -> B A -> Kill B -> B* A -> Navigate 3 -> B* B | |
440 // / / | |
441 // 4 C | |
442 // | |
443 // Initially, node1.proxy_hosts_ = {B, C} | |
444 // After we kill B, we make sure B stays in node1.proxy_hosts_, but | |
445 // C gets cleared from node1.proxy_hosts_. | |
446 // | |
447 // Note that due to another bug node2 does not re-navigate to site B and stays | |
nasko
2015/02/02 22:47:09
nit: cite the bug number here, as you've done in t
lazyboy
2015/02/03 00:22:42
Done.
| |
448 // in not rendered state. | |
449 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
450 NavigateRemoteFrameToKilledProcessWithSubtree) { | |
451 GURL main_url( | |
452 embedded_test_server()->GetURL( | |
453 "/frame_tree/page_with_two_frames_nested.html")); | |
454 NavigateToURL(shell(), main_url); | |
455 | |
456 // It is safe to obtain the root frame tree node here, as it doesn't change. | |
457 FrameTreeNode* root = | |
458 static_cast<WebContentsImpl*>(shell()->web_contents())-> | |
459 GetFrameTree()->root(); | |
460 SitePerProcessWebContentsObserver observer(shell()->web_contents()); | |
461 | |
462 ASSERT_EQ(2U, root->child_count()); | |
463 | |
464 GURL site_b_url( | |
465 embedded_test_server()->GetURL( | |
466 "bar.com", "/frame_tree/page_with_one_frame.html")); | |
467 // We can't use a SitePerProcessWebContentsObserver to verify the URL here, | |
468 // since the frame has children that may have clobbered it in the observer. | |
469 EXPECT_EQ(site_b_url, root->child_at(0)->current_url()); | |
470 | |
471 // Ensure that a new process is created for node2. | |
472 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), | |
473 root->child_at(0)->current_frame_host()->GetSiteInstance()); | |
474 // Ensure that a new process is *not* created for node3. | |
475 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(), | |
476 root->child_at(1)->current_frame_host()->GetSiteInstance()); | |
477 | |
478 ASSERT_EQ(1U, root->child_at(0)->child_count()); | |
lazyboy
2015/01/22 23:32:35
This is the part I was worried about: whether the
nasko
2015/02/02 22:47:09
This should work. It waits for DidStopLoading, whi
lazyboy
2015/02/03 00:22:42
Acknowledged.
| |
479 | |
480 // Make sure node4 points to the correct cross-site page. | |
481 FrameTreeNode* node4 = root->child_at(0)->child_at(0); | |
482 GURL site_c_url(embedded_test_server()->GetURL("baz.com", "/title1.html")); | |
483 EXPECT_EQ(site_c_url, node4->current_url()); | |
484 | |
485 // |site_instance_c| is expected to go away once we kill |child_process_b| | |
486 // below, so create a local scope so we can extend the lifetime of | |
487 // |site_instance_c| with a refptr. | |
488 { | |
489 SiteInstance* site_instance_b = | |
490 root->child_at(0)->current_frame_host()->GetSiteInstance(); | |
491 // |site_c| will go away, so extend its lifetime with a refptr. | |
492 scoped_refptr<SiteInstanceImpl> site_instance_c = | |
493 node4->current_frame_host()->GetSiteInstance(); | |
494 | |
495 // Initially proxies for both B and C will be present in the root and node3. | |
496 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost( | |
497 site_instance_b)); | |
498 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost( | |
499 site_instance_c.get())); | |
500 FrameTreeNode* node3 = root->child_at(1); | |
501 EXPECT_TRUE(node3->render_manager()->GetRenderFrameProxyHost( | |
502 site_instance_b)); | |
503 EXPECT_TRUE(node3->render_manager()->GetRenderFrameProxyHost( | |
504 site_instance_c.get())); | |
505 | |
506 // Kill that cross-site renderer/process B. | |
507 RenderProcessHost* child_process_b = | |
508 root->child_at(0)->current_frame_host()->GetProcess(); | |
509 RenderProcessHostWatcher crash_observer( | |
510 child_process_b, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | |
511 child_process_b->Shutdown(0, false); | |
512 crash_observer.Wait(); | |
513 | |
514 // Make sure proxy B stays around in root and node3. | |
515 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost( | |
516 site_instance_b)); | |
517 EXPECT_TRUE(node3->render_manager()->GetRenderFrameProxyHost( | |
518 site_instance_b)); | |
519 // Make sure proxy C goes away from root and node3. | |
520 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost( | |
521 site_instance_c.get())); | |
522 EXPECT_FALSE(node3->render_manager()->GetRenderFrameProxyHost( | |
523 site_instance_c.get())); | |
524 } | |
525 | |
526 // Now navigate the second iframe (node3) to the same site as the node2. | |
527 FrameTreeNode* node3 = root->child_at(1); | |
528 GURL url = embedded_test_server()->GetURL("bar.com", "/title1.html"); | |
529 NavigateFrameToURL(node3, url); | |
530 EXPECT_TRUE(observer.navigation_succeeded()); | |
531 EXPECT_EQ(url, observer.navigation_url()); | |
532 } | |
533 | |
381 // In A-embed-B-embed-C scenario, verify that killing process B clears proxies | 534 // In A-embed-B-embed-C scenario, verify that killing process B clears proxies |
382 // of C from the tree. | 535 // of C from the tree. |
383 // | 536 // |
384 // 1 A A | 537 // 1 A A |
385 // / \ / \ / \ . | 538 // / \ / \ / \ . |
386 // 2 3 -> B A -> Kill B -> B* A | 539 // 2 3 -> B A -> Kill B -> B* A |
387 // / / | 540 // / / |
388 // 4 C | 541 // 4 C |
389 // | 542 // |
390 // node1 is the root. | 543 // node1 is the root. |
391 // Initially, both node1.proxy_hosts_ and node3.proxy_hosts_ contain C. | 544 // Initially, both node1.proxy_hosts_ and node3.proxy_hosts_ contain C. |
392 // After we kill B, make sure proxies for C are cleared. | 545 // After we kill B, make sure proxies for C are cleared. |
393 // | |
394 // TODO(lazyboy): Once http://crbug.com/432107 is fixed, we should also make | |
395 // sure that proxies for B are not cleared when we kill B. | |
396 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | 546 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
397 KillingRendererClearsDescendantProxies) { | 547 KillingRendererClearsDescendantProxies) { |
398 GURL main_url( | 548 GURL main_url( |
399 embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html")); | 549 embedded_test_server()->GetURL( |
550 "/frame_tree/page_with_two_frames_nested.html")); | |
400 NavigateToURL(shell(), main_url); | 551 NavigateToURL(shell(), main_url); |
401 | 552 |
402 // It is safe to obtain the root frame tree node here, as it doesn't change. | 553 // It is safe to obtain the root frame tree node here, as it doesn't change. |
403 FrameTreeNode* root = | 554 FrameTreeNode* root = |
404 static_cast<WebContentsImpl*>(shell()->web_contents())-> | 555 static_cast<WebContentsImpl*>(shell()->web_contents())-> |
405 GetFrameTree()->root(); | 556 GetFrameTree()->root(); |
406 SitePerProcessWebContentsObserver observer(shell()->web_contents()); | 557 SitePerProcessWebContentsObserver observer(shell()->web_contents()); |
407 | 558 |
408 ASSERT_EQ(2U, root->child_count()); | 559 ASSERT_EQ(2U, root->child_count()); |
409 | 560 |
410 // Navigate the second subframe (node3) to a local frame. | |
411 GURL site_a_url(embedded_test_server()->GetURL("/title1.html")); | |
412 NavigateFrameToURL(root->child_at(1), site_a_url); | |
413 | |
414 // Navigate the first subframe (node2) to a cross-site page with two | |
415 // subframes. | |
416 // NavigateFrameToURL can't be used here because it doesn't guarantee that | |
417 // FrameTreeNodes will have been created for child frames when it returns. | |
418 RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 3); | |
419 GURL site_b_url( | 561 GURL site_b_url( |
420 embedded_test_server()->GetURL( | 562 embedded_test_server()->GetURL( |
421 "bar.com", "/frame_tree/page_with_one_frame.html")); | 563 "bar.com", "/frame_tree/page_with_one_frame.html")); |
422 NavigationController::LoadURLParams params_b(site_b_url); | |
423 params_b.transition_type = ui::PAGE_TRANSITION_LINK; | |
424 params_b.frame_tree_node_id = root->child_at(0)->frame_tree_node_id(); | |
425 root->child_at(0)->navigator()->GetController()->LoadURLWithParams(params_b); | |
426 frame_observer.Wait(); | |
427 | |
428 // We can't use a SitePerProcessWebContentsObserver to verify the URL here, | 564 // We can't use a SitePerProcessWebContentsObserver to verify the URL here, |
429 // since the frame has children that may have clobbered it in the observer. | 565 // since the frame has children that may have clobbered it in the observer. |
430 EXPECT_EQ(site_b_url, root->child_at(0)->current_url()); | 566 EXPECT_EQ(site_b_url, root->child_at(0)->current_url()); |
431 | 567 |
432 // Ensure that a new process is created for node2. | 568 // Ensure that a new process is created for node2. |
433 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), | 569 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), |
434 root->child_at(0)->current_frame_host()->GetSiteInstance()); | 570 root->child_at(0)->current_frame_host()->GetSiteInstance()); |
435 // Ensure that a new process is *not* created for node3. | 571 // Ensure that a new process is *not* created for node3. |
436 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(), | 572 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(), |
437 root->child_at(1)->current_frame_host()->GetSiteInstance()); | 573 root->child_at(1)->current_frame_host()->GetSiteInstance()); |
438 | 574 |
439 ASSERT_EQ(1U, root->child_at(0)->child_count()); | 575 ASSERT_EQ(1U, root->child_at(0)->child_count()); |
440 | 576 |
441 // Navigate node4 to cross-site-page. | 577 // Make sure node4 points to the correct cross-site-page. |
442 FrameTreeNode* node4 = root->child_at(0)->child_at(0); | 578 FrameTreeNode* node4 = root->child_at(0)->child_at(0); |
443 GURL site_c_url(embedded_test_server()->GetURL("baz.com", "/title2.html")); | 579 GURL site_c_url(embedded_test_server()->GetURL("baz.com", "/title1.html")); |
444 NavigateFrameToURL(node4, site_c_url); | 580 EXPECT_EQ(site_c_url, node4->current_url()); |
445 EXPECT_TRUE(observer.navigation_succeeded()); | |
446 EXPECT_EQ(site_c_url, observer.navigation_url()); | |
447 | 581 |
448 // |site_instance_c| is expected to go away once we kill |child_process_b| | 582 // |site_instance_c| is expected to go away once we kill |child_process_b| |
449 // below, so create a local scope so we can extend the lifetime of | 583 // below, so create a local scope so we can extend the lifetime of |
450 // |site_instance_c| with a refptr. | 584 // |site_instance_c| with a refptr. |
451 { | 585 { |
452 SiteInstance* site_instance_b = | 586 SiteInstance* site_instance_b = |
453 root->child_at(0)->current_frame_host()->GetSiteInstance(); | 587 root->child_at(0)->current_frame_host()->GetSiteInstance(); |
454 scoped_refptr<SiteInstanceImpl> site_instance_c = | 588 scoped_refptr<SiteInstanceImpl> site_instance_c = |
455 node4->current_frame_host()->GetSiteInstance(); | 589 node4->current_frame_host()->GetSiteInstance(); |
456 | 590 |
(...skipping 10 matching lines...) Expand all Loading... | |
467 child_process_b, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | 601 child_process_b, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
468 child_process_b->Shutdown(0, false); | 602 child_process_b->Shutdown(0, false); |
469 crash_observer.Wait(); | 603 crash_observer.Wait(); |
470 | 604 |
471 // Make sure proxy C has gone from root. | 605 // Make sure proxy C has gone from root. |
472 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost( | 606 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost( |
473 site_instance_c.get())); | 607 site_instance_c.get())); |
474 // Make sure proxy C has gone from node3 as well. | 608 // Make sure proxy C has gone from node3 as well. |
475 EXPECT_FALSE(root->child_at(1)->render_manager()->GetRenderFrameProxyHost( | 609 EXPECT_FALSE(root->child_at(1)->render_manager()->GetRenderFrameProxyHost( |
476 site_instance_c.get())); | 610 site_instance_c.get())); |
477 // TODO(lazyboy): Once http://crbug.com/432107 is fixed, we should also | 611 // Make sure proxy B stays around in root and node3. |
478 // check that proxy B exists in both root and node3. | 612 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost( |
613 site_instance_b)); | |
614 EXPECT_TRUE(root->child_at(1)->render_manager()->GetRenderFrameProxyHost( | |
615 site_instance_b)); | |
479 } | 616 } |
480 } | 617 } |
481 | 618 |
482 // Crash a subframe and ensures its children are cleared from the FrameTree. | 619 // Crash a subframe and ensures its children are cleared from the FrameTree. |
483 // See http://crbug.com/338508. | 620 // See http://crbug.com/338508. |
484 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrashSubframe) { | 621 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrashSubframe) { |
485 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); | 622 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); |
486 NavigateToURL(shell(), main_url); | 623 NavigateToURL(shell(), main_url); |
487 | 624 |
488 StartFrameAtDataURL(); | 625 StartFrameAtDataURL(); |
(...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1082 params.frame_tree_node_id = child->frame_tree_node_id(); | 1219 params.frame_tree_node_id = child->frame_tree_node_id(); |
1083 child->navigator()->GetController()->LoadURLWithParams(params); | 1220 child->navigator()->GetController()->LoadURLWithParams(params); |
1084 nav_observer.Wait(); | 1221 nav_observer.Wait(); |
1085 | 1222 |
1086 // Verify that the navigation succeeded and the expected URL was loaded. | 1223 // Verify that the navigation succeeded and the expected URL was loaded. |
1087 EXPECT_TRUE(observer.navigation_succeeded()); | 1224 EXPECT_TRUE(observer.navigation_succeeded()); |
1088 EXPECT_EQ(url, observer.navigation_url()); | 1225 EXPECT_EQ(url, observer.navigation_url()); |
1089 } | 1226 } |
1090 | 1227 |
1091 } // namespace content | 1228 } // namespace content |
OLD | NEW |