--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -66,28 +66,27 @@ XPCOMUtils.defineLazyServiceGetter(this,
Ci.nsIRDFService);
XPCOMUtils.defineLazyModuleGetter(this, "XPIInternal",
"resource://gre/modules/addons/XPIProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "XPIProvider",
"resource://gre/modules/addons/XPIProvider.jsm");
-/* globals AddonInternal, BOOTSTRAP_REASONS, KEY_APP_SYSTEM_ADDONS, KEY_APP_SYSTEM_DEFAULTS, KEY_APP_TEMPORARY, TEMPORARY_ADDON_SUFFIX, TOOLKIT_ID, XPIDatabase, XPIStates, applyBlocklistChanges, getExternalType, isTheme, isUsableAddon, isWebExtension, recordAddonTelemetry */
+/* globals AddonInternal, BOOTSTRAP_REASONS, KEY_APP_SYSTEM_ADDONS, KEY_APP_SYSTEM_DEFAULTS, KEY_APP_TEMPORARY, TEMPORARY_ADDON_SUFFIX, TOOLKIT_ID, XPIDatabase, XPIStates, getExternalType, isTheme, isUsableAddon, isWebExtension, recordAddonTelemetry */
const XPI_INTERNAL_SYMBOLS = [
"AddonInternal",
"BOOTSTRAP_REASONS",
"KEY_APP_SYSTEM_ADDONS",
"KEY_APP_SYSTEM_DEFAULTS",
"KEY_APP_TEMPORARY",
"TEMPORARY_ADDON_SUFFIX",
"TOOLKIT_ID",
"XPIDatabase",
"XPIStates",
- "applyBlocklistChanges",
"getExternalType",
"isTheme",
"isUsableAddon",
"isWebExtension",
"recordAddonTelemetry",
];
for (let name of XPI_INTERNAL_SYMBOLS) {
@@ -850,16 +849,17 @@ var loadManifestFromDir = async function
addon = await loadFromRDF(uri);
}
addon._sourceBundle = aDir.clone();
addon._installLocation = aInstallLocation;
addon.size = getFileSize(aDir);
addon.signedState = await verifyDirSignedState(aDir, addon)
.then(({signedState}) => signedState);
+ addon.updateBlocklistState();
addon.appDisabled = !isUsableAddon(addon);
defineSyncGUID(addon);
return addon;
};
/**
@@ -935,16 +935,17 @@ var loadManifestFromZipReader = async fu
if (!gIDTest.test(addon.id)) {
throw new Error(`Webextension is signed with an invalid id (${addon.id})`);
}
}
if (!addon.id && aInstallLocation.name == KEY_APP_TEMPORARY) {
addon.id = generateTemporaryInstallID(aZipReader.file);
}
}
+ addon.updateBlocklistState();
addon.appDisabled = !isUsableAddon(addon);
defineSyncGUID(addon);
return addon;
};
/**
@@ -2132,18 +2133,17 @@ this.LocalAddonInstall = class extends A
return;
}
let addon = await new Promise(resolve => {
XPIDatabase.getVisibleAddonForID(this.addon.id, resolve);
});
this.existingAddon = addon;
- if (addon)
- applyBlocklistChanges(addon, this.addon);
+ this.addon.updateBlocklistState({oldAddon: this.existingAddon});
this.addon.updateDate = Date.now();
this.addon.installDate = addon ? addon.installDate : this.addon.updateDate;
if (!this.addon.isCompatible) {
this.state = AddonManager.STATE_CHECKING;
await new Promise(resolve => {
new UpdateChecker(this.addon, {
@@ -2538,20 +2538,20 @@ this.DownloadAddonInstall = class extend
this.existingAddon = aAddon;
this.state = AddonManager.STATE_DOWNLOADED;
this.addon.updateDate = Date.now();
if (this.existingAddon) {
this.addon.existingAddonID = this.existingAddon.id;
this.addon.installDate = this.existingAddon.installDate;
- applyBlocklistChanges(this.existingAddon, this.addon);
} else {
this.addon.installDate = this.addon.updateDate;
}
+ this.addon.updateBlocklistState({oldAddon: this.existingAddon});
if (AddonManagerPrivate.callInstallListeners("onDownloadEnded",
this.listeners,
this.wrapper)) {
// If a listener changed our state then do not proceed with the install
if (this.state != AddonManager.STATE_DOWNLOADED)
return;
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -184,17 +184,17 @@ const STARTUP_MTIME_SCOPES = [KEY_APP_GL
const NOTIFICATION_FLUSH_PERMISSIONS = "flush-pending-permissions";
const XPI_PERMISSION = "install";
const TOOLKIT_ID = "toolkit@mozilla.org";
const XPI_SIGNATURE_CHECK_PERIOD = 24 * 60 * 60;
-XPCOMUtils.defineConstant(this, "DB_SCHEMA", 21);
+XPCOMUtils.defineConstant(this, "DB_SCHEMA", 22);
XPCOMUtils.defineLazyPreferenceGetter(this, "ALLOW_NON_MPC", PREF_ALLOW_NON_MPC);
const NOTIFICATION_TOOLBOX_CONNECTION_CHANGE = "toolbox-connection-change";
// Properties that exist in the install manifest
const PROP_LOCALE_SINGLE = ["name", "description", "creator", "homepageURL"];
const PROP_LOCALE_MULTI = ["developers", "translators", "contributors"];
@@ -328,17 +328,16 @@ function loadLazyObjects() {
BOOTSTRAP_REASONS,
DB_SCHEMA,
AddonInternal,
XPIProvider,
XPIStates,
syncLoadManifestFromFile,
isUsableAddon,
recordAddonTelemetry,
- applyBlocklistChanges,
flushChromeCaches,
descriptorToPath,
});
Services.scriptloader.loadSubScript(uri, scope);
for (let name of LAZY_OBJECTS) {
delete gGlobalScope[name];
@@ -755,67 +754,16 @@ SafeInstallOperation.prototype = {
}
while (this._createdDirs.length > 0)
recursiveRemove(this._createdDirs.pop());
}
};
/**
- * Sets the userDisabled and softDisabled properties of an add-on based on what
- * values those properties had for a previous instance of the add-on. The
- * previous instance may be a previous install or in the case of an application
- * version change the same add-on.
- *
- * NOTE: this may modify aNewAddon in place; callers should save the database if
- * necessary
- *
- * @param aOldAddon
- * The previous instance of the add-on
- * @param aNewAddon
- * The new instance of the add-on
- * @param aAppVersion
- * The optional application version to use when checking the blocklist
- * or undefined to use the current application
- * @param aPlatformVersion
- * The optional platform version to use when checking the blocklist or
- * undefined to use the current platform
- */
-function applyBlocklistChanges(aOldAddon, aNewAddon, aOldAppVersion,
- aOldPlatformVersion) {
- // Copy the properties by default
- aNewAddon.userDisabled = aOldAddon.userDisabled;
- aNewAddon.softDisabled = aOldAddon.softDisabled;
-
- let oldBlocklistState = Blocklist.getAddonBlocklistState(aOldAddon.wrapper,
- aOldAppVersion,
- aOldPlatformVersion);
- let newBlocklistState = Blocklist.getAddonBlocklistState(aNewAddon.wrapper);
-
- // If the blocklist state hasn't changed then the properties don't need to
- // change
- if (newBlocklistState == oldBlocklistState)
- return;
-
- if (newBlocklistState == Blocklist.STATE_SOFTBLOCKED) {
- if (aNewAddon.type != "theme") {
- // The add-on has become softblocked, set softDisabled if it isn't already
- // userDisabled
- aNewAddon.softDisabled = !aNewAddon.userDisabled;
- } else {
- // Themes just get userDisabled to switch back to the default theme
- aNewAddon.userDisabled = true;
- }
- } else {
- // If the new add-on is not softblocked then it cannot be softDisabled
- aNewAddon.softDisabled = false;
- }
-}
-
-/**
* Evaluates whether an add-on is allowed to run in safe mode.
*
* @param aAddon
* The add-on to check
* @return true if the add-on should run in safe mode
*/
function canRunInSafeMode(aAddon) {
// Even though the updated system add-ons aren't generally run in safe mode we
@@ -4544,17 +4492,17 @@ this.XPIProvider = {
AddonManagerPrivate.callAddonListeners("onEnabling", wrapper,
needsRestart);
}
if (!needsRestart) {
XPIDatabase.updateAddonActive(aAddon, !isDisabled);
if (isDisabled) {
- if (aAddon.bootstrap) {
+ if (aAddon.bootstrap && this.activeAddons.has(aAddon.id)) {
this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "shutdown",
BOOTSTRAP_REASONS.ADDON_DISABLE);
this.unloadBootstrapScope(aAddon.id);
}
AddonManagerPrivate.callAddonListeners("onDisabled", wrapper);
} else {
if (aAddon.bootstrap) {
this.callBootstrapMethod(aAddon, aAddon._sourceBundle, "startup",
@@ -4814,16 +4762,18 @@ function AddonInternal() {
AddonInternal.prototype = {
_selectedLocale: null,
_hasResourceCache: null,
active: false,
visible: false,
userDisabled: false,
appDisabled: false,
softDisabled: false,
+ blocklistState: Ci.nsIBlocklistService.STATE_NOT_BLOCKED,
+ blocklistURL: null,
sourceURI: null,
releaseNotesURI: null,
foreignInstall: false,
seen: true,
skinnable: false,
/**
* @property {Array<string>} dependencies
@@ -4983,32 +4933,77 @@ AddonInternal.prototype = {
if (targetApp.id == Services.appinfo.ID)
return targetApp;
if (targetApp.id == TOOLKIT_ID)
app = targetApp;
}
return app;
},
- get blocklistState() {
- let staticItem = findMatchingStaticBlocklistItem(this);
- if (staticItem)
- return staticItem.level;
-
- return Blocklist.getAddonBlocklistState(this.wrapper);
- },
-
- get blocklistURL() {
+ findBlocklistEntry() {
let staticItem = findMatchingStaticBlocklistItem(this);
if (staticItem) {
let url = Services.urlFormatter.formatURLPref("extensions.blocklist.itemURL");
- return url.replace(/%blockID%/g, staticItem.blockID);
- }
-
- return Blocklist.getAddonBlocklistURL(this.wrapper);
+ return {
+ state: staticItem.level,
+ url: url.replace(/%blockID%/g, staticItem.blockID)
+ };
+ }
+
+ return Blocklist.getAddonBlocklistEntry(this.wrapper);
+ },
+
+ updateBlocklistState(options = {}) {
+ let {applySoftBlock = true, oldAddon = null, updateDatabase = true} = options;
+
+ if (oldAddon) {
+ this.userDisabled = oldAddon.userDisabled;
+ this.softDisabled = oldAddon.softDisabled;
+ this.blocklistState = oldAddon.blocklistState;
+ }
+ let oldState = this.blocklistState;
+
+ let entry = this.findBlocklistEntry();
+ let newState = entry ? entry.state : Blocklist.STATE_NOT_BLOCKED;
+
+ this.blocklistState = newState;
+ this.blocklistURL = entry && entry.url;
+
+ let userDisabled, softDisabled;
+ // After a blocklist update, the blocklist service manually applies
+ // new soft blocks after displaying a UI, in which cases we need to
+ // skip updating it here.
+ if (applySoftBlock && oldState != newState) {
+ if (newState == Blocklist.STATE_SOFTBLOCKED) {
+ if (this.type == "theme") {
+ userDisabled = true;
+ } else {
+ softDisabled = !this.userDisabled;
+ }
+ } else {
+ softDisabled = false;
+ }
+ }
+
+ if (this.inDatabase && updateDatabase) {
+ XPIProvider.updateAddonDisabledState(this, userDisabled, softDisabled);
+
+ XPIDatabase.setAddonProperties(this, {
+ blocklistState: this.blocklistState,
+ blocklistURL: this.blocklistURL,
+ });
+ } else {
+ this.appDisabled = !isUsableAddon(this);
+ if (userDisabled !== undefined) {
+ this.userDisabled = userDisabled;
+ }
+ if (softDisabled !== undefined) {
+ this.softDisabled = softDisabled;
+ }
+ }
},
applyCompatibilityUpdate(aUpdate, aSyncCompatibility) {
for (let targetApp of this.targetApplications) {
for (let updateTarget of aUpdate.targetApplications) {
if (targetApp.id == updateTarget.id && (aSyncCompatibility ||
Services.vc.compare(targetApp.maxVersion, updateTarget.maxVersion) < 0)) {
targetApp.minVersion = updateTarget.minVersion;
@@ -5418,16 +5413,20 @@ AddonWrapper.prototype = {
let addon = addonFor(this);
if (!addon.active)
return false;
if (!Services.appinfo.inSafeMode)
return true;
return addon.bootstrap && canRunInSafeMode(addon);
},
+ updateBlocklistState(applySoftBlock = true) {
+ addonFor(this).updateBlocklistState({applySoftBlock});
+ },
+
get userDisabled() {
let addon = addonFor(this);
return addon.softDisabled || addon.userDisabled;
},
set userDisabled(val) {
let addon = addonFor(this);
if (val == this.userDisabled) {
return val;
@@ -6840,17 +6839,16 @@ this.XPIInternal = {
AddonInternal,
BOOTSTRAP_REASONS,
KEY_APP_SYSTEM_ADDONS,
KEY_APP_SYSTEM_DEFAULTS,
KEY_APP_TEMPORARY,
TEMPORARY_ADDON_SUFFIX,
TOOLKIT_ID,
XPIStates,
- applyBlocklistChanges,
getExternalType,
isTheme,
isUsableAddon,
isWebExtension,
recordAddonTelemetry,
get XPIDatabase() { return gGlobalScope.XPIDatabase; },
};
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -2,17 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// These are injected from XPIProvider.jsm
/* globals ADDON_SIGNING, SIGNED_TYPES, BOOTSTRAP_REASONS, DB_SCHEMA,
AddonInternal, XPIProvider, XPIStates, syncLoadManifestFromFile,
- isUsableAddon, recordAddonTelemetry, applyBlocklistChanges,
+ isUsableAddon, recordAddonTelemetry,
flushChromeCaches, descriptorToPath */
var Cc = Components.classes;
var Ci = Components.interfaces;
var Cr = Components.results;
var Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -71,21 +71,24 @@ const PROP_JSON_FIELDS = ["id", "syncGUI
"defaultLocale", "visible", "active", "userDisabled",
"appDisabled", "pendingUninstall", "installDate",
"updateDate", "applyBackgroundUpdates", "bootstrap", "path",
"skinnable", "size", "sourceURI", "releaseNotesURI",
"softDisabled", "foreignInstall", "hasBinaryComponents",
"strictCompatibility", "locales", "targetApplications",
"targetPlatforms", "multiprocessCompatible", "signedState",
"seen", "dependencies", "hasEmbeddedWebExtension", "mpcOptedOut",
- "userPermissions", "icons", "iconURL", "icon64URL"];
+ "userPermissions", "icons", "iconURL", "icon64URL",
+ "blocklistState", "blocklistURL"];
// Time to wait before async save of XPI JSON database, in milliseconds
const ASYNC_SAVE_DELAY_MS = 20;
+const SCHEMA_BLOCKLIST_VERSION = 22;
+
/**
* Asynchronously fill in the _repositoryAddon field for one addon
*/
function getRepositoryAddon(aAddon, aCallback) {
if (!aAddon) {
aCallback(aAddon);
return;
}
@@ -1319,23 +1322,24 @@ this.XPIDatabaseReconcile = {
updateMetadata(aInstallLocation, aOldAddon, aAddonState, aNewAddon) {
logger.debug("Add-on " + aOldAddon.id + " modified in " + aInstallLocation.name);
try {
// If there isn't an updated install manifest for this add-on then load it.
if (!aNewAddon) {
let file = new nsIFile(aAddonState.path);
aNewAddon = syncLoadManifestFromFile(file, aInstallLocation);
- applyBlocklistChanges(aOldAddon, aNewAddon);
// Carry over any pendingUninstall state to add-ons modified directly
// in the profile. This is important when the attempt to remove the
// add-on in processPendingFileChanges failed and caused an mtime
// change to the add-ons files.
aNewAddon.pendingUninstall = aOldAddon.pendingUninstall;
+
+ aNewAddon.updateBlocklistState({oldAddon: aOldAddon});
}
// The ID in the manifest that was loaded must match the ID of the old
// add-on.
if (aNewAddon.id != aOldAddon.id)
throw new Error("Incorrect id in install manifest for existing add-on " + aOldAddon.id);
} catch (e) {
logger.warn("updateMetadata: Add-on " + aOldAddon.id + " is invalid", e);
@@ -1425,19 +1429,17 @@ this.XPIDatabaseReconcile = {
let remove = ["syncGUID", "foreignInstall", "visible", "active",
"userDisabled", "applyBackgroundUpdates", "sourceURI",
"releaseNotesURI", "targetApplications"];
let props = PROP_JSON_FIELDS.filter(a => !remove.includes(a));
copyProperties(manifest, props, aOldAddon);
}
- // This updates the addon's JSON cached data in place
- applyBlocklistChanges(aOldAddon, aOldAddon, aOldAppVersion,
- aOldPlatformVersion);
+ aOldAddon.updateBlocklistState({updateDatabase: false});
aOldAddon.appDisabled = !isUsableAddon(aOldAddon);
return aOldAddon;
},
/**
* Compares the add-ons that are currently installed to those that were
* known to be installed when the application last ran and applies any
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -375,16 +375,72 @@ Blocklist.prototype = {
getAddonBlocklistState(addon, appVersion, toolkitVersion) {
if (!this._isBlocklistLoaded())
this._loadBlocklist();
return this._getAddonBlocklistState(addon, this._addonEntries,
appVersion, toolkitVersion);
},
/**
+ * Returns a matching blocklist entry for the given add-on, if one
+ * exists.
+ *
+ * @param id
+ * The ID of the item to get the blocklist state for.
+ * @param version
+ * The version of the item to get the blocklist state for.
+ * @param addonEntries
+ * The add-on blocklist entries to compare against.
+ * @param appVersion
+ * The application version to compare to, will use the current
+ * version if null.
+ * @param toolkitVersion
+ * The toolkit version to compare to, will use the current version if
+ * null.
+ * @returns A blocklist entry for this item, with `state` and `url`
+ * properties indicating the block state and URL, if there is
+ * a matching blocklist entry, or null otherwise.
+ */
+ _getAddonBlocklistEntry(addon, addonEntries, appVersion, toolkitVersion) {
+ if (!gBlocklistEnabled)
+ return null;
+
+ // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't).
+ if (!appVersion && !gApp.version)
+ return null;
+
+ if (!appVersion)
+ appVersion = gApp.version;
+ if (!toolkitVersion)
+ toolkitVersion = gApp.platformVersion;
+
+ var blItem = this._findMatchingAddonEntry(addonEntries, addon);
+ if (!blItem)
+ return null;
+
+ for (let currentblItem of blItem.versions) {
+ if (currentblItem.includesItem(addon.version, appVersion, toolkitVersion)) {
+ return {
+ state: (currentblItem.severity >= gBlocklistLevel ?
+ Ci.nsIBlocklistService.STATE_BLOCKED : Ci.nsIBlocklistService.STATE_SOFTBLOCKED),
+ url: blItem.blockID && this._createBlocklistURL(blItem.blockID),
+ };
+ }
+ }
+ return null;
+ },
+
+ getAddonBlocklistEntry(addon, appVersion, toolkitVersion) {
+ if (!this._isBlocklistLoaded())
+ this._loadBlocklist();
+ return this._getAddonBlocklistEntry(addon, this._addonEntries,
+ appVersion, toolkitVersion);
+ },
+
+ /**
* Private version of getAddonBlocklistState that allows the caller to pass in
* the add-on blocklist entries to compare against.
*
* @param id
* The ID of the item to get the blocklist state for.
* @param version
* The version of the item to get the blocklist state for.
* @param addonEntries
@@ -394,37 +450,19 @@ Blocklist.prototype = {
* version if null.
* @param toolkitVersion
* The toolkit version to compare to, will use the current version if
* null.
* @returns The blocklist state for the item, one of the STATE constants as
* defined in nsIBlocklistService.
*/
_getAddonBlocklistState(addon, addonEntries, appVersion, toolkitVersion) {
- if (!gBlocklistEnabled)
- return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
-
- // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't).
- if (!appVersion && !gApp.version)
- return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
-
- if (!appVersion)
- appVersion = gApp.version;
- if (!toolkitVersion)
- toolkitVersion = gApp.platformVersion;
-
- var blItem = this._findMatchingAddonEntry(addonEntries, addon);
- if (!blItem)
- return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
-
- for (let currentblItem of blItem.versions) {
- if (currentblItem.includesItem(addon.version, appVersion, toolkitVersion))
- return currentblItem.severity >= gBlocklistLevel ? Ci.nsIBlocklistService.STATE_BLOCKED :
- Ci.nsIBlocklistService.STATE_SOFTBLOCKED;
- }
+ let entry = this._getAddonBlocklistEntry(addon, addonEntries, appVersion, toolkitVersion);
+ if (entry)
+ return entry.state;
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
},
/**
* Returns the set of prefs of the add-on stored in the blocklist file
* (probably to revert them on disabling).
* @param addon
* The add-on whose to-be-reset prefs are to be found.
@@ -470,27 +508,21 @@ Blocklist.prototype = {
return entry;
}
}
return null;
},
/* See nsIBlocklistService */
getAddonBlocklistURL(addon, appVersion, toolkitVersion) {
- if (!gBlocklistEnabled)
- return "";
-
if (!this._isBlocklistLoaded())
this._loadBlocklist();
- let blItem = this._findMatchingAddonEntry(this._addonEntries, addon);
- if (!blItem || !blItem.blockID)
- return null;
-
- return this._createBlocklistURL(blItem.blockID);
+ let entry = this._getAddonBlocklistEntry(addon, this._addonEntries);
+ return entry && entry.url;
},
_createBlocklistURL(id) {
let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL);
url = url.replace(/%blockID%/g, id);
return url;
},
@@ -1302,33 +1334,32 @@ Blocklist.prototype = {
// A helper function that reverts the prefs passed to default values.
function resetPrefs(prefs) {
for (let pref of prefs)
gPref.clearUserPref(pref);
}
const types = ["extension", "theme", "locale", "dictionary", "service"];
AddonManager.getAddonsByTypes(types, addons => {
for (let addon of addons) {
- let oldState = Ci.nsIBlocklistService.STATE_NOTBLOCKED;
- if (oldAddonEntries)
- oldState = this._getAddonBlocklistState(addon, oldAddonEntries);
- let state = this.getAddonBlocklistState(addon);
+ let oldState = addon.blocklistState;
+ addon.updateBlocklistState(false);
+ let state = addon.blocklistState;
LOG("Blocklist state for " + addon.id + " changed from " +
oldState + " to " + state);
// We don't want to re-warn about add-ons
if (state == oldState)
continue;
if (state === Ci.nsIBlocklistService.STATE_BLOCKED) {
// It's a hard block. We must reset certain preferences.
let prefs = this._getAddonPrefs(addon);
resetPrefs(prefs);
- }
+ }
// Ensure that softDisabled is false if the add-on is not soft blocked
if (state != Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
addon.softDisabled = false;
// Don't warn about add-ons becoming unblocked.
if (state == Ci.nsIBlocklistService.STATE_NOT_BLOCKED)
continue;
@@ -1359,18 +1390,16 @@ Blocklist.prototype = {
icon: addon.iconURL,
disable: false,
blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
item: addon,
url: this.getAddonBlocklistURL(addon),
});
}
- AddonManagerPrivate.updateAddonAppDisabledStates();
-
var phs = Cc["@mozilla.org/plugin/host;1"].
getService(Ci.nsIPluginHost);
var plugins = phs.getPluginTags();
for (let plugin of plugins) {
let oldState = -1;
if (oldPluginEntries)
oldState = this._getPluginBlocklistState(plugin, oldPluginEntries);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js
@@ -83,16 +83,27 @@ var BlocklistService = {
getAddonBlocklistState(aAddon, aAppVersion, aToolkitVersion) {
if (aAddon.id == "bug335238_3@tests.mozilla.org")
return Ci.nsIBlocklistService.STATE_SOFTBLOCKED;
if (aAddon.id == "bug335238_4@tests.mozilla.org")
return Ci.nsIBlocklistService.STATE_BLOCKED;
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
},
+ getAddonBlocklistEntry(aAddon, aAppVersion, aToolkitVersion) {
+ let state = this.getAddonBlocklistState(aAddon, aAppVersion, aToolkitVersion);
+ if (state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
+ return {
+ state,
+ url: "http://example.com/",
+ };
+ }
+ return null;
+ },
+
getPluginBlocklistState(aPlugin, aVersion, aAppVersion, aToolkitVersion) {
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
},
isAddonBlocklisted(aAddon, aAppVersion, aToolkitVersion) {
return this.getAddonBlocklistState(aAddon, aAppVersion, aToolkitVersion) ==
Ci.nsIBlocklistService.STATE_BLOCKED;
},
--- a/xpcom/system/nsIBlocklistService.idl
+++ b/xpcom/system/nsIBlocklistService.idl
@@ -88,16 +88,36 @@ interface nsIBlocklistService : nsISuppo
* The addon item whose url is required.
* @returns The URL of the description page.
*/
AString getAddonBlocklistURL(in jsval addon,
[optional] in AString appVersion,
[optional] in AString toolkitVersion);
/**
+ * Returns the blocklist entry, as an object with `state` and `url`
+ * properties, if a blocklist entry for the add-on exists, or null
+ * othereise.
+
+ * @param addon
+ * The addon object to match.
+ * @param appVersion
+ * The version of the application we are checking in the blocklist.
+ * If this parameter is null, the version of the running application
+ * is used.
+ * @param toolkitVersion
+ * The version of the toolkit we are checking in the blocklist.
+ * If this parameter is null, the version of the running toolkit
+ * is used.
+ */
+ jsval getAddonBlocklistEntry(in jsval addon,
+ [optional] in AString appVersion,
+ [optional] in AString toolkitVersion);
+
+ /**
* Determine the blocklist web page of a plugin.
* @param plugin
* The blocked plugin that we are determining the web page for.
* @returns The URL of the description page.
*/
AString getPluginBlocklistURL(in nsIPluginTag plugin);
/**