tor-browser

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

browser_upgrade_backup.js (5057B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 const { Preferences } = ChromeUtils.importESModule(
      5  "resource://gre/modules/Preferences.sys.mjs"
      6 );
      7 
      8 const Paths = SessionFile.Paths;
      9 const PREF_UPGRADE = "browser.sessionstore.upgradeBackup.latestBuildID";
     10 const PREF_MAX_UPGRADE_BACKUPS =
     11  "browser.sessionstore.upgradeBackup.maxUpgradeBackups";
     12 
     13 /**
     14 * Prepares tests by retrieving the current platform's build ID, clearing the
     15 * build where the last backup was created and creating arbitrary JSON data
     16 * for a new backup.
     17 */
     18 function prepareTest() {
     19  let result = {};
     20 
     21  result.buildID = Services.appinfo.platformBuildID;
     22  Services.prefs.setCharPref(PREF_UPGRADE, "");
     23  result.contents = {
     24    "browser_upgrade_backup.js": Math.random(),
     25  };
     26 
     27  return result;
     28 }
     29 
     30 /**
     31 * Retrieves all upgrade backups and returns them in an array.
     32 */
     33 async function getUpgradeBackups() {
     34  let children = await IOUtils.getChildren(Paths.backups);
     35 
     36  return children.filter(path => path.startsWith(Paths.upgradeBackupPrefix));
     37 }
     38 
     39 add_setup(async function () {
     40  await SpecialPowers.pushPrefEnv({
     41    set: [["test.wait300msAfterTabSwitch", true]],
     42  });
     43 
     44  // Wait until initialization is complete
     45  await SessionStore.promiseInitialized;
     46 });
     47 
     48 add_task(async function test_upgrade_backup() {
     49  let test = prepareTest();
     50  info("Let's check if we create an upgrade backup");
     51  await SessionFile.wipe();
     52  await IOUtils.writeJSON(Paths.clean, test.contents, {
     53    compress: true,
     54  });
     55  info("Call `SessionFile.read()` to set state to 'clean'");
     56  await SessionFile.read();
     57  await SessionFile.write(""); // First call to write() triggers the backup
     58 
     59  Assert.equal(
     60    Services.prefs.getCharPref(PREF_UPGRADE),
     61    test.buildID,
     62    "upgrade backup should be set"
     63  );
     64 
     65  Assert.ok(
     66    await IOUtils.exists(Paths.upgradeBackup),
     67    "upgrade backup file has been created"
     68  );
     69 
     70  let data = await IOUtils.readJSON(Paths.upgradeBackup, { decompress: true });
     71  Assert.deepEqual(
     72    test.contents,
     73    data,
     74    "upgrade backup contains the expected contents"
     75  );
     76 
     77  info("Let's check that we don't overwrite this upgrade backup");
     78  let newContents = {
     79    "something else entirely": Math.random(),
     80  };
     81  await IOUtils.writeJSON(Paths.clean, newContents, {
     82    compress: true,
     83  });
     84  await SessionFile.write(""); // Next call to write() shouldn't trigger the backup
     85  data = await IOUtils.readJSON(Paths.upgradeBackup, { decompress: true });
     86  Assert.deepEqual(test.contents, data, "upgrade backup hasn't changed");
     87 });
     88 
     89 add_task(async function test_upgrade_backup_removal() {
     90  let test = prepareTest();
     91  let maxUpgradeBackups = Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3);
     92  info("Let's see if we remove backups if there are too many");
     93  await SessionFile.wipe();
     94  await IOUtils.writeJSON(Paths.clean, test.contents, {
     95    compress: true,
     96  });
     97  info("Call `SessionFile.read()` to set state to 'clean'");
     98  await SessionFile.read();
     99 
    100  // create dummy backups
    101  await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20080101010101", "", {
    102    compress: true,
    103  });
    104  await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20090101010101", "", {
    105    compress: true,
    106  });
    107  await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20100101010101", "", {
    108    compress: true,
    109  });
    110  await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20110101010101", "", {
    111    compress: true,
    112  });
    113  await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20120101010101", "", {
    114    compress: true,
    115  });
    116  await IOUtils.writeUTF8(Paths.upgradeBackupPrefix + "20130101010101", "", {
    117    compress: true,
    118  });
    119 
    120  // get currently existing backups
    121  let backups = await getUpgradeBackups();
    122 
    123  info("Write the session to disk and perform a backup");
    124  await SessionFile.write(""); // First call to write() triggers the backup and the cleanup
    125 
    126  // a new backup should have been created (and still exist)
    127  is(
    128    Services.prefs.getCharPref(PREF_UPGRADE),
    129    test.buildID,
    130    "upgrade backup should be set"
    131  );
    132  Assert.ok(
    133    await IOUtils.exists(Paths.upgradeBackup),
    134    "upgrade backup file has been created"
    135  );
    136 
    137  // get currently existing backups and check their count
    138  let newBackups = await getUpgradeBackups();
    139  is(
    140    newBackups.length,
    141    maxUpgradeBackups,
    142    "expected number of backups are present after removing old backups"
    143  );
    144 
    145  // find all backups that were created during the last call to `SessionFile.write("");`
    146  // ie, filter out all the backups that have already been present before the call
    147  newBackups = newBackups.filter(function (backup) {
    148    return !backups.includes(backup);
    149  });
    150 
    151  // check that exactly one new backup was created
    152  is(newBackups.length, 1, "one new backup was created that was not removed");
    153 
    154  await SessionFile.write(""); // Second call to write() should not trigger anything
    155 
    156  backups = await getUpgradeBackups();
    157  is(
    158    backups.length,
    159    maxUpgradeBackups,
    160    "second call to SessionFile.write() didn't create or remove more backups"
    161  );
    162 });