Bug 1356331 Remove hotfix code from addons manager and related tests draft
authorAndrew Swan <aswan@mozilla.com>
Wed, 13 Dec 2017 12:33:52 -0800 (2017-12-13)
changeset 749135 5ec75351902ab56c19e6903e5a0456dda953c6bb
parent 749134 3a8694c8c2e5f19d0d4a24062454c147b8b9789a
push id97321
push useraswan@mozilla.com
push dateTue, 30 Jan 2018 23:14:46 +0000 (2018-01-30)
bugs1356331
milestone60.0a1
Bug 1356331 Remove hotfix code from addons manager and related tests MozReview-Commit-ID: EjCOOgmXvVH
browser/app/profile/firefox.js
mobile/android/app/mobile.js
services/sync/modules/engines/addons.js
services/sync/tests/unit/test_addons_store.js
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/internal/AddonRepository.jsm
toolkit/mozapps/extensions/internal/XPIInstall.jsm
toolkit/mozapps/extensions/internal/XPIProvider.jsm
toolkit/mozapps/extensions/test/addons/test_hotfix_1/install.rdf
toolkit/mozapps/extensions/test/addons/test_hotfix_2/install.rdf
toolkit/mozapps/extensions/test/browser/browser_details.js
toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_1.rdf
toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_2.rdf
toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_3.rdf
toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js
toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js
toolkit/mozapps/extensions/test/xpcshell/test_hotfix_cert.js
toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js
toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -47,21 +47,16 @@ pref("extensions.getAddons.get.url", "ht
 pref("extensions.getAddons.getWithPerformance.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
 pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/search?q=%TERMS%&platform=%OS%&appver=%VERSION%");
 pref("extensions.webservice.discoverURL", "https://discovery.addons.mozilla.org/%LOCALE%/firefox/discovery/pane/%VERSION%/%OS%/%COMPATIBILITY_MODE%");
 pref("extensions.getAddons.link.url", "https://addons.mozilla.org/%LOCALE%/firefox/");
 pref("extensions.getAddons.themes.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes/?src=firefox");
 
 pref("extensions.update.autoUpdateDefault", true);
 
-pref("extensions.hotfix.id", "firefox-hotfix@mozilla.org");
-pref("extensions.hotfix.cert.checkAttributes", true);
-pref("extensions.hotfix.certs.1.sha1Fingerprint", "91:53:98:0C:C1:86:DF:47:8F:35:22:9E:11:C9:A7:31:04:49:A1:AA");
-pref("extensions.hotfix.certs.2.sha1Fingerprint", "39:E7:2B:7A:5B:CF:37:78:F9:5D:4A:E0:53:2D:2F:3D:68:53:C5:60");
-
 // Check AUS for system add-on updates.
 pref("extensions.systemAddon.update.url", "https://aus5.mozilla.org/update/3/SystemAddons/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
 
 // Disable add-ons that are not installed by the user in all scopes by default.
 // See the SCOPE constants in AddonManager.jsm for values to use here.
 pref("extensions.autoDisableScopes", 15);
 // Scopes to scan for changes at startup.
 pref("extensions.startupScanScopes", 0);
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -200,20 +200,16 @@ pref("extensions.hideInstallButton", tru
 pref("extensions.showMismatchUI", false);
 pref("extensions.hideUpdateButton", false);
 pref("extensions.strictCompatibility", false);
 pref("extensions.minCompatibleAppVersion", "11.0");
 
 pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
 pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
 
-pref("extensions.hotfix.id", "firefox-android-hotfix@mozilla.org");
-pref("extensions.hotfix.cert.checkAttributes", true);
-pref("extensions.hotfix.certs.1.sha1Fingerprint", "91:53:98:0C:C1:86:DF:47:8F:35:22:9E:11:C9:A7:31:04:49:A1:AA");
-
 /* preferences for the Get Add-ons pane */
 pref("extensions.getAddons.cache.enabled", true);
 pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/android/search?q=%TERMS%&platform=%OS%&appver=%VERSION%");
 pref("extensions.getAddons.browseAddons", "https://addons.mozilla.org/%LOCALE%/android/");
 pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/android/api/%API_VERSION%/search/guid:%IDS%?src=mobile&appOS=%OS%&appVersion=%VERSION%");
 pref("extensions.getAddons.getWithPerformance.url", "https://services.addons.mozilla.org/%LOCALE%/android/api/%API_VERSION%/search/guid:%IDS%?src=mobile&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
 
 /* preference for the locale picker */
--- a/services/sync/modules/engines/addons.js
+++ b/services/sync/modules/engines/addons.js
@@ -576,26 +576,16 @@ AddonsStore.prototype = {
     // manually placed in the profile directory, foreignInstall will be set.
     // Arguably, that add-on should be syncable.
     // TODO Address the edge case and come up with more robust heuristics.
     if (addon.foreignInstall) {
       this._log.debug(addon.id + " not syncable: is foreign install.");
       return false;
     }
 
-    // Ignore hotfix extensions (bug 741670). The pref may not be defined.
-    // XXX - note that addon.isSyncable will be false for hotfix addons, so
-    // this check isn't strictly necessary - except for Sync tests which aren't
-    // setup to create a "real" hotfix addon. This can be removed once those
-    // tests are fixed (but keeping it doesn't hurt either)
-    if (this._extensionsPrefs.get("hotfix.id", null) == addon.id) {
-      this._log.debug(addon.id + " not syncable: is a hotfix.");
-      return false;
-    }
-
     // If the AddonRepository's cache isn't enabled (which it typically isn't
     // in tests), getCachedAddonByID always returns null - so skip the check
     // in that case. We also provide a way to specifically opt-out of the check
     // even if the cache is enabled, which is used by the validators.
     if (ignoreRepoCheck || !AddonRepository.cacheEnabled) {
       return true;
     }
 
--- a/services/sync/tests/unit/test_addons_store.js
+++ b/services/sync/tests/unit/test_addons_store.js
@@ -316,54 +316,16 @@ add_test(function test_addon_syncability
   Svc.Prefs.set("addons.trustedSourceHostnames", "addons.mozilla.org");
   Assert.ok(store.isSourceURITrusted(Services.io.newURI("https://addons.mozilla.org/foo")));
 
   Svc.Prefs.reset("addons.trustedSourceHostnames");
 
   run_next_test();
 });
 
-add_test(function test_ignore_hotfixes() {
-  _("Ensure that hotfix extensions are ignored.");
-
-  // A hotfix extension is one that has the id the same as the
-  // extensions.hotfix.id pref.
-  let extensionPrefs = new Preferences("extensions.");
-
-  let addon = installAddon("test_bootstrap1_1");
-  Assert.ok(store.isAddonSyncable(addon));
-
-  let dummy = {};
-  const KEYS = ["id", "syncGUID", "type", "scope", "foreignInstall", "isSyncable"];
-  for (let k of KEYS) {
-    dummy[k] = addon[k];
-  }
-
-  // Basic sanity check.
-  Assert.ok(store.isAddonSyncable(dummy));
-
-  extensionPrefs.set("hotfix.id", dummy.id);
-  Assert.ok(!store.isAddonSyncable(dummy));
-
-  // Verify that int values don't throw off checking.
-  let prefSvc = Services.prefs.getBranch("extensions.");
-  // Need to delete pref before changing type.
-  prefSvc.deleteBranch("hotfix.id");
-  prefSvc.setIntPref("hotfix.id", 0xdeadbeef);
-
-  Assert.ok(store.isAddonSyncable(dummy));
-
-  uninstallAddon(addon);
-
-  extensionPrefs.reset("hotfix.id");
-
-  run_next_test();
-});
-
-
 add_task(async function test_get_all_ids() {
   _("Ensures that getAllIDs() returns an appropriate set.");
 
   _("Installing two addons.");
   // XXX - this test seems broken - at this point, before we've installed the
   // addons below, store.getAllIDs() returns all addons installed by previous
   // tests, even though those tests uninstalled the addon.
   // So if any tests above ever add a new addon ID, they are going to need to
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -29,24 +29,18 @@ const MOZ_COMPATIBILITY_NIGHTLY = !["aur
 const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion";
 const PREF_DEFAULT_PROVIDERS_ENABLED  = "extensions.defaultProviders.enabled";
 const PREF_EM_UPDATE_ENABLED          = "extensions.update.enabled";
 const PREF_EM_LAST_APP_VERSION        = "extensions.lastAppVersion";
 const PREF_EM_LAST_PLATFORM_VERSION   = "extensions.lastPlatformVersion";
 const PREF_EM_AUTOUPDATE_DEFAULT      = "extensions.update.autoUpdateDefault";
 const PREF_EM_STRICT_COMPATIBILITY    = "extensions.strictCompatibility";
 const PREF_EM_CHECK_UPDATE_SECURITY   = "extensions.checkUpdateSecurity";
-const PREF_EM_UPDATE_BACKGROUND_URL   = "extensions.update.background.url";
 const PREF_APP_UPDATE_ENABLED         = "app.update.enabled";
 const PREF_APP_UPDATE_AUTO            = "app.update.auto";
-const PREF_EM_HOTFIX_ID               = "extensions.hotfix.id";
-const PREF_EM_HOTFIX_LASTVERSION      = "extensions.hotfix.lastVersion";
-const PREF_EM_HOTFIX_URL              = "extensions.hotfix.url";
-const PREF_EM_CERT_CHECKATTRIBUTES    = "extensions.hotfix.cert.checkAttributes";
-const PREF_EM_HOTFIX_CERTS            = "extensions.hotfix.certs.";
 const UNKNOWN_XPCOM_ABI               = "unknownABI";
 
 const PREF_MIN_WEBEXT_PLATFORM_VERSION = "extensions.webExtensionsMinPlatformVersion";
 const PREF_WEBAPI_TESTING             = "extensions.webapi.testing";
 const PREF_WEBEXT_PERM_PROMPTS        = "extensions.webextPermissionPrompts";
 
 const UPDATE_REQUEST_VERSION          = 2;
 const CATEGORY_UPDATE_PARAMS          = "extension-update-params";
@@ -607,17 +601,16 @@ function AddonType(aID, aLocaleURI, aLoc
 var gStarted = false;
 var gStartupComplete = false;
 var gCheckCompatibility = true;
 var gStrictCompatibility = true;
 var gCheckUpdateSecurityDefault = true;
 var gCheckUpdateSecurity = gCheckUpdateSecurityDefault;
 var gUpdateEnabled = true;
 var gAutoUpdateDefault = true;
-var gHotfixID = "";
 var gWebExtensionsMinPlatformVersion = "";
 var gShutdownBarrier = null;
 var gRepoShutdownState = "";
 var gShutdownInProgress = false;
 var gPluginPageListener = null;
 var gBrowserUpdated = null;
 
 /**
@@ -838,19 +831,16 @@ var AddonManagerInternal = {
 
       gUpdateEnabled = Services.prefs.getBoolPref(PREF_EM_UPDATE_ENABLED, gUpdateEnabled);
       Services.prefs.addObserver(PREF_EM_UPDATE_ENABLED, this);
 
       gAutoUpdateDefault = Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT,
                                                       gAutoUpdateDefault);
       Services.prefs.addObserver(PREF_EM_AUTOUPDATE_DEFAULT, this);
 
-      gHotfixID = Services.prefs.getCharPref(PREF_EM_HOTFIX_ID, gHotfixID);
-      Services.prefs.addObserver(PREF_EM_HOTFIX_ID, this);
-
       gWebExtensionsMinPlatformVersion =
         Services.prefs.getCharPref(PREF_MIN_WEBEXT_PLATFORM_VERSION,
                                    gWebExtensionsMinPlatformVersion);
       Services.prefs.addObserver(PREF_MIN_WEBEXT_PLATFORM_VERSION, this);
 
       let defaultProvidersEnabled = Services.prefs.getBoolPref(PREF_DEFAULT_PROVIDERS_ENABLED, true);
       AddonManagerPrivate.recordSimpleMeasure("default_providers", defaultProvidersEnabled);
 
@@ -1114,17 +1104,16 @@ var AddonManagerInternal = {
     gRepoShutdownState = "pending";
     gShutdownInProgress = true;
     // Clean up listeners
     Services.prefs.removeObserver(PREF_EM_CHECK_COMPATIBILITY, this);
     Services.prefs.removeObserver(PREF_EM_STRICT_COMPATIBILITY, this);
     Services.prefs.removeObserver(PREF_EM_CHECK_UPDATE_SECURITY, this);
     Services.prefs.removeObserver(PREF_EM_UPDATE_ENABLED, this);
     Services.prefs.removeObserver(PREF_EM_AUTOUPDATE_DEFAULT, this);
-    Services.prefs.removeObserver(PREF_EM_HOTFIX_ID, this);
     gPluginPageListener.destroy();
     gPluginPageListener = null;
 
     let savedError = null;
     // Only shut down providers if they've been started.
     if (gStarted) {
       try {
         await gShutdownBarrier.wait();
@@ -1228,20 +1217,16 @@ var AddonManagerInternal = {
         break;
       }
       case PREF_EM_AUTOUPDATE_DEFAULT: {
         gAutoUpdateDefault = Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT, true);
 
         this.callManagerListeners("onUpdateModeChanged");
         break;
       }
-      case PREF_EM_HOTFIX_ID: {
-        gHotfixID = Services.prefs.getCharPref(PREF_EM_HOTFIX_ID, "");
-        break;
-      }
       case PREF_MIN_WEBEXT_PLATFORM_VERSION: {
         gWebExtensionsMinPlatformVersion = Services.prefs.getCharPref(PREF_MIN_WEBEXT_PLATFORM_VERSION);
         break;
       }
     }
   },
 
   /**
@@ -1352,21 +1337,18 @@ var AddonManagerInternal = {
    *                       (the resulting addon installations may still be in progress).
    */
   backgroundUpdateCheck() {
     if (!gStarted)
       throw Components.Exception("AddonManager is not initialized",
                                  Cr.NS_ERROR_NOT_INITIALIZED);
 
     let buPromise = (async () => {
-      let hotfixID = this.hotfixID;
-
       let appUpdateEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
                              Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
-      let checkHotfix = hotfixID && appUpdateEnabled;
 
       logger.debug("Background update check beginning");
 
       Services.obs.notifyObservers(null, "addons-background-update-start");
 
       if (this.updateEnabled) {
         let scope = {};
         ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
@@ -1377,20 +1359,16 @@ var AddonManagerInternal = {
         // Repopulate repository cache first, to ensure compatibility overrides
         // are up to date before checking for addon updates.
         await AddonRepository.backgroundUpdateCheck();
 
         // Keep track of all the async add-on updates happening in parallel
         let updates = [];
 
         for (let addon of allAddons) {
-          if (addon.id == hotfixID) {
-            continue;
-          }
-
           // Check all add-ons for updates so that any compatibility updates will
           // be applied
           updates.push(new Promise((resolve, reject) => {
             addon.findUpdates({
               onUpdateAvailable(aAddon, aInstall) {
                 // Start installing updates when the add-on can be updated and
                 // background updates should be applied.
                 logger.debug("Found update for add-on ${id}", aAddon);
@@ -1408,107 +1386,16 @@ var AddonManagerInternal = {
 
               onUpdateFinished: aAddon => { logger.debug("onUpdateFinished for ${id}", aAddon); resolve(); }
             }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
           }));
         }
         await Promise.all(updates);
       }
 
-      if (checkHotfix) {
-        var hotfixVersion = Services.prefs.getCharPref(PREF_EM_HOTFIX_LASTVERSION, "");
-
-        let url = null;
-        if (Services.prefs.getPrefType(PREF_EM_HOTFIX_URL) == Ci.nsIPrefBranch.PREF_STRING)
-          url = Services.prefs.getCharPref(PREF_EM_HOTFIX_URL);
-        else
-          url = Services.prefs.getCharPref(PREF_EM_UPDATE_BACKGROUND_URL);
-
-        // Build the URI from a fake add-on data.
-        url = AddonManager.escapeAddonURI({
-          id: hotfixID,
-          version: hotfixVersion,
-          userDisabled: false,
-          appDisabled: false
-        }, url);
-
-        ChromeUtils.import("resource://gre/modules/addons/AddonUpdateChecker.jsm");
-        let update = null;
-        try {
-          let foundUpdates = await new Promise((resolve, reject) => {
-            AddonUpdateChecker.checkForUpdates(hotfixID, null, url, {
-              onUpdateCheckComplete: resolve,
-              onUpdateCheckError: reject
-            });
-          });
-          update = AddonUpdateChecker.getNewestCompatibleUpdate(foundUpdates);
-        } catch (e) {
-          // AUC.checkForUpdates already logged the error
-        }
-
-        // Check that we have a hotfix update, and it's newer than the one we already
-        // have installed (if any)
-        if (update) {
-          if (Services.vc.compare(hotfixVersion, update.version) < 0) {
-            logger.debug("Downloading hotfix version " + update.version);
-            let aInstall = await AddonManagerInternal.getInstallForURL(
-                update.updateURL, "application/x-xpinstall", update.updateHash,
-                null, null, update.version);
-
-            aInstall.addListener({
-              onDownloadEnded(aInstall) {
-                if (aInstall.addon.id != hotfixID) {
-                  logger.warn("The downloaded hotfix add-on did not have the " +
-                              "expected ID and so will not be installed.");
-                  aInstall.cancel();
-                  return;
-                }
-
-                // If XPIProvider has reported the hotfix as properly signed then
-                // there is nothing more to do here
-                if (aInstall.addon.signedState == AddonManager.SIGNEDSTATE_SIGNED)
-                  return;
-
-                try {
-                  if (!Services.prefs.getBoolPref(PREF_EM_CERT_CHECKATTRIBUTES))
-                    return;
-                } catch (e) {
-                  // By default don't do certificate checks.
-                  return;
-                }
-
-                try {
-                  CertUtils.validateCert(aInstall.certificate,
-                                         CertUtils.readCertPrefs(PREF_EM_HOTFIX_CERTS));
-                } catch (e) {
-                  logger.warn("The hotfix add-on was not signed by the expected " +
-                       "certificate and so will not be installed.", e);
-                  aInstall.cancel();
-                }
-              },
-
-              onInstallEnded(aInstall) {
-                // Remember the last successfully installed version.
-                Services.prefs.setCharPref(PREF_EM_HOTFIX_LASTVERSION,
-                                           aInstall.version);
-              },
-
-              onInstallCancelled(aInstall) {
-                // Revert to the previous version if the installation was
-                // cancelled.
-                Services.prefs.setCharPref(PREF_EM_HOTFIX_LASTVERSION,
-                                           hotfixVersion);
-              }
-            });
-
-            aInstall.install();
-          }
-        }
-      }
-
       if (appUpdateEnabled) {
         try {
           await AddonManagerInternal._getProviderByName("XPIProvider").updateSystemAddons();
         } catch (e) {
           logger.warn("Failed to update system addons", e);
         }
       }
 
@@ -2775,20 +2662,16 @@ var AddonManagerInternal = {
 
   set updateEnabled(aValue) {
     aValue = !!aValue;
     if (aValue != gUpdateEnabled)
       Services.prefs.setBoolPref(PREF_EM_UPDATE_ENABLED, aValue);
     return aValue;
   },
 
-  get hotfixID() {
-    return gHotfixID;
-  },
-
   setupPromptHandler(browser, url, install, requireConfirm, source) {
     install.promptHandler = info => new Promise((resolve, _reject) => {
       let reject = () => {
         this.installNotifyObservers("addon-install-cancelled",
                                     browser, url, install);
         _reject();
       };
 
@@ -3122,21 +3005,20 @@ this.AddonManagerPrivate = {
   },
 
   backgroundUpdateCheck() {
     return AddonManagerInternal.backgroundUpdateCheck();
   },
 
   backgroundUpdateTimerHandler() {
     // Don't call through to the real update check if no checks are enabled.
-    let checkHotfix = AddonManagerInternal.hotfixID &&
-                      Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
-                      Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
-
-    if (!AddonManagerInternal.updateEnabled && !checkHotfix) {
+    let appUpdateEnabled = Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
+                           Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
+
+    if (!AddonManagerInternal.updateEnabled && !appUpdateEnabled) {
       logger.info("Skipping background update check");
       return;
     }
     // Don't return the promise here, since the caller doesn't care.
     AddonManagerInternal.backgroundUpdateCheck();
   },
 
   addStartupChange(aType, aID) {
@@ -3773,20 +3655,16 @@ this.AddonManager = {
   get autoUpdateDefault() {
     return AddonManagerInternal.autoUpdateDefault;
   },
 
   set autoUpdateDefault(aValue) {
     AddonManagerInternal.autoUpdateDefault = aValue;
   },
 
-  get hotfixID() {
-    return AddonManagerInternal.hotfixID;
-  },
-
   escapeAddonURI(aAddon, aUri, aAppVersion) {
     return AddonManagerInternal.escapeAddonURI(aAddon, aUri, aAppVersion);
   },
 
   getPreferredIconURL(aAddon, aSize, aWindow = undefined) {
     return AddonManagerInternal.getPreferredIconURL(aAddon, aSize, aWindow);
   },
 
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -2874,17 +2874,17 @@ var gDetailView = {
     var downloadsRow = document.getElementById("detail-downloads");
     if (aAddon.totalDownloads && aIsRemote) {
       var downloads = aAddon.totalDownloads;
       downloadsRow.value = downloads;
     } else {
       downloadsRow.value = null;
     }
 
-    var canUpdate = !aIsRemote && hasPermission(aAddon, "upgrade") && aAddon.id != AddonManager.hotfixID;
+    var canUpdate = !aIsRemote && hasPermission(aAddon, "upgrade");
     document.getElementById("detail-updates-row").hidden = !canUpdate;
 
     if ("applyBackgroundUpdates" in aAddon) {
       this._autoUpdate.hidden = false;
       this._autoUpdate.value = aAddon.applyBackgroundUpdates;
       let hideFindUpdates = AddonManager.shouldAutoUpdate(this._addon);
       document.getElementById("detail-findUpdates-btn").hidden = hideFindUpdates;
     } else {
--- a/toolkit/mozapps/extensions/internal/AddonRepository.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonRepository.jsm
@@ -585,19 +585,16 @@ this.AddonRepository = {
     this._addons = null;
     return AddonDatabase.delete().then(() =>
       AddonManagerPrivate.updateAddonRepositoryData());
   },
 
   async _repopulateCacheInternal(aSendPerformance, aTimeout) {
     let allAddons = await AddonManager.getAllAddons();
 
-    // Filter the hotfix out of our list of add-ons
-    allAddons = allAddons.filter(a => a.id != AddonManager.hotfixID);
-
     // Completely remove cache if caching is not enabled
     if (!this.cacheEnabled) {
       logger.debug("Clearing cache because it is disabled");
       await this._clearCache();
       return;
     }
 
     let ids = allAddons.map(a => a.id);
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -118,20 +118,16 @@ function getFile(path, base = null) {
   return file;
 }
 
 const PREF_EM_UPDATE_BACKGROUND_URL   = "extensions.update.background.url";
 const PREF_EM_UPDATE_URL              = "extensions.update.url";
 const PREF_XPI_SIGNATURES_DEV_ROOT    = "xpinstall.signatures.dev-root";
 const PREF_XPI_UNPACK                 = "extensions.alwaysUnpack";
 const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts";
-const PREF_EM_HOTFIX_ID               = "extensions.hotfix.id";
-const PREF_EM_CERT_CHECKATTRIBUTES    = "extensions.hotfix.cert.checkAttributes";
-const PREF_EM_HOTFIX_CERTS            = "extensions.hotfix.certs.";
-
 const FILE_RDF_MANIFEST               = "install.rdf";
 const FILE_WEB_MANIFEST               = "manifest.json";
 
 const KEY_TEMPDIR                     = "TmpD";
 
 const RDFURI_INSTALL_MANIFEST_ROOT    = "urn:mozilla:install-manifest";
 const PREFIX_NS_EM                    = "http://www.mozilla.org/2004/em-rdf#";
 
@@ -1041,29 +1037,16 @@ function getSignedStatus(aRv, aCert, aAd
     expectedCommonName = getHashStringForCrypto(crypto);
   }
 
   switch (aRv) {
     case Cr.NS_OK:
       if (expectedCommonName && expectedCommonName != aCert.commonName)
         return AddonManager.SIGNEDSTATE_BROKEN;
 
-      let hotfixID = Services.prefs.getStringPref(PREF_EM_HOTFIX_ID, undefined);
-      if (hotfixID && hotfixID == aAddonID && Services.prefs.getBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, false)) {
-        // The hotfix add-on has some more rigorous certificate checks
-        try {
-          CertUtils.validateCert(aCert,
-                                 CertUtils.readCertPrefs(PREF_EM_HOTFIX_CERTS));
-        } catch (e) {
-          logger.warn("The hotfix add-on was not signed by the expected " +
-                      "certificate and so will not be installed.", e);
-          return AddonManager.SIGNEDSTATE_BROKEN;
-        }
-      }
-
       if (aCert.organizationalUnit == "Mozilla Components") {
         return AddonManager.SIGNEDSTATE_SYSTEM;
       }
 
       if (aCert.organizationalUnit == "Mozilla Extensions") {
         return AddonManager.SIGNEDSTATE_PRIVILEGED;
       }
 
@@ -1090,21 +1073,16 @@ function shouldVerifySignedState(aAddon)
   // Updated system add-ons should always have their signature checked
   if (aAddon._installLocation.name == KEY_APP_SYSTEM_ADDONS)
     return true;
 
   // We don't care about signatures for default system add-ons
   if (aAddon._installLocation.name == KEY_APP_SYSTEM_DEFAULTS)
     return false;
 
-  // Hotfixes should always have their signature checked
-  let hotfixID = Services.prefs.getStringPref(PREF_EM_HOTFIX_ID, undefined);
-  if (hotfixID && aAddon.id == hotfixID)
-    return true;
-
   // Otherwise only check signatures if signing is enabled and the add-on is one
   // of the signed types.
   return AddonSettings.ADDON_SIGNING && SIGNED_TYPES.has(aAddon.type);
 }
 
 /**
  * Verifies that a zip file's contents are all correctly signed by an
  * AMO-issued certificate
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -93,17 +93,16 @@ const PREF_INTERPOSITION_ENABLED      = 
 const PREF_SYSTEM_ADDON_SET           = "extensions.systemAddonSet";
 const PREF_SYSTEM_ADDON_UPDATE_URL    = "extensions.systemAddon.update.url";
 const PREF_ALLOW_LEGACY               = "extensions.legacy.enabled";
 const PREF_ALLOW_NON_MPC              = "extensions.allow-non-mpc-extensions";
 
 const PREF_EM_MIN_COMPAT_APP_VERSION      = "extensions.minCompatibleAppVersion";
 const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion";
 
-const PREF_EM_HOTFIX_ID               = "extensions.hotfix.id";
 const PREF_EM_LAST_APP_BUILD_ID       = "extensions.lastAppBuildId";
 
 // Specify a list of valid built-in add-ons to load.
 const BUILT_IN_ADDONS_URI             = "chrome://browser/content/built_in_addons.json";
 
 const OBSOLETE_PREFERENCES = [
   "extensions.bootstrappedAddons",
   "extensions.enabledAddons",
@@ -5591,24 +5590,20 @@ AddonWrapper.prototype = {
     return addon._installLocation.isSystem;
   },
 
   get isSystem() {
     let addon = addonFor(this);
     return addon._installLocation.isSystem;
   },
 
-  // Returns true if Firefox Sync should sync this addon. Only non-hotfixes
-  // directly in the profile are considered syncable.
+  // Returns true if Firefox Sync should sync this addon. Only addons
+  // in the profile install location are considered syncable.
   get isSyncable() {
     let addon = addonFor(this);
-    let hotfixID = Services.prefs.getStringPref(PREF_EM_HOTFIX_ID, undefined);
-    if (hotfixID && hotfixID == addon.id) {
-      return false;
-    }
     return (addon._installLocation.name == KEY_APP_PROFILE);
   },
 
   get userPermissions() {
     return addonFor(this).userPermissions;
   },
 
   isCompatibleWith(aAppVersion, aPlatformVersion) {
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/addons/test_hotfix_1/install.rdf
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0"?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>hotfix@tests.mozilla.org</em:id>
-    <em:version>1.0</em:version>
-
-    <!-- Front End MetaData -->
-    <em:name>Test 1</em:name>
-    <em:description>Test Description</em:description>
-
-    <em:targetApplication>
-      <Description>
-        <em:id>xpcshell@tests.mozilla.org</em:id>
-        <em:minVersion>1</em:minVersion>
-        <em:maxVersion>1</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-  </Description>
-</RDF>
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/addons/test_hotfix_2/install.rdf
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0"?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>hotfix@tests.mozilla.org</em:id>
-    <em:version>2.0</em:version>
-
-    <!-- Front End MetaData -->
-    <em:name>Test 1</em:name>
-    <em:description>Test Description</em:description>
-
-    <em:targetApplication>
-      <Description>
-        <em:id>xpcshell@tests.mozilla.org</em:id>
-        <em:minVersion>1</em:minVersion>
-        <em:maxVersion>1</em:maxVersion>
-      </Description>
-    </em:targetApplication>
-
-  </Description>
-</RDF>
--- a/toolkit/mozapps/extensions/test/browser/browser_details.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_details.js
@@ -2,17 +2,16 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Tests various aspects of the details view
 
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
 const PREF_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault";
-const PREF_EM_HOTFIX_ID = "extensions.hotfix.id";
 
 var gManagerWindow;
 var gCategoryUtilities;
 var gProvider;
 
 var gApp = document.getElementById("bundle_brand").getString("brandShortName");
 var gVersion = Services.appinfo.version;
 var gDate = new Date(2010, 7, 1);
@@ -39,17 +38,16 @@ function open_details(aId, aType, aCallb
 }
 
 function get(aId) {
   return gManagerWindow.document.getElementById(aId);
 }
 
 function test() {
   requestLongerTimeout(2);
-  Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, "hotfix@tests.mozilla.org");
 
   waitForExplicitFinish();
 
   gProvider = new MockProvider();
 
   gProvider.createAddons([{
     id: "addon1@tests.mozilla.org",
     name: "Test add-on 1",
@@ -158,31 +156,27 @@ function test() {
     isActive: false,
     appDisabled: true,
     isCompatible: false,
   }, {
     id: "addon12@tests.mozilla.org",
     name: "Test add-on 12",
     signedState: AddonManager.SIGNEDSTATE_SIGNED,
     foreignInstall: true,
-  }, {
-    id: "hotfix@tests.mozilla.org",
-    name: "Test hotfix 1",
   }]);
 
   open_manager(null, function(aWindow) {
     gManagerWindow = aWindow;
     gCategoryUtilities = new CategoryUtilities(gManagerWindow);
 
     run_next_test();
   });
 }
 
 function end_test() {
-  Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID);
   close_manager(gManagerWindow, function() {
     finish();
   });
 }
 
 // Opens and tests the details view for add-on 1
 add_test(function() {
   open_details("addon1@tests.mozilla.org", "extension", function() {
@@ -937,36 +931,16 @@ add_test(function() {
             run_next_test();
           });
         });
       });
     });
   });
 });
 
-// Opens and tests the details view for hotfix 1
-add_test(function() {
-  open_details("hotfix@tests.mozilla.org", "extension", function() {
-    is(get("detail-name").textContent, "Test hotfix 1", "Name should be correct");
-
-    is_element_hidden(get("detail-updates-row"), "Updates should be hidden");
-
-    is_element_hidden(get("detail-prefs-btn"), "Preferences button should be hidden");
-    is_element_hidden(get("detail-enable-btn"), "Enable button should be hidden");
-    is_element_visible(get("detail-disable-btn"), "Disable button should be visible");
-    is_element_visible(get("detail-uninstall-btn"), "Remove button should be visible");
-
-    is_element_hidden(get("detail-warning"), "Warning message should be hidden");
-    is_element_hidden(get("detail-warning-link"), "Warning link should be hidden");
-    is_element_hidden(get("detail-pending"), "Pending message should be hidden");
-
-    run_next_test();
-  });
-});
-
 // Tests that upgrades with onExternalInstall apply immediately
 add_test(function() {
   open_details("addon1@tests.mozilla.org", "extension", function() {
     gProvider.createAddons([{
       id: "addon1@tests.mozilla.org",
       name: "Test add-on replacement",
       version: "2.5",
       description: "Short description replacement",
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_1.rdf
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:extension:hotfix@tests.mozilla.org">
-    <em:updates>
-      <Seq>
-        <li>
-          <Description>
-            <em:version>1.0</em:version>
-            <em:targetApplication>
-              <Description>
-                <em:id>xpcshell@tests.mozilla.org</em:id>
-                <em:minVersion>1</em:minVersion>
-                <em:maxVersion>1</em:maxVersion>
-                <em:updateLink>http://localhost:%PORT%/addons/test_hotfix_1.xpi</em:updateLink>
-              </Description>
-            </em:targetApplication>
-          </Description>
-        </li>
-      </Seq>
-    </em:updates>
-  </Description>
-
-</RDF>
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_2.rdf
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:extension:hotfix@tests.mozilla.org">
-    <em:updates>
-      <Seq>
-        <li>
-          <Description>
-            <em:version>2.0</em:version>
-            <em:targetApplication>
-              <Description>
-                <em:id>xpcshell@tests.mozilla.org</em:id>
-                <em:minVersion>1</em:minVersion>
-                <em:maxVersion>1</em:maxVersion>
-                <em:updateLink>http://localhost:%PORT%/addons/test_hotfix_2.xpi</em:updateLink>
-              </Description>
-            </em:targetApplication>
-          </Description>
-        </li>
-      </Seq>
-    </em:updates>
-  </Description>
-
-</RDF>
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_hotfix_3.rdf
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8" ?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:extension:hotfix@tests.mozilla.org">
-    <em:updates>
-      <Seq>
-        <li>
-          <Description>
-            <em:version>3.0</em:version>
-            <em:targetApplication>
-              <Description>
-                <em:id>xpcshell@tests.mozilla.org</em:id>
-                <em:minVersion>2</em:minVersion>
-                <em:maxVersion>2</em:maxVersion>
-                <em:updateLink>http://localhost:%PORT%/addons/test_hotfix_3.xpi</em:updateLink>
-              </Description>
-            </em:targetApplication>
-          </Description>
-        </li>
-      </Seq>
-    </em:updates>
-  </Description>
-
-</RDF>
--- a/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js
@@ -88,22 +88,19 @@ function run_test_2() {
   }, profileDir);
 
   // Disable rcwn to make cache behavior deterministic.
   Services.prefs.setBoolPref("network.http.rcwn.enabled", false);
 
   // Background update uses a different pref, if set
   Services.prefs.setCharPref("extensions.update.background.url",
                              "http://localhost:" + gPort + "/data/test_backgroundupdate.rdf");
+
   restartManager();
 
-  // Do hotfix checks
-  Services.prefs.setCharPref("extensions.hotfix.id", "hotfix@tests.mozilla.org");
-  Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" + gPort + "/missing.rdf");
-
   let installCount = 0;
   let completeCount = 0;
   let sawCompleteNotification = false;
 
   Services.obs.addObserver(function observer() {
     Services.obs.removeObserver(observer, "addons-background-update-complete");
 
     Assert.equal(installCount, 3);
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js
+++ /dev/null
@@ -1,309 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// This verifies that hotfix installation works
-
-// The test extension uses an insecure update url.
-Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
-// Ignore any certificate requirements the app has set
-Services.prefs.setBoolPref("extensions.hotfix.cert.checkAttributes", false);
-
-ChromeUtils.import("resource://testing-common/httpd.js");
-var testserver = new HttpServer();
-testserver.start(-1);
-gPort = testserver.identity.primaryPort;
-testserver.registerDirectory("/addons/", do_get_file("addons"));
-mapFile("/data/test_hotfix_1.rdf", testserver);
-mapFile("/data/test_hotfix_2.rdf", testserver);
-mapFile("/data/test_hotfix_3.rdf", testserver);
-
-const profileDir = gProfD.clone();
-profileDir.append("extensions");
-
-function run_test() {
-  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
-
-  startupManager();
-
-  do_test_pending();
-  run_test_1();
-}
-
-function end_test() {
-  testserver.stop(do_test_finished);
-}
-
-// Test that background updates find and install any available hotfix
-function run_test_1() {
-  Services.prefs.setCharPref("extensions.hotfix.id", "hotfix@tests.mozilla.org");
-  Services.prefs.setCharPref("extensions.update.background.url", "http://localhost:" +
-                             gPort + "/data/test_hotfix_1.rdf");
-
-  prepare_test({
-    "hotfix@tests.mozilla.org": [
-      "onInstalling"
-    ]
-  }, [
-    "onNewInstall",
-    "onDownloadStarted",
-    "onDownloadEnded",
-    "onInstallStarted",
-    "onInstallEnded",
-  ], callback_soon(check_test_1));
-
-  // We don't need to wait on the promise, just waiting for the install to finish is enough.
-  AddonManagerInternal.backgroundUpdateCheck();
-}
-
-function check_test_1() {
-  restartManager();
-
-  AddonManager.getAddonByID("hotfix@tests.mozilla.org", function(aAddon) {
-    Assert.notEqual(aAddon, null);
-    Assert.equal(aAddon.version, "1.0");
-
-    aAddon.uninstall();
-    executeSoon(run_test_2);
-  });
-}
-
-// Don't install an already used hotfix
-function run_test_2() {
-  restartManager();
-
-  AddonManager.addInstallListener({
-    onNewInstall() {
-      do_throw("Should not have seen a new install created");
-    }
-  });
-
-  // Run the background update
-  AddonManagerInternal.backgroundUpdateCheck().then(run_test_3);
-}
-
-// Install a newer hotfix
-function run_test_3() {
-  restartManager();
-  Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" +
-                             gPort + "/data/test_hotfix_2.rdf");
-
-  prepare_test({
-    "hotfix@tests.mozilla.org": [
-      "onInstalling"
-    ]
-  }, [
-    "onNewInstall",
-    "onDownloadStarted",
-    "onDownloadEnded",
-    "onInstallStarted",
-    "onInstallEnded",
-  ], callback_soon(check_test_3));
-
-  AddonManagerInternal.backgroundUpdateCheck();
-}
-
-function check_test_3() {
-  restartManager();
-
-  AddonManager.getAddonByID("hotfix@tests.mozilla.org", function(aAddon) {
-    Assert.notEqual(aAddon, null);
-    Assert.equal(aAddon.version, "2.0");
-
-    aAddon.uninstall();
-    executeSoon(run_test_4);
-  });
-}
-
-// Don't install an incompatible hotfix
-function run_test_4() {
-  restartManager();
-
-  Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" +
-                             gPort + "/data/test_hotfix_3.rdf");
-
-  AddonManager.addInstallListener({
-    onNewInstall() {
-      do_throw("Should not have seen a new install created");
-    }
-  });
-
-  AddonManagerInternal.backgroundUpdateCheck().then(run_test_5);
-}
-
-// Don't install an older hotfix
-function run_test_5() {
-  restartManager();
-
-  Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" +
-                             gPort + "/data/test_hotfix_1.rdf");
-
-  AddonManager.addInstallListener({
-    onNewInstall() {
-      do_throw("Should not have seen a new install created");
-    }
-  });
-
-  AddonManagerInternal.backgroundUpdateCheck().then(run_test_6);
-}
-
-// Don't re-download an already pending install
-function run_test_6() {
-  restartManager();
-
-  Services.prefs.setCharPref("extensions.hotfix.lastVersion", "0");
-  Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" +
-                             gPort + "/data/test_hotfix_1.rdf");
-
-  prepare_test({
-    "hotfix@tests.mozilla.org": [
-      "onInstalling"
-    ]
-  }, [
-    "onNewInstall",
-    "onDownloadStarted",
-    "onDownloadEnded",
-    "onInstallStarted",
-    "onInstallEnded",
-  ], callback_soon(check_test_6));
-
-  AddonManagerInternal.backgroundUpdateCheck();
-}
-
-function check_test_6() {
-  AddonManager.addInstallListener({
-    onNewInstall() {
-      do_throw("Should not have seen a new install created");
-    }
-  });
-
-  AddonManagerInternal.backgroundUpdateCheck()
-    .then(promiseRestartManager)
-    .then(() => promiseAddonByID("hotfix@tests.mozilla.org"))
-    .then(aAddon => {
-      aAddon.uninstall();
-      run_test_7();
-    });
-}
-
-// Start downloading again if something cancels the install
-function run_test_7() {
-  restartManager();
-
-  Services.prefs.setCharPref("extensions.hotfix.lastVersion", "0");
-
-  prepare_test({
-    "hotfix@tests.mozilla.org": [
-      "onInstalling"
-    ]
-  }, [
-    "onNewInstall",
-    "onDownloadStarted",
-    "onDownloadEnded",
-    "onInstallStarted",
-    "onInstallEnded",
-  ], check_test_7);
-
-  AddonManagerInternal.backgroundUpdateCheck();
-}
-
-function check_test_7(aInstall) {
-  prepare_test({
-    "hotfix@tests.mozilla.org": [
-      "onOperationCancelled"
-    ]
-  }, [
-    "onInstallCancelled",
-  ]);
-
-  aInstall.cancel();
-
-  prepare_test({
-    "hotfix@tests.mozilla.org": [
-      "onInstalling"
-    ]
-  }, [
-    "onNewInstall",
-    "onDownloadStarted",
-    "onDownloadEnded",
-    "onInstallStarted",
-    "onInstallEnded",
-  ], callback_soon(finish_test_7));
-
-  AddonManagerInternal.backgroundUpdateCheck();
-}
-
-function finish_test_7() {
-  restartManager();
-
-  AddonManager.getAddonByID("hotfix@tests.mozilla.org", function(aAddon) {
-    Assert.notEqual(aAddon, null);
-    Assert.equal(aAddon.version, "1.0");
-
-    aAddon.uninstall();
-    executeSoon(run_test_8);
-  });
-}
-
-// Cancel a pending install when a newer version is already available
-function run_test_8() {
-  restartManager();
-
-  Services.prefs.setCharPref("extensions.hotfix.lastVersion", "0");
-  Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" +
-                             gPort + "/data/test_hotfix_1.rdf");
-
-  prepare_test({
-    "hotfix@tests.mozilla.org": [
-      "onInstalling"
-    ]
-  }, [
-    "onNewInstall",
-    "onDownloadStarted",
-    "onDownloadEnded",
-    "onInstallStarted",
-    "onInstallEnded",
-  ], check_test_8);
-
-  AddonManagerInternal.backgroundUpdateCheck();
-}
-
-function check_test_8() {
-  Services.prefs.setCharPref("extensions.hotfix.url", "http://localhost:" +
-                             gPort + "/data/test_hotfix_2.rdf");
-
-  prepare_test({
-    "hotfix@tests.mozilla.org": [
-      "onOperationCancelled",
-      "onInstalling"
-    ]
-  }, [
-    "onNewInstall",
-    "onDownloadStarted",
-    "onDownloadEnded",
-    "onInstallStarted",
-    "onInstallCancelled",
-    "onInstallEnded",
-  ], finish_test_8);
-
-  AddonManagerInternal.backgroundUpdateCheck();
-}
-
-function finish_test_8() {
-  AddonManager.getAllInstalls(callback_soon(function(aInstalls) {
-    Assert.equal(aInstalls.length, 1);
-    Assert.equal(aInstalls[0].version, "2.0");
-
-    restartManager();
-
-    AddonManager.getAddonByID("hotfix@tests.mozilla.org", callback_soon(function(aAddon) {
-      Assert.notEqual(aAddon, null);
-      Assert.equal(aAddon.version, "2.0");
-
-      aAddon.uninstall();
-      restartManager();
-
-      end_test();
-    }));
-  }));
-}
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/test_hotfix_cert.js
+++ /dev/null
@@ -1,167 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// This verifies that hotfix installation works
-const PREF_EM_HOTFIX_ID               = "extensions.hotfix.id";
-const PREF_EM_HOTFIX_LASTVERSION      = "extensions.hotfix.lastVersion";
-const PREF_EM_HOTFIX_URL              = "extensions.hotfix.url";
-const PREF_EM_CERT_CHECKATTRIBUTES    = "extensions.hotfix.cert.checkAttributes";
-const PREF_EM_HOTFIX_CERTS            = "extensions.hotfix.certs.";
-
-// Derived from "openssl x509 -in firefox-hotfix.crt -fingerprint -sha1"
-const GOOD_FINGERPRINT = "39:E7:2B:7A:5B:CF:37:78:F9:5D:4A:E0:53:2D:2F:3D:68:53:C5:60";
-const BAD_FINGERPRINT  = "40:E7:2B:7A:5B:CF:37:78:F9:5D:4A:E0:53:2D:2F:3D:68:53:C5:60";
-
-ChromeUtils.import("resource://testing-common/httpd.js");
-var testserver = new HttpServer();
-testserver.start(-1);
-gPort = testserver.identity.primaryPort;
-testserver.registerDirectory("/data/", do_get_file("data"));
-
-// The test extension uses an insecure update url.
-Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
-// Ignore any certificate requirements the app has set
-Services.prefs.setBoolPref(PREF_EM_CERT_CHECKATTRIBUTES, true);
-Services.prefs.setCharPref(PREF_EM_HOTFIX_URL, "http://localhost:" + gPort + "/hotfix.rdf");
-// Clear out all hotfix cert prefs to make sure only the test prefs apply.
-var defaults = Services.prefs.getDefaultBranch("");
-defaults.deleteBranch(PREF_EM_HOTFIX_CERTS);
-
-/*
- * Register an addon install listener and return a promise that:
- *  resolves with the AddonInstall object if the install succeeds
- *  rejects with the AddonInstall if the install fails
- */
-function promiseInstallListener() {
-  return new Promise((resolve, reject) => {
-    let listener = {
-      onDownloadFailed: ai => {
-        AddonManager.removeInstallListener(listener);
-        reject(ai);
-      },
-      onInstallEnded: ai => {
-        AddonManager.removeInstallListener(listener);
-        resolve(ai);
-      },
-      onDownloadCancelled: ai => {
-        AddonManager.removeInstallListener(listener);
-        reject(ai);
-      }
-    };
-    AddonManager.addInstallListener(listener);
-  });
-}
-
-function promiseSuccessfulInstall() {
-  return promiseInstallListener().then(
-    aInstall => {
-      Assert.ok(true);
-      Assert.equal(aInstall.addon.id, Services.prefs.getCharPref(PREF_EM_HOTFIX_ID));
-      aInstall.addon.uninstall();
-      Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
-    },
-    aInstall => {
-      do_throw("Install should not have failed");
-    });
-}
-
-function promiseFailedInstall() {
-  return promiseInstallListener().then(
-    aInstall => {
-      do_throw("Install should not have succeeded");
-      aInstall.addon.uninstall();
-      Services.prefs.clearUserPref(PREF_EM_HOTFIX_LASTVERSION);
-    },
-    aInstall => {
-      Assert.ok(true);
-    });
-}
-
-var tryInstallHotfix = async function(id, file, installListener) {
-  Services.prefs.setCharPref(PREF_EM_HOTFIX_ID, id);
-
-  testserver.registerPathHandler("/hotfix.rdf", function(request, response) {
-    response.write(createUpdateRDF({
-      [id]: [{
-        version: "1.0",
-        targetApplications: [{
-          id: "xpcshell@tests.mozilla.org",
-          minVersion: "0",
-          maxVersion: "*",
-          updateLink: "http://localhost:" + gPort + "/data/signing_checks/" + file,
-        }]
-      }]
-    }));
-  });
-
-  await Promise.all([
-    installListener,
-    AddonManagerPrivate.backgroundUpdateCheck()
-  ]);
-
-  testserver.registerPathHandler("/hotfix.rdf", null);
-  Services.prefs.clearUserPref(PREF_EM_HOTFIX_ID);
-};
-
-// Test valid AMO hotfix signed add-ons doesn't work if the fingerprint pref is wrong
-add_task(async function amo_signed_hotfix() {
-  Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", BAD_FINGERPRINT);
-
-  await tryInstallHotfix("firefox-hotfix@mozilla.org",
-                         "hotfix_good.xpi",
-                         promiseFailedInstall());
-});
-
-// Test valid AMO hotfix signed add-ons works
-add_task(async function amo_signed_hotfix() {
-  Services.prefs.setCharPref(PREF_EM_HOTFIX_CERTS + "1.sha1Fingerprint", GOOD_FINGERPRINT);
-
-  await tryInstallHotfix("firefox-hotfix@mozilla.org",
-                         "hotfix_good.xpi",
-                         promiseSuccessfulInstall());
-});
-
-// A hotfix altered after signing should fail
-add_task(async function amo_broken_hotfix() {
-  await tryInstallHotfix("firefox-hotfix@mozilla.org",
-                         "hotfix_broken.xpi",
-                         promiseFailedInstall());
-});
-
-// Test an add-on with the wrong ID but signed by the right cert fails
-add_task(async function amo_wrongID_rightcert() {
-  await tryInstallHotfix("test@tests.mozilla.org",
-                         "hotfix_badid.xpi",
-                         promiseFailedInstall());
-});
-
-// It shouldn't matter that it requested the ID matching the cert to begin with
-// if the embedded cert's ID doesn't match the add-on's ID
-add_task(async function amo_wrongID_rightcert2() {
-  await tryInstallHotfix("firefox-hotfix@mozilla.org",
-                         "hotfix_badid.xpi",
-                         promiseFailedInstall());
-});
-
-// Test something signed by a regular AMO cert doesn't work
-add_task(async function amo_signed_addon() {
-  await tryInstallHotfix("test@tests.mozilla.org",
-                         "signed_bootstrap_1.xpi",
-                         promiseFailedInstall());
-});
-
-// Test totally unsigned add-on fails
-add_task(async function unsigned() {
-  await tryInstallHotfix("test@tests.mozilla.org",
-                         "unsigned_bootstrap_2.xpi",
-                         promiseFailedInstall());
-});
-
-function run_test() {
-  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
-
-  startupManager();
-
-  run_next_test();
-}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js
@@ -194,28 +194,13 @@ function run_test() {
   Assert.ok(AddonManager.checkUpdateSecurity);
   if (!AddonManager.checkUpdateSecurityDefault)
     Assert.ok(Services.prefs.getBoolPref("extensions.checkUpdateSecurity"));
   else
     Assert.ok(!Services.prefs.prefHasUserValue("extensions.checkUpdateSecurity"));
 
   gManagerEventsListener.shutdown();
 
-  // AddonManager.hotfixID
-  let hotfixID = "hotfix@tests.mozilla.org";
-  Services.prefs.setCharPref("extensions.hotfix.id", hotfixID);
-  Assert.equal(AddonManager.hotfixID, hotfixID);
-  // Change the pref and make sure the property is updated
-  hotfixID = "hotfix2@tests.mozilla.org";
-  Services.prefs.setCharPref("extensions.hotfix.id", hotfixID);
-  Assert.equal(AddonManager.hotfixID, hotfixID);
-  // Test an invalid pref value
-  hotfixID = 99;
-  Services.prefs.deleteBranch("extensions.hotfix.id");
-  Services.prefs.setIntPref("extensions.hotfix.id", hotfixID);
-  Assert.equal(AddonManager.hotfixID, "");
-  Services.prefs.clearUserPref("extensions.hotfix.id");
-
   // After removing the listener, ensure we get no further events.
   gManagerEventsListener.expect([]);
   AddonManager.updateEnabled = false;
   gManagerEventsListener.checkExpected();
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
@@ -211,17 +211,16 @@ tags = blocklist
 tags = blocklist
 [test_gfxBlacklist_Version.js]
 tags = blocklist
 [test_gfxBlacklist_prefs.js]
 # Bug 1248787 - consistently fails
 skip-if = true
 tags = blocklist
 [test_hasbinarycomponents.js]
-[test_hotfix.js]
 [test_install.js]
 [test_install_icons.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_install_strictcompat.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 run-sequentially = Uses hardcoded ports in xpi files.
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
@@ -14,17 +14,16 @@ support-files =
 tags = blocklist
 [test_blocklist_gfx.js]
 tags = blocklist
 [test_cache_certdb.js]
 run-if = addon_signing
 [test_cacheflush.js]
 [test_gmpProvider.js]
 skip-if = appname != "firefox"
-[test_hotfix_cert.js]
 [test_invalid_install_rdf.js]
 [test_isReady.js]
 [test_pluginInfoURL.js]
 tags = blocklist
 [test_provider_markSafe.js]
 [test_provider_shutdown.js]
 [test_provider_unsafe_access_shutdown.js]
 [test_provider_unsafe_access_startup.js]