blob: 2731d74b2435a86f63777055a0169a2957bb3988 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/test/scoped_feature_list.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/content_navigation_policy.h"
#include "content/public/test/browser_test.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/shell/browser/shell.h"
#include "content/test/content_browser_test_base.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 "testing/gtest/include/gtest/gtest.h"
namespace content {
// A set of tests for loading data: URL subframes in their own SiteInstance in
// their initiator's SiteInstanceGroup. Parameterized to also run in the legacy
// mode where data: URLs load in their initiator's SiteInstance. See
// https://crbug.com/40176090.
class DataURLSiteInstanceGroupTest
: public ContentBrowserTestBase,
public ::testing::WithParamInterface<bool> {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
IsolateAllSitesForTesting(command_line);
if (IsSiteInstanceGroupEnabled()) {
feature_list_.InitAndEnableFeature(
features::kSiteInstanceGroupsForDataUrls);
} else {
feature_list_.InitAndDisableFeature(
features::kSiteInstanceGroupsForDataUrls);
}
}
static std::string DescribeParams(
const testing::TestParamInfo<ParamType>& info) {
return info.param ? "DataSubframeHasOwnSiteInstance"
: "DataSubframeInInitiatorSiteInstance";
}
protected:
bool IsSiteInstanceGroupEnabled() const { return GetParam(); }
private:
base::test::ScopedFeatureList feature_list_;
};
// A b.com subframe navigates itself to a data: URL. This allows testing that a
// navigation from b.com to a data: URL is a local-to-local frame navigation and
// does not create a proxy, despite being cross-SiteInstance.
IN_PROC_BROWSER_TEST_P(DataURLSiteInstanceGroupTest,
DISABLED_SiteInstanceGroupDataURLSubframe) {
GURL url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b,b)"));
EXPECT_TRUE(NavigateToURL(shell(), url));
// Both subframes share a site and therefore SiteInstance.
EXPECT_EQ(main_frame()
->child_at(0)
->render_manager()
->current_frame_host()
->GetSiteInstance(),
main_frame()
->child_at(1)
->render_manager()
->current_frame_host()
->GetSiteInstance());
// The first B subframe navigates itself to a data: URL, so the data: subframe
// has initiator b.com.
GURL data_url("data:text/html,test");
EXPECT_TRUE(NavigateToURLFromRenderer(main_frame()->child_at(0), data_url));
SiteInstanceGroup* root_group = main_frame_host()->GetSiteInstance()->group();
SiteInstanceImpl* child0_instance = main_frame()
->child_at(0)
->render_manager()
->current_frame_host()
->GetSiteInstance();
SiteInstanceImpl* child1_instance = main_frame()
->child_at(1)
->render_manager()
->current_frame_host()
->GetSiteInstance();
// In both parameterization modes, the root is cross-site from the subframes
// and should not share a process or SiteInstanceGroup.
EXPECT_NE(root_group, child0_instance->group());
if (ShouldCreateSiteInstanceForDataUrls()) {
// The data: subframe should have its own SiteInstance in the same
// SiteInstanceGroup as the other B subframe.
EXPECT_NE(child0_instance, child1_instance);
EXPECT_EQ(child0_instance->group(), child1_instance->group());
} else {
// The data: subframe shares a SiteInstance with the other B subframe.
EXPECT_EQ(child0_instance, child1_instance);
}
// TODO(https://crbug.com/40269084, yangsharon): Add DepictFrameTree calls
// once they fully support SiteInstanceGroups.
}
// Check that for a main frame data: URL, about:blank frames end up in the data:
// URL's SiteInstance and can be scripted.
IN_PROC_BROWSER_TEST_P(DataURLSiteInstanceGroupTest,
MainFrameDataURLWithAboutBlank) {
// Load a main frame data: URL with an about:blank subframe. The main frame
// and subframe should be in the same SiteInstance.
GURL data_url(
"data:text/html,<body> This page has one about:blank iframe:"
"<iframe name='frame1' src='about:blank'></iframe> </body>");
EXPECT_TRUE(NavigateToURL(shell(), data_url));
EXPECT_EQ(main_frame_host()->GetSiteInstance(),
main_frame()->child_at(0)->current_frame_host()->GetSiteInstance());
EXPECT_EQ(
" Site A\n"
" +--Site A\n"
"Where A = data:nonce_A",
DepictFrameTree(*main_frame()));
// The main frame should be able to script its about:blank subframe.
EXPECT_TRUE(ExecJs(main_frame(), "frames[0].window.name = 'new-name'"));
EXPECT_EQ(main_frame()->child_at(0)->frame_name(), "new-name");
}
// Check that for a subframe data: URL, about:blank frames end up in the data:
// URL's SiteInstance and can be scripted.
IN_PROC_BROWSER_TEST_P(DataURLSiteInstanceGroupTest,
SubframeDataURLWithAboutBlank) {
// Navigate to a main frame with a cross-site iframe.
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
// Navigate the subframe to a data: URL with an about:blank subframe.
GURL data_url(
"data:text/html,<body> This page has one about:blank iframe:"
"<iframe name='frame1' src='about:blank'></iframe> </body>");
TestNavigationObserver observer(web_contents());
FrameTreeNode* child = main_frame()->child_at(0);
EXPECT_TRUE(NavigateToURLFromRenderer(child, data_url));
EXPECT_TRUE(observer.last_navigation_succeeded());
// The data: frame should be able to script its about:blank subframe.
EXPECT_TRUE(ExecJs(child, "frames[0].window.name = 'new-name'"));
EXPECT_EQ(child->child_at(0)->frame_name(), "new-name");
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/",
DepictFrameTree(*main_frame()));
// TODO(https://crbug.com/40269084, yangsharon): Add SiteInstance
// comparisons, and a SiteInstanceGroup-enabled DepictFrameTree check once
// data: URLs in SiteInstanceGroups are supported.
}
INSTANTIATE_TEST_SUITE_P(All,
DataURLSiteInstanceGroupTest,
::testing::Bool(),
&DataURLSiteInstanceGroupTest::DescribeParams);
} // namespace content