Index: content/browser/site_per_process_browsertest.cc |
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc |
index 24af2a89cafc7ca31f31f6bcd2e2ea655ccbc3ed..b707bdbb654ad370198ab8aad7e07206df02074c 100644 |
--- a/content/browser/site_per_process_browsertest.cc |
+++ b/content/browser/site_per_process_browsertest.cc |
@@ -5301,4 +5301,71 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframeDisplayNone) { |
observer->Wait(); |
} |
+// Test that a cross-origin iframe can be blocked by X-Frame-Options and CSP |
+// frame-ancestors. |
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
+ CrossSiteIframeBlockedByXFrameOptionsOrCSP) { |
+ GURL main_url(embedded_test_server()->GetURL( |
+ "a.com", "/cross_site_iframe_factory.html?a(a)")); |
+ NavigateToURL(shell(), main_url); |
+ |
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
+ ->GetFrameTree() |
+ ->root(); |
+ GURL frame_url(root->child_at(0)->current_url()); |
+ |
+ // Add a load event handler for the iframe element. |
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), |
+ "document.querySelector('iframe').onload = " |
+ " function() { document.title = 'loaded'; };")); |
+ |
+ GURL blocked_urls[] = { |
+ embedded_test_server()->GetURL("b.com", "/frame-ancestors-none.html"), |
+ embedded_test_server()->GetURL("b.com", "/x-frame-options-deny.html") |
+ }; |
+ |
+ for (size_t i = 0; i < arraysize(blocked_urls); ++i) { |
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), |
+ "document.title = 'not loaded';")); |
+ base::string16 expected_title(base::UTF8ToUTF16("loaded")); |
+ TitleWatcher title_watcher(shell()->web_contents(), expected_title); |
+ |
+ // Navigate the subframe to a blocked URL, and wait for navigation to fail. |
+ TestNavigationObserver load_observer(shell()->web_contents()); |
+ EXPECT_TRUE(ExecuteScript( |
+ shell()->web_contents(), |
+ "frames[0].location.href = '" + blocked_urls[i].spec() + "';")); |
+ load_observer.Wait(); |
+ |
+ // Blocking the frame will result in a DidFailProvisionalLoad; i.e., the |
+ // last navigation should have failed. |
+ EXPECT_FALSE(load_observer.last_navigation_succeeded()); |
+ |
+ // The blocked frame's origin should become unique. |
+ EXPECT_EQ("null", root->child_at(0)->current_origin().Serialize()); |
+ |
+ // The blocked frame should still fire a load event in its parent's process. |
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); |
+ |
+ // Double-check that the current RenderFrameHost has stopped loading. |
+ EXPECT_FALSE(root->child_at(0)->current_frame_host()->is_loading()); |
+ |
+ // Navigate the subframe to another cross-origin page and ensure that this |
+ // navigation succeeds. |
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html")); |
+ EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "child-0", c_url)); |
+ EXPECT_EQ(c_url, root->child_at(0)->current_url()); |
+ |
+ // When a page gets blocked due to XFO or CSP, it is sandboxed with the |
+ // SandboxOrigin flag (i.e., its origin is set to be unique) in the |
+ // renderer to ensure that the blocked page is seen as cross-origin. |
+ // However, those flags shouldn't affect future navigations for a frame. |
+ // Verify this for the above navigation. |
+ EXPECT_EQ(c_url.GetOrigin().spec(), |
+ root->child_at(0)->current_origin().Serialize() + "/"); |
+ EXPECT_EQ(blink::WebSandboxFlags::None, |
+ root->child_at(0)->effective_sandbox_flags()); |
+ } |
+} |
+ |
} // namespace content |