tor-browser

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

test_extension_storage_engine.js (7786B)


      1 /* Any copyright is dedicated to the Public Domain.
      2 * http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 ChromeUtils.defineESModuleGetters(this, {
      7  Service: "resource://services-sync/service.sys.mjs",
      8  extensionStorageSync: "resource://gre/modules/ExtensionStorageSync.sys.mjs",
      9 });
     10 
     11 const { ExtensionStorageEngineBridge, ExtensionStorageEngineKinto } =
     12  ChromeUtils.importESModule(
     13    "resource://services-sync/engines/extension-storage.sys.mjs"
     14  );
     15 
     16 Services.prefs.setStringPref("webextensions.storage.sync.log.level", "debug");
     17 
     18 add_task(async function test_switching_between_kinto_and_bridged() {
     19  function assertUsingKinto(message) {
     20    let kintoEngine = Service.engineManager.get("extension-storage");
     21    Assert.ok(kintoEngine instanceof ExtensionStorageEngineKinto, message);
     22  }
     23  function assertUsingBridged(message) {
     24    let bridgedEngine = Service.engineManager.get("extension-storage");
     25    Assert.ok(bridgedEngine instanceof ExtensionStorageEngineBridge, message);
     26  }
     27 
     28  let isUsingKinto = Services.prefs.getBoolPref(
     29    "webextensions.storage.sync.kinto",
     30    false
     31  );
     32  if (isUsingKinto) {
     33    assertUsingKinto("Should use Kinto engine before flipping pref");
     34  } else {
     35    assertUsingBridged("Should use bridged engine before flipping pref");
     36  }
     37 
     38  _("Flip pref");
     39  Services.prefs.setBoolPref("webextensions.storage.sync.kinto", !isUsingKinto);
     40  await Service.engineManager.switchAlternatives();
     41 
     42  if (isUsingKinto) {
     43    assertUsingBridged("Should use bridged engine after flipping pref");
     44  } else {
     45    assertUsingKinto("Should use Kinto engine after flipping pref");
     46  }
     47 
     48  _("Clean up");
     49  Services.prefs.clearUserPref("webextensions.storage.sync.kinto");
     50  await Service.engineManager.switchAlternatives();
     51 });
     52 
     53 add_task(async function test_enable() {
     54  const PREF = "services.sync.engine.extension-storage.force";
     55 
     56  let addonsEngine = Service.engineManager.get("addons");
     57  let extensionStorageEngine = Service.engineManager.get("extension-storage");
     58 
     59  try {
     60    Assert.ok(
     61      addonsEngine.enabled,
     62      "Add-ons engine should be enabled by default"
     63    );
     64    Assert.ok(
     65      extensionStorageEngine.enabled,
     66      "Extension storage engine should be enabled by default"
     67    );
     68 
     69    addonsEngine.enabled = false;
     70    Assert.ok(
     71      !extensionStorageEngine.enabled,
     72      "Disabling add-ons should disable extension storage"
     73    );
     74 
     75    extensionStorageEngine.enabled = true;
     76    Assert.ok(
     77      !extensionStorageEngine.enabled,
     78      "Enabling extension storage without override pref shouldn't work"
     79    );
     80 
     81    Services.prefs.setBoolPref(PREF, true);
     82    Assert.ok(
     83      extensionStorageEngine.enabled,
     84      "Setting override pref should enable extension storage"
     85    );
     86 
     87    extensionStorageEngine.enabled = false;
     88    Assert.ok(
     89      !extensionStorageEngine.enabled,
     90      "Disabling extension storage engine with override pref should work"
     91    );
     92 
     93    extensionStorageEngine.enabled = true;
     94    Assert.ok(
     95      extensionStorageEngine.enabled,
     96      "Enabling extension storage with override pref should work"
     97    );
     98  } finally {
     99    addonsEngine.enabled = true;
    100    Services.prefs.clearUserPref(PREF);
    101  }
    102 });
    103 
    104 add_task(async function test_notifyPendingChanges() {
    105  let engine = new ExtensionStorageEngineBridge(Service);
    106  await engine.initialize();
    107 
    108  let extension = { id: "ext-1" };
    109  let expectedChange = {
    110    a: "b",
    111    c: "d",
    112  };
    113 
    114  let lastSync = 0;
    115  let syncID = Utils.makeGUID();
    116  let error = null;
    117  engine._rustStore = {
    118    getSyncedChanges() {
    119      if (error) {
    120        throw new Error(error.message);
    121      } else {
    122        return [
    123          { extId: extension.id, changes: JSON.stringify(expectedChange) },
    124        ];
    125      }
    126    },
    127  };
    128 
    129  engine._bridge = {
    130    ensureCurrentSyncId(id) {
    131      if (syncID != id) {
    132        syncID = id;
    133        lastSync = 0;
    134      }
    135      return id;
    136    },
    137    resetSyncId() {
    138      return syncID;
    139    },
    140    syncStarted() {},
    141    lastSync() {
    142      return lastSync;
    143    },
    144    setLastSync(lastSyncMillis) {
    145      lastSync = lastSyncMillis;
    146    },
    147    apply() {
    148      return [];
    149    },
    150    setUploaded(_modified, _ids) {},
    151    syncFinished() {},
    152  };
    153 
    154  let server = await serverForFoo(engine);
    155 
    156  let actualChanges = [];
    157  let listener = changes => actualChanges.push(changes);
    158  extensionStorageSync.addOnChangedListener(extension, listener);
    159 
    160  try {
    161    await SyncTestingInfrastructure(server);
    162 
    163    info("Sync engine; notify about changes");
    164    await sync_engine_and_validate_telem(engine, false);
    165    deepEqual(
    166      actualChanges,
    167      [expectedChange],
    168      "Should notify about changes during sync"
    169    );
    170 
    171    error = new Error("oops!");
    172    actualChanges = [];
    173    await sync_engine_and_validate_telem(engine, false);
    174    deepEqual(
    175      actualChanges,
    176      [],
    177      "Should finish syncing even if notifying about changes fails"
    178    );
    179  } finally {
    180    extensionStorageSync.removeOnChangedListener(extension, listener);
    181    await promiseStopServer(server);
    182    await engine.finalize();
    183  }
    184 });
    185 
    186 // It's difficult to know what to test - there's already tests for the bridged
    187 // engine etc - so we just try and check that this engine conforms to the
    188 // mozIBridgedSyncEngine interface guarantees.
    189 add_task(async function test_engine() {
    190  // Forcibly set the bridged engine in the engine manager. the reason we do
    191  // this, unlike the other tests where we just create the engine, is so that
    192  // telemetry can get at the engine's `overrideTelemetryName`, which it gets
    193  // through the engine manager.
    194  await Service.engineManager.unregister("extension-storage");
    195  await Service.engineManager.register(ExtensionStorageEngineBridge);
    196  let engine = Service.engineManager.get("extension-storage");
    197  Assert.equal(engine.version, 1);
    198 
    199  Assert.deepEqual(await engine.getSyncID(), null);
    200  await engine.resetLocalSyncID();
    201  Assert.notEqual(await engine.getSyncID(), null);
    202 
    203  Assert.equal(await engine.getLastSync(), 0);
    204  // lastSync is seconds on this side of the world, but milli-seconds on the other.
    205  await engine.setLastSync(1234.567);
    206  // should have 2 digit precision.
    207  Assert.equal(await engine.getLastSync(), 1234.57);
    208  await engine.setLastSync(0);
    209 
    210  // Set some data.
    211  await extensionStorageSync.set({ id: "ext-2" }, { ext_2_key: "ext_2_value" });
    212  // Now do a sync with out regular test server.
    213  let server = await serverForFoo(engine);
    214  try {
    215    await SyncTestingInfrastructure(server);
    216 
    217    info("Add server records");
    218    let foo = server.user("foo");
    219    let collection = foo.collection("extension-storage");
    220    let now = new_timestamp();
    221 
    222    collection.insert(
    223      "fakeguid0000",
    224      encryptPayload({
    225        id: "fakeguid0000",
    226        extId: "ext-1",
    227        data: JSON.stringify({ foo: "bar" }),
    228      }),
    229      now
    230    );
    231 
    232    info("Sync the engine");
    233 
    234    let ping = await sync_engine_and_validate_telem(engine, false);
    235    Assert.ok(ping.engines.find(e => e.name == "rust-webext-storage"));
    236    Assert.equal(
    237      ping.engines.find(e => e.name == "extension-storage"),
    238      null
    239    );
    240 
    241    // We should have applied the data from the existing collection record.
    242    Assert.deepEqual(await extensionStorageSync.get({ id: "ext-1" }, null), {
    243      foo: "bar",
    244    });
    245 
    246    // should now be 2 records on the server.
    247    let payloads = collection.payloads();
    248    Assert.equal(payloads.length, 2);
    249    // find the new one we wrote.
    250    let newPayload =
    251      payloads[0].id == "fakeguid0000" ? payloads[1] : payloads[0];
    252    Assert.equal(newPayload.data, `{"ext_2_key":"ext_2_value"}`);
    253    // should have updated the timestamp.
    254    greater(await engine.getLastSync(), 0, "Should update last sync time");
    255  } finally {
    256    await promiseStopServer(server);
    257    await engine.finalize();
    258  }
    259 });