diff options
Diffstat (limited to 'browser/components/migration/tests/unit/head_migration.js')
-rw-r--r-- | browser/components/migration/tests/unit/head_migration.js | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/browser/components/migration/tests/unit/head_migration.js b/browser/components/migration/tests/unit/head_migration.js new file mode 100644 index 0000000000..00db0734a0 --- /dev/null +++ b/browser/components/migration/tests/unit/head_migration.js @@ -0,0 +1,261 @@ +"use strict"; + +var { MigrationUtils } = ChromeUtils.importESModule( + "resource:///modules/MigrationUtils.sys.mjs" +); +var { LoginHelper } = ChromeUtils.importESModule( + "resource://gre/modules/LoginHelper.sys.mjs" +); +var { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm"); +var { PlacesUtils } = ChromeUtils.importESModule( + "resource://gre/modules/PlacesUtils.sys.mjs" +); +var { Preferences } = ChromeUtils.importESModule( + "resource://gre/modules/Preferences.sys.mjs" +); +var { PromiseUtils } = ChromeUtils.importESModule( + "resource://gre/modules/PromiseUtils.sys.mjs" +); +var { XPCOMUtils } = ChromeUtils.importESModule( + "resource://gre/modules/XPCOMUtils.sys.mjs" +); +var { TestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TestUtils.sys.mjs" +); +var { PlacesTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/PlacesTestUtils.sys.mjs" +); +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +ChromeUtils.defineESModuleGetters(this, { + FileUtils: "resource://gre/modules/FileUtils.sys.mjs", + Sqlite: "resource://gre/modules/Sqlite.sys.mjs", +}); + +// Initialize profile. +var gProfD = do_get_profile(); + +var { getAppInfo, newAppInfo, updateAppInfo } = ChromeUtils.importESModule( + "resource://testing-common/AppInfo.sys.mjs" +); +updateAppInfo(); + +/** + * Migrates the requested resource and waits for the migration to be complete. + * + * @param {MigratorBase} migrator + * The migrator being used to migrate the data. + * @param {number} resourceType + * This is a bitfield with bits from nsIBrowserProfileMigrator flipped to indicate what + * resources should be migrated. + * @param {object|string|null} [aProfile=null] + * The profile to be migrated. If set to null, the default profile will be + * migrated. + * @param {boolean} succeeds + * True if this migration is expected to succeed. + * @returns {Promise<Array<string[]>>} + * An array of the results from each nsIObserver topics being observed to + * verify if the migration succeeded or failed. Those results are 2-element + * arrays of [subject, data]. + */ +async function promiseMigration( + migrator, + resourceType, + aProfile = null, + succeeds = null +) { + // Ensure resource migration is available. + let availableSources = await migrator.getMigrateData(aProfile); + Assert.ok( + (availableSources & resourceType) > 0, + "Resource supported by migrator" + ); + let promises = [TestUtils.topicObserved("Migration:Ended")]; + + if (succeeds !== null) { + // Check that the specific resource type succeeded + promises.push( + TestUtils.topicObserved( + succeeds ? "Migration:ItemAfterMigrate" : "Migration:ItemError", + (_, data) => data == resourceType + ) + ); + } + + // Start the migration. + migrator.migrate(resourceType, null, aProfile); + + return Promise.all(promises); +} +/** + * Function that returns a favicon url for a given page url + * + * @param {string} uri + * The Bookmark URI + * @returns {string} faviconURI + * The Favicon URI + */ +async function getFaviconForPageURI(uri) { + let faviconURI = await new Promise(resolve => { + PlacesUtils.favicons.getFaviconDataForPage(uri, favURI => { + resolve(favURI); + }); + }); + return faviconURI; +} + +/** + * Takes an array of page URIs and checks that the favicon was imported for each page URI + * + * @param {Array} pageURIs An array of page URIs + */ +async function assertFavicons(pageURIs) { + for (let uri of pageURIs) { + let faviconURI = await getFaviconForPageURI(uri); + Assert.ok(faviconURI, `Got favicon for ${uri.spec}`); + } +} + +/** + * Replaces a directory service entry with a given nsIFile. + * + * @param {string} key + * The nsIDirectoryService directory key to register a fake path for. + * For example: "AppData", "ULibDir". + * @param {nsIFile} file + * The nsIFile to map the key to. Note that this nsIFile should represent + * a directory and not an individual file. + * @see nsDirectoryServiceDefs.h for the list of directories that can be + * overridden. + */ +function registerFakePath(key, file) { + let dirsvc = Services.dirsvc.QueryInterface(Ci.nsIProperties); + let originalFile; + try { + // If a file is already provided save it and undefine, otherwise set will + // throw for persistent entries (ones that are cached). + originalFile = dirsvc.get(key, Ci.nsIFile); + dirsvc.undefine(key); + } catch (e) { + // dirsvc.get will throw if nothing provides for the key and dirsvc.undefine + // will throw if it's not a persistent entry, in either case we don't want + // to set the original file in cleanup. + originalFile = undefined; + } + + dirsvc.set(key, file); + registerCleanupFunction(() => { + dirsvc.undefine(key); + if (originalFile) { + dirsvc.set(key, originalFile); + } + }); +} + +function getRootPath() { + let dirKey; + if (AppConstants.platform == "win") { + dirKey = "LocalAppData"; + } else if (AppConstants.platform == "macosx") { + dirKey = "ULibDir"; + } else { + dirKey = "Home"; + } + return Services.dirsvc.get(dirKey, Ci.nsIFile).path; +} + +/** + * Returns a PRTime value for the current date minus daysAgo number + * of days. + * + * @param {number} daysAgo + * How many days in the past from now the returned date should be. + * @returns {number} + */ +function PRTimeDaysAgo(daysAgo) { + return PlacesUtils.toPRTime(Date.now() - daysAgo * 24 * 60 * 60 * 1000); +} + +/** + * Returns a Date value for the current date minus daysAgo number + * of days. + * + * @param {number} daysAgo + * How many days in the past from now the returned date should be. + * @returns {Date} + */ +function dateDaysAgo(daysAgo) { + return new Date(Date.now() - daysAgo * 24 * 60 * 60 * 1000); +} + +/** + * Constructs and returns a data structure consistent with the Chrome + * browsers bookmarks storage. This data structure can then be serialized + * to JSON and written to disk to simulate a Chrome browser's bookmarks + * database. + * + * @param {number} [totalBookmarks=100] + * How many bookmarks to create. + * @returns {object} + */ +function createChromeBookmarkStructure(totalBookmarks = 100) { + let bookmarksData = { + roots: { + bookmark_bar: { children: [] }, + other: { children: [] }, + synced: { children: [] }, + }, + }; + const MAX_BMS = totalBookmarks; + let barKids = bookmarksData.roots.bookmark_bar.children; + let menuKids = bookmarksData.roots.other.children; + let syncedKids = bookmarksData.roots.synced.children; + let currentMenuKids = menuKids; + let currentBarKids = barKids; + let currentSyncedKids = syncedKids; + for (let i = 0; i < MAX_BMS; i++) { + currentBarKids.push({ + url: "https://www.chrome-bookmark-bar-bookmark" + i + ".com", + name: "bookmark " + i, + type: "url", + }); + currentMenuKids.push({ + url: "https://www.chrome-menu-bookmark" + i + ".com", + name: "bookmark for menu " + i, + type: "url", + }); + currentSyncedKids.push({ + url: "https://www.chrome-synced-bookmark" + i + ".com", + name: "bookmark for synced " + i, + type: "url", + }); + if (i % 20 == 19) { + let nextFolder = { + name: "toolbar folder " + Math.ceil(i / 20), + type: "folder", + children: [], + }; + currentBarKids.push(nextFolder); + currentBarKids = nextFolder.children; + + nextFolder = { + name: "menu folder " + Math.ceil(i / 20), + type: "folder", + children: [], + }; + currentMenuKids.push(nextFolder); + currentMenuKids = nextFolder.children; + + nextFolder = { + name: "synced folder " + Math.ceil(i / 20), + type: "folder", + children: [], + }; + currentSyncedKids.push(nextFolder); + currentSyncedKids = nextFolder.children; + } + } + return bookmarksData; +} |