--- a/js/xpconnect/loader/XPCOMUtils.jsm
+++ b/js/xpconnect/loader/XPCOMUtils.jsm
@@ -253,17 +253,20 @@ var XPCOMUtils = {
* @param aInterfaceName
* The name of the interface to query the service to.
*/
defineLazyServiceGetter: function XPCU_defineLazyServiceGetter(aObject, aName,
aContract,
aInterfaceName)
{
this.defineLazyGetter(aObject, aName, function XPCU_serviceLambda() {
- return Cc[aContract].getService(Ci[aInterfaceName]);
+ if (aInterfaceName) {
+ return Cc[aContract].getService(Ci[aInterfaceName]);
+ }
+ return Cc[aContract].getService().wrappedJSObject;
});
},
/**
* Defines a lazy service getter on a specified object for each
* property in the given object.
*
* @param aObject
--- a/mobile/android/components/BlocklistPrompt.js
+++ b/mobile/android/components/BlocklistPrompt.js
@@ -5,17 +5,19 @@
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
// -----------------------------------------------------------------------
// BlocklistPrompt Service
// -----------------------------------------------------------------------
-function BlocklistPrompt() { }
+function BlocklistPrompt() {
+ this.wrappedJSObject = this;
+}
BlocklistPrompt.prototype = {
prompt: function(aAddons, aCount) {
let win = Services.wm.getMostRecentWindow("navigator:browser");
if (win.ExtensionsView.visible) {
win.ExtensionsView.showRestart("blocked");
} else {
let bundle = Services.strings.createBundle("chrome://browser/locale/browser.properties");
@@ -44,12 +46,12 @@ BlocklistPrompt.prototype = {
for (let i = 0; i < aAddons.length; i++) {
if (aAddons[i].item instanceof Ci.nsIPluginTag)
aAddons[i].item.disabled = true;
else
aAddons[i].item.userDisabled = true;
}
},
classID: Components.ID("{4e6ea350-b09a-11df-94e2-0800200c9a66}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIBlocklistPrompt])
+ QueryInterface: XPCOMUtils.generateQI([])
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([BlocklistPrompt]);
--- a/toolkit/modules/Services.jsm
+++ b/toolkit/modules/Services.jsm
@@ -87,17 +87,17 @@ var initTable = {
wm: ["@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator"],
ww: ["@mozilla.org/embedcomp/window-watcher;1", "nsIWindowWatcher"],
startup: ["@mozilla.org/toolkit/app-startup;1", "nsIAppStartup"],
sysinfo: ["@mozilla.org/system-info;1", "nsIPropertyBag2"],
clipboard: ["@mozilla.org/widget/clipboard;1", "nsIClipboard"],
DOMRequest: ["@mozilla.org/dom/dom-request-service;1", "nsIDOMRequestService"],
focus: ["@mozilla.org/focus-manager;1", "nsIFocusManager"],
uriFixup: ["@mozilla.org/docshell/urifixup;1", "nsIURIFixup"],
- blocklist: ["@mozilla.org/extensions/blocklist;1", "nsIBlocklistService"],
+ blocklist: ["@mozilla.org/extensions/blocklist;1"],
netUtils: ["@mozilla.org/network/util;1", "nsINetUtil"],
loadContextInfo: ["@mozilla.org/load-context-info-factory;1", "nsILoadContextInfoFactory"],
qms: ["@mozilla.org/dom/quota-manager-service;1", "nsIQuotaManagerService"],
};
if (AppConstants.platform == "android") {
initTable.androidBridge = ["@mozilla.org/android/bridge;1", "nsIAndroidBridge"];
}
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
@@ -103,32 +103,46 @@ var MockAsyncShutdown = {
AMscope.AsyncShutdown = MockAsyncShutdown;
class MockBlocklist {
constructor(addons) {
if (ChromeUtils.getClassName(addons) === "Object") {
addons = new Map(Object.entries(addons));
}
this.addons = addons;
+ this.wrappedJSObject = this;
+
+ // Copy blocklist constants.
+ for (let [k, v] of Object.entries(Ci.nsIBlocklistService)) {
+ if (typeof v === "number") {
+ this[k] = v;
+ }
+ }
}
get contractID() {
return "@mozilla.org/extensions/blocklist;1";
}
+ _reLazifyService() {
+ XPCOMUtils.defineLazyServiceGetter(Services, "blocklist", this.contractID);
+ }
+
register() {
this.originalCID = MockRegistrar.register(this.contractID, this);
+ this._reLazifyService();
}
unregister() {
MockRegistrar.unregister(this.originalCID);
+ this._reLazifyService();
}
getAddonBlocklistState(addon, appVersion, toolkitVersion) {
- return this.addons.get(addon.id, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
+ return this.addons.get(addon.id) || Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
}
async getAddonBlocklistEntry(addon, appVersion, toolkitVersion) {
await Promise.resolve();
let state = this.getAddonBlocklistState(addon, appVersion, toolkitVersion);
if (state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
return {
state,
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -38,17 +38,16 @@ XPCOMUtils.defineLazyModuleGetters(this,
XPIInstall: "resource://gre/modules/addons/XPIInstall.jsm",
loadManifestFromFile: "resource://gre/modules/addons/XPIInstall.jsm",
verifyBundleSignedState: "resource://gre/modules/addons/XPIInstall.jsm",
});
const {nsIBlocklistService} = Ci;
XPCOMUtils.defineLazyServiceGetters(this, {
- Blocklist: ["@mozilla.org/extensions/blocklist;1", "nsIBlocklistService"],
AddonPolicyService: ["@mozilla.org/addons/policy-service;1", "nsIAddonPolicyService"],
aomStartup: ["@mozilla.org/addons/addon-manager-startup;1", "amIAddonManagerStartup"],
});
XPCOMUtils.defineLazyGetter(this, "gTextDecoder", () => {
return new TextDecoder();
});
@@ -4498,41 +4497,41 @@ AddonInternal.prototype = {
if (staticItem) {
let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL);
return {
state: staticItem.level,
url: url.replace(/%blockID%/g, staticItem.blockID)
};
}
- return Blocklist.getAddonBlocklistEntry(this.wrapper);
+ return Services.blocklist.getAddonBlocklistEntry(this.wrapper);
},
async 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 = await this.findBlocklistEntry();
- let newState = entry ? entry.state : Blocklist.STATE_NOT_BLOCKED;
+ let newState = entry ? entry.state : Services.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 (newState == Services.blocklist.STATE_SOFTBLOCKED) {
if (this.type == "theme") {
userDisabled = true;
} else {
softDisabled = !this.userDisabled;
}
} else {
softDisabled = false;
}
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -17,20 +17,16 @@ XPCOMUtils.defineLazyModuleGetters(this,
AddonManagerPrivate: "resource://gre/modules/AddonManager.jsm",
AddonRepository: "resource://gre/modules/addons/AddonRepository.jsm",
DeferredTask: "resource://gre/modules/DeferredTask.jsm",
FileUtils: "resource://gre/modules/FileUtils.jsm",
OS: "resource://gre/modules/osfile.jsm",
Services: "resource://gre/modules/Services.jsm",
});
-XPCOMUtils.defineLazyServiceGetter(this, "Blocklist",
- "@mozilla.org/extensions/blocklist;1",
- Ci.nsIBlocklistService);
-
ChromeUtils.import("resource://gre/modules/Log.jsm");
const LOGGER_ID = "addons.xpi-utils";
const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile",
"initWithPath");
// Create a new logger for use by the Addons XPI Provider Utils
// (Requires AddonManager.jsm)
@@ -1541,17 +1537,17 @@ this.XPIDatabaseReconcile = {
if (currentAddon.type == "webextension-theme")
currentAddon.userDisabled = !isActive;
// If the add-on wasn't active and it isn't already disabled in some way
// then it was probably either softDisabled or userDisabled
if (!isActive && !currentAddon.disabled) {
// If the add-on is softblocked then assume it is softDisabled
- if (currentAddon.blocklistState == Blocklist.STATE_SOFTBLOCKED)
+ if (currentAddon.blocklistState == Services.blocklist.STATE_SOFTBLOCKED)
currentAddon.softDisabled = true;
else
currentAddon.userDisabled = true;
}
} else {
// This is a new install
if (currentAddon.foreignInstall)
AddonManagerPrivate.addStartupChange(AddonManager.STARTUP_CHANGE_INSTALLED, id);
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -1,16 +1,18 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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";
+/* eslint "valid-jsdoc": [2, {requireReturn: false}] */
+
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
try {
// AddonManager.jsm doesn't allow itself to be imported in the child
// process. We're used in the child process (for now), so guard against
// this.
@@ -71,16 +73,41 @@ const VULNERABILITYSTATUS_UPDATE_AVAILAB
const VULNERABILITYSTATUS_NO_UPDATE = 2;
const EXTENSION_BLOCK_FILTERS = ["id", "name", "creator", "homepageURL", "updateURL"];
var gLoggingEnabled = null;
var gBlocklistEnabled = true;
var gBlocklistLevel = DEFAULT_LEVEL;
+/**
+ * @class nsIBlocklistPrompt
+ *
+ * nsIBlocklistPrompt is used, if available, by the default implementation of
+ * nsIBlocklistService to display a confirmation UI to the user before blocking
+ * extensions/plugins.
+ */
+/**
+ * @method prompt
+ *
+ * Prompt the user about newly blocked addons. The prompt is then resposible
+ * for soft-blocking any addons that need to be afterwards
+ *
+ * @param {object[]} aAddons
+ * An array of addons and plugins that are blocked. These are javascript
+ * objects with properties:
+ * name - the plugin or extension name,
+ * version - the version of the extension or plugin,
+ * icon - the plugin or extension icon,
+ * disable - can be used by the nsIBlocklistPrompt to allows users to decide
+ * whether a soft-blocked add-on should be disabled,
+ * blocked - true if the item is hard-blocked, false otherwise,
+ * item - the nsIPluginTag or Addon object
+ */
+
// From appinfo in Services.jsm. It is not possible to use the one in
// Services.jsm since it will not successfully QueryInterface nsIXULAppInfo in
// xpcshell tests due to other code calling Services.appinfo before the
// nsIXULAppInfo is created by the tests.
XPCOMUtils.defineLazyGetter(this, "gApp", function() {
// eslint-disable-next-line mozilla/use-services
let appinfo = Cc["@mozilla.org/xre/app-info;1"]
.getService(Ci.nsIXULRuntime);
@@ -131,18 +158,18 @@ XPCOMUtils.defineLazyGetter(this, "gOSVe
}
osVersion = encodeURIComponent(osVersion);
}
return osVersion;
});
/**
* Logs a string to the error console.
- * @param string
- * The string to write to the error console..
+ * @param {string} string
+ * The string to write to the error console..
*/
function LOG(string) {
if (gLoggingEnabled) {
dump("*** " + string + "\n");
Services.console.logStringMessage(string);
}
}
@@ -160,16 +187,21 @@ function restartApp() {
Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
}
/**
* Checks whether this blocklist element is valid for the current OS and ABI.
* If the element has an "os" attribute then the current OS must appear in
* its comma separated list for the element to be valid. Similarly for the
* xpcomabi attribute.
+ *
+ * @param {Element} blocklistElement
+ * The blocklist element from an XML blocklist.
+ * @returns {bool}
+ * Whether the entry matches the current OS.
*/
function matchesOSABI(blocklistElement) {
if (blocklistElement.hasAttribute("os")) {
var choices = blocklistElement.getAttribute("os").split(",");
if (choices.length > 0 && !choices.includes(gApp.OS))
return false;
}
@@ -181,34 +213,36 @@ function matchesOSABI(blocklistElement)
return true;
}
/**
* Gets the current value of the locale. It's possible for this preference to
* be localized, so we have to do a little extra work here. Similar code
* exists in nsHttpHandler.cpp when building the UA string.
+ *
+ * @returns {string} The current requested locale.
*/
function getLocale() {
return Services.locale.getRequestedLocale();
}
/* Get the distribution pref values, from defaults only */
function getDistributionPrefValue(aPrefName) {
return Services.prefs.getDefaultBranch(null).getCharPref(aPrefName, "default");
}
/**
* Parse a string representation of a regular expression. Needed because we
* use the /pattern/flags form (because it's detectable), which is only
* supported as a literal in JS.
*
- * @param aStr
+ * @param {string} aStr
* String representation of regexp
- * @return RegExp instance
+ * @return {RegExp} instance
*/
function parseRegExp(aStr) {
let lastSlash = aStr.lastIndexOf("/");
let pattern = aStr.slice(1, lastSlash);
let flags = aStr.slice(lastSlash + 1);
return new RegExp(pattern, flags);
}
@@ -226,16 +260,24 @@ function Blocklist() {
gBlocklistLevel = Math.min(Services.prefs.getIntPref(PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL),
MAX_BLOCK_LEVEL);
Services.prefs.addObserver("extensions.blocklist.", this);
Services.prefs.addObserver(PREF_EM_LOGGING_ENABLED, this);
this.wrappedJSObject = this;
}
Blocklist.prototype = {
+ STATE_NOT_BLOCKED: Ci.nsIBlocklistService.STATE_NOT_BLOCKED,
+ STATE_SOFTBLOCKED: Ci.nsIBlocklistService.STATE_SOFTBLOCKED,
+ STATE_BLOCKED: Ci.nsIBlocklistService.STATE_BLOCKED,
+ STATE_OUTDATED: Ci.nsIBlocklistService.STATE_OUTDATED,
+ STATE_VULNERABLE_UPDATE_AVAILABLE: Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE,
+ STATE_VULNERABLE_NO_UPDATE: Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE,
+
+
/**
* Extension ID -> array of Version Ranges
* Each value in the version range array is a JS Object that has the
* following properties:
* "minVersion" The minimum version in a version range (default = 0)
* "maxVersion" The maximum version in a version range (default = *)
* "targetApps" Application ID -> array of Version Ranges
* (default = current application ID)
@@ -282,41 +324,53 @@ Blocklist.prototype = {
MAX_BLOCK_LEVEL);
this._blocklistUpdated(null, null);
break;
}
break;
}
},
- /* See nsIBlocklistService */
+ /**
+ * Determine the blocklist state of an add-on
+ * @param {Addon} addon
+ * The addon item to be checked.
+ * @param {string?} 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 {string?} 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.
+ * @returns {integer} The STATE constant.
+ */
getAddonBlocklistState(addon, appVersion, toolkitVersion) {
if (!this.isLoaded)
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`
+ * @param {Addon} addon
+ * The add-on object of the item to get the blocklist state for.
+ * @param {object[]} addonEntries
+ * The add-on blocklist entries to compare against.
+ * @param {string?} appVersion
+ * The application version to compare to, will use the current
+ * version if null.
+ * @param {string?} toolkitVersion
+ * The toolkit version to compare to, will use the current version if
+ * null.
+ * @returns {object?}
+ * 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).
@@ -339,53 +393,74 @@ Blocklist.prototype = {
Ci.nsIBlocklistService.STATE_BLOCKED : Ci.nsIBlocklistService.STATE_SOFTBLOCKED),
url: blItem.blockID && this._createBlocklistURL(blItem.blockID),
};
}
}
return null;
},
+ /**
+ * Returns a promise that resolves to the blocklist entry.
+ * The blocklist entry is an object with `state` and `url`
+ * properties, if a blocklist entry for the add-on exists, or null
+ * otherwise.
+
+ * @param {Addon} addon
+ * The addon object to match.
+ * @param {string?} 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 {string?} 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.
+ * @returns {Promise<object?>}
+ * The blocklist entry for the add-on, if one exists, or null
+ * otherwise.
+ */
async getAddonBlocklistEntry(addon, appVersion, toolkitVersion) {
await this.loadBlocklistAsync();
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
- * 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 The blocklist state for the item, one of the STATE constants as
- * defined in nsIBlocklistService.
+ * @param {Addon} addon
+ * The add-on object of the item to get the blocklist state for.
+ * @param {object[]} addonEntries
+ * The add-on blocklist entries to compare against.
+ * @param {string?} appVersion
+ * The application version to compare to, will use the current
+ * version if null.
+ * @param {string?} toolkitVersion
+ * The toolkit version to compare to, will use the current version if
+ * null.
+ * @returns {integer}
+ * The blocklist state for the item, one of the STATE constants as
+ * defined in nsIBlocklistService.
*/
_getAddonBlocklistState(addon, addonEntries, appVersion, toolkitVersion) {
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
+ * @param {Addon} addon
* The add-on whose to-be-reset prefs are to be found.
+ * @returns {string[]}
+ * An array of preference names.
*/
_getAddonPrefs(addon) {
let entry = this._findMatchingAddonEntry(this._addonEntries, addon);
return entry.prefs.slice(0);
},
_findMatchingAddonEntry(aAddonEntries, aAddon) {
if (!aAddon)
@@ -751,28 +826,34 @@ Blocklist.prototype = {
} catch (ex) {}
}
}
if (text)
this._loadBlocklistFromString(text);
},
+ /**
+ * Whether or not we've finished loading the blocklist.
+ */
get isLoaded() {
return this._addonEntries != null && this._gfxEntries != null && this._pluginEntries != null;
},
/* Used for testing */
_clear() {
this._addonEntries = null;
this._gfxEntries = null;
this._pluginEntries = null;
delete this._preloadPromise;
},
+ /**
+ * Trigger loading the blocklist content asynchronously.
+ */
async loadBlocklistAsync() {
if (this.isLoaded) {
return;
}
if (!this._preloadPromise) {
this._preloadPromise = this._loadBlocklistAsyncInternal();
}
await this._preloadPromise;
@@ -1072,28 +1153,29 @@ Blocklist.prototype = {
return this._getPluginBlocklistState(plugin, this._pluginEntries,
appVersion, toolkitVersion);
},
/**
* Private helper to get the blocklist entry for a plugin given a set of
* blocklist entries and versions.
*
- * @param plugin
- * The nsIPluginTag to get the blocklist state for.
- * @param pluginEntries
- * The plugin 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 {entry: blocklistEntry, version: blocklistEntryVersion},
- * or null if there is no matching entry.
+ * @param {nsIPluginTag} plugin
+ * The nsIPluginTag to get the blocklist state for.
+ * @param {object[]} pluginEntries
+ * The plugin blocklist entries to compare against.
+ * @param {string?} appVersion
+ * The application version to compare to, will use the current
+ * version if null.
+ * @param {string?} toolkitVersion
+ * The toolkit version to compare to, will use the current version if
+ * null.
+ * @returns {object?}
+ * {entry: blocklistEntry, version: blocklistEntryVersion},
+ * or null if there is no matching entry.
*/
_getPluginBlocklistEntry(plugin, pluginEntries, appVersion, toolkitVersion) {
if (!gBlocklistEnabled)
return null;
// Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't).
if (!appVersion && !gApp.version)
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
@@ -1133,28 +1215,29 @@ Blocklist.prototype = {
return null;
},
/**
* Private version of getPluginBlocklistState that allows the caller to pass in
* the plugin blocklist entries.
*
- * @param plugin
- * The nsIPluginTag to get the blocklist state for.
- * @param pluginEntries
- * The plugin 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 The blocklist state for the item, one of the STATE constants as
- * defined in nsIBlocklistService.
+ * @param {nsIPluginTag} plugin
+ * The nsIPluginTag to get the blocklist state for.
+ * @param {object[]} pluginEntries
+ * The plugin blocklist entries to compare against.
+ * @param {string?} appVersion
+ * The application version to compare to, will use the current
+ * version if null.
+ * @param {string?} toolkitVersion
+ * The toolkit version to compare to, will use the current version if
+ * null.
+ * @returns {integer}
+ * The blocklist state for the item, one of the STATE constants as
+ * defined in nsIBlocklistService.
*/
_getPluginBlocklistState(plugin, pluginEntries, appVersion, toolkitVersion) {
let r = this._getPluginBlocklistEntry(plugin, pluginEntries,
appVersion, toolkitVersion);
if (!r) {
return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
}
@@ -1345,17 +1428,17 @@ Blocklist.prototype = {
if (addonList.length == 0) {
this._notifyObserversBlocklistUpdated();
return;
}
if ("@mozilla.org/addons/blocklist-prompt;1" in Cc) {
try {
let blockedPrompter = Cc["@mozilla.org/addons/blocklist-prompt;1"]
- .getService(Ci.nsIBlocklistPrompt);
+ .getService().wrappedJSObject;
blockedPrompter.prompt(addonList);
} catch (e) {
LOG(e);
}
this._notifyObserversBlocklistUpdated();
return;
}
@@ -1414,17 +1497,17 @@ Blocklist.prototype = {
},
classID: Components.ID("{66354bc9-7ed1-4692-ae1d-8da97d6b205e}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
Ci.nsIBlocklistService,
Ci.nsITimerCallback]),
};
-/**
+/*
* Helper for constructing a blocklist.
*/
function BlocklistItemData(versionRangeElement) {
var versionRange = this.getBlocklistVersionRange(versionRangeElement);
this.minVersion = versionRange.minVersion;
this.maxVersion = versionRange.maxVersion;
if (versionRangeElement && versionRangeElement.hasAttribute("severity"))
this.severity = versionRangeElement.getAttribute("severity");
@@ -1456,24 +1539,25 @@ function BlocklistItemData(versionRangeE
this.targetApps[gApp.ID] = this.getBlocklistAppVersions(null);
}
BlocklistItemData.prototype = {
/**
* Tests if a version of an item is included in the version range and target
* application information represented by this BlocklistItemData using the
* provided application and toolkit versions.
- * @param version
- * The version of the item being tested.
- * @param appVersion
- * The application version to test with.
- * @param toolkitVersion
- * The toolkit version to test with.
- * @returns True if the version range covers the item version and application
- * or toolkit version.
+ * @param {string} version
+ * The version of the item being tested.
+ * @param {string} appVersion
+ * The application version to test with.
+ * @param {string} toolkitVersion
+ * The toolkit version to test with.
+ * @returns {boolean}
+ * True if the version range covers the item version and application
+ * or toolkit version.
*/
includesItem(version, appVersion, toolkitVersion) {
// Some platforms have no version for plugins, these don't match if there
// was a min/maxVersion provided
if (!version && (this.minVersion || this.maxVersion))
return false;
// Check if the item version matches
@@ -1486,41 +1570,44 @@ BlocklistItemData.prototype = {
// Check if the toolkit version matches
return this.matchesTargetRange(TOOLKIT_ID, toolkitVersion);
},
/**
* Checks if a version is higher than or equal to the minVersion (if provided)
* and lower than or equal to the maxVersion (if provided).
- * @param version
- * The version to test.
- * @param minVersion
- * The minimum version. If null it is assumed that version is always
- * larger.
- * @param maxVersion
- * The maximum version. If null it is assumed that version is always
- * smaller.
+ * @param {string} version
+ * The version to test.
+ * @param {string?} minVersion
+ * The minimum version. If null it is assumed that version is always
+ * larger.
+ * @param {string?} maxVersion
+ * The maximum version. If null it is assumed that version is always
+ * smaller.
+ * @returns {boolean}
+ * Whether the item matches the range.
*/
matchesRange(version, minVersion, maxVersion) {
if (minVersion && Services.vc.compare(version, minVersion) < 0)
return false;
if (maxVersion && Services.vc.compare(version, maxVersion) > 0)
return false;
return true;
},
/**
* Tests if there is a matching range for the given target application id and
* version.
- * @param appID
- * The application ID to test for, may be for an application or toolkit
- * @param appVersion
- * The version of the application to test for.
- * @returns True if this version range covers the application version given.
+ * @param {string} appID
+ * The application ID to test for, may be for an application or toolkit
+ * @param {string} appVersion
+ * The version of the application to test for.
+ * @returns {boolean}
+ * True if this version range covers the application version given.
*/
matchesTargetRange(appID, appVersion) {
var blTargetApp = this.targetApps[appID];
if (!blTargetApp)
return false;
for (let app of blTargetApp) {
if (this.matchesRange(appVersion, app.minVersion, app.maxVersion))
@@ -1528,19 +1615,20 @@ BlocklistItemData.prototype = {
}
return false;
},
/**
* Retrieves a version range (e.g. minVersion and maxVersion) for a
* blocklist item's targetApplication element.
- * @param targetAppElement
- * A targetApplication blocklist element.
- * @returns An array of JS objects with the following properties:
+ * @param {Element} targetAppElement
+ * A targetApplication blocklist element.
+ * @returns {object[]}
+ * An array of JS objects with the following properties:
* "minVersion" The minimum version in a version range (default = null).
* "maxVersion" The maximum version in a version range (default = null).
*/
getBlocklistAppVersions(targetAppElement) {
var appVersions = [ ];
if (targetAppElement) {
for (var i = 0; i < targetAppElement.childNodes.length; ++i) {
@@ -1556,19 +1644,22 @@ BlocklistItemData.prototype = {
if (appVersions.length == 0)
appVersions.push(this.getBlocklistVersionRange(null));
return appVersions;
},
/**
* Retrieves a version range (e.g. minVersion and maxVersion) for a blocklist
* versionRange element.
- * @param versionRangeElement
- * The versionRange blocklist element.
- * @returns A JS object with the following properties:
+ *
+ * @param {Element} versionRangeElement
+ * The versionRange blocklist element.
+ *
+ * @returns {Object}
+ * A JS object with the following properties:
* "minVersion" The minimum version in a version range (default = null).
* "maxVersion" The maximum version in a version range (default = null).
*/
getBlocklistVersionRange(versionRangeElement) {
var minVersion = null;
var maxVersion = null;
if (!versionRangeElement)
return { minVersion, maxVersion };
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_appversion.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_appversion.js
@@ -234,21 +234,23 @@ var PluginHost = {
countRef.value = PLUGINS.length;
return PLUGINS;
},
QueryInterface: XPCOMUtils.generateQI(["nsIPluginHost"]),
};
var BlocklistPrompt = {
+ get wrappedJSObject() { return this; },
+
prompt(list) {
gNewBlocks = list.map(item => `${item.name} ${item.version}`);
},
- QueryInterface: XPCOMUtils.generateQI(["nsIBlocklistPrompt"]),
+ QueryInterface: XPCOMUtils.generateQI([]),
};
async function loadBlocklist(file) {
let blocklistUpdated = TestUtils.topicObserved("blocklist-updated");
Services.prefs.setCharPref("extensions.blocklist.url",
"http://example.com/data/" + file);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_plugin_flashonly.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_plugin_flashonly.js
@@ -15,23 +15,21 @@ function get_test_plugintag() {
return null;
}
function run_test() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
copyBlocklistToProfile(do_get_file("data/test_bug514327_2.xml"));
- var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].getService(nsIBLS);
-
Services.prefs.setBoolPref("plugin.load_flash_only", false);
var plugin = get_test_plugintag();
if (!plugin)
do_throw("Plugin tag not found");
// run the code after the blocklist is closed
Services.obs.notifyObservers(null, "addon-blocklist-closed");
executeSoon(function() {
// should be marked as outdated by the blocklist
- Assert.ok(blocklist.getPluginBlocklistState(plugin, "1", "1.9") == nsIBLS.STATE_OUTDATED);
+ Assert.ok(Services.blocklist.getPluginBlocklistState(plugin, "1", "1.9") == nsIBLS.STATE_OUTDATED);
});
}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_plugin_outdated.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_plugin_outdated.js
@@ -41,26 +41,28 @@ var PluginHost = {
countRef.value = PLUGINS.length;
return PLUGINS;
},
QueryInterface: XPCOMUtils.generateQI(["nsIPluginHost"]),
};
var BlocklistPrompt = {
+ get wrappedJSObject() { return this; },
+
prompt(list) {
// Should only include one item
Assert.equal(list.length, 1);
// And that item should be the blocked plugin, not the outdated one
var item = list[0];
Assert.ok(item.item instanceof Ci.nsIPluginTag);
Assert.notEqual(item.name, "test_bug514327_outdated");
},
- QueryInterface: XPCOMUtils.generateQI(["nsIBlocklistPrompt"]),
+ QueryInterface: XPCOMUtils.generateQI([]),
};
async function loadBlocklist(file) {
let blocklistUpdated = TestUtils.topicObserved("blocklist-updated");
Services.prefs.setCharPref("extensions.blocklist.url",
"http://example.com/data/" + file);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js
@@ -50,17 +50,17 @@ var PLUGINS = [{
// not in the blocklist -> not blocked
name: "test_plugin_5",
version: "5",
disabled: false,
blocklisted: false
}];
function test_basic() {
- var blocklist = Cc["@mozilla.org/extensions/blocklist;1"].getService(nsIBLS);
+ var {blocklist} = Services;
Assert.ok(blocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9") == nsIBLS.STATE_OUTDATED);
Assert.ok(blocklist.getPluginBlocklistState(PLUGINS[1], "1", "1.9") == nsIBLS.STATE_VULNERABLE_UPDATE_AVAILABLE);
Assert.ok(blocklist.getPluginBlocklistState(PLUGINS[2], "1", "1.9") == nsIBLS.STATE_VULNERABLE_NO_UPDATE);
Assert.ok(blocklist.getPluginBlocklistState(PLUGINS[3], "1", "1.9") == nsIBLS.STATE_BLOCKED);
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/rules/use-services.js
@@ -41,17 +41,19 @@ var servicesASTParser = {
if (node.declarations.length === 1 &&
node.declarations[0].id &&
helpers.getIsGlobalScope(parents) &&
node.declarations[0].init.type === "ObjectExpression") {
let name = node.declarations[0].id.name;
let interfaces = {};
for (let property of node.declarations[0].init.properties) {
- interfaces[property.key.name] = property.value.elements[1].value;
+ if (property.value.elements.length > 1) {
+ interfaces[property.key.name] = property.value.elements[1].value;
+ }
}
this.identifiers[name] = interfaces;
}
},
/**
* This looks for any additions to the global variable declarations, and adds
--- a/xpcom/system/nsIBlocklistService.idl
+++ b/xpcom/system/nsIBlocklistService.idl
@@ -23,34 +23,16 @@ interface nsIBlocklistService : nsISuppo
// update available.
const unsigned long STATE_OUTDATED = 3;
// Indicates that the item is vulnerable and there is an update.
const unsigned long STATE_VULNERABLE_UPDATE_AVAILABLE = 4;
// Indicates that the item is vulnerable and there is no update.
const unsigned long STATE_VULNERABLE_NO_UPDATE = 5;
/**
- * Determine the blocklist state of an add-on
- * @param id
- * The addon item to be checked.
- * @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.
- * @returns The STATE constant.
- */
- unsigned long getAddonBlocklistState(in jsval addon,
- [optional] in AString appVersion,
- [optional] in AString toolkitVersion);
-
- /**
* Determine the blocklist state of a plugin
* @param plugin
* The plugin to get the state for
* @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
@@ -58,85 +40,10 @@ interface nsIBlocklistService : nsISuppo
* If this parameter is null, the version of the running toolkit
* is used.
* @returns The STATE constant.
*/
unsigned long getPluginBlocklistState(in nsIPluginTag plugin,
[optional] in AString appVersion,
[optional] in AString toolkitVersion);
- /**
- * Returns a promise that resolves to the blocklist entry.
- * The blocklist entry is an object with `state` and `url`
- * properties, if a blocklist entry for the add-on exists, or null
- * otherwise.
-
- * @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);
-
- /**
- * Determine the blocklist infoURL of a plugin.
- * @param plugin
- * The blocked plugin that we are determining the infoURL for.
- * @returns The preferred URL to present the user, or |null| if
- * it is not available.
- */
- AString getPluginInfoURL(in nsIPluginTag plugin);
-
- /**
- * Whether or not we've finished loading the blocklist.
- */
readonly attribute boolean isLoaded;
-
- /**
- * Trigger loading the blocklist content asynchronously.
- */
- void loadBlocklistAsync();
};
-
-/**
- * nsIBlocklistPrompt is used, if available, by the default implementation of
- * nsIBlocklistService to display a confirmation UI to the user before blocking
- * extensions/plugins.
- */
-[scriptable, uuid(ba915921-b9c0-400d-8e4f-ca1b80c5699a)]
-interface nsIBlocklistPrompt : nsISupports
-{
- /**
- * Prompt the user about newly blocked addons. The prompt is then resposible
- * for soft-blocking any addons that need to be afterwards
- *
- * @param aAddons
- * An array of addons and plugins that are blocked. These are javascript
- * objects with properties:
- * name - the plugin or extension name,
- * version - the version of the extension or plugin,
- * icon - the plugin or extension icon,
- * disable - can be used by the nsIBlocklistPrompt to allows users to decide
- * whether a soft-blocked add-on should be disabled,
- * blocked - true if the item is hard-blocked, false otherwise,
- * item - the nsIPluginTag or Addon object
- * @param aCount
- * The number of addons
- */
- void prompt([array, size_is(aCount)] in nsIVariant aAddons,
- [optional] in uint32_t aCount);
-};