blob: 5f5905045b4be953c6c637b78d405e5b6e13b7ff [file] [log] [blame]
Avi Drissman4a8573c2022-09-09 19:35:541// Copyright 2021 The Chromium Authors
Bill Budgef09f7492021-04-15 02:00:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/command_line.h"
6#include "base/test/scoped_feature_list.h"
7#include "chrome/browser/policy/policy_test_utils.h"
8#include "chrome/browser/profiles/profile.h"
9#include "chrome/browser/ui/browser.h"
10#include "chrome/common/pref_names.h"
11#include "chrome/test/base/in_process_browser_test.h"
12#include "components/network_session_configurator/common/network_switches.h"
13#include "components/policy/core/common/policy_map.h"
14#include "components/policy/policy_constants.h"
15#include "components/prefs/pref_service.h"
16#include "content/public/browser/web_contents.h"
17#include "content/public/common/content_features.h"
18#include "content/public/test/browser_test.h"
19#include "content/public/test/browser_test_utils.h"
20#include "content/public/test/content_browser_test_utils.h"
21#include "net/test/embedded_test_server/embedded_test_server.h"
22
23namespace policy {
24
25// This is a Chrome test since we need to access the Profile and Preferences.
26class ChromeSharedArrayBufferBrowserTest : public PolicyTest {
27 public:
28 using WebFeature = blink::mojom::WebFeature;
29
30 ChromeSharedArrayBufferBrowserTest() {
31 feature_list_.InitWithFeatures(
32 // Enabled:
33 {},
34 // Disabled:
35 {
36 features::kSharedArrayBuffer,
Bill Budgef09f7492021-04-15 02:00:5537 });
38 }
39
40 content::WebContents* web_contents() const {
41 return browser()->tab_strip_model()->GetActiveWebContents();
42 }
43
44 void SetPolicyAndRestartBrowser() {
45 // The preference is false by default.
46 EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean(
47 prefs::kSharedArrayBufferUnrestrictedAccessAllowed));
48
49 PolicyMap policies;
50 policies.Set(key::kSharedArrayBufferUnrestrictedAccessAllowed,
51 POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD,
52 base::Value(true), nullptr);
53 UpdateProviderPolicy(policies);
54
55 // Now the preference should be true.
56 EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
57 prefs::kSharedArrayBufferUnrestrictedAccessAllowed));
58
59 // The old browser has already created the ContentBrowserClient which reads
60 // the preference, so it can't create renderers with SABs enabled by policy.
61 // Create a new browser that will pick up the preference and enable SABs for
62 // new renderer processes.
63 Browser* new_browser = CreateBrowser(browser()->profile());
64 CloseBrowserSynchronously(browser());
65 SelectFirstBrowser();
66 ASSERT_EQ(browser(), new_browser);
67
Patrick Monette37faeab52024-11-20 19:58:4268 // Clear existing spares and navigate the new browser to 'localhost', so the
69 // tests will get new renderer processes when they navigate to xxx.com
70 // origins.
71 content::SpareRenderProcessHostManager::Get().CleanupSparesForTesting();
Bill Budgef09f7492021-04-15 02:00:5572 GURL local_host = embedded_test_server()->GetURL("/empty.html");
73 EXPECT_TRUE(NavigateToURL(web_contents(), local_host));
74 }
75
76 private:
77 void SetUpOnMainThread() final {
78 PolicyTest::SetUpOnMainThread();
79
80 ASSERT_TRUE(embedded_test_server()->Start());
81
82 ASSERT_FALSE(base::FeatureList::IsEnabled(features::kSharedArrayBuffer));
Bill Budgef09f7492021-04-15 02:00:5583 }
84
85 void SetUpCommandLine(base::CommandLine* command_line) final {
86 PolicyTest::SetUpCommandLine(command_line);
87 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
88 }
89
90 base::test::ScopedFeatureList feature_list_;
91};
92
93IN_PROC_BROWSER_TEST_F(ChromeSharedArrayBufferBrowserTest,
94 PolicyEnablesSabConstructor) {
95 SetPolicyAndRestartBrowser();
96
97 GURL url = embedded_test_server()->GetURL("a.com", "/empty.html");
98 EXPECT_TRUE(NavigateToURL(web_contents(), url));
99 EXPECT_EQ(true, content::EvalJs(web_contents(),
100 "'SharedArrayBuffer' in globalThis"));
101}
102
103IN_PROC_BROWSER_TEST_F(ChromeSharedArrayBufferBrowserTest,
104 NoPolicyNoSabConstructor) {
105 GURL url = embedded_test_server()->GetURL("a.com", "/empty.html");
106 EXPECT_TRUE(NavigateToURL(web_contents(), url));
107 EXPECT_EQ(false, content::EvalJs(web_contents(),
108 "'SharedArrayBuffer' in globalThis"));
109}
110
111IN_PROC_BROWSER_TEST_F(ChromeSharedArrayBufferBrowserTest,
arthursonzognieab5e0c2021-04-15 14:49:25112 PolicyEnablesSharing) {
Bill Budgef09f7492021-04-15 02:00:55113 SetPolicyAndRestartBrowser();
114
115 GURL main_url = embedded_test_server()->GetURL("a.com", "/empty.html");
arthursonzognieab5e0c2021-04-15 14:49:25116 GURL sub_url = embedded_test_server()->GetURL("a.com", "/empty.html");
Bill Budgef09f7492021-04-15 02:00:55117
118 EXPECT_TRUE(content::NavigateToURL(web_contents(), main_url));
Dave Tapuska6aea6e22022-06-06 21:21:51119 content::RenderFrameHost* main_document =
120 web_contents()->GetPrimaryMainFrame();
arthursonzognieab5e0c2021-04-15 14:49:25121
122 EXPECT_TRUE(content::ExecJs(main_document, content::JsReplace(R"(
123 g_sab_size = new Promise(resolve => {
124 addEventListener("message", event => resolve(event.data.byteLength));
125 });
126
Bill Budgef09f7492021-04-15 02:00:55127 g_iframe = document.createElement('iframe');
128 g_iframe.src = $1;
129 document.body.appendChild(g_iframe);
arthursonzognieab5e0c2021-04-15 14:49:25130 )",
131 sub_url)));
Bill Budgef09f7492021-04-15 02:00:55132 WaitForLoadStop(web_contents());
Dave Tapuska217f04d2021-09-22 13:35:41133 content::RenderFrameHost* sub_document = ChildFrameAt(main_document, 0);
Bill Budgef09f7492021-04-15 02:00:55134
135 EXPECT_EQ(false, EvalJs(main_document, "self.crossOriginIsolated"));
136 EXPECT_EQ(false, EvalJs(sub_document, "self.crossOriginIsolated"));
137
Bill Budgef09f7492021-04-15 02:00:55138 EXPECT_TRUE(ExecJs(sub_document, R"(
139 let sab = new SharedArrayBuffer(1234);
140 parent.postMessage(sab, "*");
141 )"));
142
143 EXPECT_EQ(1234, EvalJs(main_document, "g_sab_size"));
144}
145
arthursonzognieab5e0c2021-04-15 14:49:25146IN_PROC_BROWSER_TEST_F(ChromeSharedArrayBufferBrowserTest, NoPolicyNoSharing) {
Bill Budgef09f7492021-04-15 02:00:55147 GURL main_url = embedded_test_server()->GetURL("a.com", "/empty.html");
arthursonzognieab5e0c2021-04-15 14:49:25148 GURL sub_url = embedded_test_server()->GetURL("a.com", "/empty.html");
Bill Budgef09f7492021-04-15 02:00:55149
150 EXPECT_TRUE(content::NavigateToURL(web_contents(), main_url));
Dave Tapuska6aea6e22022-06-06 21:21:51151 content::RenderFrameHost* main_document =
152 web_contents()->GetPrimaryMainFrame();
arthursonzognieab5e0c2021-04-15 14:49:25153
154 EXPECT_TRUE(content::ExecJs(web_contents(), content::JsReplace(R"(
155 g_sab_size = new Promise(resolve => {
156 addEventListener("message", event => resolve(event.data.byteLength));
157 });
158
Bill Budgef09f7492021-04-15 02:00:55159 g_iframe = document.createElement('iframe');
160 g_iframe.src = $1;
161 document.body.appendChild(g_iframe);
arthursonzognieab5e0c2021-04-15 14:49:25162 )",
163 sub_url)));
Bill Budgef09f7492021-04-15 02:00:55164 WaitForLoadStop(web_contents());
Dave Tapuska217f04d2021-09-22 13:35:41165 content::RenderFrameHost* sub_document = ChildFrameAt(main_document, 0);
Bill Budgef09f7492021-04-15 02:00:55166
167 EXPECT_EQ(false, EvalJs(main_document, "self.crossOriginIsolated"));
168 EXPECT_EQ(false, EvalJs(sub_document, "self.crossOriginIsolated"));
169
Bill Budgef09f7492021-04-15 02:00:55170 auto postSharedArrayBuffer = EvalJs(main_document, R"(
171 // Create a WebAssembly Memory to bypass the SAB constructor restriction.
172 const sab =
173 new WebAssembly.Memory({ shared:true, initial:1, maximum:1 }).buffer;
174 g_iframe.contentWindow.postMessage(sab,"*");
175 )");
176 EXPECT_THAT(
177 postSharedArrayBuffer.error,
178 testing::HasSubstr("Failed to execute 'postMessage' on 'Window': "));
179}
180
181} // namespace policy