tor-browser

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

test_permissions.js (9258B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 const userAgentID = "2c43af06-ab6e-476a-adc4-16cbda54fb89";
      7 
      8 let db;
      9 
     10 function run_test() {
     11  do_get_profile();
     12  setPrefs({
     13    userAgentID,
     14  });
     15 
     16  db = PushServiceWebSocket.newPushDB();
     17  registerCleanupFunction(() => {
     18    return db.drop().then(_ => db.close());
     19  });
     20 
     21  run_next_test();
     22 }
     23 
     24 let unregisterDefers = {};
     25 
     26 function promiseUnregister(keyID) {
     27  return new Promise(r => (unregisterDefers[keyID] = r));
     28 }
     29 
     30 function makePushPermission(url, capability) {
     31  return {
     32    QueryInterface: ChromeUtils.generateQI(["nsIPermission"]),
     33    capability: Ci.nsIPermissionManager[capability],
     34    expireTime: 0,
     35    expireType: Ci.nsIPermissionManager.EXPIRE_NEVER,
     36    principal: Services.scriptSecurityManager.createContentPrincipal(
     37      Services.io.newURI(url),
     38      {}
     39    ),
     40    type: "desktop-notification",
     41  };
     42 }
     43 
     44 function promiseObserverNotifications(topic, count) {
     45  let notifiedScopes = [];
     46  let subChangePromise = promiseObserverNotification(topic, (subject, data) => {
     47    notifiedScopes.push(data);
     48    return notifiedScopes.length == count;
     49  });
     50  return subChangePromise.then(_ => notifiedScopes.sort());
     51 }
     52 
     53 function promiseSubscriptionChanges(count) {
     54  return promiseObserverNotifications(
     55    PushServiceComponent.subscriptionChangeTopic,
     56    count
     57  );
     58 }
     59 
     60 function promiseSubscriptionModifications(count) {
     61  return promiseObserverNotifications(
     62    PushServiceComponent.subscriptionModifiedTopic,
     63    count
     64  );
     65 }
     66 
     67 function allExpired(...keyIDs) {
     68  return Promise.all(keyIDs.map(keyID => db.getByKeyID(keyID))).then(records =>
     69    records.every(record => record.isExpired())
     70  );
     71 }
     72 
     73 add_task(async function setUp() {
     74  // Active registration; quota should be reset to 16. Since the quota isn't
     75  // exposed to content, we shouldn't receive a subscription change event.
     76  await putTestRecord(db, "active-allow", "https://example.info/page/1", 8);
     77 
     78  // Expired registration; should be dropped.
     79  await putTestRecord(db, "expired-allow", "https://example.info/page/2", 0);
     80 
     81  // Active registration; should be expired when we change the permission
     82  // to "deny".
     83  await putTestRecord(
     84    db,
     85    "active-deny-changed",
     86    "https://example.xyz/page/1",
     87    16
     88  );
     89 
     90  // Two active registrations for a visited site. These will expire when we
     91  // add a "deny" permission.
     92  await putTestRecord(db, "active-deny-added-1", "https://example.net/ham", 16);
     93  await putTestRecord(
     94    db,
     95    "active-deny-added-2",
     96    "https://example.net/green",
     97    8
     98  );
     99 
    100  // An already-expired registration for a visited site. We shouldn't send an
    101  // `unregister` request for this one, but still receive an observer
    102  // notification when we restore permissions.
    103  await putTestRecord(db, "expired-deny-added", "https://example.net/eggs", 0);
    104 
    105  // A registration that should not be affected by permission list changes
    106  // because its quota is set to `Infinity`.
    107  await putTestRecord(db, "never-expires", "app://chrome/only", Infinity);
    108 
    109  // A registration that should be dropped when we clear the permission
    110  // list.
    111  await putTestRecord(db, "drop-on-clear", "https://example.edu/lonely", 16);
    112 
    113  let handshakeDone;
    114  let handshakePromise = new Promise(resolve => (handshakeDone = resolve));
    115  PushService.init({
    116    serverURI: "wss://push.example.org/",
    117    db,
    118    makeWebSocket(uri) {
    119      return new MockWebSocket(uri, {
    120        onHello() {
    121          this.serverSendMsg(
    122            JSON.stringify({
    123              messageType: "hello",
    124              status: 200,
    125              uaid: userAgentID,
    126            })
    127          );
    128          handshakeDone();
    129        },
    130        onUnregister(request) {
    131          let resolve = unregisterDefers[request.channelID];
    132          equal(
    133            typeof resolve,
    134            "function",
    135            "Dropped unexpected channel ID " + request.channelID
    136          );
    137          delete unregisterDefers[request.channelID];
    138          equal(
    139            request.code,
    140            202,
    141            "Expected permission revoked unregister reason"
    142          );
    143          resolve();
    144          this.serverSendMsg(
    145            JSON.stringify({
    146              messageType: "unregister",
    147              status: 200,
    148              channelID: request.channelID,
    149            })
    150          );
    151        },
    152        onACK() {},
    153      });
    154    },
    155  });
    156  await handshakePromise;
    157 });
    158 
    159 add_task(async function test_permissions_allow_added() {
    160  let subChangePromise = promiseSubscriptionChanges(1);
    161 
    162  await PushService._onPermissionChange(
    163    makePushPermission("https://example.info", "ALLOW_ACTION"),
    164    "added"
    165  );
    166  let notifiedScopes = await subChangePromise;
    167 
    168  deepEqual(
    169    notifiedScopes,
    170    ["https://example.info/page/2"],
    171    "Wrong scopes after adding allow"
    172  );
    173 
    174  let record = await db.getByKeyID("active-allow");
    175  equal(
    176    record.quota,
    177    16,
    178    "Should reset quota for active records after adding allow"
    179  );
    180 
    181  record = await db.getByKeyID("expired-allow");
    182  ok(!record, "Should drop expired records after adding allow");
    183 });
    184 
    185 add_task(async function test_permissions_allow_deleted() {
    186  let subModifiedPromise = promiseSubscriptionModifications(1);
    187 
    188  let unregisterPromise = promiseUnregister("active-allow");
    189 
    190  await PushService._onPermissionChange(
    191    makePushPermission("https://example.info", "ALLOW_ACTION"),
    192    "deleted"
    193  );
    194 
    195  await unregisterPromise;
    196 
    197  let notifiedScopes = await subModifiedPromise;
    198  deepEqual(
    199    notifiedScopes,
    200    ["https://example.info/page/1"],
    201    "Wrong scopes modified after deleting allow"
    202  );
    203 
    204  let record = await db.getByKeyID("active-allow");
    205  ok(record.isExpired(), "Should expire active record after deleting allow");
    206 });
    207 
    208 add_task(async function test_permissions_deny_added() {
    209  let subModifiedPromise = promiseSubscriptionModifications(2);
    210 
    211  let unregisterPromise = Promise.all([
    212    promiseUnregister("active-deny-added-1"),
    213    promiseUnregister("active-deny-added-2"),
    214  ]);
    215 
    216  await PushService._onPermissionChange(
    217    makePushPermission("https://example.net", "DENY_ACTION"),
    218    "added"
    219  );
    220  await unregisterPromise;
    221 
    222  let notifiedScopes = await subModifiedPromise;
    223  deepEqual(
    224    notifiedScopes,
    225    ["https://example.net/green", "https://example.net/ham"],
    226    "Wrong scopes modified after adding deny"
    227  );
    228 
    229  let isExpired = await allExpired("active-deny-added-1", "expired-deny-added");
    230  ok(isExpired, "Should expire all registrations after adding deny");
    231 });
    232 
    233 add_task(async function test_permissions_deny_deleted() {
    234  await PushService._onPermissionChange(
    235    makePushPermission("https://example.net", "DENY_ACTION"),
    236    "deleted"
    237  );
    238 
    239  let isExpired = await allExpired("active-deny-added-1", "expired-deny-added");
    240  ok(isExpired, "Should retain expired registrations after deleting deny");
    241 });
    242 
    243 add_task(async function test_permissions_allow_changed() {
    244  let subChangePromise = promiseSubscriptionChanges(3);
    245 
    246  await PushService._onPermissionChange(
    247    makePushPermission("https://example.net", "ALLOW_ACTION"),
    248    "changed"
    249  );
    250 
    251  let notifiedScopes = await subChangePromise;
    252 
    253  deepEqual(
    254    notifiedScopes,
    255    [
    256      "https://example.net/eggs",
    257      "https://example.net/green",
    258      "https://example.net/ham",
    259    ],
    260    "Wrong scopes after changing to allow"
    261  );
    262 
    263  let droppedRecords = await Promise.all([
    264    db.getByKeyID("active-deny-added-1"),
    265    db.getByKeyID("active-deny-added-2"),
    266    db.getByKeyID("expired-deny-added"),
    267  ]);
    268  ok(
    269    !droppedRecords.some(Boolean),
    270    "Should drop all expired registrations after changing to allow"
    271  );
    272 });
    273 
    274 add_task(async function test_permissions_deny_changed() {
    275  let subModifiedPromise = promiseSubscriptionModifications(1);
    276 
    277  let unregisterPromise = promiseUnregister("active-deny-changed");
    278 
    279  await PushService._onPermissionChange(
    280    makePushPermission("https://example.xyz", "DENY_ACTION"),
    281    "changed"
    282  );
    283 
    284  await unregisterPromise;
    285 
    286  let notifiedScopes = await subModifiedPromise;
    287  deepEqual(
    288    notifiedScopes,
    289    ["https://example.xyz/page/1"],
    290    "Wrong scopes modified after changing to deny"
    291  );
    292 
    293  let record = await db.getByKeyID("active-deny-changed");
    294  ok(record.isExpired(), "Should expire active record after changing to deny");
    295 });
    296 
    297 add_task(async function test_permissions_clear() {
    298  let subModifiedPromise = promiseSubscriptionModifications(3);
    299 
    300  deepEqual(
    301    await getAllKeyIDs(db),
    302    ["active-allow", "active-deny-changed", "drop-on-clear", "never-expires"],
    303    "Wrong records in database before clearing"
    304  );
    305 
    306  let unregisterPromise = Promise.all([
    307    promiseUnregister("active-allow"),
    308    promiseUnregister("active-deny-changed"),
    309    promiseUnregister("drop-on-clear"),
    310  ]);
    311 
    312  await PushService._onPermissionChange(null, "cleared");
    313 
    314  await unregisterPromise;
    315 
    316  let notifiedScopes = await subModifiedPromise;
    317  deepEqual(
    318    notifiedScopes,
    319    [
    320      "https://example.edu/lonely",
    321      "https://example.info/page/1",
    322      "https://example.xyz/page/1",
    323    ],
    324    "Wrong scopes modified after clearing registrations"
    325  );
    326 
    327  deepEqual(
    328    await getAllKeyIDs(db),
    329    ["never-expires"],
    330    "Unrestricted registrations should not be dropped"
    331  );
    332 });