tor-browser

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

commit 76ec61f47fa59e18c79d2793cea2dc7d12b19806
parent d5170780c8bb580ed73318c3a4458cc4fdb13714
Author: Harsheet <hsohaney@mozilla.com>
Date:   Mon,  3 Nov 2025 16:59:48 +0000

Bug 1997067 - Add error handling for the case where there is no valid default folder for backups. r=cdupuis

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

Diffstat:
Mbrowser/components/backup/BackupService.sys.mjs | 38+++++++++++++++++++++++++++++---------
Mbrowser/components/backup/content/turn-on-scheduled-backups.mjs | 17+++++++++++------
Mbrowser/components/backup/tests/browser/browser_settings_create_backup.js | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 140 insertions(+), 17 deletions(-)

diff --git a/browser/components/backup/BackupService.sys.mjs b/browser/components/backup/BackupService.sys.mjs @@ -841,10 +841,20 @@ export class BackupService extends EventTarget { * @returns {string} The path of the default parent directory */ static get DEFAULT_PARENT_DIR_PATH() { - return ( - BackupService.oneDriveFolderPath?.path || - Services.dirsvc.get("Docs", Ci.nsIFile).path - ); + let path = ""; + try { + path = + BackupService.oneDriveFolderPath?.path || + Services.dirsvc.get("Docs", Ci.nsIFile).path; + } catch (e) { + // If this errors, we can safely return an empty string + lazy.logConsole.error( + "There was an error when getting the Default Parent Directory: ", + e + ); + } + + return path; } /** @@ -1162,11 +1172,13 @@ export class BackupService extends EventTarget { get state() { if (!Object.keys(this.#_state.defaultParent).length) { let defaultPath = BackupService.DEFAULT_PARENT_DIR_PATH; - this.#_state.defaultParent = { - path: defaultPath, - fileName: PathUtils.filename(defaultPath), - iconURL: this.getIconFromFilePath(defaultPath), - }; + if (defaultPath) { + this.#_state.defaultParent = { + path: defaultPath, + fileName: PathUtils.filename(defaultPath), + iconURL: this.getIconFromFilePath(defaultPath), + }; + } } return Object.freeze(structuredClone(this.#_state)); @@ -4118,6 +4130,14 @@ export class BackupService extends EventTarget { this.stateUpdate(); } + /** + * TEST ONLY: reset's the defaultParent state for testing purposes + */ + resetDefaultParentInternalState() { + this.#_state.defaultParent = {}; + this.stateUpdate(); + } + /* * Attempts to open a native file explorer window at the last backup file's * location on the filesystem. diff --git a/browser/components/backup/content/turn-on-scheduled-backups.mjs b/browser/components/backup/content/turn-on-scheduled-backups.mjs @@ -2,7 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import { html } from "chrome://global/content/vendor/lit.all.mjs"; +import { html, nothing } from "chrome://global/content/vendor/lit.all.mjs"; import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; // eslint-disable-next-line import/no-unassigned-import @@ -255,17 +255,22 @@ export default class TurnOnScheduledBackups extends MozLitElement { let filename = this.defaultLabel; let iconURL = this.defaultIconURL || this.#placeholderIconURL; + const hasFilename = !!filename; + const l10nArgs = hasFilename + ? JSON.stringify({ recommendedFolder: filename }) + : null; + return html` <input id="backup-location-filepicker-input-default" class="backup-location-filepicker-input" type="text" readonly - data-l10n-id="turn-on-scheduled-backups-location-default-folder" - data-l10n-args=${JSON.stringify({ - recommendedFolder: filename, - })} - data-l10n-attrs="value" + data-l10n-id=${hasFilename + ? "turn-on-scheduled-backups-location-default-folder" + : nothing} + data-l10n-args=${hasFilename ? l10nArgs : nothing} + data-l10n-attrs=${hasFilename ? "value" : "placeholder"} style=${`background-image: url(${iconURL})`} /> `; diff --git a/browser/components/backup/tests/browser/browser_settings_create_backup.js b/browser/components/backup/tests/browser/browser_settings_create_backup.js @@ -18,8 +18,8 @@ add_setup(async () => { ); await SpecialPowers.pushPrefEnv({ set: [ - [BACKUP_DEFAULT_LOCATION_PREF, TEST_PROFILE_PATH], - [SCHEDULED_BACKUPS_ENABLED_PREF, true], + [BACKUP_DEFAULT_LOCATION_PREF, ""], + [SCHEDULED_BACKUPS_ENABLED_PREF, false], ], }); @@ -30,9 +30,107 @@ add_setup(async () => { }); /** + * Tests the case where there is no DEFAULT_PARENT_DIR_PATH + */ +add_task(async function test_no_default_folder() { + const sandbox = sinon.createSandbox(); + + let bs = getAndMaybeInitBackupService(); + bs.resetDefaultParentInternalState(); + + let callCount = 0; + let getterStub = sandbox + .stub(BackupService, "DEFAULT_PARENT_DIR_PATH") + .get(() => { + callCount++; + return ""; + }); + + await BrowserTestUtils.withNewTab("about:preferences#sync", async browser => { + let settings = browser.contentDocument.querySelector("backup-settings"); + let turnOnButton = settings.scheduledBackupsButtonEl; + + await settings.updateComplete; + + console.log( + "DO WE HAVE A DEFAULT PARENT ALREADY???", + settings.backupServiceState.defaultParent + ); + + Assert.ok(bs.archiveEnabledStatus, "Archive is enabled for backups"); + + Assert.ok( + turnOnButton, + "Button to turn on scheduled backups should be found" + ); + + turnOnButton.click(); + + await settings.updateComplete; + + let turnOnScheduledBackups = settings.turnOnScheduledBackupsEl; + + Assert.ok( + turnOnScheduledBackups, + "turn-on-scheduled-backups should be found" + ); + + // woops looks like getting the default dir threw an error, lets make sure we handled that + Assert.greaterOrEqual( + callCount, + 1, + "The default dir getter was called atleast once" + ); + + let filePathInputDefault = turnOnScheduledBackups.filePathInputDefaultEl; + + Assert.equal( + filePathInputDefault.value, + "", + "Default input displays the expected text" + ); + + let dialog = settings.turnOnScheduledBackupsDialogEl; + let dialogClosePromise = BrowserTestUtils.waitForEvent(dialog, "close"); + dialog.close(); + + await dialogClosePromise; + + getterStub.restore(); + }); + + await BrowserTestUtils.withNewTab("about:preferences#sync", async browser => { + let settings = browser.contentDocument.querySelector("backup-settings"); + + Assert.ok( + settings.turnOnScheduledBackupsEl, + "turn-on-scheduled-backups should be found" + ); + settings.scheduledBackupsButtonEl.click(); + + const documentsPath = BackupService.DEFAULT_PARENT_DIR_PATH; + + Assert.equal( + settings.turnOnScheduledBackupsEl.filePathInputDefaultEl.value, + `${PathUtils.filename(documentsPath)} (recommended)`, + "Default input displays the expected text" + ); + }); + + sandbox.restore(); + await SpecialPowers.popPrefEnv(); +}); + +/** * Test creating a new backup using the "Backup now" button */ add_task(async function test_create_new_backup_trigger() { + await SpecialPowers.pushPrefEnv({ + set: [ + [BACKUP_DEFAULT_LOCATION_PREF, TEST_PROFILE_PATH], + [SCHEDULED_BACKUPS_ENABLED_PREF, true], + ], + }); await BrowserTestUtils.withNewTab("about:preferences#sync", async browser => { Services.fog.testResetFOG();