| // Copyright 2022 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/command_line.h" |
| #include "base/feature_list.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "chrome/browser/metrics/metrics_memory_details.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "components/network_session_configurator/common/network_switches.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/content_features.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/test/browser_test.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/content_mock_cert_verifier.h" |
| #include "content/public/test/test_navigation_observer.h" |
| #include "net/dns/mock_host_resolver.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "third_party/blink/public/common/features.h" |
| #include "url/gurl.h" |
| |
| class TestMemoryDetails : public MetricsMemoryDetails { |
| public: |
| TestMemoryDetails() : MetricsMemoryDetails(base::DoNothing()) {} |
| |
| TestMemoryDetails(const TestMemoryDetails&) = delete; |
| TestMemoryDetails& operator=(const TestMemoryDetails&) = delete; |
| |
| void StartFetchAndWait() { |
| uma_ = std::make_unique<base::HistogramTester>(); |
| StartFetch(); |
| run_loop_.Run(); |
| } |
| |
| // Assumes we've just finished calling StartFetchAndWait(), and there is at |
| // most one sample recorded for `metric`. |
| void VerifyMetricResult(const std::string& metric, int value, int count) { |
| std::vector<base::Bucket> histogram_for_metric = |
| uma_->GetAllSamples(metric); |
| if (histogram_for_metric.size()) { |
| EXPECT_EQ(base::Bucket(value, count), histogram_for_metric[0]) |
| << " : metric = " << metric; |
| } else { |
| EXPECT_EQ(0, count) << " : metric = " << metric; |
| } |
| } |
| |
| // Returns a HistogramTester which observed the most recent call to |
| // StartFetchAndWait(). |
| base::HistogramTester* uma() { return uma_.get(); } |
| |
| private: |
| ~TestMemoryDetails() override = default; |
| |
| void OnDetailsAvailable() override { |
| MetricsMemoryDetails::OnDetailsAvailable(); |
| // Exit the loop initiated by StartFetchAndWait(). |
| run_loop_.QuitWhenIdle(); |
| } |
| |
| std::unique_ptr<base::HistogramTester> uma_; |
| base::RunLoop run_loop_; |
| }; |
| |
| class IsolatedSandboxedIframeBrowserTestBase : public InProcessBrowserTest { |
| public: |
| explicit IsolatedSandboxedIframeBrowserTestBase( |
| bool enable_isolate_sandboxed_iframes) |
| : https_server_(net::EmbeddedTestServer::TYPE_HTTPS), |
| enable_isolate_sandboxed_iframes_(enable_isolate_sandboxed_iframes) { |
| // To keep the tests easier to reason about, turn off both the spare |
| // renderer process and process reuse for subframes in different |
| // BrowsingInstances. |
| if (enable_isolate_sandboxed_iframes_) { |
| feature_list_.InitWithFeatures( |
| /* enable_features */ {blink::features::kIsolateSandboxedIframes, |
| features::kDisableProcessReuse}, |
| /* disable_features */ {features::kSpareRendererForSitePerProcess}); |
| } else { |
| feature_list_.InitWithFeatures( |
| /* enable_features */ {features::kDisableProcessReuse}, |
| /* disable_features */ {blink::features::kIsolateSandboxedIframes, |
| features::kSpareRendererForSitePerProcess}); |
| } |
| } |
| |
| IsolatedSandboxedIframeBrowserTestBase( |
| const IsolatedSandboxedIframeBrowserTestBase&) = delete; |
| IsolatedSandboxedIframeBrowserTestBase& operator=( |
| const IsolatedSandboxedIframeBrowserTestBase&) = delete; |
| |
| ~IsolatedSandboxedIframeBrowserTestBase() override = default; |
| |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| mock_cert_verifier_.SetUpCommandLine(command_line); |
| ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); |
| https_server()->AddDefaultHandlers(GetChromeTestDataDir()); |
| ASSERT_TRUE(https_server()->Start()); |
| } |
| |
| void SetUpOnMainThread() override { |
| host_resolver()->AddRule("*", "127.0.0.1"); |
| embedded_test_server()->StartAcceptingConnections(); |
| } |
| |
| void SetUpInProcessBrowserTestFixture() override { |
| mock_cert_verifier_.SetUpInProcessBrowserTestFixture(); |
| } |
| |
| void TearDownInProcessBrowserTestFixture() override { |
| mock_cert_verifier_.TearDownInProcessBrowserTestFixture(); |
| } |
| |
| void TearDownOnMainThread() override { |
| ASSERT_TRUE(https_server()->ShutdownAndWaitUntilComplete()); |
| } |
| |
| net::EmbeddedTestServer* https_server() { return &https_server_; } |
| |
| void VerifyStartupMetrics() { |
| scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails(); |
| details->StartFetchAndWait(); |
| |
| // Verify we're starting at zero. |
| details->VerifyMetricResult("SiteIsolation.IsolatableSandboxedIframes", |
| 0 /* value */, 1 /* count*/); |
| details->VerifyMetricResult( |
| "SiteIsolation.IsolatableSandboxedIframes.UniqueOrigins", 0 /* value */, |
| 1 /* count*/); |
| details->VerifyMetricResult( |
| "SiteIsolation.IsolatableSandboxedIframes.UniqueSites", 0 /* value */, |
| 1 /* count*/); |
| details->VerifyMetricResult( |
| "Memory.RenderProcessHost.Count2.SandboxedIframeOverhead", |
| 0 /* value */, 1 /* count*/); |
| } |
| |
| void VerifyMetrics(int isolatable_sandboxed_iframes_value, |
| int unique_origins_value, |
| int unique_sites_value, |
| int process_overhead_value) { |
| scoped_refptr<TestMemoryDetails> details = new TestMemoryDetails(); |
| details->StartFetchAndWait(); |
| |
| details->VerifyMetricResult("SiteIsolation.IsolatableSandboxedIframes", |
| isolatable_sandboxed_iframes_value, |
| 1 /* count*/); |
| details->VerifyMetricResult( |
| "SiteIsolation.IsolatableSandboxedIframes.UniqueOrigins", |
| unique_origins_value, 1 /* count*/); |
| details->VerifyMetricResult( |
| "SiteIsolation.IsolatableSandboxedIframes.UniqueSites", |
| unique_sites_value, 1 /* count*/); |
| details->VerifyMetricResult( |
| "Memory.RenderProcessHost.Count2.SandboxedIframeOverhead", |
| process_overhead_value, 1 /* count*/); |
| } |
| |
| private: |
| content::ContentMockCertVerifier mock_cert_verifier_; |
| net::EmbeddedTestServer https_server_; |
| base::test::ScopedFeatureList feature_list_; |
| bool enable_isolate_sandboxed_iframes_; |
| }; // class IsolatedSandboxedIframeBrowserTestBase |
| |
| class IsolatedSandboxedIframeBrowserTest |
| : public IsolatedSandboxedIframeBrowserTestBase { |
| public: |
| IsolatedSandboxedIframeBrowserTest() |
| : IsolatedSandboxedIframeBrowserTestBase( |
| true /* enable_isolate_sandboxed_iframes */) {} |
| |
| IsolatedSandboxedIframeBrowserTest( |
| const IsolatedSandboxedIframeBrowserTest&) = delete; |
| IsolatedSandboxedIframeBrowserTest& operator=( |
| const IsolatedSandboxedIframeBrowserTest&) = delete; |
| |
| ~IsolatedSandboxedIframeBrowserTest() override = default; |
| }; // class IsolatedSandboxedIframeBrowserTest |
| |
| class NotIsolatedSandboxedIframeBrowserTest |
| : public IsolatedSandboxedIframeBrowserTestBase { |
| public: |
| NotIsolatedSandboxedIframeBrowserTest() |
| : IsolatedSandboxedIframeBrowserTestBase( |
| false /* enable_isolate_sandboxed_iframes */) {} |
| |
| NotIsolatedSandboxedIframeBrowserTest( |
| const NotIsolatedSandboxedIframeBrowserTest&) = delete; |
| NotIsolatedSandboxedIframeBrowserTest& operator=( |
| const NotIsolatedSandboxedIframeBrowserTest&) = delete; |
| |
| ~NotIsolatedSandboxedIframeBrowserTest() override = default; |
| }; // class NotIsolatedSandboxedIframeBrowserTest |
| |
| // Test that a single isolatable frame generates correct metrics. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, IsolatedSandbox) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| // The child needs to have the same origin as the parent. |
| GURL child_url(main_url); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| content::RenderFrameHost* frame_host = web_contents->GetPrimaryMainFrame(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create sandboxed child frame, same-origin. |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame = document.createElement('iframe'); " |
| "frame.sandbox = ''; " |
| "frame.src = '%s'; " |
| "document.body.appendChild(frame);", |
| child_url.spec().c_str()); |
| EXPECT_TRUE(ExecJs(frame_host, js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 1; |
| int unique_origins_value = 1; |
| int unique_sites_value = 1; |
| int process_overhead_value = 1; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Test to verify that two isolatable frames from one origin generate the |
| // correct metrics. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| IsolatedSandboxSiblingSubframes) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| // The child needs to have the same origin as the parent. |
| GURL child_url(main_url); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| content::RenderFrameHost* frame_host = web_contents->GetPrimaryMainFrame(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create sandboxed child frame, same-origin. |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame1 = document.createElement('iframe'); " |
| "frame1.sandbox = ''; " |
| "frame1.src = '%s'; " |
| "document.body.appendChild(frame1); " |
| "var frame2 = document.createElement('iframe'); " |
| "frame2.sandbox = ''; " |
| "frame2.src = '%s'; " |
| "document.body.appendChild(frame2);", |
| child_url.spec().c_str(), child_url.spec().c_str()); |
| EXPECT_TRUE(ExecJs(frame_host, js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 2; |
| int unique_origins_value = 1; |
| int unique_sites_value = 1; |
| int process_overhead_value = 1; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // A test to exercise the case where the number of origins, sites, and |
| // isolatable iframes are all different. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| IsolatedSandbox3Frames2Origins1Site) { |
| GURL main_url(embedded_test_server()->GetURL("foo.com", "/title1.html")); |
| GURL child_url_a(embedded_test_server()->GetURL("a.foo.com", "/title1.html")); |
| GURL child_url_b(embedded_test_server()->GetURL("b.foo.com", "/title1.html")); |
| |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| content::RenderFrameHost* frame_host = web_contents->GetPrimaryMainFrame(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create three sandboxed child frames, same-site but two unique origins. |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame1 = document.createElement('iframe'); " |
| "frame1.sandbox = ''; " |
| "frame1.src = '%s'; " |
| "document.body.appendChild(frame1); " |
| "var frame2 = document.createElement('iframe'); " |
| "frame2.sandbox = ''; " |
| "frame2.src = '%s'; " |
| "document.body.appendChild(frame2);" |
| "var frame3 = document.createElement('iframe'); " |
| "frame3.sandbox = ''; " |
| "frame3.src = '%s'; " |
| "document.body.appendChild(frame3);", |
| child_url_a.spec().c_str(), child_url_b.spec().c_str(), |
| child_url_b.spec().c_str()); |
| EXPECT_TRUE(ExecJs(frame_host, js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 3; |
| int unique_origins_value = 2; |
| int unique_sandboxed_siteinfos_value = 1; |
| int process_overhead_value = 1; |
| if (blink::features::kIsolateSandboxedIframesGroupingParam.Get() == |
| blink::features::IsolateSandboxedIframesGrouping::kPerOrigin) { |
| unique_sandboxed_siteinfos_value = 2; |
| process_overhead_value = 2; |
| } |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sandboxed_siteinfos_value, process_overhead_value); |
| } |
| |
| // A test to verify that the metrics for process overhead pick up multiple |
| // processes for sandboxed iframes associated with different sites. |
| IN_PROC_BROWSER_TEST_F( |
| IsolatedSandboxedIframeBrowserTest, |
| IsolatedSandboxOverheadMetricsForDifferentSiteSandboxFrames) { |
| GURL main_url_a(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| GURL child_url_a(main_url_a); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url_a)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| content::RenderFrameHost* frame_host = web_contents->GetPrimaryMainFrame(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create sandboxed child frame, same-origin. |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame = document.createElement('iframe'); " |
| "frame.sandbox = ''; " |
| "frame.src = '%s'; " |
| "document.body.appendChild(frame);", |
| child_url_a.spec().c_str()); |
| EXPECT_TRUE(ExecJs(frame_host, js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Open a second tab on a different site, with an isolatable sandboxed iframe. |
| GURL main_url_b(embedded_test_server()->GetURL("b.com", "/title1.html")); |
| GURL child_url_b(main_url_b); |
| ASSERT_TRUE(AddTabAtIndex(1, main_url_b, ui::PAGE_TRANSITION_TYPED)); |
| content::WebContents* web_contents_b = |
| browser()->tab_strip_model()->GetWebContentsAt(1); |
| |
| // Create sandboxed child frame, same-origin. |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame = document.createElement('iframe'); " |
| "frame.sandbox = ''; " |
| "frame.src = '%s'; " |
| "document.body.appendChild(frame);", |
| child_url_b.spec().c_str()); |
| EXPECT_TRUE(ExecJs(web_contents_b->GetPrimaryMainFrame(), js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents_b)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 2; |
| int unique_origins_value = 2; |
| int unique_sites_value = 2; |
| int process_overhead_value = 2; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Test to verify that a srcdoc sandboxed iframe generates the correct metrics. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| IsolatedSandboxSrcdocSubframe) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create sandboxed child frame, with srcdoc content. |
| std::string child_inner_text("srcdoc sandboxed subframe"); |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame = document.createElement('iframe'); " |
| "frame.sandbox = 'allow-scripts'; " |
| "frame.srcdoc = '%s'; " |
| "document.body.appendChild(frame);", |
| child_inner_text.c_str()); |
| EXPECT_TRUE(ExecJs(web_contents->GetPrimaryMainFrame(), js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 1; |
| int unique_origins_value = 1; |
| int unique_sites_value = 1; |
| int process_overhead_value = 1; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Test to verify that a sandboxed iframes with about:blank doesn't get counted |
| // in the metrics. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| NotIsolatedSandboxAboutBlankSubframe) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create sandboxed child frame, with about:blank content. |
| { |
| std::string js_str( |
| "var frame = document.createElement('iframe'); " |
| "frame.id = 'child_frame'; " |
| "frame.sandbox = ''; " |
| "frame.src = 'about:blank'; " |
| "document.body.appendChild(frame);"); |
| EXPECT_TRUE(ExecJs(web_contents->GetPrimaryMainFrame(), js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 0; |
| int unique_origins_value = 0; |
| int unique_sites_value = 0; |
| int process_overhead_value = 0; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Test to verify that a sandboxed iframe with an empty url (nothing committed) |
| // doesn't get counted in the metrics. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| NotIsolatedSandboxEmptyUrlSubframe) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create sandboxed child frame, with about:blank content. |
| { |
| GURL empty_url(embedded_test_server()->GetURL("a.com", "/page204.html")); |
| std::string js_str = base::StringPrintf( |
| "var frame = document.createElement('iframe'); " |
| "frame.id = 'child_frame'; " |
| "frame.sandbox = ''; " |
| "frame.src = '%s'; " |
| "document.body.appendChild(frame);", |
| empty_url.spec().c_str()); |
| EXPECT_TRUE(ExecJs(web_contents->GetPrimaryMainFrame(), js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 0; |
| int unique_origins_value = 0; |
| int unique_sites_value = 0; |
| int process_overhead_value = 0; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Test to verify that a javascript: sandboxed iframe does not generate any |
| // metrics. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| SandboxedIframeWithJSUrl) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create sandboxed child frame with a javascript: URL. |
| std::string js_url_str("javascript:\"foo\""); |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame = document.createElement('iframe'); " |
| "frame.id = 'test_frame'; " |
| "frame.sandbox = 'allow-scripts'; " |
| "frame.src = '%s'; " |
| "document.body.appendChild(frame);", |
| js_url_str.c_str()); |
| EXPECT_TRUE(ExecJs(web_contents->GetPrimaryMainFrame(), js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 0; |
| int unique_origins_value = 0; |
| int unique_sites_value = 0; |
| int process_overhead_value = 0; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Verify that when the flag for isolating sandboxed iframe is off, we collect |
| // metrics for isolatable iframe count and number of unique origins, but no |
| // metrics for actual process overhead. |
| IN_PROC_BROWSER_TEST_F(NotIsolatedSandboxedIframeBrowserTest, IsolatedSandbox) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| // The child needs to have the same origin as the parent. |
| GURL child_url(main_url); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create sandboxed child frame, same-origin. |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame = document.createElement('iframe'); " |
| "frame.sandbox = ''; " |
| "frame.src = '%s'; " |
| "document.body.appendChild(frame);", |
| child_url.spec().c_str()); |
| EXPECT_TRUE(ExecJs(web_contents->GetPrimaryMainFrame(), js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 1; |
| int unique_origins_value = 1; |
| int unique_sites_value = 1; |
| int process_overhead_value = 0; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Test to make sure that a sandboxed mainframe is considered isolatable if it |
| // has a same-site opener. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| SandboxedMainframeWithSameSiteOpener) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| GURL child_url(main_url); |
| GURL popup_url(main_url); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| VerifyStartupMetrics(); |
| |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame = document.createElement('iframe'); " |
| "frame.id = 'test_frame'; " |
| "frame.sandbox = 'allow-popups allow-scripts'; " |
| "frame.src = '%s'; " |
| "document.body.appendChild(frame);", |
| child_url.spec().c_str()); |
| EXPECT_TRUE(ExecJs(web_contents->GetPrimaryMainFrame(), js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Open popup from sandboxed iframe. This creates a sandboxed mainframe that |
| // is isolatable. We make sure the popup url is same-site to the opener, |
| // otherwise it would just create an OOPIF. |
| content::RenderFrameHost* child_rfh = |
| ChildFrameAt(web_contents->GetPrimaryMainFrame(), 0); |
| { |
| std::string js_str = |
| base::StringPrintf("window.open('%s');", popup_url.spec().c_str()); |
| |
| content::TestNavigationObserver popup_observer(nullptr); |
| popup_observer.StartWatchingNewWebContents(); |
| EXPECT_TRUE(ExecJs(child_rfh, js_str)); |
| popup_observer.Wait(); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 2; |
| int unique_origins_value = 1; |
| int unique_sites_value = 1; |
| int process_overhead_value = 1; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Test to make sure that a CSP sandboxed mainframe is considered isolatable |
| // when opened by a non-sandboxed parent. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| CspSandboxedMainframeWithSameSiteOpener) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| GURL popup_url(embedded_test_server()->GetURL("a.com", "/csp-sandbox.html")); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| VerifyStartupMetrics(); |
| |
| // Open popup from (non-sandboxed) main frame. The popup will arrive with a |
| // CSP sandbox header, and so will be marked isolatable since it is same-site |
| // to its opener. |
| { |
| std::string js_str = |
| base::StringPrintf("window.open('%s');", popup_url.spec().c_str()); |
| |
| content::TestNavigationObserver popup_observer(nullptr); |
| popup_observer.StartWatchingNewWebContents(); |
| EXPECT_TRUE(ExecJs(web_contents->GetPrimaryMainFrame(), js_str)); |
| popup_observer.Wait(); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 1; |
| int unique_origins_value = 1; |
| int unique_sites_value = 1; |
| int process_overhead_value = 1; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Test to make sure that a CSP sandboxed mainframe is not considered isolatable |
| // when when visited directly. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| CspSandboxedMainframeVisitedDirectly) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/csp-sandbox.html")); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 0; |
| int unique_origins_value = 0; |
| int unique_sites_value = 0; |
| int process_overhead_value = 0; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |
| |
| // Test to make sure that an iframe with a data:url is appropriately counted by |
| // the sandbox isolation metrics. |
| IN_PROC_BROWSER_TEST_F(IsolatedSandboxedIframeBrowserTest, |
| SandboxedIframeWithDataURL) { |
| GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); |
| content::WebContents* web_contents = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| VerifyStartupMetrics(); |
| |
| // Create sandboxed child frame with a data URL. |
| std::string data_url_str("data:text/html,dataurl"); |
| { |
| std::string js_str = base::StringPrintf( |
| "var frame = document.createElement('iframe'); " |
| "frame.id = 'test_frame'; " |
| "frame.sandbox = ''; " |
| "frame.src = '%s'; " |
| "document.body.appendChild(frame);", |
| data_url_str.c_str()); |
| EXPECT_TRUE(ExecJs(web_contents->GetPrimaryMainFrame(), js_str)); |
| ASSERT_TRUE(WaitForLoadStop(web_contents)); |
| } |
| |
| // Verify histograms are updated. |
| int isolatable_sandboxed_iframes_value = 1; |
| int unique_origins_value = 1; |
| int unique_sites_value = 1; |
| int process_overhead_value = 1; |
| VerifyMetrics(isolatable_sandboxed_iframes_value, unique_origins_value, |
| unique_sites_value, process_overhead_value); |
| } |