diff options
Diffstat (limited to 'services/sync/tests/unit/test_prefs_store.js')
-rw-r--r-- | services/sync/tests/unit/test_prefs_store.js | 333 |
1 files changed, 333 insertions, 0 deletions
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..6236b8e5da --- /dev/null +++ b/services/sync/tests/unit/test_prefs_store.js @@ -0,0 +1,333 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { Preferences } = ChromeUtils.import( + "resource://gre/modules/Preferences.jsm" +); +const { PrefRec } = ChromeUtils.import( + "resource://services-sync/engines/prefs.js" +); +const { Service } = ChromeUtils.import("resource://services-sync/service.js"); + +const PREFS_GUID = CommonUtils.encodeBase64URL(Services.appinfo.ID); + +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(); + +// Attempting to set the +// security.turn_off_all_security_so_that_viruses_can_take_over_this_computer +// preference to enable Cu.exitIfInAutomation crashes, probably due to +// shutdown behaviors faked by AddonTestUtils.jsm's cleanup function. +do_disable_fast_shutdown(); + +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(""); + } +}); |