| 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
|
|
|