tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ProfileDataUpgrader.sys.mjs (45311B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
      6 
      7 const lazy = {};
      8 
      9 ChromeUtils.defineESModuleGetters(lazy, {
     10  AddonManager: "resource://gre/modules/AddonManager.sys.mjs",
     11  FormAutofillUtils: "resource://gre/modules/shared/FormAutofillUtils.sys.mjs",
     12  FirefoxBridgeExtensionUtils:
     13    "resource:///modules/FirefoxBridgeExtensionUtils.sys.mjs",
     14  LoginHelper: "resource://gre/modules/LoginHelper.sys.mjs",
     15  PlacesUIUtils: "moz-src:///browser/components/places/PlacesUIUtils.sys.mjs",
     16  UsageReporting: "resource://gre/modules/UsageReporting.sys.mjs",
     17 });
     18 
     19 export let ProfileDataUpgrader = {
     20  _migrateXULStoreForDocument(fromURL, toURL) {
     21    Array.from(Services.xulStore.getIDsEnumerator(fromURL)).forEach(id => {
     22      Array.from(Services.xulStore.getAttributeEnumerator(fromURL, id)).forEach(
     23        attr => {
     24          let value = Services.xulStore.getValue(fromURL, id, attr);
     25          Services.xulStore.setValue(toURL, id, attr, value);
     26        }
     27      );
     28    });
     29  },
     30 
     31  _migrateHashedKeysForXULStoreForDocument(docUrl) {
     32    Array.from(Services.xulStore.getIDsEnumerator(docUrl))
     33      .filter(id => id.startsWith("place:"))
     34      .forEach(id => {
     35        Services.xulStore.removeValue(docUrl, id, "open");
     36        let hashedId = lazy.PlacesUIUtils.obfuscateUrlForXulStore(id);
     37        Services.xulStore.setValue(docUrl, hashedId, "open", "true");
     38      });
     39  },
     40 
     41  /**
     42   * This method transforms data in the profile directory so that it can be
     43   * used in the current version of Firefox. It is organized similar to
     44   * typical database version upgrades: we are invoked with the version of the
     45   * profile data on disk (`existingDataVersion`) and the version we expect/need
     46   * (`newVersion`), and execute any necessary migrations.
     47   *
     48   * In practice, most of the migrations move user choices from one preference
     49   * to another, or ensure that other mechanical file moves (e.g. of document
     50   * URLs like browser.xhtml).
     51   *
     52   * If you're adding a new migration, you will need to increment
     53   * APP_DATA_VERSION in BrowserGlue.sys.mjs' _migrateUI. That version is not
     54   * in this module so that we can avoid loading this module entirely in common
     55   * cases (Firefox startups where a profile is not upgraded).
     56   *
     57   * Note that this is invoked very early on startup and should try to avoid
     58   * doing very expensive things immediately unless absolutely necessary. Some
     59   * of the migrations will therefore set a pref or otherwise flag that their
     60   * component needs to do more work later, perhaps during idle tasks or
     61   * similar, to avoid front-loading the component initialization into this
     62   * early part of startup. Of course, some of these migrations (e.g. to ensure
     63   * that browser windows remember their sizes if the URL to browser.xhtml has
     64   * changed) _need_ to run very early, and that is OK.
     65   *
     66   * @param {integer} existingDataVersion
     67   *  The version of the data in the profile.
     68   * @param {integer} newVersion
     69   *  The version that the application expects/needs.
     70   */
     71  // eslint-disable-next-line complexity
     72  upgrade(existingDataVersion, newVersion) {
     73    const BROWSER_DOCURL = AppConstants.BROWSER_CHROME_URL;
     74 
     75    let xulStore = Services.xulStore;
     76 
     77    if (existingDataVersion < 90) {
     78      this._migrateXULStoreForDocument(
     79        "chrome://browser/content/places/historySidebar.xul",
     80        "chrome://browser/content/places/historySidebar.xhtml"
     81      );
     82      this._migrateXULStoreForDocument(
     83        "chrome://browser/content/places/places.xul",
     84        "chrome://browser/content/places/places.xhtml"
     85      );
     86      this._migrateXULStoreForDocument(
     87        "chrome://browser/content/places/bookmarksSidebar.xul",
     88        "chrome://browser/content/places/bookmarksSidebar.xhtml"
     89      );
     90    }
     91 
     92    // Clear socks proxy values if they were shared from http, to prevent
     93    // websocket breakage after bug 1577862 (see bug 969282).
     94    if (
     95      existingDataVersion < 91 &&
     96      Services.prefs.getBoolPref("network.proxy.share_proxy_settings", false) &&
     97      Services.prefs.getIntPref("network.proxy.type", 0) == 1
     98    ) {
     99      let httpProxy = Services.prefs.getCharPref("network.proxy.http", "");
    100      let httpPort = Services.prefs.getIntPref("network.proxy.http_port", 0);
    101      let socksProxy = Services.prefs.getCharPref("network.proxy.socks", "");
    102      let socksPort = Services.prefs.getIntPref("network.proxy.socks_port", 0);
    103      if (httpProxy && httpProxy == socksProxy && httpPort == socksPort) {
    104        Services.prefs.setCharPref(
    105          "network.proxy.socks",
    106          Services.prefs.getCharPref("network.proxy.backup.socks", "")
    107        );
    108        Services.prefs.setIntPref(
    109          "network.proxy.socks_port",
    110          Services.prefs.getIntPref("network.proxy.backup.socks_port", 0)
    111        );
    112      }
    113    }
    114 
    115    if (existingDataVersion < 92) {
    116      // privacy.userContext.longPressBehavior pref was renamed and changed to a boolean
    117      let longpress = Services.prefs.getIntPref(
    118        "privacy.userContext.longPressBehavior",
    119        0
    120      );
    121      if (longpress == 1) {
    122        Services.prefs.setBoolPref(
    123          "privacy.userContext.newTabContainerOnLeftClick.enabled",
    124          true
    125        );
    126      }
    127    }
    128 
    129    if (existingDataVersion < 93) {
    130      // The Gecko Profiler Addon is now an internal component. Remove the old
    131      // addon, and enable the new UI.
    132 
    133      function enableProfilerButton(wasAddonActive) {
    134        // Enable the feature pref. This will add it to the customization palette,
    135        // but not to the the navbar.
    136        Services.prefs.setBoolPref(
    137          "devtools.performance.popup.feature-flag",
    138          true
    139        );
    140 
    141        if (wasAddonActive) {
    142          const { ProfilerMenuButton } = ChromeUtils.importESModule(
    143            "resource://devtools/client/performance-new/popup/menu-button.sys.mjs"
    144          );
    145          if (!ProfilerMenuButton.isInNavbar()) {
    146            ProfilerMenuButton.addToNavbar();
    147          }
    148        }
    149      }
    150 
    151      let addonPromise;
    152      try {
    153        addonPromise = lazy.AddonManager.getAddonByID(
    154          "geckoprofiler@mozilla.com"
    155        );
    156      } catch (error) {
    157        console.error(
    158          "Could not access the AddonManager to upgrade the profile. This is most " +
    159            "likely because the upgrader is being run from an xpcshell test where " +
    160            "the AddonManager is not initialized."
    161        );
    162      }
    163      Promise.resolve(addonPromise).then(addon => {
    164        if (!addon) {
    165          // Either the addon wasn't installed, or the call to getAddonByID failed.
    166          return;
    167        }
    168        // Remove the old addon.
    169        const wasAddonActive = addon.isActive;
    170        addon
    171          .uninstall()
    172          .catch(console.error)
    173          .then(() => enableProfilerButton(wasAddonActive))
    174          .catch(console.error);
    175      }, console.error);
    176    }
    177 
    178    // Clear unused socks proxy backup values - see bug 1625773.
    179    if (existingDataVersion < 94) {
    180      let backup = Services.prefs.getCharPref("network.proxy.backup.socks", "");
    181      let backupPort = Services.prefs.getIntPref(
    182        "network.proxy.backup.socks_port",
    183        0
    184      );
    185      let socksProxy = Services.prefs.getCharPref("network.proxy.socks", "");
    186      let socksPort = Services.prefs.getIntPref("network.proxy.socks_port", 0);
    187      if (backup == socksProxy) {
    188        Services.prefs.clearUserPref("network.proxy.backup.socks");
    189      }
    190      if (backupPort == socksPort) {
    191        Services.prefs.clearUserPref("network.proxy.backup.socks_port");
    192      }
    193    }
    194 
    195    if (existingDataVersion < 95) {
    196      const oldPrefName = "media.autoplay.enabled.user-gestures-needed";
    197      const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
    198      const newPrefValue = oldPrefValue ? 0 : 1;
    199      Services.prefs.setIntPref("media.autoplay.blocking_policy", newPrefValue);
    200      Services.prefs.clearUserPref(oldPrefName);
    201    }
    202 
    203    if (existingDataVersion < 96) {
    204      const oldPrefName = "browser.urlbar.openViewOnFocus";
    205      const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
    206      Services.prefs.setBoolPref(
    207        "browser.urlbar.suggest.topsites",
    208        oldPrefValue
    209      );
    210      Services.prefs.clearUserPref(oldPrefName);
    211    }
    212 
    213    if (existingDataVersion < 97) {
    214      let userCustomizedWheelMax = Services.prefs.prefHasUserValue(
    215        "general.smoothScroll.mouseWheel.durationMaxMS"
    216      );
    217      let userCustomizedWheelMin = Services.prefs.prefHasUserValue(
    218        "general.smoothScroll.mouseWheel.durationMinMS"
    219      );
    220 
    221      if (!userCustomizedWheelMin && !userCustomizedWheelMax) {
    222        // If the user has an existing profile but hasn't customized the wheel
    223        // animation duration, they will now get the new default values. This
    224        // condition used to set a migrationPercent pref to 0, so that users
    225        // upgrading an older profile would gradually have their wheel animation
    226        // speed migrated to the new values. However, that "gradual migration"
    227        // was phased out by FF 86, so we don't need to set that pref anymore.
    228      } else if (userCustomizedWheelMin && !userCustomizedWheelMax) {
    229        // If they customized just one of the two, save the old value for the
    230        // other one as well, because the two values go hand-in-hand and we
    231        // don't want to move just one to a new value and leave the other one
    232        // at a customized value. In both of these cases, we leave the "migration
    233        // complete" percentage at 100, because they have customized this and
    234        // don't need any further migration.
    235        Services.prefs.setIntPref(
    236          "general.smoothScroll.mouseWheel.durationMaxMS",
    237          400
    238        );
    239      } else if (!userCustomizedWheelMin && userCustomizedWheelMax) {
    240        // Same as above case, but for the other pref.
    241        Services.prefs.setIntPref(
    242          "general.smoothScroll.mouseWheel.durationMinMS",
    243          200
    244        );
    245      } else {
    246        // The last remaining case is if they customized both values, in which
    247        // case also don't need to do anything; the user's customized values
    248        // will be retained and respected.
    249      }
    250    }
    251 
    252    if (existingDataVersion < 98) {
    253      Services.prefs.clearUserPref("browser.search.cohort");
    254    }
    255 
    256    if (existingDataVersion < 99) {
    257      Services.prefs.clearUserPref("security.tls.version.enable-deprecated");
    258    }
    259 
    260    if (existingDataVersion < 102) {
    261      // In Firefox 83, we moved to a dynamic button, so it needs to be removed
    262      // from default placement. This is done early enough that it doesn't
    263      // impact adding new managed bookmarks.
    264      const { CustomizableUI } = ChromeUtils.importESModule(
    265        "moz-src:///browser/components/customizableui/CustomizableUI.sys.mjs"
    266      );
    267      CustomizableUI.removeWidgetFromArea("managed-bookmarks");
    268    }
    269 
    270    // We have to rerun these because we had to use 102 on beta.
    271    // They were 101 and 102 before.
    272    if (existingDataVersion < 103) {
    273      // Set a pref if the bookmarks toolbar was already visible,
    274      // so we can keep it visible when navigating away from newtab
    275      let bookmarksToolbarWasVisible =
    276        Services.xulStore.getValue(
    277          BROWSER_DOCURL,
    278          "PersonalToolbar",
    279          "collapsed"
    280        ) == "false";
    281      if (bookmarksToolbarWasVisible) {
    282        // Migrate the user to the "always visible" value. See firefox.js for
    283        // the other possible states.
    284        Services.prefs.setCharPref(
    285          "browser.toolbars.bookmarks.visibility",
    286          "always"
    287        );
    288      }
    289      Services.xulStore.removeValue(
    290        BROWSER_DOCURL,
    291        "PersonalToolbar",
    292        "collapsed"
    293      );
    294 
    295      Services.prefs.clearUserPref(
    296        "browser.livebookmarks.migrationAttemptsLeft"
    297      );
    298    }
    299 
    300    // For existing profiles, continue putting bookmarks in the
    301    // "other bookmarks" folder.
    302    if (existingDataVersion < 104) {
    303      Services.prefs.setCharPref(
    304        "browser.bookmarks.defaultLocation",
    305        "unfiled"
    306      );
    307    }
    308 
    309    // Renamed and flipped the logic of a pref to make its purpose more clear.
    310    if (existingDataVersion < 105) {
    311      const oldPrefName = "browser.urlbar.imeCompositionClosesPanel";
    312      const oldPrefValue = Services.prefs.getBoolPref(oldPrefName, true);
    313      Services.prefs.setBoolPref(
    314        "browser.urlbar.keepPanelOpenDuringImeComposition",
    315        !oldPrefValue
    316      );
    317      Services.prefs.clearUserPref(oldPrefName);
    318    }
    319 
    320    if (existingDataVersion < 107) {
    321      // Migrate old http URIs for mailto handlers to their https equivalents.
    322      // The handler service will do this. We need to wait with migrating
    323      // until the handler service has started up, so just set a pref here.
    324      const kPref = "browser.handlers.migrations";
    325      // We might have set up another migration further up. Create an array,
    326      // and drop empty strings resulting from the `split`:
    327      let migrations = Services.prefs
    328        .getCharPref(kPref, "")
    329        .split(",")
    330        .filter(x => !!x);
    331      migrations.push("secure-mail");
    332      Services.prefs.setCharPref(kPref, migrations.join(","));
    333    }
    334 
    335    if (existingDataVersion < 108) {
    336      // Migrate old ctrlTab pref to new ctrlTab pref
    337      let defaultValue = false;
    338      let oldPrefName = "browser.ctrlTab.recentlyUsedOrder";
    339      let oldPrefDefault = true;
    340      // Use old pref value if the user used Ctrl+Tab before, elsewise use new default value
    341      if (Services.prefs.getBoolPref("browser.engagement.ctrlTab.has-used")) {
    342        let newPrefValue = Services.prefs.getBoolPref(
    343          oldPrefName,
    344          oldPrefDefault
    345        );
    346        Services.prefs.setBoolPref(
    347          "browser.ctrlTab.sortByRecentlyUsed",
    348          newPrefValue
    349        );
    350      } else {
    351        Services.prefs.setBoolPref(
    352          "browser.ctrlTab.sortByRecentlyUsed",
    353          defaultValue
    354        );
    355      }
    356    }
    357 
    358    if (existingDataVersion < 109) {
    359      // Migrate old pref to new pref
    360      if (
    361        Services.prefs.prefHasUserValue("signon.recipes.remoteRecipesEnabled")
    362      ) {
    363        // Fetch the previous value of signon.recipes.remoteRecipesEnabled and assign it to signon.recipes.remoteRecipes.enabled.
    364        Services.prefs.setBoolPref(
    365          "signon.recipes.remoteRecipes.enabled",
    366          Services.prefs.getBoolPref(
    367            "signon.recipes.remoteRecipesEnabled",
    368            true
    369          )
    370        );
    371        //Then clear user pref
    372        Services.prefs.clearUserPref("signon.recipes.remoteRecipesEnabled");
    373      }
    374    }
    375 
    376    if (existingDataVersion < 120) {
    377      // Migrate old titlebar bool pref to new int-based one.
    378      const oldPref = "browser.tabs.drawInTitlebar";
    379      const newPref = "browser.tabs.inTitlebar";
    380      if (Services.prefs.prefHasUserValue(oldPref)) {
    381        // We may have int prefs for builds between bug 1736518 and bug 1739539.
    382        const oldPrefType = Services.prefs.getPrefType(oldPref);
    383        if (oldPrefType == Services.prefs.PREF_BOOL) {
    384          Services.prefs.setIntPref(
    385            newPref,
    386            Services.prefs.getBoolPref(oldPref) ? 1 : 0
    387          );
    388        } else {
    389          Services.prefs.setIntPref(
    390            newPref,
    391            Services.prefs.getIntPref(oldPref)
    392          );
    393        }
    394        Services.prefs.clearUserPref(oldPref);
    395      }
    396    }
    397 
    398    if (existingDataVersion < 121) {
    399      // Migrate stored uris and convert them to use hashed keys
    400      this._migrateHashedKeysForXULStoreForDocument(BROWSER_DOCURL);
    401      this._migrateHashedKeysForXULStoreForDocument(
    402        "chrome://browser/content/places/bookmarksSidebar.xhtml"
    403      );
    404      this._migrateHashedKeysForXULStoreForDocument(
    405        "chrome://browser/content/places/historySidebar.xhtml"
    406      );
    407    }
    408 
    409    if (existingDataVersion < 122) {
    410      // Migrate xdg-desktop-portal pref from old to new prefs.
    411      try {
    412        const oldPref = "widget.use-xdg-desktop-portal";
    413        if (Services.prefs.getBoolPref(oldPref)) {
    414          Services.prefs.setIntPref(
    415            "widget.use-xdg-desktop-portal.file-picker",
    416            1
    417          );
    418          Services.prefs.setIntPref(
    419            "widget.use-xdg-desktop-portal.mime-handler",
    420            1
    421          );
    422        }
    423        Services.prefs.clearUserPref(oldPref);
    424      } catch (ex) {}
    425    }
    426 
    427    // Bug 1745248: Due to multiple backouts, do not use UI Version 123
    428    // as this version is most likely set for the Nightly channel
    429 
    430    if (existingDataVersion < 124) {
    431      // Migrate "extensions.formautofill.available" and
    432      // "extensions.formautofill.creditCards.available" from old to new prefs
    433      const oldFormAutofillModule = "extensions.formautofill.available";
    434      const oldCreditCardsAvailable =
    435        "extensions.formautofill.creditCards.available";
    436      const newCreditCardsAvailable =
    437        "extensions.formautofill.creditCards.supported";
    438      const newAddressesAvailable =
    439        "extensions.formautofill.addresses.supported";
    440      if (Services.prefs.prefHasUserValue(oldFormAutofillModule)) {
    441        let moduleAvailability = Services.prefs.getCharPref(
    442          oldFormAutofillModule
    443        );
    444        if (moduleAvailability == "on") {
    445          Services.prefs.setCharPref(newAddressesAvailable, moduleAvailability);
    446          Services.prefs.setCharPref(
    447            newCreditCardsAvailable,
    448            Services.prefs.getBoolPref(oldCreditCardsAvailable) ? "on" : "off"
    449          );
    450        }
    451 
    452        if (moduleAvailability == "off") {
    453          Services.prefs.setCharPref(
    454            newCreditCardsAvailable,
    455            moduleAvailability
    456          );
    457          Services.prefs.setCharPref(newAddressesAvailable, moduleAvailability);
    458        }
    459      }
    460 
    461      // after migrating, clear old prefs so we can remove them later.
    462      Services.prefs.clearUserPref(oldFormAutofillModule);
    463      Services.prefs.clearUserPref(oldCreditCardsAvailable);
    464    }
    465 
    466    if (existingDataVersion < 125) {
    467      // Bug 1756243 - Clear PiP cached coordinates since we changed their
    468      // coordinate space.
    469      const PIP_PLAYER_URI =
    470        "chrome://global/content/pictureinpicture/player.xhtml";
    471      try {
    472        for (let value of ["left", "top", "width", "height"]) {
    473          Services.xulStore.removeValue(
    474            PIP_PLAYER_URI,
    475            "picture-in-picture",
    476            value
    477          );
    478        }
    479      } catch (ex) {
    480        console.error("Failed to clear XULStore PiP values: ", ex);
    481      }
    482    }
    483 
    484    function migrateXULAttributeToStyle(url, id, attr) {
    485      try {
    486        let value = Services.xulStore.getValue(url, id, attr);
    487        if (value) {
    488          Services.xulStore.setValue(url, id, "style", `${attr}: ${value}px;`);
    489        }
    490      } catch (ex) {
    491        console.error(`Error migrating ${id}'s ${attr} value: `, ex);
    492      }
    493    }
    494 
    495    // Bug 1792748 used version 129 with a buggy variant of the sidebar width
    496    // migration. This version is already in use in the nightly channel, so it
    497    // shouldn't be used.
    498 
    499    // Bug 1793366: migrate sidebar persisted attribute from width to style.
    500    if (existingDataVersion < 130) {
    501      migrateXULAttributeToStyle(BROWSER_DOCURL, "sidebar-box", "width");
    502    }
    503 
    504    // Migration 131 was moved to 133 to allow for an uplift.
    505 
    506    if (existingDataVersion < 132) {
    507      // These attributes are no longer persisted, thus remove them from xulstore.
    508      for (let url of [
    509        "chrome://browser/content/places/bookmarkProperties.xhtml",
    510        "chrome://browser/content/places/bookmarkProperties2.xhtml",
    511      ]) {
    512        for (let attr of ["width", "screenX", "screenY"]) {
    513          xulStore.removeValue(url, "bookmarkproperties", attr);
    514        }
    515      }
    516    }
    517 
    518    if (existingDataVersion < 133) {
    519      xulStore.removeValue(BROWSER_DOCURL, "urlbar-container", "width");
    520    }
    521 
    522    // Migration 134 was removed because it was no longer necessary.
    523 
    524    if (existingDataVersion < 135 && AppConstants.platform == "linux") {
    525      // Avoid changing titlebar setting for users that used to had it off.
    526      try {
    527        if (!Services.prefs.prefHasUserValue("browser.tabs.inTitlebar")) {
    528          let de = Services.appinfo.desktopEnvironment;
    529          let oldDefault = de.includes("gnome") || de.includes("pantheon");
    530          if (!oldDefault) {
    531            Services.prefs.setIntPref("browser.tabs.inTitlebar", 0);
    532          }
    533        }
    534      } catch (e) {
    535        console.error("Error migrating tabsInTitlebar setting", e);
    536      }
    537    }
    538 
    539    if (existingDataVersion < 136) {
    540      migrateXULAttributeToStyle(
    541        "chrome://browser/content/places/places.xhtml",
    542        "placesList",
    543        "width"
    544      );
    545    }
    546 
    547    if (existingDataVersion < 137) {
    548      // The default value for enabling smooth scrolls is now false if the
    549      // user prefers reduced motion. If the value was previously set, do
    550      // not reset it, but if it was not explicitly set preserve the old
    551      // default value.
    552      if (
    553        !Services.prefs.prefHasUserValue("general.smoothScroll") &&
    554        Services.appinfo.prefersReducedMotion
    555      ) {
    556        Services.prefs.setBoolPref("general.smoothScroll", true);
    557      }
    558    }
    559 
    560    if (existingDataVersion < 138) {
    561      // Bug 1757297: Change scheme of all existing 'https-only-load-insecure'
    562      // permissions with https scheme to http scheme.
    563      try {
    564        Services.perms
    565          .getAllByTypes(["https-only-load-insecure"])
    566          .filter(permission => permission.principal.schemeIs("https"))
    567          .forEach(permission => {
    568            const capability = permission.capability;
    569            const uri = permission.principal.URI.mutate()
    570              .setScheme("http")
    571              .finalize();
    572            const principal =
    573              Services.scriptSecurityManager.createContentPrincipal(uri, {});
    574            Services.perms.removePermission(permission);
    575            Services.perms.addFromPrincipal(
    576              principal,
    577              "https-only-load-insecure",
    578              capability
    579            );
    580          });
    581      } catch (e) {
    582        console.error("Error migrating https-only-load-insecure permission", e);
    583      }
    584    }
    585 
    586    if (existingDataVersion < 139) {
    587      // Reset the default permissions to ALLOW_ACTION to rollback issues for
    588      // affected users, see Bug 1579517
    589      // originInfo in the format [origin, type]
    590      [
    591        ["https://www.mozilla.org", "uitour"],
    592        ["https://support.mozilla.org", "uitour"],
    593        ["about:home", "uitour"],
    594        ["about:newtab", "uitour"],
    595        ["https://addons.mozilla.org", "install"],
    596        ["https://support.mozilla.org", "remote-troubleshooting"],
    597        ["about:welcome", "autoplay-media"],
    598      ].forEach(originInfo => {
    599        // Reset permission on the condition that it is set to
    600        // UNKNOWN_ACTION, we want to prevent resetting user
    601        // manipulated permissions
    602        if (
    603          Services.perms.UNKNOWN_ACTION ==
    604          Services.perms.testPermissionFromPrincipal(
    605            Services.scriptSecurityManager.createContentPrincipalFromOrigin(
    606              originInfo[0]
    607            ),
    608            originInfo[1]
    609          )
    610        ) {
    611          // Adding permissions which have default values does not create
    612          // new permissions, but rather remove the UNKNOWN_ACTION permission
    613          // overrides. User's not affected by Bug 1579517 will not be affected by this addition.
    614          Services.perms.addFromPrincipal(
    615            Services.scriptSecurityManager.createContentPrincipalFromOrigin(
    616              originInfo[0]
    617            ),
    618            originInfo[1],
    619            Services.perms.ALLOW_ACTION
    620          );
    621        }
    622      });
    623    }
    624 
    625    if (existingDataVersion < 140) {
    626      // Remove browser.fixup.alternate.enabled pref in Bug 1850902.
    627      Services.prefs.clearUserPref("browser.fixup.alternate.enabled");
    628    }
    629 
    630    if (existingDataVersion < 141) {
    631      for (const filename of ["signons.sqlite", "signons.sqlite.corrupt"]) {
    632        const filePath = PathUtils.join(PathUtils.profileDir, filename);
    633        IOUtils.remove(filePath, { ignoreAbsent: true }).catch(console.error);
    634      }
    635    }
    636 
    637    if (existingDataVersion < 142) {
    638      // Bug 1860392 - Remove incorrectly persisted theming values from sidebar style.
    639      try {
    640        let value = xulStore.getValue(BROWSER_DOCURL, "sidebar-box", "style");
    641        if (value) {
    642          // Remove custom properties.
    643          value = value
    644            .split(";")
    645            .filter(v => !v.trim().startsWith("--"))
    646            .join(";");
    647          xulStore.setValue(BROWSER_DOCURL, "sidebar-box", "style", value);
    648        }
    649      } catch (ex) {
    650        console.error(ex);
    651      }
    652    }
    653 
    654    if (existingDataVersion < 143) {
    655      // Version 143 has been superseded by version 145 below.
    656    }
    657 
    658    if (existingDataVersion < 144) {
    659      // TerminatorTelemetry was removed in bug 1879136. Before it was removed,
    660      // the ShutdownDuration.json file would be written to disk at shutdown
    661      // so that the next launch of the browser could read it in and send
    662      // shutdown performance measurements.
    663      //
    664      // Unfortunately, this mechanism and its measurements were fairly
    665      // unreliable, so they were removed.
    666      for (const filename of [
    667        "ShutdownDuration.json",
    668        "ShutdownDuration.json.tmp",
    669      ]) {
    670        const filePath = PathUtils.join(PathUtils.profileDir, filename);
    671        IOUtils.remove(filePath, { ignoreAbsent: true }).catch(console.error);
    672      }
    673    }
    674 
    675    if (existingDataVersion < 145) {
    676      if (AppConstants.platform == "win") {
    677        // In Firefox 122, we enabled the firefox and firefox-private protocols.
    678        // We switched over to using firefox-bridge and firefox-private-bridge,
    679        // but we want to clean up the use of the other protocols.
    680        lazy.FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
    681          lazy.FirefoxBridgeExtensionUtils.OLD_PUBLIC_PROTOCOL,
    682          lazy.FirefoxBridgeExtensionUtils.OLD_PRIVATE_PROTOCOL
    683        );
    684 
    685        // Clean up the old user prefs from FX 122
    686        Services.prefs.clearUserPref(
    687          "network.protocol-handler.external.firefox"
    688        );
    689        Services.prefs.clearUserPref(
    690          "network.protocol-handler.external.firefox-private"
    691        );
    692 
    693        // In Firefox 126, we switched over to using native messaging so the
    694        // protocols are no longer necessary even in firefox-bridge and
    695        // firefox-private-bridge form
    696        lazy.FirefoxBridgeExtensionUtils.maybeDeleteBridgeProtocolRegistryEntries(
    697          lazy.FirefoxBridgeExtensionUtils.PUBLIC_PROTOCOL,
    698          lazy.FirefoxBridgeExtensionUtils.PRIVATE_PROTOCOL
    699        );
    700        Services.prefs.clearUserPref(
    701          "network.protocol-handler.external.firefox-bridge"
    702        );
    703        Services.prefs.clearUserPref(
    704          "network.protocol-handler.external.firefox-private-bridge"
    705        );
    706        Services.prefs.clearUserPref("browser.shell.customProtocolsRegistered");
    707      }
    708    }
    709 
    710    let hasRun146Migration = false;
    711    if (existingDataVersion < 147) {
    712      // Directly copy old os auth pref values prior to 147 to the new boolean
    713      // pref for OS auth (UI migration 156). Previously, this migration version
    714      // migrated the old OS auth pref values to an encrypted string pref.
    715      const prevOsAuthForCc = !Services.prefs.getBoolPref(
    716        "signon.management.page.os-auth.enabled",
    717        false
    718      );
    719      const newOSAuthNameForCc =
    720        "extensions.formautofill.creditCards.os-auth.locked.enabled";
    721      Services.prefs.setBoolPref(newOSAuthNameForCc, prevOsAuthForCc);
    722      Services.prefs.lockPref(newOSAuthNameForCc);
    723 
    724      const prevOsAuthForPw = !Services.prefs.getBoolPref(
    725        "extensions.formautofill.reauth.enabled",
    726        false
    727      );
    728      const newOSAuthNameForPw =
    729        "signon.management.page.os-auth.locked.enabled";
    730      Services.prefs.setBoolPref(newOSAuthNameForPw, prevOsAuthForPw);
    731      Services.prefs.lockPref(newOSAuthNameForPw);
    732 
    733      hasRun146Migration = true;
    734      Services.prefs.clearUserPref("extensions.formautofill.reauth.enabled");
    735      Services.prefs.clearUserPref("signon.management.page.os-auth.enabled");
    736    }
    737 
    738    if (existingDataVersion < 148) {
    739      // The Firefox Translations addon is now a built-in Firefox feature.
    740      let addonPromise;
    741      try {
    742        addonPromise = lazy.AddonManager.getAddonByID(
    743          "firefox-translations-addon@mozilla.org"
    744        );
    745      } catch (error) {
    746        // This always throws in xpcshell as the AddonManager is not initialized.
    747        if (!Services.env.exists("XPCSHELL_TEST_PROFILE_DIR")) {
    748          console.error(
    749            "Could not access the AddonManager to upgrade the profile."
    750          );
    751        }
    752      }
    753      addonPromise?.then(addon => addon?.uninstall()).catch(console.error);
    754    }
    755 
    756    if (existingDataVersion < 149) {
    757      // remove permissions used by deleted nsContentManager
    758      [
    759        "other",
    760        "script",
    761        "image",
    762        "stylesheet",
    763        "object",
    764        "document",
    765        "subdocument",
    766        "refresh",
    767        "xbl",
    768        "ping",
    769        "xmlhttprequest",
    770        "objectsubrequest",
    771        "dtd",
    772        "font",
    773        "websocket",
    774        "csp_report",
    775        "xslt",
    776        "beacon",
    777        "fetch",
    778        "manifest",
    779        "speculative",
    780      ].forEach(type => {
    781        Services.perms.removeByType(type);
    782      });
    783    }
    784 
    785    if (existingDataVersion < 150) {
    786      Services.prefs.clearUserPref("toolkit.telemetry.pioneerId");
    787    }
    788 
    789    if (existingDataVersion < 151) {
    790      // Existing Firefox users should have the usage reporting upload
    791      // preference "inherit" the general data reporting preference.
    792      lazy.UsageReporting.adoptDataReportingPreference();
    793    }
    794 
    795    if (
    796      existingDataVersion < 152 &&
    797      Services.prefs.getBoolPref("sidebar.revamp") &&
    798      !Services.prefs.getBoolPref("browser.ml.chat.enabled")
    799    ) {
    800      let tools = Services.prefs.getCharPref("sidebar.main.tools");
    801      if (tools?.includes("aichat")) {
    802        let updatedTools = tools
    803          .split(",")
    804          .filter(t => t != "aichat")
    805          .join(",");
    806        Services.prefs.setCharPref("sidebar.main.tools", updatedTools);
    807      }
    808    }
    809 
    810    if (
    811      existingDataVersion < 153 &&
    812      Services.prefs.getBoolPref("sidebar.revamp") &&
    813      !Services.prefs.prefHasUserValue("sidebar.main.tools")
    814    ) {
    815      // This pref will now be a user set branch but we want to preserve the previous
    816      // default value for existing sidebar.revamp users who hadn't changed it.
    817      Services.prefs.setCharPref(
    818        "sidebar.main.tools",
    819        "aichat,syncedtabs,history"
    820      );
    821    }
    822 
    823    if (existingDataVersion < 154) {
    824      // Remove mibbit handler.
    825      // The handler service will do this. We need to wait with migrating
    826      // until the handler service has started up, so just set a pref here.
    827      const kPref = "browser.handlers.migrations";
    828      // We might have set up another migration further up. Create an array,
    829      // and drop empty strings resulting from the `split`:
    830      let migrations = Services.prefs
    831        .getCharPref(kPref, "")
    832        .split(",")
    833        .filter(x => !!x);
    834      migrations.push("mibbit");
    835      Services.prefs.setCharPref(kPref, migrations.join(","));
    836    }
    837 
    838    if (existingDataVersion < 155) {
    839      // Remove outdated sidebar info from XULStore.
    840      for (const attr of [
    841        "checked",
    842        "positionend",
    843        "sidebarcommand",
    844        "style",
    845      ]) {
    846        Services.xulStore.removeValue(BROWSER_DOCURL, "sidebar-box", attr);
    847      }
    848    }
    849 
    850    if (existingDataVersion < 156) {
    851      const customBlockListEnabled = Services.prefs.getBoolPref(
    852        "browser.contentblocking.customBlockList.preferences.ui.enabled",
    853        false
    854      );
    855      if (customBlockListEnabled) {
    856        Services.prefs.clearUserPref(
    857          "browser.contentblocking.customBlockList.preferences.ui.enabled"
    858        );
    859        Services.prefs.clearUserPref("urlclassifier.trackingTable");
    860      }
    861    }
    862 
    863    if (existingDataVersion < 157) {
    864      // We've changed the 147 migration to copy the old OS auth pref values of
    865      // that version to the new locked boolean prefs instead, so no need to
    866      // perform a migration if it's already been done.
    867      if (!hasRun146Migration) {
    868        // We're moving away from string encrypted prefs for OS Authentication and
    869        // using locked boolean prefs instead.
    870        // To determine the state of the old OS Auth value, manually read these prefs.
    871        // This treats any non-empty-string value as "turned off", irrespective of
    872        // whether it correctly decrypts to the correct value, because we cannot do
    873        // the decryption if the primary password has not yet been provided.
    874        const prevOsAuthForCc = !Services.prefs.getStringPref(
    875          "extensions.formautofill.creditCards.reauth.optout",
    876          ""
    877        );
    878        const prevOsAuthForPw = !Services.prefs.getStringPref(
    879          "signon.management.page.os-auth.optout",
    880          ""
    881        );
    882 
    883        lazy.LoginHelper.setOSAuthEnabled(prevOsAuthForPw);
    884        lazy.FormAutofillUtils.setOSAuthEnabled(prevOsAuthForCc);
    885 
    886        Services.prefs.clearUserPref(
    887          "extensions.formautofill.creditCards.reauth.optout"
    888        );
    889        Services.prefs.clearUserPref("signon.management.page.os-auth.optout");
    890      }
    891    }
    892 
    893    // Nightly users who have run the migration for 157 will have had OS auth
    894    // set to true for everyone who has migrated and there's no way to retrieve
    895    // the old OS auth pref value because it was cleared in the previous
    896    // migration. So we force the pref to false. See bug 1974217.
    897    if (AppConstants.NIGHTLY_BUILD && existingDataVersion === 158) {
    898      lazy.LoginHelper.setOSAuthEnabled(false);
    899      lazy.FormAutofillUtils.setOSAuthEnabled(false);
    900    }
    901 
    902    if (existingDataVersion < 159) {
    903      // Bug 1979014 / bug 1980398 - autohide attribute becomes a real boolean attribute.
    904      let menubarWasEnabled =
    905        Services.xulStore.getValue(
    906          BROWSER_DOCURL,
    907          "toolbar-menubar",
    908          "autohide"
    909        ) == "false";
    910      if (menubarWasEnabled) {
    911        Services.xulStore.setValue(
    912          BROWSER_DOCURL,
    913          "toolbar-menubar",
    914          "autohide",
    915          "-moz-missing\n"
    916        );
    917      }
    918    }
    919 
    920    if (existingDataVersion < 160) {
    921      // Force all logins to be re-encrypted to make use of more modern crypto.
    922      // This pref is checked in the initialization of the LoginManagerStorage.
    923      Services.prefs.setBoolPref("signon.reencryptionNeeded", true);
    924    }
    925 
    926    // Updating from 161 to 163 to trigger re-migrations of the Rusts store.
    927    if (existingDataVersion < 163) {
    928      // Force all logins to be re-migrated to the rust store.
    929      Services.prefs.setBoolPref("signon.rustMirror.migrationNeeded", true);
    930    }
    931 
    932    // Update the migration version.
    933    Services.prefs.setIntPref("browser.migration.version", newVersion);
    934  },
    935 
    936  upgradeBB(isNewProfile) {
    937    // Version 1: 13.0a3. Reset layout.css.prefers-color-scheme.content-override
    938    //            for tor-browser#41739.
    939    // Version 2: 14.0a5: Reset the privacy tracking headers preferences since
    940    //            the UI is hidden. tor-browser#42777.
    941    //            Also, do not set
    942    //            dom.security.https_only_mode_send_http_background_request in
    943    //            the security level anymore (tor-browser#42149).
    944    //            Also, reset security.xfocsp.errorReporting.automatic since we
    945    //            hid its neterror checkbox. tor-browser#42653.
    946    // Version 3: 14.0a7: Reset general.smoothScroll. tor-browser#42070.
    947    // Version 4: 15.0a2: Drop ML components. tor-browser#44045.
    948    // Version 5: 15.0a3: Disable LaterRun using prefs. tor-browser#42630.
    949    // Version 6: 15.0a4: Reset browser colors. tor-browser#43850.
    950    const MIGRATION_VERSION = 6;
    951    const MIGRATION_PREF = "basebrowser.migration.version";
    952 
    953    if (isNewProfile) {
    954      // Do not migrate fresh profiles
    955      Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
    956      return;
    957    } else if (isNewProfile === undefined) {
    958      // If this happens, check if upstream updated their function and do not
    959      // set this member anymore!
    960      console.error("upgradeBB: isNewProfile is undefined.");
    961    }
    962 
    963    const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
    964    if (currentVersion < 1) {
    965      Services.prefs.clearUserPref(
    966        "layout.css.prefers-color-scheme.content-override"
    967      );
    968    }
    969    if (currentVersion < 2) {
    970      for (const prefName of [
    971        "privacy.globalprivacycontrol.enabled",
    972        "privacy.donottrackheader.enabled",
    973        // Telemetry preference for if the user changed the value.
    974        "privacy.globalprivacycontrol.was_ever_enabled",
    975        // The next two preferences have no corresponding UI, but are related.
    976        "privacy.globalprivacycontrol.functionality.enabled",
    977        "privacy.globalprivacycontrol.pbmode.enabled",
    978        "dom.security.https_only_mode_send_http_background_request",
    979        "security.xfocsp.errorReporting.automatic",
    980      ]) {
    981        Services.prefs.clearUserPref(prefName);
    982      }
    983    }
    984    if (currentVersion < 3) {
    985      Services.prefs.clearUserPref("general.smoothScroll");
    986    }
    987    if (currentVersion < 4) {
    988      for (const prefName of [
    989        "browser.translations.enable",
    990        "browser.ml.enable",
    991        "browser.ml.chat.enabled",
    992        "browser.ml.linkPreview.enabled",
    993        "browser.tabs.groups.smart.enabled",
    994        "browser.tabs.groups.smart.userEnabled",
    995        "extensions.ml.enabled",
    996        "pdfjs.enableAltText",
    997        "pdfjs.enableAltTextForEnglish",
    998        "pdfjs.enableGuessAltText",
    999        "pdfjs.enableAltTextModelDownload",
   1000        "browser.urlbar.quicksuggest.mlEnabled",
   1001        "places.semanticHistory.featureGate",
   1002      ]) {
   1003        // Preferences are locked. Do not want user values to linger in the
   1004        // user's profile and become active if these preferences become unlocked
   1005        // in the future.
   1006        Services.prefs.clearUserPref(prefName);
   1007      }
   1008    }
   1009    if (currentVersion < 5) {
   1010      for (const prefName of [
   1011        "browser.laterrun.bookkeeping.sessionCount",
   1012        "browser.laterrun.bookkeeping.profileCreationTime",
   1013        "browser.laterrun.bookkeeping.updateAppliedTime",
   1014      ]) {
   1015        Services.prefs.clearUserPref(prefName);
   1016      }
   1017    }
   1018    if (currentVersion < 6) {
   1019      // Clear the related preference that is no longer read by upstream's code.
   1020      Services.prefs.clearUserPref("browser.display.use_system_colors");
   1021      if (Services.prefs.getBoolPref("privacy.resistFingerprinting", true)) {
   1022        for (const prefName of [
   1023          // User has not switched off resist fingerprinting. We want to reset
   1024          // any "0" (automatic, use system colours) and "2" (always use browser
   1025          // colours) values.
   1026          // The "0" value cannot be set by the user under RFP in
   1027          // about:preferences. The "2" value can be set, but has a different
   1028          // name and a warning about website detectability. tor-browser#43850.
   1029          "browser.display.document_color_use",
   1030          // Under RFP, the following colours are ignored. So we clear them.
   1031          // NOTE: Only a subset of can be set via the colors.xhtml dialog in
   1032          // about:preferences.
   1033          "browser.anchor_color",
   1034          "browser.anchor_color.dark",
   1035          "browser.visited_color",
   1036          "browser.visited_color.dark",
   1037          "browser.display.foreground_color",
   1038          "browser.display.foreground_color.dark",
   1039          "browser.display.background_color",
   1040          "browser.display.background_color.dark",
   1041          "browser.active_color",
   1042          "browser.active_color.dark",
   1043        ]) {
   1044          Services.prefs.clearUserPref(prefName);
   1045        }
   1046      }
   1047    }
   1048    Services.prefs.setIntPref(MIGRATION_PREF, MIGRATION_VERSION);
   1049  },
   1050 
   1051  async upgradeTB(isNewProfile) {
   1052    // Version 1: Tor Browser 12.0. We use it to remove langpacks, after the
   1053    //            migration to packaged locales.
   1054    // Version 2: Tor Browser 13.0/13.0a1: tor-browser#41845. Also, removed some
   1055    //            torbutton preferences that are not used anymore.
   1056    // Version 3: Tor Browser 13.0.7/13.5a3: Remove blockchair
   1057    //            (tor-browser#42283).
   1058    // Version 4: Tor Browser 14.0a4 (2024-09-02): Remove Twitter, Yahoo and
   1059    //            YouTube search engines (tor-browser#41835).
   1060    // Version 5: Tor Browser 14.0a5: Clear user preference for CFR settings
   1061    //            since we hid the UI (tor-browser#43118).
   1062    // Version 6: Tor Browser 14.5a3: Clear preference for TorSettings that is
   1063    //            no longer used (tor-browser#41921).
   1064    //            Drop unused TorConnect setting (tor-browser#43462).
   1065    // Version 7: Tor Browser 14.5a6: Clear home page update url preference
   1066    //            (tor-browser#43567).
   1067    // Version 8: Tor Browser 15.0a2: Remove legacy search addons
   1068    //            (tor-browser#43111).
   1069    // Version 9: Tor Browser 15.0a3: Remove YEC 2024 preference.
   1070    //            (tor-browser#44180)
   1071    const TBB_MIGRATION_VERSION = 9;
   1072    const MIGRATION_PREF = "torbrowser.migration.version";
   1073 
   1074    // If we decide to force updating users to pass through any version
   1075    // following 12.0, we can remove this check, and check only whether
   1076    // MIGRATION_PREF has a user value, like Mozilla does.
   1077    if (isNewProfile) {
   1078      // Do not migrate fresh profiles
   1079      Services.prefs.setIntPref(MIGRATION_PREF, TBB_MIGRATION_VERSION);
   1080      return;
   1081    } else if (isNewProfile === undefined) {
   1082      // If this happens, check if upstream updated their function and do not
   1083      // set this member anymore!
   1084      console.error("upgradeTB: isNewProfile is undefined.");
   1085    }
   1086 
   1087    const currentVersion = Services.prefs.getIntPref(MIGRATION_PREF, 0);
   1088    const removeLangpacks = async () => {
   1089      for (const addon of await AddonManager.getAddonsByTypes(["locale"])) {
   1090        await addon.uninstall();
   1091      }
   1092    };
   1093    if (currentVersion < 1) {
   1094      try {
   1095        await removeLangpacks();
   1096      } catch (err) {
   1097        console.error("Could not remove langpacks", err);
   1098      }
   1099    }
   1100    if (currentVersion < 2) {
   1101      const prefToClear = [
   1102        // tor-browser#41845: We were forcing these value by check the value of
   1103        // automatic PBM. We decided not to change
   1104        "browser.cache.disk.enable",
   1105        "places.history.enabled",
   1106        "security.nocertdb",
   1107        "permissions.memory_only",
   1108        // Old torbutton preferences not used anymore.
   1109        "extensions.torbutton.loglevel",
   1110        "extensions.torbutton.logmethod",
   1111        "extensions.torbutton.pref_fixup_version",
   1112        "extensions.torbutton.resize_new_windows",
   1113        "extensions.torbutton.startup",
   1114        "extensions.torlauncher.prompt_for_locale",
   1115        "extensions.torlauncher.loglevel",
   1116        "extensions.torlauncher.logmethod",
   1117        "extensions.torlauncher.torrc_fixup_version",
   1118      ];
   1119      for (const pref of prefToClear) {
   1120        if (Services.prefs.prefHasUserValue(pref)) {
   1121          Services.prefs.clearUserPref(pref);
   1122        }
   1123      }
   1124    }
   1125    const dropAddons = async list => {
   1126      for (const id of list) {
   1127        try {
   1128          const engine = await lazy.AddonManager.getAddonByID(id);
   1129          await engine?.uninstall();
   1130        } catch {}
   1131      }
   1132    };
   1133    if (currentVersion < 3) {
   1134      await dropAddons([
   1135        "blockchair@search.mozilla.org",
   1136        "blockchair-onion@search.mozilla.org",
   1137      ]);
   1138    }
   1139    if (currentVersion < 4) {
   1140      await dropAddons([
   1141        "twitter@search.mozilla.org",
   1142        "yahoo@search.mozilla.org",
   1143        "youtube@search.mozilla.org",
   1144      ]);
   1145    }
   1146    if (currentVersion < 5) {
   1147      for (const pref of [
   1148        "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
   1149        "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
   1150      ]) {
   1151        Services.prefs.clearUserPref(pref);
   1152      }
   1153    }
   1154    if (currentVersion < 6) {
   1155      Services.prefs.clearUserPref("torbrowser.settings.enabled");
   1156      Services.prefs.clearUserPref("torbrowser.bootstrap.allow_internet_test");
   1157    }
   1158    if (currentVersion < 7) {
   1159      Services.prefs.clearUserPref("torbrowser.post_update.url");
   1160    }
   1161    if (currentVersion < 8) {
   1162      await dropAddons([
   1163        "ddg@search.mozilla.org",
   1164        "ddg-onion@search.mozilla.org",
   1165        "google@search.mozilla.org",
   1166        "startpage@search.mozilla.org",
   1167        "startpage-onion@search.mozilla.org",
   1168        "wikipedia@search.mozilla.org",
   1169      ]);
   1170    }
   1171    if (currentVersion < 9) {
   1172      Services.prefs.clearUserPref("torbrowser.homepage.yec2024.message");
   1173    }
   1174 
   1175    Services.prefs.setIntPref(MIGRATION_PREF, TBB_MIGRATION_VERSION);
   1176  },
   1177 };