blob: 6a2c55f44d33a208ac440c7fdf3a8a5518e04324 [file] [log] [blame]
[email protected]5f96f5a62014-01-10 00:05:111// 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.
4
Ken Rockot86bea1c2017-05-16 06:21:355#include "base/command_line.h"
avib7348942015-12-25 20:57:106#include "base/macros.h"
7#include "build/build_config.h"
[email protected]5f96f5a62014-01-10 00:05:118#include "content/browser/frame_host/frame_tree.h"
9#include "content/browser/frame_host/frame_tree_node.h"
Lukasz Anforowicz9e0ce4e2017-09-28 19:09:1510#include "content/browser/frame_host/render_frame_host_impl.h"
[email protected]5f96f5a62014-01-10 00:05:1111#include "content/browser/renderer_host/render_view_host_impl.h"
12#include "content/browser/web_contents/web_contents_impl.h"
13#include "content/public/browser/notification_service.h"
14#include "content/public/browser/notification_types.h"
nickdb193a12016-09-09 23:09:2315#include "content/public/common/content_switches.h"
[email protected]5f96f5a62014-01-10 00:05:1116#include "content/public/common/url_constants.h"
17#include "content/public/test/browser_test_utils.h"
[email protected]6e9def12014-03-27 20:23:2818#include "content/public/test/content_browser_test.h"
19#include "content/public/test/content_browser_test_utils.h"
[email protected]5f96f5a62014-01-10 00:05:1120#include "content/public/test/test_navigation_observer.h"
21#include "content/public/test/test_utils.h"
22#include "content/shell/browser/shell.h"
nickdb193a12016-09-09 23:09:2323#include "content/shell/common/shell_switches.h"
[email protected]82307f6b2014-08-07 03:30:1224#include "content/test/content_browser_test_utils_internal.h"
[email protected]5f96f5a62014-01-10 00:05:1125#include "net/dns/mock_host_resolver.h"
alexmos478dcbb2014-12-10 21:24:4626#include "net/test/embedded_test_server/embedded_test_server.h"
Blink Reformata30d4232018-04-07 15:31:0627#include "third_party/blink/public/common/frame/sandbox_flags.h"
nick1466c842015-11-25 20:08:0628#include "url/url_constants.h"
[email protected]5f96f5a62014-01-10 00:05:1129
30namespace content {
31
nickdb193a12016-09-09 23:09:2332namespace {
33
Nick Carterb7e71312018-08-03 23:36:1334EvalJsResult GetOriginFromRenderer(FrameTreeNode* node) {
Philip Jägenstedt67302a22018-09-14 09:58:0535 return EvalJs(node, "self.origin");
nickdb193a12016-09-09 23:09:2336}
37
38} // namespace
39
[email protected]5f96f5a62014-01-10 00:05:1140class FrameTreeBrowserTest : public ContentBrowserTest {
41 public:
42 FrameTreeBrowserTest() {}
43
alexmos478dcbb2014-12-10 21:24:4644 void SetUpOnMainThread() override {
45 host_resolver()->AddRule("*", "127.0.0.1");
alexmos478dcbb2014-12-10 21:24:4646 SetupCrossSiteRedirector(embedded_test_server());
martijn12d2dad2016-11-11 10:59:2747 ASSERT_TRUE(embedded_test_server()->Start());
alexmos478dcbb2014-12-10 21:24:4648 }
49
[email protected]5f96f5a62014-01-10 00:05:1150 private:
51 DISALLOW_COPY_AND_ASSIGN(FrameTreeBrowserTest);
52};
53
54// Ensures FrameTree correctly reflects page structure during navigations.
55IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeShape) {
alexmos478dcbb2014-12-10 21:24:4656 GURL base_url = embedded_test_server()->GetURL("A.com", "/site_isolation/");
[email protected]5f96f5a62014-01-10 00:05:1157
58 // Load doc without iframes. Verify FrameTree just has root.
59 // Frame tree:
60 // Site-A Root
61 NavigateToURL(shell(), base_url.Resolve("blank.html"));
62 FrameTreeNode* root =
63 static_cast<WebContentsImpl*>(shell()->web_contents())->
64 GetFrameTree()->root();
65 EXPECT_EQ(0U, root->child_count());
66
67 // Add 2 same-site frames. Verify 3 nodes in tree with proper names.
68 // Frame tree:
69 // Site-A Root -- Site-A frame1
70 // \-- Site-A frame2
71 WindowedNotificationObserver observer1(
72 content::NOTIFICATION_LOAD_STOP,
73 content::Source<NavigationController>(
74 &shell()->web_contents()->GetController()));
75 NavigateToURL(shell(), base_url.Resolve("frames-X-X.html"));
76 observer1.Wait();
77 ASSERT_EQ(2U, root->child_count());
78 EXPECT_EQ(0U, root->child_at(0)->child_count());
79 EXPECT_EQ(0U, root->child_at(1)->child_count());
80}
81
82// TODO(ajwong): Talk with nasko and merge this functionality with
83// FrameTreeShape.
84IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeShape2) {
[email protected]5f96f5a62014-01-10 00:05:1185 NavigateToURL(shell(),
alexmos478dcbb2014-12-10 21:24:4686 embedded_test_server()->GetURL("/frame_tree/top.html"));
[email protected]5f96f5a62014-01-10 00:05:1187
88 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
[email protected]5f96f5a62014-01-10 00:05:1189 FrameTreeNode* root = wc->GetFrameTree()->root();
90
[email protected]58faf942014-02-20 21:03:5891 // Check that the root node is properly created.
[email protected]5f96f5a62014-01-10 00:05:1192 ASSERT_EQ(3UL, root->child_count());
93 EXPECT_EQ(std::string(), root->frame_name());
[email protected]5f96f5a62014-01-10 00:05:1194
95 ASSERT_EQ(2UL, root->child_at(0)->child_count());
96 EXPECT_STREQ("1-1-name", root->child_at(0)->frame_name().c_str());
97
98 // Verify the deepest node exists and has the right name.
99 ASSERT_EQ(2UL, root->child_at(2)->child_count());
100 EXPECT_EQ(1UL, root->child_at(2)->child_at(1)->child_count());
101 EXPECT_EQ(0UL, root->child_at(2)->child_at(1)->child_at(0)->child_count());
[email protected]b0cd7a952014-03-08 11:44:06102 EXPECT_STREQ("3-1-name",
[email protected]5f96f5a62014-01-10 00:05:11103 root->child_at(2)->child_at(1)->child_at(0)->frame_name().c_str());
104
105 // Navigate to about:blank, which should leave only the root node of the frame
106 // tree in the browser process.
alexmos478dcbb2014-12-10 21:24:46107 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
[email protected]5f96f5a62014-01-10 00:05:11108
109 root = wc->GetFrameTree()->root();
110 EXPECT_EQ(0UL, root->child_count());
111 EXPECT_EQ(std::string(), root->frame_name());
[email protected]5f96f5a62014-01-10 00:05:11112}
113
114// Test that we can navigate away if the previous renderer doesn't clean up its
115// child frames.
116IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeAfterCrash) {
[email protected]5f96f5a62014-01-10 00:05:11117 NavigateToURL(shell(),
alexmos478dcbb2014-12-10 21:24:46118 embedded_test_server()->GetURL("/frame_tree/top.html"));
[email protected]5f96f5a62014-01-10 00:05:11119
creise42f2a52014-09-18 18:14:57120 // Ensure the view and frame are live.
121 RenderViewHost* rvh = shell()->web_contents()->GetRenderViewHost();
122 RenderFrameHostImpl* rfh =
123 static_cast<RenderFrameHostImpl*>(rvh->GetMainFrame());
124 EXPECT_TRUE(rvh->IsRenderViewLive());
125 EXPECT_TRUE(rfh->IsRenderFrameLive());
126
[email protected]5f96f5a62014-01-10 00:05:11127 // Crash the renderer so that it doesn't send any FrameDetached messages.
128 RenderProcessHostWatcher crash_observer(
129 shell()->web_contents(),
130 RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
Wez0abfbf512018-03-03 01:54:45131 ASSERT_TRUE(
132 shell()->web_contents()->GetMainFrame()->GetProcess()->Shutdown(0));
[email protected]5f96f5a62014-01-10 00:05:11133 crash_observer.Wait();
134
[email protected]58faf942014-02-20 21:03:58135 // The frame tree should be cleared.
[email protected]5f96f5a62014-01-10 00:05:11136 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
[email protected]5f96f5a62014-01-10 00:05:11137 FrameTreeNode* root = wc->GetFrameTree()->root();
138 EXPECT_EQ(0UL, root->child_count());
[email protected]5f96f5a62014-01-10 00:05:11139
creise42f2a52014-09-18 18:14:57140 // Ensure the view and frame aren't live anymore.
141 EXPECT_FALSE(rvh->IsRenderViewLive());
142 EXPECT_FALSE(rfh->IsRenderFrameLive());
143
[email protected]5f96f5a62014-01-10 00:05:11144 // Navigate to a new URL.
alexmos478dcbb2014-12-10 21:24:46145 GURL url(embedded_test_server()->GetURL("/title1.html"));
[email protected]58faf942014-02-20 21:03:58146 NavigateToURL(shell(), url);
[email protected]5f96f5a62014-01-10 00:05:11147 EXPECT_EQ(0UL, root->child_count());
[email protected]58faf942014-02-20 21:03:58148 EXPECT_EQ(url, root->current_url());
creise42f2a52014-09-18 18:14:57149
150 // Ensure the view and frame are live again.
151 EXPECT_TRUE(rvh->IsRenderViewLive());
152 EXPECT_TRUE(rfh->IsRenderFrameLive());
[email protected]5f96f5a62014-01-10 00:05:11153}
154
155// Test that we can navigate away if the previous renderer doesn't clean up its
156// child frames.
pauljensen58ee2ea22015-01-26 17:45:53157// Flaky on Mac. http://crbug.com/452018
158#if defined(OS_MACOSX)
159#define MAYBE_NavigateWithLeftoverFrames DISABLED_NavigateWithLeftoverFrames
160#else
161#define MAYBE_NavigateWithLeftoverFrames NavigateWithLeftoverFrames
162#endif
163IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, MAYBE_NavigateWithLeftoverFrames) {
alexmos478dcbb2014-12-10 21:24:46164 GURL base_url = embedded_test_server()->GetURL("A.com", "/site_isolation/");
[email protected]5f96f5a62014-01-10 00:05:11165
166 NavigateToURL(shell(),
alexmos478dcbb2014-12-10 21:24:46167 embedded_test_server()->GetURL("/frame_tree/top.html"));
[email protected]5f96f5a62014-01-10 00:05:11168
169 // Hang the renderer so that it doesn't send any FrameDetached messages.
170 // (This navigation will never complete, so don't wait for it.)
171 shell()->LoadURL(GURL(kChromeUIHangURL));
172
173 // Check that the frame tree still has children.
174 WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
175 FrameTreeNode* root = wc->GetFrameTree()->root();
176 ASSERT_EQ(3UL, root->child_count());
177
178 // Navigate to a new URL. We use LoadURL because NavigateToURL will try to
179 // wait for the previous navigation to stop.
180 TestNavigationObserver tab_observer(wc, 1);
181 shell()->LoadURL(base_url.Resolve("blank.html"));
182 tab_observer.Wait();
183
[email protected]58faf942014-02-20 21:03:58184 // The frame tree should now be cleared.
[email protected]5f96f5a62014-01-10 00:05:11185 EXPECT_EQ(0UL, root->child_count());
[email protected]5f96f5a62014-01-10 00:05:11186}
187
creise42f2a52014-09-18 18:14:57188// Ensure that IsRenderFrameLive is true for main frames and same-site iframes.
189IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, IsRenderFrameLive) {
alexmos478dcbb2014-12-10 21:24:46190 GURL main_url(embedded_test_server()->GetURL("/frame_tree/top.html"));
creise42f2a52014-09-18 18:14:57191 NavigateToURL(shell(), main_url);
192
193 // It is safe to obtain the root frame tree node here, as it doesn't change.
194 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
195 ->GetFrameTree()->root();
196
197 // The root and subframe should each have a live RenderFrame.
198 EXPECT_TRUE(
199 root->current_frame_host()->render_view_host()->IsRenderViewLive());
200 EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
201 EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
202
203 // Load a same-site page into iframe and it should still be live.
alexmos478dcbb2014-12-10 21:24:46204 GURL http_url(embedded_test_server()->GetURL("/title1.html"));
creise42f2a52014-09-18 18:14:57205 NavigateFrameToURL(root->child_at(0), http_url);
206 EXPECT_TRUE(
207 root->current_frame_host()->render_view_host()->IsRenderViewLive());
208 EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
209 EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
210}
211
alexmosbc7eafa2014-12-06 01:38:09212// Ensure that origins are correctly set on navigations.
213IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, OriginSetOnNavigation) {
nick1466c842015-11-25 20:08:06214 GURL about_blank(url::kAboutBlankURL);
215 GURL main_url(
216 embedded_test_server()->GetURL("a.com", "/frame_tree/top.html"));
alexmosbc7eafa2014-12-06 01:38:09217 EXPECT_TRUE(NavigateToURL(shell(), main_url));
nick1466c842015-11-25 20:08:06218 WebContents* contents = shell()->web_contents();
alexmosbc7eafa2014-12-06 01:38:09219
220 // It is safe to obtain the root frame tree node here, as it doesn't change.
nick1466c842015-11-25 20:08:06221 FrameTreeNode* root =
222 static_cast<WebContentsImpl*>(contents)->GetFrameTree()->root();
alexmosbc7eafa2014-12-06 01:38:09223
224 // Extra '/' is added because the replicated origin is serialized in RFC 6454
225 // format, which dictates no trailing '/', whereas GURL::GetOrigin does put a
226 // '/' at the end.
nick1466c842015-11-25 20:08:06227 EXPECT_EQ(main_url.GetOrigin().spec(),
228 root->current_origin().Serialize() + '/');
229 EXPECT_EQ(
230 main_url.GetOrigin().spec(),
231 root->current_frame_host()->GetLastCommittedOrigin().Serialize() + '/');
alexmosbc7eafa2014-12-06 01:38:09232
nick1466c842015-11-25 20:08:06233 // The iframe is inititially same-origin.
234 EXPECT_TRUE(
235 root->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
236 root->child_at(0)->current_frame_host()->GetLastCommittedOrigin()));
237 EXPECT_EQ(root->current_origin().Serialize(), GetOriginFromRenderer(root));
238 EXPECT_EQ(root->child_at(0)->current_origin().Serialize(),
239 GetOriginFromRenderer(root->child_at(0)));
240
241 // Navigate the iframe cross-origin.
242 GURL frame_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
alexmosbc7eafa2014-12-06 01:38:09243 NavigateFrameToURL(root->child_at(0), frame_url);
nick1466c842015-11-25 20:08:06244 EXPECT_EQ(frame_url, root->child_at(0)->current_url());
245 EXPECT_EQ(frame_url.GetOrigin().spec(),
246 root->child_at(0)->current_origin().Serialize() + '/');
247 EXPECT_FALSE(
248 root->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
249 root->child_at(0)->current_frame_host()->GetLastCommittedOrigin()));
250 EXPECT_EQ(root->current_origin().Serialize(), GetOriginFromRenderer(root));
251 EXPECT_EQ(root->child_at(0)->current_origin().Serialize(),
252 GetOriginFromRenderer(root->child_at(0)));
alexmosbc7eafa2014-12-06 01:38:09253
nick1466c842015-11-25 20:08:06254 // Parent-initiated about:blank navigation should inherit the parent's a.com
255 // origin.
256 NavigateIframeToURL(contents, "1-1-id", about_blank);
257 EXPECT_EQ(about_blank, root->child_at(0)->current_url());
258 EXPECT_EQ(main_url.GetOrigin().spec(),
259 root->child_at(0)->current_origin().Serialize() + '/');
260 EXPECT_EQ(root->current_frame_host()->GetLastCommittedOrigin().Serialize(),
261 root->child_at(0)
262 ->current_frame_host()
263 ->GetLastCommittedOrigin()
264 .Serialize());
265 EXPECT_TRUE(
266 root->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
267 root->child_at(0)->current_frame_host()->GetLastCommittedOrigin()));
268 EXPECT_EQ(root->current_origin().Serialize(), GetOriginFromRenderer(root));
269 EXPECT_EQ(root->child_at(0)->current_origin().Serialize(),
270 GetOriginFromRenderer(root->child_at(0)));
alexmosbc7eafa2014-12-06 01:38:09271
272 GURL data_url("data:text/html,foo");
273 EXPECT_TRUE(NavigateToURL(shell(), data_url));
274
275 // Navigating to a data URL should set a unique origin. This is represented
276 // as "null" per RFC 6454.
nick1466c842015-11-25 20:08:06277 EXPECT_EQ("null", root->current_origin().Serialize());
278 EXPECT_TRUE(contents->GetMainFrame()->GetLastCommittedOrigin().unique());
279 EXPECT_EQ("null", GetOriginFromRenderer(root));
alexmosbc7eafa2014-12-06 01:38:09280
281 // Re-navigating to a normal URL should update the origin.
282 EXPECT_TRUE(NavigateToURL(shell(), main_url));
nick1466c842015-11-25 20:08:06283 EXPECT_EQ(main_url.GetOrigin().spec(),
284 root->current_origin().Serialize() + '/');
285 EXPECT_EQ(
286 main_url.GetOrigin().spec(),
287 contents->GetMainFrame()->GetLastCommittedOrigin().Serialize() + '/');
288 EXPECT_FALSE(contents->GetMainFrame()->GetLastCommittedOrigin().unique());
289 EXPECT_EQ(root->current_origin().Serialize(), GetOriginFromRenderer(root));
alexmosbc7eafa2014-12-06 01:38:09290}
291
nick9f34e2892016-01-12 21:01:07292// Tests a cross-origin navigation to a blob URL. The main frame initiates this
293// navigation on its grandchild. It should wind up in the main frame's process.
294IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateGrandchildToBlob) {
295 WebContents* contents = shell()->web_contents();
296 FrameTreeNode* root =
297 static_cast<WebContentsImpl*>(contents)->GetFrameTree()->root();
298
299 // First, snapshot the FrameTree for a normal A(B(A)) case where all frames
300 // are served over http. The blob test should result in the same structure.
301 EXPECT_TRUE(NavigateToURL(
302 shell(), embedded_test_server()->GetURL(
303 "a.com", "/cross_site_iframe_factory.html?a(b(a))")));
304 std::string reference_tree = FrameTreeVisualizer().DepictFrameTree(root);
305
306 GURL main_url(embedded_test_server()->GetURL(
307 "a.com", "/cross_site_iframe_factory.html?a(b(c))"));
308 EXPECT_TRUE(NavigateToURL(shell(), main_url));
309
310 // The root node will initiate the navigation; its grandchild node will be the
311 // target of the navigation.
312 FrameTreeNode* target = root->child_at(0)->child_at(0);
313
creisb2d5f1f32016-11-07 23:25:05314 RenderFrameDeletedObserver deleted_observer(target->current_frame_host());
Nick Carterb7e71312018-08-03 23:36:13315 std::string html =
316 "<html><body><div>This is blob content.</div>"
317 "<script>"
Philip Jägenstedt67302a22018-09-14 09:58:05318 "window.parent.parent.postMessage('HI', self.origin);"
Nick Carterb7e71312018-08-03 23:36:13319 "</script></body></html>";
320 std::string script = JsReplace(
321 "new Promise((resolve) => {"
322 " window.addEventListener('message', resolve, false);"
323 " var blob = new Blob([$1], {type: 'text/html'});"
324 " var blob_url = URL.createObjectURL(blob);"
325 " frames[0][0].location.href = blob_url;"
326 "}).then((event) => {"
nick9f34e2892016-01-12 21:01:07327 " document.body.appendChild(document.createTextNode(event.data));"
Nick Carterb7e71312018-08-03 23:36:13328 " return event.source.location.href;"
329 "});",
330 html);
331 std::string blob_url_string = EvalJs(root, script).ExtractString();
creisb2d5f1f32016-11-07 23:25:05332 // Wait for the RenderFrame to go away, if this will be cross-process.
333 if (AreAllSitesIsolatedForTesting())
334 deleted_observer.WaitUntilDeleted();
nick9f34e2892016-01-12 21:01:07335 EXPECT_EQ(GURL(blob_url_string), target->current_url());
336 EXPECT_EQ(url::kBlobScheme, target->current_url().scheme());
337 EXPECT_FALSE(target->current_origin().unique());
338 EXPECT_EQ("a.com", target->current_origin().host());
339 EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
Nick Carterb7e71312018-08-03 23:36:13340 EXPECT_EQ("This is blob content.",
341 EvalJs(target, "document.body.children[0].innerHTML"));
nick9f34e2892016-01-12 21:01:07342 EXPECT_EQ(reference_tree, FrameTreeVisualizer().DepictFrameTree(root));
343}
344
345IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, NavigateChildToAboutBlank) {
346 GURL main_url(embedded_test_server()->GetURL(
347 "a.com", "/cross_site_iframe_factory.html?a(b(c))"));
348 EXPECT_TRUE(NavigateToURL(shell(), main_url));
349 WebContentsImpl* contents =
350 static_cast<WebContentsImpl*>(shell()->web_contents());
351
352 // The leaf node (c.com) will be navigated. Its parent node (b.com) will
353 // initiate the navigation.
354 FrameTreeNode* target =
355 contents->GetFrameTree()->root()->child_at(0)->child_at(0);
356 FrameTreeNode* initiator = target->parent();
357
358 // Give the target a name.
Nick Carterb7e71312018-08-03 23:36:13359 EXPECT_TRUE(ExecJs(target, "window.name = 'target';"));
nick9f34e2892016-01-12 21:01:07360
361 // Use window.open(about:blank), then poll the document for access.
Nick Carterb7e71312018-08-03 23:36:13362 EvalJsResult about_blank_origin = EvalJs(
nickadef4a52016-06-09 18:45:54363 initiator,
Nick Carterb7e71312018-08-03 23:36:13364 "new Promise(resolve => {"
365 " var didNavigate = false;"
366 " var intervalID = setInterval(function() {"
367 " if (!didNavigate) {"
368 " didNavigate = true;"
369 " window.open('about:blank', 'target');"
370 " }"
371 " // Poll the document until it doesn't throw a SecurityError.\n"
372 " try {"
373 " frames[0].document.write('Hi from ' + document.domain);"
374 " } catch (e) { return; }"
375 " clearInterval(intervalID);"
Philip Jägenstedt67302a22018-09-14 09:58:05376 " resolve(frames[0].self.origin);"
Nick Carterb7e71312018-08-03 23:36:13377 " }, 16);"
378 "});");
379 EXPECT_EQ(target->current_origin(), about_blank_origin);
nick9f34e2892016-01-12 21:01:07380 EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url());
381 EXPECT_EQ(url::kAboutScheme, target->current_url().scheme());
382 EXPECT_FALSE(target->current_origin().unique());
383 EXPECT_EQ("b.com", target->current_origin().host());
384 EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
nick9f34e2892016-01-12 21:01:07385
Nick Carterb7e71312018-08-03 23:36:13386 EXPECT_EQ("Hi from b.com", EvalJs(target, "document.body.innerHTML"));
nick9f34e2892016-01-12 21:01:07387}
388
389// Nested iframes, three origins: A(B(C)). Frame A navigates C to about:blank
390// (via window.open). This should wind up in A's origin per the spec. Test fails
391// because of http://crbug.com/564292
392IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest,
393 DISABLED_NavigateGrandchildToAboutBlank) {
394 GURL main_url(embedded_test_server()->GetURL(
395 "a.com", "/cross_site_iframe_factory.html?a(b(c))"));
396 EXPECT_TRUE(NavigateToURL(shell(), main_url));
397 WebContentsImpl* contents =
398 static_cast<WebContentsImpl*>(shell()->web_contents());
399
400 // The leaf node (c.com) will be navigated. Its grandparent node (a.com) will
401 // initiate the navigation.
402 FrameTreeNode* target =
403 contents->GetFrameTree()->root()->child_at(0)->child_at(0);
404 FrameTreeNode* initiator = target->parent()->parent();
405
406 // Give the target a name.
Nick Carterb7e71312018-08-03 23:36:13407 EXPECT_TRUE(ExecJs(target, "window.name = 'target';"));
nick9f34e2892016-01-12 21:01:07408
409 // Use window.open(about:blank), then poll the document for access.
Nick Carterb7e71312018-08-03 23:36:13410 EvalJsResult about_blank_origin =
411 EvalJs(initiator,
412 "new Promise((resolve) => {"
413 " var didNavigate = false;"
414 " var intervalID = setInterval(() => {"
415 " if (!didNavigate) {"
416 " didNavigate = true;"
417 " window.open('about:blank', 'target');"
418 " }"
419 " // May raise a SecurityError, that's expected.\n"
420 " try {"
421 " frames[0][0].document.write('Hi from ' + document.domain);"
422 " } catch (e) { return; }"
423 " clearInterval(intervalID);"
Philip Jägenstedt67302a22018-09-14 09:58:05424 " resolve(frames[0][0].self.origin);"
Nick Carterb7e71312018-08-03 23:36:13425 " }, 16);"
426 "});");
427 EXPECT_EQ(target->current_origin(), about_blank_origin);
nick9f34e2892016-01-12 21:01:07428 EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url());
429 EXPECT_EQ(url::kAboutScheme, target->current_url().scheme());
430 EXPECT_FALSE(target->current_origin().unique());
431 EXPECT_EQ("a.com", target->current_origin().host());
432 EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme());
nick9f34e2892016-01-12 21:01:07433
Nick Carterb7e71312018-08-03 23:36:13434 EXPECT_EQ("Hi from a.com", EvalJs(target, "document.body.innerHTML"));
nick9f34e2892016-01-12 21:01:07435}
436
naskofaa01fb2016-04-30 01:04:17437// Ensures that iframe with srcdoc is always put in the same origin as its
438// parent frame.
439IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, ChildFrameWithSrcdoc) {
440 GURL main_url(embedded_test_server()->GetURL(
441 "a.com", "/cross_site_iframe_factory.html?a(b)"));
442 EXPECT_TRUE(NavigateToURL(shell(), main_url));
443 WebContentsImpl* contents =
444 static_cast<WebContentsImpl*>(shell()->web_contents());
445 FrameTreeNode* root = contents->GetFrameTree()->root();
446 EXPECT_EQ(1U, root->child_count());
447
448 FrameTreeNode* child = root->child_at(0);
Philip Jägenstedt67302a22018-09-14 09:58:05449 std::string frame_origin = EvalJs(child, "self.origin;").ExtractString();
naskofaa01fb2016-04-30 01:04:17450 EXPECT_TRUE(
451 child->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
Daniel Cheng88186bd52017-10-20 08:14:46452 url::Origin::Create(GURL(frame_origin))));
naskofaa01fb2016-04-30 01:04:17453 EXPECT_FALSE(
454 root->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith(
Daniel Cheng88186bd52017-10-20 08:14:46455 url::Origin::Create(GURL(frame_origin))));
naskofaa01fb2016-04-30 01:04:17456
457 // Create a new iframe with srcdoc and add it to the main frame. It should
458 // be created in the same SiteInstance as the parent.
459 {
460 std::string script("var f = document.createElement('iframe');"
461 "f.srcdoc = 'some content';"
462 "document.body.appendChild(f)");
463 TestNavigationObserver observer(shell()->web_contents());
Nick Carterb7e71312018-08-03 23:36:13464 EXPECT_TRUE(ExecJs(root, script));
naskofaa01fb2016-04-30 01:04:17465 EXPECT_EQ(2U, root->child_count());
466 observer.Wait();
467
arthursonzogniee7f43b2016-12-06 10:52:29468 EXPECT_EQ(GURL(kAboutSrcDocURL), root->child_at(1)->current_url());
Philip Jägenstedt67302a22018-09-14 09:58:05469 EvalJsResult frame_origin = EvalJs(root->child_at(1), "self.origin");
naskofaa01fb2016-04-30 01:04:17470 EXPECT_EQ(root->current_frame_host()->GetLastCommittedURL().GetOrigin(),
Nick Carterb7e71312018-08-03 23:36:13471 GURL(frame_origin.ExtractString()));
naskofaa01fb2016-04-30 01:04:17472 EXPECT_NE(child->current_frame_host()->GetLastCommittedURL().GetOrigin(),
Nick Carterb7e71312018-08-03 23:36:13473 GURL(frame_origin.ExtractString()));
naskofaa01fb2016-04-30 01:04:17474 }
475
476 // Set srcdoc on the existing cross-site frame. It should navigate the frame
477 // back to the origin of the parent.
478 {
479 std::string script("var f = document.getElementById('child-0');"
480 "f.srcdoc = 'some content';");
481 TestNavigationObserver observer(shell()->web_contents());
Nick Carterb7e71312018-08-03 23:36:13482 EXPECT_TRUE(ExecJs(root, script));
naskofaa01fb2016-04-30 01:04:17483 observer.Wait();
484
arthursonzogniee7f43b2016-12-06 10:52:29485 EXPECT_EQ(GURL(kAboutSrcDocURL), child->current_url());
Nick Carterb7e71312018-08-03 23:36:13486 EXPECT_EQ(
487 url::Origin::Create(root->current_frame_host()->GetLastCommittedURL())
488 .Serialize(),
Philip Jägenstedt67302a22018-09-14 09:58:05489 EvalJs(child, "self.origin"));
naskofaa01fb2016-04-30 01:04:17490 }
491}
492
Ian Clelland5cbaaf82017-11-27 22:00:03493// Ensure that sandbox flags are correctly set in the main frame when set by
494// Content-Security-Policy header.
495IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, SandboxFlagsSetForMainFrame) {
496 GURL main_url(embedded_test_server()->GetURL("/csp_sandboxed_frame.html"));
497 EXPECT_TRUE(NavigateToURL(shell(), main_url));
498
499 // It is safe to obtain the root frame tree node here, as it doesn't change.
500 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
501 ->GetFrameTree()
502 ->root();
503
504 // Verify that sandbox flags are set properly for the root FrameTreeNode and
505 // RenderFrameHost. Root frame is sandboxed with "allow-scripts".
506 EXPECT_EQ(blink::WebSandboxFlags::kNone,
507 root->effective_frame_policy().sandbox_flags);
508 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
509 ~blink::WebSandboxFlags::kAutomaticFeatures,
510 root->active_sandbox_flags());
511 EXPECT_EQ(root->active_sandbox_flags(),
512 root->current_frame_host()->active_sandbox_flags());
513
514 // Verify that child frames inherit sandbox flags from the root. First frame
515 // has no explicitly set flags of its own, and should inherit those from the
516 // root. Second frame is completely sandboxed.
517 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
518 ~blink::WebSandboxFlags::kAutomaticFeatures,
519 root->child_at(0)->effective_frame_policy().sandbox_flags);
520 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
521 ~blink::WebSandboxFlags::kAutomaticFeatures,
522 root->child_at(0)->active_sandbox_flags());
523 EXPECT_EQ(root->child_at(0)->active_sandbox_flags(),
524 root->child_at(0)->current_frame_host()->active_sandbox_flags());
525 EXPECT_EQ(blink::WebSandboxFlags::kAll,
526 root->child_at(1)->effective_frame_policy().sandbox_flags);
527 EXPECT_EQ(blink::WebSandboxFlags::kAll,
528 root->child_at(1)->active_sandbox_flags());
529 EXPECT_EQ(root->child_at(1)->active_sandbox_flags(),
530 root->child_at(1)->current_frame_host()->active_sandbox_flags());
531
532 // Navigating the main frame to a different URL should clear sandbox flags.
533 GURL unsandboxed_url(embedded_test_server()->GetURL("/title1.html"));
534 NavigateFrameToURL(root, unsandboxed_url);
535
536 // Verify that sandbox flags are cleared properly for the root FrameTreeNode
537 // and RenderFrameHost.
538 EXPECT_EQ(blink::WebSandboxFlags::kNone,
539 root->effective_frame_policy().sandbox_flags);
540 EXPECT_EQ(blink::WebSandboxFlags::kNone, root->active_sandbox_flags());
541 EXPECT_EQ(blink::WebSandboxFlags::kNone,
542 root->current_frame_host()->active_sandbox_flags());
543}
544
alexmosf832a2f2015-01-27 22:44:03545// Ensure that sandbox flags are correctly set when child frames are created.
546IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, SandboxFlagsSetForChildFrames) {
547 GURL main_url(embedded_test_server()->GetURL("/sandboxed_frames.html"));
548 EXPECT_TRUE(NavigateToURL(shell(), main_url));
549
550 // It is safe to obtain the root frame tree node here, as it doesn't change.
551 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
552 ->GetFrameTree()->root();
553
554 // Verify that sandbox flags are set properly for all FrameTreeNodes.
555 // First frame is completely sandboxed; second frame uses "allow-scripts",
556 // which resets both SandboxFlags::Scripts and
557 // SandboxFlags::AutomaticFeatures bits per blink::parseSandboxPolicy(), and
558 // third frame has "allow-scripts allow-same-origin".
Ian Clellandcdc4f312017-10-13 22:24:12559 EXPECT_EQ(blink::WebSandboxFlags::kNone,
560 root->effective_frame_policy().sandbox_flags);
Blink Reformat1c4d759e2017-04-09 16:34:54561 EXPECT_EQ(blink::WebSandboxFlags::kAll,
Ian Clellandcdc4f312017-10-13 22:24:12562 root->child_at(0)->effective_frame_policy().sandbox_flags);
Blink Reformat1c4d759e2017-04-09 16:34:54563 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
564 ~blink::WebSandboxFlags::kAutomaticFeatures,
Ian Clellandcdc4f312017-10-13 22:24:12565 root->child_at(1)->effective_frame_policy().sandbox_flags);
Blink Reformat1c4d759e2017-04-09 16:34:54566 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
567 ~blink::WebSandboxFlags::kAutomaticFeatures &
568 ~blink::WebSandboxFlags::kOrigin,
Ian Clellandcdc4f312017-10-13 22:24:12569 root->child_at(2)->effective_frame_policy().sandbox_flags);
alexmosf832a2f2015-01-27 22:44:03570
571 // Sandboxed frames should set a unique origin unless they have the
572 // "allow-same-origin" directive.
alexmos6e940102016-01-19 22:47:25573 EXPECT_EQ("null", root->child_at(0)->current_origin().Serialize());
574 EXPECT_EQ("null", root->child_at(1)->current_origin().Serialize());
575 EXPECT_EQ(main_url.GetOrigin().spec(),
576 root->child_at(2)->current_origin().Serialize() + "/");
alexmosf832a2f2015-01-27 22:44:03577
578 // Navigating to a different URL should not clear sandbox flags.
579 GURL frame_url(embedded_test_server()->GetURL("/title1.html"));
580 NavigateFrameToURL(root->child_at(0), frame_url);
Blink Reformat1c4d759e2017-04-09 16:34:54581 EXPECT_EQ(blink::WebSandboxFlags::kAll,
Ian Clellandcdc4f312017-10-13 22:24:12582 root->child_at(0)->effective_frame_policy().sandbox_flags);
alexmosf832a2f2015-01-27 22:44:03583}
584
Ian Clelland5cbaaf82017-11-27 22:00:03585// Ensure that sandbox flags are correctly set in the child frames when set by
586// Content-Security-Policy header, and in combination with the sandbox iframe
587// attribute.
588IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest,
589 SandboxFlagsSetByCSPForChildFrames) {
590 GURL main_url(embedded_test_server()->GetURL("/sandboxed_frames_csp.html"));
591 EXPECT_TRUE(NavigateToURL(shell(), main_url));
592
593 // It is safe to obtain the root frame tree node here, as it doesn't change.
594 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
595 ->GetFrameTree()
596 ->root();
597
598 // Verify that sandbox flags are set properly for all FrameTreeNodes.
599 // First frame has no iframe sandbox flags, but the framed document is served
600 // with a CSP header which sets "allow-scripts", "allow-popups" and
601 // "allow-pointer-lock".
602 // Second frame is sandboxed with "allow-scripts", "allow-pointer-lock" and
603 // "allow-orientation-lock", and the framed document is also served with a CSP
604 // header which uses "allow-popups" and "allow-pointer-lock". The resulting
605 // sandbox for the frame should only have "allow-pointer-lock".
606 EXPECT_EQ(blink::WebSandboxFlags::kNone,
607 root->effective_frame_policy().sandbox_flags);
608 EXPECT_EQ(blink::WebSandboxFlags::kNone, root->active_sandbox_flags());
609 EXPECT_EQ(root->active_sandbox_flags(),
610 root->current_frame_host()->active_sandbox_flags());
611 EXPECT_EQ(blink::WebSandboxFlags::kNone,
612 root->child_at(0)->effective_frame_policy().sandbox_flags);
613 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
614 ~blink::WebSandboxFlags::kAutomaticFeatures &
615 ~blink::WebSandboxFlags::kPopups &
616 ~blink::WebSandboxFlags::kPointerLock,
617 root->child_at(0)->active_sandbox_flags());
618 EXPECT_EQ(root->child_at(0)->active_sandbox_flags(),
619 root->child_at(0)->current_frame_host()->active_sandbox_flags());
620 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
621 ~blink::WebSandboxFlags::kAutomaticFeatures &
622 ~blink::WebSandboxFlags::kPointerLock &
623 ~blink::WebSandboxFlags::kOrientationLock,
624 root->child_at(1)->effective_frame_policy().sandbox_flags);
625 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
626 ~blink::WebSandboxFlags::kAutomaticFeatures &
627 ~blink::WebSandboxFlags::kPointerLock,
628 root->child_at(1)->active_sandbox_flags());
629 EXPECT_EQ(root->child_at(1)->active_sandbox_flags(),
630 root->child_at(1)->current_frame_host()->active_sandbox_flags());
631
632 // Navigating to a different URL *should* clear CSP-set sandbox flags, but
633 // should retain those flags set by the frame owner.
634 GURL frame_url(embedded_test_server()->GetURL("/title1.html"));
635
636 NavigateFrameToURL(root->child_at(0), frame_url);
637 EXPECT_EQ(blink::WebSandboxFlags::kNone,
638 root->child_at(0)->effective_frame_policy().sandbox_flags);
639 EXPECT_EQ(blink::WebSandboxFlags::kNone,
640 root->child_at(0)->active_sandbox_flags());
641 EXPECT_EQ(root->child_at(0)->active_sandbox_flags(),
642 root->child_at(0)->current_frame_host()->active_sandbox_flags());
643
644 NavigateFrameToURL(root->child_at(1), frame_url);
645 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
646 ~blink::WebSandboxFlags::kAutomaticFeatures &
647 ~blink::WebSandboxFlags::kPointerLock &
648 ~blink::WebSandboxFlags::kOrientationLock,
649 root->child_at(1)->effective_frame_policy().sandbox_flags);
650 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts &
651 ~blink::WebSandboxFlags::kAutomaticFeatures &
652 ~blink::WebSandboxFlags::kPointerLock &
653 ~blink::WebSandboxFlags::kOrientationLock,
654 root->child_at(1)->active_sandbox_flags());
655 EXPECT_EQ(root->child_at(1)->active_sandbox_flags(),
656 root->child_at(1)->current_frame_host()->active_sandbox_flags());
657}
658
alexmose201c7cd2015-06-10 17:14:21659// Ensure that a popup opened from a subframe sets its opener to the subframe's
660// FrameTreeNode, and that the opener is cleared if the subframe is destroyed.
661IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, SubframeOpenerSetForNewWindow) {
662 GURL main_url(embedded_test_server()->GetURL("/frame_tree/top.html"));
663 EXPECT_TRUE(NavigateToURL(shell(), main_url));
664
665 // It is safe to obtain the root frame tree node here, as it doesn't change.
666 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
667 ->GetFrameTree()
668 ->root();
669
670 // Open a new window from a subframe.
671 ShellAddedObserver new_shell_observer;
672 GURL popup_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
Nick Carterb7e71312018-08-03 23:36:13673 EXPECT_TRUE(
674 ExecJs(root->child_at(0), JsReplace("window.open($1);", popup_url)));
alexmose201c7cd2015-06-10 17:14:21675 Shell* new_shell = new_shell_observer.GetShell();
676 WebContents* new_contents = new_shell->web_contents();
677 WaitForLoadStop(new_contents);
678
679 // Check that the new window's opener points to the correct subframe on
680 // original window.
681 FrameTreeNode* popup_root =
682 static_cast<WebContentsImpl*>(new_contents)->GetFrameTree()->root();
683 EXPECT_EQ(root->child_at(0), popup_root->opener());
684
685 // Close the original window. This should clear the new window's opener.
686 shell()->Close();
687 EXPECT_EQ(nullptr, popup_root->opener());
688}
689
[email protected]82307f6b2014-08-07 03:30:12690class CrossProcessFrameTreeBrowserTest : public ContentBrowserTest {
691 public:
692 CrossProcessFrameTreeBrowserTest() {}
693
dchengc2282aa2014-10-21 12:07:58694 void SetUpCommandLine(base::CommandLine* command_line) override {
nickd30fd962015-07-27 21:51:08695 IsolateAllSitesForTesting(command_line);
[email protected]82307f6b2014-08-07 03:30:12696 }
697
alexmos478dcbb2014-12-10 21:24:46698 void SetUpOnMainThread() override {
699 host_resolver()->AddRule("*", "127.0.0.1");
alexmos478dcbb2014-12-10 21:24:46700 SetupCrossSiteRedirector(embedded_test_server());
martijn12d2dad2016-11-11 10:59:27701 ASSERT_TRUE(embedded_test_server()->Start());
alexmos478dcbb2014-12-10 21:24:46702 }
703
[email protected]82307f6b2014-08-07 03:30:12704 private:
705 DISALLOW_COPY_AND_ASSIGN(CrossProcessFrameTreeBrowserTest);
706};
707
708// Ensure that we can complete a cross-process subframe navigation.
[email protected]82307f6b2014-08-07 03:30:12709IN_PROC_BROWSER_TEST_F(CrossProcessFrameTreeBrowserTest,
nasko83fe5dc2015-07-01 16:34:19710 CreateCrossProcessSubframeProxies) {
alexmos478dcbb2014-12-10 21:24:46711 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
[email protected]82307f6b2014-08-07 03:30:12712 NavigateToURL(shell(), main_url);
713
714 // It is safe to obtain the root frame tree node here, as it doesn't change.
715 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
716 ->GetFrameTree()->root();
717
[email protected]14522ce42014-08-08 18:56:16718 // There should not be a proxy for the root's own SiteInstance.
719 SiteInstance* root_instance = root->current_frame_host()->GetSiteInstance();
720 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost(root_instance));
721
[email protected]82307f6b2014-08-07 03:30:12722 // Load same-site page into iframe.
alexmos478dcbb2014-12-10 21:24:46723 GURL http_url(embedded_test_server()->GetURL("/title1.html"));
[email protected]82307f6b2014-08-07 03:30:12724 NavigateFrameToURL(root->child_at(0), http_url);
725
[email protected]82307f6b2014-08-07 03:30:12726 // Load cross-site page into iframe.
alexmos478dcbb2014-12-10 21:24:46727 GURL cross_site_url(
728 embedded_test_server()->GetURL("foo.com", "/title2.html"));
[email protected]82307f6b2014-08-07 03:30:12729 NavigateFrameToURL(root->child_at(0), cross_site_url);
730
731 // Ensure that we have created a new process for the subframe.
naskoe6edde32014-10-17 15:36:48732 ASSERT_EQ(2U, root->child_count());
[email protected]82307f6b2014-08-07 03:30:12733 FrameTreeNode* child = root->child_at(0);
[email protected]14522ce42014-08-08 18:56:16734 SiteInstance* child_instance = child->current_frame_host()->GetSiteInstance();
[email protected]82307f6b2014-08-07 03:30:12735 RenderViewHost* rvh = child->current_frame_host()->render_view_host();
736 RenderProcessHost* rph = child->current_frame_host()->GetProcess();
737
738 EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh);
[email protected]14522ce42014-08-08 18:56:16739 EXPECT_NE(shell()->web_contents()->GetSiteInstance(), child_instance);
Lukasz Anforowicz9e0ce4e2017-09-28 19:09:15740 EXPECT_NE(shell()->web_contents()->GetMainFrame()->GetProcess(), rph);
[email protected]82307f6b2014-08-07 03:30:12741
742 // Ensure that the root node has a proxy for the child node's SiteInstance.
[email protected]14522ce42014-08-08 18:56:16743 EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(child_instance));
[email protected]82307f6b2014-08-07 03:30:12744
745 // Also ensure that the child has a proxy for the root node's SiteInstance.
[email protected]14522ce42014-08-08 18:56:16746 EXPECT_TRUE(child->render_manager()->GetRenderFrameProxyHost(root_instance));
747
748 // The nodes should not have proxies for their own SiteInstance.
749 EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost(root_instance));
750 EXPECT_FALSE(
751 child->render_manager()->GetRenderFrameProxyHost(child_instance));
creise42f2a52014-09-18 18:14:57752
753 // Ensure that the RenderViews and RenderFrames are all live.
754 EXPECT_TRUE(
755 root->current_frame_host()->render_view_host()->IsRenderViewLive());
756 EXPECT_TRUE(
757 child->current_frame_host()->render_view_host()->IsRenderViewLive());
758 EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
759 EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive());
[email protected]82307f6b2014-08-07 03:30:12760}
761
alexmosbc7eafa2014-12-06 01:38:09762IN_PROC_BROWSER_TEST_F(CrossProcessFrameTreeBrowserTest,
763 OriginSetOnCrossProcessNavigations) {
alexmos478dcbb2014-12-10 21:24:46764 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
alexmosbc7eafa2014-12-06 01:38:09765 EXPECT_TRUE(NavigateToURL(shell(), main_url));
766
767 // It is safe to obtain the root frame tree node here, as it doesn't change.
768 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
769 ->GetFrameTree()->root();
770
creisabdd2bd62015-11-21 01:14:58771 EXPECT_EQ(root->current_origin().Serialize() + '/',
alexmosbc7eafa2014-12-06 01:38:09772 main_url.GetOrigin().spec());
773
774 // First frame is an about:blank frame. Check that its origin is correctly
775 // inherited from the parent.
creisabdd2bd62015-11-21 01:14:58776 EXPECT_EQ(root->child_at(0)->current_origin().Serialize() + '/',
777 main_url.GetOrigin().spec());
alexmosbc7eafa2014-12-06 01:38:09778
779 // Second frame loads a same-site page. Its origin should also be the same
780 // as the parent.
creisabdd2bd62015-11-21 01:14:58781 EXPECT_EQ(root->child_at(1)->current_origin().Serialize() + '/',
782 main_url.GetOrigin().spec());
alexmosbc7eafa2014-12-06 01:38:09783
alexmosbc7eafa2014-12-06 01:38:09784 // Load cross-site page into the first frame.
alexmos478dcbb2014-12-10 21:24:46785 GURL cross_site_url(
786 embedded_test_server()->GetURL("foo.com", "/title2.html"));
alexmosbc7eafa2014-12-06 01:38:09787 NavigateFrameToURL(root->child_at(0), cross_site_url);
788
creisabdd2bd62015-11-21 01:14:58789 EXPECT_EQ(root->child_at(0)->current_origin().Serialize() + '/',
790 cross_site_url.GetOrigin().spec());
alexmosbc7eafa2014-12-06 01:38:09791
792 // The root's origin shouldn't have changed.
creisabdd2bd62015-11-21 01:14:58793 EXPECT_EQ(root->current_origin().Serialize() + '/',
alexmosbc7eafa2014-12-06 01:38:09794 main_url.GetOrigin().spec());
795
796 GURL data_url("data:text/html,foo");
797 NavigateFrameToURL(root->child_at(1), data_url);
798
799 // Navigating to a data URL should set a unique origin. This is represented
800 // as "null" per RFC 6454.
creisabdd2bd62015-11-21 01:14:58801 EXPECT_EQ(root->child_at(1)->current_origin().Serialize(), "null");
alexmosbc7eafa2014-12-06 01:38:09802}
803
Ian Clelland5cbaaf82017-11-27 22:00:03804// Ensure that a popup opened from a sandboxed main frame inherits sandbox flags
805// from its opener.
806IN_PROC_BROWSER_TEST_F(CrossProcessFrameTreeBrowserTest,
807 SandboxFlagsSetForNewWindow) {
808 GURL main_url(
809 embedded_test_server()->GetURL("/sandboxed_main_frame_script.html"));
810 EXPECT_TRUE(NavigateToURL(shell(), main_url));
811
812 // It is safe to obtain the root frame tree node here, as it doesn't change.
813 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
814 ->GetFrameTree()
815 ->root();
816
817 // Open a new window from the main frame.
818 GURL popup_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
819 Shell* new_shell = OpenPopup(root->current_frame_host(), popup_url, "");
820 EXPECT_TRUE(new_shell);
821 WebContents* new_contents = new_shell->web_contents();
822
823 // Check that the new window's sandbox flags correctly reflect the opener's
824 // flags. Main frame sets allow-popups, allow-pointer-lock and allow-scripts.
825 FrameTreeNode* popup_root =
826 static_cast<WebContentsImpl*>(new_contents)->GetFrameTree()->root();
827 blink::WebSandboxFlags main_frame_sandbox_flags =
828 root->current_frame_host()->active_sandbox_flags();
829 EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kPopups &
830 ~blink::WebSandboxFlags::kPointerLock &
831 ~blink::WebSandboxFlags::kScripts &
832 ~blink::WebSandboxFlags::kAutomaticFeatures,
833 main_frame_sandbox_flags);
834
835 EXPECT_EQ(main_frame_sandbox_flags,
836 popup_root->effective_frame_policy().sandbox_flags);
837 EXPECT_EQ(main_frame_sandbox_flags, popup_root->active_sandbox_flags());
838 EXPECT_EQ(main_frame_sandbox_flags,
839 popup_root->current_frame_host()->active_sandbox_flags());
840}
841
nickdb193a12016-09-09 23:09:23842// FrameTreeBrowserTest variant where we isolate http://*.is, Iceland's top
naskoabed2a52017-05-03 05:10:17843// level domain. This is an analogue to isolating extensions, which we can use
844// inside content_browsertests, where extensions don't exist. Iceland, like an
nickdb193a12016-09-09 23:09:23845// extension process, is a special place with magical powers; we want to protect
846// it from outsiders.
847class IsolateIcelandFrameTreeBrowserTest : public ContentBrowserTest {
848 public:
849 IsolateIcelandFrameTreeBrowserTest() {}
850
851 void SetUpCommandLine(base::CommandLine* command_line) override {
alexis.menard83f1b6d2017-05-17 19:37:33852 // blink suppresses navigations to blob URLs of origins different from the
853 // frame initiating the navigation. We disable those checks for this test,
854 // to test what happens in a compromise scenario.
855 command_line->AppendSwitch(switches::kDisableWebSecurity);
nickdb193a12016-09-09 23:09:23856 command_line->AppendSwitchASCII(switches::kIsolateSitesForTesting, "*.is");
857 }
858
859 void SetUpOnMainThread() override {
860 host_resolver()->AddRule("*", "127.0.0.1");
nickdb193a12016-09-09 23:09:23861 SetupCrossSiteRedirector(embedded_test_server());
martijn12d2dad2016-11-11 10:59:27862 ASSERT_TRUE(embedded_test_server()->Start());
nickdb193a12016-09-09 23:09:23863 }
864
865 private:
866 DISALLOW_COPY_AND_ASSIGN(IsolateIcelandFrameTreeBrowserTest);
867};
868
869// Regression test for https://crbug.com/644966
870IN_PROC_BROWSER_TEST_F(IsolateIcelandFrameTreeBrowserTest,
871 ProcessSwitchForIsolatedBlob) {
nickdb193a12016-09-09 23:09:23872 // Set up an iframe.
873 WebContents* contents = shell()->web_contents();
874 FrameTreeNode* root =
875 static_cast<WebContentsImpl*>(contents)->GetFrameTree()->root();
876 GURL main_url(embedded_test_server()->GetURL(
nick07fd7e12016-09-12 18:54:06877 "a.com", "/cross_site_iframe_factory.html?a(a)"));
nickdb193a12016-09-09 23:09:23878 EXPECT_TRUE(NavigateToURL(shell(), main_url));
879
880 // The navigation targets an invalid blob url; that's intentional to trigger
881 // an error response. The response should commit in a process dedicated to
882 // http://b.is.
Nick Carterb7e71312018-08-03 23:36:13883 EXPECT_EQ(
884 "done",
885 EvalJs(
886 root,
887 "new Promise((resolve) => {"
888 " var iframe_element = document.getElementsByTagName('iframe')[0];"
889 " iframe_element.onload = () => resolve('done');"
890 " iframe_element.src = 'blob:http://b.is:2932/';"
891 "});"));
nickdb193a12016-09-09 23:09:23892 WaitForLoadStop(contents);
893
894 // Make sure we did a process transfer back to "b.is".
895 EXPECT_EQ(
896 " Site A ------------ proxies for B\n"
897 " +--Site B ------- proxies for A\n"
898 "Where A = http://a.com/\n"
899 " B = http://b.is/",
900 FrameTreeVisualizer().DepictFrameTree(root));
901}
902
[email protected]5f96f5a62014-01-10 00:05:11903} // namespace content