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

Unified Diff: content/browser/top_document_isolation_browsertest.cc

Issue 1797363002: "Top Document Isolation" mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Suppress tests under --site-per-process Created 4 years, 9 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
« no previous file with comments | « content/browser/site_instance_impl.cc ('k') | content/common/site_isolation_policy.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/top_document_isolation_browsertest.cc
diff --git a/content/browser/top_document_isolation_browsertest.cc b/content/browser/top_document_isolation_browsertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..dd4541f23185caed04f5107cef2316f837af94ba
--- /dev/null
+++ b/content/browser/top_document_isolation_browsertest.cc
@@ -0,0 +1,571 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/command_line.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/test_frame_navigation_observer.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class TopDocumentIsolationTest : public ContentBrowserTest {
+ public:
+ TopDocumentIsolationTest() {}
+
+ protected:
+ std::string DepictFrameTree(FrameTreeNode* node) {
+ return visualizer_.DepictFrameTree(node);
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(switches::kTopDocumentIsolation);
+ }
+
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ SetupCrossSiteRedirector(embedded_test_server());
+ }
+
+ FrameTreeNode* root() {
+ return static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ }
+
+ void GoBack() {
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_load_observer.Wait();
+ }
+
+ Shell* OpenPopup(FrameTreeNode* opener, const std::string& url) {
+ GURL gurl =
+ opener->current_frame_host()->GetLastCommittedURL().Resolve(url);
+ return content::OpenPopup(opener->current_frame_host(), gurl, "_blank");
+ }
+
+ void RendererInitiatedNavigateToURL(FrameTreeNode* node, const GURL& url) {
+ TestFrameNavigationObserver nav_observer(node);
+ ASSERT_TRUE(ExecuteScript(node->current_frame_host(),
+ "window.location.href='" + url.spec() + "'"));
+ nav_observer.Wait();
+ }
+
+ private:
+ FrameTreeVisualizer visualizer_;
+};
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, SameSiteDeeplyNested) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A\n"
+ " |--Site A\n"
+ " +--Site A\n"
+ " |--Site A\n"
+ " +--Site A\n"
+ " +--Site A\n"
+ "Where A = http://a.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, CrossSiteDeeplyNested) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c(d(b))))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, ReturnToTopSite) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(a(c)))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ " +--Site A -- proxies for B\n"
+ " +--Site B -- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateSubframeToTopSite) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c(d)))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ GURL ada_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(d(a))"));
+ RendererInitiatedNavigateToURL(root()->child_at(0)->child_at(0), ada_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ " +--Site A -- proxies for B\n"
+ " +--Site B -- proxies for A\n"
+ " +--Site A -- proxies for B\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateToSubframeSite) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL ab_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ GURL ba_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(a, c)"));
+
+ NavigateToURL(shell(), ab_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ NavigateToURL(shell(), ba_url);
+
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ " |--Site B ------- proxies for C\n"
+ " +--Site B ------- proxies for C\n"
+ "Where B = default subframe process\n"
+ " C = http://b.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
+ NavigateToSubframeSiteWithPopup) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ // A(B) -> B(A), but while a separate B(A) popup exists.
+ GURL ab_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+
+ NavigateToURL(shell(), ab_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ Shell* popup =
+ OpenPopup(root()->child_at(0), "/cross_site_iframe_factory.html?b(a)");
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(popup->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // This popup's main frame must stay in the default subframe siteinstance,
+ // since its opener (the b.com subframe) may synchronously script it. Note
+ // that the popup's subframe is same-site with window.top.opener.top, the
+ // a.com main frame of the tab. But --top-document-isolation does not
+ // currently place the popup subframe in the a.com process in this case.
+ EXPECT_EQ(
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+
+ GURL ba_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(a, c)"));
+ NavigateToURL(shell(), ba_url);
+
+ // This navigation destroys the popup's opener, so we allow the main frame to
+ // commit in a top level process for b.com, in spite of the b.com popup in the
+ // default subframe process.
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ " |--Site B ------- proxies for C\n"
+ " +--Site B ------- proxies for C\n"
+ "Where B = default subframe process\n"
+ " C = http://b.com/",
+ DepictFrameTree(root()));
+ EXPECT_EQ(
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+
+ // Navigate the popup to a new site.
+ GURL c_url(embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c(c, c, c, c)"));
+ NavigateToURL(popup, c_url);
+ EXPECT_EQ(
+ " Site D ------------ proxies for B\n"
+ " |--Site D ------- proxies for B\n"
+ " |--Site D ------- proxies for B\n"
+ " |--Site D ------- proxies for B\n"
+ " +--Site D ------- proxies for B\n"
+ "Where B = default subframe process\n"
+ " D = http://c.com/",
+ DepictFrameTree(popup_root));
+ NavigateToURL(shell(), c_url);
+ EXPECT_EQ(
+ " Site D\n"
+ " |--Site D\n"
+ " |--Site D\n"
+ " |--Site D\n"
+ " +--Site D\n"
+ "Where D = http://c.com/",
+ DepictFrameTree(popup_root));
+ EXPECT_EQ(
+ " Site D\n"
+ " |--Site D\n"
+ " |--Site D\n"
+ " |--Site D\n"
+ " +--Site D\n"
+ "Where D = http://c.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
+ NavigateToSubframeSiteWithPopup2) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ // A(B, C) -> C(A, B), but while a separate C(A) popup exists.
+ //
+ // This test is constructed so that c.com is the second site to commit in the
+ // default subframe SiteInstance, so the default subframe SiteInstance does
+ // not have a "c.com" as the value of GetSiteURL().
+ GURL abb_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b, b)"));
+
+ NavigateToURL(shell(), abb_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " |--Site B ------- proxies for A\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ // A(B, B) -> A(B, C)
+ GURL c_url(embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c"));
+ NavigateFrameToURL(root()->child_at(1), c_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " |--Site B ------- proxies for A\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ // This test exercises what happens when the SiteURL of the default subframe
+ // siteinstance doesn't match the subframe site.
+ EXPECT_NE("c.com", root()
+ ->child_at(1)
+ ->current_frame_host()
+ ->GetSiteInstance()
+ ->GetSiteURL()
+ .host());
+
+ // Subframe C creates C(A) popup.
+ Shell* popup =
+ OpenPopup(root()->child_at(1), "/cross_site_iframe_factory.html?c(a)");
+
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(popup->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // The popup must stay with its opener, in the default subframe process.
+ EXPECT_EQ(
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+
+ GURL cab_url(embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c(a, b)"));
+ NavigateToURL(shell(), cab_url);
+
+ // This c.com navigation currently breaks out of the default subframe process,
+ // even though that process houses a c.com pop-up.
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ " |--Site B ------- proxies for C\n"
+ " +--Site B ------- proxies for C\n"
+ "Where B = default subframe process\n"
+ " C = http://c.com/",
+ DepictFrameTree(root()));
+
+ // c.com popup should remain where it was, in the subframe process.
+ EXPECT_EQ(
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+ EXPECT_EQ(nullptr, popup_root->opener());
+
+ // If we navigate the popup to a new site, it ought to transfer processes.
+ GURL d_url(embedded_test_server()->GetURL(
+ "d.com", "/cross_site_iframe_factory.html?d"));
+ NavigateToURL(popup, d_url);
+ EXPECT_EQ(
+ " Site D ------------ proxies for B\n"
+ "Where B = default subframe process\n"
+ " D = http://d.com/",
+ DepictFrameTree(popup_root));
+ NavigateToURL(shell(), d_url);
+ EXPECT_EQ(
+ " Site D\n"
+ "Where D = http://d.com/",
+ DepictFrameTree(popup_root));
+ EXPECT_EQ(
+ " Site D\n"
+ "Where D = http://d.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, FramesForSitesInHistory) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ // First, do a series of navigations.
+ GURL a_url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a");
+ GURL b_url = embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b");
+ GURL c_url = embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c");
+
+ // Browser-initiated navigation to a.com.
+ NavigateToURL(shell(), a_url);
+ EXPECT_EQ(
+ " Site A\n"
+ "Where A = http://a.com/",
+ DepictFrameTree(root()));
+
+ // Browser-initiated navigation to b.com.
+ NavigateToURL(shell(), b_url);
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = http://b.com/",
+ DepictFrameTree(root()));
+
+ // Renderer-initiated navigation back to a.com. This shouldn't swap processes.
+ RendererInitiatedNavigateToURL(root(), a_url);
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = http://b.com/",
+ DepictFrameTree(root()));
+
+ // Browser-initiated navigation to c.com.
+ NavigateToURL(shell(), c_url);
+ EXPECT_EQ(
+ " Site C\n"
+ "Where C = http://c.com/",
+ DepictFrameTree(root()));
+
+ // Now, navigate to a fourth site with iframes to the sites in the history.
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL(
+ "d.com", "/cross_site_iframe_factory.html?d(a,b,c)"));
+
+ EXPECT_EQ(
+ " Site D ------------ proxies for E\n"
+ " |--Site E ------- proxies for D\n"
+ " |--Site E ------- proxies for D\n"
+ " +--Site E ------- proxies for D\n"
+ "Where D = http://d.com/\n"
+ " E = default subframe process",
+ DepictFrameTree(root()));
+
+ // Now try going back.
+ GoBack();
+ EXPECT_EQ(
+ " Site C\n"
+ "Where C = http://c.com/",
+ DepictFrameTree(root()));
+ GoBack();
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = http://b.com/",
+ DepictFrameTree(root()));
+ GoBack();
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = http://b.com/",
+ DepictFrameTree(root()));
+ GoBack();
+ EXPECT_EQ(
+ " Site A\n"
+ "Where A = http://a.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, CrossSiteAtLevelTwo) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a(b, a))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site A ------- proxies for B\n"
+ " |--Site B -- proxies for A\n"
+ " +--Site A -- proxies for B\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ GURL c_url(embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c"));
+ NavigateFrameToURL(root()->child_at(0)->child_at(1), c_url);
+
+ // This navigation should complete in the default subframe siteinstance.
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site A ------- proxies for B\n"
+ " |--Site B -- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, PopupAndRedirection) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "page.com", "/cross_site_iframe_factory.html?page(adnetwork)"));
+
+ // User opens page on page.com which contains a subframe from adnetwork.com.
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://page.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ GURL ad_url(embedded_test_server()->GetURL(
+ "ad.com", "/cross_site_iframe_factory.html?ad"));
+
+ // adnetwork.com retrieves an ad from advertiser (ad.com) and redirects the
+ // subframe to ad.com.
+ RendererInitiatedNavigateToURL(root()->child_at(0), ad_url);
+
+ // The subframe still uses the default subframe SiteInstance after navigation.
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://page.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ // User clicks the ad in the subframe, which opens a popup on the ad
+ // network's domain.
+ GURL popup_url(embedded_test_server()->GetURL(
+ "adnetwork.com", "/cross_site_iframe_factory.html?adnetwork"));
+ Shell* popup = OpenPopup(root()->child_at(0), popup_url.spec());
+
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(popup->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // It's ok for the popup to break out of the subframe process because it's
+ // currently cross-site from its opener frame.
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ "Where B = default subframe process\n"
+ " C = http://adnetwork.com/",
+ DepictFrameTree(popup_root));
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B C\n"
+ " +--Site B ------- proxies for A C\n"
+ "Where A = http://page.com/\n"
+ " B = default subframe process\n"
+ " C = http://adnetwork.com/",
+ DepictFrameTree(root()));
+
+ // The popup redirects itself to the advertiser's website (ad.com).
+ RendererInitiatedNavigateToURL(popup_root, ad_url);
+
+ // This must join its same-site opener, in the default subframe SiteInstance.
+ EXPECT_EQ(
+ " Site A ------------ proxies for B C\n"
+ " +--Site B ------- proxies for A C\n"
+ "Where A = http://page.com/\n"
+ " B = default subframe process\n"
+ " C = http://adnetwork.com/",
+ DepictFrameTree(root()));
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ "Where B = default subframe process\n"
+ " C = http://adnetwork.com/",
+ DepictFrameTree(popup_root));
+}
+
+} // namespace content
« no previous file with comments | « content/browser/site_instance_impl.cc ('k') | content/common/site_isolation_policy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698