tor-browser

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

browser_identityPopup_HttpsOnlyMode.js (7951B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 const HTTPS_ONLY_PERMISSION = "https-only-load-insecure";
      6 const WEBSITE = scheme => `${scheme}://example.com`;
      7 
      8 add_setup(async function () {
      9  await SpecialPowers.pushPrefEnv({
     10    set: [["test.wait300msAfterTabSwitch", true]],
     11  });
     12 });
     13 
     14 add_task(async function () {
     15  info("Running regular tests");
     16  await runTests();
     17  info("Running tests with view-source: uri");
     18  await runTests({ outerScheme: "view-source" });
     19 });
     20 
     21 async function runTests(options = {}) {
     22  const { outerScheme = "" } = options;
     23  const outerSchemePrefix = outerScheme ? outerScheme + ":" : "";
     24 
     25  await SpecialPowers.pushPrefEnv({
     26    set: [["dom.security.https_only_mode", true]],
     27  });
     28 
     29  // Site is already HTTPS, so the UI should not be visible.
     30  await runTest({
     31    name: "No HTTPS-Only UI",
     32    initialScheme: outerSchemePrefix + "https",
     33    initialPermission: 0,
     34    isUiVisible: false,
     35  });
     36 
     37  // Site gets upgraded to HTTPS, so the UI should be visible.
     38  // Adding a HTTPS-Only exemption through the menulist should reload the page and
     39  // set the permission accordingly.
     40  await runTest({
     41    name: "Add HTTPS-Only exemption",
     42    initialScheme: outerSchemePrefix + "http",
     43    initialPermission: 0,
     44    isUiVisible: true,
     45    selectPermission: 1,
     46    expectReload: true,
     47    finalScheme: outerScheme || "https",
     48  });
     49 
     50  // HTTPS-Only Mode is disabled for this site, so the UI should be visible.
     51  // Switching HTTPS-Only exemption modes through the menulist should not reload the page
     52  // but set the permission accordingly.
     53  await runTest({
     54    name: "Switch between HTTPS-Only exemption modes",
     55    initialScheme: outerSchemePrefix + "http",
     56    initialPermission: 1,
     57    isUiVisible: true,
     58    selectPermission: 2,
     59    expectReload: false,
     60    finalScheme: outerScheme || "http",
     61  });
     62 
     63  // HTTPS-Only Mode is disabled for this site, so the UI should be visible.
     64  // Disabling HTTPS-Only exemptions through the menulist should reload and upgrade the
     65  // page and set the permission accordingly.
     66  await runTest({
     67    name: "Remove HTTPS-Only exemption again",
     68    initialScheme: outerSchemePrefix + "http",
     69    initialPermission: 2,
     70    permissionScheme: "http",
     71    isUiVisible: true,
     72    selectPermission: 0,
     73    expectReload: true,
     74    finalScheme: outerScheme || "https",
     75  });
     76 
     77  await SpecialPowers.flushPrefEnv();
     78  await SpecialPowers.pushPrefEnv({
     79    set: [["dom.security.https_first", true]],
     80  });
     81 
     82  // Site is already HTTPS, so the UI should not be visible.
     83  await runTest({
     84    name: "No HTTPS-Only UI",
     85    initialScheme: outerSchemePrefix + "https",
     86    initialPermission: 0,
     87    permissionScheme: "https",
     88    isUiVisible: false,
     89  });
     90 
     91  // Site gets upgraded to HTTPS, so the UI should be visible.
     92  // Adding a HTTPS-Only exemption through the menulist should reload the page and
     93  // set the permission accordingly.
     94  await runTest({
     95    name: "Add HTTPS-Only exemption",
     96    initialScheme: outerSchemePrefix + "http",
     97    initialPermission: 0,
     98    permissionScheme: "https",
     99    isUiVisible: true,
    100    selectPermission: 1,
    101    expectReload: true,
    102    finalScheme: outerScheme || "https",
    103  });
    104 
    105  // HTTPS-First Mode is disabled for this site, so the UI should be visible.
    106  // Switching HTTPS-Only exemption modes through the menulist should not reload the page
    107  // but set the permission accordingly.
    108  await runTest({
    109    name: "Switch between HTTPS-Only exemption modes",
    110    initialScheme: outerSchemePrefix + "http",
    111    initialPermission: 1,
    112    permissionScheme: "http",
    113    isUiVisible: true,
    114    selectPermission: 2,
    115    expectReload: false,
    116    finalScheme: outerScheme || "http",
    117  });
    118 
    119  // HTTPS-First Mode is disabled for this site, so the UI should be visible.
    120  // Disabling HTTPS-Only exemptions through the menulist should reload and upgrade the
    121  // page and set the permission accordingly.
    122  await runTest({
    123    name: "Remove HTTPS-Only exemption again",
    124    initialScheme: outerSchemePrefix + "http",
    125    initialPermission: 2,
    126    isUiVisible: true,
    127    selectPermission: 0,
    128    expectReload: true,
    129    finalScheme: outerScheme || "https",
    130  });
    131 }
    132 
    133 async function runTest(options) {
    134  // Set the initial permission
    135  setPermission(WEBSITE("http"), options.initialPermission);
    136 
    137  await BrowserTestUtils.withNewTab(
    138    WEBSITE(options.initialScheme),
    139    async function (browser) {
    140      const name = options.name + " | ";
    141 
    142      // Open the identity popup.
    143      let { gIdentityHandler } = gBrowser.ownerGlobal;
    144      let promisePanelOpen = BrowserTestUtils.waitForEvent(
    145        gBrowser.ownerGlobal,
    146        "popupshown",
    147        true,
    148        event => event.target == gIdentityHandler._identityPopup
    149      );
    150      gIdentityHandler._identityIconBox.click();
    151      await promisePanelOpen;
    152 
    153      // Check if the HTTPS-Only UI is visible
    154      const httpsOnlyUI = document.getElementById(
    155        "identity-popup-security-httpsonlymode"
    156      );
    157      is(
    158        gBrowser.ownerGlobal.getComputedStyle(httpsOnlyUI).display != "none",
    159        options.isUiVisible,
    160        options.isUiVisible
    161          ? name + "HTTPS-Only UI should be visible."
    162          : name + "HTTPS-Only UI shouldn't be visible."
    163      );
    164 
    165      // If it's not visible we can't do much else :)
    166      if (!options.isUiVisible) {
    167        return;
    168      }
    169 
    170      // Check if the value of the menulist matches the initial permission
    171      const httpsOnlyMenulist = document.getElementById(
    172        "identity-popup-security-httpsonlymode-menulist"
    173      );
    174      is(
    175        parseInt(httpsOnlyMenulist.value, 10),
    176        options.initialPermission,
    177        name + "Menulist value should match expected permission value."
    178      );
    179 
    180      // Select another HTTPS-Only state and potentially wait for the page to reload
    181      if (options.expectReload) {
    182        const loaded = BrowserTestUtils.browserLoaded(browser);
    183        httpsOnlyMenulist.getItemAtIndex(options.selectPermission).doCommand();
    184        await loaded;
    185      } else {
    186        httpsOnlyMenulist.getItemAtIndex(options.selectPermission).doCommand();
    187      }
    188 
    189      // Check if the site has the expected scheme
    190      is(
    191        browser.currentURI.scheme,
    192        options.finalScheme,
    193        name + "Unexpected scheme after page reloaded."
    194      );
    195 
    196      // Check if the permission was sucessfully changed
    197      is(
    198        getPermission(WEBSITE("http")),
    199        options.selectPermission,
    200        name + "Set permission should match the one selected from the menulist."
    201      );
    202    }
    203  );
    204 
    205  // Reset permission
    206  Services.perms.removeAll();
    207 }
    208 
    209 function setPermission(url, newValue) {
    210  let uri = Services.io.newURI(url);
    211  let principal = Services.scriptSecurityManager.createContentPrincipal(
    212    uri,
    213    {}
    214  );
    215  if (newValue === 0) {
    216    Services.perms.removeFromPrincipal(principal, HTTPS_ONLY_PERMISSION);
    217  } else if (newValue === 1) {
    218    Services.perms.addFromPrincipal(
    219      principal,
    220      HTTPS_ONLY_PERMISSION,
    221      Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW,
    222      Ci.nsIPermissionManager.EXPIRE_NEVER
    223    );
    224  } else {
    225    Services.perms.addFromPrincipal(
    226      principal,
    227      HTTPS_ONLY_PERMISSION,
    228      Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW_SESSION,
    229      Ci.nsIPermissionManager.EXPIRE_SESSION
    230    );
    231  }
    232 }
    233 
    234 function getPermission(url) {
    235  let uri = Services.io.newURI(url);
    236  let principal = Services.scriptSecurityManager.createContentPrincipal(
    237    uri,
    238    {}
    239  );
    240  const state = Services.perms.testPermissionFromPrincipal(
    241    principal,
    242    HTTPS_ONLY_PERMISSION
    243  );
    244  switch (state) {
    245    case Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW_SESSION:
    246      return 2; // Off temporarily
    247    case Ci.nsIHttpsOnlyModePermission.LOAD_INSECURE_ALLOW:
    248      return 1; // Off
    249    default:
    250      return 0; // On
    251  }
    252 }