Bug 1895943 - Implement file picker and save location for backups. r=backup-reviewers,mconley,fluent-reviewers,flod,firefox-desktop-core-reviewers
1. Allows for selecting a custom path or the default (Documents) path for saving backups. The selection is passed from the "turn-on-scheduled-backups" dialog to "BackupService". 2. After pressing the "Choose" button in the dialog, a filepicker will appear so that a folder can be selected. 3. Once the dialog is confirmed, the absolute path is saved to a pref called "browser.backup.location" and saved in the service state. Other changes: - Added the Documents folder as the default save location - Added an onUpdate function for "browser.backup.location" that passes the updated BackupService state to registered widgets (backup settings section, dialogs) - Added Storybook entries and tests for the newly updated input and filepicker Figma: https://www.figma.com/design/vNbX4c0ws0L1qr0mxpKvsW/Fx-Backup?node-id=147-4568&t=tILUMKfg8c6Ed1Ul-0 (turn on backup dialog) Differential Revision: https://phabricator.services.mozilla.com/D210850
This commit is contained in:
@@ -6,6 +6,7 @@ import * as DefaultBackupResources from "resource:///modules/backup/BackupResour
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const BACKUP_DIR_PREF_NAME = "browser.backup.location";
|
||||
const SCHEDULED_BACKUPS_ENABLED_PREF_NAME = "browser.backup.scheduled.enabled";
|
||||
const lazy = {};
|
||||
|
||||
@@ -37,6 +38,13 @@ ChromeUtils.defineLazyGetter(lazy, "ZipWriter", () =>
|
||||
Components.Constructor("@mozilla.org/zipwriter;1", "nsIZipWriter", "open")
|
||||
);
|
||||
|
||||
ChromeUtils.defineLazyGetter(lazy, "gFluentStrings", function () {
|
||||
return new Localization(
|
||||
["branding/brand.ftl", "preview/backupSettings.ftl"],
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
"scheduledBackupsPref",
|
||||
@@ -50,6 +58,20 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
||||
}
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
lazy,
|
||||
"backupDirPref",
|
||||
BACKUP_DIR_PREF_NAME,
|
||||
Services.dirsvc.get("Docs", Ci.nsIFile)
|
||||
.path /* Default directory is Documents */,
|
||||
async function onUpdateLocationDirPath(_pref, _prevVal, newVal) {
|
||||
let bs = BackupService.get();
|
||||
if (bs) {
|
||||
await bs.onUpdateLocationDirPath(newVal);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* The BackupService class orchestrates the scheduling and creation of profile
|
||||
* backups. It also does most of the heavy lifting for the restoration of a
|
||||
@@ -71,6 +93,13 @@ export class BackupService extends EventTarget {
|
||||
*/
|
||||
#resources = new Map();
|
||||
|
||||
/**
|
||||
* The name of the backup folder. Should be localized.
|
||||
*
|
||||
* @see BACKUP_DIR_NAME
|
||||
*/
|
||||
static #backupFolderName = null;
|
||||
|
||||
/**
|
||||
* Set to true if a backup is currently in progress. Causes stateUpdate()
|
||||
* to be called.
|
||||
@@ -112,7 +141,12 @@ export class BackupService extends EventTarget {
|
||||
* @type {object}
|
||||
*/
|
||||
#_state = {
|
||||
backupFilePath: "Documents", // TODO: make save location configurable (bug 1895943)
|
||||
backupDirPath: lazy.backupDirPref,
|
||||
defaultParent: {
|
||||
path: BackupService.DEFAULT_PARENT_DIR_PATH,
|
||||
fileName: PathUtils.filename(BackupService.DEFAULT_PARENT_DIR_PATH),
|
||||
iconURL: this.getIconFromFilePath(BackupService.DEFAULT_PARENT_DIR_PATH),
|
||||
},
|
||||
backupInProgress: false,
|
||||
scheduledBackupsEnabled: lazy.scheduledBackupsPref,
|
||||
encryptionEnabled: false,
|
||||
@@ -152,6 +186,29 @@ export class BackupService extends EventTarget {
|
||||
*/
|
||||
#encState = undefined;
|
||||
|
||||
/**
|
||||
* The path of the default parent directory for saving backups.
|
||||
* The current default is the Documents directory.
|
||||
*
|
||||
* @returns {string} The path of the default parent directory
|
||||
*/
|
||||
static get DEFAULT_PARENT_DIR_PATH() {
|
||||
return Services.dirsvc.get("Docs", Ci.nsIFile).path;
|
||||
}
|
||||
|
||||
/**
|
||||
* The localized name for the user's backup folder.
|
||||
*
|
||||
* @returns {string} The localized backup folder name
|
||||
*/
|
||||
static get BACKUP_DIR_NAME() {
|
||||
if (!BackupService.#backupFolderName) {
|
||||
BackupService.#backupFolderName =
|
||||
lazy.gFluentStrings.formatValueSync("backup-folder-name");
|
||||
}
|
||||
return BackupService.#backupFolderName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the folder within the profile folder where this service reads
|
||||
* and writes state to.
|
||||
@@ -924,6 +981,65 @@ export class BackupService extends EventTarget {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parent directory of the backups folder. Calling this function will update
|
||||
* browser.backup.location.
|
||||
*
|
||||
* @param {string} parentDirPath directory path
|
||||
*/
|
||||
setParentDirPath(parentDirPath) {
|
||||
try {
|
||||
if (!parentDirPath || !PathUtils.filename(parentDirPath)) {
|
||||
throw new Error("Parent directory path is invalid.");
|
||||
}
|
||||
// Recreate the backups path with the new parent directory.
|
||||
let fullPath = PathUtils.join(
|
||||
parentDirPath,
|
||||
BackupService.BACKUP_DIR_NAME
|
||||
);
|
||||
Services.prefs.setStringPref(BACKUP_DIR_PREF_NAME, fullPath);
|
||||
} catch (e) {
|
||||
lazy.logConsole.error(
|
||||
`Failed to set parent directory ${parentDirPath}. ${e}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates backupDirPath in the backup service state. Should be called every time the value
|
||||
* for browser.backup.location changes.
|
||||
*
|
||||
* @param {string} newDirPath the new directory path for storing backups
|
||||
*/
|
||||
async onUpdateLocationDirPath(newDirPath) {
|
||||
lazy.logConsole.debug(`Updating backup location to ${newDirPath}`);
|
||||
|
||||
this.#_state.backupDirPath = newDirPath;
|
||||
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.
|
||||
*
|
||||
* @param {string} path Path of the file to read its icon from.
|
||||
* @returns {string|null} The moz-icon URL of the specified file, or
|
||||
* null if the icon cannot be retreived.
|
||||
*/
|
||||
getIconFromFilePath(path) {
|
||||
if (!path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
let fileURI = PathUtils.toFileURI(path);
|
||||
return `moz-icon:${fileURI}?size=16`;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets browser.backup.scheduled.enabled to true or false.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user