1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
|
from contextlib import contextmanager
from marionette_harness import MarionetteTestCase
class ExperimentStatus:
UNENROLLED = 0
ENROLLED_CONTROL = 1
ENROLLED_TREATMENT = 2
DISQUALIFIED = 3
class ContentWin32kLockdownState:
LockdownEnabled = 1
MissingWebRender = 2
OperatingSystemNotSupported = 3
PrefNotSet = 4
MissingRemoteWebGL = 5
MissingNonNativeTheming = 6
DisabledByEnvVar = 7
DisabledBySafeMode = 8
DisabledByE10S = 9
DisabledByUserPref = 10
EnabledByUserPref = 11
DisabledByControlGroup = 12
EnabledByTreatmentGroup = 13
DisabledByDefault = 14
EnabledByDefault = 15
class Prefs:
ENROLLMENT_STATUS = "security.sandbox.content.win32k-experiment.enrollmentStatus"
STARTUP_ENROLLMENT_STATUS = (
"security.sandbox.content.win32k-experiment.startupEnrollmentStatus"
)
WIN32K = "security.sandbox.content.win32k-disable"
WEBGL = "webgl.out-of-process"
ENV_DISABLE_WIN32K = "MOZ_ENABLE_WIN32K"
ENV_DISABLE_E10S = "MOZ_FORCE_DISABLE_E10S"
class TestWin32kAutostart(MarionetteTestCase):
SANDBOX_NAME = "win32k-autostart"
def execute_script(self, code, *args, **kwargs):
with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
return self.marionette.execute_script(
code, new_sandbox=False, sandbox=self.SANDBOX_NAME, *args, **kwargs
)
def get_win32k_status(self):
return self.execute_script(
r"""
let win = Services.wm.getMostRecentWindow("navigator:browser");
let ses = "security.sandbox.content.win32k-experiment.startupEnrollmentStatus";
return {
win32kSessionStatus: Services.appinfo.win32kSessionStatus,
win32kStatus: Services.appinfo.win32kLiveStatusTestingOnly,
win32kExperimentStatus: Services.appinfo.win32kExperimentStatus,
win32kPref: Services.prefs.getBoolPref("security.sandbox.content.win32k-disable"),
win32kStartupEnrollmentStatusPref: Services.prefs.getIntPref(ses),
};
"""
)
def check_win32k_status(
self, status, sessionStatus, experimentStatus, pref, enrollmentStatusPref
):
# We CANNOT check win32kEnrollmentStatusPref after a restart because we only set this
# pref on the default branch, and it goes away after a restart, so we only check
# the startupEnrollmentStatusPref
expected = {
"win32kSessionStatus": sessionStatus,
"win32kStatus": status,
"win32kExperimentStatus": experimentStatus,
"win32kPref": pref,
"win32kStartupEnrollmentStatusPref": enrollmentStatusPref,
}
status = self.get_win32k_status()
for prop, value in expected.items():
self.assertEqual(
status[prop],
value,
"%s should have the value `%r`, but has `%r`"
% (prop, value, status[prop]),
)
def set_env(self, env, value):
self.execute_script(
"env.set(arguments[0], arguments[1]);", script_args=(env, value)
)
def get_env(self, env):
return self.execute_script("return env.get(arguments[0]);", script_args=(env,))
def set_enrollment_status(self, status):
self.marionette.set_pref(Prefs.ENROLLMENT_STATUS, status, default_branch=True)
updated_status = self.marionette.get_pref(Prefs.ENROLLMENT_STATUS)
self.assertTrue(
status == updated_status or updated_status == ExperimentStatus.DISQUALIFIED
)
startup_status = self.marionette.get_pref(Prefs.STARTUP_ENROLLMENT_STATUS)
self.assertEqual(
startup_status,
updated_status,
"Startup enrollment status (%r) should match "
"session status (%r)" % (startup_status, updated_status),
)
def restart(self, prefs=None, env=None):
if prefs:
self.marionette.set_prefs(prefs)
if env:
for name, value in env.items():
self.set_env(name, value)
self.marionette.restart(in_app=True, clean=False)
self.setUpSession()
# Sanity check our environment.
if prefs:
for key, val in prefs.items():
if val is not None:
self.assertEqual(self.marionette.get_pref(key), val)
if env:
for key, val in env.items():
self.assertEqual(self.get_env(key), val or "")
def setUpSession(self):
self.marionette.set_context(self.marionette.CONTEXT_CHROME)
self.execute_script(
r"""
// We're running in a function, in a sandbox, that inherits from an
// X-ray wrapped window. Anything we want to be globally available
// needs to be defined on that window.
window.env = Services.env;
"""
)
@contextmanager
def full_restart(self):
profile = self.marionette.instance.profile
try:
self.marionette.quit()
yield profile
finally:
self.marionette.start_session()
self.setUpSession()
def setUp(self):
super(TestWin32kAutostart, self).setUp()
# If we have configured marionette to require a particular value for
# `win32k.autostart`, remove it as a forced pref until `tearDown`, and
# perform a clean restart, so we run this test without the pref
# pre-configured.
self.win32kRequired = None
if Prefs.WIN32K in self.marionette.instance.required_prefs:
self.win32kRequired = self.marionette.instance.required_prefs[Prefs.WIN32K]
del self.marionette.instance.required_prefs[Prefs.WIN32K]
self.marionette.restart(in_app=False, clean=True)
self.setUpSession()
# Marionette doesn't let you set preferences on the default branch before startup
# so we can't test the default=False and default=True scenarios in one test
# What we can do is generate all the tests, and then only run the runs for which
# the default is. (And run the other ones locally to make sure they work before
# we land it.)
prefJS = 'return Services.prefs.getBoolPref("security.sandbox.content.win32k-disable");'
self.default_is = self.execute_script(prefJS)
if self.default_is is False:
# Win32k status must start out with `disabledByDefault`
self.check_win32k_status(
status=ContentWin32kLockdownState.DisabledByDefault,
sessionStatus=ContentWin32kLockdownState.DisabledByDefault,
experimentStatus=ExperimentStatus.UNENROLLED,
pref=False,
enrollmentStatusPref=ExperimentStatus.UNENROLLED,
)
else:
# Win32k status must start out with `enabledByDefault`
self.check_win32k_status(
status=ContentWin32kLockdownState.EnabledByDefault,
sessionStatus=ContentWin32kLockdownState.EnabledByDefault,
experimentStatus=ExperimentStatus.UNENROLLED,
pref=True,
enrollmentStatusPref=ExperimentStatus.UNENROLLED,
)
def tearDown(self):
if self.win32kRequired is not None:
self.marionette.instance.required_prefs[Prefs.WIN32K] = self.win32kRequired
self.marionette.restart(in_app=False, clean=True)
super(TestWin32kAutostart, self).tearDown()
|