Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Unified Diff: content/browser/site_per_process_browsertest.cc

Issue 1957783002: Replicate Content-Security-Policy into remote frame proxies. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebasing + small self-review tweaks (comments + assert->dcheck). Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 9e312c8d05b019ba59e80d3c3acd6d91b5aca4b4..c97101c7780c263ad6e49dd3aa429570129b0cbd 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -55,6 +55,7 @@
#include "ipc/ipc_security_test_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
#include "ui/display/display_switches.h"
@@ -6332,6 +6333,191 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
}
}
+// Test that a cross-origin frame's navigation can be blocked by CSP frame-src.
+// In this version of a test, CSP comes from HTTP headers.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ CrossSiteIframeBlockedByParentCSPFromHeaders) {
+ GURL main_url(
+ embedded_test_server()->GetURL("a.com", "/frame-src-self-and-b.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Sanity-check that the test page has the expected shape for testing.
+ EXPECT_FALSE(root->child_at(0)->HasSameOrigin(*root));
+ EXPECT_EQ(embedded_test_server()->GetURL("b.com", "/title2.html"),
+ root->child_at(0)->current_url());
alexmos 2016/05/16 22:31:56 Perhaps we could also check root->current_replicat
Łukasz Anforowicz 2016/05/16 23:12:51 Done. This sounds like a good idea. I guess one
alexmos 2016/05/16 23:38:56 Thanks! One final thought I just had is that it m
Łukasz Anforowicz 2016/05/17 00:19:43 Done (here and for the srcdoc test).
+
+ // Monitor subframe's load events via main frame's title.
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "document.querySelector('iframe').onload = "
+ " function() { document.title = 'loaded'; };"));
+ 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);
+
+ // Try to navigate the subframe to a blocked URL.
+ TestNavigationObserver load_observer(shell()->web_contents());
+ GURL blocked_url = embedded_test_server()->GetURL("c.com", "/title3.html");
+ EXPECT_TRUE(
+ ExecuteScript(root->child_at(0)->current_frame_host(),
+ "window.location.href = '" + blocked_url.spec() + "';"));
+
+ // The blocked frame should still fire a load event in its parent's process.
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ // Check that the current RenderFrameHost has stopped loading.
+ if (root->child_at(0)->current_frame_host()->is_loading()) {
+ ADD_FAILURE() << "Blocked RenderFrameHost shouldn't be loading anything";
+ load_observer.Wait();
+ }
+
+ // The blocked frame should stay at the old location.
+ EXPECT_EQ(embedded_test_server()->GetURL("b.com", "/title2.html"),
+ root->child_at(0)->current_url());
+
+ // The blocked frame should keep the old title.
+ std::string frame_title;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ root->child_at(0)->current_frame_host(),
+ "domAutomationController.send(document.title)", &frame_title));
+ EXPECT_EQ("Title Of Awesomeness", frame_title);
+}
+
+// Test that a cross-origin frame's navigation can be blocked by CSP frame-src.
+// In this version of a test, CSP comes from a <meta> element added after the
+// page has already loaded.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ CrossSiteIframeBlockedByParentCSPFromMeta) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+
+ // Navigate the subframe to a location we will disallow in the future.
+ NavigateFrameToURL(root->child_at(0),
+ embedded_test_server()->GetURL("b.com", "/title2.html"));
alexmos 2016/05/16 22:31:56 nit: consider defining the b.com URL in a var and
Łukasz Anforowicz 2016/05/16 23:12:51 Done.
+
+ // Add frame-src CSP via a new <meta> element.
+ EXPECT_TRUE(ExecuteScript(
+ shell()->web_contents(),
+ "var meta = document.createElement('meta');"
+ "meta.httpEquiv = 'Content-Security-Policy';"
+ "meta.content = 'frame-src https://a.com:*';"
+ "document.getElementsByTagName('head')[0].appendChild(meta);"));
+
+ // Sanity-check that the test page has the expected shape for testing.
+ // (the CSP should not have an effect on the already loaded frames).
+ EXPECT_FALSE(root->child_at(0)->HasSameOrigin(*root));
+ EXPECT_EQ(embedded_test_server()->GetURL("b.com", "/title2.html"),
+ root->child_at(0)->current_url());
+
+ // Monitor subframe's load events via main frame's title.
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "document.querySelector('iframe').onload = "
+ " function() { document.title = 'loaded'; };"));
+ 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);
+
+ // Try to navigate the subframe to a blocked URL.
+ TestNavigationObserver load_observer2(shell()->web_contents());
+ GURL blocked_url = embedded_test_server()->GetURL("c.com", "/title3.html");
+ EXPECT_TRUE(
+ ExecuteScript(root->child_at(0)->current_frame_host(),
+ "window.location.href = '" + blocked_url.spec() + "';"));
+
+ // The blocked frame should still fire a load event in its parent's process.
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ // Check that the current RenderFrameHost has stopped loading.
+ if (root->child_at(0)->current_frame_host()->is_loading()) {
+ ADD_FAILURE() << "Blocked RenderFrameHost shouldn't be loading anything";
+ load_observer2.Wait();
+ }
+
+ // The blocked frame should stay at the old location.
+ EXPECT_EQ(embedded_test_server()->GetURL("b.com", "/title2.html"),
+ root->child_at(0)->current_url());
+
+ // The blocked frame should keep the old title.
+ std::string frame_title;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ root->child_at(0)->current_frame_host(),
+ "domAutomationController.send(document.title)", &frame_title));
+ EXPECT_EQ("Title Of Awesomeness", frame_title);
+}
+
+// Test that a cross-origin frame's navigation can be blocked by CSP frame-src.
+// In this version of a test, CSP is inherited by srcdoc iframe from a parent
+// that declared CSP via HTTP headers. Cross-origin frame navigating to a
+// blocked location is a child of the srcdoc iframe.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ CrossSiteIframeBlockedByCSPInheritedBySrcDocParent) {
+ GURL main_url(
+ embedded_test_server()->GetURL("a.com", "/frame-src-self-and-b.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = web_contents()->GetFrameTree()->root();
+ FrameTreeNode* srcdoc_frame = root->child_at(1);
+ EXPECT_TRUE(srcdoc_frame != nullptr);
+ FrameTreeNode* navigating_frame = srcdoc_frame->child_at(0);
+ EXPECT_TRUE(navigating_frame != nullptr);
+
+ // Sanity-check that the test page has the expected shape for testing.
+ // (the CSP should not have an effect on the already loaded frames).
+ EXPECT_TRUE(srcdoc_frame->HasSameOrigin(*root));
+ EXPECT_FALSE(srcdoc_frame->HasSameOrigin(*navigating_frame));
+ EXPECT_EQ(embedded_test_server()->GetURL("b.com", "/title2.html"),
+ navigating_frame->current_url());
+
+ // Monitor navigating_frame's load events via srcdoc_frame posting
+ // a message to the parent frame.
+ EXPECT_TRUE(
+ ExecuteScript(root->current_frame_host(),
+ "window.addEventListener('message', function(event) {"
+ " document.title = event.data;"
+ "});"));
+ EXPECT_TRUE(ExecuteScript(
+ srcdoc_frame->current_frame_host(),
+ "document.querySelector('iframe').onload = "
+ " function() { window.top.postMessage('loaded', '*'); };"));
+ 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);
+
+ // Try to navigate the subframe to a blocked URL.
+ TestNavigationObserver load_observer2(shell()->web_contents());
+ GURL blocked_url = embedded_test_server()->GetURL("c.com", "/title3.html");
+ EXPECT_TRUE(
+ ExecuteScript(navigating_frame->current_frame_host(),
+ "window.location.href = '" + blocked_url.spec() + "';"));
+
+ // The blocked frame should still fire a load event in its parent's process.
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ // Check that the current RenderFrameHost has stopped loading.
+ if (navigating_frame->current_frame_host()->is_loading()) {
+ ADD_FAILURE() << "Blocked RenderFrameHost shouldn't be loading anything";
+ load_observer2.Wait();
+ }
+
+ // The blocked frame should stay at the old location.
+ EXPECT_EQ(embedded_test_server()->GetURL("b.com", "/title2.html"),
+ navigating_frame->current_url());
+
+ // The blocked frame should keep the old title.
+ std::string frame_title;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ navigating_frame->current_frame_host(),
+ "domAutomationController.send(document.title)", &frame_title));
+ EXPECT_EQ("Title Of Awesomeness", frame_title);
+}
+
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScreenCoordinates) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
« no previous file with comments | « content/browser/frame_host/render_frame_host_manager.cc ('k') | content/common/content_param_traits_macros.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698