Chromium Code Reviews| 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..07992aab35ae027e9b654baa8539cc7c462df284 |
| --- /dev/null |
| +++ b/content/browser/isolate_top_document_browsertest.cc |
| @@ -0,0 +1,409 @@ |
| +// 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 { |
| + |
| +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::kIsolateTopDocument); |
| + } |
| + |
| + void SetUpOnMainThread() { |
|
Xiaocheng
2016/03/22 04:35:04
Please add |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(); |
| + } |
| + |
| + 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 = http://b.com/ (3rd party)", |
| + 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 = http://b.com/ (3rd party)", |
| + 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 = http://b.com/ (3rd party)", |
| + DepictFrameTree(root())); |
| + |
| + NavigateToURL(shell(), ba_url); |
| + |
| + // TODO(nick): The following result is wrong; after navigation, b.com should |
| + // be in a dedicated process; a.com and b.com should share a 3rd party |
| + // subframe process. |
| + EXPECT_EQ( |
| + " 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 = http://b.com/ (3rd party)", |
| + 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 = http://b.com/ (3rd party)", |
| + DepictFrameTree(root())); |
| + |
| + ShellAddedObserver new_shell_observer; |
| + EXPECT_TRUE(ExecuteScript( |
| + root()->child_at(0)->current_frame_host(), |
| + "popup = window.open('/cross_site_iframe_factory.html?b(a)');")); |
| + Shell* popup = new_shell_observer.GetShell(); |
| + |
| + FrameTreeNode* popup_root = |
| + static_cast<WebContentsImpl*>(popup->web_contents()) |
| + ->GetFrameTree() |
| + ->root(); |
| + |
| + // TODO(nick): This popup is an example of a main frame that ends up in the |
| + // 3rd party process. This is unavoidable in this case, however. |
| + EXPECT_EQ( |
| + " Site B\n" |
| + "Where B = http://b.com/ (3rd party)", |
| + DepictFrameTree(popup_root)); |
| + |
| + // Because of the existing popup, this navigation needs to stay in the 3rd |
| + // party process as well. |
| + GURL ba_url(embedded_test_server()->GetURL( |
| + "b.com", "/cross_site_iframe_factory.html?b(a, c)")); |
| + NavigateToURL(shell(), ba_url); |
| + |
| + EXPECT_EQ( |
| + " Site B ------------ proxies for A\n" |
| + " +--Site A ------- proxies for B\n" |
| + "Where A = http://a.com/\n" |
| + " B = http://b.com/ (3rd party)", |
| + DepictFrameTree(popup_root)); |
| + EXPECT_EQ( |
| + " 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 = http://b.com/ (3rd party)", |
| + DepictFrameTree(root())); |
| + |
| + // If we navigate the popup to a new site, it ought to leave the 3rd party |
| + // process. |
| + 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 C ------------ proxies for A B\n" |
| + " |--Site C ------- proxies for A B\n" |
| + " |--Site C ------- proxies for A B\n" |
| + " |--Site C ------- proxies for A B\n" |
| + " +--Site C ------- proxies for A B\n" |
| + "Where A = http://a.com/\n" |
| + " B = http://b.com/ (3rd party)\n" |
| + " C = http://c.com/", |
| + DepictFrameTree(popup_root)); |
| + NavigateToURL(shell(), c_url); |
| + EXPECT_EQ( |
| + " Site C\n" |
| + " |--Site C\n" |
| + " |--Site C\n" |
| + " |--Site C\n" |
| + " +--Site C\n" |
| + "Where C = http://c.com/", |
| + DepictFrameTree(popup_root)); |
| + EXPECT_EQ( |
| + " Site C\n" |
| + " |--Site C\n" |
| + " |--Site C\n" |
| + " |--Site C\n" |
| + " +--Site C\n" |
| + "Where C = 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 = http://b.com/ (3rd party)", |
| + 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 = http://b.com/ (3rd party)", |
| + DepictFrameTree(root())); |
| + |
| + // Subframe C creates C(A) popup. |
| + ShellAddedObserver new_shell_observer; |
| + EXPECT_TRUE(ExecuteScript( |
| + root()->child_at(0)->current_frame_host(), |
| + "popup = window.open('/cross_site_iframe_factory.html?c(a)');")); |
| + Shell* popup = new_shell_observer.GetShell(); |
| + |
| + FrameTreeNode* popup_root = |
| + static_cast<WebContentsImpl*>(popup->web_contents()) |
| + ->GetFrameTree() |
| + ->root(); |
| + |
| + // TODO(nick): This popup is an example of a main frame that ends up in the |
| + // 3rd party process. This is unavoidable in this case, however. |
| + EXPECT_EQ( |
| + " Site B\n" |
| + "Where B = http://b.com/ (3rd party)", |
| + DepictFrameTree(popup_root)); |
| + |
| + // Because of the existing popup, this navigation needs to stay in the 3rd |
| + // party process as well. |
| + GURL ba_url(embedded_test_server()->GetURL( |
| + "c.com", "/cross_site_iframe_factory.html?c(a, b)")); |
| + NavigateToURL(shell(), ba_url); |
| + |
| + EXPECT_EQ( |
| + " Site B ------------ proxies for A\n" |
| + " +--Site A ------- proxies for B\n" |
| + "Where A = http://a.com/\n" |
| + " B = http://b.com/ (3rd party)", |
| + DepictFrameTree(popup_root)); |
| + |
| + // TODO(nick): This is a bug, caused by the fact that the BrowsingInstance |
| + // didn't record that SiteInstance B is also in use by c.com. |
| + EXPECT_EQ( |
| + " Site C ------------ proxies for A B\n" |
| + " |--Site A ------- proxies for B C\n" |
| + " +--Site B ------- proxies for A C\n" |
| + "Where A = http://a.com/\n" |
| + " B = http://b.com/ (3rd party)\n" |
| + " C = http://c.com/", |
| + DepictFrameTree(root())); |
| + |
| + // 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 A B\n" |
| + "Where A = http://a.com/\n" |
| + " B = http://b.com/ (3rd party)\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 |
| + // for these cross-site navigations. What should the behavior be here, for |
| + // --isolate-top-document? |
| + 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, |
| + // 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 A B C\n" |
| + " |--Site A ------- proxies for B C D\n" |
| + " |--Site B ------- proxies for A C D\n" |
| + " +--Site C ------- proxies for A B D\n" |
| + "Where A = http://a.com/\n" |
| + " B = http://b.com/\n" |
| + " C = http://c.com/\n" |
| + " D = http://d.com/", |
| + 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 = http://b.com/ (3rd party)", |
| + 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 = http://b.com/ (3rd party)", |
| + DepictFrameTree(root())); |
| +} |
| + |
|
Xiaocheng
2016/03/22 04:35:04
Can we add the following test case? It doesn't con
|
| +} // namespace content |