From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- services/sync/tests/unit/test_prefs_store.js | 414 +++++++++++++++++++++++++++ 1 file changed, 414 insertions(+) create mode 100644 services/sync/tests/unit/test_prefs_store.js (limited to 'services/sync/tests/unit/test_prefs_store.js') diff --git a/services/sync/tests/unit/test_prefs_store.js b/services/sync/tests/unit/test_prefs_store.js new file mode 100644 index 0000000000..23ee9f3a72 --- /dev/null +++ b/services/sync/tests/unit/test_prefs_store.js @@ -0,0 +1,414 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { PromiseTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PromiseTestUtils.sys.mjs" +); +PromiseTestUtils.allowMatchingRejectionsGlobally( + /Unable to arm timer, the object has been finalized\./ +); +PromiseTestUtils.allowMatchingRejectionsGlobally( + /IOUtils\.profileBeforeChange getter: IOUtils: profileBeforeChange phase has already finished/ +); + +const { Preferences } = ChromeUtils.importESModule( + "resource://gre/modules/Preferences.sys.mjs" +); +const { PrefRec, getPrefsGUIDForTest } = ChromeUtils.importESModule( + "resource://services-sync/engines/prefs.sys.mjs" +); +const PREFS_GUID = getPrefsGUIDForTest(); +const { Service } = ChromeUtils.importESModule( + "resource://services-sync/service.sys.mjs" +); + +const DEFAULT_THEME_ID = "default-theme@mozilla.org"; +const COMPACT_THEME_ID = "firefox-compact-light@mozilla.org"; + +AddonTestUtils.init(this); +AddonTestUtils.createAppInfo( + "xpcshell@tests.mozilla.org", + "XPCShell", + "1", + "1.9.2" +); +AddonTestUtils.overrideCertDB(); + +add_task(async function run_test() { + _("Test fixtures."); + // Part of this test ensures the default theme, via the preference + // extensions.activeThemeID, is synced correctly - so we do a little + // addons initialization to allow this to work. + + // Enable application scopes to ensure the builtin theme is going to + // be installed as part of the the addon manager startup. + Preferences.set("extensions.enabledScopes", AddonManager.SCOPE_APPLICATION); + await AddonTestUtils.promiseStartupManager(); + + // Install another built-in theme. + await AddonManager.installBuiltinAddon("resource://builtin-themes/light/"); + + const defaultThemeAddon = await AddonManager.getAddonByID(DEFAULT_THEME_ID); + ok(defaultThemeAddon, "Got an addon wrapper for the default theme"); + + const otherThemeAddon = await AddonManager.getAddonByID(COMPACT_THEME_ID); + ok(otherThemeAddon, "Got an addon wrapper for the compact theme"); + + await otherThemeAddon.enable(); + + // read our custom prefs file before doing anything. + Services.prefs.readDefaultPrefsFromFile( + do_get_file("prefs_test_prefs_store.js") + ); + + let engine = Service.engineManager.get("prefs"); + let store = engine._store; + let prefs = new Preferences(); + try { + _("Expect the compact light theme to be active"); + Assert.strictEqual(prefs.get("extensions.activeThemeID"), COMPACT_THEME_ID); + + _("The GUID corresponds to XUL App ID."); + let allIDs = await store.getAllIDs(); + let ids = Object.keys(allIDs); + Assert.equal(ids.length, 1); + Assert.equal(ids[0], PREFS_GUID); + Assert.ok(allIDs[PREFS_GUID]); + + Assert.ok(await store.itemExists(PREFS_GUID)); + Assert.equal(false, await store.itemExists("random-gibberish")); + + _("Unknown prefs record is created as deleted."); + let record = await store.createRecord("random-gibberish", "prefs"); + Assert.ok(record.deleted); + + _("Prefs record contains only prefs that should be synced."); + record = await store.createRecord(PREFS_GUID, "prefs"); + Assert.strictEqual(record.value["testing.int"], 123); + Assert.strictEqual(record.value["testing.string"], "ohai"); + Assert.strictEqual(record.value["testing.bool"], true); + // non-existing prefs get null as the value + Assert.strictEqual(record.value["testing.nonexistent"], null); + // as do prefs that have a default value. + Assert.strictEqual(record.value["testing.default"], null); + Assert.strictEqual(record.value["testing.turned.off"], undefined); + Assert.strictEqual(record.value["testing.not.turned.on"], undefined); + + _("Prefs record contains the correct control prefs."); + // All control prefs which have the default value and where the pref + // itself is synced should appear, but with null as the value. + Assert.strictEqual( + record.value["services.sync.prefs.sync.testing.int"], + null + ); + Assert.strictEqual( + record.value["services.sync.prefs.sync.testing.string"], + null + ); + Assert.strictEqual( + record.value["services.sync.prefs.sync.testing.bool"], + null + ); + Assert.strictEqual( + record.value["services.sync.prefs.sync.testing.dont.change"], + null + ); + Assert.strictEqual( + record.value["services.sync.prefs.sync.testing.nonexistent"], + null + ); + Assert.strictEqual( + record.value["services.sync.prefs.sync.testing.default"], + null + ); + + // but this control pref has a non-default value so that value is synced. + Assert.strictEqual( + record.value["services.sync.prefs.sync.testing.turned.off"], + false + ); + + _("Unsyncable prefs are treated correctly."); + // Prefs we consider unsyncable (since they are URLs that won't be stable on + // another firefox) shouldn't be included - neither the value nor the + // control pref should appear. + Assert.strictEqual(record.value["testing.unsynced.url"], undefined); + Assert.strictEqual( + record.value["services.sync.prefs.sync.testing.unsynced.url"], + undefined + ); + // Other URLs with user prefs should be synced, though. + Assert.strictEqual( + record.value["testing.synced.url"], + "https://www.example.com" + ); + Assert.strictEqual( + record.value["services.sync.prefs.sync.testing.synced.url"], + null + ); + + _("Update some prefs, including one that's to be reset/deleted."); + // This pref is not going to be reset or deleted as there's no "control pref" + // in either the incoming record or locally. + prefs.set( + "testing.deleted-without-control-pref", + "I'm deleted-without-control-pref" + ); + // Another pref with only a local control pref. + prefs.set( + "testing.deleted-with-local-control-pref", + "I'm deleted-with-local-control-pref" + ); + prefs.set( + "services.sync.prefs.sync.testing.deleted-with-local-control-pref", + true + ); + // And a pref without a local control pref but one that's incoming. + prefs.set( + "testing.deleted-with-incoming-control-pref", + "I'm deleted-with-incoming-control-pref" + ); + record = new PrefRec("prefs", PREFS_GUID); + record.value = { + "extensions.activeThemeID": DEFAULT_THEME_ID, + "testing.int": 42, + "testing.string": "im in ur prefs", + "testing.bool": false, + "testing.deleted-without-control-pref": null, + "testing.deleted-with-local-control-pref": null, + "testing.deleted-with-incoming-control-pref": null, + "services.sync.prefs.sync.testing.deleted-with-incoming-control-pref": true, + "testing.somepref": "im a new pref from other device", + "services.sync.prefs.sync.testing.somepref": true, + // Pretend some a stale remote client is overwriting it with a value + // we consider unsyncable. + "testing.synced.url": "blob:ebeb707a-502e-40c6-97a5-dd4bda901463", + // Make sure we can replace the unsynced URL with a valid URL. + "testing.unsynced.url": "https://www.example.com/2", + // Make sure our "master control pref" is ignored. + "services.sync.prefs.dangerously_allow_arbitrary": true, + "services.sync.prefs.sync.services.sync.prefs.dangerously_allow_arbitrary": true, + }; + + const onceAddonEnabled = AddonTestUtils.promiseAddonEvent("onEnabled"); + + await store.update(record); + Assert.strictEqual(prefs.get("testing.int"), 42); + Assert.strictEqual(prefs.get("testing.string"), "im in ur prefs"); + Assert.strictEqual(prefs.get("testing.bool"), false); + Assert.strictEqual( + prefs.get("testing.deleted-without-control-pref"), + "I'm deleted-without-control-pref" + ); + Assert.strictEqual( + prefs.get("testing.deleted-with-local-control-pref"), + undefined + ); + Assert.strictEqual( + prefs.get("testing.deleted-with-incoming-control-pref"), + "I'm deleted-with-incoming-control-pref" + ); + Assert.strictEqual( + prefs.get("testing.dont.change"), + "Please don't change me." + ); + Assert.strictEqual(prefs.get("testing.somepref"), undefined); + Assert.strictEqual( + prefs.get("testing.synced.url"), + "https://www.example.com" + ); + Assert.strictEqual( + prefs.get("testing.unsynced.url"), + "https://www.example.com/2" + ); + Assert.strictEqual(Svc.Prefs.get("prefs.sync.testing.somepref"), undefined); + Assert.strictEqual( + prefs.get("services.sync.prefs.dangerously_allow_arbitrary"), + false + ); + Assert.strictEqual( + prefs.get( + "services.sync.prefs.sync.services.sync.prefs.dangerously_allow_arbitrary" + ), + undefined + ); + + await onceAddonEnabled; + ok( + !defaultThemeAddon.userDisabled, + "the default theme should have been enabled" + ); + ok( + otherThemeAddon.userDisabled, + "the compact theme should have been disabled" + ); + + _("Only the current app's preferences are applied."); + record = new PrefRec("prefs", "some-fake-app"); + record.value = { + "testing.int": 98, + }; + await store.update(record); + Assert.equal(prefs.get("testing.int"), 42); + } finally { + prefs.resetBranch(""); + } +}); + +add_task(async function test_dangerously_allow() { + _("services.sync.prefs.dangerously_allow_arbitrary"); + // read our custom prefs file before doing anything. + Services.prefs.readDefaultPrefsFromFile( + do_get_file("prefs_test_prefs_store.js") + ); + // configure so that arbitrary prefs are synced. + Services.prefs.setBoolPref( + "services.sync.prefs.dangerously_allow_arbitrary", + true + ); + + let engine = Service.engineManager.get("prefs"); + let store = engine._store; + let prefs = new Preferences(); + try { + _("Update some prefs"); + // This pref is not going to be reset or deleted as there's no "control pref" + // in either the incoming record or locally. + prefs.set( + "testing.deleted-without-control-pref", + "I'm deleted-without-control-pref" + ); + // Another pref with only a local control pref. + prefs.set( + "testing.deleted-with-local-control-pref", + "I'm deleted-with-local-control-pref" + ); + prefs.set( + "services.sync.prefs.sync.testing.deleted-with-local-control-pref", + true + ); + // And a pref without a local control pref but one that's incoming. + prefs.set( + "testing.deleted-with-incoming-control-pref", + "I'm deleted-with-incoming-control-pref" + ); + let record = new PrefRec("prefs", PREFS_GUID); + record.value = { + "testing.deleted-without-control-pref": null, + "testing.deleted-with-local-control-pref": null, + "testing.deleted-with-incoming-control-pref": null, + "services.sync.prefs.sync.testing.deleted-with-incoming-control-pref": true, + "testing.somepref": "im a new pref from other device", + "services.sync.prefs.sync.testing.somepref": true, + // Make sure our "master control pref" is ignored, even when it's already set. + "services.sync.prefs.dangerously_allow_arbitrary": false, + "services.sync.prefs.sync.services.sync.prefs.dangerously_allow_arbitrary": true, + }; + await store.update(record); + Assert.strictEqual( + prefs.get("testing.deleted-without-control-pref"), + "I'm deleted-without-control-pref" + ); + Assert.strictEqual( + prefs.get("testing.deleted-with-local-control-pref"), + undefined + ); + Assert.strictEqual( + prefs.get("testing.deleted-with-incoming-control-pref"), + undefined + ); + Assert.strictEqual( + prefs.get("testing.somepref"), + "im a new pref from other device" + ); + Assert.strictEqual(Svc.Prefs.get("prefs.sync.testing.somepref"), true); + Assert.strictEqual( + prefs.get("services.sync.prefs.dangerously_allow_arbitrary"), + true + ); + Assert.strictEqual( + prefs.get( + "services.sync.prefs.sync.services.sync.prefs.dangerously_allow_arbitrary" + ), + undefined + ); + } finally { + prefs.resetBranch(""); + } +}); + +add_task(async function test_incoming_sets_seen() { + _("Test the sync-seen allow-list"); + + let engine = Service.engineManager.get("prefs"); + let store = engine._store; + let prefs = new Preferences(); + + Services.prefs.readDefaultPrefsFromFile( + do_get_file("prefs_test_prefs_store.js") + ); + const defaultValue = "the value"; + Assert.equal(prefs.get("testing.seen"), defaultValue); + + let record = await store.createRecord(PREFS_GUID, "prefs"); + // Haven't seen a non-default value before, so remains null. + Assert.strictEqual(record.value["testing.seen"], null); + + // pretend an incoming record with the default value - it might not be + // the default everywhere, so we treat it specially. + record = new PrefRec("prefs", PREFS_GUID); + record.value = { + "testing.seen": defaultValue, + }; + await store.update(record); + // Our special control value should now be set. + Assert.strictEqual( + prefs.get("services.sync.prefs.sync-seen.testing.seen"), + true + ); + // It's still the default value, so the value is not considered changed + Assert.equal(prefs.isSet("testing.seen"), false); + + // But now that special control value is set, the record always contains the value. + record = await store.createRecord(PREFS_GUID, "prefs"); + Assert.strictEqual(record.value["testing.seen"], defaultValue); +}); + +add_task(async function test_outgoing_when_changed() { + _("Test the 'seen' pref is set first sync of non-default value"); + + let engine = Service.engineManager.get("prefs"); + let store = engine._store; + let prefs = new Preferences(); + prefs.resetBranch(); + + Services.prefs.readDefaultPrefsFromFile( + do_get_file("prefs_test_prefs_store.js") + ); + const defaultValue = "the value"; + Assert.equal(prefs.get("testing.seen"), defaultValue); + + let record = await store.createRecord(PREFS_GUID, "prefs"); + // Haven't seen a non-default value before, so remains null. + Assert.strictEqual(record.value["testing.seen"], null); + + // Change the value. + prefs.set("testing.seen", "new value"); + record = await store.createRecord(PREFS_GUID, "prefs"); + // creating the record toggled that "seen" pref. + Assert.strictEqual( + prefs.get("services.sync.prefs.sync-seen.testing.seen"), + true + ); + Assert.strictEqual(prefs.get("testing.seen"), "new value"); + + // Resetting the pref does not change that seen value. + prefs.reset("testing.seen"); + Assert.strictEqual(prefs.get("testing.seen"), defaultValue); + + record = await store.createRecord(PREFS_GUID, "prefs"); + Assert.strictEqual( + prefs.get("services.sync.prefs.sync-seen.testing.seen"), + true + ); +}); -- cgit v1.2.3