Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / browser / frame_host / frame_tree_browsertest.cc
blobd96ee59d10e7784f38e88e264369527ad95acee9
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/command_line.h"
6 #include "content/browser/frame_host/frame_tree.h"
7 #include "content/browser/frame_host/frame_tree_node.h"
8 #include "content/browser/renderer_host/render_view_host_impl.h"
9 #include "content/browser/web_contents/web_contents_impl.h"
10 #include "content/public/browser/notification_service.h"
11 #include "content/public/browser/notification_types.h"
12 #include "content/public/common/content_switches.h"
13 #include "content/public/common/url_constants.h"
14 #include "content/public/test/browser_test_utils.h"
15 #include "content/public/test/content_browser_test.h"
16 #include "content/public/test/content_browser_test_utils.h"
17 #include "content/public/test/test_navigation_observer.h"
18 #include "content/public/test/test_utils.h"
19 #include "content/shell/browser/shell.h"
20 #include "content/test/content_browser_test_utils_internal.h"
21 #include "net/dns/mock_host_resolver.h"
23 namespace content {
25 class FrameTreeBrowserTest : public ContentBrowserTest {
26 public:
27 FrameTreeBrowserTest() {}
29 private:
30 DISALLOW_COPY_AND_ASSIGN(FrameTreeBrowserTest);
33 // Ensures FrameTree correctly reflects page structure during navigations.
34 IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeShape) {
35 host_resolver()->AddRule("*", "127.0.0.1");
36 ASSERT_TRUE(test_server()->Start());
38 GURL base_url = test_server()->GetURL("files/site_isolation/");
39 GURL::Replacements replace_host;
40 std::string host_str("A.com"); // Must stay in scope with replace_host.
41 replace_host.SetHostStr(host_str);
42 base_url = base_url.ReplaceComponents(replace_host);
44 // Load doc without iframes. Verify FrameTree just has root.
45 // Frame tree:
46 // Site-A Root
47 NavigateToURL(shell(), base_url.Resolve("blank.html"));
48 FrameTreeNode* root =
49 static_cast<WebContentsImpl*>(shell()->web_contents())->
50 GetFrameTree()->root();
51 EXPECT_EQ(0U, root->child_count());
53 // Add 2 same-site frames. Verify 3 nodes in tree with proper names.
54 // Frame tree:
55 // Site-A Root -- Site-A frame1
56 // \-- Site-A frame2
57 WindowedNotificationObserver observer1(
58 content::NOTIFICATION_LOAD_STOP,
59 content::Source<NavigationController>(
60 &shell()->web_contents()->GetController()));
61 NavigateToURL(shell(), base_url.Resolve("frames-X-X.html"));
62 observer1.Wait();
63 ASSERT_EQ(2U, root->child_count());
64 EXPECT_EQ(0U, root->child_at(0)->child_count());
65 EXPECT_EQ(0U, root->child_at(1)->child_count());
68 // TODO(ajwong): Talk with nasko and merge this functionality with
69 // FrameTreeShape.
70 IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeShape2) {
71 ASSERT_TRUE(test_server()->Start());
72 NavigateToURL(shell(),
73 test_server()->GetURL("files/frame_tree/top.html"));
75 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
76 FrameTreeNode* root = wc->GetFrameTree()->root();
78 // Check that the root node is properly created.
79 ASSERT_EQ(3UL, root->child_count());
80 EXPECT_EQ(std::string(), root->frame_name());
82 ASSERT_EQ(2UL, root->child_at(0)->child_count());
83 EXPECT_STREQ("1-1-name", root->child_at(0)->frame_name().c_str());
85 // Verify the deepest node exists and has the right name.
86 ASSERT_EQ(2UL, root->child_at(2)->child_count());
87 EXPECT_EQ(1UL, root->child_at(2)->child_at(1)->child_count());
88 EXPECT_EQ(0UL, root->child_at(2)->child_at(1)->child_at(0)->child_count());
89 EXPECT_STREQ("3-1-name",
90 root->child_at(2)->child_at(1)->child_at(0)->frame_name().c_str());
92 // Navigate to about:blank, which should leave only the root node of the frame
93 // tree in the browser process.
94 NavigateToURL(shell(), test_server()->GetURL("files/title1.html"));
96 root = wc->GetFrameTree()->root();
97 EXPECT_EQ(0UL, root->child_count());
98 EXPECT_EQ(std::string(), root->frame_name());
101 // Test that we can navigate away if the previous renderer doesn't clean up its
102 // child frames.
103 IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeAfterCrash) {
104 ASSERT_TRUE(test_server()->Start());
105 NavigateToURL(shell(),
106 test_server()->GetURL("files/frame_tree/top.html"));
108 // Crash the renderer so that it doesn't send any FrameDetached messages.
109 RenderProcessHostWatcher crash_observer(
110 shell()->web_contents(),
111 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
112 NavigateToURL(shell(), GURL(kChromeUICrashURL));
113 crash_observer.Wait();
115 // The frame tree should be cleared.
116 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
117 FrameTreeNode* root = wc->GetFrameTree()->root();
118 EXPECT_EQ(0UL, root->child_count());
120 // Navigate to a new URL.
121 GURL url(test_server()->GetURL("files/title1.html"));
122 NavigateToURL(shell(), url);
123 EXPECT_EQ(0UL, root->child_count());
124 EXPECT_EQ(url, root->current_url());
127 // Test that we can navigate away if the previous renderer doesn't clean up its
128 // child frames.
129 IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateWithLeftoverFrames) {
130 host_resolver()->AddRule("*", "127.0.0.1");
131 ASSERT_TRUE(test_server()->Start());
133 GURL base_url = test_server()->GetURL("files/site_isolation/");
134 GURL::Replacements replace_host;
135 std::string host_str("A.com"); // Must stay in scope with replace_host.
136 replace_host.SetHostStr(host_str);
137 base_url = base_url.ReplaceComponents(replace_host);
139 NavigateToURL(shell(),
140 test_server()->GetURL("files/frame_tree/top.html"));
142 // Hang the renderer so that it doesn't send any FrameDetached messages.
143 // (This navigation will never complete, so don't wait for it.)
144 shell()->LoadURL(GURL(kChromeUIHangURL));
146 // Check that the frame tree still has children.
147 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
148 FrameTreeNode* root = wc->GetFrameTree()->root();
149 ASSERT_EQ(3UL, root->child_count());
151 // Navigate to a new URL. We use LoadURL because NavigateToURL will try to
152 // wait for the previous navigation to stop.
153 TestNavigationObserver tab_observer(wc, 1);
154 shell()->LoadURL(base_url.Resolve("blank.html"));
155 tab_observer.Wait();
157 // The frame tree should now be cleared.
158 EXPECT_EQ(0UL, root->child_count());
161 class CrossProcessFrameTreeBrowserTest : public ContentBrowserTest {
162 public:
163 CrossProcessFrameTreeBrowserTest() {}
165 virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
166 command_line->AppendSwitch(switches::kSitePerProcess);
169 private:
170 DISALLOW_COPY_AND_ASSIGN(CrossProcessFrameTreeBrowserTest);
173 // Ensure that we can complete a cross-process subframe navigation.
174 #if defined(OS_ANDROID)
175 #define MAYBE_CreateCrossProcessSubframeProxies DISABLED_CreateCrossProcessSubframeProxies
176 #else
177 #define MAYBE_CreateCrossProcessSubframeProxies CreateCrossProcessSubframeProxies
178 #endif
179 IN_PROC_BROWSER_TEST_F(CrossProcessFrameTreeBrowserTest,
180 MAYBE_CreateCrossProcessSubframeProxies) {
181 host_resolver()->AddRule("*", "127.0.0.1");
182 ASSERT_TRUE(test_server()->Start());
183 GURL main_url(test_server()->GetURL("files/site_per_process_main.html"));
184 NavigateToURL(shell(), main_url);
186 // It is safe to obtain the root frame tree node here, as it doesn't change.
187 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
188 ->GetFrameTree()->root();
190 // There should not be a proxy for the root's own SiteInstance.
191 SiteInstance* root_instance = root->current_frame_host()->GetSiteInstance();
192 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost(root_instance));
194 // Load same-site page into iframe.
195 GURL http_url(test_server()->GetURL("files/title1.html"));
196 NavigateFrameToURL(root->child_at(0), http_url);
198 // These must stay in scope with replace_host.
199 GURL::Replacements replace_host;
200 std::string foo_com("foo.com");
202 // Load cross-site page into iframe.
203 GURL cross_site_url(test_server()->GetURL("files/title2.html"));
204 replace_host.SetHostStr(foo_com);
205 cross_site_url = cross_site_url.ReplaceComponents(replace_host);
206 NavigateFrameToURL(root->child_at(0), cross_site_url);
208 // Ensure that we have created a new process for the subframe.
209 ASSERT_EQ(1U, root->child_count());
210 FrameTreeNode* child = root->child_at(0);
211 SiteInstance* child_instance = child->current_frame_host()->GetSiteInstance();
212 RenderViewHost* rvh = child->current_frame_host()->render_view_host();
213 RenderProcessHost* rph = child->current_frame_host()->GetProcess();
215 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh);
216 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), child_instance);
217 EXPECT_NE(shell()->web_contents()->GetRenderProcessHost(), rph);
219 // Ensure that the root node has a proxy for the child node's SiteInstance.
220 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(child_instance));
222 // Also ensure that the child has a proxy for the root node's SiteInstance.
223 EXPECT_TRUE(child->render_manager()->GetRenderFrameProxyHost(root_instance));
225 // The nodes should not have proxies for their own SiteInstance.
226 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost(root_instance));
227 EXPECT_FALSE(
228 child->render_manager()->GetRenderFrameProxyHost(child_instance));
231 } // namespace content