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 | |
nasko
2015/01/20 23:51:23
"navigate B" is unclear. Does it mean "navigate 3
lazyboy
2015/01/21 18:52:14
Yes, Done.
| |
394 // B and we expect that to complete normally. | |
395 // See http://crbug.com/432107. | |
396 // | |
397 // Note that due to another bug node2 does not re-navigate to site B and stays | |
nasko
2015/01/20 23:51:23
Do we have a bug filed for this? If not, let's fil
lazyboy
2015/01/21 18:52:14
Filed bug and added reference to it.
| |
398 // in not rendered state. | |
399 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
400 NavigateRemoteFrameToKilledProcess) { | |
401 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); | |
402 NavigateToURL(shell(), main_url); | |
403 | |
404 // It is safe to obtain the root frame tree node here, as it doesn't change. | |
405 FrameTreeNode* node1 = | |
nasko
2015/01/20 23:51:23
nit: s/node1/root/
lazyboy
2015/01/21 18:52:14
Done.
| |
406 static_cast<WebContentsImpl*>(shell()->web_contents())-> | |
407 GetFrameTree()->root(); | |
408 | |
409 SitePerProcessWebContentsObserver observer(shell()->web_contents()); | |
410 ASSERT_EQ(2U, node1->child_count()); | |
411 | |
412 FrameTreeNode* node2 = node1->child_at(0); | |
413 // Load cross-site page into first iframe (node2). | |
414 GURL url = embedded_test_server()->GetURL("foo.com", "/title1.html"); | |
415 NavigateFrameToURL(node2, url); | |
416 EXPECT_TRUE(observer.navigation_succeeded()); | |
417 EXPECT_EQ(url, observer.navigation_url()); | |
418 | |
419 // Kill that cross-site renderer. | |
420 RenderProcessHost* child_process = | |
421 node2->current_frame_host()->GetProcess(); | |
422 RenderProcessHostWatcher crash_observer( | |
423 child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | |
424 child_process->Shutdown(0, false); | |
425 crash_observer.Wait(); | |
426 | |
427 // Now navigate the second iframe (node3) to the same site as the node2. | |
428 FrameTreeNode* node3 = node1->child_at(1); | |
429 url = embedded_test_server()->GetURL("foo.com", "/title2.html"); | |
430 NavigateFrameToURL(node3, url); | |
431 EXPECT_TRUE(observer.navigation_succeeded()); | |
432 EXPECT_EQ(url, observer.navigation_url()); | |
433 } | |
434 | |
435 // This test is similar to | |
436 // SitePerProcessBrowserTest.NavigateRemoteFrameToKilledProcess with | |
437 // addition that node2 also has a cross-origin frame to site C. | |
438 // | |
439 // 1 A A A | |
440 // / \ / \ / \ / \ . | |
441 // 2 3 -> B A -> Kill B -> B* A -> Navigate 3 -> B* B | |
442 // / / | |
443 // 4 C | |
nasko
2015/01/20 23:51:23
Awesome ASCII art! It is very useful to understand
lazyboy
2015/01/21 18:52:14
Acknowledged.
| |
444 // | |
445 // Initially, node1.proxy_hosts_ = {B, C} | |
446 // After we kill B, we make sure B stays in node1.proxy_hosts_, but | |
447 // C gets cleared from node1.proxy_hosts_. | |
448 // | |
449 // Note that due to another bug node2 does not re-navigate to site B and stays | |
450 // in not rendered state. | |
451 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
452 NavigateRemoteFrameToKilledProcessWithSubtree) { | |
453 GURL main_url( | |
454 embedded_test_server()->GetURL( | |
455 "/frame_tree/page_with_two_frames.html")); | |
456 NavigateToURL(shell(), main_url); | |
457 | |
458 // It is safe to obtain the root frame tree node here, as it doesn't change. | |
459 FrameTreeNode* root = | |
460 static_cast<WebContentsImpl*>(shell()->web_contents())-> | |
461 GetFrameTree()->root(); | |
462 SitePerProcessWebContentsObserver observer(shell()->web_contents()); | |
463 | |
464 // Navigate the second subframe (node3) to a local frame. | |
465 GURL site_a_url(embedded_test_server()->GetURL("/title1.html")); | |
nasko
2015/01/20 23:51:23
It will be useful to just create a full structure
lazyboy
2015/01/21 18:52:14
This could only be done for the second subframe (n
lazyboy
2015/01/22 23:32:35
After discussion, I've update this further. Now th
| |
466 NavigateFrameToURL(root->child_at(1), site_a_url); | |
467 | |
468 // Navigate the first subframe (node2) to a cross-site page with two | |
469 // subframes. | |
470 // NavigateFrameToURL can't be used here because it doesn't guarantee that | |
471 // FrameTreeNodes will have been created for child frames when it returns. | |
472 RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 3); | |
473 GURL site_b_url( | |
474 embedded_test_server()->GetURL( | |
475 "bar.com", "/frame_tree/page_with_one_frame.html")); | |
476 NavigationController::LoadURLParams params_b(site_b_url); | |
477 params_b.transition_type = ui::PAGE_TRANSITION_LINK; | |
478 params_b.frame_tree_node_id = root->child_at(0)->frame_tree_node_id(); | |
479 root->child_at(0)->navigator()->GetController()->LoadURLWithParams(params_b); | |
480 frame_observer.Wait(); | |
481 | |
482 ASSERT_EQ(2U, root->child_count()); | |
483 | |
484 // We can't use a SitePerProcessWebContentsObserver to verify the URL here, | |
485 // since the frame has children that may have clobbered it in the observer. | |
486 EXPECT_EQ(site_b_url, root->child_at(0)->current_url()); | |
487 | |
488 // Ensure that a new process is created for node2. | |
489 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), | |
490 root->child_at(0)->current_frame_host()->GetSiteInstance()); | |
491 // Ensure that a new process is *not* created for node3. | |
492 EXPECT_EQ(shell()->web_contents()->GetSiteInstance(), | |
493 root->child_at(1)->current_frame_host()->GetSiteInstance()); | |
494 | |
495 ASSERT_EQ(1U, root->child_at(0)->child_count()); | |
496 | |
497 // Navigate node4 to cross-site-page. | |
498 FrameTreeNode* node4 = root->child_at(0)->child_at(0); | |
499 GURL site_c_url(embedded_test_server()->GetURL("baz.com", "/title2.html")); | |
500 NavigateFrameToURL(node4, site_c_url); | |
501 EXPECT_TRUE(observer.navigation_succeeded()); | |
502 EXPECT_EQ(site_c_url, observer.navigation_url()); | |
503 | |
504 // |site_instance_c| is expected to go away once we kill |child_process_b| | |
505 // below, so create a local scope so we can extend the lifetime of | |
506 // |site_instance_c| with a refptr. | |
507 { | |
508 SiteInstance* site_instance_b = | |
509 root->child_at(0)->current_frame_host()->GetSiteInstance(); | |
510 // |site_c| will go away, so extend its lifetime with a refptr. | |
511 scoped_refptr<SiteInstanceImpl> site_instance_c = | |
512 node4->current_frame_host()->GetSiteInstance(); | |
513 | |
514 // Initially proxies for both B and C will be present in the root and node3. | |
515 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost( | |
516 site_instance_b)); | |
517 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost( | |
518 site_instance_c.get())); | |
519 FrameTreeNode* node3 = root->child_at(1); | |
520 EXPECT_TRUE(node3->render_manager()->GetRenderFrameProxyHost( | |
521 site_instance_b)); | |
522 EXPECT_TRUE(node3->render_manager()->GetRenderFrameProxyHost( | |
523 site_instance_c.get())); | |
524 | |
525 // Kill that cross-site renderer/process B. | |
526 RenderProcessHost* child_process_b = | |
527 root->child_at(0)->current_frame_host()->GetProcess(); | |
528 RenderProcessHostWatcher crash_observer( | |
529 child_process_b, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | |
530 child_process_b->Shutdown(0, false); | |
531 crash_observer.Wait(); | |
532 | |
533 // Make sure proxy B stays around in root and node3. | |
534 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost( | |
535 site_instance_b)); | |
536 EXPECT_TRUE(node3->render_manager()->GetRenderFrameProxyHost( | |
537 site_instance_b)); | |
538 // Make sure proxy C goes away from root and node3. | |
539 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost( | |
540 site_instance_c.get())); | |
541 EXPECT_FALSE(node3->render_manager()->GetRenderFrameProxyHost( | |
542 site_instance_c.get())); | |
543 } | |
544 | |
545 // Now navigate the second iframe (node3) to the same site as the node2. | |
546 FrameTreeNode* node3 = root->child_at(1); | |
547 GURL url = embedded_test_server()->GetURL("bar.com", "/title1.html"); | |
548 NavigateFrameToURL(node3, url); | |
549 EXPECT_TRUE(observer.navigation_succeeded()); | |
550 EXPECT_EQ(url, observer.navigation_url()); | |
551 } | |
552 | |
381 // In A-embed-B-embed-C scenario, verify that killing process B clears proxies | 553 // In A-embed-B-embed-C scenario, verify that killing process B clears proxies |
382 // of C from the tree. | 554 // of C from the tree. |
383 // | 555 // |
384 // 1 A A | 556 // 1 A A |
385 // / \ / \ / \ . | 557 // / \ / \ / \ . |
386 // 2 3 -> B A -> Kill B -> B* A | 558 // 2 3 -> B A -> Kill B -> B* A |
387 // / / | 559 // / / |
388 // 4 C | 560 // 4 C |
389 // | 561 // |
390 // node1 is the root. | 562 // node1 is the root. |
391 // Initially, both node1.proxy_hosts_ and node3.proxy_hosts_ contain C. | 563 // Initially, both node1.proxy_hosts_ and node3.proxy_hosts_ contain C. |
392 // After we kill B, make sure proxies for C are cleared. | 564 // 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, | 565 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
397 KillingRendererClearsDescendantProxies) { | 566 KillingRendererClearsDescendantProxies) { |
398 GURL main_url( | 567 GURL main_url( |
399 embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html")); | 568 embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html")); |
400 NavigateToURL(shell(), main_url); | 569 NavigateToURL(shell(), main_url); |
401 | 570 |
402 // It is safe to obtain the root frame tree node here, as it doesn't change. | 571 // It is safe to obtain the root frame tree node here, as it doesn't change. |
403 FrameTreeNode* root = | 572 FrameTreeNode* root = |
404 static_cast<WebContentsImpl*>(shell()->web_contents())-> | 573 static_cast<WebContentsImpl*>(shell()->web_contents())-> |
405 GetFrameTree()->root(); | 574 GetFrameTree()->root(); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 child_process_b, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | 636 child_process_b, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
468 child_process_b->Shutdown(0, false); | 637 child_process_b->Shutdown(0, false); |
469 crash_observer.Wait(); | 638 crash_observer.Wait(); |
470 | 639 |
471 // Make sure proxy C has gone from root. | 640 // Make sure proxy C has gone from root. |
472 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost( | 641 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost( |
473 site_instance_c.get())); | 642 site_instance_c.get())); |
474 // Make sure proxy C has gone from node3 as well. | 643 // Make sure proxy C has gone from node3 as well. |
475 EXPECT_FALSE(root->child_at(1)->render_manager()->GetRenderFrameProxyHost( | 644 EXPECT_FALSE(root->child_at(1)->render_manager()->GetRenderFrameProxyHost( |
476 site_instance_c.get())); | 645 site_instance_c.get())); |
477 // TODO(lazyboy): Once http://crbug.com/432107 is fixed, we should also | 646 // Make sure proxy B stays around in root and node3. |
478 // check that proxy B exists in both root and node3. | 647 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost( |
648 site_instance_b)); | |
649 EXPECT_TRUE(root->child_at(1)->render_manager()->GetRenderFrameProxyHost( | |
650 site_instance_b)); | |
479 } | 651 } |
480 } | 652 } |
481 | 653 |
482 // Crash a subframe and ensures its children are cleared from the FrameTree. | 654 // Crash a subframe and ensures its children are cleared from the FrameTree. |
483 // See http://crbug.com/338508. | 655 // See http://crbug.com/338508. |
484 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrashSubframe) { | 656 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrashSubframe) { |
485 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); | 657 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); |
486 NavigateToURL(shell(), main_url); | 658 NavigateToURL(shell(), main_url); |
487 | 659 |
488 StartFrameAtDataURL(); | 660 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(); | 1254 params.frame_tree_node_id = child->frame_tree_node_id(); |
1083 child->navigator()->GetController()->LoadURLWithParams(params); | 1255 child->navigator()->GetController()->LoadURLWithParams(params); |
1084 nav_observer.Wait(); | 1256 nav_observer.Wait(); |
1085 | 1257 |
1086 // Verify that the navigation succeeded and the expected URL was loaded. | 1258 // Verify that the navigation succeeded and the expected URL was loaded. |
1087 EXPECT_TRUE(observer.navigation_succeeded()); | 1259 EXPECT_TRUE(observer.navigation_succeeded()); |
1088 EXPECT_EQ(url, observer.navigation_url()); | 1260 EXPECT_EQ(url, observer.navigation_url()); |
1089 } | 1261 } |
1090 | 1262 |
1091 } // namespace content | 1263 } // namespace content |
OLD | NEW |