[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 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. |
| 4 | |
Ken Rockot | 86bea1c | 2017-05-16 06:21:35 | [diff] [blame] | 5 | #include "base/command_line.h" |
avi | b734894 | 2015-12-25 20:57:10 | [diff] [blame] | 6 | #include "base/macros.h" |
| 7 | #include "build/build_config.h" |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 8 | #include "content/browser/frame_host/frame_tree.h" |
| 9 | #include "content/browser/frame_host/frame_tree_node.h" |
Lukasz Anforowicz | 9e0ce4e | 2017-09-28 19:09:15 | [diff] [blame] | 10 | #include "content/browser/frame_host/render_frame_host_impl.h" |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 11 | #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" |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 15 | #include "content/public/common/content_switches.h" |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 16 | #include "content/public/common/url_constants.h" |
| 17 | #include "content/public/test/browser_test_utils.h" |
[email protected] | 6e9def1 | 2014-03-27 20:23:28 | [diff] [blame] | 18 | #include "content/public/test/content_browser_test.h" |
| 19 | #include "content/public/test/content_browser_test_utils.h" |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 20 | #include "content/public/test/test_navigation_observer.h" |
| 21 | #include "content/public/test/test_utils.h" |
| 22 | #include "content/shell/browser/shell.h" |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 23 | #include "content/shell/common/shell_switches.h" |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 24 | #include "content/test/content_browser_test_utils_internal.h" |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 25 | #include "net/dns/mock_host_resolver.h" |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 26 | #include "net/test/embedded_test_server/embedded_test_server.h" |
Blink Reformat | a30d423 | 2018-04-07 15:31:06 | [diff] [blame] | 27 | #include "third_party/blink/public/common/frame/sandbox_flags.h" |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 28 | #include "url/url_constants.h" |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 29 | |
| 30 | namespace content { |
| 31 | |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 32 | namespace { |
| 33 | |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 34 | EvalJsResult GetOriginFromRenderer(FrameTreeNode* node) { |
Philip Jägenstedt | 67302a2 | 2018-09-14 09:58:05 | [diff] [blame] | 35 | return EvalJs(node, "self.origin"); |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 36 | } |
| 37 | |
| 38 | } // namespace |
| 39 | |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 40 | class FrameTreeBrowserTest : public ContentBrowserTest { |
| 41 | public: |
| 42 | FrameTreeBrowserTest() {} |
| 43 | |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 44 | void SetUpOnMainThread() override { |
| 45 | host_resolver()->AddRule("*", "127.0.0.1"); |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 46 | SetupCrossSiteRedirector(embedded_test_server()); |
martijn | 12d2dad | 2016-11-11 10:59:27 | [diff] [blame] | 47 | ASSERT_TRUE(embedded_test_server()->Start()); |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 48 | } |
| 49 | |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 50 | private: |
| 51 | DISALLOW_COPY_AND_ASSIGN(FrameTreeBrowserTest); |
| 52 | }; |
| 53 | |
| 54 | // Ensures FrameTree correctly reflects page structure during navigations. |
| 55 | IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeShape) { |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 56 | GURL base_url = embedded_test_server()->GetURL("A.com", "/site_isolation/"); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 57 | |
| 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. |
| 84 | IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeShape2) { |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 85 | NavigateToURL(shell(), |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 86 | embedded_test_server()->GetURL("/frame_tree/top.html")); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 87 | |
| 88 | WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 89 | FrameTreeNode* root = wc->GetFrameTree()->root(); |
| 90 | |
[email protected] | 58faf94 | 2014-02-20 21:03:58 | [diff] [blame] | 91 | // Check that the root node is properly created. |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 92 | ASSERT_EQ(3UL, root->child_count()); |
| 93 | EXPECT_EQ(std::string(), root->frame_name()); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 94 | |
| 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] | b0cd7a95 | 2014-03-08 11:44:06 | [diff] [blame] | 102 | EXPECT_STREQ("3-1-name", |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 103 | 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. |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 107 | NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 108 | |
| 109 | root = wc->GetFrameTree()->root(); |
| 110 | EXPECT_EQ(0UL, root->child_count()); |
| 111 | EXPECT_EQ(std::string(), root->frame_name()); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | // Test that we can navigate away if the previous renderer doesn't clean up its |
| 115 | // child frames. |
| 116 | IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, FrameTreeAfterCrash) { |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 117 | NavigateToURL(shell(), |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 118 | embedded_test_server()->GetURL("/frame_tree/top.html")); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 119 | |
creis | e42f2a5 | 2014-09-18 18:14:57 | [diff] [blame] | 120 | // 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] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 127 | // 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); |
Wez | 0abfbf51 | 2018-03-03 01:54:45 | [diff] [blame] | 131 | ASSERT_TRUE( |
| 132 | shell()->web_contents()->GetMainFrame()->GetProcess()->Shutdown(0)); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 133 | crash_observer.Wait(); |
| 134 | |
[email protected] | 58faf94 | 2014-02-20 21:03:58 | [diff] [blame] | 135 | // The frame tree should be cleared. |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 136 | WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 137 | FrameTreeNode* root = wc->GetFrameTree()->root(); |
| 138 | EXPECT_EQ(0UL, root->child_count()); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 139 | |
creis | e42f2a5 | 2014-09-18 18:14:57 | [diff] [blame] | 140 | // Ensure the view and frame aren't live anymore. |
| 141 | EXPECT_FALSE(rvh->IsRenderViewLive()); |
| 142 | EXPECT_FALSE(rfh->IsRenderFrameLive()); |
| 143 | |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 144 | // Navigate to a new URL. |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 145 | GURL url(embedded_test_server()->GetURL("/title1.html")); |
[email protected] | 58faf94 | 2014-02-20 21:03:58 | [diff] [blame] | 146 | NavigateToURL(shell(), url); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 147 | EXPECT_EQ(0UL, root->child_count()); |
[email protected] | 58faf94 | 2014-02-20 21:03:58 | [diff] [blame] | 148 | EXPECT_EQ(url, root->current_url()); |
creis | e42f2a5 | 2014-09-18 18:14:57 | [diff] [blame] | 149 | |
| 150 | // Ensure the view and frame are live again. |
| 151 | EXPECT_TRUE(rvh->IsRenderViewLive()); |
| 152 | EXPECT_TRUE(rfh->IsRenderFrameLive()); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | // Test that we can navigate away if the previous renderer doesn't clean up its |
| 156 | // child frames. |
pauljensen | 58ee2ea2 | 2015-01-26 17:45:53 | [diff] [blame] | 157 | // 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 |
| 163 | IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, MAYBE_NavigateWithLeftoverFrames) { |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 164 | GURL base_url = embedded_test_server()->GetURL("A.com", "/site_isolation/"); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 165 | |
| 166 | NavigateToURL(shell(), |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 167 | embedded_test_server()->GetURL("/frame_tree/top.html")); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 168 | |
| 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] | 58faf94 | 2014-02-20 21:03:58 | [diff] [blame] | 184 | // The frame tree should now be cleared. |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 185 | EXPECT_EQ(0UL, root->child_count()); |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 186 | } |
| 187 | |
creis | e42f2a5 | 2014-09-18 18:14:57 | [diff] [blame] | 188 | // Ensure that IsRenderFrameLive is true for main frames and same-site iframes. |
| 189 | IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, IsRenderFrameLive) { |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 190 | GURL main_url(embedded_test_server()->GetURL("/frame_tree/top.html")); |
creis | e42f2a5 | 2014-09-18 18:14:57 | [diff] [blame] | 191 | 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. |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 204 | GURL http_url(embedded_test_server()->GetURL("/title1.html")); |
creis | e42f2a5 | 2014-09-18 18:14:57 | [diff] [blame] | 205 | 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 | |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 212 | // Ensure that origins are correctly set on navigations. |
| 213 | IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, OriginSetOnNavigation) { |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 214 | GURL about_blank(url::kAboutBlankURL); |
| 215 | GURL main_url( |
| 216 | embedded_test_server()->GetURL("a.com", "/frame_tree/top.html")); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 217 | EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 218 | WebContents* contents = shell()->web_contents(); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 219 | |
| 220 | // It is safe to obtain the root frame tree node here, as it doesn't change. |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 221 | FrameTreeNode* root = |
| 222 | static_cast<WebContentsImpl*>(contents)->GetFrameTree()->root(); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 223 | |
| 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. |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 227 | 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() + '/'); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 232 | |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 233 | // 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")); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 243 | NavigateFrameToURL(root->child_at(0), frame_url); |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 244 | 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))); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 253 | |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 254 | // 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))); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 271 | |
| 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. |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 277 | EXPECT_EQ("null", root->current_origin().Serialize()); |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 278 | EXPECT_TRUE(contents->GetMainFrame()->GetLastCommittedOrigin().opaque()); |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 279 | EXPECT_EQ("null", GetOriginFromRenderer(root)); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 280 | |
| 281 | // Re-navigating to a normal URL should update the origin. |
| 282 | EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 283 | EXPECT_EQ(main_url.GetOrigin().spec(), |
| 284 | root->current_origin().Serialize() + '/'); |
| 285 | EXPECT_EQ( |
| 286 | main_url.GetOrigin().spec(), |
| 287 | contents->GetMainFrame()->GetLastCommittedOrigin().Serialize() + '/'); |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 288 | EXPECT_FALSE(contents->GetMainFrame()->GetLastCommittedOrigin().opaque()); |
nick | 1466c84 | 2015-11-25 20:08:06 | [diff] [blame] | 289 | EXPECT_EQ(root->current_origin().Serialize(), GetOriginFromRenderer(root)); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 290 | } |
| 291 | |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 292 | // 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. |
| 294 | IN_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 | |
creis | b2d5f1f3 | 2016-11-07 23:25:05 | [diff] [blame] | 314 | RenderFrameDeletedObserver deleted_observer(target->current_frame_host()); |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 315 | std::string html = |
| 316 | "<html><body><div>This is blob content.</div>" |
| 317 | "<script>" |
Philip Jägenstedt | 67302a2 | 2018-09-14 09:58:05 | [diff] [blame] | 318 | "window.parent.parent.postMessage('HI', self.origin);" |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 319 | "</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) => {" |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 327 | " document.body.appendChild(document.createTextNode(event.data));" |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 328 | " return event.source.location.href;" |
| 329 | "});", |
| 330 | html); |
| 331 | std::string blob_url_string = EvalJs(root, script).ExtractString(); |
creis | b2d5f1f3 | 2016-11-07 23:25:05 | [diff] [blame] | 332 | // Wait for the RenderFrame to go away, if this will be cross-process. |
| 333 | if (AreAllSitesIsolatedForTesting()) |
| 334 | deleted_observer.WaitUntilDeleted(); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 335 | EXPECT_EQ(GURL(blob_url_string), target->current_url()); |
| 336 | EXPECT_EQ(url::kBlobScheme, target->current_url().scheme()); |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 337 | EXPECT_FALSE(target->current_origin().opaque()); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 338 | EXPECT_EQ("a.com", target->current_origin().host()); |
| 339 | EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme()); |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 340 | EXPECT_EQ("This is blob content.", |
| 341 | EvalJs(target, "document.body.children[0].innerHTML")); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 342 | EXPECT_EQ(reference_tree, FrameTreeVisualizer().DepictFrameTree(root)); |
| 343 | } |
| 344 | |
| 345 | IN_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 Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 359 | EXPECT_TRUE(ExecJs(target, "window.name = 'target';")); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 360 | |
| 361 | // Use window.open(about:blank), then poll the document for access. |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 362 | EvalJsResult about_blank_origin = EvalJs( |
nick | adef4a5 | 2016-06-09 18:45:54 | [diff] [blame] | 363 | initiator, |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 364 | "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ägenstedt | 67302a2 | 2018-09-14 09:58:05 | [diff] [blame] | 376 | " resolve(frames[0].self.origin);" |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 377 | " }, 16);" |
| 378 | "});"); |
| 379 | EXPECT_EQ(target->current_origin(), about_blank_origin); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 380 | EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url()); |
| 381 | EXPECT_EQ(url::kAboutScheme, target->current_url().scheme()); |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 382 | EXPECT_FALSE(target->current_origin().opaque()); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 383 | EXPECT_EQ("b.com", target->current_origin().host()); |
| 384 | EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme()); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 385 | |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 386 | EXPECT_EQ("Hi from b.com", EvalJs(target, "document.body.innerHTML")); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 387 | } |
| 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 |
| 392 | IN_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 Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 407 | EXPECT_TRUE(ExecJs(target, "window.name = 'target';")); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 408 | |
| 409 | // Use window.open(about:blank), then poll the document for access. |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 410 | 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ägenstedt | 67302a2 | 2018-09-14 09:58:05 | [diff] [blame] | 424 | " resolve(frames[0][0].self.origin);" |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 425 | " }, 16);" |
| 426 | "});"); |
| 427 | EXPECT_EQ(target->current_origin(), about_blank_origin); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 428 | EXPECT_EQ(GURL(url::kAboutBlankURL), target->current_url()); |
| 429 | EXPECT_EQ(url::kAboutScheme, target->current_url().scheme()); |
Chris Palmer | ab5e5b5 | 2018-09-28 19:19:30 | [diff] [blame] | 430 | EXPECT_FALSE(target->current_origin().opaque()); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 431 | EXPECT_EQ("a.com", target->current_origin().host()); |
| 432 | EXPECT_EQ(url::kHttpScheme, target->current_origin().scheme()); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 433 | |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 434 | EXPECT_EQ("Hi from a.com", EvalJs(target, "document.body.innerHTML")); |
nick | 9f34e289 | 2016-01-12 21:01:07 | [diff] [blame] | 435 | } |
| 436 | |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 437 | // Ensures that iframe with srcdoc is always put in the same origin as its |
| 438 | // parent frame. |
| 439 | IN_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ägenstedt | 67302a2 | 2018-09-14 09:58:05 | [diff] [blame] | 449 | std::string frame_origin = EvalJs(child, "self.origin;").ExtractString(); |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 450 | EXPECT_TRUE( |
| 451 | child->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith( |
Daniel Cheng | 88186bd5 | 2017-10-20 08:14:46 | [diff] [blame] | 452 | url::Origin::Create(GURL(frame_origin)))); |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 453 | EXPECT_FALSE( |
| 454 | root->current_frame_host()->GetLastCommittedOrigin().IsSameOriginWith( |
Daniel Cheng | 88186bd5 | 2017-10-20 08:14:46 | [diff] [blame] | 455 | url::Origin::Create(GURL(frame_origin)))); |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 456 | |
| 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 Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 464 | EXPECT_TRUE(ExecJs(root, script)); |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 465 | EXPECT_EQ(2U, root->child_count()); |
| 466 | observer.Wait(); |
| 467 | |
arthursonzogni | ee7f43b | 2016-12-06 10:52:29 | [diff] [blame] | 468 | EXPECT_EQ(GURL(kAboutSrcDocURL), root->child_at(1)->current_url()); |
Philip Jägenstedt | 67302a2 | 2018-09-14 09:58:05 | [diff] [blame] | 469 | EvalJsResult frame_origin = EvalJs(root->child_at(1), "self.origin"); |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 470 | EXPECT_EQ(root->current_frame_host()->GetLastCommittedURL().GetOrigin(), |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 471 | GURL(frame_origin.ExtractString())); |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 472 | EXPECT_NE(child->current_frame_host()->GetLastCommittedURL().GetOrigin(), |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 473 | GURL(frame_origin.ExtractString())); |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 474 | } |
| 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 Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 482 | EXPECT_TRUE(ExecJs(root, script)); |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 483 | observer.Wait(); |
| 484 | |
arthursonzogni | ee7f43b | 2016-12-06 10:52:29 | [diff] [blame] | 485 | EXPECT_EQ(GURL(kAboutSrcDocURL), child->current_url()); |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 486 | EXPECT_EQ( |
| 487 | url::Origin::Create(root->current_frame_host()->GetLastCommittedURL()) |
| 488 | .Serialize(), |
Philip Jägenstedt | 67302a2 | 2018-09-14 09:58:05 | [diff] [blame] | 489 | EvalJs(child, "self.origin")); |
nasko | faa01fb | 2016-04-30 01:04:17 | [diff] [blame] | 490 | } |
| 491 | } |
| 492 | |
Ian Clelland | 5cbaaf8 | 2017-11-27 22:00:03 | [diff] [blame] | 493 | // Ensure that sandbox flags are correctly set in the main frame when set by |
| 494 | // Content-Security-Policy header. |
| 495 | IN_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 | |
alexmos | f832a2f | 2015-01-27 22:44:03 | [diff] [blame] | 545 | // Ensure that sandbox flags are correctly set when child frames are created. |
| 546 | IN_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 Clelland | cdc4f31 | 2017-10-13 22:24:12 | [diff] [blame] | 559 | EXPECT_EQ(blink::WebSandboxFlags::kNone, |
| 560 | root->effective_frame_policy().sandbox_flags); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 561 | EXPECT_EQ(blink::WebSandboxFlags::kAll, |
Ian Clelland | cdc4f31 | 2017-10-13 22:24:12 | [diff] [blame] | 562 | root->child_at(0)->effective_frame_policy().sandbox_flags); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 563 | EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts & |
| 564 | ~blink::WebSandboxFlags::kAutomaticFeatures, |
Ian Clelland | cdc4f31 | 2017-10-13 22:24:12 | [diff] [blame] | 565 | root->child_at(1)->effective_frame_policy().sandbox_flags); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 566 | EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kScripts & |
| 567 | ~blink::WebSandboxFlags::kAutomaticFeatures & |
| 568 | ~blink::WebSandboxFlags::kOrigin, |
Ian Clelland | cdc4f31 | 2017-10-13 22:24:12 | [diff] [blame] | 569 | root->child_at(2)->effective_frame_policy().sandbox_flags); |
alexmos | f832a2f | 2015-01-27 22:44:03 | [diff] [blame] | 570 | |
| 571 | // Sandboxed frames should set a unique origin unless they have the |
| 572 | // "allow-same-origin" directive. |
alexmos | 6e94010 | 2016-01-19 22:47:25 | [diff] [blame] | 573 | 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() + "/"); |
alexmos | f832a2f | 2015-01-27 22:44:03 | [diff] [blame] | 577 | |
| 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 Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 581 | EXPECT_EQ(blink::WebSandboxFlags::kAll, |
Ian Clelland | cdc4f31 | 2017-10-13 22:24:12 | [diff] [blame] | 582 | root->child_at(0)->effective_frame_policy().sandbox_flags); |
alexmos | f832a2f | 2015-01-27 22:44:03 | [diff] [blame] | 583 | } |
| 584 | |
Ian Clelland | 5cbaaf8 | 2017-11-27 22:00:03 | [diff] [blame] | 585 | // 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. |
| 588 | IN_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 | |
alexmos | e201c7cd | 2015-06-10 17:14:21 | [diff] [blame] | 659 | // 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. |
| 661 | IN_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 Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 673 | EXPECT_TRUE( |
| 674 | ExecJs(root->child_at(0), JsReplace("window.open($1);", popup_url))); |
alexmos | e201c7cd | 2015-06-10 17:14:21 | [diff] [blame] | 675 | 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 | |
Shivani Sharma | c4f56158 | 2018-11-15 15:58:39 | [diff] [blame^] | 690 | // Tests that the user activation bits get cleared when a same-site document is |
| 691 | // installed in the frame. |
| 692 | IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, |
| 693 | ClearUserActivationForNewDocument) { |
| 694 | GURL main_url(embedded_test_server()->GetURL("/frame_tree/top.html")); |
| 695 | EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| 696 | |
| 697 | // It is safe to obtain the root frame tree node here, as it doesn't change. |
| 698 | FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 699 | ->GetFrameTree() |
| 700 | ->root(); |
| 701 | |
| 702 | EXPECT_FALSE(root->HasBeenActivated()); |
| 703 | EXPECT_FALSE(root->HasTransientUserActivation()); |
| 704 | |
| 705 | // Set the user activation bits. |
| 706 | root->UpdateUserActivationState( |
| 707 | blink::UserActivationUpdateType::kNotifyActivation); |
| 708 | EXPECT_TRUE(root->HasBeenActivated()); |
| 709 | EXPECT_TRUE(root->HasTransientUserActivation()); |
| 710 | |
| 711 | // Install a new same-site document to check the clearing of user activation |
| 712 | // bits. |
| 713 | GURL url(embedded_test_server()->GetURL("/title1.html")); |
| 714 | EXPECT_TRUE(NavigateToURL(shell(), url)); |
| 715 | |
| 716 | EXPECT_FALSE(root->HasBeenActivated()); |
| 717 | EXPECT_FALSE(root->HasTransientUserActivation()); |
| 718 | } |
| 719 | |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 720 | class CrossProcessFrameTreeBrowserTest : public ContentBrowserTest { |
| 721 | public: |
| 722 | CrossProcessFrameTreeBrowserTest() {} |
| 723 | |
dcheng | c2282aa | 2014-10-21 12:07:58 | [diff] [blame] | 724 | void SetUpCommandLine(base::CommandLine* command_line) override { |
nick | d30fd96 | 2015-07-27 21:51:08 | [diff] [blame] | 725 | IsolateAllSitesForTesting(command_line); |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 726 | } |
| 727 | |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 728 | void SetUpOnMainThread() override { |
| 729 | host_resolver()->AddRule("*", "127.0.0.1"); |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 730 | SetupCrossSiteRedirector(embedded_test_server()); |
martijn | 12d2dad | 2016-11-11 10:59:27 | [diff] [blame] | 731 | ASSERT_TRUE(embedded_test_server()->Start()); |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 732 | } |
| 733 | |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 734 | private: |
| 735 | DISALLOW_COPY_AND_ASSIGN(CrossProcessFrameTreeBrowserTest); |
| 736 | }; |
| 737 | |
| 738 | // Ensure that we can complete a cross-process subframe navigation. |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 739 | IN_PROC_BROWSER_TEST_F(CrossProcessFrameTreeBrowserTest, |
nasko | 83fe5dc | 2015-07-01 16:34:19 | [diff] [blame] | 740 | CreateCrossProcessSubframeProxies) { |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 741 | GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 742 | NavigateToURL(shell(), main_url); |
| 743 | |
| 744 | // It is safe to obtain the root frame tree node here, as it doesn't change. |
| 745 | FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 746 | ->GetFrameTree()->root(); |
| 747 | |
[email protected] | 14522ce4 | 2014-08-08 18:56:16 | [diff] [blame] | 748 | // There should not be a proxy for the root's own SiteInstance. |
| 749 | SiteInstance* root_instance = root->current_frame_host()->GetSiteInstance(); |
| 750 | EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost(root_instance)); |
| 751 | |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 752 | // Load same-site page into iframe. |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 753 | GURL http_url(embedded_test_server()->GetURL("/title1.html")); |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 754 | NavigateFrameToURL(root->child_at(0), http_url); |
| 755 | |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 756 | // Load cross-site page into iframe. |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 757 | GURL cross_site_url( |
| 758 | embedded_test_server()->GetURL("foo.com", "/title2.html")); |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 759 | NavigateFrameToURL(root->child_at(0), cross_site_url); |
| 760 | |
| 761 | // Ensure that we have created a new process for the subframe. |
nasko | e6edde3 | 2014-10-17 15:36:48 | [diff] [blame] | 762 | ASSERT_EQ(2U, root->child_count()); |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 763 | FrameTreeNode* child = root->child_at(0); |
[email protected] | 14522ce4 | 2014-08-08 18:56:16 | [diff] [blame] | 764 | SiteInstance* child_instance = child->current_frame_host()->GetSiteInstance(); |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 765 | RenderViewHost* rvh = child->current_frame_host()->render_view_host(); |
| 766 | RenderProcessHost* rph = child->current_frame_host()->GetProcess(); |
| 767 | |
| 768 | EXPECT_NE(shell()->web_contents()->GetRenderViewHost(), rvh); |
[email protected] | 14522ce4 | 2014-08-08 18:56:16 | [diff] [blame] | 769 | EXPECT_NE(shell()->web_contents()->GetSiteInstance(), child_instance); |
Lukasz Anforowicz | 9e0ce4e | 2017-09-28 19:09:15 | [diff] [blame] | 770 | EXPECT_NE(shell()->web_contents()->GetMainFrame()->GetProcess(), rph); |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 771 | |
| 772 | // Ensure that the root node has a proxy for the child node's SiteInstance. |
[email protected] | 14522ce4 | 2014-08-08 18:56:16 | [diff] [blame] | 773 | EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(child_instance)); |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 774 | |
| 775 | // Also ensure that the child has a proxy for the root node's SiteInstance. |
[email protected] | 14522ce4 | 2014-08-08 18:56:16 | [diff] [blame] | 776 | EXPECT_TRUE(child->render_manager()->GetRenderFrameProxyHost(root_instance)); |
| 777 | |
| 778 | // The nodes should not have proxies for their own SiteInstance. |
| 779 | EXPECT_FALSE(root->render_manager()->GetRenderFrameProxyHost(root_instance)); |
| 780 | EXPECT_FALSE( |
| 781 | child->render_manager()->GetRenderFrameProxyHost(child_instance)); |
creis | e42f2a5 | 2014-09-18 18:14:57 | [diff] [blame] | 782 | |
| 783 | // Ensure that the RenderViews and RenderFrames are all live. |
| 784 | EXPECT_TRUE( |
| 785 | root->current_frame_host()->render_view_host()->IsRenderViewLive()); |
| 786 | EXPECT_TRUE( |
| 787 | child->current_frame_host()->render_view_host()->IsRenderViewLive()); |
| 788 | EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive()); |
| 789 | EXPECT_TRUE(root->child_at(0)->current_frame_host()->IsRenderFrameLive()); |
[email protected] | 82307f6b | 2014-08-07 03:30:12 | [diff] [blame] | 790 | } |
| 791 | |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 792 | IN_PROC_BROWSER_TEST_F(CrossProcessFrameTreeBrowserTest, |
| 793 | OriginSetOnCrossProcessNavigations) { |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 794 | GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 795 | EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| 796 | |
| 797 | // It is safe to obtain the root frame tree node here, as it doesn't change. |
| 798 | FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 799 | ->GetFrameTree()->root(); |
| 800 | |
creis | abdd2bd6 | 2015-11-21 01:14:58 | [diff] [blame] | 801 | EXPECT_EQ(root->current_origin().Serialize() + '/', |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 802 | main_url.GetOrigin().spec()); |
| 803 | |
| 804 | // First frame is an about:blank frame. Check that its origin is correctly |
| 805 | // inherited from the parent. |
creis | abdd2bd6 | 2015-11-21 01:14:58 | [diff] [blame] | 806 | EXPECT_EQ(root->child_at(0)->current_origin().Serialize() + '/', |
| 807 | main_url.GetOrigin().spec()); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 808 | |
| 809 | // Second frame loads a same-site page. Its origin should also be the same |
| 810 | // as the parent. |
creis | abdd2bd6 | 2015-11-21 01:14:58 | [diff] [blame] | 811 | EXPECT_EQ(root->child_at(1)->current_origin().Serialize() + '/', |
| 812 | main_url.GetOrigin().spec()); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 813 | |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 814 | // Load cross-site page into the first frame. |
alexmos | 478dcbb | 2014-12-10 21:24:46 | [diff] [blame] | 815 | GURL cross_site_url( |
| 816 | embedded_test_server()->GetURL("foo.com", "/title2.html")); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 817 | NavigateFrameToURL(root->child_at(0), cross_site_url); |
| 818 | |
creis | abdd2bd6 | 2015-11-21 01:14:58 | [diff] [blame] | 819 | EXPECT_EQ(root->child_at(0)->current_origin().Serialize() + '/', |
| 820 | cross_site_url.GetOrigin().spec()); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 821 | |
| 822 | // The root's origin shouldn't have changed. |
creis | abdd2bd6 | 2015-11-21 01:14:58 | [diff] [blame] | 823 | EXPECT_EQ(root->current_origin().Serialize() + '/', |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 824 | main_url.GetOrigin().spec()); |
| 825 | |
| 826 | GURL data_url("data:text/html,foo"); |
| 827 | NavigateFrameToURL(root->child_at(1), data_url); |
| 828 | |
| 829 | // Navigating to a data URL should set a unique origin. This is represented |
| 830 | // as "null" per RFC 6454. |
creis | abdd2bd6 | 2015-11-21 01:14:58 | [diff] [blame] | 831 | EXPECT_EQ(root->child_at(1)->current_origin().Serialize(), "null"); |
alexmos | bc7eafa | 2014-12-06 01:38:09 | [diff] [blame] | 832 | } |
| 833 | |
Ian Clelland | 5cbaaf8 | 2017-11-27 22:00:03 | [diff] [blame] | 834 | // Ensure that a popup opened from a sandboxed main frame inherits sandbox flags |
| 835 | // from its opener. |
| 836 | IN_PROC_BROWSER_TEST_F(CrossProcessFrameTreeBrowserTest, |
| 837 | SandboxFlagsSetForNewWindow) { |
| 838 | GURL main_url( |
| 839 | embedded_test_server()->GetURL("/sandboxed_main_frame_script.html")); |
| 840 | EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| 841 | |
| 842 | // It is safe to obtain the root frame tree node here, as it doesn't change. |
| 843 | FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 844 | ->GetFrameTree() |
| 845 | ->root(); |
| 846 | |
| 847 | // Open a new window from the main frame. |
| 848 | GURL popup_url(embedded_test_server()->GetURL("foo.com", "/title1.html")); |
| 849 | Shell* new_shell = OpenPopup(root->current_frame_host(), popup_url, ""); |
| 850 | EXPECT_TRUE(new_shell); |
| 851 | WebContents* new_contents = new_shell->web_contents(); |
| 852 | |
| 853 | // Check that the new window's sandbox flags correctly reflect the opener's |
| 854 | // flags. Main frame sets allow-popups, allow-pointer-lock and allow-scripts. |
| 855 | FrameTreeNode* popup_root = |
| 856 | static_cast<WebContentsImpl*>(new_contents)->GetFrameTree()->root(); |
| 857 | blink::WebSandboxFlags main_frame_sandbox_flags = |
| 858 | root->current_frame_host()->active_sandbox_flags(); |
| 859 | EXPECT_EQ(blink::WebSandboxFlags::kAll & ~blink::WebSandboxFlags::kPopups & |
| 860 | ~blink::WebSandboxFlags::kPointerLock & |
| 861 | ~blink::WebSandboxFlags::kScripts & |
| 862 | ~blink::WebSandboxFlags::kAutomaticFeatures, |
| 863 | main_frame_sandbox_flags); |
| 864 | |
| 865 | EXPECT_EQ(main_frame_sandbox_flags, |
| 866 | popup_root->effective_frame_policy().sandbox_flags); |
| 867 | EXPECT_EQ(main_frame_sandbox_flags, popup_root->active_sandbox_flags()); |
| 868 | EXPECT_EQ(main_frame_sandbox_flags, |
| 869 | popup_root->current_frame_host()->active_sandbox_flags()); |
| 870 | } |
| 871 | |
Shivani Sharma | c4f56158 | 2018-11-15 15:58:39 | [diff] [blame^] | 872 | // Tests that the user activation bits get cleared when a cross-site document is |
| 873 | // installed in the frame. |
| 874 | IN_PROC_BROWSER_TEST_F(CrossProcessFrameTreeBrowserTest, |
| 875 | ClearUserActivationForNewDocument) { |
| 876 | GURL main_url(embedded_test_server()->GetURL("/frame_tree/top.html")); |
| 877 | EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| 878 | |
| 879 | // It is safe to obtain the root frame tree node here, as it doesn't change. |
| 880 | FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 881 | ->GetFrameTree() |
| 882 | ->root(); |
| 883 | |
| 884 | EXPECT_FALSE(root->HasBeenActivated()); |
| 885 | EXPECT_FALSE(root->HasTransientUserActivation()); |
| 886 | |
| 887 | // Set the user activation bits. |
| 888 | root->UpdateUserActivationState( |
| 889 | blink::UserActivationUpdateType::kNotifyActivation); |
| 890 | EXPECT_TRUE(root->HasBeenActivated()); |
| 891 | EXPECT_TRUE(root->HasTransientUserActivation()); |
| 892 | |
| 893 | // Install a new cross-site document to check the clearing of user activation |
| 894 | // bits. |
| 895 | GURL cross_site_url( |
| 896 | embedded_test_server()->GetURL("foo.com", "/title2.html")); |
| 897 | EXPECT_TRUE(NavigateToURL(shell(), cross_site_url)); |
| 898 | |
| 899 | EXPECT_FALSE(root->HasBeenActivated()); |
| 900 | EXPECT_FALSE(root->HasTransientUserActivation()); |
| 901 | } |
| 902 | |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 903 | // FrameTreeBrowserTest variant where we isolate http://*.is, Iceland's top |
nasko | abed2a5 | 2017-05-03 05:10:17 | [diff] [blame] | 904 | // level domain. This is an analogue to isolating extensions, which we can use |
| 905 | // inside content_browsertests, where extensions don't exist. Iceland, like an |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 906 | // extension process, is a special place with magical powers; we want to protect |
| 907 | // it from outsiders. |
| 908 | class IsolateIcelandFrameTreeBrowserTest : public ContentBrowserTest { |
| 909 | public: |
| 910 | IsolateIcelandFrameTreeBrowserTest() {} |
| 911 | |
| 912 | void SetUpCommandLine(base::CommandLine* command_line) override { |
Lukasz Anforowicz | e7c87d1 | 2018-11-03 02:53:34 | [diff] [blame] | 913 | // Blink suppresses navigations to blob URLs of origins different from the |
alexis.menard | 83f1b6d | 2017-05-17 19:37:33 | [diff] [blame] | 914 | // frame initiating the navigation. We disable those checks for this test, |
| 915 | // to test what happens in a compromise scenario. |
| 916 | command_line->AppendSwitch(switches::kDisableWebSecurity); |
Lukasz Anforowicz | e7c87d1 | 2018-11-03 02:53:34 | [diff] [blame] | 917 | |
| 918 | // ProcessSwitchForIsolatedBlob test below requires that one of URLs used in |
| 919 | // the test (blob:http://b.is:2932/) belongs to an isolated origin. |
| 920 | command_line->AppendSwitchASCII(switches::kIsolateOrigins, |
| 921 | "http://b.is:2932/"); |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 922 | } |
| 923 | |
| 924 | void SetUpOnMainThread() override { |
| 925 | host_resolver()->AddRule("*", "127.0.0.1"); |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 926 | SetupCrossSiteRedirector(embedded_test_server()); |
martijn | 12d2dad | 2016-11-11 10:59:27 | [diff] [blame] | 927 | ASSERT_TRUE(embedded_test_server()->Start()); |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 928 | } |
| 929 | |
| 930 | private: |
| 931 | DISALLOW_COPY_AND_ASSIGN(IsolateIcelandFrameTreeBrowserTest); |
| 932 | }; |
| 933 | |
| 934 | // Regression test for https://crbug.com/644966 |
| 935 | IN_PROC_BROWSER_TEST_F(IsolateIcelandFrameTreeBrowserTest, |
| 936 | ProcessSwitchForIsolatedBlob) { |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 937 | // Set up an iframe. |
| 938 | WebContents* contents = shell()->web_contents(); |
| 939 | FrameTreeNode* root = |
| 940 | static_cast<WebContentsImpl*>(contents)->GetFrameTree()->root(); |
| 941 | GURL main_url(embedded_test_server()->GetURL( |
nick | 07fd7e1 | 2016-09-12 18:54:06 | [diff] [blame] | 942 | "a.com", "/cross_site_iframe_factory.html?a(a)")); |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 943 | EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| 944 | |
| 945 | // The navigation targets an invalid blob url; that's intentional to trigger |
| 946 | // an error response. The response should commit in a process dedicated to |
Lukasz Anforowicz | e7c87d1 | 2018-11-03 02:53:34 | [diff] [blame] | 947 | // http://b.is:2932. |
Nick Carter | b7e7131 | 2018-08-03 23:36:13 | [diff] [blame] | 948 | EXPECT_EQ( |
| 949 | "done", |
| 950 | EvalJs( |
| 951 | root, |
| 952 | "new Promise((resolve) => {" |
| 953 | " var iframe_element = document.getElementsByTagName('iframe')[0];" |
| 954 | " iframe_element.onload = () => resolve('done');" |
| 955 | " iframe_element.src = 'blob:http://b.is:2932/';" |
| 956 | "});")); |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 957 | WaitForLoadStop(contents); |
| 958 | |
| 959 | // Make sure we did a process transfer back to "b.is". |
| 960 | EXPECT_EQ( |
| 961 | " Site A ------------ proxies for B\n" |
| 962 | " +--Site B ------- proxies for A\n" |
| 963 | "Where A = http://a.com/\n" |
Lukasz Anforowicz | e7c87d1 | 2018-11-03 02:53:34 | [diff] [blame] | 964 | " B = http://b.is:2932/", |
nick | db193a1 | 2016-09-09 23:09:23 | [diff] [blame] | 965 | FrameTreeVisualizer().DepictFrameTree(root)); |
| 966 | } |
| 967 | |
[email protected] | 5f96f5a6 | 2014-01-10 00:05:11 | [diff] [blame] | 968 | } // namespace content |