diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /browser/components/migration/FileMigrators.sys.mjs | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/components/migration/FileMigrators.sys.mjs')
-rw-r--r-- | browser/components/migration/FileMigrators.sys.mjs | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/browser/components/migration/FileMigrators.sys.mjs b/browser/components/migration/FileMigrators.sys.mjs new file mode 100644 index 0000000000..3384011c13 --- /dev/null +++ b/browser/components/migration/FileMigrators.sys.mjs @@ -0,0 +1,359 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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/. */ + +const lazy = {}; + +ChromeUtils.defineESModuleGetters(lazy, { + BookmarkHTMLUtils: "resource://gre/modules/BookmarkHTMLUtils.sys.mjs", + BookmarkJSONUtils: "resource://gre/modules/BookmarkJSONUtils.sys.mjs", + LoginCSVImport: "resource://gre/modules/LoginCSVImport.sys.mjs", + MigrationWizardConstants: + "chrome://browser/content/migration/migration-wizard-constants.mjs", +}); + +ChromeUtils.defineLazyGetter(lazy, "gFluentStrings", function () { + return new Localization([ + "branding/brand.ftl", + "browser/migrationWizard.ftl", + ]); +}); + +/** + * Base class for a migration that involves reading a single file off of + * the disk that the user picks using a file picker. The file might be + * generated by another browser or some other application. + */ +export class FileMigratorBase { + /** + * This must be overridden to return a simple string identifier for the + * migrator, for example "password-csv". This key is what + * is used as an identifier when calling MigrationUtils.getFileMigrator. + * + * @type {string} + */ + static get key() { + throw new Error("FileMigrator.key must be overridden."); + } + + /** + * This must be overridden to return a Fluent string ID mapping to the display + * name for this migrator. These strings should be defined in migrationWizard.ftl. + * + * @type {string} + */ + static get displayNameL10nID() { + throw new Error("FileMigrator.displayNameL10nID must be overridden."); + } + + /** + * This getter should get overridden to return an icon url to represent the + * file to be imported from. By default, this will just use the default Favicon + * image. + * + * @type {string} + */ + static get brandImage() { + return "chrome://global/skin/icons/defaultFavicon.svg"; + } + + /** + * Returns true if the migrator is configured to be enabled. + * + * @type {boolean} + * true if the migrator should be shown in the migration wizard. + */ + get enabled() { + throw new Error("FileMigrator.enabled must be overridden."); + } + + /** + * This getter should be overridden to return a Fluent string ID for what + * the migration wizard header should be while the file migration is + * underway. + * + * @type {string} + */ + get progressHeaderL10nID() { + throw new Error("FileMigrator.progressHeaderL10nID must be overridden."); + } + + /** + * This getter should be overridden to return a Fluent string ID for what + * the migration wizard header should be while the file migration is + * done. + * + * @type {string} + */ + get successHeaderL10nID() { + throw new Error("FileMigrator.progressHeaderL10nID must be overridden."); + } + + /** + * @typedef {object} FilePickerConfiguration + * @property {string} title + * The title that should be assigned to the native file picker window. + * @property {FilePickerConfigurationFilter[]} filters + * One or more extension filters that should be applied to the native + * file picker window to make selection easier. + */ + + /** + * @typedef {object} FilePickerConfigurationFilter + * @property {string} title + * The title for the filter. Example: "CSV Files" + * @property {string} extensionPattern + * A matching pattern for the filter. Example: "*.csv" + */ + + /** + * A subclass of FileMigratorBase will eventually open a native file picker + * for the user to select the file from their file system. + * + * Subclasses need to override this method in order to configure the + * native file picker. + * + * @returns {Promise<FilePickerConfiguration>} + */ + async getFilePickerConfig() { + throw new Error("FileMigrator.getFilePickerConfig must be overridden."); + } + + /** + * Returns a list of one or more resource types that should appear to be + * in progress of migrating while the file migration occurs. Notably, + * this does not need to match the resource types that are returned by + * `FileMigratorBase.migrate`. + * + * @type {string[]} + * An array of resource types from the + * MigrationWizardConstants.DISPLAYED_RESOURCE_TYPES set. + */ + get displayedResourceTypes() { + throw new Error("FileMigrator.displayedResourceTypes must be overridden"); + } + + /** + * Called to perform the file migration once the user makes a selection + * from the native file picker. This will not be called if the user + * chooses to cancel the native file picker. + * + * @param {string} filePath + * The path that the user selected from the native file picker. + */ + // eslint-disable-next-line no-unused-vars + async migrate(filePath) { + throw new Error("FileMigrator.migrate must be overridden."); + } +} + +/** + * A file migrator for importing passwords from CSV or TSV files. CSV + * files are more common, so this is what we show as the file type for + * the display name, but this FileMigrator accepts both. + */ +export class PasswordFileMigrator extends FileMigratorBase { + static get key() { + return "file-password-csv"; + } + + static get displayNameL10nID() { + return "migration-wizard-migrator-display-name-file-password-csv"; + } + + static get brandImage() { + return "chrome://branding/content/document.ico"; + } + + get enabled() { + return Services.prefs.getBoolPref( + "signon.management.page.fileImport.enabled", + false + ); + } + + get displayedResourceTypes() { + return [ + lazy.MigrationWizardConstants.DISPLAYED_FILE_RESOURCE_TYPES + .PASSWORDS_FROM_FILE, + ]; + } + + get progressHeaderL10nID() { + return "migration-passwords-from-file-progress-header"; + } + + get successHeaderL10nID() { + return "migration-passwords-from-file-success-header"; + } + + async getFilePickerConfig() { + let [title, csvFilterTitle, tsvFilterTitle] = + await lazy.gFluentStrings.formatValues([ + { id: "migration-passwords-from-file-picker-title" }, + { id: "migration-passwords-from-file-csv-filter-title" }, + { id: "migration-passwords-from-file-tsv-filter-title" }, + ]); + + return { + title, + filters: [ + { + title: csvFilterTitle, + extensionPattern: "*.csv", + }, + { + title: tsvFilterTitle, + extensionPattern: "*.tsv", + }, + ], + }; + } + + async migrate(filePath) { + try { + let summary = await lazy.LoginCSVImport.importFromCSV(filePath); + let newEntries = 0; + let updatedEntries = 0; + for (let entry of summary) { + if (entry.result == "added") { + newEntries++; + } else if (entry.result == "modified") { + updatedEntries++; + } + } + let [newMessage, updatedMessage] = await lazy.gFluentStrings.formatValues( + [ + { + id: "migration-wizard-progress-success-new-passwords", + args: { newEntries }, + }, + { + id: "migration-wizard-progress-success-updated-passwords", + args: { updatedEntries }, + }, + ] + ); + + Services.prefs.setBoolPref( + "browser.migrate.interactions.csvpasswords", + true + ); + + return { + [lazy.MigrationWizardConstants.DISPLAYED_FILE_RESOURCE_TYPES + .PASSWORDS_NEW]: newMessage, + [lazy.MigrationWizardConstants.DISPLAYED_FILE_RESOURCE_TYPES + .PASSWORDS_UPDATED]: updatedMessage, + }; + } catch (e) { + console.error(e); + + let errorMessage = await lazy.gFluentStrings.formatValue( + "migration-passwords-from-file-no-valid-data" + ); + throw new Error(errorMessage); + } + } +} + +/** + * A file migrator for importing bookmarks from a HTML or JSON file. + * + * @class BookmarksFileMigrator + * @augments {FileMigratorBase} + */ +export class BookmarksFileMigrator extends FileMigratorBase { + static get key() { + return "file-bookmarks"; + } + + static get displayNameL10nID() { + return "migration-wizard-migrator-display-name-file-bookmarks"; + } + + static get brandImage() { + return "chrome://branding/content/document.ico"; + } + + get enabled() { + return Services.prefs.getBoolPref( + "browser.migrate.bookmarks-file.enabled", + false + ); + } + + get displayedResourceTypes() { + return [ + lazy.MigrationWizardConstants.DISPLAYED_FILE_RESOURCE_TYPES + .BOOKMARKS_FROM_FILE, + ]; + } + + get progressHeaderL10nID() { + return "migration-bookmarks-from-file-progress-header"; + } + + get successHeaderL10nID() { + return "migration-bookmarks-from-file-success-header"; + } + + async getFilePickerConfig() { + let [title, htmlFilterTitle, jsonFilterTitle] = + await lazy.gFluentStrings.formatValues([ + { id: "migration-bookmarks-from-file-picker-title" }, + { id: "migration-bookmarks-from-file-html-filter-title" }, + { id: "migration-bookmarks-from-file-json-filter-title" }, + ]); + + return { + title, + filters: [ + { + title: htmlFilterTitle, + extensionPattern: "*.html", + }, + { + title: jsonFilterTitle, + extensionPattern: "*.json", + }, + ], + }; + } + + async migrate(filePath) { + try { + let pathCheck = filePath.toLowerCase(); + let importedCount; + + if (pathCheck.endsWith("html")) { + importedCount = await lazy.BookmarkHTMLUtils.importFromFile(filePath); + } else if (pathCheck.endsWith("json") || pathCheck.endsWith("jsonlz4")) { + importedCount = await lazy.BookmarkJSONUtils.importFromFile(filePath); + } + + if (!importedCount) { + // The catch will cause us to show a default error message. + throw new Error(); + } + + let importedMessage = await lazy.gFluentStrings.formatValue( + "migration-wizard-progress-success-new-bookmarks", + { + newEntries: importedCount, + } + ); + return { + [lazy.MigrationWizardConstants.DISPLAYED_FILE_RESOURCE_TYPES + .BOOKMARKS_FROM_FILE]: importedMessage, + }; + } catch (e) { + console.error(e); + + let errorMessage = await lazy.gFluentStrings.formatValue( + "migration-bookmarks-from-file-no-valid-data" + ); + throw new Error(errorMessage); + } + } +} |