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

Unified Diff: content/browser/isolate_top_document_browsertest.cc

Issue 1797363002: "Top Document Isolation" mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add missing override 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
Index: content/browser/isolate_top_document_browsertest.cc
diff --git a/content/browser/isolate_top_document_browsertest.cc b/content/browser/isolate_top_document_browsertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ebd0020f27f0abba2b4a195154732ee5adc7e447
--- /dev/null
+++ b/content/browser/isolate_top_document_browsertest.cc
@@ -0,0 +1,468 @@
+// 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 "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// TODO(nick): Rename this class/file to match the new switch name.
Charlie Reis 2016/03/25 19:47:13 Yep, worth doing.
ncarter (slow) 2016/03/28 22:00:29 Done.
+class IsolateTopDocumentBrowserTest : public ContentBrowserTest {
+ public:
+ IsolateTopDocumentBrowserTest() {}
+
+ 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");
+ }
+
+ private:
+ FrameTreeVisualizer visualizer_;
+};
+
+IN_PROC_BROWSER_TEST_F(IsolateTopDocumentBrowserTest, SameSiteDeeplyNested) {
+ 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(IsolateTopDocumentBrowserTest, CrossSiteDeeplyNested) {
+ 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(IsolateTopDocumentBrowserTest, ReturnToTopSite) {
+ 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(IsolateTopDocumentBrowserTest, NavigateToSubframeSite) {
+ 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(IsolateTopDocumentBrowserTest,
+ NavigateToSubframeSiteWithPopup) {
+ // 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();
+
+ EXPECT_EQ(
Charlie Reis 2016/03/25 19:47:12 Maybe add a comment about how (at least for now) w
ncarter (slow) 2016/03/28 22:00:29 Done.
+ " 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);
+
+ EXPECT_EQ(
Charlie Reis 2016/03/25 19:47:13 Let's add a comment here as well, saying we're ok
ncarter (slow) 2016/03/28 22:00:29 Done.
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+ 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()));
+
+ // 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(IsolateTopDocumentBrowserTest,
+ NavigateToSubframeSiteWithPopup2) {
+ // A(B, C) -> C(A, B), but while a separate C(A) popup exists.
+ 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()));
+
+ // 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 in the default subframe process.
+ EXPECT_EQ(
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+
+ // Because of the existing popup, this navigation needs to stay in the 3rd
+ // party process as well.
Charlie Reis 2016/03/25 19:47:13 s/3rd party/subframe/ Also, this comment disagree
ncarter (slow) 2016/03/28 22:00:29 Done. I also clarified what the difference is bet
+ GURL ba_url(embedded_test_server()->GetURL(
Charlie Reis 2016/03/25 19:47:12 nit: ca_url?
ncarter (slow) 2016/03/28 22:00:28 Done.
+ "c.com", "/cross_site_iframe_factory.html?c(a, b)"));
+ NavigateToURL(shell(), ba_url);
+
+ // TODO(nick): This c.com navigation currently breaks out of the default
+ // subframe process, even though that process houses a c.com pop-up. Bug or
+ // feature?
Charlie Reis 2016/03/25 19:47:12 I think this is probably ok for now. The subframe
ncarter (slow) 2016/03/28 22:00:28 Done.
+ 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.
Charlie Reis 2016/03/25 19:47:12 Is there a reason to check this? We haven't chang
ncarter (slow) 2016/03/28 22:00:29 Yes. Proxies could have been created.
Charlie Reis 2016/03/29 17:17:12 Acknowledged.
+ 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(IsolateTopDocumentBrowserTest, FramesForSitesInHistory) {
+ // First, do a series of navigations.
+ NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a"));
+ EXPECT_EQ(
+ " Site A\n"
+ "Where A = http://a.com/",
+ DepictFrameTree(root()));
+ NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b"));
+
+ // TODO(nick): Without --isolate-top-document, we would not swap processes
Charlie Reis 2016/03/25 19:47:12 nit: --top-document-isolation, here and below.
ncarter (slow) 2016/03/28 22:00:29 Done.
+ // for these cross-site navigations. What should the behavior be here, for
+ // --isolate-top-document?
Charlie Reis 2016/03/25 19:47:12 I don't follow. We do swap processes for top-leve
ncarter (slow) 2016/03/28 22:00:29 My original prototype was based on making the top
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = http://b.com/",
+ DepictFrameTree(root()));
+ NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c"));
+ 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)"));
+
+ // TODO(nick): These subframes ought to end up in the third-party process,
Xiaocheng 2016/03/25 08:30:52 nit: This TODO can be removed now.
ncarter (slow) 2016/03/28 22:00:29 Done.
+ // but because we cache the SiteInstances in the navigation entries, we
+ // can't place these subframes into the siteinstance for 3rd party frames.
+ 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 A\n"
+ "Where A = http://a.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(IsolateTopDocumentBrowserTest, CrossSiteAtLevelTwo) {
+ 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 using the existing 3rd party 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(IsolateTopDocumentBrowserTest, PopupAndRedirection) {
+ 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
Charlie Reis 2016/03/25 19:47:12 nit: End with period.
ncarter (slow) 2016/03/28 22:00:29 Done.
+ 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 C.
Xiaocheng 2016/03/25 08:30:52 nit: C -> ad.com
ncarter (slow) 2016/03/28 22:00:29 Done.
+ // TODO(nick): Make this a renderer-inititated navigation.
Charlie Reis 2016/03/25 19:47:13 Yep, let's do this. Shouldn't change the outcome,
ncarter (slow) 2016/03/28 22:00:29 Done.
+ NavigateFrameToURL(root()->child_at(0), ad_url);
+
+ // The subframe still uses the same third-party 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
+ // platform's domain.
Charlie Reis 2016/03/25 19:47:12 s/platform/network/
ncarter (slow) 2016/03/28 22:00:28 Done.
+ 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();
+
+ EXPECT_EQ(
Charlie Reis 2016/03/25 19:47:12 Let's add a comment about how we think it's ok for
ncarter (slow) 2016/03/28 22:00:29 Done.
+ " 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));
+
+ // The popup redirects itself to the advertiser's website (ad.com).
+ NavigateToURL(popup, ad_url);
+
+ // This must join its same-site opener, in the default subframe SiteInstance.
Charlie Reis 2016/03/25 19:47:12 Wow, I'm impressed this passes. That's a cool con
ncarter (slow) 2016/03/28 22:00:29 Acknowledged.
+ 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()));
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698