diff options
Diffstat (limited to 'browser/components/migration')
24 files changed, 0 insertions, 3155 deletions
diff --git a/browser/components/migration/tests/browser/.eslintrc.js b/browser/components/migration/tests/browser/.eslintrc.js deleted file mode 100644 index 3ea6eeb8c..000000000 --- a/browser/components/migration/tests/browser/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -"use strict"; - -module.exports = { - "extends": [ - "../../../../../testing/mochitest/browser.eslintrc.js", - "../../../../../testing/mochitest/mochitest.eslintrc.js", - ] -}; - diff --git a/browser/components/migration/tests/browser/browser.ini b/browser/components/migration/tests/browser/browser.ini deleted file mode 100644 index 94edfe7aa..000000000 --- a/browser/components/migration/tests/browser/browser.ini +++ /dev/null @@ -1,3 +0,0 @@ -[browser_undo_notification.js] -[browser_undo_notification_wording.js] -[browser_undo_notification_multiple_dismissal.js] diff --git a/browser/components/migration/tests/browser/browser_undo_notification.js b/browser/components/migration/tests/browser/browser_undo_notification.js deleted file mode 100644 index 6c97922e0..000000000 --- a/browser/components/migration/tests/browser/browser_undo_notification.js +++ /dev/null @@ -1,67 +0,0 @@ -"use strict"; - -let scope = {}; -Cu.import("resource:///modules/AutoMigrate.jsm", scope); -let oldCanUndo = scope.AutoMigrate.canUndo; -let oldUndo = scope.AutoMigrate.undo; -registerCleanupFunction(function() { - scope.AutoMigrate.canUndo = oldCanUndo; - scope.AutoMigrate.undo = oldUndo; -}); - -const kExpectedNotificationId = "automigration-undo"; - -add_task(function* autoMigrationUndoNotificationShows() { - let getNotification = browser => - gBrowser.getNotificationBox(browser).getNotificationWithValue(kExpectedNotificationId); - - scope.AutoMigrate.canUndo = () => true; - let undoCalled; - scope.AutoMigrate.undo = () => { undoCalled = true }; - for (let url of ["about:newtab", "about:home"]) { - undoCalled = false; - // Can't use pushPrefEnv because of bug 1323779 - Services.prefs.setCharPref("browser.migrate.automigrate.browser", "someunknownbrowser"); - let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url, false); - let browser = tab.linkedBrowser; - if (!getNotification(browser)) { - info(`Notification for ${url} not immediately present, waiting for it.`); - yield BrowserTestUtils.waitForNotificationBar(gBrowser, browser, kExpectedNotificationId); - } - - ok(true, `Got notification for ${url}`); - let notification = getNotification(browser); - let notificationBox = notification.parentNode; - notification.querySelector("button.notification-button-default").click(); - ok(!undoCalled, "Undo should not be called when clicking the default button"); - is(notification, notificationBox._closedNotification, "Notification should be closing"); - yield BrowserTestUtils.removeTab(tab); - - undoCalled = false; - Services.prefs.setCharPref("browser.migrate.automigrate.browser", "chrome"); - tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url, false); - browser = tab.linkedBrowser; - if (!getNotification(browser)) { - info(`Notification for ${url} not immediately present, waiting for it.`); - yield BrowserTestUtils.waitForNotificationBar(gBrowser, browser, kExpectedNotificationId); - } - - ok(true, `Got notification for ${url}`); - notification = getNotification(browser); - notificationBox = notification.parentNode; - // Set up the survey: - yield SpecialPowers.pushPrefEnv({set: [ - ["browser.migrate.automigrate.undo-survey", "https://example.com/?browser=%IMPORTEDBROWSER%"], - ["browser.migrate.automigrate.undo-survey-locales", "en-US"], - ]}); - let tabOpenedPromise = BrowserTestUtils.waitForNewTab(gBrowser, "https://example.com/?browser=Google%20Chrome"); - notification.querySelector("button:not(.notification-button-default)").click(); - ok(undoCalled, "Undo should be called when clicking the non-default (Don't Keep) button"); - is(notification, notificationBox._closedNotification, "Notification should be closing"); - let surveyTab = yield tabOpenedPromise; - ok(surveyTab, "Should have opened a tab with a survey"); - yield BrowserTestUtils.removeTab(surveyTab); - yield BrowserTestUtils.removeTab(tab); - } -}); - diff --git a/browser/components/migration/tests/browser/browser_undo_notification_multiple_dismissal.js b/browser/components/migration/tests/browser/browser_undo_notification_multiple_dismissal.js deleted file mode 100644 index 90b5d0d08..000000000 --- a/browser/components/migration/tests/browser/browser_undo_notification_multiple_dismissal.js +++ /dev/null @@ -1,122 +0,0 @@ -"use strict"; - - -const kExpectedNotificationId = "automigration-undo"; - -/** - * Pretend we can undo something, trigger a notification, pick the undo option, - * and verify that the notifications are all dismissed immediately. - */ -add_task(function* checkNotificationsDismissed() { - yield SpecialPowers.pushPrefEnv({set: [ - ["browser.migrate.automigrate.enabled", true], - ["browser.migrate.automigrate.ui.enabled", true], - ]}); - let getNotification = browser => - gBrowser.getNotificationBox(browser).getNotificationWithValue(kExpectedNotificationId); - - Services.prefs.setCharPref("browser.migrate.automigrate.browser", "someunknownbrowser"); - - let {guid, lastModified} = yield PlacesUtils.bookmarks.insert( - {title: "Some imported bookmark", parentGuid: PlacesUtils.bookmarks.toolbarGuid, url: "http://www.example.com"} - ); - - let testUndoData = { - visits: [], - bookmarks: [{guid, lastModified: lastModified.getTime()}], - logins: [], - }; - let path = OS.Path.join(OS.Constants.Path.profileDir, "initialMigrationMetadata.jsonlz4"); - registerCleanupFunction(() => { - return OS.File.remove(path, {ignoreAbsent: true}); - }); - yield OS.File.writeAtomic(path, JSON.stringify(testUndoData), { - encoding: "utf-8", - compression: "lz4", - tmpPath: path + ".tmp", - }); - - let firstTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home", false); - if (!getNotification(firstTab.linkedBrowser)) { - info(`Notification not immediately present on first tab, waiting for it.`); - yield BrowserTestUtils.waitForNotificationBar(gBrowser, firstTab.linkedBrowser, kExpectedNotificationId); - } - let secondTab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:home", false); - if (!getNotification(secondTab.linkedBrowser)) { - info(`Notification not immediately present on second tab, waiting for it.`); - yield BrowserTestUtils.waitForNotificationBar(gBrowser, secondTab.linkedBrowser, kExpectedNotificationId); - } - - // Create a listener for the removal in the first tab, and a listener for bookmarks removal, - // then click 'Don't keep' in the second tab, and verify that the notification is removed - // before we start removing bookmarks. - let haveRemovedBookmark = false; - let bmObserver; - let bookmarkRemovedPromise = new Promise(resolve => { - bmObserver = { - onItemRemoved(itemId, parentId, index, itemType, uri, removedGuid) { - if (guid == removedGuid) { - haveRemovedBookmark = true; - resolve(); - } - }, - }; - PlacesUtils.bookmarks.addObserver(bmObserver, false); - registerCleanupFunction(() => PlacesUtils.bookmarks.removeObserver(bmObserver)); - }); - - let firstTabNotificationRemovedPromise = new Promise(resolve => { - let notification = getNotification(firstTab.linkedBrowser); - // Save this reference because notification.parentNode will be null once it's removed. - let notificationBox = notification.parentNode; - let mut = new MutationObserver(mutations => { - // Yucky, but we have to detect either the removal via animation (with marginTop) - // or when the element is removed. We can't just detect the element being removed - // because this happens asynchronously (after the animation) and so it'd race - // with the rest of the undo happening. - for (let mutation of mutations) { - if (mutation.target == notification && mutation.attributeName == "style" && - parseInt(notification.style.marginTop, 10) < 0) { - ok(!haveRemovedBookmark, "Should not have removed bookmark yet"); - mut.disconnect(); - resolve(); - return; - } - if (mutation.target == notificationBox && mutation.removedNodes.length && - mutation.removedNodes[0] == notification) { - ok(!haveRemovedBookmark, "Should not have removed bookmark yet"); - mut.disconnect(); - resolve(); - return; - } - } - }); - mut.observe(notification.parentNode, {childList: true}); - mut.observe(notification, {attributes: true}); - }); - - let prefResetPromise = new Promise(resolve => { - const kObservedPref = "browser.migrate.automigrate.browser"; - let obs = () => { - Services.prefs.removeObserver(kObservedPref, obs); - ok(!Services.prefs.prefHasUserValue(kObservedPref), - "Pref should have been reset"); - resolve(); - }; - Services.prefs.addObserver(kObservedPref, obs, false); - }); - - // Click "Don't keep" button: - let notificationToActivate = getNotification(secondTab.linkedBrowser); - notificationToActivate.querySelector("button:not(.notification-button-default)").click(); - info("Waiting for notification to be removed in first (background) tab"); - yield firstTabNotificationRemovedPromise; - info("Waiting for bookmark to be removed"); - yield bookmarkRemovedPromise; - info("Waiting for prefs to be reset"); - yield prefResetPromise; - - info("Removing spare tabs"); - yield BrowserTestUtils.removeTab(firstTab); - yield BrowserTestUtils.removeTab(secondTab); -}); diff --git a/browser/components/migration/tests/browser/browser_undo_notification_wording.js b/browser/components/migration/tests/browser/browser_undo_notification_wording.js deleted file mode 100644 index f0a9ceec9..000000000 --- a/browser/components/migration/tests/browser/browser_undo_notification_wording.js +++ /dev/null @@ -1,67 +0,0 @@ -"use strict"; - -let scope = {}; -Cu.import("resource:///modules/AutoMigrate.jsm", scope); -let oldCanUndo = scope.AutoMigrate.canUndo; -registerCleanupFunction(function() { - scope.AutoMigrate.canUndo = oldCanUndo; -}); - -const kExpectedNotificationId = "automigration-undo"; - -add_task(function* autoMigrationUndoNotificationShows() { - let getNotification = browser => - gBrowser.getNotificationBox(browser).getNotificationWithValue(kExpectedNotificationId); - let localizedVersionOf = str => { - if (str == "logins") { - return "passwords"; - } - if (str == "visits") { - return "history"; - } - return str; - }; - - scope.AutoMigrate.canUndo = () => true; - let url = "about:newtab"; - Services.prefs.setCharPref("browser.migrate.automigrate.browser", "someunknownbrowser"); - const kSubsets = [ - ["bookmarks", "logins", "visits"], - ["bookmarks", "logins"], - ["bookmarks", "visits"], - ["logins", "visits"], - ["bookmarks"], - ["logins"], - ["visits"], - ]; - const kAllItems = ["bookmarks", "logins", "visits"]; - for (let subset of kSubsets) { - let state = new Map(subset.map(item => [item, [{}]])); - scope.AutoMigrate._setImportedItemPrefFromState(state); - let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url, false); - let browser = tab.linkedBrowser; - - if (!getNotification(browser)) { - info(`Notification for ${url} not immediately present, waiting for it.`); - yield BrowserTestUtils.waitForNotificationBar(gBrowser, browser, kExpectedNotificationId); - } - - ok(true, `Got notification for ${url}`); - let notification = getNotification(browser); - let notificationText = document.getAnonymousElementByAttribute(notification, "class", "messageText"); - notificationText = notificationText.textContent; - for (let potentiallyImported of kAllItems) { - let localizedImportItem = localizedVersionOf(potentiallyImported); - if (subset.includes(potentiallyImported)) { - ok(notificationText.includes(localizedImportItem), - "Expected notification to contain " + localizedImportItem); - } else { - ok(!notificationText.includes(localizedImportItem), - "Expected notification not to contain " + localizedImportItem); - } - } - - yield BrowserTestUtils.removeTab(tab); - } -}); - diff --git a/browser/components/migration/tests/marionette/manifest.ini b/browser/components/migration/tests/marionette/manifest.ini deleted file mode 100644 index 3f404e724..000000000 --- a/browser/components/migration/tests/marionette/manifest.ini +++ /dev/null @@ -1,5 +0,0 @@ -[DEFAULT] -run-if = buildapp == 'browser' - -[test_refresh_firefox.py] - diff --git a/browser/components/migration/tests/marionette/test_refresh_firefox.py b/browser/components/migration/tests/marionette/test_refresh_firefox.py deleted file mode 100644 index b348a3dcd..000000000 --- a/browser/components/migration/tests/marionette/test_refresh_firefox.py +++ /dev/null @@ -1,416 +0,0 @@ -import os -import shutil - -from marionette_harness import MarionetteTestCase - - -class TestFirefoxRefresh(MarionetteTestCase): - _username = "marionette-test-login" - _password = "marionette-test-password" - _bookmarkURL = "about:mozilla" - _bookmarkText = "Some bookmark from Marionette" - - _cookieHost = "firefox-refresh.marionette-test.mozilla.org" - _cookiePath = "some/cookie/path" - _cookieName = "somecookie" - _cookieValue = "some cookie value" - - _historyURL = "http://firefox-refresh.marionette-test.mozilla.org/" - _historyTitle = "Test visit for Firefox Reset" - - _formHistoryFieldName = "some-very-unique-marionette-only-firefox-reset-field" - _formHistoryValue = "special-pumpkin-value" - - _expectedURLs = ["about:robots", "about:mozilla"] - - def savePassword(self): - self.runCode(""" - let myLogin = new global.LoginInfo( - "test.marionette.mozilla.com", - "http://test.marionette.mozilla.com/some/form/", - null, - arguments[0], - arguments[1], - "username", - "password" - ); - Services.logins.addLogin(myLogin) - """, script_args=[self._username, self._password]) - - def createBookmark(self): - self.marionette.execute_script(""" - let url = arguments[0]; - let title = arguments[1]; - PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.bookmarksMenuFolder, - makeURI(url), 0, title); - """, script_args=[self._bookmarkURL, self._bookmarkText]) - - def createHistory(self): - error = self.runAsyncCode(""" - // Copied from PlacesTestUtils, which isn't available in Marionette tests. - let didReturn; - PlacesUtils.asyncHistory.updatePlaces( - [{title: arguments[1], uri: makeURI(arguments[0]), visits: [{ - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - visitDate: (Date.now() - 5000) * 1000, - referrerURI: makeURI("about:mozilla"), - }] - }], - { - handleError(resultCode, place) { - didReturn = true; - marionetteScriptFinished("Unexpected error in adding visit: " + resultCode); - }, - handleResult() {}, - handleCompletion() { - if (!didReturn) { - marionetteScriptFinished(false); - } - }, - } - ); - """, script_args=[self._historyURL, self._historyTitle]) - if error: - print error - - def createFormHistory(self): - error = self.runAsyncCode(""" - let updateDefinition = { - op: "add", - fieldname: arguments[0], - value: arguments[1], - firstUsed: (Date.now() - 5000) * 1000, - }; - let finished = false; - global.FormHistory.update(updateDefinition, { - handleError(error) { - finished = true; - marionetteScriptFinished(error); - }, - handleCompletion() { - if (!finished) { - marionetteScriptFinished(false); - } - } - }); - """, script_args=[self._formHistoryFieldName, self._formHistoryValue]) - if error: - print error - - def createCookie(self): - self.runCode(""" - // Expire in 15 minutes: - let expireTime = Math.floor(Date.now() / 1000) + 15 * 60; - Services.cookies.add(arguments[0], arguments[1], arguments[2], arguments[3], - true, false, false, expireTime); - """, script_args=[self._cookieHost, self._cookiePath, self._cookieName, self._cookieValue]) - - def createSession(self): - self.runAsyncCode(""" - const COMPLETE_STATE = Ci.nsIWebProgressListener.STATE_STOP + - Ci.nsIWebProgressListener.STATE_IS_NETWORK; - let {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {}); - let expectedURLs = Array.from(arguments[0]) - gBrowser.addTabsProgressListener({ - onStateChange(browser, webprogress, request, flags, status) { - try { - request && request.QueryInterface(Ci.nsIChannel); - } catch (ex) {} - let uriLoaded = request.originalURI && request.originalURI.spec; - if ((flags & COMPLETE_STATE == COMPLETE_STATE) && uriLoaded && - expectedURLs.includes(uriLoaded)) { - TabStateFlusher.flush(browser).then(function() { - expectedURLs.splice(expectedURLs.indexOf(uriLoaded), 1); - if (!expectedURLs.length) { - gBrowser.removeTabsProgressListener(this); - marionetteScriptFinished(); - } - }); - } - } - }); - for (let url of expectedURLs) { - gBrowser.addTab(url); - } - """, script_args=[self._expectedURLs]) - - def checkPassword(self): - loginInfo = self.marionette.execute_script(""" - let ary = Services.logins.findLogins({}, - "test.marionette.mozilla.com", - "http://test.marionette.mozilla.com/some/form/", - null, {}); - return ary.length ? ary : {username: "null", password: "null"}; - """) - self.assertEqual(len(loginInfo), 1) - self.assertEqual(loginInfo[0]['username'], self._username) - self.assertEqual(loginInfo[0]['password'], self._password) - - loginCount = self.marionette.execute_script(""" - return Services.logins.getAllLogins().length; - """) - self.assertEqual(loginCount, 1, "No other logins are present") - - def checkBookmark(self): - titleInBookmarks = self.marionette.execute_script(""" - let url = arguments[0]; - let bookmarkIds = PlacesUtils.bookmarks.getBookmarkIdsForURI(makeURI(url), {}, {}); - return bookmarkIds.length == 1 ? PlacesUtils.bookmarks.getItemTitle(bookmarkIds[0]) : ""; - """, script_args=[self._bookmarkURL]) - self.assertEqual(titleInBookmarks, self._bookmarkText) - - def checkHistory(self): - historyResults = self.runAsyncCode(""" - let placeInfos = []; - PlacesUtils.asyncHistory.getPlacesInfo(makeURI(arguments[0]), { - handleError(resultCode, place) { - placeInfos = null; - marionetteScriptFinished("Unexpected error in fetching visit: " + resultCode); - }, - handleResult(placeInfo) { - placeInfos.push(placeInfo); - }, - handleCompletion() { - if (placeInfos) { - if (!placeInfos.length) { - marionetteScriptFinished("No visits found"); - } else { - marionetteScriptFinished(placeInfos); - } - } - }, - }); - """, script_args=[self._historyURL]) - if type(historyResults) == str: - self.fail(historyResults) - return - - historyCount = len(historyResults) - self.assertEqual(historyCount, 1, "Should have exactly 1 entry for URI, got %d" % historyCount) - if historyCount == 1: - self.assertEqual(historyResults[0]['title'], self._historyTitle) - - def checkFormHistory(self): - formFieldResults = self.runAsyncCode(""" - let results = []; - global.FormHistory.search(["value"], {fieldname: arguments[0]}, { - handleError(error) { - results = error; - }, - handleResult(result) { - results.push(result); - }, - handleCompletion() { - marionetteScriptFinished(results); - }, - }); - """, script_args=[self._formHistoryFieldName]) - if type(formFieldResults) == str: - self.fail(formFieldResults) - return - - formFieldResultCount = len(formFieldResults) - self.assertEqual(formFieldResultCount, 1, "Should have exactly 1 entry for this field, got %d" % formFieldResultCount) - if formFieldResultCount == 1: - self.assertEqual(formFieldResults[0]['value'], self._formHistoryValue) - - formHistoryCount = self.runAsyncCode(""" - let count; - let callbacks = { - handleResult: rv => count = rv, - handleCompletion() { - marionetteScriptFinished(count); - }, - }; - global.FormHistory.count({}, callbacks); - """) - self.assertEqual(formHistoryCount, 1, "There should be only 1 entry in the form history") - - def checkCookie(self): - cookieInfo = self.runCode(""" - try { - let cookieEnum = Services.cookies.getCookiesFromHost(arguments[0]); - let cookie = null; - while (cookieEnum.hasMoreElements()) { - let hostCookie = cookieEnum.getNext(); - hostCookie.QueryInterface(Ci.nsICookie2); - // getCookiesFromHost returns any cookie from the BASE host. - if (hostCookie.rawHost != arguments[0]) - continue; - if (cookie != null) { - return "more than 1 cookie! That shouldn't happen!"; - } - cookie = hostCookie; - } - return {path: cookie.path, name: cookie.name, value: cookie.value}; - } catch (ex) { - return "got exception trying to fetch cookie: " + ex; - } - """, script_args=[self._cookieHost]) - if not isinstance(cookieInfo, dict): - self.fail(cookieInfo) - return - self.assertEqual(cookieInfo['path'], self._cookiePath) - self.assertEqual(cookieInfo['value'], self._cookieValue) - self.assertEqual(cookieInfo['name'], self._cookieName) - - def checkSession(self): - tabURIs = self.runCode(""" - return [... gBrowser.browsers].map(b => b.currentURI && b.currentURI.spec) - """) - self.assertSequenceEqual(tabURIs, ["about:welcomeback"]) - - tabURIs = self.runAsyncCode(""" - let mm = gBrowser.selectedBrowser.messageManager; - let fs = function() { - content.document.getElementById("errorTryAgain").click(); - }; - let {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {}); - window.addEventListener("SSWindowStateReady", function testSSPostReset() { - window.removeEventListener("SSWindowStateReady", testSSPostReset, false); - Promise.all(gBrowser.browsers.map(b => TabStateFlusher.flush(b))).then(function() { - marionetteScriptFinished([... gBrowser.browsers].map(b => b.currentURI && b.currentURI.spec)); - }); - }, false); - mm.loadFrameScript("data:application/javascript,(" + fs.toString() + ")()", true); - """) - self.assertSequenceEqual(tabURIs, ["about:blank"] + self._expectedURLs) - pass - - def checkProfile(self, hasMigrated=False): - self.checkPassword() - self.checkBookmark() - self.checkHistory() - self.checkFormHistory() - self.checkCookie() - if hasMigrated: - self.checkSession() - - def createProfileData(self): - self.savePassword() - self.createBookmark() - self.createHistory() - self.createFormHistory() - self.createCookie() - self.createSession() - - def setUpScriptData(self): - self.marionette.set_context(self.marionette.CONTEXT_CHROME) - self.marionette.execute_script(""" - global.LoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1", "nsILoginInfo", "init"); - global.profSvc = Cc["@mozilla.org/toolkit/profile-service;1"].getService(Ci.nsIToolkitProfileService); - global.Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences; - global.FormHistory = Cu.import("resource://gre/modules/FormHistory.jsm", {}).FormHistory; - """, new_sandbox=False, sandbox='system') - - def runCode(self, script, *args, **kwargs): - return self.marionette.execute_script(script, new_sandbox=False, sandbox='system', *args, **kwargs) - - def runAsyncCode(self, script, *args, **kwargs): - return self.marionette.execute_async_script(script, new_sandbox=False, sandbox='system', *args, **kwargs) - - def setUp(self): - MarionetteTestCase.setUp(self) - self.setUpScriptData() - - self.reset_profile_path = None - self.desktop_backup_path = None - - self.createProfileData() - - def tearDown(self): - # Force yet another restart with a clean profile to disconnect from the - # profile and environment changes we've made, to leave a more or less - # blank slate for the next person. - self.marionette.restart(clean=True, in_app=False) - self.setUpScriptData() - - # Super - MarionetteTestCase.tearDown(self) - - # Some helpers to deal with removing a load of files - import errno, stat - def handleRemoveReadonly(func, path, exc): - excvalue = exc[1] - if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES: - os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777 - func(path) - else: - raise - - if self.desktop_backup_path: - shutil.rmtree(self.desktop_backup_path, ignore_errors=False, onerror=handleRemoveReadonly) - - if self.reset_profile_path: - # Remove ourselves from profiles.ini - profileLeafName = os.path.basename(os.path.normpath(self.reset_profile_path)) - self.runCode(""" - let [salt, name] = arguments[0].split("."); - let profile = global.profSvc.getProfileByName(name); - profile.remove(false) - global.profSvc.flush(); - """, script_args=[profileLeafName]) - # And delete all the files. - shutil.rmtree(self.reset_profile_path, ignore_errors=False, onerror=handleRemoveReadonly) - - def doReset(self): - self.runCode(""" - // Ensure the current (temporary) profile is in profiles.ini: - let profD = Services.dirsvc.get("ProfD", Ci.nsIFile); - let profileName = "marionette-test-profile-" + Date.now(); - let myProfile = global.profSvc.createProfile(profD, profileName); - global.profSvc.flush() - - // Now add the reset parameters: - let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment); - let allMarionettePrefs = Services.prefs.getChildList("marionette."); - let prefObj = {}; - for (let pref of allMarionettePrefs) { - let prefSuffix = pref.substr("marionette.".length); - let prefVal = global.Preferences.get(pref); - prefObj[prefSuffix] = prefVal; - } - let marionetteInfo = JSON.stringify(prefObj); - env.set("MOZ_MARIONETTE_PREF_STATE_ACROSS_RESTARTS", marionetteInfo); - env.set("MOZ_RESET_PROFILE_RESTART", "1"); - env.set("XRE_PROFILE_PATH", arguments[0]); - env.set("XRE_PROFILE_NAME", profileName); - """, script_args=[self.marionette.instance.profile.profile]) - - profileLeafName = os.path.basename(os.path.normpath(self.marionette.instance.profile.profile)) - - # Now restart the browser to get it reset: - self.marionette.restart(clean=False, in_app=True) - self.setUpScriptData() - - # Determine the new profile path (we'll need to remove it when we're done) - self.reset_profile_path = self.runCode(""" - let profD = Services.dirsvc.get("ProfD", Ci.nsIFile); - return profD.path; - """) - - # Determine the backup path - self.desktop_backup_path = self.runCode(""" - let container; - try { - container = Services.dirsvc.get("Desk", Ci.nsIFile); - } catch (ex) { - container = Services.dirsvc.get("Home", Ci.nsIFile); - } - let bundle = Services.strings.createBundle("chrome://mozapps/locale/profile/profileSelection.properties"); - let dirName = bundle.formatStringFromName("resetBackupDirectory", [Services.appinfo.name], 1); - container.append(dirName); - container.append(arguments[0]); - return container.path; - """, script_args = [profileLeafName]) - - self.assertTrue(os.path.isdir(self.reset_profile_path), "Reset profile path should be present") - self.assertTrue(os.path.isdir(self.desktop_backup_path), "Backup profile path should be present") - - def testReset(self): - self.checkProfile() - - self.doReset() - - # Now check that we're doing OK... - self.checkProfile(hasMigrated=True) diff --git a/browser/components/migration/tests/unit/.eslintrc.js b/browser/components/migration/tests/unit/.eslintrc.js deleted file mode 100644 index ba65517f9..000000000 --- a/browser/components/migration/tests/unit/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -"use strict"; - -module.exports = { // eslint-disable-line no-undef - "extends": [ - "../../../../../testing/xpcshell/xpcshell.eslintrc.js" - ] -}; diff --git a/browser/components/migration/tests/unit/AppData/Local/Google/Chrome/User Data/Default/Login Data b/browser/components/migration/tests/unit/AppData/Local/Google/Chrome/User Data/Default/Login Data Binary files differdeleted file mode 100644 index 914149c71..000000000 --- a/browser/components/migration/tests/unit/AppData/Local/Google/Chrome/User Data/Default/Login Data +++ /dev/null diff --git a/browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Default/Cookies b/browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Default/Cookies Binary files differdeleted file mode 100644 index 83d855cb3..000000000 --- a/browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Default/Cookies +++ /dev/null diff --git a/browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Local State b/browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Local State deleted file mode 100644 index 01b99455e..000000000 --- a/browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Local State +++ /dev/null @@ -1,22 +0,0 @@ -{ - "profile" : { - "info_cache" : { - "Default" : { - "active_time" : 1430950755.65137, - "is_using_default_name" : true, - "is_ephemeral" : false, - "is_omitted_from_profile_list" : false, - "user_name" : "", - "background_apps" : false, - "is_using_default_avatar" : true, - "avatar_icon" : "chrome://theme/IDR_PROFILE_AVATAR_0", - "name" : "Person 1" - } - }, - "profiles_created" : 1, - "last_used" : "Default", - "last_active_profiles" : [ - "Default" - ] - } -} diff --git a/browser/components/migration/tests/unit/Library/Safari/Bookmarks.plist b/browser/components/migration/tests/unit/Library/Safari/Bookmarks.plist Binary files differdeleted file mode 100644 index 40783c7b1..000000000 --- a/browser/components/migration/tests/unit/Library/Safari/Bookmarks.plist +++ /dev/null diff --git a/browser/components/migration/tests/unit/head_migration.js b/browser/components/migration/tests/unit/head_migration.js deleted file mode 100644 index d3c258d54..000000000 --- a/browser/components/migration/tests/unit/head_migration.js +++ /dev/null @@ -1,69 +0,0 @@ -"use strict"; - -/* exported gProfD, promiseMigration, registerFakePath */ - -var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; - -Cu.importGlobalProperties([ "URL" ]); - -Cu.import("resource:///modules/MigrationUtils.jsm"); -Cu.import("resource://gre/modules/LoginHelper.jsm"); -Cu.import("resource://gre/modules/NetUtil.jsm"); -Cu.import("resource://gre/modules/PlacesUtils.jsm"); -Cu.import("resource://gre/modules/Preferences.jsm"); -Cu.import("resource://gre/modules/PromiseUtils.jsm"); -Cu.import("resource://gre/modules/Task.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://testing-common/TestUtils.jsm"); -Cu.import("resource://testing-common/PlacesTestUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", - "resource://gre/modules/FileUtils.jsm"); - -// Initialize profile. -var gProfD = do_get_profile(); - -Cu.import("resource://testing-common/AppInfo.jsm"); /* globals updateAppInfo */ -updateAppInfo(); - -/** - * Migrates the requested resource and waits for the migration to be complete. - */ -function promiseMigration(migrator, resourceType, aProfile = null) { - // Ensure resource migration is available. - let availableSources = migrator.getMigrateData(aProfile, false); - Assert.ok((availableSources & resourceType) > 0, "Resource supported by migrator"); - - return new Promise (resolve => { - Services.obs.addObserver(function onMigrationEnded() { - Services.obs.removeObserver(onMigrationEnded, "Migration:Ended"); - resolve(); - }, "Migration:Ended", false); - - migrator.migrate(resourceType, null, aProfile); - }); -} - -/** - * Replaces a directory service entry with a given nsIFile. - */ -function registerFakePath(key, file) { - // Register our own provider for the Library directory. - let provider = { - getFile(prop, persistent) { - persistent.value = true; - if (prop == key) { - return file; - } - throw Cr.NS_ERROR_FAILURE; - }, - QueryInterface: XPCOMUtils.generateQI([ Ci.nsIDirectoryServiceProvider ]) - }; - Services.dirsvc.QueryInterface(Ci.nsIDirectoryService) - .registerProvider(provider); - do_register_cleanup(() => { - Services.dirsvc.QueryInterface(Ci.nsIDirectoryService) - .unregisterProvider(provider); - }); -} diff --git a/browser/components/migration/tests/unit/test_Chrome_cookies.js b/browser/components/migration/tests/unit/test_Chrome_cookies.js deleted file mode 100644 index 006693951..000000000 --- a/browser/components/migration/tests/unit/test_Chrome_cookies.js +++ /dev/null @@ -1,51 +0,0 @@ -"use strict"; - -Cu.import("resource://gre/modules/ForgetAboutSite.jsm"); - -add_task(function* () { - registerFakePath("ULibDir", do_get_file("Library/")); - let migrator = MigrationUtils.getMigrator("chrome"); - - Assert.ok(migrator.sourceExists, "Sanity check the source exists"); - - const COOKIE = { - expiry: 2145934800, - host: "unencryptedcookie.invalid", - isHttpOnly: false, - isSession: false, - name: "testcookie", - path: "/", - value: "testvalue", - }; - - // Sanity check. - Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 0, - "There are no cookies initially"); - - const PROFILE = { - id: "Default", - name: "Person 1", - }; - - // Migrate unencrypted cookies. - yield promiseMigration(migrator, MigrationUtils.resourceTypes.COOKIES, PROFILE); - - Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 1, - "Migrated the expected number of unencrypted cookies"); - Assert.equal(Services.cookies.countCookiesFromHost("encryptedcookie.invalid"), 0, - "Migrated the expected number of encrypted cookies"); - - // Now check the cookie details. - let enumerator = Services.cookies.getCookiesFromHost(COOKIE.host, {}); - Assert.ok(enumerator.hasMoreElements(), "Cookies available"); - let foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2); - - for (let prop of Object.keys(COOKIE)) { - Assert.equal(foundCookie[prop], COOKIE[prop], "Check cookie " + prop); - } - - // Cleanup. - ForgetAboutSite.removeDataFromDomain(COOKIE.host); - Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 0, - "There are no cookies after cleanup"); -}); diff --git a/browser/components/migration/tests/unit/test_Chrome_passwords.js b/browser/components/migration/tests/unit/test_Chrome_passwords.js deleted file mode 100644 index 49147bd61..000000000 --- a/browser/components/migration/tests/unit/test_Chrome_passwords.js +++ /dev/null @@ -1,219 +0,0 @@ -"use strict"; - -Cu.import("resource://gre/modules/OSCrypto.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -const PROFILE = { - id: "Default", - name: "Person 1", -}; - -const TEST_LOGINS = [ - { - id: 1, // id of the row in the chrome login db - username: "username", - password: "password", - hostname: "https://c9.io", - formSubmitURL: "https://c9.io", - httpRealm: null, - usernameField: "inputEmail", - passwordField: "inputPassword", - timeCreated: 1437418416037, - timePasswordChanged: 1437418416037, - timesUsed: 1, - }, - { - id: 2, - username: "username@gmail.com", - password: "password2", - hostname: "https://accounts.google.com", - formSubmitURL: "https://accounts.google.com", - httpRealm: null, - usernameField: "Email", - passwordField: "Passwd", - timeCreated: 1437418446598, - timePasswordChanged: 1437418446598, - timesUsed: 6, - }, - { - id: 3, - username: "username", - password: "password3", - hostname: "https://www.facebook.com", - formSubmitURL: "https://www.facebook.com", - httpRealm: null, - usernameField: "email", - passwordField: "pass", - timeCreated: 1437418478851, - timePasswordChanged: 1437418478851, - timesUsed: 1, - }, - { - id: 4, - username: "user", - password: "password", - hostname: "http://httpbin.org", - formSubmitURL: null, - httpRealm: "me@kennethreitz.com", // Digest auth. - usernameField: "", - passwordField: "", - timeCreated: 1437787462368, - timePasswordChanged: 1437787462368, - timesUsed: 1, - }, - { - id: 5, - username: "buser", - password: "bpassword", - hostname: "http://httpbin.org", - formSubmitURL: null, - httpRealm: "Fake Realm", // Basic auth. - usernameField: "", - passwordField: "", - timeCreated: 1437787539233, - timePasswordChanged: 1437787539233, - timesUsed: 1, - }, -]; - -var crypto = new OSCrypto(); -var dbConn; - -function promiseSetPassword(login) { - return new Promise((resolve, reject) => { - let stmt = dbConn.createAsyncStatement(` - UPDATE logins - SET password_value = :password_value - WHERE rowid = :rowid - `); - let passwordValue = crypto.stringToArray(crypto.encryptData(login.password)); - stmt.bindBlobByName("password_value", passwordValue, passwordValue.length); - stmt.params.rowid = login.id; - - stmt.executeAsync({ - handleError(aError) { - reject("Error with the query: " + aError.message); - }, - - handleCompletion(aReason) { - if (aReason === Ci.mozIStorageStatementCallback.REASON_FINISHED) { - resolve(); - } else { - reject("Query has failed: " + aReason); - } - }, - }); - stmt.finalize(); - }); -} - -function checkLoginsAreEqual(passwordManagerLogin, chromeLogin, id) { - passwordManagerLogin.QueryInterface(Ci.nsILoginMetaInfo); - - Assert.equal(passwordManagerLogin.username, chromeLogin.username, - "The two logins ID " + id + " have the same username"); - Assert.equal(passwordManagerLogin.password, chromeLogin.password, - "The two logins ID " + id + " have the same password"); - Assert.equal(passwordManagerLogin.hostname, chromeLogin.hostname, - "The two logins ID " + id + " have the same hostname"); - Assert.equal(passwordManagerLogin.formSubmitURL, chromeLogin.formSubmitURL, - "The two logins ID " + id + " have the same formSubmitURL"); - Assert.equal(passwordManagerLogin.httpRealm, chromeLogin.httpRealm, - "The two logins ID " + id + " have the same httpRealm"); - Assert.equal(passwordManagerLogin.usernameField, chromeLogin.usernameField, - "The two logins ID " + id + " have the same usernameElement"); - Assert.equal(passwordManagerLogin.passwordField, chromeLogin.passwordField, - "The two logins ID " + id + " have the same passwordElement"); - Assert.equal(passwordManagerLogin.timeCreated, chromeLogin.timeCreated, - "The two logins ID " + id + " have the same timeCreated"); - Assert.equal(passwordManagerLogin.timePasswordChanged, chromeLogin.timePasswordChanged, - "The two logins ID " + id + " have the same timePasswordChanged"); - Assert.equal(passwordManagerLogin.timesUsed, chromeLogin.timesUsed, - "The two logins ID " + id + " have the same timesUsed"); -} - -function generateDifferentLogin(login) { - let newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].createInstance(Ci.nsILoginInfo); - - newLogin.init(login.hostname, login.formSubmitURL, null, - login.username, login.password + 1, login.usernameField + 1, - login.passwordField + 1); - newLogin.QueryInterface(Ci.nsILoginMetaInfo); - newLogin.timeCreated = login.timeCreated + 1; - newLogin.timePasswordChanged = login.timePasswordChanged + 1; - newLogin.timesUsed = login.timesUsed + 1; - return newLogin; -} - -add_task(function* setup() { - let loginDataFile = do_get_file("AppData/Local/Google/Chrome/User Data/Default/Login Data"); - dbConn = Services.storage.openUnsharedDatabase(loginDataFile); - registerFakePath("LocalAppData", do_get_file("AppData/Local/")); - - do_register_cleanup(() => { - Services.logins.removeAllLogins(); - dbConn.asyncClose(); - crypto.finalize(); - }); -}); - -add_task(function* test_importIntoEmptyDB() { - for (let login of TEST_LOGINS) { - yield promiseSetPassword(login); - } - - let migrator = MigrationUtils.getMigrator("chrome"); - Assert.ok(migrator.sourceExists, "Sanity check the source exists"); - - let logins = Services.logins.getAllLogins({}); - Assert.equal(logins.length, 0, "There are no logins initially"); - - // Migrate the logins. - yield promiseMigration(migrator, MigrationUtils.resourceTypes.PASSWORDS, PROFILE); - - logins = Services.logins.getAllLogins({}); - Assert.equal(logins.length, TEST_LOGINS.length, "Check login count after importing the data"); - Assert.equal(logins.length, MigrationUtils._importQuantities.logins, - "Check telemetry matches the actual import."); - - for (let i = 0; i < TEST_LOGINS.length; i++) { - checkLoginsAreEqual(logins[i], TEST_LOGINS[i], i + 1); - } -}); - -// Test that existing logins for the same primary key don't get overwritten -add_task(function* test_importExistingLogins() { - let migrator = MigrationUtils.getMigrator("chrome"); - Assert.ok(migrator.sourceExists, "Sanity check the source exists"); - - Services.logins.removeAllLogins(); - let logins = Services.logins.getAllLogins({}); - Assert.equal(logins.length, 0, "There are no logins after removing all of them"); - - let newLogins = []; - - // Create 3 new logins that are different but where the key properties are still the same. - for (let i = 0; i < 3; i++) { - newLogins.push(generateDifferentLogin(TEST_LOGINS[i])); - Services.logins.addLogin(newLogins[i]); - } - - logins = Services.logins.getAllLogins({}); - Assert.equal(logins.length, newLogins.length, "Check login count after the insertion"); - - for (let i = 0; i < newLogins.length; i++) { - checkLoginsAreEqual(logins[i], newLogins[i], i + 1); - } - // Migrate the logins. - yield promiseMigration(migrator, MigrationUtils.resourceTypes.PASSWORDS, PROFILE); - - logins = Services.logins.getAllLogins({}); - Assert.equal(logins.length, TEST_LOGINS.length, - "Check there are still the same number of logins after re-importing the data"); - Assert.equal(logins.length, MigrationUtils._importQuantities.logins, - "Check telemetry matches the actual import."); - - for (let i = 0; i < newLogins.length; i++) { - checkLoginsAreEqual(logins[i], newLogins[i], i + 1); - } -}); diff --git a/browser/components/migration/tests/unit/test_Edge_availability.js b/browser/components/migration/tests/unit/test_Edge_availability.js deleted file mode 100644 index dba0e27bb..000000000 --- a/browser/components/migration/tests/unit/test_Edge_availability.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; - -const EDGE_AVAILABLE_MIGRATIONS = - MigrationUtils.resourceTypes.COOKIES | - MigrationUtils.resourceTypes.BOOKMARKS | - MigrationUtils.resourceTypes.HISTORY | - MigrationUtils.resourceTypes.PASSWORDS; - -add_task(function* () { - let migrator = MigrationUtils.getMigrator("edge"); - Cu.import("resource://gre/modules/AppConstants.jsm"); - Assert.equal(!!(migrator && migrator.sourceExists), AppConstants.isPlatformAndVersionAtLeast("win", "10"), - "Edge should be available for migration if and only if we're on Win 10+"); - if (migrator) { - let migratableData = migrator.getMigrateData(null, false); - Assert.equal(migratableData, EDGE_AVAILABLE_MIGRATIONS, - "All the data types we expect should be available"); - } -}); - diff --git a/browser/components/migration/tests/unit/test_Edge_db_migration.js b/browser/components/migration/tests/unit/test_Edge_db_migration.js deleted file mode 100644 index 56ff612d5..000000000 --- a/browser/components/migration/tests/unit/test_Edge_db_migration.js +++ /dev/null @@ -1,471 +0,0 @@ -"use strict"; - -Cu.import("resource://gre/modules/ctypes.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -let eseBackStage = Cu.import("resource:///modules/ESEDBReader.jsm"); -let ESE = eseBackStage.ESE; -let KERNEL = eseBackStage.KERNEL; -let gLibs = eseBackStage.gLibs; -let COLUMN_TYPES = eseBackStage.COLUMN_TYPES; -let declareESEFunction = eseBackStage.declareESEFunction; -let loadLibraries = eseBackStage.loadLibraries; - -let gESEInstanceCounter = 1; - -ESE.JET_COLUMNCREATE_W = new ctypes.StructType("JET_COLUMNCREATE_W", [ - {"cbStruct": ctypes.unsigned_long}, - {"szColumnName": ESE.JET_PCWSTR}, - {"coltyp": ESE.JET_COLTYP }, - {"cbMax": ctypes.unsigned_long }, - {"grbit": ESE.JET_GRBIT }, - {"pvDefault": ctypes.voidptr_t}, - {"cbDefault": ctypes.unsigned_long }, - {"cp": ctypes.unsigned_long }, - {"columnid": ESE.JET_COLUMNID}, - {"err": ESE.JET_ERR}, -]); - -function createColumnCreationWrapper({name, type, cbMax}) { - // We use a wrapper object because we need to be sure the JS engine won't GC - // data that we're "only" pointing to. - let wrapper = {}; - wrapper.column = new ESE.JET_COLUMNCREATE_W(); - wrapper.column.cbStruct = ESE.JET_COLUMNCREATE_W.size; - let wchar_tArray = ctypes.ArrayType(ctypes.char16_t); - wrapper.name = new wchar_tArray(name.length + 1); - wrapper.name.value = String(name); - wrapper.column.szColumnName = wrapper.name; - wrapper.column.coltyp = type; - let fallback = 0; - switch (type) { - case COLUMN_TYPES.JET_coltypText: - fallback = 255; - // Intentional fall-through - case COLUMN_TYPES.JET_coltypLongText: - wrapper.column.cbMax = cbMax || fallback || 64 * 1024; - break; - case COLUMN_TYPES.JET_coltypGUID: - wrapper.column.cbMax = 16; - break; - case COLUMN_TYPES.JET_coltypBit: - wrapper.column.cbMax = 1; - break; - case COLUMN_TYPES.JET_coltypLongLong: - wrapper.column.cbMax = 8; - break; - default: - throw new Error("Unknown column type!"); - } - - wrapper.column.columnid = new ESE.JET_COLUMNID(); - wrapper.column.grbit = 0; - wrapper.column.pvDefault = null; - wrapper.column.cbDefault = 0; - wrapper.column.cp = 0; - - return wrapper; -} - -// "forward declarations" of indexcreate and setinfo structs, which we don't use. -ESE.JET_INDEXCREATE = new ctypes.StructType("JET_INDEXCREATE"); -ESE.JET_SETINFO = new ctypes.StructType("JET_SETINFO"); - -ESE.JET_TABLECREATE_W = new ctypes.StructType("JET_TABLECREATE_W", [ - {"cbStruct": ctypes.unsigned_long}, - {"szTableName": ESE.JET_PCWSTR}, - {"szTemplateTableName": ESE.JET_PCWSTR}, - {"ulPages": ctypes.unsigned_long}, - {"ulDensity": ctypes.unsigned_long}, - {"rgcolumncreate": ESE.JET_COLUMNCREATE_W.ptr}, - {"cColumns": ctypes.unsigned_long}, - {"rgindexcreate": ESE.JET_INDEXCREATE.ptr}, - {"cIndexes": ctypes.unsigned_long}, - {"grbit": ESE.JET_GRBIT}, - {"tableid": ESE.JET_TABLEID}, - {"cCreated": ctypes.unsigned_long}, -]); - -function createTableCreationWrapper(tableName, columns) { - let wrapper = {}; - let wchar_tArray = ctypes.ArrayType(ctypes.char16_t); - wrapper.name = new wchar_tArray(tableName.length + 1); - wrapper.name.value = String(tableName); - wrapper.table = new ESE.JET_TABLECREATE_W(); - wrapper.table.cbStruct = ESE.JET_TABLECREATE_W.size; - wrapper.table.szTableName = wrapper.name; - wrapper.table.szTemplateTableName = null; - wrapper.table.ulPages = 1; - wrapper.table.ulDensity = 0; - let columnArrayType = ESE.JET_COLUMNCREATE_W.array(columns.length); - wrapper.columnAry = new columnArrayType(); - wrapper.table.rgcolumncreate = wrapper.columnAry.addressOfElement(0); - wrapper.table.cColumns = columns.length; - wrapper.columns = []; - for (let i = 0; i < columns.length; i++) { - let column = columns[i]; - let columnWrapper = createColumnCreationWrapper(column); - wrapper.columnAry.addressOfElement(i).contents = columnWrapper.column; - wrapper.columns.push(columnWrapper); - } - wrapper.table.rgindexcreate = null; - wrapper.table.cIndexes = 0; - return wrapper; -} - -function convertValueForWriting(value, valueType) { - let buffer; - let valueOfValueType = ctypes.UInt64.lo(valueType); - switch (valueOfValueType) { - case COLUMN_TYPES.JET_coltypLongLong: - if (value instanceof Date) { - buffer = new KERNEL.FILETIME(); - let sysTime = new KERNEL.SYSTEMTIME(); - sysTime.wYear = value.getUTCFullYear(); - sysTime.wMonth = value.getUTCMonth() + 1; - sysTime.wDay = value.getUTCDate(); - sysTime.wHour = value.getUTCHours(); - sysTime.wMinute = value.getUTCMinutes(); - sysTime.wSecond = value.getUTCSeconds(); - sysTime.wMilliseconds = value.getUTCMilliseconds(); - let rv = KERNEL.SystemTimeToFileTime(sysTime.address(), buffer.address()); - if (!rv) { - throw new Error("Failed to get FileTime."); - } - return [buffer, KERNEL.FILETIME.size]; - } - throw new Error("Unrecognized value for longlong column"); - case COLUMN_TYPES.JET_coltypLongText: - let wchar_tArray = ctypes.ArrayType(ctypes.char16_t); - buffer = new wchar_tArray(value.length + 1); - buffer.value = String(value); - return [buffer, buffer.length * 2]; - case COLUMN_TYPES.JET_coltypBit: - buffer = new ctypes.uint8_t(); - // Bizarre boolean values, but whatever: - buffer.value = value ? 255 : 0; - return [buffer, 1]; - case COLUMN_TYPES.JET_coltypGUID: - let byteArray = ctypes.ArrayType(ctypes.uint8_t); - buffer = new byteArray(16); - let j = 0; - for (let i = 0; i < value.length; i++) { - if (!(/[0-9a-f]/i).test(value[i])) { - continue; - } - let byteAsHex = value.substr(i, 2); - buffer[j++] = parseInt(byteAsHex, 16); - i++; - } - return [buffer, 16]; - } - - throw new Error("Unknown type " + valueType); -} - -let initializedESE = false; - -let eseDBWritingHelpers = { - setupDB(dbFile, tableName, columns, rows) { - if (!initializedESE) { - initializedESE = true; - loadLibraries(); - - KERNEL.SystemTimeToFileTime = gLibs.kernel.declare("SystemTimeToFileTime", - ctypes.default_abi, ctypes.bool, KERNEL.SYSTEMTIME.ptr, KERNEL.FILETIME.ptr); - - declareESEFunction("CreateDatabaseW", ESE.JET_SESID, ESE.JET_PCWSTR, - ESE.JET_PCWSTR, ESE.JET_DBID.ptr, ESE.JET_GRBIT); - declareESEFunction("CreateTableColumnIndexW", ESE.JET_SESID, ESE.JET_DBID, - ESE.JET_TABLECREATE_W.ptr); - declareESEFunction("BeginTransaction", ESE.JET_SESID); - declareESEFunction("CommitTransaction", ESE.JET_SESID, ESE.JET_GRBIT); - declareESEFunction("PrepareUpdate", ESE.JET_SESID, ESE.JET_TABLEID, - ctypes.unsigned_long); - declareESEFunction("Update", ESE.JET_SESID, ESE.JET_TABLEID, - ctypes.voidptr_t, ctypes.unsigned_long, - ctypes.unsigned_long.ptr); - declareESEFunction("SetColumn", ESE.JET_SESID, ESE.JET_TABLEID, - ESE.JET_COLUMNID, ctypes.voidptr_t, - ctypes.unsigned_long, ESE.JET_GRBIT, ESE.JET_SETINFO.ptr); - ESE.SetSystemParameterW(null, 0, 64 /* JET_paramDatabasePageSize*/, - 8192, null); - } - - let rootPath = dbFile.parent.path + "\\"; - let logPath = rootPath + "LogFiles\\"; - - try { - this._instanceId = new ESE.JET_INSTANCE(); - ESE.CreateInstanceW(this._instanceId.address(), - "firefox-dbwriter-" + (gESEInstanceCounter++)); - this._instanceCreated = true; - - ESE.SetSystemParameterW(this._instanceId.address(), 0, - 0 /* JET_paramSystemPath*/, 0, rootPath); - ESE.SetSystemParameterW(this._instanceId.address(), 0, - 1 /* JET_paramTempPath */, 0, rootPath); - ESE.SetSystemParameterW(this._instanceId.address(), 0, - 2 /* JET_paramLogFilePath*/, 0, logPath); - // Shouldn't try to call JetTerm if the following call fails. - this._instanceCreated = false; - ESE.Init(this._instanceId.address()); - this._instanceCreated = true; - this._sessionId = new ESE.JET_SESID(); - ESE.BeginSessionW(this._instanceId, this._sessionId.address(), null, - null); - this._sessionCreated = true; - - this._dbId = new ESE.JET_DBID(); - this._dbPath = rootPath + "spartan.edb"; - ESE.CreateDatabaseW(this._sessionId, this._dbPath, null, - this._dbId.address(), 0); - this._opened = this._attached = true; - - let tableCreationWrapper = createTableCreationWrapper(tableName, columns); - ESE.CreateTableColumnIndexW(this._sessionId, this._dbId, - tableCreationWrapper.table.address()); - this._tableId = tableCreationWrapper.table.tableid; - - let columnIdMap = new Map(); - if (rows.length) { - // Iterate over the struct we passed into ESENT because they have the - // created column ids. - let columnCount = ctypes.UInt64.lo(tableCreationWrapper.table.cColumns); - let columnsPassed = tableCreationWrapper.table.rgcolumncreate; - for (let i = 0; i < columnCount; i++) { - let column = columnsPassed.contents; - columnIdMap.set(column.szColumnName.readString(), column); - columnsPassed = columnsPassed.increment(); - } - ESE.ManualMove(this._sessionId, this._tableId, - -2147483648 /* JET_MoveFirst */, 0); - ESE.BeginTransaction(this._sessionId); - for (let row of rows) { - ESE.PrepareUpdate(this._sessionId, this._tableId, 0 /* JET_prepInsert */); - for (let columnName in row) { - let col = columnIdMap.get(columnName); - let colId = col.columnid; - let [val, valSize] = convertValueForWriting(row[columnName], col.coltyp); - /* JET_bitSetOverwriteLV */ - ESE.SetColumn(this._sessionId, this._tableId, colId, val.address(), valSize, 4, null); - } - let actualBookmarkSize = new ctypes.unsigned_long(); - ESE.Update(this._sessionId, this._tableId, null, 0, actualBookmarkSize.address()); - } - ESE.CommitTransaction(this._sessionId, 0 /* JET_bitWaitLastLevel0Commit */); - } - } finally { - try { - this._close(); - } catch (ex) { - Cu.reportError(ex); - } - } - }, - - _close() { - if (this._tableId) { - ESE.FailSafeCloseTable(this._sessionId, this._tableId); - delete this._tableId; - } - if (this._opened) { - ESE.FailSafeCloseDatabase(this._sessionId, this._dbId, 0); - this._opened = false; - } - if (this._attached) { - ESE.FailSafeDetachDatabaseW(this._sessionId, this._dbPath); - this._attached = false; - } - if (this._sessionCreated) { - ESE.FailSafeEndSession(this._sessionId, 0); - this._sessionCreated = false; - } - if (this._instanceCreated) { - ESE.FailSafeTerm(this._instanceId); - this._instanceCreated = false; - } - }, -}; - -add_task(function*() { - let tempFile = Services.dirsvc.get("TmpD", Ci.nsIFile); - tempFile.append("fx-xpcshell-edge-db"); - tempFile.createUnique(tempFile.DIRECTORY_TYPE, 0o600); - - let db = tempFile.clone(); - db.append("spartan.edb"); - - let logs = tempFile.clone(); - logs.append("LogFiles"); - logs.create(tempFile.DIRECTORY_TYPE, 0o600); - - let creationDate = new Date(Date.now() - 5000); - const kEdgeMenuParent = "62d07e2b-5f0d-4e41-8426-5f5ec9717beb"; - let itemsInDB = [ - { - URL: "http://www.mozilla.org/", - Title: "Mozilla", - DateUpdated: new Date(creationDate.valueOf() + 100), - ItemId: "1c00c10a-15f6-4618-92dd-22575102a4da", - ParentId: kEdgeMenuParent, - IsFolder: false, - IsDeleted: false, - }, - { - Title: "Folder", - DateUpdated: new Date(creationDate.valueOf() + 200), - ItemId: "564b21f2-05d6-4f7d-8499-304d00ccc3aa", - ParentId: kEdgeMenuParent, - IsFolder: true, - IsDeleted: false, - }, - { - Title: "Item in folder", - URL: "http://www.iteminfolder.org/", - DateUpdated: new Date(creationDate.valueOf() + 300), - ItemId: "c295ddaf-04a1-424a-866c-0ebde011e7c8", - ParentId: "564b21f2-05d6-4f7d-8499-304d00ccc3aa", - IsFolder: false, - IsDeleted: false, - }, - { - Title: "Deleted folder", - DateUpdated: new Date(creationDate.valueOf() + 400), - ItemId: "a547573c-4d4d-4406-a736-5b5462d93bca", - ParentId: kEdgeMenuParent, - IsFolder: true, - IsDeleted: true, - }, - { - Title: "Deleted item", - URL: "http://www.deleteditem.org/", - DateUpdated: new Date(creationDate.valueOf() + 500), - ItemId: "37a574bb-b44b-4bbc-a414-908615536435", - ParentId: kEdgeMenuParent, - IsFolder: false, - IsDeleted: true, - }, - { - Title: "Item in deleted folder (should be in root)", - URL: "http://www.itemindeletedfolder.org/", - DateUpdated: new Date(creationDate.valueOf() + 600), - ItemId: "74dd1cc3-4c5d-471f-bccc-7bc7c72fa621", - ParentId: "a547573c-4d4d-4406-a736-5b5462d93bca", - IsFolder: false, - IsDeleted: false, - }, - { - Title: "_Favorites_Bar_", - DateUpdated: new Date(creationDate.valueOf() + 700), - ItemId: "921dc8a0-6c83-40ef-8df1-9bd1c5c56aaf", - ParentId: kEdgeMenuParent, - IsFolder: true, - IsDeleted: false, - }, - { - Title: "Item in favorites bar", - URL: "http://www.iteminfavoritesbar.org/", - DateUpdated: new Date(creationDate.valueOf() + 800), - ItemId: "9f2b1ff8-b651-46cf-8f41-16da8bcb6791", - ParentId: "921dc8a0-6c83-40ef-8df1-9bd1c5c56aaf", - IsFolder: false, - IsDeleted: false, - }, - ]; - eseDBWritingHelpers.setupDB(db, "Favorites", [ - {type: COLUMN_TYPES.JET_coltypLongText, name: "URL", cbMax: 4096}, - {type: COLUMN_TYPES.JET_coltypLongText, name: "Title", cbMax: 4096}, - {type: COLUMN_TYPES.JET_coltypLongLong, name: "DateUpdated"}, - {type: COLUMN_TYPES.JET_coltypGUID, name: "ItemId"}, - {type: COLUMN_TYPES.JET_coltypBit, name: "IsDeleted"}, - {type: COLUMN_TYPES.JET_coltypBit, name: "IsFolder"}, - {type: COLUMN_TYPES.JET_coltypGUID, name: "ParentId"}, - ], itemsInDB); - - let migrator = Cc["@mozilla.org/profile/migrator;1?app=browser&type=edge"] - .createInstance(Ci.nsIBrowserProfileMigrator); - let bookmarksMigrator = migrator.wrappedJSObject.getESEMigratorForTesting(db); - Assert.ok(bookmarksMigrator.exists, "Should recognize table we just created"); - - let source = MigrationUtils.getLocalizedString("sourceNameEdge"); - let sourceLabel = MigrationUtils.getLocalizedString("importedBookmarksFolder", [source]); - - let seenBookmarks = []; - let bookmarkObserver = { - onItemAdded(itemId, parentId, index, itemType, url, title, dateAdded, itemGuid, parentGuid) { - if (title.startsWith("Deleted")) { - ok(false, "Should not see deleted items being bookmarked!"); - } - seenBookmarks.push({itemId, parentId, index, itemType, url, title, dateAdded, itemGuid, parentGuid}); - }, - onBeginUpdateBatch() {}, - onEndUpdateBatch() {}, - onItemRemoved() {}, - onItemChanged() {}, - onItemVisited() {}, - onItemMoved() {}, - }; - PlacesUtils.bookmarks.addObserver(bookmarkObserver, false); - - let migrateResult = yield new Promise(resolve => bookmarksMigrator.migrate(resolve)).catch(ex => { - Cu.reportError(ex); - Assert.ok(false, "Got an exception trying to migrate data! " + ex); - return false; - }); - PlacesUtils.bookmarks.removeObserver(bookmarkObserver); - Assert.ok(migrateResult, "Migration should succeed"); - Assert.equal(seenBookmarks.length, 7, "Should have seen 7 items being bookmarked."); - Assert.equal(seenBookmarks.filter(bm => bm.title != sourceLabel).length, - MigrationUtils._importQuantities.bookmarks, - "Telemetry should have items except for 'From Microsoft Edge' folders"); - - let menuParents = seenBookmarks.filter(item => item.parentGuid == PlacesUtils.bookmarks.menuGuid); - Assert.equal(menuParents.length, 1, "Should have a single folder added to the menu"); - let toolbarParents = seenBookmarks.filter(item => item.parentGuid == PlacesUtils.bookmarks.toolbarGuid); - Assert.equal(toolbarParents.length, 1, "Should have a single item added to the toolbar"); - let menuParentGuid = menuParents[0].itemGuid; - let toolbarParentGuid = toolbarParents[0].itemGuid; - - let expectedTitlesInMenu = itemsInDB.filter(item => item.ParentId == kEdgeMenuParent).map(item => item.Title); - // Hacky, but seems like much the simplest way: - expectedTitlesInMenu.push("Item in deleted folder (should be in root)"); - let expectedTitlesInToolbar = itemsInDB.filter(item => item.ParentId == "921dc8a0-6c83-40ef-8df1-9bd1c5c56aaf").map(item => item.Title); - - let edgeNameStr = MigrationUtils.getLocalizedString("sourceNameEdge"); - let importParentFolderName = MigrationUtils.getLocalizedString("importedBookmarksFolder", [edgeNameStr]); - - for (let bookmark of seenBookmarks) { - let shouldBeInMenu = expectedTitlesInMenu.includes(bookmark.title); - let shouldBeInToolbar = expectedTitlesInToolbar.includes(bookmark.title); - if (bookmark.title == "Folder" || bookmark.title == importParentFolderName) { - Assert.equal(bookmark.itemType, PlacesUtils.bookmarks.TYPE_FOLDER, - "Bookmark " + bookmark.title + " should be a folder"); - } else { - Assert.notEqual(bookmark.itemType, PlacesUtils.bookmarks.TYPE_FOLDER, - "Bookmark " + bookmark.title + " should not be a folder"); - } - - if (shouldBeInMenu) { - Assert.equal(bookmark.parentGuid, menuParentGuid, "Item '" + bookmark.title + "' should be in menu"); - } else if (shouldBeInToolbar) { - Assert.equal(bookmark.parentGuid, toolbarParentGuid, "Item '" + bookmark.title + "' should be in toolbar"); - } else if (bookmark.itemGuid == menuParentGuid || bookmark.itemGuid == toolbarParentGuid) { - Assert.ok(true, "Expect toolbar and menu folders to not be in menu or toolbar"); - } else { - // Bit hacky, but we do need to check this. - Assert.equal(bookmark.title, "Item in folder", "Subfoldered item shouldn't be in menu or toolbar"); - let parent = seenBookmarks.find(maybeParent => maybeParent.itemGuid == bookmark.parentGuid); - Assert.equal(parent && parent.title, "Folder", "Subfoldered item should be in subfolder labeled 'Folder'"); - } - - let dbItem = itemsInDB.find(someItem => bookmark.title == someItem.Title); - if (!dbItem) { - Assert.equal(bookmark.title, importParentFolderName, "Only the extra layer of folders isn't in the input we stuck in the DB."); - Assert.ok([menuParentGuid, toolbarParentGuid].includes(bookmark.itemGuid), "This item should be one of the containers"); - } else { - Assert.equal(dbItem.URL || null, bookmark.url && bookmark.url.spec, "URL is correct"); - Assert.equal(dbItem.DateUpdated.valueOf(), (new Date(bookmark.dateAdded / 1000)).valueOf(), "Date added is correct"); - } - } -}); - diff --git a/browser/components/migration/tests/unit/test_IE7_passwords.js b/browser/components/migration/tests/unit/test_IE7_passwords.js deleted file mode 100644 index 1ce016a7d..000000000 --- a/browser/components/migration/tests/unit/test_IE7_passwords.js +++ /dev/null @@ -1,397 +0,0 @@ -"use strict"; - -Cu.import("resource://gre/modules/AppConstants.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "WindowsRegistry", - "resource://gre/modules/WindowsRegistry.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "OSCrypto", - "resource://gre/modules/OSCrypto.jsm"); - -const IE7_FORM_PASSWORDS_MIGRATOR_NAME = "IE7FormPasswords"; -const LOGINS_KEY = "Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2"; -const EXTENSION = "-backup"; -const TESTED_WEBSITES = { - twitter: { - uri: makeURI("https://twitter.com"), - hash: "A89D42BC6406E27265B1AD0782B6F376375764A301", - data: [12, 0, 0, 0, 56, 0, 0, 0, 38, 0, 0, 0, 87, 73, 67, 75, 24, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 36, 67, 124, 118, 212, 208, 1, 8, 0, 0, 0, 18, 0, 0, 0, 68, 36, 67, 124, 118, 212, 208, 1, 9, 0, 0, 0, 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0, 0, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0, 57, 0, 0, 0], - logins: [ - { - username: "abcdefgh", - password: "123456789", - hostname: "https://twitter.com", - formSubmitURL: "", - httpRealm: null, - usernameField: "", - passwordField: "", - timeCreated: 1439325854000, - timeLastUsed: 1439325854000, - timePasswordChanged: 1439325854000, - timesUsed: 1, - }, - ], - }, - facebook: { - uri: makeURI("https://www.facebook.com/"), - hash: "EF44D3E034009CB0FD1B1D81A1FF3F3335213BD796", - data: [12, 0, 0, 0, 152, 0, 0, 0, 160, 0, 0, 0, 87, 73, 67, 75, 24, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 182, 125, 18, 121, 212, 208, 1, 9, 0, 0, 0, 20, 0, 0, 0, 88, 182, 125, 18, 121, 212, 208, 1, 9, 0, 0, 0, 40, 0, 0, 0, 134, 65, 33, 37, 121, 212, 208, 1, 9, 0, 0, 0, 60, 0, 0, 0, 134, 65, 33, 37, 121, 212, 208, 1, 9, 0, 0, 0, 80, 0, 0, 0, 45, 242, 246, 62, 121, 212, 208, 1, 9, 0, 0, 0, 100, 0, 0, 0, 45, 242, 246, 62, 121, 212, 208, 1, 9, 0, 0, 0, 120, 0, 0, 0, 28, 10, 193, 80, 121, 212, 208, 1, 9, 0, 0, 0, 140, 0, 0, 0, 28, 10, 193, 80, 121, 212, 208, 1, 9, 0, 0, 0, 117, 0, 115, 0, 101, 0, 114, 0, 110, 0, 97, 0, 109, 0, 101, 0, 48, 0, 0, 0, 112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 48, 0, 0, 0, 117, 0, 115, 0, 101, 0, 114, 0, 110, 0, 97, 0, 109, 0, 101, 0, 49, 0, 0, 0, 112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 49, 0, 0, 0, 117, 0, 115, 0, 101, 0, 114, 0, 110, 0, 97, 0, 109, 0, 101, 0, 50, 0, 0, 0, 112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 50, 0, 0, 0, 117, 0, 115, 0, 101, 0, 114, 0, 110, 0, 97, 0, 109, 0, 101, 0, 51, 0, 0, 0, 112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 51, 0, 0, 0], - logins: [ - { - username: "username0", - password: "password0", - hostname: "https://www.facebook.com", - formSubmitURL: "", - httpRealm: null, - usernameField: "", - passwordField: "", - timeCreated: 1439326966000, - timeLastUsed: 1439326966000, - timePasswordChanged: 1439326966000, - timesUsed: 1, - }, - { - username: "username1", - password: "password1", - hostname: "https://www.facebook.com", - formSubmitURL: "", - httpRealm: null, - usernameField: "", - passwordField: "", - timeCreated: 1439326997000, - timeLastUsed: 1439326997000, - timePasswordChanged: 1439326997000, - timesUsed: 1, - }, - { - username: "username2", - password: "password2", - hostname: "https://www.facebook.com", - formSubmitURL: "", - httpRealm: null, - usernameField: "", - passwordField: "", - timeCreated: 1439327040000, - timeLastUsed: 1439327040000, - timePasswordChanged: 1439327040000, - timesUsed: 1, - }, - { - username: "username3", - password: "password3", - hostname: "https://www.facebook.com", - formSubmitURL: "", - httpRealm: null, - usernameField: "", - passwordField: "", - timeCreated: 1439327070000, - timeLastUsed: 1439327070000, - timePasswordChanged: 1439327070000, - timesUsed: 1, - }, - ], - }, - live: { - uri: makeURI("https://login.live.com/"), - hash: "7B506F2D6B81D939A8E0456F036EE8970856FF705E", - data: [12, 0, 0, 0, 56, 0, 0, 0, 44, 0, 0, 0, 87, 73, 67, 75, 24, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 212, 17, 219, 140, 148, 212, 208, 1, 9, 0, 0, 0, 20, 0, 0, 0, 212, 17, 219, 140, 148, 212, 208, 1, 11, 0, 0, 0, 114, 0, 105, 0, 97, 0, 100, 0, 104, 0, 49, 6, 74, 6, 39, 6, 54, 6, 0, 0, 39, 6, 66, 6, 49, 6, 35, 6, 80, 0, 192, 0, 223, 0, 119, 0, 246, 0, 114, 0, 100, 0, 0, 0], - logins: [ - { - username: "riadhرياض", - password: "اقرأPÀßwörd", - hostname: "https://login.live.com", - formSubmitURL: "", - httpRealm: null, - usernameField: "", - passwordField: "", - timeCreated: 1439338767000, - timeLastUsed: 1439338767000, - timePasswordChanged: 1439338767000, - timesUsed: 1, - }, - ], - }, - reddit: { - uri: makeURI("http://www.reddit.com/"), - hash: "B644028D1C109A91EC2C4B9D1F145E55A1FAE42065", - data: [12, 0, 0, 0, 152, 0, 0, 0, 212, 0, 0, 0, 87, 73, 67, 75, 24, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 8, 234, 114, 153, 212, 208, 1, 1, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 97, 93, 131, 116, 153, 212, 208, 1, 3, 0, 0, 0, 14, 0, 0, 0, 97, 93, 131, 116, 153, 212, 208, 1, 16, 0, 0, 0, 48, 0, 0, 0, 88, 150, 78, 174, 153, 212, 208, 1, 4, 0, 0, 0, 58, 0, 0, 0, 88, 150, 78, 174, 153, 212, 208, 1, 29, 0, 0, 0, 118, 0, 0, 0, 79, 102, 137, 34, 154, 212, 208, 1, 15, 0, 0, 0, 150, 0, 0, 0, 79, 102, 137, 34, 154, 212, 208, 1, 30, 0, 0, 0, 97, 0, 0, 0, 0, 0, 252, 140, 173, 138, 146, 48, 0, 0, 66, 0, 105, 0, 116, 0, 116, 0, 101, 0, 32, 0, 98, 0, 101, 0, 115, 0, 116, 0, 228, 0, 116, 0, 105, 0, 103, 0, 101, 0, 110, 0, 0, 0, 205, 145, 110, 127, 198, 91, 1, 120, 0, 0, 31, 4, 48, 4, 64, 4, 62, 4, 59, 4, 76, 4, 32, 0, 67, 4, 65, 4, 63, 4, 53, 4, 72, 4, 61, 4, 62, 4, 32, 0, 65, 4, 49, 4, 64, 4, 62, 4, 72, 4, 53, 4, 61, 4, 46, 0, 32, 0, 18, 4, 62, 4, 57, 4, 66, 4, 56, 4, 0, 0, 40, 6, 51, 6, 69, 6, 32, 0, 39, 6, 68, 6, 68, 6, 71, 6, 32, 0, 39, 6, 68, 6, 49, 6, 45, 6, 69, 6, 70, 6, 0, 0, 118, 0, 101, 0, 117, 0, 105, 0, 108, 0, 108, 0, 101, 0, 122, 0, 32, 0, 108, 0, 101, 0, 32, 0, 118, 0, 233, 0, 114, 0, 105, 0, 102, 0, 105, 0, 101, 0, 114, 0, 32, 0, 224, 0, 32, 0, 110, 0, 111, 0, 117, 0, 118, 0, 101, 0, 97, 0, 117, 0, 0, 0], - logins: [ - { - username: "購読を", - password: "Bitte bestätigen", - hostname: "http://www.reddit.com", - formSubmitURL: "", - httpRealm: null, - usernameField: "", - passwordField: "", - timeCreated: 1439340874000, - timeLastUsed: 1439340874000, - timePasswordChanged: 1439340874000, - timesUsed: 1, - }, - { - username: "重置密码", - password: "Пароль успешно сброшен. Войти", - hostname: "http://www.reddit.com", - formSubmitURL: "", - httpRealm: null, - usernameField: "", - passwordField: "", - timeCreated: 1439340971000, - timeLastUsed: 1439340971000, - timePasswordChanged: 1439340971000, - timesUsed: 1, - }, - { - username: "بسم الله الرحمن", - password: "veuillez le vérifier à nouveau", - hostname: "http://www.reddit.com", - formSubmitURL: "", - httpRealm: null, - usernameField: "", - passwordField: "", - timeCreated: 1439341166000, - timeLastUsed: 1439341166000, - timePasswordChanged: 1439341166000, - timesUsed: 1, - }, - ], - }, -}; - -const TESTED_URLS = [ - "http://a.foo.com", - "http://b.foo.com", - "http://c.foo.com", - "http://www.test.net", - "http://www.test.net/home", - "http://www.test.net/index", - "https://a.bar.com", - "https://b.bar.com", - "https://c.bar.com", -]; - -var nsIWindowsRegKey = Ci.nsIWindowsRegKey; -var Storage2Key; - -/* - * If the key value exists, it's going to be backed up and replaced, so the value could be restored. - * Otherwise a new value is going to be created. - */ -function backupAndStore(key, name, value) { - if (key.hasValue(name)) { - // backup the the current value - let type = key.getValueType(name); - // create a new value using use the current value name followed by EXTENSION as its new name - switch (type) { - case nsIWindowsRegKey.TYPE_STRING: - key.writeStringValue(name + EXTENSION, key.readStringValue(name)); - break; - case nsIWindowsRegKey.TYPE_BINARY: - key.writeBinaryValue(name + EXTENSION, key.readBinaryValue(name)); - break; - case nsIWindowsRegKey.TYPE_INT: - key.writeIntValue(name + EXTENSION, key.readIntValue(name)); - break; - case nsIWindowsRegKey.TYPE_INT64: - key.writeInt64Value(name + EXTENSION, key.readInt64Value(name)); - break; - } - } - key.writeBinaryValue(name, value); -} - -// Remove all values where their names are members of the names array from the key of registry -function removeAllValues(key, names) { - for (let name of names) { - key.removeValue(name); - } -} - -// Restore all the backed up values -function restore(key) { - let count = key.valueCount; - let names = []; // the names of the key values - for (let i = 0; i < count; ++i) { - names.push(key.getValueName(i)); - } - - for (let name of names) { - // backed up values have EXTENSION at the end of their names - if (name.lastIndexOf(EXTENSION) == name.length - EXTENSION.length) { - let valueName = name.substr(0, name.length - EXTENSION.length); - let type = key.getValueType(name); - // create a new value using the name before the backup and removed the backed up one - switch (type) { - case nsIWindowsRegKey.TYPE_STRING: - key.writeStringValue(valueName, key.readStringValue(name)); - key.removeValue(name); - break; - case nsIWindowsRegKey.TYPE_BINARY: - key.writeBinaryValue(valueName, key.readBinaryValue(name)); - key.removeValue(name); - break; - case nsIWindowsRegKey.TYPE_INT: - key.writeIntValue(valueName, key.readIntValue(name)); - key.removeValue(name); - break; - case nsIWindowsRegKey.TYPE_INT64: - key.writeInt64Value(valueName, key.readInt64Value(name)); - key.removeValue(name); - break; - } - } - } -} - -function checkLoginsAreEqual(passwordManagerLogin, IELogin, id) { - passwordManagerLogin.QueryInterface(Ci.nsILoginMetaInfo); - for (let attribute in IELogin) { - Assert.equal(passwordManagerLogin[attribute], IELogin[attribute], - "The two logins ID " + id + " have the same " + attribute); - } -} - -function createRegistryPath(path) { - let loginPath = path.split("\\"); - let parentKey = Cc["@mozilla.org/windows-registry-key;1"]. - createInstance(nsIWindowsRegKey); - let currentPath = []; - for (let currentKey of loginPath) { - parentKey.open(nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, currentPath.join("\\"), - nsIWindowsRegKey.ACCESS_ALL); - - if (!parentKey.hasChild(currentKey)) { - parentKey.createChild(currentKey, 0); - } - currentPath.push(currentKey); - parentKey.close(); - } -} - -function getFirstResourceOfType(type) { - let migrator = Cc["@mozilla.org/profile/migrator;1?app=browser&type=ie"] - .createInstance(Ci.nsISupports) - .wrappedJSObject; - let migrators = migrator.getResources(); - for (let m of migrators) { - if (m.name == IE7_FORM_PASSWORDS_MIGRATOR_NAME && m.type == type) { - return m; - } - } - throw new Error("failed to find the " + type + " migrator"); -} - -function makeURI(aURL) { - return Services.io.newURI(aURL, null, null); -} - -add_task(function* setup() { - if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) { - Assert.throws(() => getFirstResourceOfType(MigrationUtils.resourceTypes.PASSWORDS), - "The migrator doesn't exist for win8+"); - return; - } - // create the path to Storage2 in the registry if it doest exist. - createRegistryPath(LOGINS_KEY); - Storage2Key = Cc["@mozilla.org/windows-registry-key;1"]. - createInstance(nsIWindowsRegKey); - Storage2Key.open(nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, LOGINS_KEY, - nsIWindowsRegKey.ACCESS_ALL); - - // create a dummy value otherwise the migrator doesn't exist - if (!Storage2Key.hasValue("dummy")) { - Storage2Key.writeBinaryValue("dummy", "dummy"); - } -}); - -add_task(function* test_passwordsNotAvailable() { - if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) { - return; - } - - let migrator = getFirstResourceOfType(MigrationUtils.resourceTypes.PASSWORDS); - Assert.ok(migrator.exists, "The migrator has to exist"); - let logins = Services.logins.getAllLogins({}); - Assert.equal(logins.length, 0, "There are no logins at the beginning of the test"); - - let uris = []; // the uris of the migrated logins - for (let url of TESTED_URLS) { - uris.push(makeURI(url)); - // in this test, there is no IE login data in the registry, so after the migration, the number - // of logins in the store should be 0 - migrator._migrateURIs(uris); - logins = Services.logins.getAllLogins({}); - Assert.equal(logins.length, 0, - "There are no logins after doing the migration without adding values to the registry"); - } -}); - -add_task(function* test_passwordsAvailable() { - if (AppConstants.isPlatformAndVersionAtLeast("win", "6.2")) { - return; - } - - let crypto = new OSCrypto(); - let hashes = []; // the hashes of all migrator websites, this is going to be used for the clean up - - do_register_cleanup(() => { - Services.logins.removeAllLogins(); - logins = Services.logins.getAllLogins({}); - Assert.equal(logins.length, 0, "There are no logins after the cleanup"); - // remove all the values created in this test from the registry - removeAllValues(Storage2Key, hashes); - // restore all backed up values - restore(Storage2Key); - - // clean the dummy value - if (Storage2Key.hasValue("dummy")) { - Storage2Key.removeValue("dummy"); - } - Storage2Key.close(); - crypto.finalize(); - }); - - let migrator = getFirstResourceOfType(MigrationUtils.resourceTypes.PASSWORDS); - Assert.ok(migrator.exists, "The migrator has to exist"); - let logins = Services.logins.getAllLogins({}); - Assert.equal(logins.length, 0, "There are no logins at the beginning of the test"); - - let uris = []; // the uris of the migrated logins - - let loginCount = 0; - for (let current in TESTED_WEBSITES) { - let website = TESTED_WEBSITES[current]; - // backup the current the registry value if it exists and replace the existing value/create a - // new value with the encrypted data - backupAndStore(Storage2Key, website.hash, - crypto.encryptData(crypto.arrayToString(website.data), - website.uri.spec, true)); - Assert.ok(migrator.exists, "The migrator has to exist"); - uris.push(website.uri); - hashes.push(website.hash); - - migrator._migrateURIs(uris); - logins = Services.logins.getAllLogins({}); - // check that the number of logins in the password manager has increased as expected which means - // that all the values for the current website were imported - loginCount += website.logins.length; - Assert.equal(logins.length, loginCount, - "The number of logins has increased after the migration"); - // NB: because telemetry records any login data passed to the login manager, it - // also gets told about logins that are duplicates or invalid (for one reason - // or another) and so its counts might exceed those of the login manager itself. - Assert.greaterOrEqual(MigrationUtils._importQuantities.logins, loginCount, - "Telemetry quantities equal or exceed the actual import."); - // Reset - this normally happens at the start of a new migration, but we're calling - // the migrator directly so can't rely on that: - MigrationUtils._importQuantities.logins = 0; - - let startIndex = loginCount - website.logins.length; - // compares the imported password manager logins with their expected logins - for (let i = 0; i < website.logins.length; i++) { - checkLoginsAreEqual(logins[startIndex + i], website.logins[i], - " " + current + " - " + i + " "); - } - } -}); diff --git a/browser/components/migration/tests/unit/test_IE_bookmarks.js b/browser/components/migration/tests/unit/test_IE_bookmarks.js deleted file mode 100644 index a166c0502..000000000 --- a/browser/components/migration/tests/unit/test_IE_bookmarks.js +++ /dev/null @@ -1,44 +0,0 @@ -"use strict"; - -add_task(function* () { - let migrator = MigrationUtils.getMigrator("ie"); - // Sanity check for the source. - Assert.ok(migrator.sourceExists); - - // Wait for the imported bookmarks. Check that "From Internet Explorer" - // folders are created in the menu and on the toolbar. - let source = MigrationUtils.getLocalizedString("sourceNameIE"); - let label = MigrationUtils.getLocalizedString("importedBookmarksFolder", [source]); - - let expectedParents = [ PlacesUtils.bookmarksMenuFolderId, - PlacesUtils.toolbarFolderId ]; - - let itemCount = 0; - let bmObserver = { - onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle) { - if (aTitle != label) { - itemCount++; - } - if (expectedParents.length > 0 && aTitle == label) { - let index = expectedParents.indexOf(aParentId); - Assert.notEqual(index, -1); - expectedParents.splice(index, 1); - } - }, - onBeginUpdateBatch() {}, - onEndUpdateBatch() {}, - onItemRemoved() {}, - onItemChanged() {}, - onItemVisited() {}, - onItemMoved() {}, - }; - PlacesUtils.bookmarks.addObserver(bmObserver, false); - - yield promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS); - PlacesUtils.bookmarks.removeObserver(bmObserver); - Assert.equal(MigrationUtils._importQuantities.bookmarks, itemCount, - "Ensure telemetry matches actual number of imported items."); - - // Check the bookmarks have been imported to all the expected parents. - Assert.equal(expectedParents.length, 0, "Got all the expected parents"); -}); diff --git a/browser/components/migration/tests/unit/test_IE_cookies.js b/browser/components/migration/tests/unit/test_IE_cookies.js deleted file mode 100644 index 37a7462f2..000000000 --- a/browser/components/migration/tests/unit/test_IE_cookies.js +++ /dev/null @@ -1,111 +0,0 @@ -"use strict"; - -XPCOMUtils.defineLazyModuleGetter(this, "ctypes", - "resource://gre/modules/ctypes.jsm"); - -add_task(function* () { - let migrator = MigrationUtils.getMigrator("ie"); - // Sanity check for the source. - Assert.ok(migrator.sourceExists); - - const BOOL = ctypes.bool; - const LPCTSTR = ctypes.char16_t.ptr; - const DWORD = ctypes.uint32_t; - const LPDWORD = DWORD.ptr; - - let wininet = ctypes.open("Wininet"); - - /* - BOOL InternetSetCookieW( - _In_ LPCTSTR lpszUrl, - _In_ LPCTSTR lpszCookieName, - _In_ LPCTSTR lpszCookieData - ); - */ - let setIECookie = wininet.declare("InternetSetCookieW", - ctypes.default_abi, - BOOL, - LPCTSTR, - LPCTSTR, - LPCTSTR); - - /* - BOOL InternetGetCookieW( - _In_ LPCTSTR lpszUrl, - _In_ LPCTSTR lpszCookieName, - _Out_ LPCTSTR lpszCookieData, - _Inout_ LPDWORD lpdwSize - ); - */ - let getIECookie = wininet.declare("InternetGetCookieW", - ctypes.default_abi, - BOOL, - LPCTSTR, - LPCTSTR, - LPCTSTR, - LPDWORD); - - // We need to randomize the cookie to avoid clashing with other cookies - // that might have been set by previous tests and not properly cleared. - let date = (new Date()).getDate(); - const COOKIE = { - get host() { - return new URL(this.href).host; - }, - href: `http://mycookietest.${Math.random()}.com`, - name: "testcookie", - value: "testvalue", - expiry: new Date(new Date().setDate(date + 2)) - }; - let data = ctypes.char16_t.array()(256); - let sizeRef = DWORD(256).address(); - - do_register_cleanup(() => { - // Remove the cookie. - try { - let expired = new Date(new Date().setDate(date - 2)); - let rv = setIECookie(COOKIE.href, COOKIE.name, - `; expires=${expired.toUTCString()}`); - Assert.ok(rv, "Expired the IE cookie"); - Assert.ok(!getIECookie(COOKIE.href, COOKIE.name, data, sizeRef), - "The cookie has been properly removed"); - } catch (ex) {} - - // Close the library. - try { - wininet.close(); - } catch (ex) {} - }); - - // Create the persistent cookie in IE. - let value = `${COOKIE.value}; expires=${COOKIE.expiry.toUTCString()}`; - let rv = setIECookie(COOKIE.href, COOKIE.name, value); - Assert.ok(rv, "Added a persistent IE cookie: " + value); - - // Sanity check the cookie has been created. - Assert.ok(getIECookie(COOKIE.href, COOKIE.name, data, sizeRef), - "Found the added persistent IE cookie"); - do_print("Found cookie: " + data.readString()); - Assert.equal(data.readString(), `${COOKIE.name}=${COOKIE.value}`, - "Found the expected cookie"); - - // Sanity check that there are no cookies. - Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 0, - "There are no cookies initially"); - - // Migrate cookies. - yield promiseMigration(migrator, MigrationUtils.resourceTypes.COOKIES); - - Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 1, - "Migrated the expected number of cookies"); - - // Now check the cookie details. - let enumerator = Services.cookies.getCookiesFromHost(COOKIE.host, {}); - Assert.ok(enumerator.hasMoreElements()); - let foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2); - - Assert.equal(foundCookie.name, COOKIE.name); - Assert.equal(foundCookie.value, COOKIE.value); - Assert.equal(foundCookie.host, "." + COOKIE.host); - Assert.equal(foundCookie.expiry, Math.floor(COOKIE.expiry / 1000)); -}); diff --git a/browser/components/migration/tests/unit/test_Safari_bookmarks.js b/browser/components/migration/tests/unit/test_Safari_bookmarks.js deleted file mode 100644 index edc32dc72..000000000 --- a/browser/components/migration/tests/unit/test_Safari_bookmarks.js +++ /dev/null @@ -1,46 +0,0 @@ -"use strict"; - -add_task(function* () { - registerFakePath("ULibDir", do_get_file("Library/")); - - let migrator = MigrationUtils.getMigrator("safari"); - // Sanity check for the source. - Assert.ok(migrator.sourceExists); - - // Wait for the imported bookmarks. Check that "From Safari" - // folders are created on the toolbar. - let source = MigrationUtils.getLocalizedString("sourceNameSafari"); - let label = MigrationUtils.getLocalizedString("importedBookmarksFolder", [source]); - - let expectedParents = [ PlacesUtils.toolbarFolderId ]; - let itemCount = 0; - - let bmObserver = { - onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle) { - if (aTitle != label) { - itemCount++; - } - if (expectedParents.length > 0 && aTitle == label) { - let index = expectedParents.indexOf(aParentId); - Assert.ok(index != -1, "Found expected parent"); - expectedParents.splice(index, 1); - } - }, - onBeginUpdateBatch() {}, - onEndUpdateBatch() {}, - onItemRemoved() {}, - onItemChanged() {}, - onItemVisited() {}, - onItemMoved() {}, - }; - PlacesUtils.bookmarks.addObserver(bmObserver, false); - - yield promiseMigration(migrator, MigrationUtils.resourceTypes.BOOKMARKS); - PlacesUtils.bookmarks.removeObserver(bmObserver); - - // Check the bookmarks have been imported to all the expected parents. - Assert.ok(!expectedParents.length, "No more expected parents"); - Assert.equal(itemCount, 13, "Should import all 13 items."); - // Check that the telemetry matches: - Assert.equal(MigrationUtils._importQuantities.bookmarks, itemCount, "Telemetry reporting correct."); -}); diff --git a/browser/components/migration/tests/unit/test_automigration.js b/browser/components/migration/tests/unit/test_automigration.js deleted file mode 100644 index bc9076a6c..000000000 --- a/browser/components/migration/tests/unit/test_automigration.js +++ /dev/null @@ -1,695 +0,0 @@ -"use strict"; - -let AutoMigrateBackstage = Cu.import("resource:///modules/AutoMigrate.jsm"); /* globals AutoMigrate */ - -let gShimmedMigratorKeyPicker = null; -let gShimmedMigrator = null; - -const kUsecPerMin = 60 * 1000000; - -// This is really a proxy on MigrationUtils, but if we specify that directly, -// we get in trouble because the object itself is frozen, and Proxies can't -// return a different value to an object when directly proxying a frozen -// object. -AutoMigrateBackstage.MigrationUtils = new Proxy({}, { - get(target, name) { - if (name == "getMigratorKeyForDefaultBrowser" && gShimmedMigratorKeyPicker) { - return gShimmedMigratorKeyPicker; - } - if (name == "getMigrator" && gShimmedMigrator) { - return function() { return gShimmedMigrator }; - } - return MigrationUtils[name]; - }, -}); - -do_register_cleanup(function() { - AutoMigrateBackstage.MigrationUtils = MigrationUtils; -}); - -// This should be replaced by using History.fetch with a fetchVisits option, -// once that becomes available -function* visitsForURL(url) -{ - let visitCount = 0; - let db = yield PlacesUtils.promiseDBConnection(); - visitCount = yield db.execute( - `SELECT count(*) FROM moz_historyvisits v - JOIN moz_places h ON h.id = v.place_id - WHERE url_hash = hash(:url) AND url = :url`, - {url}); - visitCount = visitCount[0].getInt64(0); - return visitCount; -} - - -/** - * Test automatically picking a browser to migrate from - */ -add_task(function* checkMigratorPicking() { - Assert.throws(() => AutoMigrate.pickMigrator("firefox"), - /Can't automatically migrate from Firefox/, - "Should throw when explicitly picking Firefox."); - - Assert.throws(() => AutoMigrate.pickMigrator("gobbledygook"), - /migrator object is not available/, - "Should throw when passing unknown migrator key"); - gShimmedMigratorKeyPicker = function() { - return "firefox"; - }; - Assert.throws(() => AutoMigrate.pickMigrator(), - /Can't automatically migrate from Firefox/, - "Should throw when implicitly picking Firefox."); - gShimmedMigratorKeyPicker = function() { - return "gobbledygook"; - }; - Assert.throws(() => AutoMigrate.pickMigrator(), - /migrator object is not available/, - "Should throw when an unknown migrator is the default"); - gShimmedMigratorKeyPicker = function() { - return ""; - }; - Assert.throws(() => AutoMigrate.pickMigrator(), - /Could not determine default browser key/, - "Should throw when an unknown migrator is the default"); -}); - - -/** - * Test automatically picking a profile to migrate from - */ -add_task(function* checkProfilePicking() { - let fakeMigrator = {sourceProfiles: [{id: "a"}, {id: "b"}]}; - let profB = fakeMigrator.sourceProfiles[1]; - Assert.throws(() => AutoMigrate.pickProfile(fakeMigrator), - /Don't know how to pick a profile when more/, - "Should throw when there are multiple profiles."); - Assert.throws(() => AutoMigrate.pickProfile(fakeMigrator, "c"), - /Profile specified was not found/, - "Should throw when the profile supplied doesn't exist."); - let profileToMigrate = AutoMigrate.pickProfile(fakeMigrator, "b"); - Assert.equal(profileToMigrate, profB, "Should return profile supplied"); - - fakeMigrator.sourceProfiles = null; - Assert.throws(() => AutoMigrate.pickProfile(fakeMigrator, "c"), - /Profile specified but only a default profile found./, - "Should throw when the profile supplied doesn't exist."); - profileToMigrate = AutoMigrate.pickProfile(fakeMigrator); - Assert.equal(profileToMigrate, null, "Should return default profile when that's the only one."); - - fakeMigrator.sourceProfiles = []; - Assert.throws(() => AutoMigrate.pickProfile(fakeMigrator), - /No profile data found/, - "Should throw when no profile data is present."); - - fakeMigrator.sourceProfiles = [{id: "a"}]; - let profA = fakeMigrator.sourceProfiles[0]; - profileToMigrate = AutoMigrate.pickProfile(fakeMigrator); - Assert.equal(profileToMigrate, profA, "Should return the only profile if only one is present."); -}); - -/** - * Test the complete automatic process including browser and profile selection, - * and actual migration (which implies startup) - */ -add_task(function* checkIntegration() { - gShimmedMigrator = { - get sourceProfiles() { - do_print("Read sourceProfiles"); - return null; - }, - getMigrateData(profileToMigrate) { - this._getMigrateDataArgs = profileToMigrate; - return Ci.nsIBrowserProfileMigrator.BOOKMARKS; - }, - migrate(types, startup, profileToMigrate) { - this._migrateArgs = [types, startup, profileToMigrate]; - }, - }; - gShimmedMigratorKeyPicker = function() { - return "gobbledygook"; - }; - AutoMigrate.migrate("startup"); - Assert.strictEqual(gShimmedMigrator._getMigrateDataArgs, null, - "getMigrateData called with 'null' as a profile"); - - let {BOOKMARKS, HISTORY, PASSWORDS} = Ci.nsIBrowserProfileMigrator; - let expectedTypes = BOOKMARKS | HISTORY | PASSWORDS; - Assert.deepEqual(gShimmedMigrator._migrateArgs, [expectedTypes, "startup", null], - "migrate called with 'null' as a profile"); -}); - -/** - * Test the undo preconditions and a no-op undo in the automigrator. - */ -add_task(function* checkUndoPreconditions() { - let shouldAddData = false; - gShimmedMigrator = { - get sourceProfiles() { - do_print("Read sourceProfiles"); - return null; - }, - getMigrateData(profileToMigrate) { - this._getMigrateDataArgs = profileToMigrate; - return Ci.nsIBrowserProfileMigrator.BOOKMARKS; - }, - migrate(types, startup, profileToMigrate) { - this._migrateArgs = [types, startup, profileToMigrate]; - if (shouldAddData) { - // Insert a login and check that that worked. - MigrationUtils.insertLoginWrapper({ - hostname: "www.mozilla.org", - formSubmitURL: "http://www.mozilla.org", - username: "user", - password: "pass", - }); - } - TestUtils.executeSoon(function() { - Services.obs.notifyObservers(null, "Migration:Ended", undefined); - }); - }, - }; - - gShimmedMigratorKeyPicker = function() { - return "gobbledygook"; - }; - AutoMigrate.migrate("startup"); - let migrationFinishedPromise = TestUtils.topicObserved("Migration:Ended"); - Assert.strictEqual(gShimmedMigrator._getMigrateDataArgs, null, - "getMigrateData called with 'null' as a profile"); - - let {BOOKMARKS, HISTORY, PASSWORDS} = Ci.nsIBrowserProfileMigrator; - let expectedTypes = BOOKMARKS | HISTORY | PASSWORDS; - Assert.deepEqual(gShimmedMigrator._migrateArgs, [expectedTypes, "startup", null], - "migrate called with 'null' as a profile"); - - yield migrationFinishedPromise; - Assert.ok(Preferences.has("browser.migrate.automigrate.browser"), - "Should have set browser pref"); - Assert.ok(!(yield AutoMigrate.canUndo()), "Should not be able to undo migration, as there's no data"); - gShimmedMigrator._migrateArgs = null; - gShimmedMigrator._getMigrateDataArgs = null; - Preferences.reset("browser.migrate.automigrate.browser"); - shouldAddData = true; - - AutoMigrate.migrate("startup"); - migrationFinishedPromise = TestUtils.topicObserved("Migration:Ended"); - Assert.strictEqual(gShimmedMigrator._getMigrateDataArgs, null, - "getMigrateData called with 'null' as a profile"); - Assert.deepEqual(gShimmedMigrator._migrateArgs, [expectedTypes, "startup", null], - "migrate called with 'null' as a profile"); - - yield migrationFinishedPromise; - let storedLogins = Services.logins.findLogins({}, "www.mozilla.org", - "http://www.mozilla.org", null); - Assert.equal(storedLogins.length, 1, "Should have 1 login"); - - Assert.ok(Preferences.has("browser.migrate.automigrate.browser"), - "Should have set browser pref"); - Assert.ok((yield AutoMigrate.canUndo()), "Should be able to undo migration, as now there's data"); - - yield AutoMigrate.undo(); - Assert.ok(true, "Should be able to finish an undo cycle."); - - // Check that the undo removed the passwords: - storedLogins = Services.logins.findLogins({}, "www.mozilla.org", - "http://www.mozilla.org", null); - Assert.equal(storedLogins.length, 0, "Should have no logins"); -}); - -/** - * Fake a migration and then try to undo it to verify all data gets removed. - */ -add_task(function* checkUndoRemoval() { - MigrationUtils.initializeUndoData(); - Preferences.set("browser.migrate.automigrate.browser", "automationbrowser"); - // Insert a login and check that that worked. - MigrationUtils.insertLoginWrapper({ - hostname: "www.mozilla.org", - formSubmitURL: "http://www.mozilla.org", - username: "user", - password: "pass", - }); - let storedLogins = Services.logins.findLogins({}, "www.mozilla.org", - "http://www.mozilla.org", null); - Assert.equal(storedLogins.length, 1, "Should have 1 login"); - - // Insert a bookmark and check that we have exactly 1 bookmark for that URI. - yield MigrationUtils.insertBookmarkWrapper({ - parentGuid: PlacesUtils.bookmarks.toolbarGuid, - url: "http://www.example.org/", - title: "Some example bookmark", - }); - - let bookmark = yield PlacesUtils.bookmarks.fetch({url: "http://www.example.org/"}); - Assert.ok(bookmark, "Should have a bookmark before undo"); - Assert.equal(bookmark.title, "Some example bookmark", "Should have correct bookmark before undo."); - - // Insert 2 history visits - let now_uSec = Date.now() * 1000; - let visitedURI = Services.io.newURI("http://www.example.com/", null, null); - let frecencyUpdatePromise = new Promise(resolve => { - let expectedChanges = 2; - let observer = { - onFrecencyChanged: function() { - if (!--expectedChanges) { - PlacesUtils.history.removeObserver(observer); - resolve(); - } - }, - }; - PlacesUtils.history.addObserver(observer, false); - }); - yield MigrationUtils.insertVisitsWrapper([{ - uri: visitedURI, - visits: [ - { - transitionType: PlacesUtils.history.TRANSITION_LINK, - visitDate: now_uSec, - }, - { - transitionType: PlacesUtils.history.TRANSITION_LINK, - visitDate: now_uSec - 100 * kUsecPerMin, - }, - ] - }]); - yield frecencyUpdatePromise; - - // Verify that both visits get reported. - let opts = PlacesUtils.history.getNewQueryOptions(); - opts.resultType = opts.RESULTS_AS_VISIT; - let query = PlacesUtils.history.getNewQuery(); - query.uri = visitedURI; - let visits = PlacesUtils.history.executeQuery(query, opts); - visits.root.containerOpen = true; - Assert.equal(visits.root.childCount, 2, "Should have 2 visits"); - // Clean up: - visits.root.containerOpen = false; - - yield AutoMigrate.saveUndoState(); - - // Verify that we can undo, then undo: - Assert.ok(AutoMigrate.canUndo(), "Should be possible to undo migration"); - yield AutoMigrate.undo(); - - let histograms = [ - "FX_STARTUP_MIGRATION_UNDO_BOOKMARKS_ERRORCOUNT", - "FX_STARTUP_MIGRATION_UNDO_LOGINS_ERRORCOUNT", - "FX_STARTUP_MIGRATION_UNDO_VISITS_ERRORCOUNT", - ]; - for (let histogramId of histograms) { - let keyedHistogram = Services.telemetry.getKeyedHistogramById(histogramId); - let histogramData = keyedHistogram.snapshot().automationbrowser; - Assert.equal(histogramData.sum, 0, `Should have reported 0 errors to ${histogramId}.`); - Assert.greaterOrEqual(histogramData.counts[0], 1, `Should have reported value of 0 one time to ${histogramId}.`); - } - histograms = [ - "FX_STARTUP_MIGRATION_UNDO_BOOKMARKS_MS", - "FX_STARTUP_MIGRATION_UNDO_LOGINS_MS", - "FX_STARTUP_MIGRATION_UNDO_VISITS_MS", - "FX_STARTUP_MIGRATION_UNDO_TOTAL_MS", - ]; - for (let histogramId of histograms) { - Assert.greater(Services.telemetry.getKeyedHistogramById(histogramId).snapshot().automationbrowser.sum, 0, - `Should have reported non-zero time spent using undo for ${histogramId}`); - } - - // Check that the undo removed the history visits: - visits = PlacesUtils.history.executeQuery(query, opts); - visits.root.containerOpen = true; - Assert.equal(visits.root.childCount, 0, "Should have no more visits"); - visits.root.containerOpen = false; - - // Check that the undo removed the bookmarks: - bookmark = yield PlacesUtils.bookmarks.fetch({url: "http://www.example.org/"}); - Assert.ok(!bookmark, "Should have no bookmarks after undo"); - - // Check that the undo removed the passwords: - storedLogins = Services.logins.findLogins({}, "www.mozilla.org", - "http://www.mozilla.org", null); - Assert.equal(storedLogins.length, 0, "Should have no logins"); -}); - -add_task(function* checkUndoBookmarksState() { - MigrationUtils.initializeUndoData(); - const {TYPE_FOLDER, TYPE_BOOKMARK} = PlacesUtils.bookmarks; - let title = "Some example bookmark"; - let url = "http://www.example.com"; - let parentGuid = PlacesUtils.bookmarks.toolbarGuid; - let {guid, lastModified} = yield MigrationUtils.insertBookmarkWrapper({ - title, url, parentGuid - }); - Assert.deepEqual((yield MigrationUtils.stopAndRetrieveUndoData()).get("bookmarks"), - [{lastModified, parentGuid, guid, type: TYPE_BOOKMARK}]); - - MigrationUtils.initializeUndoData(); - ({guid, lastModified} = yield MigrationUtils.insertBookmarkWrapper({ - title, parentGuid, type: TYPE_FOLDER - })); - let folder = {guid, lastModified, parentGuid, type: TYPE_FOLDER}; - let folderGuid = folder.guid; - ({guid, lastModified} = yield MigrationUtils.insertBookmarkWrapper({ - title, url, parentGuid: folderGuid - })); - let kid1 = {guid, lastModified, parentGuid: folderGuid, type: TYPE_BOOKMARK}; - ({guid, lastModified} = yield MigrationUtils.insertBookmarkWrapper({ - title, url, parentGuid: folderGuid - })); - let kid2 = {guid, lastModified, parentGuid: folderGuid, type: TYPE_BOOKMARK}; - - let bookmarksUndo = (yield MigrationUtils.stopAndRetrieveUndoData()).get("bookmarks"); - Assert.equal(bookmarksUndo.length, 3); - // We expect that the last modified time from first kid #1 and then kid #2 - // has been propagated to the folder: - folder.lastModified = kid2.lastModified; - // Not just using deepEqual on the entire array (which should work) because - // the failure messages get truncated by xpcshell which is unhelpful. - Assert.deepEqual(bookmarksUndo[0], folder); - Assert.deepEqual(bookmarksUndo[1], kid1); - Assert.deepEqual(bookmarksUndo[2], kid2); - yield PlacesUtils.bookmarks.eraseEverything(); -}); - -add_task(function* testBookmarkRemovalByUndo() { - const {TYPE_FOLDER} = PlacesUtils.bookmarks; - MigrationUtils.initializeUndoData(); - let title = "Some example bookmark"; - let url = "http://www.mymagicaluniqueurl.com"; - let parentGuid = PlacesUtils.bookmarks.toolbarGuid; - let {guid} = yield MigrationUtils.insertBookmarkWrapper({ - title: "Some folder", parentGuid, type: TYPE_FOLDER - }); - let folderGuid = guid; - let itemsToRemove = []; - ({guid} = yield MigrationUtils.insertBookmarkWrapper({ - title: "Inner folder", parentGuid: folderGuid, type: TYPE_FOLDER - })); - let innerFolderGuid = guid; - itemsToRemove.push(innerFolderGuid); - - ({guid} = yield MigrationUtils.insertBookmarkWrapper({ - title: "Inner inner folder", parentGuid: innerFolderGuid, type: TYPE_FOLDER - })); - itemsToRemove.push(guid); - - ({guid} = yield MigrationUtils.insertBookmarkWrapper({ - title: "Inner nested item", url: "http://inner-nested-example.com", parentGuid: guid - })); - itemsToRemove.push(guid); - - ({guid} = yield MigrationUtils.insertBookmarkWrapper({ - title, url, parentGuid: folderGuid - })); - itemsToRemove.push(guid); - - for (let toBeRemovedGuid of itemsToRemove) { - let dbResultForGuid = yield PlacesUtils.bookmarks.fetch(toBeRemovedGuid); - Assert.ok(dbResultForGuid, "Should be able to find items that will be removed."); - } - let bookmarkUndoState = (yield MigrationUtils.stopAndRetrieveUndoData()).get("bookmarks"); - // Now insert a separate item into this folder, not related to the migration. - let newItem = yield PlacesUtils.bookmarks.insert( - {title: "Not imported", parentGuid: folderGuid, url: "http://www.example.com"} - ); - - yield AutoMigrate._removeUnchangedBookmarks(bookmarkUndoState); - Assert.ok(true, "Successfully removed imported items."); - - let itemFromDB = yield PlacesUtils.bookmarks.fetch(newItem.guid); - Assert.ok(itemFromDB, "Item we inserted outside of migration is still there."); - itemFromDB = yield PlacesUtils.bookmarks.fetch(folderGuid); - Assert.ok(itemFromDB, "Folder we inserted in migration is still there because of new kids."); - for (let removedGuid of itemsToRemove) { - let dbResultForGuid = yield PlacesUtils.bookmarks.fetch(removedGuid); - let dbgStr = dbResultForGuid && dbResultForGuid.title; - Assert.equal(null, dbResultForGuid, "Should not be able to find items that should have been removed, but found " + dbgStr); - } - yield PlacesUtils.bookmarks.eraseEverything(); -}); - -add_task(function* checkUndoLoginsState() { - MigrationUtils.initializeUndoData(); - MigrationUtils.insertLoginWrapper({ - username: "foo", - password: "bar", - hostname: "https://example.com", - formSubmitURL: "https://example.com/", - timeCreated: new Date(), - }); - let storedLogins = Services.logins.findLogins({}, "https://example.com", "", ""); - let storedLogin = storedLogins[0]; - storedLogin.QueryInterface(Ci.nsILoginMetaInfo); - let {guid, timePasswordChanged} = storedLogin; - let undoLoginData = (yield MigrationUtils.stopAndRetrieveUndoData()).get("logins"); - Assert.deepEqual([{guid, timePasswordChanged}], undoLoginData); - Services.logins.removeAllLogins(); -}); - -add_task(function* testLoginsRemovalByUndo() { - MigrationUtils.initializeUndoData(); - MigrationUtils.insertLoginWrapper({ - username: "foo", - password: "bar", - hostname: "https://example.com", - formSubmitURL: "https://example.com/", - timeCreated: new Date(), - }); - MigrationUtils.insertLoginWrapper({ - username: "foo", - password: "bar", - hostname: "https://example.org", - formSubmitURL: "https://example.org/", - timeCreated: new Date(new Date().getTime() - 10000), - }); - // This should update the existing login - LoginHelper.maybeImportLogin({ - username: "foo", - password: "bazzy", - hostname: "https://example.org", - formSubmitURL: "https://example.org/", - timePasswordChanged: new Date(), - }); - Assert.equal(1, LoginHelper.searchLoginsWithObject({hostname: "https://example.org", formSubmitURL: "https://example.org/"}).length, - "Should be only 1 login for example.org (that was updated)"); - let undoLoginData = (yield MigrationUtils.stopAndRetrieveUndoData()).get("logins"); - - yield AutoMigrate._removeUnchangedLogins(undoLoginData); - Assert.equal(0, LoginHelper.searchLoginsWithObject({hostname: "https://example.com", formSubmitURL: "https://example.com/"}).length, - "unchanged example.com entry should have been removed."); - Assert.equal(1, LoginHelper.searchLoginsWithObject({hostname: "https://example.org", formSubmitURL: "https://example.org/"}).length, - "changed example.org entry should have persisted."); - Services.logins.removeAllLogins(); -}); - -add_task(function* checkUndoVisitsState() { - MigrationUtils.initializeUndoData(); - yield MigrationUtils.insertVisitsWrapper([{ - uri: NetUtil.newURI("http://www.example.com/"), - title: "Example", - visits: [{ - visitDate: new Date("2015-07-10").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }, { - visitDate: new Date("2015-09-10").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }, { - visitDate: new Date("2015-08-10").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }], - }, { - uri: NetUtil.newURI("http://www.example.org/"), - title: "Example", - visits: [{ - visitDate: new Date("2016-04-03").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }, { - visitDate: new Date("2015-08-03").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }], - }, { - uri: NetUtil.newURI("http://www.example.com/"), - title: "Example", - visits: [{ - visitDate: new Date("2015-10-10").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }], - }]); - let undoVisitData = (yield MigrationUtils.stopAndRetrieveUndoData()).get("visits"); - Assert.deepEqual(Array.from(undoVisitData.map(v => v.url)).sort(), - ["http://www.example.com/", "http://www.example.org/"]); - Assert.deepEqual(undoVisitData.find(v => v.url == "http://www.example.com/"), { - url: "http://www.example.com/", - visitCount: 4, - first: new Date("2015-07-10").getTime() * 1000, - last: new Date("2015-10-10").getTime() * 1000, - }); - Assert.deepEqual(undoVisitData.find(v => v.url == "http://www.example.org/"), { - url: "http://www.example.org/", - visitCount: 2, - first: new Date("2015-08-03").getTime() * 1000, - last: new Date("2016-04-03").getTime() * 1000, - }); - - yield PlacesTestUtils.clearHistory(); -}); - -add_task(function* checkUndoVisitsState() { - MigrationUtils.initializeUndoData(); - yield MigrationUtils.insertVisitsWrapper([{ - uri: NetUtil.newURI("http://www.example.com/"), - title: "Example", - visits: [{ - visitDate: new Date("2015-07-10").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }, { - visitDate: new Date("2015-09-10").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }, { - visitDate: new Date("2015-08-10").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }], - }, { - uri: NetUtil.newURI("http://www.example.org/"), - title: "Example", - visits: [{ - visitDate: new Date("2016-04-03").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }, { - visitDate: new Date("2015-08-03").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }], - }, { - uri: NetUtil.newURI("http://www.example.com/"), - title: "Example", - visits: [{ - visitDate: new Date("2015-10-10").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }], - }, { - uri: NetUtil.newURI("http://www.mozilla.org/"), - title: "Example", - visits: [{ - visitDate: new Date("2015-01-01").getTime() * 1000, - transitionType: Ci.nsINavHistoryService.TRANSITION_LINK, - }], - }]); - - // We have to wait until frecency updates have been handled in order - // to accurately determine whether we're doing the right thing. - let frecencyUpdatesHandled = new Promise(resolve => { - PlacesUtils.history.addObserver({ - onFrecencyChanged(aURI) { - if (aURI.spec == "http://www.unrelated.org/") { - PlacesUtils.history.removeObserver(this); - resolve(); - } - } - }, false); - }); - yield PlacesUtils.history.insertMany([{ - url: "http://www.example.com/", - title: "Example", - visits: [{ - date: new Date("2015-08-16"), - }], - }, { - url: "http://www.example.org/", - title: "Example", - visits: [{ - date: new Date("2016-01-03"), - }, { - date: new Date("2015-05-03"), - }], - }, { - url: "http://www.unrelated.org/", - title: "Unrelated", - visits: [{ - date: new Date("2015-09-01"), - }], - }]); - yield frecencyUpdatesHandled; - let undoVisitData = (yield MigrationUtils.stopAndRetrieveUndoData()).get("visits"); - - let frecencyChangesExpected = new Map([ - ["http://www.example.com/", PromiseUtils.defer()], - ["http://www.example.org/", PromiseUtils.defer()] - ]); - let uriDeletedExpected = new Map([ - ["http://www.mozilla.org/", PromiseUtils.defer()], - ]); - let wrongMethodDeferred = PromiseUtils.defer(); - let observer = { - onBeginUpdateBatch: function() {}, - onEndUpdateBatch: function() {}, - onVisit: function(uri) { - wrongMethodDeferred.reject(new Error("Unexpected call to onVisit " + uri.spec)); - }, - onTitleChanged: function(uri) { - wrongMethodDeferred.reject(new Error("Unexpected call to onTitleChanged " + uri.spec)); - }, - onClearHistory: function() { - wrongMethodDeferred.reject("Unexpected call to onClearHistory"); - }, - onPageChanged: function(uri) { - wrongMethodDeferred.reject(new Error("Unexpected call to onPageChanged " + uri.spec)); - }, - onFrecencyChanged: function(aURI) { - do_print("frecency change"); - Assert.ok(frecencyChangesExpected.has(aURI.spec), - "Should be expecting frecency change for " + aURI.spec); - frecencyChangesExpected.get(aURI.spec).resolve(); - }, - onManyFrecenciesChanged: function() { - do_print("Many frecencies changed"); - wrongMethodDeferred.reject(new Error("This test can't deal with onManyFrecenciesChanged to be called")); - }, - onDeleteURI: function(aURI) { - do_print("delete uri"); - Assert.ok(uriDeletedExpected.has(aURI.spec), - "Should be expecting uri deletion for " + aURI.spec); - uriDeletedExpected.get(aURI.spec).resolve(); - }, - }; - PlacesUtils.history.addObserver(observer, false); - - yield AutoMigrate._removeSomeVisits(undoVisitData); - PlacesUtils.history.removeObserver(observer); - yield Promise.all(uriDeletedExpected.values()); - yield Promise.all(frecencyChangesExpected.values()); - - Assert.equal(yield visitsForURL("http://www.example.com/"), 1, - "1 example.com visit (out of 5) should have persisted despite being within the range, due to limiting"); - Assert.equal(yield visitsForURL("http://www.mozilla.org/"), 0, - "0 mozilla.org visits should have persisted (out of 1)."); - Assert.equal(yield visitsForURL("http://www.example.org/"), 2, - "2 example.org visits should have persisted (out of 4)."); - Assert.equal(yield visitsForURL("http://www.unrelated.org/"), 1, - "1 unrelated.org visits should have persisted as it's not involved in the import."); - yield PlacesTestUtils.clearHistory(); -}); - -add_task(function* checkHistoryRemovalCompletion() { - AutoMigrate._errorMap = {bookmarks: 0, visits: 0, logins: 0}; - yield AutoMigrate._removeSomeVisits([{url: "http://www.example.com/", limit: -1}]); - ok(true, "Removing visits should complete even if removing some visits failed."); - Assert.equal(AutoMigrate._errorMap.visits, 1, "Should have logged the error for visits."); - - // Unfortunately there's not a reliable way to make removing bookmarks be - // unhappy unless the DB is messed up (e.g. contains children but has - // parents removed already). - yield AutoMigrate._removeUnchangedBookmarks([ - {guid: PlacesUtils.bookmarks, lastModified: new Date(0), parentGuid: 0}, - {guid: "gobbledygook", lastModified: new Date(0), parentGuid: 0}, - ]); - ok(true, "Removing bookmarks should complete even if some items are gone or bogus."); - Assert.equal(AutoMigrate._errorMap.bookmarks, 0, - "Should have ignored removing non-existing (or builtin) bookmark."); - - - yield AutoMigrate._removeUnchangedLogins([ - {guid: "gobbledygook", timePasswordChanged: new Date(0)}, - ]); - ok(true, "Removing logins should complete even if logins don't exist."); - Assert.equal(AutoMigrate._errorMap.logins, 0, - "Should have ignored removing non-existing logins."); -}); diff --git a/browser/components/migration/tests/unit/test_fx_telemetry.js b/browser/components/migration/tests/unit/test_fx_telemetry.js deleted file mode 100644 index a276f52f8..000000000 --- a/browser/components/migration/tests/unit/test_fx_telemetry.js +++ /dev/null @@ -1,288 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -/* globals do_get_tempdir */ - -"use strict"; - -function run_test() { - run_next_test(); -} - -function readFile(file) { - let stream = Cc["@mozilla.org/network/file-input-stream;1"] - .createInstance(Ci.nsIFileInputStream); - stream.init(file, -1, -1, Ci.nsIFileInputStream.CLOSE_ON_EOF); - - let sis = Cc["@mozilla.org/scriptableinputstream;1"] - .createInstance(Ci.nsIScriptableInputStream); - sis.init(stream); - let contents = sis.read(file.fileSize); - sis.close(); - return contents; -} - -function checkDirectoryContains(dir, files) { - print("checking " + dir.path + " - should contain " + Object.keys(files)); - let seen = new Set(); - let enumerator = dir.directoryEntries; - while (enumerator.hasMoreElements()) { - let file = enumerator.getNext().QueryInterface(Ci.nsIFile); - print("found file: " + file.path); - Assert.ok(file.leafName in files, file.leafName + " exists, but shouldn't"); - - let expectedContents = files[file.leafName]; - if (typeof expectedContents != "string") { - // it's a subdir - recurse! - Assert.ok(file.isDirectory(), "should be a subdir"); - let newDir = dir.clone(); - newDir.append(file.leafName); - checkDirectoryContains(newDir, expectedContents); - } else { - Assert.ok(!file.isDirectory(), "should be a regular file"); - let contents = readFile(file); - Assert.equal(contents, expectedContents); - } - seen.add(file.leafName); - } - let missing = []; - for (let x in files) { - if (!seen.has(x)) { - missing.push(x); - } - } - Assert.deepEqual(missing, [], "no missing files in " + dir.path); -} - -function getTestDirs() { - // we make a directory structure in a temp dir which mirrors what we are - // testing. - let tempDir = do_get_tempdir(); - let srcDir = tempDir.clone(); - srcDir.append("test_source_dir"); - srcDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - - let targetDir = tempDir.clone(); - targetDir.append("test_target_dir"); - targetDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - - // no need to cleanup these dirs - the xpcshell harness will do it for us. - return [srcDir, targetDir]; -} - -function writeToFile(dir, leafName, contents) { - let file = dir.clone(); - file.append(leafName); - - let outputStream = FileUtils.openFileOutputStream(file); - outputStream.write(contents, contents.length); - outputStream.close(); -} - -function createSubDir(dir, subDirName) { - let subDir = dir.clone(); - subDir.append(subDirName); - subDir.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY); - return subDir; -} - -function promiseMigrator(name, srcDir, targetDir) { - let migrator = Cc["@mozilla.org/profile/migrator;1?app=browser&type=firefox"] - .createInstance(Ci.nsISupports) - .wrappedJSObject; - let migrators = migrator._getResourcesInternal(srcDir, targetDir); - for (let m of migrators) { - if (m.name == name) { - return new Promise(resolve => m.migrate(resolve)); - } - } - throw new Error("failed to find the " + name + " migrator"); -} - -function promiseTelemetryMigrator(srcDir, targetDir) { - return promiseMigrator("telemetry", srcDir, targetDir); -} - -add_task(function* test_empty() { - let [srcDir, targetDir] = getTestDirs(); - let ok = yield promiseTelemetryMigrator(srcDir, targetDir); - Assert.ok(ok, "callback should have been true with empty directories"); - // check both are empty - checkDirectoryContains(srcDir, {}); - checkDirectoryContains(targetDir, {}); -}); - -add_task(function* test_migrate_files() { - let [srcDir, targetDir] = getTestDirs(); - - // Set up datareporting files, some to copy, some not. - let stateContent = JSON.stringify({ - clientId: "68d5474e-19dc-45c1-8e9a-81fca592707c", - }); - let sessionStateContent = "foobar 5432"; - let subDir = createSubDir(srcDir, "datareporting"); - writeToFile(subDir, "state.json", stateContent); - writeToFile(subDir, "session-state.json", sessionStateContent); - writeToFile(subDir, "other.file", "do not copy"); - - let archived = createSubDir(subDir, "archived"); - writeToFile(archived, "other.file", "do not copy"); - - // Set up FHR files, they should not be copied. - writeToFile(srcDir, "healthreport.sqlite", "do not copy"); - writeToFile(srcDir, "healthreport.sqlite-wal", "do not copy"); - subDir = createSubDir(srcDir, "healthreport"); - writeToFile(subDir, "state.json", "do not copy"); - writeToFile(subDir, "other.file", "do not copy"); - - // Perform migration. - let ok = yield promiseTelemetryMigrator(srcDir, targetDir); - Assert.ok(ok, "callback should have been true with important telemetry files copied"); - - checkDirectoryContains(targetDir, { - "datareporting": { - "state.json": stateContent, - "session-state.json": sessionStateContent, - }, - }); -}); - -add_task(function* test_fallback_fhr_state() { - let [srcDir, targetDir] = getTestDirs(); - - // Test that we fall back to migrating FHR state if the datareporting - // state file does not exist. - let stateContent = JSON.stringify({ - clientId: "68d5474e-19dc-45c1-8e9a-81fca592707c", - }); - let subDir = createSubDir(srcDir, "healthreport"); - writeToFile(subDir, "state.json", stateContent); - - // Perform migration. - let ok = yield promiseTelemetryMigrator(srcDir, targetDir); - Assert.ok(ok, "callback should have been true"); - - checkDirectoryContains(targetDir, { - "healthreport": { - "state.json": stateContent, - }, - }); -}); - - -add_task(function* test_datareporting_not_dir() { - let [srcDir, targetDir] = getTestDirs(); - - writeToFile(srcDir, "datareporting", "I'm a file but should be a directory"); - - let ok = yield promiseTelemetryMigrator(srcDir, targetDir); - Assert.ok(ok, "callback should have been true even though the directory was a file"); - - checkDirectoryContains(targetDir, {}); -}); - -add_task(function* test_datareporting_empty() { - let [srcDir, targetDir] = getTestDirs(); - - // Migrate with an empty 'datareporting' subdir. - createSubDir(srcDir, "datareporting"); - let ok = yield promiseTelemetryMigrator(srcDir, targetDir); - Assert.ok(ok, "callback should have been true"); - - // We should end up with no migrated files. - checkDirectoryContains(targetDir, { - "datareporting": {}, - }); -}); - -add_task(function* test_healthreport_empty() { - let [srcDir, targetDir] = getTestDirs(); - - // Migrate with no 'datareporting' and an empty 'healthreport' subdir. - createSubDir(srcDir, "healthreport"); - let ok = yield promiseTelemetryMigrator(srcDir, targetDir); - Assert.ok(ok, "callback should have been true"); - - // We should end up with no migrated files. - checkDirectoryContains(targetDir, {}); -}); - -add_task(function* test_datareporting_many() { - let [srcDir, targetDir] = getTestDirs(); - - // Create some datareporting files. - let subDir = createSubDir(srcDir, "datareporting"); - let shouldBeCopied = "should be copied"; - writeToFile(subDir, "state.json", shouldBeCopied); - writeToFile(subDir, "session-state.json", shouldBeCopied); - writeToFile(subDir, "something.else", "should not"); - createSubDir(subDir, "emptyDir"); - - let ok = yield promiseTelemetryMigrator(srcDir, targetDir); - Assert.ok(ok, "callback should have been true"); - - checkDirectoryContains(targetDir, { - "datareporting" : { - "state.json": shouldBeCopied, - "session-state.json": shouldBeCopied, - } - }); -}); - -add_task(function* test_no_session_state() { - let [srcDir, targetDir] = getTestDirs(); - - // Check that migration still works properly if we only have state.json. - let subDir = createSubDir(srcDir, "datareporting"); - let stateContent = "abcd984"; - writeToFile(subDir, "state.json", stateContent); - - let ok = yield promiseTelemetryMigrator(srcDir, targetDir); - Assert.ok(ok, "callback should have been true"); - - checkDirectoryContains(targetDir, { - "datareporting" : { - "state.json": stateContent, - } - }); -}); - -add_task(function* test_no_state() { - let [srcDir, targetDir] = getTestDirs(); - - // Check that migration still works properly if we only have session-state.json. - let subDir = createSubDir(srcDir, "datareporting"); - let sessionStateContent = "abcd512"; - writeToFile(subDir, "session-state.json", sessionStateContent); - - let ok = yield promiseTelemetryMigrator(srcDir, targetDir); - Assert.ok(ok, "callback should have been true"); - - checkDirectoryContains(targetDir, { - "datareporting" : { - "session-state.json": sessionStateContent, - } - }); -}); - -add_task(function* test_times_migration() { - let [srcDir, targetDir] = getTestDirs(); - - // create a times.json in the source directory. - let contents = JSON.stringify({created: 1234}); - writeToFile(srcDir, "times.json", contents); - - let earliest = Date.now(); - let ok = yield promiseMigrator("times", srcDir, targetDir); - Assert.ok(ok, "callback should have been true"); - let latest = Date.now(); - - let timesFile = targetDir.clone(); - timesFile.append("times.json"); - - let raw = readFile(timesFile); - let times = JSON.parse(raw); - Assert.ok(times.reset >= earliest && times.reset <= latest); - // and it should have left the creation time alone. - Assert.equal(times.created, 1234); -}); diff --git a/browser/components/migration/tests/unit/xpcshell.ini b/browser/components/migration/tests/unit/xpcshell.ini deleted file mode 100644 index 1b9f0a5f1..000000000 --- a/browser/components/migration/tests/unit/xpcshell.ini +++ /dev/null @@ -1,26 +0,0 @@ -[DEFAULT] -head = head_migration.js -tail = -firefox-appdir = browser -skip-if = toolkit == 'android' -support-files = - Library/** - AppData/** - -[test_automigration.js] -[test_Chrome_cookies.js] -skip-if = os != "mac" # Relies on ULibDir -[test_Chrome_passwords.js] -skip-if = os != "win" -[test_Edge_availability.js] -[test_Edge_db_migration.js] -skip-if = os != "win" || os_version == "5.1" || os_version == "5.2" # Relies on post-XP bits of ESEDB -[test_fx_telemetry.js] -[test_IE_bookmarks.js] -skip-if = os != "win" -[test_IE_cookies.js] -skip-if = os != "win" -[test_IE7_passwords.js] -skip-if = os != "win" -[test_Safari_bookmarks.js] -skip-if = os != "mac" |