tor-browser

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

commit 9c6fac590c320c4d27b94fd7d48ddfe43198708b
parent f30cf7c5e8dd019bee8c5aac10c8975e6529f67a
Author: Jason Prickett <jprickett@mozilla.com>
Date:   Thu,  9 Oct 2025 17:14:59 +0000

Bug 1993126 - Display backup file info underneath input when file is selected r=omc-reviewers,sthompson,mviar

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

Diffstat:
Mbrowser/components/backup/BackupService.sys.mjs | 2++
Mbrowser/components/backup/content/restore-from-backup.css | 7+++++++
Mbrowser/components/backup/content/restore-from-backup.mjs | 15+++++++++++++++
Mbrowser/components/backup/tests/browser/browser_settings_restore_from_backup.js | 70++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbrowser/components/backup/tests/xpcshell/test_BackupService.js | 9+++++++--
5 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/browser/components/backup/BackupService.sys.mjs b/browser/components/backup/BackupService.sys.mjs @@ -2623,6 +2623,7 @@ export class BackupService extends EventTarget { appVersion: AppConstants.MOZ_APP_VERSION, buildID: AppConstants.MOZ_BUILDID, profileName, + deviceName: Services.sysinfo.get("device") || Services.dns.myHostName, machineName: lazy.fxAccounts.device.getLocalName(), osName: Services.sysinfo.getProperty("name"), osVersion: Services.sysinfo.getProperty("version"), @@ -3784,6 +3785,7 @@ export class BackupService extends EventTarget { this.#_state.backupFileInfo = { isEncrypted, date: archiveJSON?.meta?.date, + deviceName: archiveJSON?.meta?.deviceName, }; this.#_state.backupFileToRestore = backupFilePath; this.stateUpdate(); diff --git a/browser/components/backup/content/restore-from-backup.css b/browser/components/backup/content/restore-from-backup.css @@ -94,6 +94,13 @@ #backup-filepicker-button { margin-block: var(--space-xsmall); } + + #restore-from-backup-backup-found-info { + text-align: start; + color: var(--text-color-deemphasized); + font-size: var(--font-size-small); + margin-top: var(--space-xsmall); + } } #backup-password { diff --git a/browser/components/backup/content/restore-from-backup.mjs b/browser/components/backup/content/restore-from-backup.mjs @@ -253,6 +253,21 @@ export default class RestoreFromBackup extends MozLitElement { data-l10n-id="restore-from-backup-no-backup-file-link" ></a>` : null} + ${this.backupServiceState?.backupFileInfo + ? html`<p + id="restore-from-backup-backup-found-info" + data-l10n-id="backup-file-creation-date-and-device" + data-l10n-args=${JSON.stringify({ + machineName: + this.backupServiceState.backupFileInfo.deviceName ?? "", + date: this.backupServiceState.backupFileInfo.date + ? new Date( + this.backupServiceState.backupFileInfo.date + ).getTime() + : 0, + })} + ></p>` + : null} </fieldset> <fieldset id="password-entry-controls"> diff --git a/browser/components/backup/tests/browser/browser_settings_restore_from_backup.js b/browser/components/backup/tests/browser/browser_settings_restore_from_backup.js @@ -107,6 +107,7 @@ add_task(async function test_restore_from_backup() { ...restoreFromBackup.backupServiceState, backupFileInfo: { date: new Date(), + deviceName: "test-device", isEncrypted: true, }, }; @@ -368,3 +369,72 @@ add_task( ); } ); + +/** + * Tests that the backup file info is displayed when backupFileInfo is present + */ +add_task(async function test_restore_backup_file_info_display() { + await BrowserTestUtils.withNewTab("about:preferences#sync", async browser => { + let settings = browser.contentDocument.querySelector("backup-settings"); + await settings.updateComplete; + + Assert.ok( + settings.restoreFromBackupButtonEl, + "Restore button should exist" + ); + + settings.restoreFromBackupButtonEl.click(); + await settings.updateComplete; + + let restoreFromBackup = settings.restoreFromBackupEl; + Assert.ok(restoreFromBackup, "restore-from-backup should be found"); + + // Initially, backup file info should not be displayed underneath the input + let fileInfoSpan = restoreFromBackup.shadowRoot.querySelector( + "#restore-from-backup-backup-found-info" + ); + Assert.ok( + !fileInfoSpan, + "Backup file info should not be displayed when backupFileInfo is null" + ); + + // Set backup file info with device name and date + const mockDate = new Date("2025-10-07T21:27:56.844Z"); + const mockDeviceName = "test-device"; + restoreFromBackup.backupServiceState = { + ...restoreFromBackup.backupServiceState, + backupFileInfo: { + date: mockDate, + deviceName: mockDeviceName, + isEncrypted: false, + }, + }; + await restoreFromBackup.updateComplete; + + fileInfoSpan = restoreFromBackup.shadowRoot.querySelector( + "#restore-from-backup-backup-found-info" + ); + Assert.ok( + fileInfoSpan, + "Backup file info should be displayed when backupFileInfo is set" + ); + + Assert.equal( + fileInfoSpan.getAttribute("data-l10n-id"), + "backup-file-creation-date-and-device", + "Should have the correct l10n id" + ); + + const l10nArgs = JSON.parse(fileInfoSpan.getAttribute("data-l10n-args")); + Assert.equal( + l10nArgs.machineName, + mockDeviceName, + "l10n args should contain the correct device name" + ); + Assert.equal( + l10nArgs.date, + mockDate.getTime(), + "l10n args should contain the correct date" + ); + }); +}); diff --git a/browser/components/backup/tests/xpcshell/test_BackupService.js b/browser/components/backup/tests/xpcshell/test_BackupService.js @@ -856,12 +856,17 @@ add_task(async function test_getBackupFileInfo() { const DATE = "2024-06-25T21:59:11.777Z"; const IS_ENCRYPTED = true; + const DEVICE_NAME = "test-device"; let fakeSampleArchiveResult = { isEncrypted: IS_ENCRYPTED, startByteOffset: 26985, contentType: "multipart/mixed", - archiveJSON: { version: 1, meta: { date: DATE }, encConfig: {} }, + archiveJSON: { + version: 1, + meta: { date: DATE, deviceName: DEVICE_NAME }, + encConfig: {}, + }, }; sandbox @@ -879,7 +884,7 @@ add_task(async function test_getBackupFileInfo() { Assert.deepEqual( bs.state.backupFileInfo, - { isEncrypted: IS_ENCRYPTED, date: DATE }, + { isEncrypted: IS_ENCRYPTED, date: DATE, deviceName: DEVICE_NAME }, "State should match a subset from the archive sample." );