tor-browser

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

test_storage_tombstones.js (5841B)


      1 /**
      2 * Tests tombstones in address/creditcard records.
      3 */
      4 
      5 "use strict";
      6 
      7 let FormAutofillStorage;
      8 add_setup(async () => {
      9  ({ FormAutofillStorage } = ChromeUtils.importESModule(
     10    "resource://autofill/FormAutofillStorage.sys.mjs"
     11  ));
     12 });
     13 
     14 const TEST_STORE_FILE_NAME = "test-tombstones.json";
     15 
     16 const TEST_ADDRESS_1 = {
     17  "given-name": "Timothy",
     18  "additional-name": "John",
     19  "family-name": "Berners-Lee",
     20  organization: "World Wide Web Consortium",
     21  "street-address": "32 Vassar Street\nMIT Room 32-G524",
     22  "address-level2": "Cambridge",
     23  "address-level1": "MA",
     24  "postal-code": "02139",
     25  country: "US",
     26  tel: "+1 617 253 5702",
     27  email: "timbl@w3.org",
     28 };
     29 
     30 const TEST_CC_1 = {
     31  "cc-name": "John Doe",
     32  "cc-number": "4111111111111111",
     33  "cc-exp-month": 4,
     34  "cc-exp-year": 2017,
     35 };
     36 
     37 let do_check_tombstone_record = profile => {
     38  Assert.ok(profile.deleted);
     39  Assert.deepEqual(
     40    Object.keys(profile).sort(),
     41    ["guid", "timeLastModified", "deleted"].sort()
     42  );
     43 };
     44 
     45 // Like add_task, but actually adds 2 - one for addresses and one for cards.
     46 function add_storage_task(test_function) {
     47  add_task(async function () {
     48    let path = getTempFile(TEST_STORE_FILE_NAME).path;
     49    let profileStorage = new FormAutofillStorage(path);
     50    let testCC1 = Object.assign({}, TEST_CC_1);
     51    await profileStorage.initialize();
     52 
     53    for (let [storage, record] of [
     54      [profileStorage.addresses, TEST_ADDRESS_1],
     55      [profileStorage.creditCards, testCC1],
     56    ]) {
     57      await test_function(storage, record);
     58    }
     59  });
     60 }
     61 
     62 add_storage_task(async function test_simple_tombstone(storage, record) {
     63  info("check simple tombstone semantics");
     64 
     65  let guid = await storage.add(record);
     66  Assert.equal((await storage.getAll()).length, 1);
     67 
     68  storage.remove(guid);
     69 
     70  // should be unable to get it normally.
     71  Assert.equal(await storage.get(guid), null);
     72  // and getAll should also not return it.
     73  Assert.equal((await storage.getAll()).length, 0);
     74 
     75  // but getAll allows us to access deleted items - but we didn't create
     76  // a tombstone here, so even that will not get it.
     77  let all = await storage.getAll({ includeDeleted: true });
     78  Assert.equal(all.length, 0);
     79 });
     80 
     81 add_storage_task(async function test_simple_synctombstone(storage, record) {
     82  info("check simple tombstone semantics for synced records");
     83 
     84  let guid = await storage.add(record);
     85  Assert.equal((await storage.getAll()).length, 1);
     86 
     87  storage.pullSyncChanges(); // force sync metadata, which triggers tombstone behaviour.
     88 
     89  storage.remove(guid);
     90 
     91  // should be unable to get it normally.
     92  Assert.equal(await storage.get(guid), null);
     93  // and getAll should also not return it.
     94  Assert.equal((await storage.getAll()).length, 0);
     95 
     96  // but getAll allows us to access deleted items.
     97  let all = await storage.getAll({ includeDeleted: true });
     98  Assert.equal(all.length, 1);
     99 
    100  do_check_tombstone_record(all[0]);
    101 
    102  // a tombstone got from API should look exactly the same as it got from the
    103  // disk (besides "_sync").
    104  let tombstoneInDisk = Object.assign(
    105    {},
    106    storage._store.data[storage._collectionName][0]
    107  );
    108  delete tombstoneInDisk._sync;
    109  do_check_tombstone_record(tombstoneInDisk);
    110 });
    111 
    112 add_storage_task(async function test_add_tombstone(storage, _record) {
    113  info("Should be able to add a new tombstone");
    114  let guid = await storage.add({ guid: "test-guid-1", deleted: true });
    115 
    116  // should be unable to get it normally.
    117  Assert.equal(await storage.get(guid), null);
    118  // and getAll should also not return it.
    119  Assert.equal((await storage.getAll()).length, 0);
    120 
    121  // but getAll allows us to access deleted items.
    122  let all = await storage.getAll({ rawData: true, includeDeleted: true });
    123  Assert.equal(all.length, 1);
    124 
    125  do_check_tombstone_record(all[0]);
    126 
    127  // a tombstone got from API should look exactly the same as it got from the
    128  // disk (besides "_sync").
    129  let tombstoneInDisk = Object.assign(
    130    {},
    131    storage._store.data[storage._collectionName][0]
    132  );
    133  delete tombstoneInDisk._sync;
    134  do_check_tombstone_record(tombstoneInDisk);
    135 });
    136 
    137 add_storage_task(
    138  async function test_add_tombstone_without_guid(storage, _record) {
    139    info(
    140      "Should not be able to add a new tombstone without specifying the guid"
    141    );
    142    await Assert.rejects(storage.add({ deleted: true }), /Record missing GUID/);
    143    Assert.equal((await storage.getAll({ includeDeleted: true })).length, 0);
    144  }
    145 );
    146 
    147 add_storage_task(
    148  async function test_add_tombstone_existing_guid(storage, record) {
    149    info(
    150      "Should not be able to add a new tombstone when a record with that ID exists"
    151    );
    152    let guid = await storage.add(record);
    153    await Assert.rejects(
    154      storage.add({ guid, deleted: true }),
    155      /a record with this GUID already exists/
    156    );
    157 
    158    // same if the existing item is already a tombstone.
    159    await storage.add({ guid: "test-guid-1", deleted: true });
    160    await Assert.rejects(
    161      storage.add({ guid: "test-guid-1", deleted: true }),
    162      /a record with this GUID already exists/
    163    );
    164  }
    165 );
    166 
    167 add_storage_task(async function test_update_tombstone(storage, _record) {
    168  info("Updating a tombstone should fail");
    169  let guid = await storage.add({ guid: "test-guid-1", deleted: true });
    170  await Assert.rejects(storage.update(guid, {}), /No matching record./);
    171 });
    172 
    173 add_storage_task(
    174  async function test_remove_existing_tombstone(storage, _record) {
    175    info("Removing a record that's already a tombstone should be a no-op");
    176    let guid = await storage.add({
    177      guid: "test-guid-1",
    178      deleted: true,
    179      timeLastModified: 1234,
    180    });
    181 
    182    storage.remove(guid);
    183    let all = await storage.getAll({ rawData: true, includeDeleted: true });
    184    Assert.equal(all.length, 1);
    185 
    186    do_check_tombstone_record(all[0]);
    187    equal(all[0].timeLastModified, 1234); // should not be updated to now().
    188  }
    189 );