tor-browser

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

test_prefs_store.js (14045B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 const { PromiseTestUtils } = ChromeUtils.importESModule(
      5  "resource://testing-common/PromiseTestUtils.sys.mjs"
      6 );
      7 PromiseTestUtils.allowMatchingRejectionsGlobally(
      8  /Unable to arm timer, the object has been finalized\./
      9 );
     10 PromiseTestUtils.allowMatchingRejectionsGlobally(
     11  /IOUtils\.profileBeforeChange getter: IOUtils: profileBeforeChange phase has already finished/
     12 );
     13 
     14 const { PrefRec, getPrefsGUIDForTest } = ChromeUtils.importESModule(
     15  "resource://services-sync/engines/prefs.sys.mjs"
     16 );
     17 const PREFS_GUID = getPrefsGUIDForTest();
     18 const { Service } = ChromeUtils.importESModule(
     19  "resource://services-sync/service.sys.mjs"
     20 );
     21 
     22 const DEFAULT_THEME_ID = "default-theme@mozilla.org";
     23 const COMPACT_THEME_ID = "firefox-compact-light@mozilla.org";
     24 
     25 AddonTestUtils.init(this);
     26 AddonTestUtils.createAppInfo(
     27  "xpcshell@tests.mozilla.org",
     28  "XPCShell",
     29  "1",
     30  "1.9.2"
     31 );
     32 AddonTestUtils.overrideCertDB();
     33 
     34 let prefsWithUserValue = new Set();
     35 add_setup(function record_prefsWithUserValue() {
     36  for (const pref of Services.prefs.getChildList("")) {
     37    if (Services.prefs.prefHasUserValue(pref)) {
     38      prefsWithUserValue.add(pref);
     39    }
     40  }
     41 });
     42 
     43 function clearValues() {
     44  for (const pref of Services.prefs.getChildList("")) {
     45    if (!prefsWithUserValue.has(pref)) {
     46      Services.prefs.clearUserPref(pref);
     47    }
     48  }
     49 }
     50 
     51 add_task(async function run_test() {
     52  _("Test fixtures.");
     53  // Part of this test ensures the default theme, via the preference
     54  // extensions.activeThemeID, is synced correctly - so we do a little
     55  // addons initialization to allow this to work.
     56 
     57  // Enable application scopes to ensure the builtin theme is going to
     58  // be installed as part of the the addon manager startup.
     59  Services.prefs.setIntPref(
     60    "extensions.enabledScopes",
     61    AddonManager.SCOPE_APPLICATION
     62  );
     63  await AddonTestUtils.promiseStartupManager();
     64 
     65  // Install another built-in theme.
     66  await AddonManager.installBuiltinAddon("resource://builtin-themes/light/");
     67 
     68  const defaultThemeAddon = await AddonManager.getAddonByID(DEFAULT_THEME_ID);
     69  ok(defaultThemeAddon, "Got an addon wrapper for the default theme");
     70 
     71  const otherThemeAddon = await AddonManager.getAddonByID(COMPACT_THEME_ID);
     72  ok(otherThemeAddon, "Got an addon wrapper for the compact theme");
     73 
     74  await otherThemeAddon.enable();
     75 
     76  // read our custom prefs file before doing anything.
     77  Services.prefs.readDefaultPrefsFromFile(
     78    do_get_file("prefs_test_prefs_store.js")
     79  );
     80 
     81  let engine = Service.engineManager.get("prefs");
     82  let store = engine._store;
     83  try {
     84    _("Expect the compact light theme to be active");
     85    Assert.strictEqual(
     86      Services.prefs.getStringPref("extensions.activeThemeID"),
     87      COMPACT_THEME_ID
     88    );
     89 
     90    _("The GUID corresponds to XUL App ID.");
     91    let allIDs = await store.getAllIDs();
     92    let ids = Object.keys(allIDs);
     93    Assert.equal(ids.length, 1);
     94    Assert.equal(ids[0], PREFS_GUID);
     95    Assert.ok(allIDs[PREFS_GUID]);
     96 
     97    Assert.ok(await store.itemExists(PREFS_GUID));
     98    Assert.equal(false, await store.itemExists("random-gibberish"));
     99 
    100    _("Unknown prefs record is created as deleted.");
    101    let record = await store.createRecord("random-gibberish", "prefs");
    102    Assert.ok(record.deleted);
    103 
    104    _("Prefs record contains only prefs that should be synced.");
    105    record = await store.createRecord(PREFS_GUID, "prefs");
    106    Assert.strictEqual(record.value["testing.int"], 123);
    107    Assert.strictEqual(record.value["testing.string"], "ohai");
    108    Assert.strictEqual(record.value["testing.bool"], true);
    109    // non-existing prefs get null as the value
    110    Assert.strictEqual(record.value["testing.nonexistent"], null);
    111    // as do prefs that have a default value.
    112    Assert.strictEqual(record.value["testing.default"], null);
    113    Assert.strictEqual(record.value["testing.turned.off"], undefined);
    114    Assert.strictEqual(record.value["testing.not.turned.on"], undefined);
    115 
    116    _("Prefs record contains the correct control prefs.");
    117    // All control prefs which have the default value and where the pref
    118    // itself is synced should appear, but with null as the value.
    119    Assert.strictEqual(
    120      record.value["services.sync.prefs.sync.testing.int"],
    121      null
    122    );
    123    Assert.strictEqual(
    124      record.value["services.sync.prefs.sync.testing.string"],
    125      null
    126    );
    127    Assert.strictEqual(
    128      record.value["services.sync.prefs.sync.testing.bool"],
    129      null
    130    );
    131    Assert.strictEqual(
    132      record.value["services.sync.prefs.sync.testing.dont.change"],
    133      null
    134    );
    135    Assert.strictEqual(
    136      record.value["services.sync.prefs.sync.testing.nonexistent"],
    137      null
    138    );
    139    Assert.strictEqual(
    140      record.value["services.sync.prefs.sync.testing.default"],
    141      null
    142    );
    143 
    144    // but this control pref has a non-default value so that value is synced.
    145    Assert.strictEqual(
    146      record.value["services.sync.prefs.sync.testing.turned.off"],
    147      false
    148    );
    149 
    150    _("Unsyncable prefs are treated correctly.");
    151    // Prefs we consider unsyncable (since they are URLs that won't be stable on
    152    // another firefox) shouldn't be included - neither the value nor the
    153    // control pref should appear.
    154    Assert.strictEqual(record.value["testing.unsynced.url"], undefined);
    155    Assert.strictEqual(
    156      record.value["services.sync.prefs.sync.testing.unsynced.url"],
    157      undefined
    158    );
    159    // Other URLs with user prefs should be synced, though.
    160    Assert.strictEqual(
    161      record.value["testing.synced.url"],
    162      "https://www.example.com"
    163    );
    164    Assert.strictEqual(
    165      record.value["services.sync.prefs.sync.testing.synced.url"],
    166      null
    167    );
    168 
    169    _("Update some prefs, including one that's to be reset/deleted.");
    170    // This pref is not going to be reset or deleted as there's no "control pref"
    171    // in either the incoming record or locally.
    172    Services.prefs.setStringPref(
    173      "testing.deleted-without-control-pref",
    174      "I'm deleted-without-control-pref"
    175    );
    176    // Another pref with only a local control pref.
    177    Services.prefs.setStringPref(
    178      "testing.deleted-with-local-control-pref",
    179      "I'm deleted-with-local-control-pref"
    180    );
    181    Services.prefs.setBoolPref(
    182      "services.sync.prefs.sync.testing.deleted-with-local-control-pref",
    183      true
    184    );
    185    // And a pref without a local control pref but one that's incoming.
    186    Services.prefs.setStringPref(
    187      "testing.deleted-with-incoming-control-pref",
    188      "I'm deleted-with-incoming-control-pref"
    189    );
    190    record = new PrefRec("prefs", PREFS_GUID);
    191    record.value = {
    192      "extensions.activeThemeID": DEFAULT_THEME_ID,
    193      "testing.int": 42,
    194      "testing.string": "im in ur prefs",
    195      "testing.bool": false,
    196      "testing.deleted-without-control-pref": null,
    197      "testing.deleted-with-local-control-pref": null,
    198      "testing.deleted-with-incoming-control-pref": null,
    199      "services.sync.prefs.sync.testing.deleted-with-incoming-control-pref": true,
    200      "testing.somepref": "im a new pref from other device",
    201      "services.sync.prefs.sync.testing.somepref": true,
    202      // Pretend some a stale remote client is overwriting it with a value
    203      // we consider unsyncable.
    204      "testing.synced.url": "blob:ebeb707a-502e-40c6-97a5-dd4bda901463",
    205      // Make sure we can replace the unsynced URL with a valid URL.
    206      "testing.unsynced.url": "https://www.example.com/2",
    207      // Make sure our "master control pref" is ignored.
    208      "services.sync.prefs.dangerously_allow_arbitrary": true,
    209      "services.sync.prefs.sync.services.sync.prefs.dangerously_allow_arbitrary": true,
    210    };
    211 
    212    const onceAddonEnabled = AddonTestUtils.promiseAddonEvent("onEnabled");
    213 
    214    await store.update(record);
    215    Assert.strictEqual(Services.prefs.getIntPref("testing.int"), 42);
    216    Assert.strictEqual(
    217      Services.prefs.getStringPref("testing.string"),
    218      "im in ur prefs"
    219    );
    220    Assert.strictEqual(Services.prefs.getBoolPref("testing.bool"), false);
    221    Assert.strictEqual(
    222      Services.prefs.getStringPref("testing.deleted-without-control-pref"),
    223      "I'm deleted-without-control-pref"
    224    );
    225    Assert.strictEqual(
    226      Services.prefs.getPrefType("testing.deleted-with-local-control-pref"),
    227      Ci.nsIPrefBranch.PREF_INVALID
    228    );
    229    Assert.strictEqual(
    230      Services.prefs.getStringPref(
    231        "testing.deleted-with-incoming-control-pref"
    232      ),
    233      "I'm deleted-with-incoming-control-pref"
    234    );
    235    Assert.strictEqual(
    236      Services.prefs.getStringPref("testing.dont.change"),
    237      "Please don't change me."
    238    );
    239    Assert.strictEqual(
    240      Services.prefs.getPrefType("testing.somepref"),
    241      Ci.nsIPrefBranch.PREF_INVALID
    242    );
    243    Assert.strictEqual(
    244      Services.prefs.getStringPref("testing.synced.url"),
    245      "https://www.example.com"
    246    );
    247    Assert.strictEqual(
    248      Services.prefs.getStringPref("testing.unsynced.url"),
    249      "https://www.example.com/2"
    250    );
    251    Assert.strictEqual(
    252      Svc.PrefBranch.getPrefType("prefs.sync.testing.somepref"),
    253      Ci.nsIPrefBranch.PREF_INVALID
    254    );
    255    Assert.strictEqual(
    256      Services.prefs.getBoolPref(
    257        "services.sync.prefs.dangerously_allow_arbitrary"
    258      ),
    259      false
    260    );
    261    Assert.strictEqual(
    262      Services.prefs.getPrefType(
    263        "services.sync.prefs.sync.services.sync.prefs.dangerously_allow_arbitrary"
    264      ),
    265      Ci.nsIPrefBranch.PREF_INVALID
    266    );
    267 
    268    await onceAddonEnabled;
    269    ok(
    270      !defaultThemeAddon.userDisabled,
    271      "the default theme should have been enabled"
    272    );
    273    ok(
    274      otherThemeAddon.userDisabled,
    275      "the compact theme should have been disabled"
    276    );
    277 
    278    _("Only the current app's preferences are applied.");
    279    record = new PrefRec("prefs", "some-fake-app");
    280    record.value = {
    281      "testing.int": 98,
    282    };
    283    await store.update(record);
    284    Assert.equal(Services.prefs.getIntPref("testing.int"), 42);
    285  } finally {
    286    clearValues();
    287  }
    288 });
    289 
    290 add_task(async function test_dangerously_allow() {
    291  _("services.sync.prefs.dangerously_allow_arbitrary");
    292  // Bug 1538015 added a capability to "dangerously allow" arbitrary prefs.
    293  // Bug 1854698 removed that capability but did keep the fact we never
    294  // sync the pref which enabled the "dangerous" behaviour, just incase someone
    295  // tries to sync it back to a profile which *does* support that pref.
    296  Services.prefs.readDefaultPrefsFromFile(
    297    do_get_file("prefs_test_prefs_store.js")
    298  );
    299 
    300  let engine = Service.engineManager.get("prefs");
    301  let store = engine._store;
    302  try {
    303    // an incoming record with our old "dangerous" pref.
    304    let record = new PrefRec("prefs", PREFS_GUID);
    305    record.value = {
    306      "services.sync.prefs.dangerously_allow_arbitrary": true,
    307      "services.sync.prefs.sync.services.sync.prefs.dangerously_allow_arbitrary": true,
    308    };
    309    await store.update(record);
    310    Assert.strictEqual(
    311      Services.prefs.getBoolPref(
    312        "services.sync.prefs.dangerously_allow_arbitrary"
    313      ),
    314      false
    315    );
    316    Assert.strictEqual(
    317      Services.prefs.getPrefType(
    318        "services.sync.prefs.sync.services.sync.prefs.dangerously_allow_arbitrary"
    319      ),
    320      Ci.nsIPrefBranch.PREF_INVALID
    321    );
    322  } finally {
    323    clearValues();
    324  }
    325 });
    326 
    327 add_task(async function test_incoming_sets_seen() {
    328  _("Test the sync-seen allow-list");
    329 
    330  let engine = Service.engineManager.get("prefs");
    331  let store = engine._store;
    332 
    333  Services.prefs.readDefaultPrefsFromFile(
    334    do_get_file("prefs_test_prefs_store.js")
    335  );
    336  const defaultValue = "the value";
    337  Assert.equal(Services.prefs.getStringPref("testing.seen"), defaultValue);
    338 
    339  let record = await store.createRecord(PREFS_GUID, "prefs");
    340  // Haven't seen a non-default value before, so remains null.
    341  Assert.strictEqual(record.value["testing.seen"], null);
    342 
    343  // pretend an incoming record with the default value - it might not be
    344  // the default everywhere, so we treat it specially.
    345  record = new PrefRec("prefs", PREFS_GUID);
    346  record.value = {
    347    "testing.seen": defaultValue,
    348  };
    349  await store.update(record);
    350  // Our special control value should now be set.
    351  Assert.strictEqual(
    352    Services.prefs.getBoolPref("services.sync.prefs.sync-seen.testing.seen"),
    353    true
    354  );
    355  // It's still the default value, so the value is not considered changed
    356  Assert.equal(Services.prefs.prefHasUserValue("testing.seen"), false);
    357 
    358  // But now that special control value is set, the record always contains the value.
    359  record = await store.createRecord(PREFS_GUID, "prefs");
    360  Assert.strictEqual(record.value["testing.seen"], defaultValue);
    361 });
    362 
    363 add_task(async function test_outgoing_when_changed() {
    364  _("Test the 'seen' pref is set first sync of non-default value");
    365 
    366  let engine = Service.engineManager.get("prefs");
    367  let store = engine._store;
    368  clearValues();
    369 
    370  Services.prefs.readDefaultPrefsFromFile(
    371    do_get_file("prefs_test_prefs_store.js")
    372  );
    373  const defaultValue = "the value";
    374  Assert.equal(Services.prefs.getStringPref("testing.seen"), defaultValue);
    375 
    376  let record = await store.createRecord(PREFS_GUID, "prefs");
    377  // Haven't seen a non-default value before, so remains null.
    378  Assert.strictEqual(record.value["testing.seen"], null);
    379 
    380  // Change the value.
    381  Services.prefs.setStringPref("testing.seen", "new value");
    382  record = await store.createRecord(PREFS_GUID, "prefs");
    383  // creating the record toggled that "seen" pref.
    384  Assert.strictEqual(
    385    Services.prefs.getBoolPref("services.sync.prefs.sync-seen.testing.seen"),
    386    true
    387  );
    388  Assert.strictEqual(Services.prefs.getStringPref("testing.seen"), "new value");
    389 
    390  // Resetting the pref does not change that seen value.
    391  Services.prefs.clearUserPref("testing.seen");
    392  Assert.strictEqual(
    393    Services.prefs.getStringPref("testing.seen"),
    394    defaultValue
    395  );
    396 
    397  record = await store.createRecord(PREFS_GUID, "prefs");
    398  Assert.strictEqual(
    399    Services.prefs.getBoolPref("services.sync.prefs.sync-seen.testing.seen"),
    400    true
    401  );
    402 });