Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
FormAutofillUtils: "resource://gre/modules/shared/FormAutofillUtils.sys.mjs",
FirefoxBridgeExtensionUtils:
"resource:///modules/FirefoxBridgeExtensionUtils.sys.mjs",
LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs",
PlacesUIUtils: "resource:///modules/PlacesUIUtils.sys.mjs",
UrlbarPrefs: "resource:///modules/UrlbarPrefs.sys.mjs",
UsageReporting: "resource://gre/modules/UsageReporting.sys.mjs",
});
export let ProfileDataUpgrader = {
_migrateXULStoreForDocument(fromURL, toURL) {
Array.from(Services.xulStore.getIDsEnumerator(fromURL)).forEach(id => {
Array.from(Services.xulStore.getAttributeEnumerator(fromURL, id)).forEach(
attr => {
let value = Services.xulStore.getValue(fromURL, id, attr);
Services.xulStore.setValue(toURL, id, attr, value);
}
);
});
},
_migrateHashedKeysForXULStoreForDocument(docUrl) {
Array.from(Services.xulStore.getIDsEnumerator(docUrl))
.filter(id => id.startsWith("place:"))
.forEach(id => {
Services.xulStore.removeValue(docUrl, id, "open");
let hashedId = lazy.PlacesUIUtils.obfuscateUrlForXulStore(id);
Services.xulStore.setValue(docUrl, hashedId, "open", "true");
});
},
/**
* This method transforms data in the profile directory so that it can be
* used in the current version of Firefox. It is organized similar to
* typical database version upgrades: we are invoked with the version of the
* profile data on disk (`existingDataVersion`) and the version we expect/need
* (`newVersion`), and execute any necessary migrations.
*
* In practice, most of the migrations move user choices from one preference
* to another, or ensure that other mechanical file moves (e.g. of document
* URLs like browser.xhtml).
*
* If you're adding a new migration, you will need to increment
* APP_DATA_VERSION in BrowserGlue.sys.mjs' _migrateUI. That version is not
* in this module so that we can avoid loading this module entirely in common
* cases (Firefox startups where a profile is not upgraded).
*
* Note that this is invoked very early on startup and should try to avoid
* doing very expensive things immediately unless absolutely necessary. Some
* of the migrations will therefore set a pref or otherwise flag that their
* component needs to do more work later, perhaps during idle tasks or
* similar, to avoid front-loading the component initialization into this
* early part of startup. Of course, some of these migrations (e.g. to ensure
* that browser windows remember their sizes if the URL to browser.xhtml has
* changed) _need_ to run very early, and that is OK.
*
* @param {integer} existingDataVersion
* The version of the data in the profile.
* @param {integer} newVersion
* The version that the application expects/needs.
*/
// eslint-disable-next-line complexity
upgrade(existingDataVersion, newVersion) {
const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL;
let xulStore = Services.xulStore;
if (existingDataVersion < 90) {
this._migrateXULStoreForDocument(
"chrome://browser/content/places/historySidebar.xhtml"
);
this._migrateXULStoreForDocument(
"chrome://browser/content/places/places.xhtml"
);
this._migrateXULStoreForDocument(
"chrome://browser/content/places/bookmarksSidebar.xhtml"
);
}
// Clear socks proxy values if they were shared from http, to prevent
if (
existingDataVersion < 91 &&
Services.prefs.getBoolPref("network.proxy.share_proxy_settings", false) &&
Services.prefs.getIntPref("network.proxy.type", 0) == 1
) {
let httpProxy = Services.prefs.getCharPref("network.proxy.http", "");
let httpPort = Services.prefs.getIntPref("network.proxy.http_port", 0);
let socksProxy = Services.prefs.getCharPref("network.proxy.socks", "");
let socksPort = Services.prefs.getIntPref("network.proxy.socks_port", 0);
if (httpProxy && httpProxy == socksProxy && httpPort == socksPort) {
Services.prefs.setCharPref(
"network.proxy.socks",
Services.prefs.getCharPref("network.proxy.backup.socks", "")
);
Services.prefs.setIntPref(
"network.proxy.socks_port",
Services.prefs.getIntPref("network.proxy.backup.socks_port", 0)
);
}
}
if (existingDataVersion < 92) {
// privacy.userContext.longPressBehavior pref was renamed and changed to a boolean
let longpress = Services.prefs.getIntPref(
"privacy.userContext.longPressBehavior",
0
);
if (longpress == 1) {
Services.prefs.setBoolPref(
"privacy.userContext.newTabContainerOnLeftClick.enabled",
true
);
}
}
if (existingDataVersion < 93) {
// The Gecko Profiler Addon is now an internal component. Remove the old
// addon, and enable the new UI.
function enableProfilerButton(wasAddonActive) {
// Enable the feature pref. This will add it to the customization palette,
// but not to the the navbar.
Services.prefs.setBoolPref(
"devtools.performance.popup.feature-flag",
true
);
if (wasAddonActive) {
const { ProfilerMenuButton } = ChromeUtils.importESModule(
"resource://devtools/client/performance-new/popup/menu-button.sys.mjs"
);
if (!ProfilerMenuButton.isInNavbar()) {
ProfilerMenuButton.addToNavbar();
}
}
}
let addonPromise;
try {
addonPromise = lazy.AddonManager.getAddonByID(
"geckoprofiler@mozilla.com"
);
} catch (error) {
console.error(
"Could not access the AddonManager to upgrade the profile. This is most " +
"likely because the upgrader is being run from an xpcshell test where " +
"the AddonManager is not initialized."
);
}
Promise.resolve(addonPromise).then(addon => {
if (!addon) {
// Either the addon wasn't installed, or the call to getAddonByID failed.
return;
}
// Remove the old addon.
const wasAddonActive = addon.isActive;
addon
.uninstall()
.catch(console.error)
.then(() => enableProfilerButton(wasAddonActive))
.catch(console.error);
}, console.error);
}
if (existingDataVersion < 94) {
let backup = Services.prefs.getCharPref("network.proxy.backup.socks", "");
let backupPort = Services.prefs.getIntPref(
"network.proxy.backup.socks_port",
0
);
let socksProxy = Services.prefs.getCharPref("network.proxy.socks", "");
let socksPort = Services.prefs.getIntPref("network.proxy.socks_port", 0);
if (backup == socksProxy) {
Services.prefs.clearUserPref("network.proxy.backup.socks");
}
if (backupPort == socksPort) {
Services.prefs.clearUserPref("network.proxy.backup.socks_port");
}
}
if (existingDataVersion < 95) {
const oldPrefName = "media.autoplay.enabled.user-gestures-needed";
const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
const newPrefValue = oldPrefValue ? 0 : 1;
Services.prefs.setIntPref("media.autoplay.blocking_policy", newPrefValue);
Services.prefs.clearUserPref(oldPrefName);
}
if (existingDataVersion < 96) {
const oldPrefName = "browser.urlbar.openViewOnFocus";
const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
Services.prefs.setBoolPref(
"browser.urlbar.suggest.topsites",
oldPrefValue
);
Services.prefs.clearUserPref(oldPrefName);
}
if (existingDataVersion < 97) {
let userCustomizedWheelMax = Services.prefs.prefHasUserValue(
"general.smoothScroll.mouseWheel.durationMaxMS"
);
let userCustomizedWheelMin = Services.prefs.prefHasUserValue(
"general.smoothScroll.mouseWheel.durationMinMS"
);
if (!userCustomizedWheelMin && !userCustomizedWheelMax) {
// If the user has an existing profile but hasn't customized the wheel
// animation duration, they will now get the new default values. This
// condition used to set a migrationPercent pref to 0, so that users
// upgrading an older profile would gradually have their wheel animation
// speed migrated to the new values. However, that "gradual migration"
// was phased out by FF 86, so we don't need to set that pref anymore.
} else if (userCustomizedWheelMin && !userCustomizedWheelMax) {
// If they customized just one of the two, save the old value for the
// other one as well, because the two values go hand-in-hand and we
// don't want to move just one to a new value and leave the other one
// at a customized value. In both of these cases, we leave the "migration
// complete" percentage at 100, because they have customized this and
// don't need any further migration.
Services.prefs.setIntPref(
"general.smoothScroll.mouseWheel.durationMaxMS",
400
);
} else if (!userCustomizedWheelMin && userCustomizedWheelMax) {
// Same as above case, but for the other pref.
Services.prefs.setIntPref(
"general.smoothScroll.mouseWheel.durationMinMS",
200
);
} else {
// The last remaining case is if they customized both values, in which
// case also don't need to do anything; the user's customized values
// will be retained and respected.
}
}
if (existingDataVersion < 98) {
Services.prefs.clearUserPref("browser.search.cohort");
}
if (existingDataVersion < 99) {
Services.prefs.clearUserPref("security.tls.version.enable-deprecated");
}
if (existingDataVersion < 102) {
// In Firefox 83, we moved to a dynamic button, so it needs to be removed
// from default placement. This is done early enough that it doesn't
// impact adding new managed bookmarks.
const { CustomizableUI } = ChromeUtils.importESModule(
"resource:///modules/CustomizableUI.sys.mjs"
);
CustomizableUI.removeWidgetFromArea("managed-bookmarks");
}
// We have to rerun these because we had to use 102 on beta.
// They were 101 and 102 before.
if (existingDataVersion < 103) {
// Set a pref if the bookmarks toolbar was already visible,
// so we can keep it visible when navigating away from newtab
let bookmarksToolbarWasVisible =
Services.xulStore.getValue(
BROWSER_DOCURL,
"PersonalToolbar",
"collapsed"
) == "false";
if (bookmarksToolbarWasVisible) {
// Migrate the user to the "always visible" value. See firefox.js for
// the other possible states.
Services.prefs.setCharPref(
"browser.toolbars.bookmarks.visibility",
"always"
);
}
Services.xulStore.removeValue(
BROWSER_DOCURL,
"PersonalToolbar",
"collapsed"
);
Services.prefs.clearUserPref(
"browser.livebookmarks.migrationAttemptsLeft"
);
}
// For existing profiles, continue putting bookmarks in the
// "other bookmarks" folder.
if (existingDataVersion < 104) {
Services.prefs.setCharPref(
"browser.bookmarks.defaultLocation",
"unfiled"
);
}
// Renamed and flipped the logic of a pref to make its purpose more clear.
if (existingDataVersion < 105) {
const oldPrefName = "browser.urlbar.imeCompositionClosesPanel";
const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
Services.prefs.setBoolPref(
"browser.urlbar.keepPanelOpenDuringImeComposition",
!oldPrefValue
);
Services.prefs.clearUserPref(oldPrefName);
}
// Initialize the new browser.urlbar.showSuggestionsBeforeGeneral pref.
if (existingDataVersion < 106) {
lazy.UrlbarPrefs.initializeShowSearchSuggestionsFirstPref();
}
if (existingDataVersion < 107) {
// Migrate old http URIs for mailto handlers to their https equivalents.
// The handler service will do this. We need to wait with migrating
// until the handler service has started up, so just set a pref here.
const kPref = "browser.handlers.migrations";
// We might have set up another migration further up. Create an array,
// and drop empty strings resulting from the `split`:
let migrations = Services.prefs
.getCharPref(kPref, "")
.split(",")
.filter(x => !!x);
migrations.push("secure-mail");
Services.prefs.setCharPref(kPref, migrations.join(","));
}
if (existingDataVersion < 108) {
// Migrate old ctrlTab pref to new ctrlTab pref
let defaultValue = false;
let oldPrefName = "browser.ctrlTab.recentlyUsedOrder";
let oldPrefDefault = true;
// Use old pref value if the user used Ctrl+Tab before, elsewise use new default value
if (Services.prefs.getBoolPref("browser.engagement.ctrlTab.has-used")) {
let newPrefValue = Services.prefs.getBoolPref(
oldPrefName,
oldPrefDefault
);
Services.prefs.setBoolPref(
"browser.ctrlTab.sortByRecentlyUsed",
newPrefValue
);
} else {
Services.prefs.setBoolPref(
"browser.ctrlTab.sortByRecentlyUsed",
defaultValue
);
}
}
if (existingDataVersion < 109) {
// Migrate old pref to new pref
if (
Services.prefs.prefHasUserValue("signon.recipes.remoteRecipesEnabled")
) {
// Fetch the previous value of signon.recipes.remoteRecipesEnabled and assign it to signon.recipes.remoteRecipes.enabled.
Services.prefs.setBoolPref(
"signon.recipes.remoteRecipes.enabled",
Services.prefs.getBoolPref(
"signon.recipes.remoteRecipesEnabled",
true
)
);
//Then clear user pref
Services.prefs.clearUserPref("signon.recipes.remoteRecipesEnabled");
}
}
if (existingDataVersion < 120) {
// Migrate old titlebar bool pref to new int-based one.
const oldPref = "browser.tabs.drawInTitlebar";
const newPref = "browser.tabs.inTitlebar";
if (Services.prefs.prefHasUserValue(oldPref)) {
const oldPrefType = Services.prefs.getPrefType(oldPref);
if (oldPrefType == Services.prefs.PREF_BOOL) {
Services.prefs.setIntPref(
newPref,
Services.prefs.getBoolPref(oldPref) ? 1 : 0
);
} else {
Services.prefs.setIntPref(
newPref,
Services.prefs.getIntPref(oldPref)
);
}
Services.prefs.clearUserPref(oldPref);
}
}
if (existingDataVersion < 121) {
// Migrate stored uris and convert them to use hashed keys
this._migrateHashedKeysForXULStoreForDocument(BROWSER_DOCURL);
this._migrateHashedKeysForXULStoreForDocument(
"chrome://browser/content/places/bookmarksSidebar.xhtml"
);
this._migrateHashedKeysForXULStoreForDocument(
"chrome://browser/content/places/historySidebar.xhtml"
);
}
if (existingDataVersion < 122) {
// Migrate xdg-desktop-portal pref from old to new prefs.
try {
const oldPref = "widget.use-xdg-desktop-portal";
if (Services.prefs.getBoolPref(oldPref)) {
Services.prefs.setIntPref(
"widget.use-xdg-desktop-portal.file-picker",
1
);
Services.prefs.setIntPref(
"widget.use-xdg-desktop-portal.mime-handler",
1
);
}
Services.prefs.clearUserPref(oldPref);
} catch (ex) {}
}
// as this version is most likely set for the Nightly channel
if (existingDataVersion < 124) {
// Migrate "extensions.formautofill.available" and
// "extensions.formautofill.creditCards.available" from old to new prefs
const oldFormAutofillModule = "extensions.formautofill.available";
const oldCreditCardsAvailable =
"extensions.formautofill.creditCards.available";
const newCreditCardsAvailable =
"extensions.formautofill.creditCards.supported";
const newAddressesAvailable =
"extensions.formautofill.addresses.supported";
if (Services.prefs.prefHasUserValue(oldFormAutofillModule)) {
let moduleAvailability = Services.prefs.getCharPref(
oldFormAutofillModule
);
if (moduleAvailability == "on") {
Services.prefs.setCharPref(newAddressesAvailable, moduleAvailability);
Services.prefs.setCharPref(
newCreditCardsAvailable,
Services.prefs.getBoolPref(oldCreditCardsAvailable) ? "on" : "off"
);
}
if (moduleAvailability == "off") {
Services.prefs.setCharPref(
newCreditCardsAvailable,
moduleAvailability
);
Services.prefs.setCharPref(newAddressesAvailable, moduleAvailability);
}
}
// after migrating, clear old prefs so we can remove them later.
Services.prefs.clearUserPref(oldFormAutofillModule);
Services.prefs.clearUserPref(oldCreditCardsAvailable);
}
if (existingDataVersion < 125) {
// coordinate space.
const PIP_PLAYER_URI =
"chrome://global/content/pictureinpicture/player.xhtml";
try {
for (let value of ["left", "top", "width", "height"]) {
Services.xulStore.removeValue(
PIP_PLAYER_URI,
"picture-in-picture",
value
);
}
} catch (ex) {
console.error("Failed to clear XULStore PiP values: ", ex);
}
}
function migrateXULAttributeToStyle(url, id, attr) {
try {
let value = Services.xulStore.getValue(url, id, attr);
if (value) {
Services.xulStore.setValue(url, id, "style", `${attr}: ${value}px;`);
}
} catch (ex) {
console.error(`Error migrating ${id}'s ${attr} value: `, ex);
}
}
// migration. This version is already in use in the nightly channel, so it
// shouldn't be used.
if (existingDataVersion < 130) {
migrateXULAttributeToStyle(BROWSER_DOCURL, "sidebar-box", "width");
}
// Migration 131 was moved to 133 to allow for an uplift.
if (existingDataVersion < 132) {
// These attributes are no longer persisted, thus remove them from xulstore.
for (let url of [
"chrome://browser/content/places/bookmarkProperties.xhtml",
]) {
for (let attr of ["width", "screenX", "screenY"]) {
xulStore.removeValue(url, "bookmarkproperties", attr);
}
}
}
if (existingDataVersion < 133) {
xulStore.removeValue(BROWSER_DOCURL, "urlbar-container", "width");
}
// Migration 134 was removed because it was no longer necessary.
if (existingDataVersion < 135 && AppConstants.platform == "linux") {
// Avoid changing titlebar setting for users that used to had it off.
try {
if (!Services.prefs.prefHasUserValue("browser.tabs.inTitlebar")) {
let de = Services.appinfo.desktopEnvironment;
let oldDefault = de.includes("gnome") || de.includes("pantheon");
if (!oldDefault) {
Services.prefs.setIntPref("browser.tabs.inTitlebar", 0);
}
}
} catch (e) {
console.error("Error migrating tabsInTitlebar setting", e);
}
}
if (existingDataVersion < 136) {
migrateXULAttributeToStyle(
"chrome://browser/content/places/places.xhtml",
"placesList",
"width"
);
}
if (existingDataVersion < 137) {
// The default value for enabling smooth scrolls is now false if the
// user prefers reduced motion. If the value was previously set, do
// not reset it, but if it was not explicitly set preserve the old
// default value.
if (
!Services.prefs.prefHasUserValue("general.smoothScroll") &&
Services.appinfo.prefersReducedMotion
) {
Services.prefs.setBoolPref("general.smoothScroll", true);
}
}
if (existingDataVersion < 138) {
// permissions with https scheme to http scheme.
try {
Services.perms
.getAllByTypes(["https-only-load-insecure"])
.filter(permission => permission.principal.schemeIs("https"))
.forEach(permission => {
const capability = permission.capability;
const uri = permission.principal.URI.mutate()
.setScheme("http")
.finalize();
const principal =
Services.scriptSecurityManager.createContentPrincipal(uri, {});
Services.perms.removePermission(permission);
Services.perms.addFromPrincipal(
principal,
"https-only-load-insecure",
capability
);
});
} catch (e) {
console.error("Error migrating https-only-load-insecure permission", e);
}
}
if (existingDataVersion < 139) {
// Reset the default permissions to ALLOW_ACTION to rollback issues for
// originInfo in the format [origin, type]
[
["about:home", "uitour"],
["about:newtab", "uitour"],
["about:welcome", "autoplay-media"],
].forEach(originInfo => {
// Reset permission on the condition that it is set to
// UNKNOWN_ACTION, we want to prevent resetting user
// manipulated permissions
if (
Services.perms.UNKNOWN_ACTION ==
Services.perms.testPermissionFromPrincipal(
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
originInfo[0]
),
originInfo[1]
)
) {
// Adding permissions which have default values does not create
// new permissions, but rather remove the UNKNOWN_ACTION permission
Services.perms.addFromPrincipal(
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
originInfo[0]
),
originInfo[1],
Services.perms.ALLOW_ACTION
);
}
});
}
if (existingDataVersion < 140) {
Services.prefs.clearUserPref("browser.fixup.alternate.enabled");
}
if (existingDataVersion < 141) {
for (const filename of ["signons.sqlite", "signons.sqlite.corrupt"]) {
const filePath = PathUtils.join(PathUtils.profileDir, filename);
IOUtils.remove(filePath, { ignoreAbsent: true }).catch(console.error);
}
}
if (existingDataVersion < 142) {
try {
let value = xulStore.getValue(BROWSER_DOCURL, "sidebar-box", "style");
if (value) {
// Remove custom properties.
value = value
.split(";")
.filter(v => !v.trim().startsWith("--"))
.join(";");
xulStore.setValue(BROWSER_DOCURL, "sidebar-box", "style", value);
}
} catch (ex) {
console.error(ex);
}
}
if (existingDataVersion < 143) {
// Version 143 has been superseded by version 145 below.
}
if (existingDataVersion < 144) {
// the ShutdownDuration.json file would be written to disk at shutdown
// so that the next launch of the browser could read it in and send
// shutdown performance measurements.
//
// Unfortunately, this mechanism and its measurements were fairly
// unreliable, so they were removed.
for (const filename of [
"ShutdownDuration.json",
"ShutdownDuration.json.tmp",
]) {
const filePath = PathUtils.join(PathUtils.profileDir, filename);
IOUtils.remove(filePath, { ignoreAbsent: true }).catch(console.error);
}
}
if (existingDataVersion < 145) {
if (AppConstants.platform == "win") {
// In Firefox 122, we enabled the firefox and firefox-private protocols.
// We switched over to using firefox-bridge and firefox-private-bridge,
// but we want to clean up the use of the other protocols.
lazy.FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
lazy.FirefoxBridgeExtensionUtils.OLD_PUBLIC_PROTOCOL,
lazy.FirefoxBridgeExtensionUtils.OLD_PRIVATE_PROTOCOL
);
// Clean up the old user prefs from FX 122
Services.prefs.clearUserPref(
"network.protocol-handler.external.firefox"
);
Services.prefs.clearUserPref(
"network.protocol-handler.external.firefox-private"
);
// In Firefox 126, we switched over to using native messaging so the
// protocols are no longer necessary even in firefox-bridge and
// firefox-private-bridge form
lazy.FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
lazy.FirefoxBridgeExtensionUtils.PUBLIC_PROTOCOL,
lazy.FirefoxBridgeExtensionUtils.PRIVATE_PROTOCOL
);
Services.prefs.clearUserPref(
"network.protocol-handler.external.firefox-bridge"
);
Services.prefs.clearUserPref(
"network.protocol-handler.external.firefox-private-bridge"
);
Services.prefs.clearUserPref("browser.shell.customProtocolsRegistered");
}
}
// Version 146 had a typo issue and thus it has been replaced by 147.
if (existingDataVersion < 147) {
// We're securing the boolean prefs for OS Authentication.
// This is achieved by converting them into a string pref and encrypting the values
// stored inside it.
// Note: we don't run this on nightly builds and we also do not run this
// for users with primary password enabled. That means both these sets of
// users will have the features turned on by default. For Nightly this is
// an intentional product decision; for primary password this is because
// we cannot encrypt the opt-out value without asking for the primary
// password, which in turn means we cannot migrate without doing so. It
// is also very difficult to postpone this migration because there is no
// way to know when the user has put in the primary password. We will
// probably reconsider some of this architecture in future, but for now
// this is the least-painful method considering the alternatives, cf.
if (
!AppConstants.NIGHTLY_BUILD &&
!lazy.LoginHelper.isPrimaryPasswordSet()
) {
const hasRunBetaMigration = Services.prefs
.getCharPref("browser.startup.homepage_override.mstone", "")
.startsWith("127.0");
// Version 146 UI migration wrote to a wrong `creditcards` pref when
// the feature was disabled, instead it should have used `creditCards`.
// The correct pref name is in AUTOFILL_CREDITCARDS_REAUTH_PREF.
// Note that we only wrote prefs if the feature was disabled.
let ccTypoDisabled = !lazy.FormAutofillUtils.getOSAuthEnabled(
"extensions.formautofill.creditcards.reauth.optout"
);
let ccCorrectPrefDisabled = !lazy.FormAutofillUtils.getOSAuthEnabled(
lazy.FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF
);
let ccPrevReauthPrefValue = Services.prefs.getBoolPref(
"extensions.formautofill.reauth.enabled",
false
);
let userHadEnabledCreditCardReauth =
// If we've run beta migration, and neither typo nor correct pref
// indicate disablement, the user enabled the pref:
(hasRunBetaMigration && !ccTypoDisabled && !ccCorrectPrefDisabled) ||
// Or if we never ran beta migration and the bool pref is set:
ccPrevReauthPrefValue;
lazy.FormAutofillUtils.setOSAuthEnabled(
lazy.FormAutofillUtils.AUTOFILL_CREDITCARDS_REAUTH_PREF,
userHadEnabledCreditCardReauth
);
if (!hasRunBetaMigration) {
const passwordsPrevReauthPrefValue = Services.prefs.getBoolPref(
"signon.management.page.os-auth.enabled",
false
);
lazy.LoginHelper.setOSAuthEnabled(
lazy.LoginHelper.OS_AUTH_FOR_PASSWORDS_PREF,
passwordsPrevReauthPrefValue
);
}
}
Services.prefs.clearUserPref("extensions.formautofill.reauth.enabled");
Services.prefs.clearUserPref("signon.management.page.os-auth.enabled");
Services.prefs.clearUserPref(
"extensions.formautofill.creditcards.reauth.optout"
);
}
if (existingDataVersion < 148) {
// The Firefox Translations addon is now a built-in Firefox feature.
let addonPromise;
try {
addonPromise = lazy.AddonManager.getAddonByID(
"firefox-translations-addon@mozilla.org"
);
} catch (error) {
// This always throws in xpcshell as the AddonManager is not initialized.
if (!Services.env.exists("XPCSHELL_TEST_PROFILE_DIR")) {
console.error(
"Could not access the AddonManager to upgrade the profile."
);
}
}
addonPromise?.then(addon => addon?.uninstall()).catch(console.error);
}
if (existingDataVersion < 149) {
// remove permissions used by deleted nsContentManager
[
"other",
"script",
"image",
"stylesheet",
"object",
"document",
"subdocument",
"refresh",
"xbl",
"ping",
"xmlhttprequest",
"objectsubrequest",
"dtd",
"font",
"websocket",
"csp_report",
"xslt",
"beacon",
"fetch",
"manifest",
"speculative",
].forEach(type => {
Services.perms.removeByType(type);
});
}
if (existingDataVersion < 150) {
Services.prefs.clearUserPref("toolkit.telemetry.pioneerId");
}
if (existingDataVersion < 151) {
// Existing Firefox users should have the usage reporting upload
// preference "inherit" the general data reporting preference.
lazy.UsageReporting.adoptDataReportingPreference();
}
if (
existingDataVersion < 152 &&
Services.prefs.getBoolPref("sidebar.revamp") &&
!Services.prefs.getBoolPref("browser.ml.chat.enabled")
) {
let tools = Services.prefs.getCharPref("sidebar.main.tools");
if (tools?.includes("aichat")) {
let updatedTools = tools
.split(",")
.filter(t => t != "aichat")
.join(",");
Services.prefs.setCharPref("sidebar.main.tools", updatedTools);
}
}
if (
existingDataVersion < 153 &&
Services.prefs.getBoolPref("sidebar.revamp") &&
!Services.prefs.prefHasUserValue("sidebar.main.tools")
) {
// This pref will now be a user set branch but we want to preserve the previous
// default value for existing sidebar.revamp users who hadn't changed it.
Services.prefs.setCharPref(
"sidebar.main.tools",
"aichat,syncedtabs,history"
);
}
if (existingDataVersion < 154) {
// Remove mibbit handler.
// The handler service will do this. We need to wait with migrating
// until the handler service has started up, so just set a pref here.
const kPref = "browser.handlers.migrations";
// We might have set up another migration further up. Create an array,
// and drop empty strings resulting from the `split`:
let migrations = Services.prefs
.getCharPref(kPref, "")
.split(",")
.filter(x => !!x);
migrations.push("mibbit");
Services.prefs.setCharPref(kPref, migrations.join(","));
}
if (existingDataVersion < 155) {
// Remove outdated sidebar info from XULStore.
for (const attr of [
"checked",
"positionend",
"sidebarcommand",
"style",
]) {
Services.xulStore.removeValue(BROWSER_DOCURL, "sidebar-box", attr);
}
}
// Update the migration version.
Services.prefs.setIntPref("browser.migration.version", newVersion);
},
};