Bug 264750 Updating disabled extensions re-enables them

p=rob_strong@exchangecode.com r/a=benjamin
This commit is contained in:
bugzilla%arlen.demon.co.uk 2005-07-25 23:27:38 +00:00
Родитель 920e33d25a
Коммит 6a5e6ef55f
4 изменённых файлов: 197 добавлений и 141 удалений

Просмотреть файл

@ -4,6 +4,13 @@ aboutWindowVersionString=version %S
aboutExtension=About %S...
updatingMessage=Looking for updates to %S...
updateAvailableMessage=A new version of %S (%S) is available.
updateCompatibilityMessage=A compatibility update has been applied to %S.
updateNoUpdateMessage=No updates were found for %S.
updateErrorMessage=An error occurred while trying to find updates for %S.
updateDisabledMessage=Updates are disabled for %S.
updateAppManagedMessage=Updates to %S are performed when %S is updated.
updateReadOnlyMessage=Update not supported (install location is read only).
updateNotManagedMessage=Update not supported (install location is not managed by %S).
restartBeforeEnableTitle=Enable Extension
restartBeforeDisableTitle=Disable Extension
restartBeforeEnableMessage=%S will be enabled the next time you restart %S.

Просмотреть файл

@ -95,7 +95,7 @@ var gUpdateWizard = {
if (this.items.length == 0) {
var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
this.items = em.getUpdateableItemList(nsIUpdateItem.TYPE_ADDON, { });
this.items = em.getItemList(nsIUpdateItem.TYPE_ADDON, { });
}
var pref =

Просмотреть файл

@ -165,7 +165,7 @@ interface nsIInstallLocation : nsISupports
* XXXben - Some of this stuff should go into a management-ey interface,
* some into an app-startup-ey interface.
*/
[scriptable, uuid(2c981b79-6873-41da-8341-7cda018b6e18)]
[scriptable, uuid(003efd62-feb2-4bec-9846-48237fb169ba)]
interface nsIExtensionManager : nsISupports
{
/**
@ -286,23 +286,6 @@ interface nsIExtensionManager : nsISupports
void getItemList(in unsigned long type, out unsigned long itemCount,
[retval, array, size_is(itemCount)] out nsIUpdateItem items);
/*
* Retrieves a list of nsIUpdateItems of items matching the specified type
* that can be updated.
* @param type
* The type of item to return.
* @param countRef
* The XPCJS reference to the number of items returned.
* @returns An array of nsIUpdateItems matching the type filter that can be
* updated based on if the item is not appManaged, does not have
* a pending install, upgrade, or uninstall operation, the item's
* update.enabled pref is not set to false, and the item's location
* is writeable.
*/
void getUpdateableItemList(in unsigned long type,
out unsigned long itemCount,
[retval, array, size_is(itemCount)] out nsIUpdateItem items);
/**
* Retrieves a list of nsIUpdateItems of items that are incompatible
* with the supplied parameters.
@ -512,6 +495,13 @@ interface nsIAddonUpdateCheckListener : nsISupports
const unsigned long STATUS_FAILURE = 4;
const unsigned long STATUS_NO_UPDATE = 8;
const unsigned long STATUS_DISABLED = 16;
const unsigned long STATUS_APP_MANAGED = 32;
const unsigned long STATUS_READ_ONLY = 64;
const unsigned long STATUS_PENDING_OP = 128;
const unsigned long STATUS_NOT_MANAGED = 256;
const unsigned long STATUS_DISALLOWED =
STATUS_DISABLED + STATUS_APP_MANAGED + STATUS_READ_ONLY +
STATUS_PENDING_OP + STATUS_NOT_MANAGED;
/**
* Addon update has ended

Просмотреть файл

@ -22,6 +22,7 @@
* Ben Goodger <ben@mozilla.org> (Google Inc.)
* Benjamin Smedberg <benjamin@smedbergs.us>
* Jens Bannmann <jens.b@web.de>
* Robert Strong <rob_strong@exchangecode.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -2516,7 +2517,7 @@ ExtensionManager.prototype = {
else if (installData.error == INSTALLERROR_INCOMPATIBLE_VERSION) {
LOG("... success, item installed but is not compatible");
callback(installManifest, installData.id, location, installData.type);
em.disableItem(id);
em._appDisableItem(id);
}
else {
/**
@ -2914,7 +2915,7 @@ ExtensionManager.prototype = {
LOG("_upgradeThemeChrome: failed to upgrade contents manifest for " +
"theme: " + item.id + ", exception: " + e + "... The theme will be " +
"disabled.");
this.disableItem(item.id);
this._appDisableItem(item.id);
}
finally {
try {
@ -2988,7 +2989,8 @@ ExtensionManager.prototype = {
var items = PendingOperations.getOperations(OP_NEEDS_ENABLE);
for (var i = items.length - 1; i >= 0; --i) {
var id = items[0].id;
ds.setItemProperty(id, EM_R("disabled"), null);
ds.setItemProperty(id, EM_R("userDisabled"), null);
ds.setItemProperty(id, EM_R("appDisabled"), null);
var installLocation = this.getInstallLocation(id);
StartupCache.put(installLocation, id, OP_NONE, true);
PendingOperations.clearItem(id);
@ -3000,7 +3002,11 @@ ExtensionManager.prototype = {
items = PendingOperations.getOperations(OP_NEEDS_DISABLE);
for (i = items.length - 1; i >= 0; --i) {
id = items[i].id;
ds.setItemProperty(id, EM_R("disabled"), EM_L("true"));
// Only set the userDisabled property when the item's appDisabled
// property is not true since an item can't be disabled by the user
// when it is already disabled by the application.
if (ds.getItemProperty(id, "appDisabled") != "true")
ds.setItemProperty(id, EM_R("userDisabled"), EM_L("true"));
installLocation = this.getInstallLocation(id);
StartupCache.put(installLocation, id, OP_NONE, true);
PendingOperations.clearItem(id);
@ -3029,7 +3035,7 @@ ExtensionManager.prototype = {
items = PendingOperations.getOperations(OP_NEEDS_INSTALL);
for (i = items.length - 1; i >= 0; --i) {
needsRestart = true;
var id = items[i].id;
id = items[i].id;
// check if there is updated app compatibility info
newTargetAppInfo = ds.getUpdatedTargetAppInfo(id);
if (newTargetAppInfo)
@ -3114,7 +3120,7 @@ ExtensionManager.prototype = {
if (items.length > 0) {
// Now disable the items so they won't hurt anything.
for (var i = 0; i < items.length; ++i)
this.disableItem(items[i].id);
this._appDisableItem(items[i].id);
this._showMismatchWindow(items);
needsRestart = true;
@ -3274,12 +3280,14 @@ ExtensionManager.prototype = {
var oldPrefix = (item.type == nsIUpdateItem.TYPE_EXTENSION) ? PREFIX_EXTENSION : PREFIX_THEME;
var oldRes = gRDF.GetResource(oldPrefix + item.id);
// Disable the item if it was disabled in the version 1.0 extensions
// datasource otherwise enable the item. If an item is incompatible it
// will be disabled later during the incompatible check.
// datasource.
if (oldExtensionsDS.GetTarget(oldRes, EM_R("disabled"), true))
this.disableItem(item.id);
else if (ds.getItemProperty(item.id, "disabled") == "true")
this.enableItem(item.id);
// app enable all items that are app disabled. If it is incompatible
// it will be app disabled later on.
if (ds.getItemProperty(item.id, "appDisabled") == "true")
this._appEnableItem(item.id);
// if the item is already compatible don't attempt to migrate the
// item's compatibility info
@ -3354,7 +3362,7 @@ ExtensionManager.prototype = {
op == OP_NEEDS_UNINSTALL || op == OP_NEEDS_DISABLE)
continue;
}
// Suppress items that have been disabled by the user.
// Suppress items that have been disabled by the user or the app.
if (ds.getItemProperty(item.id, "disabled") != "true")
activeItems.push({ id: item.id, location: installLocation });
}
@ -3851,7 +3859,9 @@ ExtensionManager.prototype = {
LOG("Phone Home Listener: Update For " + addon.id + " ended, status = " + status);
em.datasource.removeDownload(this._xpi.path);
LOG("Version Check Phone Home Completed");
if (status & nsIAddonUpdateCheckListener.STATUS_DATA_FOUND) {
// Only compatibility updates (e.g. STATUS_VERSIONINFO) are currently
// supported
if (status == nsIAddonUpdateCheckListener.STATUS_VERSIONINFO) {
em.datasource.setTargetApplicationInfo(addon.id,
addon.minAppVersion,
addon.maxAppVersion,
@ -4112,11 +4122,11 @@ ExtensionManager.prototype = {
* The nsIUpdateItem type of this item.
*/
_upgradeItem: function (installManifest, id, installLocation, type) {
// Clear any "disabled" flags that may have been set by the mismatch
// Clear any "appDisabled" flags that may have been set by the mismatch
// checking code at startup.
var ds = this.datasource;
ds.updateVisibleList(id, installLocation.name, false);
var props = { disabled : null,
var props = { appDisabled : null,
name : EM_L(getManifestProperty(installManifest, "name")),
version : EM_L(getManifestProperty(installManifest, "version")),
installLocation : EM_L(installLocation.name),
@ -4206,6 +4216,7 @@ ExtensionManager.prototype = {
var installManifest = getInstallManifest(installRDF);
if (installManifest) {
var type = getAddonTypeFromInstallManifest(installManifest);
var userDisabled = ds.getItemProperty(id, "userDisabled") == "true";
// Clean the item resource
ds.removeItemMetadata(id);
@ -4213,6 +4224,8 @@ ExtensionManager.prototype = {
// "initial state" for installation.
this._configureForthcomingItem(installManifest, id, installLocation,
type);
if (userDisabled)
ds.setItemProperty(id, EM_R("userDisabled"), EM_L("true"));
}
if (stagedFileExists)
installRDF.remove(false);
@ -4334,26 +4347,62 @@ ExtensionManager.prototype = {
StartupCache.put(location, id, op, true);
PendingOperations.addItem(op, { locationKey: location.name, id: id });
var ds = this.datasource;
ds.updateProperty(id, "displayDescription");
ds.updateProperty(id, "opType");
ds.updateProperty(id, "updateable");
ds.updateProperty(id, "displayDescription");
var restartRequired = this.installRequiresRestart(id, ds.getItemProperty(id, "type"))
this._updateManifests(restartRequired);
},
/**
* Enables an item for the application (e.g. the item meets all requirements
* for it to be enabled). If the item is not disabled by the user this will
* also set the needs-enable operation for the next restart.
* @param id
* The ID of the item to be enabled by the application.
*/
_appEnableItem: function(id) {
var ds = this.datasource;
if (ds.getItemProperty(id, "userDisabled") != "true") {
this._setOp(id, OP_NEEDS_ENABLE);
this._notifyAction(id, EM_ITEM_ENABLED);
}
else {
ds.setItemProperty(id, EM_R("appDisabled"), null);
ds.updateProperty(id, "compatible");
ds.updateProperty(id, "displayDescription");
}
},
/**
* Disables an item for the application (e.g. the item does not meets all
* requirements like app compatibility for it to be enabled). If the item is
* not disabled by the user this will also set the needs-disable operation
* for the next restart.
* @param id
* The ID of the item to be disabled by the application.
*/
_appDisableItem: function(id) {
var ds = this.datasource;
ds.setItemProperty(id, EM_R("appDisabled"), EM_L("true"));
if (ds.getItemProperty(id, "userDisabled") != "true") {
this._setOp(id, OP_NEEDS_DISABLE);
this._notifyAction(id, EM_ITEM_DISABLED);
}
},
/**
* Sets an item to be enabled. If the item is already enabled this clears
* the needs-enable operation for the next restart. If the item's operation
* is set to be uninstalled this will cancel the uninstall and sets the
* needs-enable operation for the next restart if the item is disabled.
* Sets an item to be enabled by the user. If the item is already enabled this
* clears the needs-enable operation for the next restart. If the item's
* operation is set to needs-uninstall this will cancel the uninstall and set
* the needs-enable operation for the next restart if the item is disabled.
*
* @param id
* The ID of the item to enable.
* The ID of the item to be enabled by the user.
*/
enableItem: function(id) {
var ds = this.datasource;
var disabled = ds.getItemProperty(id, "disabled") ? true : false;
if (disabled) {
if (ds.getItemProperty(id, "userDisabled") == "true") {
this._setOp(id, OP_NEEDS_ENABLE);
this._notifyAction(id, EM_ITEM_ENABLED);
}
@ -4364,15 +4413,14 @@ ExtensionManager.prototype = {
},
/**
* Sets an item to be disabled. If the item is already disabled this clears
* the needs-disable operation for the next restart.
* Sets an item to be disabled by the user. If the item is already disabled
* this clears the needs-disable operation for the next restart.
* @param id
* The ID of the item to disable.
* The ID of the item to be disabled by the user.
*/
disableItem: function(id) {
var ds = this.datasource;
var disabled = ds.getItemProperty(id, "disabled") ? true : false;
if (disabled) {
if (ds.getItemProperty(id, "userDisabled") == "true") {
this._setOp(id, OP_NONE);
this._notifyAction(id, EM_ITEM_CANCEL);
}
@ -4400,7 +4448,7 @@ ExtensionManager.prototype = {
gApp.version);
if (items.length == 0)
items = this.getUpdateableItemList(nsIUpdateItem.TYPE_ADDON, { });
items = this.getItemList(nsIUpdateItem.TYPE_ADDON, { });
var updater = new ExtensionItemUpdater(appID, appVersion, this);
updater.checkForUpdates(items, items.length, versionUpdateOnly, listener);
@ -4446,23 +4494,6 @@ ExtensionManager.prototype = {
return this.datasource.getItemList(type, countRef);
},
/*
* Retrieves a list of nsIUpdateItems of items matching the specified type
* that can be updated.
* @param type
* The type of item to return.
* @param countRef
* The XPCJS reference to the number of items returned.
* @returns An array of nsIUpdateItems matching the type filter that can be
* updated based on if the item is not appManaged, does not have
* a pending install, upgrade, or uninstall operation, the item's
* update.enabled pref is not set to false, and the item's location
* is writeable.
*/
getUpdateableItemList: function(type, countRef) {
return this.datasource.getUpdateableItemList(type, countRef);
},
/**
* See nsIExtensionManager.idl
*/
@ -5031,8 +5062,8 @@ ExtensionItemUpdater.prototype = {
// already been disabled, re-enable it.
var op = StartupCache.entries[aLocalItem.installLocationKey][aLocalItem.id].op;
if (op == OP_NEEDS_DISABLE ||
this._emDS.getItemProperty(aLocalItem.id, "disabled") == "true")
this._em.enableItem(aLocalItem.id);
this._emDS.getItemProperty(aLocalItem.id, "appDisabled") == "true")
this._em._appEnableItem(aLocalItem.id);
}
},
@ -5093,6 +5124,42 @@ RDFItemUpdater.prototype = {
}
catch (e) { }
// Items managed by the app are not checked for updates.
var emDS = this._updater._emDS;
if (emDS.getItemProperty(aItem.id, "appManaged") == "true") {
var status = nsIAddonUpdateCheckListener.STATUS_APP_MANAGED;
this._updater.checkForDone(aItem, status);
return;
}
// Items that have a pending install, uninstall, or upgrade are not checked
// for updates.
var opType = emDS.getItemProperty(aItem.id, "opType");
if (opType == OP_NEEDS_INSTALL || opType == OP_NEEDS_UNINSTALL ||
opType == OP_NEEDS_UPGRADE) {
var status = nsIAddonUpdateCheckListener.STATUS_PENDING_OP;
this._updater.checkForDone(aItem, status);
return;
}
var installLocation = InstallLocations.get(emDS.getInstallLocationKey(aItem.id));
// Don't check items for updates that are installed in a location that is
// not managed by the app.
if (installLocation && (installLocation.name == "winreg-app-global" ||
installLocation.name == "winreg-app-user")) {
var status = nsIAddonUpdateCheckListener.STATUS_NOT_MANAGED;
this._updater.checkForDone(aItem, status);
return;
}
// Don't check items for updates if the location can't be written to except
// when performing a version only update.
if (!aVersionUpdateOnly && (!installLocation || !installLocation.canAccess)) {
var status = nsIAddonUpdateCheckListener.STATUS_READ_ONLY;
this._updater.checkForDone(aItem, status);
return;
}
this._versionUpdateOnly = aVersionUpdateOnly;
this._item = aItem;
@ -5256,7 +5323,9 @@ RDFItemUpdater.prototype = {
aLocalItem.name,
"", "", "",
aLocalItem.type);
if (this._updater._isValidUpdate(aLocalItem, sameItem)) {
if (this._updater._isValidUpdate(aLocalItem, sameItem) &&
(aLocalItem.minAppVersion != sameItem.minAppVersion ||
aLocalItem.maxAppVersion != sameItem.maxAppVersion)) {
// Install-time updates are not written to the DS because there is no
// entry yet, EM just uses the notifications to ascertain (by hand)
// whether or not there is a remote maxVersion tweak that makes the
@ -5280,7 +5349,7 @@ RDFItemUpdater.prototype = {
item = newerItem;
status = nsIAddonUpdateCheckListener.STATUS_UPDATE;
}
else if (this._versionUpdateOnly && sameItem) {
else if (sameItem) {
item = sameItem;
status = nsIAddonUpdateCheckListener.STATUS_VERSIONINFO;
}
@ -5416,7 +5485,7 @@ RDFItemUpdater.prototype = {
"the update datasource for item " + this._item.id + ", error: " + aErrorMsg);
}
catch (e) {
LOG("RDFItemUpdater:onError: Failure during onAddonUpdateEnded call");
LOG("RDFItemUpdater:onError: Failure during removeXMLSinkObserver call");
}
this._updater.checkForDone(this._item,
nsIAddonUpdateCheckListener.STATUS_FAILURE);
@ -5508,8 +5577,9 @@ ExtensionsDataSource.prototype = {
var id = stripPrefix(item.Value, PREFIX_ITEM_URI);
var type = this.getItemProperty(id, "type");
// Skip this item if we're not seeking disabled items
var disabled = this.getItemProperty(id, "disabled") == "true";
if (!includeDisabled && disabled)
if (!includeDisabled &&
(this.getItemProperty(id, "disabled") == "true" ||
this.getItemProperty(id, "appDisabled") == "true"))
continue;
// If the id of this item matches one of the items potentially installed
@ -5556,36 +5626,6 @@ ExtensionsDataSource.prototype = {
return items;
},
/*
* Retrieves a list of nsIUpdateItems of items matching the specified type
* that can be updated.
* @param type
* The type of item to return.
* @param countRef
* The XPCJS reference to the number of items returned.
* @returns An array of nsIUpdateItems matching the type filter that can be
* updated based on if the item is not appManaged, does not have
* a pending install, upgrade, or uninstall operation, the item's
* update.enabled pref is not set to false, and the item's location
* is writeable.
*/
getUpdateableItemList: function(desiredType, countRef) {
var items = [];
var ctr = getContainer(this, this._itemRoot);
var elements = ctr.GetElements();
while (elements.hasMoreElements()) {
var e = elements.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
var eID = stripPrefix(e.Value, PREFIX_ITEM_URI);
var type = this.getItemProperty(eID, "type");
if (type != -1 && type & desiredType) {
if (this.getItemProperty(eID, "updateable") == "true")
items.push(this.getItemForID(eID));
}
}
countRef.value = items.length;
return items;
},
/**
* Get a list of Item IDs that have a flag set
* @param flag
@ -6072,9 +6112,9 @@ ExtensionsDataSource.prototype = {
this._inner.Assert(targetRes, property, anon, true);
}
}
this.updateProperty(id, "displayDescription");
this.updateProperty(id, "opType");
this.updateProperty(id, "updateable");
this.updateProperty(id, "displayDescription");
this.Flush();
},
@ -6362,7 +6402,7 @@ ExtensionsDataSource.prototype = {
*/
onAddonUpdateEnded: function(addon, status) {
LOG("Datasource: Addon Update Ended: " + addon.id + ", status: " + status);
this._updateURLs[addon.id] = null;
this._updateURLs[addon.id] = status;
var url = null, version = null;
var updateAvailable = status == nsIAddonUpdateCheckListener.STATUS_UPDATE;
if (updateAvailable) {
@ -6456,7 +6496,8 @@ ExtensionsDataSource.prototype = {
},
/**
* If we're in safe mode, force the generic about dialog for all extensions.
* If we're in safe mode, the item is disabled by the user or app, or the
* item is to be upgraded force the generic about dialog for the item.
*/
_rdfGet_aboutURL: function(item, property) {
var id = stripPrefix(item.Value, PREFIX_ITEM_URI);
@ -6509,52 +6550,55 @@ ExtensionsDataSource.prototype = {
var extensionsStrings = BundleManager.getBundle(URI_EXTENSIONS_PROPERTIES);
var itemName = this.getItemProperty(id, "name");
function getLiteral(key, string1, string2) {
function getLiteral(key, strings) {
return EM_L(extensionsStrings.formatStringFromName(key,
[string1, string2], 2));
strings, strings.length));
}
if (id in this._updateURLs && this._updateURLs[id]) {
switch (this._updateURLs[id]) {
case id:
return getLiteral("updatingMessage", [itemName]);
case nsIAddonUpdateCheckListener.STATUS_NO_UPDATE:
return getLiteral("updateNoUpdateMessage", [itemName]);
case nsIAddonUpdateCheckListener.STATUS_VERSIONINFO:
return getLiteral("updateCompatibilityMessage", [itemName]);
case nsIAddonUpdateCheckListener.STATUS_FAILURE:
return getLiteral("updateErrorMessage", [itemName]);
case nsIAddonUpdateCheckListener.STATUS_DISABLED:
return getLiteral("updateDisabledMessage", [itemName]);
case nsIAddonUpdateCheckListener.STATUS_APP_MANAGED:
return getLiteral("updateAppManagedMessage", [itemName, BundleManager.appName]);
case nsIAddonUpdateCheckListener.STATUS_READ_ONLY:
return getLiteral("updateReadOnlyMessage", []);
case nsIAddonUpdateCheckListener.STATUS_NOT_MANAGED:
return getLiteral("updateNotManagedMessage", [BundleManager.appName]);
}
}
if (id in this._updateURLs && this._updateURLs[id])
return getLiteral("updatingMessage", itemName, BundleManager.appName);
var node = this._inner.GetTarget(item, EM_R("availableUpdateURL"), true);
if (node) {
var version = this.getItemProperty(id, "availableUpdateVersion");
return getLiteral("updateAvailableMessage", itemName,
version);
return getLiteral("updateAvailableMessage", [itemName, version]);
}
var key = this.getItemProperty(id, "installLocation");
if (key in StartupCache.entries && id in StartupCache.entries[key] &&
StartupCache.entries[key][id] &&
this._em.installRequiresRestart(id, this.getItemProperty(id, "type"))) {
switch (StartupCache.entries[key][id].op) {
case OP_NEEDS_DISABLE:
return getLiteral("restartBeforeDisableMessage", itemName, BundleManager.appName);
case OP_NEEDS_ENABLE:
return getLiteral("restartBeforeEnableMessage", itemName, BundleManager.appName);
case OP_NEEDS_INSTALL:
return getLiteral("restartBeforeInstallMessage", itemName, BundleManager.appName);
case OP_NEEDS_UNINSTALL:
return getLiteral("restartBeforeUninstallMessage", itemName, BundleManager.appName);
case OP_NEEDS_UPGRADE:
return getLiteral("restartBeforeUpgradeMessage", itemName, BundleManager.appName);
}
}
if (this.getItemProperty(id, "disabled") == "true" &&
this.getItemProperty(id, "compatible") != "true") {
// See if this item was disabled because it was incompatible and if so
// show a message saying this is why it is deactivated.
// XXXben potential visual-glitch bug here with extensions whose install.rdf
// manifests state that they are incompatible but when phone home checking
// reveals that they are compatible and they are installed the
// incompatible metadata is written anyway and will remain in the ds
// until the next background update check corrects it - this means that
// when a compatible extension is installed in this manner it is
// likely that when it is disabled it will show this special-case
// error message.
return getLiteral("incompatibleExtension", BundleManager.appName, gApp.version);
var opType = this.getItemProperty(id, "opType");
switch (opType) {
case OP_NEEDS_DISABLE:
return getLiteral("restartBeforeDisableMessage", [itemName, BundleManager.appName]);
case OP_NEEDS_ENABLE:
return getLiteral("restartBeforeEnableMessage", [itemName, BundleManager.appName]);
case OP_NEEDS_INSTALL:
return getLiteral("restartBeforeInstallMessage", [itemName, BundleManager.appName]);
case OP_NEEDS_UNINSTALL:
return getLiteral("restartBeforeUninstallMessage", [itemName, BundleManager.appName]);
case OP_NEEDS_UPGRADE:
return getLiteral("restartBeforeUpgradeMessage", [itemName, BundleManager.appName]);
}
if (this.getItemProperty(id, "appDisabled") == "true" &&
this.getItemProperty(id, "compatible") != "true")
return getLiteral("incompatibleExtension", [BundleManager.appName, gApp.version]);
if (inSafeMode())
return getLiteral("disabledBySafeMode", itemName, BundleManager.appName);
return getLiteral("disabledBySafeMode", [itemName, BundleManager.appName]);
// No special state for this item, so just use the "description" property.
return this.GetTarget(item, EM_R("description"), true);
@ -6627,6 +6671,21 @@ ExtensionsDataSource.prototype = {
return this._getLocalizablePropertyValue(item, property);
},
/**
* Get the em:disabled property. This will be true if the item has a
* appDisabled or a userDisabled property that is true as long as it is not
* about to be disabled.
*/
_rdfGet_disabled: function(item, property) {
var id = stripPrefix(item.Value, PREFIX_ITEM_URI);
if ((this.getItemProperty(id, "userDisabled") == "true" ||
this.getItemProperty(id, "appDisabled") == "true") &&
this.getItemProperty(id, "opType") != OP_NEEDS_DISABLE)
return EM_L("true");
return EM_L("false");
},
/**
* Get the em:updateable property - this specifies whether the item is
* allowed to be updated