tor-browser

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

test_service_sync_updateEnabledEngines.js (17727B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 const { Service } = ChromeUtils.importESModule(
      5  "resource://services-sync/service.sys.mjs"
      6 );
      7 
      8 const { EngineSynchronizer } = ChromeUtils.importESModule(
      9  "resource://services-sync/stages/enginesync.sys.mjs"
     10 );
     11 
     12 function QuietStore() {
     13  Store.call("Quiet");
     14 }
     15 QuietStore.prototype = {
     16  async getAllIDs() {
     17    return [];
     18  },
     19 };
     20 
     21 function SteamEngine() {
     22  SyncEngine.call(this, "Steam", Service);
     23 }
     24 SteamEngine.prototype = {
     25  // We're not interested in engine sync but what the service does.
     26  _storeObj: QuietStore,
     27 
     28  _sync: async function _sync() {
     29    await this._syncStartup();
     30  },
     31 };
     32 Object.setPrototypeOf(SteamEngine.prototype, SyncEngine.prototype);
     33 
     34 function StirlingEngine() {
     35  SyncEngine.call(this, "Stirling", Service);
     36 }
     37 StirlingEngine.prototype = {
     38  // This engine's enabled state is the same as the SteamEngine's.
     39  get prefName() {
     40    return "steam";
     41  },
     42 };
     43 Object.setPrototypeOf(StirlingEngine.prototype, SteamEngine.prototype);
     44 
     45 // Tracking info/collections.
     46 var collectionsHelper = track_collections_helper();
     47 var upd = collectionsHelper.with_updated_collection;
     48 
     49 function sync_httpd_setup(handlers) {
     50  handlers["/1.1/johndoe/info/collections"] = collectionsHelper.handler;
     51  delete collectionsHelper.collections.crypto;
     52  delete collectionsHelper.collections.meta;
     53 
     54  let cr = new ServerWBO("keys");
     55  handlers["/1.1/johndoe/storage/crypto/keys"] = upd("crypto", cr.handler());
     56 
     57  let cl = new ServerCollection();
     58  handlers["/1.1/johndoe/storage/clients"] = upd("clients", cl.handler());
     59 
     60  return httpd_setup(handlers);
     61 }
     62 
     63 async function setUp(server) {
     64  await SyncTestingInfrastructure(server, "johndoe", "ilovejane");
     65  // Ensure that the server has valid keys so that logging in will work and not
     66  // result in a server wipe, rendering many of these tests useless.
     67  await generateNewKeys(Service.collectionKeys);
     68  let serverKeys = Service.collectionKeys.asWBO("crypto", "keys");
     69  await serverKeys.encrypt(Service.identity.syncKeyBundle);
     70  let { success } = await serverKeys.upload(
     71    Service.resource(Service.cryptoKeysURL)
     72  );
     73  ok(success);
     74 }
     75 
     76 const PAYLOAD = 42;
     77 
     78 add_task(async function setup() {
     79  await Service.engineManager.clear();
     80  validate_all_future_pings();
     81 
     82  await Service.engineManager.register(SteamEngine);
     83  await Service.engineManager.register(StirlingEngine);
     84 });
     85 
     86 add_task(async function test_newAccount() {
     87  enableValidationPrefs();
     88 
     89  _("Test: New account does not disable locally enabled engines.");
     90  let engine = Service.engineManager.get("steam");
     91  let server = sync_httpd_setup({
     92    "/1.1/johndoe/storage/meta/global": new ServerWBO("global", {}).handler(),
     93    "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(),
     94  });
     95  await setUp(server);
     96 
     97  try {
     98    _("Engine is enabled from the beginning.");
     99    Service._ignorePrefObserver = true;
    100    engine.enabled = true;
    101    Service._ignorePrefObserver = false;
    102 
    103    _("Sync.");
    104    await Service.sync();
    105 
    106    _("Engine continues to be enabled.");
    107    Assert.ok(engine.enabled);
    108  } finally {
    109    await Service.startOver();
    110    await promiseStopServer(server);
    111  }
    112 });
    113 
    114 add_task(async function test_enabledLocally() {
    115  enableValidationPrefs();
    116 
    117  _("Test: Engine is disabled on remote clients and enabled locally");
    118  Service.syncID = "abcdefghij";
    119  let engine = Service.engineManager.get("steam");
    120  let metaWBO = new ServerWBO("global", {
    121    syncID: Service.syncID,
    122    storageVersion: STORAGE_VERSION,
    123    engines: {},
    124  });
    125  let server = sync_httpd_setup({
    126    "/1.1/johndoe/storage/meta/global": metaWBO.handler(),
    127    "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(),
    128  });
    129  await setUp(server);
    130 
    131  try {
    132    _("Enable engine locally.");
    133    engine.enabled = true;
    134 
    135    _("Sync.");
    136    await Service.sync();
    137 
    138    _("Meta record now contains the new engine.");
    139    Assert.ok(!!metaWBO.data.engines.steam);
    140 
    141    _("Engine continues to be enabled.");
    142    Assert.ok(engine.enabled);
    143  } finally {
    144    await Service.startOver();
    145    await promiseStopServer(server);
    146  }
    147 });
    148 
    149 add_task(async function test_disabledLocally() {
    150  enableValidationPrefs();
    151 
    152  _("Test: Engine is enabled on remote clients and disabled locally");
    153  Service.syncID = "abcdefghij";
    154  let engine = Service.engineManager.get("steam");
    155  let syncID = await engine.resetLocalSyncID();
    156  let metaWBO = new ServerWBO("global", {
    157    syncID: Service.syncID,
    158    storageVersion: STORAGE_VERSION,
    159    engines: { steam: { syncID, version: engine.version } },
    160  });
    161  let steamCollection = new ServerWBO("steam", PAYLOAD);
    162 
    163  let server = sync_httpd_setup({
    164    "/1.1/johndoe/storage/meta/global": metaWBO.handler(),
    165    "/1.1/johndoe/storage/steam": steamCollection.handler(),
    166  });
    167  await setUp(server);
    168 
    169  try {
    170    _("Disable engine locally.");
    171    Service._ignorePrefObserver = true;
    172    engine.enabled = true;
    173    Service._ignorePrefObserver = false;
    174    engine.enabled = false;
    175 
    176    _("Sync.");
    177    await Service.sync();
    178 
    179    _("Meta record no longer contains engine.");
    180    Assert.ok(!metaWBO.data.engines.steam);
    181 
    182    _("Server records are wiped.");
    183    Assert.equal(steamCollection.payload, undefined);
    184 
    185    _("Engine continues to be disabled.");
    186    Assert.ok(!engine.enabled);
    187  } finally {
    188    await Service.startOver();
    189    await promiseStopServer(server);
    190  }
    191 });
    192 
    193 add_task(async function test_disabledLocally_wipe503() {
    194  enableValidationPrefs();
    195 
    196  _("Test: Engine is enabled on remote clients and disabled locally");
    197  Service.syncID = "abcdefghij";
    198  let engine = Service.engineManager.get("steam");
    199  let syncID = await engine.resetLocalSyncID();
    200  let metaWBO = new ServerWBO("global", {
    201    syncID: Service.syncID,
    202    storageVersion: STORAGE_VERSION,
    203    engines: { steam: { syncID, version: engine.version } },
    204  });
    205 
    206  function service_unavailable(request, response) {
    207    let body = "Service Unavailable";
    208    response.setStatusLine(request.httpVersion, 503, "Service Unavailable");
    209    response.setHeader("Retry-After", "23");
    210    response.bodyOutputStream.write(body, body.length);
    211  }
    212 
    213  let server = sync_httpd_setup({
    214    "/1.1/johndoe/storage/meta/global": metaWBO.handler(),
    215    "/1.1/johndoe/storage/steam": service_unavailable,
    216  });
    217  await setUp(server);
    218 
    219  _("Disable engine locally.");
    220  Service._ignorePrefObserver = true;
    221  engine.enabled = true;
    222  Service._ignorePrefObserver = false;
    223  engine.enabled = false;
    224 
    225  _("Sync.");
    226  await Service.sync();
    227  Assert.equal(Service.status.sync, SERVER_MAINTENANCE);
    228 
    229  await Service.startOver();
    230  await promiseStopServer(server);
    231 });
    232 
    233 add_task(async function test_enabledRemotely() {
    234  enableValidationPrefs();
    235 
    236  _("Test: Engine is disabled locally and enabled on a remote client");
    237  Service.syncID = "abcdefghij";
    238  let engine = Service.engineManager.get("steam");
    239  let syncID = await engine.resetLocalSyncID();
    240  let metaWBO = new ServerWBO("global", {
    241    syncID: Service.syncID,
    242    storageVersion: STORAGE_VERSION,
    243    engines: { steam: { syncID, version: engine.version } },
    244  });
    245  let server = sync_httpd_setup({
    246    "/1.1/johndoe/storage/meta/global": upd("meta", metaWBO.handler()),
    247 
    248    "/1.1/johndoe/storage/steam": upd(
    249      "steam",
    250      new ServerWBO("steam", {}).handler()
    251    ),
    252  });
    253  await setUp(server);
    254 
    255  // We need to be very careful how we do this, so that we don't trigger a
    256  // fresh start!
    257  try {
    258    _("Upload some keys to avoid a fresh start.");
    259    let wbo = await Service.collectionKeys.generateNewKeysWBO();
    260    await wbo.encrypt(Service.identity.syncKeyBundle);
    261    Assert.equal(
    262      200,
    263      (await wbo.upload(Service.resource(Service.cryptoKeysURL))).status
    264    );
    265 
    266    _("Engine is disabled.");
    267    Assert.ok(!engine.enabled);
    268 
    269    _("Sync.");
    270    await Service.sync();
    271 
    272    _("Engine is enabled.");
    273    Assert.ok(engine.enabled);
    274 
    275    _("Meta record still present.");
    276    Assert.equal(metaWBO.data.engines.steam.syncID, await engine.getSyncID());
    277  } finally {
    278    await Service.startOver();
    279    await promiseStopServer(server);
    280  }
    281 });
    282 
    283 add_task(async function test_disabledRemotelyTwoClients() {
    284  enableValidationPrefs();
    285 
    286  _(
    287    "Test: Engine is enabled locally and disabled on a remote client... with two clients."
    288  );
    289  Service.syncID = "abcdefghij";
    290  let engine = Service.engineManager.get("steam");
    291  let metaWBO = new ServerWBO("global", {
    292    syncID: Service.syncID,
    293    storageVersion: STORAGE_VERSION,
    294    engines: {},
    295  });
    296  let server = sync_httpd_setup({
    297    "/1.1/johndoe/storage/meta/global": upd("meta", metaWBO.handler()),
    298 
    299    "/1.1/johndoe/storage/steam": upd(
    300      "steam",
    301      new ServerWBO("steam", {}).handler()
    302    ),
    303  });
    304  await setUp(server);
    305 
    306  try {
    307    _("Enable engine locally.");
    308    Service._ignorePrefObserver = true;
    309    engine.enabled = true;
    310    Service._ignorePrefObserver = false;
    311 
    312    _("Sync.");
    313    await Service.sync();
    314 
    315    _("Disable engine by deleting from meta/global.");
    316    let d = metaWBO.data;
    317    delete d.engines.steam;
    318    metaWBO.payload = JSON.stringify(d);
    319    metaWBO.modified = Date.now() / 1000;
    320 
    321    _("Add a second client and verify that the local pref is changed.");
    322    Service.clientsEngine._store._remoteClients.foobar = {
    323      name: "foobar",
    324      type: "desktop",
    325    };
    326    await Service.sync();
    327 
    328    _("Engine is disabled.");
    329    Assert.ok(!engine.enabled);
    330  } finally {
    331    await Service.startOver();
    332    await promiseStopServer(server);
    333  }
    334 });
    335 
    336 add_task(async function test_disabledRemotely() {
    337  enableValidationPrefs();
    338 
    339  _("Test: Engine is enabled locally and disabled on a remote client");
    340  Service.syncID = "abcdefghij";
    341  let engine = Service.engineManager.get("steam");
    342  let metaWBO = new ServerWBO("global", {
    343    syncID: Service.syncID,
    344    storageVersion: STORAGE_VERSION,
    345    engines: {},
    346  });
    347  let server = sync_httpd_setup({
    348    "/1.1/johndoe/storage/meta/global": metaWBO.handler(),
    349    "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(),
    350  });
    351  await setUp(server);
    352 
    353  try {
    354    _("Enable engine locally.");
    355    Service._ignorePrefObserver = true;
    356    engine.enabled = true;
    357    Service._ignorePrefObserver = false;
    358 
    359    _("Sync.");
    360    await Service.sync();
    361 
    362    _("Engine is not disabled: only one client.");
    363    Assert.ok(engine.enabled);
    364  } finally {
    365    await Service.startOver();
    366    await promiseStopServer(server);
    367  }
    368 });
    369 
    370 add_task(async function test_dependentEnginesEnabledLocally() {
    371  enableValidationPrefs();
    372 
    373  _("Test: Engine is disabled on remote clients and enabled locally");
    374  Service.syncID = "abcdefghij";
    375  let steamEngine = Service.engineManager.get("steam");
    376  let stirlingEngine = Service.engineManager.get("stirling");
    377  let metaWBO = new ServerWBO("global", {
    378    syncID: Service.syncID,
    379    storageVersion: STORAGE_VERSION,
    380    engines: {},
    381  });
    382  let server = sync_httpd_setup({
    383    "/1.1/johndoe/storage/meta/global": metaWBO.handler(),
    384    "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(),
    385    "/1.1/johndoe/storage/stirling": new ServerWBO("stirling", {}).handler(),
    386  });
    387  await setUp(server);
    388 
    389  try {
    390    _("Enable engine locally. Doing it on one is enough.");
    391    steamEngine.enabled = true;
    392 
    393    _("Sync.");
    394    await Service.sync();
    395 
    396    _("Meta record now contains the new engines.");
    397    Assert.ok(!!metaWBO.data.engines.steam);
    398    Assert.ok(!!metaWBO.data.engines.stirling);
    399 
    400    _("Engines continue to be enabled.");
    401    Assert.ok(steamEngine.enabled);
    402    Assert.ok(stirlingEngine.enabled);
    403  } finally {
    404    await Service.startOver();
    405    await promiseStopServer(server);
    406  }
    407 });
    408 
    409 add_task(async function test_dependentEnginesDisabledLocally() {
    410  enableValidationPrefs();
    411 
    412  _(
    413    "Test: Two dependent engines are enabled on remote clients and disabled locally"
    414  );
    415  Service.syncID = "abcdefghij";
    416  let steamEngine = Service.engineManager.get("steam");
    417  let steamSyncID = await steamEngine.resetLocalSyncID();
    418  let stirlingEngine = Service.engineManager.get("stirling");
    419  let stirlingSyncID = await stirlingEngine.resetLocalSyncID();
    420  let metaWBO = new ServerWBO("global", {
    421    syncID: Service.syncID,
    422    storageVersion: STORAGE_VERSION,
    423    engines: {
    424      steam: { syncID: steamSyncID, version: steamEngine.version },
    425      stirling: { syncID: stirlingSyncID, version: stirlingEngine.version },
    426    },
    427  });
    428 
    429  let steamCollection = new ServerWBO("steam", PAYLOAD);
    430  let stirlingCollection = new ServerWBO("stirling", PAYLOAD);
    431 
    432  let server = sync_httpd_setup({
    433    "/1.1/johndoe/storage/meta/global": metaWBO.handler(),
    434    "/1.1/johndoe/storage/steam": steamCollection.handler(),
    435    "/1.1/johndoe/storage/stirling": stirlingCollection.handler(),
    436  });
    437  await setUp(server);
    438 
    439  try {
    440    _("Disable engines locally. Doing it on one is enough.");
    441    Service._ignorePrefObserver = true;
    442    steamEngine.enabled = true;
    443    Assert.ok(stirlingEngine.enabled);
    444    Service._ignorePrefObserver = false;
    445    steamEngine.enabled = false;
    446    Assert.ok(!stirlingEngine.enabled);
    447 
    448    _("Sync.");
    449    await Service.sync();
    450 
    451    _("Meta record no longer contains engines.");
    452    Assert.ok(!metaWBO.data.engines.steam);
    453    Assert.ok(!metaWBO.data.engines.stirling);
    454 
    455    _("Server records are wiped.");
    456    Assert.equal(steamCollection.payload, undefined);
    457    Assert.equal(stirlingCollection.payload, undefined);
    458 
    459    _("Engines continue to be disabled.");
    460    Assert.ok(!steamEngine.enabled);
    461    Assert.ok(!stirlingEngine.enabled);
    462  } finally {
    463    await Service.startOver();
    464    await promiseStopServer(server);
    465  }
    466 });
    467 
    468 add_task(async function test_service_updateLocalEnginesState() {
    469  Service.syncID = "abcdefghij";
    470  const engine = Service.engineManager.get("steam");
    471  const metaWBO = new ServerWBO("global", {
    472    syncID: Service.syncID,
    473    storageVersion: STORAGE_VERSION,
    474    declined: ["steam"],
    475    engines: {},
    476  });
    477  const server = httpd_setup({
    478    "/1.1/johndoe/storage/meta/global": metaWBO.handler(),
    479  });
    480  await SyncTestingInfrastructure(server, "johndoe");
    481 
    482  // Disconnect sync.
    483  await Service.startOver();
    484  Service._ignorePrefObserver = true;
    485  // Steam engine is enabled on our machine.
    486  engine.enabled = true;
    487  Service._ignorePrefObserver = false;
    488  Service.identity._findCluster = () => server.baseURI + "/1.1/johndoe/";
    489 
    490  // Update engine state from the server.
    491  await Service.updateLocalEnginesState();
    492  // Now disabled.
    493  Assert.ok(!engine.enabled);
    494 });
    495 
    496 add_task(async function test_service_enableAfterUpdateState() {
    497  Service.syncID = "abcdefghij";
    498  const engine = Service.engineManager.get("steam");
    499  const metaWBO = new ServerWBO("global", {
    500    syncID: Service.syncID,
    501    storageVersion: STORAGE_VERSION,
    502    declined: ["steam"],
    503    engines: { someengine: {} },
    504  });
    505  const server = httpd_setup({
    506    "/1.1/johndoe/storage/meta/global": metaWBO.handler(),
    507  });
    508  await SyncTestingInfrastructure(server, "johndoe");
    509 
    510  // Disconnect sync.
    511  await Service.startOver();
    512  Service.identity._findCluster = () => server.baseURI + "/1.1/johndoe/";
    513 
    514  // Update engine state from the server.
    515  await Service.updateLocalEnginesState();
    516  // Now disabled, reflecting what's on the server.
    517  Assert.ok(!engine.enabled);
    518  // Enable the engine, as though the user selected it via CWTS.
    519  engine.enabled = true;
    520 
    521  // Do the "reconcile local and remote states" dance.
    522  let engineSync = new EngineSynchronizer(Service);
    523  await engineSync._updateEnabledEngines();
    524  await Service._maybeUpdateDeclined();
    525  // engine should remain enabled.
    526  Assert.ok(engine.enabled);
    527  // engine should no longer appear in declined on the server.
    528  Assert.deepEqual(metaWBO.data.declined, []);
    529 });
    530 
    531 add_task(async function test_service_disableAfterUpdateState() {
    532  Service.syncID = "abcdefghij";
    533  const engine = Service.engineManager.get("steam");
    534  const metaWBO = new ServerWBO("global", {
    535    syncID: Service.syncID,
    536    storageVersion: STORAGE_VERSION,
    537    declined: [],
    538    engines: { steam: {} },
    539  });
    540  const server = httpd_setup({
    541    "/1.1/johndoe/storage/meta/global": metaWBO.handler(),
    542  });
    543  await SyncTestingInfrastructure(server, "johndoe");
    544 
    545  // Disconnect sync.
    546  await Service.startOver();
    547  Service.identity._findCluster = () => server.baseURI + "/1.1/johndoe/";
    548 
    549  // Update engine state from the server.
    550  await Service.updateLocalEnginesState();
    551  // Now enabled, reflecting what's on the server.
    552  Assert.ok(engine.enabled);
    553  // Disable the engine, as though via CWTS.
    554  engine.enabled = false;
    555 
    556  // Do the "reconcile local and remote states" dance.
    557  let engineSync = new EngineSynchronizer(Service);
    558  await engineSync._updateEnabledEngines();
    559  await Service._maybeUpdateDeclined();
    560  // engine should remain disabled.
    561  Assert.ok(!engine.enabled);
    562  // engine should now appear in declined on the server.
    563  Assert.deepEqual(metaWBO.data.declined, ["steam"]);
    564  // and should have been removed from engines.
    565  Assert.deepEqual(metaWBO.data.engines, {});
    566 });
    567 
    568 add_task(async function test_service_updateLocalEnginesState_no_meta_global() {
    569  Service.syncID = "abcdefghij";
    570  const engine = Service.engineManager.get("steam");
    571  // The server doesn't contain /meta/global (sync was never enabled).
    572  const server = httpd_setup({});
    573  await SyncTestingInfrastructure(server, "johndoe");
    574 
    575  // Disconnect sync.
    576  await Service.startOver();
    577  Service._ignorePrefObserver = true;
    578  // Steam engine is enabled on our machine.
    579  engine.enabled = true;
    580  Service._ignorePrefObserver = false;
    581  Service.identity._findCluster = () => server.baseURI + "/1.1/johndoe/";
    582 
    583  // Update engine state from the server.
    584  await Service.updateLocalEnginesState();
    585  // Still enabled.
    586  Assert.ok(engine.enabled);
    587 });