tor-browser

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

browser_temporary_permissions_expiry.js (6158B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 /* eslint-disable mozilla/no-arbitrary-setTimeout */
      4 
      5 "use strict";
      6 
      7 const ORIGIN = "https://example.com";
      8 const PERMISSIONS_PAGE =
      9  getRootDirectory(gTestPath).replace("chrome://mochitests/content", ORIGIN) +
     10  "permissions.html";
     11 
     12 // Ignore promise rejection caused by clicking Deny button.
     13 const { PromiseTestUtils } = ChromeUtils.importESModule(
     14  "resource://testing-common/PromiseTestUtils.sys.mjs"
     15 );
     16 PromiseTestUtils.allowMatchingRejectionsGlobally(/The request is not allowed/);
     17 
     18 const EXPIRE_TIME_MS = 100;
     19 const TIMEOUT_MS = 500;
     20 
     21 const EXPIRE_TIME_CUSTOM_MS = 1000;
     22 const TIMEOUT_CUSTOM_MS = 1500;
     23 
     24 const kVREnabled = SpecialPowers.getBoolPref("dom.vr.enabled");
     25 
     26 // Test that temporary permissions can be re-requested after they expired
     27 // and that the identity block is updated accordingly.
     28 add_task(async function testTempPermissionRequestAfterExpiry() {
     29  await SpecialPowers.pushPrefEnv({
     30    set: [
     31      ["privacy.temporary_permission_expire_time_ms", EXPIRE_TIME_MS],
     32      ["media.navigator.permission.fake", true],
     33      ["dom.vr.always_support_vr", true],
     34    ],
     35  });
     36 
     37  let principal =
     38    Services.scriptSecurityManager.createContentPrincipalFromOrigin(ORIGIN);
     39  let ids = ["geo", "camera"];
     40 
     41  if (kVREnabled) {
     42    ids.push("xr");
     43  }
     44 
     45  for (let id of ids) {
     46    await BrowserTestUtils.withNewTab(
     47      PERMISSIONS_PAGE,
     48      async function (browser) {
     49        let blockedIcon = gPermissionPanel._identityPermissionBox.querySelector(
     50          `.blocked-permission-icon[data-permission-id='${id}']`
     51        );
     52 
     53        SitePermissions.setForPrincipal(
     54          principal,
     55          id,
     56          SitePermissions.BLOCK,
     57          SitePermissions.SCOPE_TEMPORARY,
     58          browser
     59        );
     60 
     61        Assert.deepEqual(
     62          SitePermissions.getForPrincipal(principal, id, browser),
     63          {
     64            state: SitePermissions.BLOCK,
     65            scope: SitePermissions.SCOPE_TEMPORARY,
     66          }
     67        );
     68 
     69        ok(
     70          blockedIcon.hasAttribute("showing"),
     71          "blocked permission icon is shown"
     72        );
     73 
     74        await new Promise(c => setTimeout(c, TIMEOUT_MS));
     75 
     76        Assert.deepEqual(
     77          SitePermissions.getForPrincipal(principal, id, browser),
     78          {
     79            state: SitePermissions.UNKNOWN,
     80            scope: SitePermissions.SCOPE_PERSISTENT,
     81          }
     82        );
     83 
     84        let popupshown = BrowserTestUtils.waitForEvent(
     85          PopupNotifications.panel,
     86          "popupshown"
     87        );
     88 
     89        // Request a permission;
     90        await BrowserTestUtils.synthesizeMouseAtCenter(`#${id}`, {}, browser);
     91 
     92        await popupshown;
     93 
     94        ok(
     95          !blockedIcon.hasAttribute("showing"),
     96          "blocked permission icon is not shown"
     97        );
     98 
     99        let popuphidden = BrowserTestUtils.waitForEvent(
    100          PopupNotifications.panel,
    101          "popuphidden"
    102        );
    103 
    104        let notification = PopupNotifications.panel.firstElementChild;
    105        EventUtils.synthesizeMouseAtCenter(notification.secondaryButton, {});
    106 
    107        await popuphidden;
    108 
    109        SitePermissions.removeFromPrincipal(principal, id, browser);
    110      }
    111    );
    112  }
    113 });
    114 
    115 /**
    116 * Test whether the identity UI shows the permission granted state.
    117 *
    118 * @param {boolean} state - true = Shows permission granted, false otherwise.
    119 */
    120 async function testIdentityPermissionGrantedState(state) {
    121  let hasAttribute;
    122  let msg = `Identity permission box ${
    123    state ? "shows" : "does not show"
    124  } granted permissions.`;
    125  await TestUtils.waitForCondition(() => {
    126    hasAttribute =
    127      gPermissionPanel._identityPermissionBox.hasAttribute("hasPermissions");
    128    return hasAttribute == state;
    129  }, msg);
    130  is(hasAttribute, state, msg);
    131 }
    132 
    133 // Test that temporary permissions can have custom expiry time and the identity
    134 // block is updated correctly on expiry.
    135 add_task(async function testTempPermissionCustomExpiry() {
    136  const TEST_ID = "geo";
    137  // Set a default expiry time which is lower than the custom one we'll set.
    138  await SpecialPowers.pushPrefEnv({
    139    set: [["privacy.temporary_permission_expire_time_ms", EXPIRE_TIME_MS]],
    140  });
    141 
    142  await BrowserTestUtils.withNewTab(PERMISSIONS_PAGE, async browser => {
    143    Assert.deepEqual(
    144      SitePermissions.getForPrincipal(null, TEST_ID, browser),
    145      {
    146        state: SitePermissions.UNKNOWN,
    147        scope: SitePermissions.SCOPE_PERSISTENT,
    148      },
    149      "Permission not set initially"
    150    );
    151 
    152    await testIdentityPermissionGrantedState(false);
    153 
    154    // Set permission with custom expiry time.
    155    SitePermissions.setForPrincipal(
    156      null,
    157      "geo",
    158      SitePermissions.ALLOW,
    159      SitePermissions.SCOPE_TEMPORARY,
    160      browser,
    161      EXPIRE_TIME_CUSTOM_MS
    162    );
    163 
    164    await testIdentityPermissionGrantedState(true);
    165 
    166    // We've set the permission, start the timer promise.
    167    let timeout = new Promise(resolve =>
    168      setTimeout(resolve, TIMEOUT_CUSTOM_MS)
    169    );
    170 
    171    Assert.deepEqual(
    172      SitePermissions.getForPrincipal(null, TEST_ID, browser),
    173      {
    174        state: SitePermissions.ALLOW,
    175        scope: SitePermissions.SCOPE_TEMPORARY,
    176      },
    177      "We should see the temporary permission we just set."
    178    );
    179 
    180    // Wait for half of the expiry time.
    181    await new Promise(resolve =>
    182      setTimeout(resolve, EXPIRE_TIME_CUSTOM_MS / 2)
    183    );
    184    Assert.deepEqual(
    185      SitePermissions.getForPrincipal(null, TEST_ID, browser),
    186      {
    187        state: SitePermissions.ALLOW,
    188        scope: SitePermissions.SCOPE_TEMPORARY,
    189      },
    190      "Temporary permission should not have expired yet."
    191    );
    192 
    193    // Wait until permission expiry.
    194    await timeout;
    195 
    196    // Identity permission section should have updated by now. It should do this
    197    // without relying on side-effects of the SitePermissions getter.
    198    await testIdentityPermissionGrantedState(false);
    199 
    200    Assert.deepEqual(
    201      SitePermissions.getForPrincipal(null, TEST_ID, browser),
    202      {
    203        state: SitePermissions.UNKNOWN,
    204        scope: SitePermissions.SCOPE_PERSISTENT,
    205      },
    206      "Permission should have expired"
    207    );
    208  });
    209 });