tor-browser

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

commit 4cbe981d6d500a5d551cca33e10bf9a6b55bc91a
parent 97f2a0770ea2e72a77b7028c9f530f61fda2fb7d
Author: Harsheet <hsohaney@mozilla.com>
Date:   Fri, 12 Dec 2025 13:56:25 +0000

Bug 2003079 - Switch to using a lazy pref getter for the backup file name to sync the state and pref. r=mconley

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

Diffstat:
Mbrowser/components/backup/BackupService.sys.mjs | 92++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Mbrowser/components/backup/tests/xpcshell/test_BackupService.js | 6+++++-
2 files changed, 71 insertions(+), 27 deletions(-)

diff --git a/browser/components/backup/BackupService.sys.mjs b/browser/components/backup/BackupService.sys.mjs @@ -210,7 +210,19 @@ XPCOMUtils.defineLazyPreferenceGetter( lazy, "lastBackupFileName", LAST_BACKUP_FILE_NAME_PREF_NAME, - "" + "", + function onUpdateLastBackupFileName(_pref, _prevVal, newVal) { + let bs; + try { + bs = BackupService.get(); + } catch (e) { + // This can throw if the BackupService hasn't initialized yet, which + // is a case we're okay to ignore. + } + if (bs) { + bs.onUpdateLastBackupFileName(newVal); + } + } ); XPCOMUtils.defineLazyServiceGetter( @@ -860,7 +872,7 @@ export class BackupService extends EventTarget { encryptionEnabled: false, /** @type {number?} Number of seconds since UNIX epoch */ lastBackupDate: null, - lastBackupFileName: "", + lastBackupFileName: lazy.lastBackupFileName, supportBaseLink: Services.urlFormatter.formatURLPref("app.support.baseURL"), recoveryInProgress: false, /** @@ -1245,12 +1257,15 @@ export class BackupService extends EventTarget { /** * Returns a reference to a BackupService singleton. If this is the first time * that this getter is accessed, this causes the BackupService singleton to be - * be instantiated. + * instantiated. * * @static - * @type {BackupService} + * @param {object} BackupResources + * Optional object containing BackupResource classes to initialize the instance with. + * @returns {BackupService} + * The BackupService singleton instance. */ - static init() { + static init(BackupResources = DefaultBackupResources) { if (this.#instance) { return this.#instance; } @@ -1258,7 +1273,7 @@ export class BackupService extends EventTarget { // If there is unsent restore telemetry, send it now. GleanPings.profileRestore.submit(); - this.#instance = new BackupService(DefaultBackupResources); + this.#instance = new BackupService(BackupResources); this.#instance.checkForPostRecovery(); this.#instance.initBackupScheduler(); @@ -1267,6 +1282,22 @@ export class BackupService extends EventTarget { } /** + * Clears the BackupService singleton instance. + * This should only be used in tests. + * + * @static + */ + static uninit() { + if (this.#instance) { + lazy.logConsole.debug("Uninitting the BackupService"); + + this.#instance.uninitBackupScheduler(); + this.#instance.uninitStatusObservers(); + this.#instance = null; + } + } + + /** * Returns a reference to the BackupService singleton. If the singleton has * not been initialized, an error is thrown. * @@ -1916,9 +1947,6 @@ export class BackupService extends EventTarget { await IOUtils.move(sourcePath, destPath); Services.prefs.setStringPref(LAST_BACKUP_FILE_NAME_PREF_NAME, FILENAME); - // It is expected that our caller will call stateUpdate(), so we skip doing - // that here. This is done via the backupInProgress setter in createBackup. - this.#_state.lastBackupFileName = FILENAME; for (let childFilePath of existingChildren) { let childFileName = PathUtils.filename(childFilePath); @@ -3661,6 +3689,32 @@ export class BackupService extends EventTarget { } /** + * Updates lastBackupFileName in the backup service state. Should be called every time + * the value for browser.backup.scheduled.last-backup-file changes. + * + * @param {string} newLastBackupFileName + * Name of the last known backup file + */ + onUpdateLastBackupFileName(newLastBackupFileName) { + lazy.logConsole.debug( + `The last backup file name is being updated to ${newLastBackupFileName}` + ); + + this.#_state.lastBackupFileName = newLastBackupFileName; + + if (!newLastBackupFileName) { + lazy.logConsole.debug( + `Looks like we've cleared the last backup file name, let's also clear the last backup date` + ); + + this.#_state.lastBackupDate = null; + Services.prefs.clearUserPref(LAST_BACKUP_TIMESTAMP_PREF_NAME); + } + + this.stateUpdate(); + } + + /** * Returns the moz-icon URL of a file. To get the moz-icon URL, the * file path is convered to a fileURI. If there is a problem retreiving * the moz-icon due to an invalid file path, return null instead. @@ -4006,16 +4060,8 @@ export class BackupService extends EventTarget { LAST_BACKUP_TIMESTAMP_PREF_NAME, 0 ); - if (!lastBackupPrefValue) { - this.#_state.lastBackupDate = null; - } else { - this.#_state.lastBackupDate = lastBackupPrefValue; - } - this.#_state.lastBackupFileName = Services.prefs.getStringPref( - LAST_BACKUP_FILE_NAME_PREF_NAME, - "" - ); + this.#_state.lastBackupDate = lastBackupPrefValue || null; this.stateUpdate(); @@ -4587,7 +4633,7 @@ export class BackupService extends EventTarget { async showBackupLocation() { let backupFilePath = PathUtils.join( lazy.backupDirPref, - this.#_state.lastBackupFileName + lazy.lastBackupFileName ); if (await IOUtils.exists(backupFilePath)) { new lazy.nsLocalFile(backupFilePath).reveal(); @@ -4621,7 +4667,7 @@ export class BackupService extends EventTarget { speedUpHeuristic = false, } = {}) { // Do we already have a backup for this browser? if so, we don't need to do any searching! - if (this.#_state.lastBackupFileName) { + if (lazy.lastBackupFileName) { return { found: true, multipleBackupsFound: false, @@ -4862,13 +4908,7 @@ export class BackupService extends EventTarget { }); } - this.#_state.lastBackupDate = null; - Services.prefs.clearUserPref(LAST_BACKUP_TIMESTAMP_PREF_NAME); - - this.#_state.lastBackupFileName = ""; Services.prefs.clearUserPref(LAST_BACKUP_FILE_NAME_PREF_NAME); - - this.stateUpdate(); } else { lazy.logConsole.log( "Not deleting last backup file, since none is known about." diff --git a/browser/components/backup/tests/xpcshell/test_BackupService.js b/browser/components/backup/tests/xpcshell/test_BackupService.js @@ -114,7 +114,7 @@ async function testCreateBackupHelper(sandbox, taskFn) { .stub(FakeBackupResource3.prototype, "recover") .resolves(fake3PostRecoveryEntry); - let bs = new BackupService({ + let bs = BackupService.init({ FakeBackupResource1, FakeBackupResource2, FakeBackupResource3, @@ -392,6 +392,10 @@ async function testCreateBackupHelper(sandbox, taskFn) { await maybeRemovePath(fakeProfilePath); await maybeRemovePath(recoveredProfilePath); await maybeRemovePath(EXPECTED_ARCHIVE_PATH); + + Services.prefs.clearUserPref(LAST_BACKUP_FILE_NAME_PREF_NAME); + + BackupService.uninit(); } /**