B2G/gecko/toolkit/mozapps/extensions/XPIProvider.jsm
/**
   * Uninstalls an add-on, immediately if possible or marks it as pending
   * uninstall if not.
   *
   * @param  aAddon
   *         The DBAddonInternal to uninstall
   * @throws if the addon cannot be uninstalled because it is in an install
   *         location that does not allow it
   */
Uninstalls an add-on, immediately if possible or marks it as pending
uninstall if not.

@param  aAddon
The DBAddonInternal to uninstall
@throws if the addon cannot be uninstalled because it is in an install
location that does not allow it
Uninstalls an add - on immediately if possible or marks it as pending uninstall if not . @param aAddon The DBAddonInternal to uninstall @throws if the addon cannot be uninstalled because it is in an install location that does not allow it
function XPI_uninstallAddon(aAddon) {
    if (!(aAddon instanceof DBAddonInternal))
      throw new Error("Can only uninstall installed addons.");
    if (aAddon._installLocation.locked)
      throw new Error("Cannot uninstall addons from locked install locations");
    if ("_hasResourceCache" in aAddon)
      aAddon._hasResourceCache = new Map();
    let requiresRestart = this.uninstallRequiresRestart(aAddon);
    if (requiresRestart) {
      let stage = aAddon._installLocation.getStagingDir();
      stage.append(aAddon.id);
      if (!stage.exists())
        stage.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
      XPIDatabase.setAddonProperties(aAddon, {
        pendingUninstall: true
      });
      Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, true);
    }
    if (!aAddon.visible)
      return;
    let wrapper = createWrapper(aAddon);
    AddonManagerPrivate.callAddonListeners("onUninstalling", wrapper,
                                           requiresRestart);
    function revealAddon(aAddon) {
      XPIDatabase.makeAddonVisible(aAddon);
      let wrappedAddon = createWrapper(aAddon);
      AddonManagerPrivate.callAddonListeners("onInstalling", wrappedAddon, false);
      if (!isAddonDisabled(aAddon) && !XPIProvider.enableRequiresRestart(aAddon)) {
        aAddon.active = true;
        XPIDatabase.updateAddonActive(aAddon);
      }
      if (aAddon.bootstrap) {
        let file = aAddon._installLocation.getLocationForID(aAddon.id);
        XPIProvider.callBootstrapMethod(aAddon.id, aAddon.version, aAddon.type, file,
                                        "install", BOOTSTRAP_REASONS.ADDON_INSTALL);
        if (aAddon.active) {
          XPIProvider.callBootstrapMethod(aAddon.id, aAddon.version, aAddon.type, file,
                                          "startup", BOOTSTRAP_REASONS.ADDON_INSTALL);
        }
        else {
          XPIProvider.unloadBootstrapScope(aAddon.id);
        }
      }
      AddonManagerPrivate.callAddonListeners("onInstalled", wrappedAddon);
    }
    function checkInstallLocation(aPos) {
      if (aPos < 0)
        return;
      let location = XPIProvider.installLocations[aPos];
      XPIDatabase.getAddonInLocation(aAddon.id, location.name,
        function checkInstallLocation_getAddonInLocation(aNewAddon) {
        if (aNewAddon)
          revealAddon(aNewAddon);
        else
          checkInstallLocation(aPos - 1);
      })
    }
    if (!requiresRestart) {
      if (aAddon.bootstrap) {
        let file = aAddon._installLocation.getLocationForID(aAddon.id);
        if (aAddon.active) {
          this.callBootstrapMethod(aAddon.id, aAddon.version, aAddon.type, file,
                                   "shutdown",
                                   BOOTSTRAP_REASONS.ADDON_UNINSTALL);
        }
        this.callBootstrapMethod(aAddon.id, aAddon.version, aAddon.type, file,
                                 "uninstall",
                                 BOOTSTRAP_REASONS.ADDON_UNINSTALL);
        this.unloadBootstrapScope(aAddon.id);
        flushStartupCache();
      }
      aAddon._installLocation.uninstallAddon(aAddon.id);
      XPIDatabase.removeAddonMetadata(aAddon);
      AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper);
      checkInstallLocation(this.installLocations.length - 1);
    }
    if (aAddon.type == "theme" && aAddon.active)
      AddonManagerPrivate.notifyAddonChanged(null, aAddon.type, requiresRestart);
  }
function XPI_uninstallAddon ( aAddon ) { if ( ! ( aAddon instanceof DBAddonInternal ) ) throw new Error ( "Can only uninstall installed addons." ) ; if ( aAddon . _installLocation . locked ) throw new Error ( "Cannot uninstall addons from locked install locations" ) ; if ( "_hasResourceCache" in aAddon ) aAddon . _hasResourceCache = new Map ( ) ; let requiresRestart = this . uninstallRequiresRestart ( aAddon ) ; if ( requiresRestart ) { let stage = aAddon . _installLocation . getStagingDir ( ) ; stage . append ( aAddon . id ) ; if ( ! stage . exists ( ) ) stage . create ( Ci . nsIFile . DIRECTORY_TYPE , FileUtils . PERMS_DIRECTORY ) ; XPIDatabase . setAddonProperties ( aAddon , { pendingUninstall : true } ) ; Services . prefs . setBoolPref ( PREF_PENDING_OPERATIONS , true ) ; } if ( ! aAddon . visible ) return ; let wrapper = createWrapper ( aAddon ) ; AddonManagerPrivate . callAddonListeners ( "onUninstalling" , wrapper , requiresRestart ) ; function revealAddon ( aAddon ) { XPIDatabase . makeAddonVisible ( aAddon ) ; let wrappedAddon = createWrapper ( aAddon ) ; AddonManagerPrivate . callAddonListeners ( "onInstalling" , wrappedAddon , false ) ; if ( ! isAddonDisabled ( aAddon ) && ! XPIProvider . enableRequiresRestart ( aAddon ) ) { aAddon . active = true ; XPIDatabase . updateAddonActive ( aAddon ) ; } if ( aAddon . bootstrap ) { let file = aAddon . _installLocation . getLocationForID ( aAddon . id ) ; XPIProvider . callBootstrapMethod ( aAddon . id , aAddon . version , aAddon . type , file , "install" , BOOTSTRAP_REASONS . ADDON_INSTALL ) ; if ( aAddon . active ) { XPIProvider . callBootstrapMethod ( aAddon . id , aAddon . version , aAddon . type , file , "startup" , BOOTSTRAP_REASONS . ADDON_INSTALL ) ; } else { XPIProvider . unloadBootstrapScope ( aAddon . id ) ; } } AddonManagerPrivate . callAddonListeners ( "onInstalled" , wrappedAddon ) ; } function checkInstallLocation ( aPos ) { if ( aPos < 0 ) return ; let location = XPIProvider . installLocations [ aPos ] ; XPIDatabase . getAddonInLocation ( aAddon . id , location . name , function checkInstallLocation_getAddonInLocation ( aNewAddon ) { if ( aNewAddon ) revealAddon ( aNewAddon ) ; else checkInstallLocation ( aPos - 1 ) ; } ) } if ( ! requiresRestart ) { if ( aAddon . bootstrap ) { let file = aAddon . _installLocation . getLocationForID ( aAddon . id ) ; if ( aAddon . active ) { this . callBootstrapMethod ( aAddon . id , aAddon . version , aAddon . type , file , "shutdown" , BOOTSTRAP_REASONS . ADDON_UNINSTALL ) ; } this . callBootstrapMethod ( aAddon . id , aAddon . version , aAddon . type , file , "uninstall" , BOOTSTRAP_REASONS . ADDON_UNINSTALL ) ; this . unloadBootstrapScope ( aAddon . id ) ; flushStartupCache ( ) ; } aAddon . _installLocation . uninstallAddon ( aAddon . id ) ; XPIDatabase . removeAddonMetadata ( aAddon ) ; AddonManagerPrivate . callAddonListeners ( "onUninstalled" , wrapper ) ; checkInstallLocation ( this . installLocations . length - 1 ) ; } if ( aAddon . type == "theme" && aAddon . active ) AddonManagerPrivate . notifyAddonChanged ( null , aAddon . type , requiresRestart ) ; }
Uninstalls an add-on, immediately if possible or marks it as pending
 uninstall if not.
Uninstalls an add - on immediately if possible or marks it as pending uninstall if not .
// Inactive add-ons don't require a restart to uninstall // We create an empty directory in the staging directory to indicate that // an uninstall is necessary on next startup. // If the add-on is not visible then there is no need to notify listeners. // Reveal the highest priority add-on with the same ID // We always send onInstalled even if a restart is required to enable // the revealed add-on // Notify any other providers that a new theme has been enabled