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 "content/browser/frame_host/cross_process_frame_connector.h" | 9 #include "content/browser/frame_host/cross_process_frame_connector.h" |
10 #include "content/browser/frame_host/frame_tree.h" | 10 #include "content/browser/frame_host/frame_tree.h" |
| 11 #include "content/browser/frame_host/navigator.h" |
11 #include "content/browser/frame_host/render_frame_proxy_host.h" | 12 #include "content/browser/frame_host/render_frame_proxy_host.h" |
12 #include "content/browser/frame_host/render_widget_host_view_child_frame.h" | 13 #include "content/browser/frame_host/render_widget_host_view_child_frame.h" |
13 #include "content/browser/renderer_host/render_view_host_impl.h" | 14 #include "content/browser/renderer_host/render_view_host_impl.h" |
14 #include "content/browser/web_contents/web_contents_impl.h" | 15 #include "content/browser/web_contents/web_contents_impl.h" |
15 #include "content/public/browser/notification_observer.h" | 16 #include "content/public/browser/notification_observer.h" |
16 #include "content/public/browser/notification_service.h" | 17 #include "content/public/browser/notification_service.h" |
17 #include "content/public/browser/notification_types.h" | 18 #include "content/public/browser/notification_types.h" |
18 #include "content/public/browser/web_contents_observer.h" | 19 #include "content/public/browser/web_contents_observer.h" |
19 #include "content/public/common/content_switches.h" | 20 #include "content/public/common/content_switches.h" |
20 #include "content/public/test/browser_test_utils.h" | 21 #include "content/public/test/browser_test_utils.h" |
21 #include "content/public/test/content_browser_test_utils.h" | 22 #include "content/public/test/content_browser_test_utils.h" |
22 #include "content/public/test/test_utils.h" | 23 #include "content/public/test/test_utils.h" |
23 #include "content/shell/browser/shell.h" | 24 #include "content/shell/browser/shell.h" |
24 #include "content/test/content_browser_test_utils_internal.h" | 25 #include "content/test/content_browser_test_utils_internal.h" |
| 26 #include "content/test/test_frame_navigation_observer.h" |
25 #include "net/dns/mock_host_resolver.h" | 27 #include "net/dns/mock_host_resolver.h" |
26 #include "net/test/embedded_test_server/embedded_test_server.h" | 28 #include "net/test/embedded_test_server/embedded_test_server.h" |
27 | 29 |
28 namespace content { | 30 namespace content { |
29 | 31 |
30 class SitePerProcessWebContentsObserver: public WebContentsObserver { | 32 class SitePerProcessWebContentsObserver: public WebContentsObserver { |
31 public: | 33 public: |
32 explicit SitePerProcessWebContentsObserver(WebContents* web_contents) | 34 explicit SitePerProcessWebContentsObserver(WebContents* web_contents) |
33 : WebContentsObserver(web_contents), | 35 : WebContentsObserver(web_contents), |
34 navigation_succeeded_(false) {} | 36 navigation_succeeded_(false) {} |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 root->child_at(0), | 241 root->child_at(0), |
240 embedded_test_server()->GetURL("/cross-site/foo.com/title2.html")); | 242 embedded_test_server()->GetURL("/cross-site/foo.com/title2.html")); |
241 // Verify that the navigation succeeded and the expected URL was loaded. | 243 // Verify that the navigation succeeded and the expected URL was loaded. |
242 EXPECT_TRUE(observer.navigation_succeeded()); | 244 EXPECT_TRUE(observer.navigation_succeeded()); |
243 EXPECT_EQ(embedded_test_server()->base_url().scheme(), | 245 EXPECT_EQ(embedded_test_server()->base_url().scheme(), |
244 observer.navigation_url().scheme()); | 246 observer.navigation_url().scheme()); |
245 EXPECT_EQ("foo.com", observer.navigation_url().host()); | 247 EXPECT_EQ("foo.com", observer.navigation_url().host()); |
246 EXPECT_EQ("/title2.html", observer.navigation_url().path()); | 248 EXPECT_EQ("/title2.html", observer.navigation_url().path()); |
247 | 249 |
248 // Ensure that we have created a new process for the subframe. | 250 // Ensure that we have created a new process for the subframe. |
249 ASSERT_EQ(1U, root->child_count()); | 251 ASSERT_EQ(2U, root->child_count()); |
250 SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance(); | 252 SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance(); |
251 RenderViewHost* rvh = child->current_frame_host()->render_view_host(); | 253 RenderViewHost* rvh = child->current_frame_host()->render_view_host(); |
252 RenderProcessHost* rph = child->current_frame_host()->GetProcess(); | 254 RenderProcessHost* rph = child->current_frame_host()->GetProcess(); |
253 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh); | 255 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh); |
254 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance); | 256 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance); |
255 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph); | 257 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph); |
256 { | 258 { |
257 // There should be now two RenderWidgetHosts, one for each process | 259 // There should be now two RenderWidgetHosts, one for each process |
258 // rendering a frame. | 260 // rendering a frame. |
259 std::set<RenderWidgetHostView*> views_set = | 261 std::set<RenderWidgetHostView*> views_set = |
(...skipping 13 matching lines...) Expand all Loading... |
273 root->child_at(0), | 275 root->child_at(0), |
274 embedded_test_server()->GetURL("/cross-site/bar.com/title3.html")); | 276 embedded_test_server()->GetURL("/cross-site/bar.com/title3.html")); |
275 EXPECT_TRUE(observer.navigation_succeeded()); | 277 EXPECT_TRUE(observer.navigation_succeeded()); |
276 EXPECT_EQ(embedded_test_server()->base_url().scheme(), | 278 EXPECT_EQ(embedded_test_server()->base_url().scheme(), |
277 observer.navigation_url().scheme()); | 279 observer.navigation_url().scheme()); |
278 EXPECT_EQ("bar.com", observer.navigation_url().host()); | 280 EXPECT_EQ("bar.com", observer.navigation_url().host()); |
279 EXPECT_EQ("/title3.html", observer.navigation_url().path()); | 281 EXPECT_EQ("/title3.html", observer.navigation_url().path()); |
280 | 282 |
281 // Check again that a new process is created and is different from the | 283 // Check again that a new process is created and is different from the |
282 // top level one and the previous one. | 284 // top level one and the previous one. |
283 ASSERT_EQ(1U, root->child_count()); | 285 ASSERT_EQ(2U, root->child_count()); |
284 child = root->child_at(0); | 286 child = root->child_at(0); |
285 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), | 287 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), |
286 child->current_frame_host()->render_view_host()); | 288 child->current_frame_host()->render_view_host()); |
287 EXPECT_NE(rvh, child->current_frame_host()->render_view_host()); | 289 EXPECT_NE(rvh, child->current_frame_host()->render_view_host()); |
288 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), | 290 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), |
289 child->current_frame_host()->GetSiteInstance()); | 291 child->current_frame_host()->GetSiteInstance()); |
290 EXPECT_NE(site_instance, | 292 EXPECT_NE(site_instance, |
291 child->current_frame_host()->GetSiteInstance()); | 293 child->current_frame_host()->GetSiteInstance()); |
292 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), | 294 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), |
293 child->current_frame_host()->GetProcess()); | 295 child->current_frame_host()->GetProcess()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 | 334 |
333 // Load cross-site page into iframe. | 335 // Load cross-site page into iframe. |
334 NavigateFrameToURL( | 336 NavigateFrameToURL( |
335 root->child_at(0), | 337 root->child_at(0), |
336 embedded_test_server()->GetURL("/cross-site/foo.com/title2.html")); | 338 embedded_test_server()->GetURL("/cross-site/foo.com/title2.html")); |
337 EXPECT_TRUE(observer.navigation_succeeded()); | 339 EXPECT_TRUE(observer.navigation_succeeded()); |
338 EXPECT_EQ("foo.com", observer.navigation_url().host()); | 340 EXPECT_EQ("foo.com", observer.navigation_url().host()); |
339 EXPECT_EQ("/title2.html", observer.navigation_url().path()); | 341 EXPECT_EQ("/title2.html", observer.navigation_url().path()); |
340 | 342 |
341 // Ensure that we have created a new process for the subframe. | 343 // Ensure that we have created a new process for the subframe. |
342 ASSERT_EQ(1U, root->child_count()); | 344 ASSERT_EQ(2U, root->child_count()); |
343 SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance(); | 345 SiteInstance* site_instance = child->current_frame_host()->GetSiteInstance(); |
344 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance); | 346 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance); |
345 | 347 |
346 // Emulate the main frame changing the src of the iframe such that it | 348 // Emulate the main frame changing the src of the iframe such that it |
347 // navigates cross-site. | 349 // navigates cross-site. |
348 NavigateIframeToURL( | 350 NavigateIframeToURL( |
349 shell(), | 351 shell(), |
350 embedded_test_server()->GetURL("/cross-site/bar.com/title3.html"), | 352 embedded_test_server()->GetURL("/cross-site/bar.com/title3.html"), |
351 "test"); | 353 "test"); |
352 EXPECT_TRUE(observer.navigation_succeeded()); | 354 EXPECT_TRUE(observer.navigation_succeeded()); |
353 EXPECT_EQ("bar.com", observer.navigation_url().host()); | 355 EXPECT_EQ("bar.com", observer.navigation_url().host()); |
354 EXPECT_EQ("/title3.html", observer.navigation_url().path()); | 356 EXPECT_EQ("/title3.html", observer.navigation_url().path()); |
355 | 357 |
356 // Check again that a new process is created and is different from the | 358 // Check again that a new process is created and is different from the |
357 // top level one and the previous one. | 359 // top level one and the previous one. |
358 ASSERT_EQ(1U, root->child_count()); | 360 ASSERT_EQ(2U, root->child_count()); |
359 child = root->child_at(0); | 361 child = root->child_at(0); |
360 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), | 362 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), |
361 child->current_frame_host()->GetSiteInstance()); | 363 child->current_frame_host()->GetSiteInstance()); |
362 EXPECT_NE(site_instance, | 364 EXPECT_NE(site_instance, |
363 child->current_frame_host()->GetSiteInstance()); | 365 child->current_frame_host()->GetSiteInstance()); |
364 | 366 |
365 // TODO(japhet): This currently causes an assertion in the renderer process. | 367 // TODO(japhet): This currently causes an assertion in the renderer process. |
366 // Enable when the assertion is fixed. | 368 // Enable when the assertion is fixed. |
367 //NavigateFrameToURL(child, http_url); | 369 //NavigateFrameToURL(child, http_url); |
368 //EXPECT_EQ(http_url, observer.navigation_url()); | 370 //EXPECT_EQ(http_url, observer.navigation_url()); |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 GURL server_redirect_http_url(test_server()->GetURL( | 643 GURL server_redirect_http_url(test_server()->GetURL( |
642 "server-redirect?" + client_redirect_http_url.spec())); | 644 "server-redirect?" + client_redirect_http_url.spec())); |
643 EXPECT_TRUE(NavigateIframeToURL(shell(), server_redirect_http_url, "test")); | 645 EXPECT_TRUE(NavigateIframeToURL(shell(), server_redirect_http_url, "test")); |
644 | 646 |
645 // DidFailProvisionalLoad when navigating to client_redirect_http_url. | 647 // DidFailProvisionalLoad when navigating to client_redirect_http_url. |
646 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url); | 648 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url); |
647 EXPECT_FALSE(observer.navigation_succeeded()); | 649 EXPECT_FALSE(observer.navigation_succeeded()); |
648 } | 650 } |
649 } | 651 } |
650 | 652 |
| 653 // Ensure that when navigating a frame cross-process RenderFrameProxyHosts are |
| 654 // created in the FrameTree skipping the subtree of the navigating frame. |
| 655 // TODO(nasko): Test is disabled on Android, because it times out. It should |
| 656 // be fixed together with CrossSiteIframe on that platform. |
| 657 #if defined(OS_ANDROID) |
| 658 #define MAYBE_ProxyCreationSkipsSubtree DISABLED_ProxyCreationSkipsSubtree |
| 659 #else |
| 660 #define MAYBE_ProxyCreationSkipsSubtree ProxyCreationSkipsSubtree |
| 661 #endif |
| 662 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
| 663 MAYBE_ProxyCreationSkipsSubtree) { |
| 664 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); |
| 665 NavigateToURL(shell(), main_url); |
| 666 |
| 667 // It is safe to obtain the root frame tree node here, as it doesn't change. |
| 668 FrameTreeNode* root = |
| 669 static_cast<WebContentsImpl*>(shell()->web_contents())-> |
| 670 GetFrameTree()->root(); |
| 671 |
| 672 EXPECT_TRUE(root->child_at(1) != NULL); |
| 673 EXPECT_EQ(2U, root->child_at(1)->child_count()); |
| 674 |
| 675 { |
| 676 // Load same-site page into iframe. |
| 677 SitePerProcessWebContentsObserver observer(shell()->web_contents()); |
| 678 GURL http_url(embedded_test_server()->GetURL("/title1.html")); |
| 679 NavigateFrameToURL(root->child_at(0), http_url); |
| 680 EXPECT_EQ(http_url, observer.navigation_url()); |
| 681 EXPECT_TRUE(observer.navigation_succeeded()); |
| 682 RenderFrameProxyHost* proxy_to_parent = |
| 683 root->child_at(0)->render_manager()->GetRenderFrameProxyHost( |
| 684 shell()->web_contents()->GetSiteInstance()); |
| 685 EXPECT_FALSE(proxy_to_parent); |
| 686 } |
| 687 |
| 688 // Create the cross-site URL to navigate to. |
| 689 GURL::Replacements replace_host; |
| 690 std::string foo_com("foo.com"); |
| 691 GURL cross_site_url(embedded_test_server()->GetURL("/frame_tree/1-1.html")); |
| 692 replace_host.SetHostStr(foo_com); |
| 693 cross_site_url = cross_site_url.ReplaceComponents(replace_host); |
| 694 |
| 695 // Load cross-site page into the second iframe without waiting for the |
| 696 // navigation to complete. Once LoadURLWithParams returns, we would expect |
| 697 // proxies to have been created in the frame tree, but children of the |
| 698 // navigating frame to still be present. The reason is that we don't run the |
| 699 // message loop, so no IPCs that alter the frame tree can be processed. |
| 700 FrameTreeNode* child = root->child_at(1); |
| 701 SiteInstance* site = NULL; |
| 702 { |
| 703 SitePerProcessWebContentsObserver observer(shell()->web_contents()); |
| 704 TestFrameNavigationObserver navigation_observer(child); |
| 705 NavigationController::LoadURLParams params(cross_site_url); |
| 706 params.transition_type = PageTransitionFromInt(ui::PAGE_TRANSITION_LINK); |
| 707 params.frame_tree_node_id = child->frame_tree_node_id(); |
| 708 child->navigator()->GetController()->LoadURLWithParams(params); |
| 709 EXPECT_TRUE(child->render_manager()->pending_frame_host()); |
| 710 |
| 711 site = child->render_manager()->pending_frame_host()->GetSiteInstance(); |
| 712 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site); |
| 713 |
| 714 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(site)); |
| 715 EXPECT_TRUE( |
| 716 root->child_at(0)->render_manager()->GetRenderFrameProxyHost(site)); |
| 717 EXPECT_FALSE(child->render_manager()->GetRenderFrameProxyHost(site)); |
| 718 for (size_t i = 0; i < child->child_count(); ++i) { |
| 719 EXPECT_FALSE( |
| 720 child->child_at(i)->render_manager()->GetRenderFrameProxyHost(site)); |
| 721 } |
| 722 // Now that the verification is done, run the message loop and wait for the |
| 723 // navigation to complete. |
| 724 navigation_observer.Wait(); |
| 725 EXPECT_FALSE(child->render_manager()->pending_frame_host()); |
| 726 EXPECT_EQ(cross_site_url, observer.navigation_url()); |
| 727 EXPECT_TRUE(observer.navigation_succeeded()); |
| 728 } |
| 729 |
| 730 // Load another cross-site page into the same iframe. |
| 731 cross_site_url = embedded_test_server()->GetURL("/title2.html"); |
| 732 std::string bar_com("bar.com"); |
| 733 replace_host.SetHostStr(bar_com); |
| 734 cross_site_url = cross_site_url.ReplaceComponents(replace_host); |
| 735 |
| 736 { |
| 737 // Perform the same checks as the first cross-site navigation, since |
| 738 // there have been issues in subsequent cross-site navigations. Also ensure |
| 739 // that the SiteInstance has properly changed. |
| 740 // TODO(nasko): Once we have proper cleanup of resources, add code to |
| 741 // verify that the intermediate SiteInstance/RenderFrameHost have been |
| 742 // properly cleaned up. |
| 743 SitePerProcessWebContentsObserver observer(shell()->web_contents()); |
| 744 TestFrameNavigationObserver navigation_observer(child); |
| 745 NavigationController::LoadURLParams params(cross_site_url); |
| 746 params.transition_type = PageTransitionFromInt(ui::PAGE_TRANSITION_LINK); |
| 747 params.frame_tree_node_id = child->frame_tree_node_id(); |
| 748 child->navigator()->GetController()->LoadURLWithParams(params); |
| 749 EXPECT_TRUE(child->render_manager()->pending_frame_host() != NULL); |
| 750 |
| 751 SiteInstance* site2 = |
| 752 child->render_manager()->pending_frame_host()->GetSiteInstance(); |
| 753 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site2); |
| 754 EXPECT_NE(site, site2); |
| 755 |
| 756 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(site2)); |
| 757 EXPECT_TRUE( |
| 758 root->child_at(0)->render_manager()->GetRenderFrameProxyHost(site2)); |
| 759 EXPECT_FALSE(child->render_manager()->GetRenderFrameProxyHost(site2)); |
| 760 for (size_t i = 0; i < child->child_count(); ++i) { |
| 761 EXPECT_FALSE( |
| 762 child->child_at(i)->render_manager()->GetRenderFrameProxyHost(site2)); |
| 763 } |
| 764 |
| 765 navigation_observer.Wait(); |
| 766 EXPECT_EQ(cross_site_url, observer.navigation_url()); |
| 767 EXPECT_TRUE(observer.navigation_succeeded()); |
| 768 EXPECT_EQ(0U, child->child_count()); |
| 769 } |
| 770 } |
| 771 |
651 } // namespace content | 772 } // namespace content |
OLD | NEW |