tor-browser

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

commit 046ec69f081a6b24948dd8c48bc1030bb1194e23
parent 92a4d5250a0fa8978d244313c3ba14a43da742c8
Author: Tessa Heidkamp <theidkamp@g79vdt4jmw.speedport.ip>
Date:   Thu, 20 Nov 2025 16:03:00 +0000

Bug 2001305 - Set poisoned pref to true after failed migration. r=joschmidt,credential-management-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D273403

Diffstat:
Mtoolkit/components/passwordmgr/LoginManagerRustMirror.sys.mjs | 9++++++++-
Mtoolkit/components/passwordmgr/test/browser/browser_rust_mirror.js | 38+++++++++++++++++++++++++++++---------
2 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/toolkit/components/passwordmgr/LoginManagerRustMirror.sys.mjs b/toolkit/components/passwordmgr/LoginManagerRustMirror.sys.mjs @@ -82,13 +82,19 @@ function recordMigrationStatus( numberOfLoginsToMigrate, numberOfLoginsMigrated ) { + const had_errors = numberOfLoginsMigrated < numberOfLoginsToMigrate; + Glean.pwmgr.rustMigrationStatus.record({ run_id: runId, duration_ms: duration, number_of_logins_to_migrate: numberOfLoginsToMigrate, number_of_logins_migrated: numberOfLoginsMigrated, - had_errors: numberOfLoginsMigrated < numberOfLoginsToMigrate, + had_errors, }); + + if (had_errors) { + Services.prefs.setBoolPref("signon.rustMirror.poisoned", true); + } } function recordMigrationFailure(runId, error) { @@ -334,6 +340,7 @@ export class LoginManagerRustMirror { this.#logger.log("Migration complete."); } catch (e) { + Services.prefs.setBoolPref("signon.rustMirror.poisoned", true); this.#logger.error("migration error:", e); } finally { const duration = Date.now() - t0; diff --git a/toolkit/components/passwordmgr/test/browser/browser_rust_mirror.js b/toolkit/components/passwordmgr/test/browser/browser_rust_mirror.js @@ -291,18 +291,23 @@ add_task(async function test_migration_is_idempotent() { add_task(async function test_migration_partial_failure() { // ensure mirror is off await SpecialPowers.pushPrefEnv({ - set: [["signon.rustMirror.enabled", false]], + set: [ + ["signon.rustMirror.enabled", false], + ["signon.rustMirror.poisoned", false], + ], }); const rustStorage = new LoginManagerRustStorage(); // Save the first (valid) login into Rust for real, then simulate results - sinon.stub(rustStorage, "addLoginsAsync").callsFake(async (logins, _cont) => { - await rustStorage.addWithMeta(logins[0]); - return [ - { login: {}, error: null }, // row 0 success - { login: null, error: { message: "row failed" } }, // row 1 failure - ]; - }); + sinon + .stub(LoginManagerRustStorage.prototype, "addLoginsAsync") + .callsFake(async (logins, _cont) => { + await rustStorage.addWithMeta(logins[0]); + return [ + { login: {}, error: null }, // row 0 success + { login: null, error: { message: "row failed" } }, // row 1 failure + ]; + }); const login_ok = LoginTestUtils.testData.formLogin({ username: "test-user-ok", @@ -327,6 +332,12 @@ add_task(async function test_migration_partial_failure() { const rustLogins = await rustStorage.getAllLogins(); Assert.equal(rustLogins.length, 1, "only valid login migrated"); + Assert.equal( + Services.prefs.getBoolPref("signon.rustMirror.poisoned", false), + true, + "poisoned pref is set to true on partial migration failure" + ); + sinon.restore(); LoginTestUtils.clearData(); rustStorage.removeAllLogins(); @@ -340,7 +351,10 @@ add_task(async function test_migration_partial_failure() { add_task(async function test_migration_rejects_when_bulk_add_rejects() { // turn mirror off await SpecialPowers.pushPrefEnv({ - set: [["signon.rustMirror.enabled", false]], + set: [ + ["signon.rustMirror.enabled", false], + ["signon.rustMirror.poisoned", false], + ], }); const rustStorage = new LoginManagerRustStorage(); @@ -371,6 +385,12 @@ add_task(async function test_migration_rejects_when_bulk_add_rejects() { ); Assert.equal(newPrefValue, true, "pref has not been reset"); + Assert.equal( + Services.prefs.getBoolPref("signon.rustMirror.poisoned", false), + true, + "poisoned pref is set to true on hard migration failure" + ); + sinon.restore(); LoginTestUtils.clearData(); rustStorage.removeAllLogins();