Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test runs only with pattern: os != 'android'
- Manifest: services/sync/tests/unit/xpcshell.toml
/* Any copyright is dedicated to the Public Domain.
/**
* sync must not keep re-prompting on every subsequent sync. When the Primary
* Password is locked, the Rust-backed RustPasswordEngine must skip syncing
* *without* prompting and record the master-password-locked login state, so the
* scheduler backs off - matching the behaviour of the legacy PasswordEngine.
*
* RustPasswordEngine.initialize() reaches into the active Rust store for its
* bridge, so getActiveStore() is stubbed to avoid depending on the Rust backend.
*/
"use strict";
/* import-globals-from head_errorhandler_common.js */
const { Service } = ChromeUtils.importESModule(
);
const { RustPasswordEngine } = ChromeUtils.importESModule(
);
const { LoginManagerStorage } = ChromeUtils.importESModule(
"resource://passwordmgr/passwordstorage.sys.mjs"
);
const PREF_ACTIVE = "signon.storage.rust.active";
// `isLoggedIn` is a non-configurable getter on the real Services.logins, so swap
// in a minimal stand-in for the duration of the check and restore it afterwards.
function stubLoggedIn(value) {
let oldLogins = Services.logins;
Services.logins = { isLoggedIn: value };
return () => {
Services.logins = oldLogins;
};
}
let engine;
let sandbox;
let superSync;
add_task(async function setup() {
await Service.promiseInitialized;
Services.prefs.clearUserPref(PREF_ACTIVE);
sandbox = sinon.createSandbox();
sandbox.stub(LoginManagerStorage, "getActiveStore").returns({
bridgedEngine: async () => ({}),
});
// Stub the inherited real sync so a call is observable (and wouldn't hit the
// network); RustPasswordEngine._sync() delegates to it when unlocked.
superSync = sandbox.stub(SyncEngine.prototype, "_sync").resolves();
Services.prefs.setBoolPref(PREF_ACTIVE, true);
await Service.engineManager.switchAlternatives();
engine = Service.engineManager.get("passwords");
Assert.ok(
engine instanceof RustPasswordEngine,
"the Rust-backed engine is active"
);
});
add_task(async function test_skips_and_records_lock_when_locked() {
superSync.resetHistory();
let restore = stubLoggedIn(false);
Service.status.login = LOGIN_SUCCEEDED;
try {
await engine._sync();
Assert.ok(
superSync.notCalled,
"the engine skips the real sync (which would prompt) while locked"
);
Assert.equal(
Service.status.login,
MASTER_PASSWORD_LOCKED,
"a locked Primary Password records the master-password-locked login state"
);
} finally {
restore();
}
});
add_task(async function test_syncs_normally_when_unlocked() {
superSync.resetHistory();
let restore = stubLoggedIn(true);
Service.status.login = LOGIN_SUCCEEDED;
try {
await engine._sync();
Assert.ok(
superSync.calledOnce,
"the engine performs a normal sync when the Primary Password is unlocked"
);
Assert.equal(
Service.status.login,
LOGIN_SUCCEEDED,
"an unlocked Primary Password leaves the login state untouched"
);
} finally {
restore();
}
});
add_task(async function teardown() {
Services.prefs.clearUserPref(PREF_ACTIVE);
await Service.engineManager.switchAlternatives();
sandbox.restore();
Service.status.resetSync();
});