tor-browser

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

test_temporary_storage.js (8413B)


      1 /**
      2 * Any copyright is dedicated to the Public Domain.
      3 * http://creativecommons.org/publicdomain/zero/1.0/
      4 */
      5 /* eslint-disable mozilla/no-arbitrary-setTimeout */
      6 
      7 var testGenerator = testSteps();
      8 
      9 function* testSteps() {
     10  const name = this.window
     11    ? window.location.pathname
     12    : "test_temporary_storage.js";
     13  const finalVersion = 2;
     14 
     15  const tempStorageLimitKB = 1024;
     16  const checkpointSleepTimeSec = 5;
     17 
     18  function getSpec(index) {
     19    return "http://foo" + index + ".com";
     20  }
     21 
     22  for (let temporary of [true, false]) {
     23    info("Testing '" + (temporary ? "temporary" : "default") + "' storage");
     24 
     25    setTemporaryStorageLimit(tempStorageLimitKB);
     26 
     27    clearAllDatabases(continueToNextStepSync);
     28    yield undefined;
     29 
     30    info("Stage 1 - Creating empty databases until we reach the quota limit");
     31 
     32    let databases = [];
     33    let options = { version: finalVersion };
     34    if (temporary) {
     35      options.storage = "temporary";
     36    }
     37 
     38    while (true) {
     39      let spec = getSpec(databases.length);
     40 
     41      info("Opening database for " + spec + " with version " + options.version);
     42 
     43      let gotUpgradeIncomplete = false;
     44      let gotUpgradeComplete = false;
     45 
     46      let request = indexedDB.openForPrincipal(
     47        getPrincipal(spec),
     48        name,
     49        options
     50      );
     51      request.onerror = function (event) {
     52        is(
     53          request.error.name,
     54          gotUpgradeIncomplete ? "AbortError" : "QuotaExceededError",
     55          "Reached quota limit"
     56        );
     57        event.preventDefault();
     58        testGenerator.next(false);
     59      };
     60      request.onupgradeneeded = function (event) {
     61        event.target.transaction.onabort = function (e) {
     62          gotUpgradeIncomplete = true;
     63          is(e.target.error.name, "QuotaExceededError", "Reached quota limit");
     64        };
     65        event.target.transaction.oncomplete = function () {
     66          gotUpgradeComplete = true;
     67        };
     68      };
     69      request.onsuccess = function (event) {
     70        let db = event.target.result;
     71        is(db.version, finalVersion, "Correct version " + finalVersion);
     72        databases.push(db);
     73        testGenerator.next(true);
     74      };
     75 
     76      let shouldContinue = yield undefined;
     77      if (shouldContinue) {
     78        is(gotUpgradeComplete, true, "Got upgradeneeded event");
     79        ok(true, "Got success event");
     80      } else {
     81        break;
     82      }
     83    }
     84 
     85    while (true) {
     86      info(
     87        "Sleeping for " +
     88          checkpointSleepTimeSec +
     89          " seconds to let all " +
     90          "checkpoints finish so that we know we have reached quota limit"
     91      );
     92      setTimeout(continueToNextStepSync, checkpointSleepTimeSec * 1000);
     93      yield undefined;
     94 
     95      let spec = getSpec(databases.length);
     96 
     97      info("Opening database for " + spec + " with version " + options.version);
     98 
     99      let gotUpgradeIncomplete = false;
    100      let gotUpgradeComplete = false;
    101 
    102      let request = indexedDB.openForPrincipal(
    103        getPrincipal(spec),
    104        name,
    105        options
    106      );
    107      request.onerror = function (event) {
    108        is(
    109          request.error.name,
    110          gotUpgradeIncomplete ? "AbortError" : "QuotaExceededError",
    111          "Reached quota limit"
    112        );
    113        event.preventDefault();
    114        testGenerator.next(false);
    115      };
    116      request.onupgradeneeded = function (event) {
    117        event.target.transaction.onabort = function (e) {
    118          gotUpgradeIncomplete = true;
    119          is(e.target.error.name, "QuotaExceededError", "Reached quota limit");
    120        };
    121        event.target.transaction.oncomplete = function () {
    122          gotUpgradeComplete = true;
    123        };
    124      };
    125      request.onsuccess = function (event) {
    126        let db = event.target.result;
    127        is(db.version, finalVersion, "Correct version " + finalVersion);
    128        databases.push(db);
    129        testGenerator.next(true);
    130      };
    131 
    132      let shouldContinue = yield undefined;
    133      if (shouldContinue) {
    134        is(gotUpgradeComplete, true, "Got upgradeneeded event");
    135        ok(true, "Got success event");
    136      } else {
    137        break;
    138      }
    139    }
    140 
    141    let databaseCount = databases.length;
    142    info("Created " + databaseCount + " databases before quota limit reached");
    143 
    144    info(
    145      "Stage 2 - " +
    146        "Closing all databases and then attempting to create one more, then " +
    147        "verifying that the oldest origin was cleared"
    148    );
    149 
    150    for (let i = 0; i < databases.length; i++) {
    151      info("Closing database for " + getSpec(i));
    152      databases[i].close();
    153 
    154      // Timer resolution on Windows is low so wait for 40ms just to be safe.
    155      setTimeout(continueToNextStepSync, 40);
    156      yield undefined;
    157    }
    158    databases = null;
    159 
    160    let spec = getSpec(databaseCount);
    161    info("Opening database for " + spec + " with version " + options.version);
    162 
    163    let request = indexedDB.openForPrincipal(getPrincipal(spec), name, options);
    164    request.onerror = errorHandler;
    165    request.onupgradeneeded = grabEventAndContinueHandler;
    166    request.onsuccess = unexpectedSuccessHandler;
    167    let event = yield undefined;
    168 
    169    is(event.type, "upgradeneeded", "Got upgradeneeded event");
    170 
    171    request.onupgradeneeded = unexpectedSuccessHandler;
    172    request.onsuccess = grabEventAndContinueHandler;
    173    event = yield undefined;
    174 
    175    is(event.type, "success", "Got success event");
    176 
    177    let db = event.target.result;
    178    is(db.version, finalVersion, "Correct version " + finalVersion);
    179    db.close();
    180    db = null;
    181 
    182    setTemporaryStorageLimit(tempStorageLimitKB * 2);
    183 
    184    resetAllDatabases(continueToNextStepSync);
    185    yield undefined;
    186 
    187    delete options.version;
    188 
    189    spec = getSpec(0);
    190    info("Opening database for " + spec + " with unspecified version");
    191 
    192    request = indexedDB.openForPrincipal(getPrincipal(spec), name, options);
    193    request.onerror = errorHandler;
    194    request.onupgradeneeded = grabEventAndContinueHandler;
    195    request.onsuccess = unexpectedSuccessHandler;
    196    event = yield undefined;
    197 
    198    is(event.type, "upgradeneeded", "Got upgradeneeded event");
    199 
    200    request.onupgradeneeded = unexpectedSuccessHandler;
    201    request.onsuccess = grabEventAndContinueHandler;
    202    event = yield undefined;
    203 
    204    is(event.type, "success", "Got success event");
    205 
    206    db = event.target.result;
    207    is(db.version, 1, "Correct version 1 (database was recreated)");
    208    db.close();
    209    db = null;
    210 
    211    info(
    212      "Stage 3 - " +
    213        "Cutting storage limit in half to force deletion of some databases"
    214    );
    215 
    216    setTemporaryStorageLimit(tempStorageLimitKB / 2);
    217 
    218    resetAllDatabases(continueToNextStepSync);
    219    yield undefined;
    220 
    221    info("Opening database for " + spec + " with unspecified version");
    222 
    223    // Open the same db again to force QM to delete others. The first origin (0)
    224    // should be the most recent so it should not be deleted and we should not
    225    // get an upgradeneeded event here.
    226    request = indexedDB.openForPrincipal(getPrincipal(spec), name, options);
    227    request.onerror = errorHandler;
    228    request.onupgradeneeded = unexpectedSuccessHandler;
    229    request.onsuccess = grabEventAndContinueHandler;
    230    event = yield undefined;
    231 
    232    is(event.type, "success", "Got correct event type");
    233 
    234    db = event.target.result;
    235    is(db.version, 1, "Correct version 1");
    236    db.close();
    237    db = null;
    238 
    239    setTemporaryStorageLimit(tempStorageLimitKB * 2);
    240 
    241    resetAllDatabases(continueToNextStepSync);
    242    yield undefined;
    243 
    244    options.version = finalVersion;
    245 
    246    let newDatabaseCount = 0;
    247    for (let i = 0; i < databaseCount; i++) {
    248      let spec = getSpec(i);
    249      info("Opening database for " + spec + " with version " + options.version);
    250 
    251      let request = indexedDB.openForPrincipal(
    252        getPrincipal(spec),
    253        name,
    254        options
    255      );
    256      request.onerror = errorHandler;
    257      request.onupgradeneeded = function (event) {
    258        if (!event.oldVersion) {
    259          newDatabaseCount++;
    260        }
    261      };
    262      request.onsuccess = grabEventAndContinueHandler;
    263      let event = yield undefined;
    264 
    265      is(event.type, "success", "Got correct event type");
    266 
    267      let db = request.result;
    268      is(db.version, finalVersion, "Correct version " + finalVersion);
    269      db.close();
    270    }
    271 
    272    info("Needed to recreate " + newDatabaseCount + " databases");
    273    ok(newDatabaseCount, "Created some new databases");
    274    ok(newDatabaseCount < databaseCount, "Didn't recreate all databases");
    275  }
    276 
    277  finishTest();
    278  yield undefined;
    279 }