tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 });