browser_etp_advanced.js (11183B)
1 /* Any copyright is dedicated to the Public Domain. 2 * https://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Tests for the ETP advanced settings view. 7 8 const CAT_PREF = "browser.contentblocking.category"; 9 const BASELINE_PREF = "privacy.trackingprotection.allow_list.baseline.enabled"; 10 const CONVENIENCE_PREF = 11 "privacy.trackingprotection.allow_list.convenience.enabled"; 12 const PERMISSIONS_DIALOG_URL = 13 "chrome://browser/content/preferences/dialogs/permissions.xhtml"; 14 15 add_setup(async function () { 16 await SpecialPowers.pushPrefEnv({ 17 set: [["browser.settings-redesign.enabled", true]], 18 }); 19 }); 20 21 // Verifies category radios reflect pref changes and the customize entry point navigates correctly. 22 add_task(async function test_etp_category_radios_and_customize_navigation() { 23 await SpecialPowers.pushPrefEnv({ 24 set: [ 25 [CAT_PREF, "standard"], 26 [BASELINE_PREF, true], 27 [CONVENIENCE_PREF, true], 28 ], 29 }); 30 31 let { win, doc, tab } = await openEtpPage(); 32 33 let standardRadio = getControl(doc, "etpLevelStandard"); 34 let strictRadio = getControl(doc, "etpLevelStrict"); 35 let customRadio = getControl(doc, "etpLevelCustom"); 36 let customizeButton = getControl(doc, "etpCustomizeButton"); 37 let levelWarning = getControl(doc, "etpLevelWarning"); 38 39 ok(standardRadio.checked, "Standard ETP level is initially selected"); 40 ok( 41 customizeButton.parentDisabled, 42 "Customize button disabled until custom level selected" 43 ); 44 ok( 45 BrowserTestUtils.isHidden(levelWarning), 46 "ETP level warning hidden while standard selected" 47 ); 48 49 info("Switch to strict and wait for the pref to change"); 50 let prefChange = waitForAndAssertPrefState( 51 CAT_PREF, 52 "strict", 53 "ETP category pref set to strict" 54 ); 55 synthesizeClick(strictRadio); 56 await prefChange; 57 ok(strictRadio.checked, "Strict radio button selected"); 58 59 let strictBaselineWrapper = getControlWrapper( 60 doc, 61 "etpAllowListBaselineEnabled" 62 ); 63 ok( 64 BrowserTestUtils.isVisible(strictBaselineWrapper), 65 "Baseline checkbox for strict is visible when strict selected" 66 ); 67 68 let levelWarningVisible = () => BrowserTestUtils.isVisible(levelWarning); 69 if (!levelWarningVisible()) { 70 await BrowserTestUtils.waitForMutationCondition( 71 levelWarning, 72 { attributes: true, attributeFilter: ["hidden"] }, 73 levelWarningVisible 74 ); 75 } 76 ok(levelWarningVisible(), "ETP level warning visible for strict level"); 77 78 info("Switch to custom and ensure the pref updates"); 79 prefChange = waitForAndAssertPrefState( 80 CAT_PREF, 81 "custom", 82 "ETP category pref set to custom" 83 ); 84 synthesizeClick(customRadio); 85 await prefChange; 86 ok(customRadio.checked, "Custom radio button selected"); 87 88 let customizeEnabled = () => !customizeButton.parentDisabled; 89 if (!customizeEnabled()) { 90 await BrowserTestUtils.waitForMutationCondition( 91 customizeButton, 92 { attributes: true, attributeFilter: ["parentdisabled"] }, 93 customizeEnabled 94 ); 95 } 96 ok(customizeEnabled(), "Customize button enabled when custom level selected"); 97 ok(levelWarningVisible(), "ETP level warning remains visible for custom"); 98 99 info("Click customize and wait for the custom pane to load"); 100 let paneShown = waitForPaneChange("etpCustomize"); 101 synthesizeClick(customizeButton); 102 await paneShown; 103 is( 104 win.history.state, 105 "paneEtpCustomize", 106 "Customize button navigated to the ETP custom pane" 107 ); 108 109 BrowserTestUtils.removeTab(tab); 110 }); 111 112 // Ensures the reload tabs message bar appears when ETP settings change. 113 add_task(async function test_reload_tabs_message_bar() { 114 await SpecialPowers.pushPrefEnv({ 115 set: [ 116 [CAT_PREF, "strict"], 117 [BASELINE_PREF, true], 118 [CONVENIENCE_PREF, true], 119 ], 120 }); 121 122 info("Open an additional tab so the reload notification will show"); 123 let extraTab = await BrowserTestUtils.openNewForegroundTab( 124 gBrowser, 125 "https://example.com" 126 ); 127 128 let { doc, tab } = await openEtpPage(); 129 130 let reloadTabsHint = getControl(doc, "reloadTabsHint"); 131 ok(reloadTabsHint, "reloadTabsHint element exists"); 132 ok( 133 BrowserTestUtils.isHidden(reloadTabsHint), 134 "Reload tabs message bar is initially hidden" 135 ); 136 137 info("Toggle convenience checkbox to trigger reload notification"); 138 let convenienceCheckbox = getControl(doc, "etpAllowListConvenienceEnabled"); 139 ok(convenienceCheckbox.checked, "Convenience checkbox starts checked"); 140 141 let prefChange = waitForAndAssertPrefState( 142 CONVENIENCE_PREF, 143 false, 144 "Convenience pref disabled" 145 ); 146 synthesizeClick(convenienceCheckbox); 147 await prefChange; 148 149 info("Wait for message bar to become visible"); 150 await BrowserTestUtils.waitForCondition( 151 () => BrowserTestUtils.isVisible(reloadTabsHint), 152 "Waiting for reload tabs message bar to become visible" 153 ); 154 155 ok( 156 BrowserTestUtils.isVisible(reloadTabsHint), 157 "Reload tabs message bar is visible after changing ETP setting" 158 ); 159 160 let reloadButton = reloadTabsHint.querySelector("moz-button"); 161 ok(reloadButton, "Reload button exists in the message bar"); 162 163 info("Click reload button to hide the message bar"); 164 synthesizeClick(reloadButton); 165 166 await BrowserTestUtils.waitForCondition( 167 () => BrowserTestUtils.isHidden(reloadTabsHint), 168 "Waiting for reload tabs message bar to become hidden" 169 ); 170 171 ok( 172 BrowserTestUtils.isHidden(reloadTabsHint), 173 "Reload tabs message bar is hidden after reload button clicked" 174 ); 175 176 BrowserTestUtils.removeTab(extraTab); 177 BrowserTestUtils.removeTab(tab); 178 }); 179 180 // Ensures strict baseline checkbox flows prompt for confirmation and gate the convenience checkbox. 181 add_task(async function test_strict_baseline_checkbox_requires_confirmation() { 182 await SpecialPowers.pushPrefEnv({ 183 set: [ 184 [CAT_PREF, "strict"], 185 [BASELINE_PREF, true], 186 [CONVENIENCE_PREF, true], 187 ], 188 }); 189 190 let { doc, tab } = await openEtpPage(); 191 192 let baselineCheckbox = getControl(doc, "etpAllowListBaselineEnabled"); 193 let convenienceCheckbox = getControl(doc, "etpAllowListConvenienceEnabled"); 194 195 ok(baselineCheckbox.checked, "Baseline checkbox starts checked"); 196 197 info("Cancel the confirmation dialog and ensure checkbox stays checked"); 198 await clickEtpBaselineCheckboxWithConfirm( 199 doc, 200 "etpAllowListBaselineEnabled", 201 BASELINE_PREF, 202 true, 203 0 204 ); 205 ok( 206 baselineCheckbox.checked, 207 "Baseline checkbox remains checked after cancelling dialog" 208 ); 209 210 info("Confirm the dialog to disable the baseline allow list"); 211 await clickEtpBaselineCheckboxWithConfirm( 212 doc, 213 "etpAllowListBaselineEnabled", 214 BASELINE_PREF, 215 false, 216 1 217 ); 218 ok( 219 !Services.prefs.getBoolPref(BASELINE_PREF), 220 "Baseline pref disabled after confirming dialog" 221 ); 222 ok( 223 convenienceCheckbox.parentDisabled, 224 "Convenience checkbox disabled when baseline unchecked" 225 ); 226 227 info("Re-enable baseline and ensure convenience becomes active again"); 228 let prefChange = waitForAndAssertPrefState( 229 BASELINE_PREF, 230 true, 231 "Baseline pref restored" 232 ); 233 synthesizeClick(baselineCheckbox); 234 await prefChange; 235 236 let convenienceEnabled = () => !convenienceCheckbox.parentDisabled; 237 if (!convenienceEnabled()) { 238 await BrowserTestUtils.waitForMutationCondition( 239 convenienceCheckbox, 240 { attributes: true, attributeFilter: ["parentdisabled"] }, 241 convenienceEnabled 242 ); 243 } 244 ok( 245 convenienceEnabled(), 246 "Convenience checkbox enabled again after baseline re-enabled" 247 ); 248 249 BrowserTestUtils.removeTab(tab); 250 }); 251 252 // Ensures the RFP warning visibility follows the resistFingerprinting pref. 253 add_task(async function test_rfp_warning_visibility() { 254 await SpecialPowers.pushPrefEnv({ 255 set: [ 256 [CAT_PREF, "strict"], 257 ["privacy.resistFingerprinting.pbmode", false], 258 ["privacy.resistFingerprinting", false], 259 ], 260 }); 261 262 let { doc, tab } = await openEtpPage(); 263 264 let rfpWarning = getControl(doc, "rfpWarning"); 265 ok( 266 BrowserTestUtils.isHidden(rfpWarning), 267 "RFP warning hidden while pref disabled" 268 ); 269 270 let mutationTarget = doc.documentElement; 271 let warningVisibleCondition = () => { 272 let el = doc.getElementById("rfpWarning"); 273 return el && BrowserTestUtils.isVisible(el); 274 }; 275 276 info("Enable normal RFP and wait for the warning to show"); 277 let waitForVisible = BrowserTestUtils.waitForMutationCondition( 278 mutationTarget, 279 { attributes: true, childList: true, subtree: true }, 280 warningVisibleCondition 281 ); 282 Services.prefs.setBoolPref("privacy.resistFingerprinting", true); 283 await waitForVisible; 284 rfpWarning = getControl(doc, "rfpWarning"); 285 ok( 286 BrowserTestUtils.isVisible(rfpWarning), 287 "RFP warning visible when pref enabled" 288 ); 289 290 let warningHiddenCondition = () => { 291 let el = doc.getElementById("rfpWarning"); 292 return el && BrowserTestUtils.isHidden(el); 293 }; 294 295 info("Disable normal RFP and wait for the warning to hide"); 296 let waitForHidden = BrowserTestUtils.waitForMutationCondition( 297 mutationTarget, 298 { attributes: true, childList: true, subtree: true }, 299 warningHiddenCondition 300 ); 301 Services.prefs.setBoolPref("privacy.resistFingerprinting", false); 302 await waitForHidden; 303 rfpWarning = getControl(doc, "rfpWarning"); 304 ok( 305 BrowserTestUtils.isHidden(rfpWarning), 306 "RFP warning hidden when pref disabled again" 307 ); 308 309 info("Enable PBM RFP and wait for the warning to show"); 310 waitForVisible = BrowserTestUtils.waitForMutationCondition( 311 mutationTarget, 312 { attributes: true, childList: true, subtree: true }, 313 warningVisibleCondition 314 ); 315 Services.prefs.setBoolPref("privacy.resistFingerprinting.pbmode", true); 316 await waitForVisible; 317 rfpWarning = getControl(doc, "rfpWarning"); 318 ok( 319 BrowserTestUtils.isVisible(rfpWarning), 320 "RFP warning visible when PBM pref enabled" 321 ); 322 323 info("Disable PBM RFP and wait for the warning to hide"); 324 waitForHidden = BrowserTestUtils.waitForMutationCondition( 325 mutationTarget, 326 { attributes: true, childList: true, subtree: true }, 327 warningHiddenCondition 328 ); 329 Services.prefs.setBoolPref("privacy.resistFingerprinting.pbmode", false); 330 await waitForHidden; 331 rfpWarning = getControl(doc, "rfpWarning"); 332 ok( 333 BrowserTestUtils.isHidden(rfpWarning), 334 "RFP warning hidden when PBM pref disabled again" 335 ); 336 337 BrowserTestUtils.removeTab(tab); 338 }); 339 340 // Ensures the manage exceptions button opens the permissions dialog. 341 add_task(async function test_manage_exceptions_button_opens_dialog() { 342 await SpecialPowers.pushPrefEnv({ 343 set: [[CAT_PREF, "standard"]], 344 }); 345 346 let { doc, tab } = await openEtpPage(); 347 348 let manageButton = getControl(doc, "etpManageExceptionsButton"); 349 let dialogPromise = promiseLoadSubDialog(PERMISSIONS_DIALOG_URL); 350 synthesizeClick(manageButton); 351 let dialogWin = await dialogPromise; 352 await dialogWin.document.mozSubdialogReady; 353 ok( 354 dialogWin.document.getElementById("permissionsBox"), 355 "Permissions dialog rendered for manage exceptions" 356 ); 357 let dialogEl = dialogWin.document.querySelector("dialog"); 358 dialogEl.getButton("cancel").click(); 359 await BrowserTestUtils.waitForEvent(dialogWin, "unload"); 360 361 BrowserTestUtils.removeTab(tab); 362 });