tor-browser

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

commit adcc104bc7d8afb196df6b3b3adf76bbe8d4c6f6
parent b65113ed0849854fbc6833c0c9619e27bd89b890
Author: Johannes Schmidt <joschmidt@mozilla.com>
Date:   Tue, 21 Oct 2025 14:30:20 +0000

Bug 1993218 - emit rust mirror events and harden tests - r=dimi

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

Diffstat:
Mtoolkit/components/passwordmgr/LoginManagerRustMirror.sys.mjs | 8++++++++
Mtoolkit/components/passwordmgr/test/browser/browser_rust_mirror.js | 99+++++++++++++++++++++++++++++++++++++++++--------------------------------------
2 files changed, 59 insertions(+), 48 deletions(-)

diff --git a/toolkit/components/passwordmgr/LoginManagerRustMirror.sys.mjs b/toolkit/components/passwordmgr/LoginManagerRustMirror.sys.mjs @@ -259,6 +259,11 @@ export class LoginManagerRustMirror { this.#logger.error(`error: received unhandled event "${eventName}"`); break; } + + Services.obs.notifyObservers( + null, + `rust-mirror.event.${eventName}.finished` + ); } async #maybeRunMigration() { @@ -339,6 +344,9 @@ export class LoginManagerRustMirror { numberOfLoginsMigrated ); this.#migrationInProgress = false; + + // Notify about the finished migration. This is used in tests. + Services.obs.notifyObservers(null, "rust-mirror.migration.finished"); } } } diff --git a/toolkit/components/passwordmgr/test/browser/browser_rust_mirror.js b/toolkit/components/passwordmgr/test/browser/browser_rust_mirror.js @@ -27,12 +27,15 @@ add_task(async function test_mirror_addLogin() { username: "username", password: "password", }); + const addLoginFinishedPromise = TestUtils.topicObserved( + "rust-mirror.event.addLogin.finished" + ); await Services.logins.addLoginAsync(loginInfo); + await addLoginFinishedPromise; // note LoginManagerRustStorage is a singleton and already initialized when // Services.logins gets initialized. const rustStorage = new LoginManagerRustStorage(); - const storedLoginInfos = await Services.logins.getAllLogins(); const rustStoredLoginInfos = await rustStorage.getAllLogins(); LoginTestUtils.assertLoginListsEqual(storedLoginInfos, rustStoredLoginInfos); @@ -54,9 +57,11 @@ add_task(async function test_mirror_modifyLogin() { username: "username", password: "password", }); + const addLoginFinishedPromise = TestUtils.topicObserved( + "rust-mirror.event.addLogin.finished" + ); await Services.logins.addLoginAsync(loginInfo); - - const rustStorage = new LoginManagerRustStorage(); + await addLoginFinishedPromise; const [storedLoginInfo] = await Services.logins.getAllLogins(); @@ -66,13 +71,17 @@ add_task(async function test_mirror_modifyLogin() { usernameField: "new_form_field_username", passwordField: "new_form_field_password", }); + const modifyLoginFinishedPromise = TestUtils.topicObserved( + "rust-mirror.event.modifyLogin.finished" + ); Services.logins.modifyLogin(storedLoginInfo, modifiedLoginInfo); + await modifyLoginFinishedPromise; + const rustStorage = new LoginManagerRustStorage(); const [storedModifiedLoginInfo] = await Services.logins.getAllLogins(); const [rustStoredModifiedLoginInfo] = await rustStorage.searchLoginsAsync({ guid: storedLoginInfo.guid, }); - LoginTestUtils.assertLoginListsEqual( [storedModifiedLoginInfo], [rustStoredModifiedLoginInfo] @@ -95,14 +104,20 @@ add_task(async function test_mirror_removeLogin() { username: "username", password: "password", }); + const addLoginFinishedPromise = TestUtils.topicObserved( + "rust-mirror.event.addLogin.finished" + ); await Services.logins.addLoginAsync(loginInfo); - - const rustStorage = new LoginManagerRustStorage(); + await addLoginFinishedPromise; const [storedLoginInfo] = await Services.logins.getAllLogins(); - + const removeLoginFinishedPromise = TestUtils.topicObserved( + "rust-mirror.event.removeLogin.finished" + ); Services.logins.removeLogin(storedLoginInfo); + await removeLoginFinishedPromise; + const rustStorage = new LoginManagerRustStorage(); const allLogins = await rustStorage.getAllLogins(); Assert.equal(allLogins.length, 0); @@ -116,27 +131,21 @@ add_task(async function test_mirror_removeLogin() { */ add_task(async function test_mirror_csv_import_add() { await SpecialPowers.pushPrefEnv({ - set: [ - ["signon.rustMirror.enabled", true], - ["signon.rustMirror.migrationNeeded", true], - ], + set: [["signon.rustMirror.enabled", true]], }); let csvFile = await LoginTestUtils.file.setupCsvFileWithLines([ "url,username,password,httpRealm,formActionOrigin,guid,timeCreated,timeLastUsed,timePasswordChanged", `https://example.com,joe@example.com,qwerty,My realm,,{5ec0d12f-e194-4279-ae1b-d7d281bb46f0},1589617814635,1589710449871,1589617846802`, ]); - const prefChangePromise = TestUtils.waitForPrefChange( - "signon.rustMirror.migrationNeeded" + const importLoginsFinishedPromise = TestUtils.topicObserved( + "rust-mirror.event.importLogins.finished" ); await LoginCSVImport.importFromCSV(csvFile.path); // wait for the mirror to complete - await prefChangePromise; + await importLoginsFinishedPromise; - // note LoginManagerRustStorage is a singleton and already initialized when - // Services.logins gets initialized. const rustStorage = new LoginManagerRustStorage(); - const storedLoginInfos = await Services.logins.getAllLogins(); const rustStoredLoginInfos = await rustStorage.getAllLogins(); LoginTestUtils.assertLoginListsEqual(storedLoginInfos, rustStoredLoginInfos); @@ -151,10 +160,7 @@ add_task(async function test_mirror_csv_import_add() { */ add_task(async function test_mirror_csv_import_modify() { await SpecialPowers.pushPrefEnv({ - set: [ - ["signon.rustMirror.enabled", true], - ["signon.rustMirror.migrationNeeded", true], - ], + set: [["signon.rustMirror.enabled", true]], }); // create a login @@ -163,26 +169,27 @@ add_task(async function test_mirror_csv_import_modify() { username: "username", password: "password", }); - const login = await Services.logins.addLoginAsync(loginInfo); - const prefChangePromise = TestUtils.waitForPrefChange( - "signon.rustMirror.migrationNeeded" + const addLoginFinishedPromise = TestUtils.topicObserved( + "rust-mirror.event.addLogin.finished" ); + const login = await Services.logins.addLoginAsync(loginInfo); + await addLoginFinishedPromise; + // and import it, so we update let csvFile = await LoginTestUtils.file.setupCsvFileWithLines([ "url,username,password,httpRealm,formActionOrigin,guid,timeCreated,timeLastUsed,timePasswordChanged", `https://example.com,username,qwerty,My realm,,${login.guid},1589617814635,1589710449871,1589617846802`, ]); + const importLoginsFinishedPromise = TestUtils.topicObserved( + "rust-mirror.event.importLogins.finished" + ); await LoginCSVImport.importFromCSV(csvFile.path); // wait for the mirror to complete - await prefChangePromise; + await importLoginsFinishedPromise; - // note LoginManagerRustStorage is a singleton and already initialized when - // Services.logins gets initialized. const rustStorage = new LoginManagerRustStorage(); - const [storedLoginInfo] = await Services.logins.getAllLogins(); const [rustStoredLoginInfo] = await rustStorage.getAllLogins(); - Assert.equal( storedLoginInfo.password, rustStoredLoginInfo.password, @@ -242,10 +249,13 @@ add_task(async function test_migration_is_idempotent() { username: "test-user", password: "secure-password", }); + const addLoginFinishedPromise = TestUtils.topicObserved( + "rust-mirror.event.addLogin.finished" + ); await Services.logins.addLoginAsync(login); + await addLoginFinishedPromise; const rustStorage = new LoginManagerRustStorage(); - let rustLogins = await rustStorage.getAllLogins(); Assert.equal( rustLogins.length, @@ -257,14 +267,13 @@ add_task(async function test_migration_is_idempotent() { await SpecialPowers.pushPrefEnv({ set: [["signon.rustMirror.enabled", false]], }); - // using the migrationNeeded pref change as an indicator that the migration did run - const prefChangePromise = TestUtils.waitForPrefChange( - "signon.rustMirror.migrationNeeded" + const migrationFinishedPromise = TestUtils.topicObserved( + "rust-mirror.migration.finished" ); await SpecialPowers.pushPrefEnv({ set: [["signon.rustMirror.enabled", true]], }); - await prefChangePromise; + await migrationFinishedPromise; rustLogins = await rustStorage.getAllLogins(); Assert.equal(rustLogins.length, 1, "No duplicate after second migration"); @@ -307,16 +316,13 @@ add_task(async function test_migration_partial_failure() { await Services.logins.addLoginAsync(login_bad); // trigger again - await SpecialPowers.pushPrefEnv({ - set: [["signon.rustMirror.enabled", false]], - }); + const migrationFinishedPromise = TestUtils.topicObserved( + "rust-mirror.migration.finished" + ); await SpecialPowers.pushPrefEnv({ set: [["signon.rustMirror.enabled", true]], }); - - // and wait a little, due to the lack of a migration-complete event. - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - await new Promise(resolve => setTimeout(resolve, 200)); + await migrationFinishedPromise; const rustLogins = await rustStorage.getAllLogins(); Assert.equal(rustLogins.length, 1, "only valid login migrated"); @@ -348,16 +354,13 @@ add_task(async function test_migration_rejects_when_bulk_add_rejects() { await Services.logins.addLoginAsync(login); // trigger again - await SpecialPowers.pushPrefEnv({ - set: [["signon.rustMirror.enabled", false]], - }); + const migrationFinishedPromise = TestUtils.topicObserved( + "rust-mirror.migration.finished" + ); await SpecialPowers.pushPrefEnv({ set: [["signon.rustMirror.enabled", true]], }); - - // and wait a little, due to the lack of a migration-complete event. - // eslint-disable-next-line mozilla/no-arbitrary-setTimeout - await new Promise(resolve => setTimeout(resolve, 200)); + await migrationFinishedPromise; const rustLogins = await rustStorage.getAllLogins(); Assert.equal(rustLogins.length, 0, "zero logins migrated");