--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1271,19 +1271,16 @@ BrowserGlue.prototype = {
});
}
Services.tm.idleDispatchToMainThread(() => {
LanguagePrompt.init();
});
ChromeUtils.idleDispatch(() => {
- Blocklist.loadBlocklistAsync();
- });
- ChromeUtils.idleDispatch(() => {
Blocklist.checkForGfxBlocklistEntries();
});
Services.tm.idleDispatchToMainThread(() => {
SavantShieldStudy.init();
});
},
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -273,28 +273,36 @@ class BlocklistPromiseHandler final : pu
// sentinel, setting it to nullptr when we run.
if (!mTag) {
return;
}
mTag = nullptr;
sPendingBlocklistStateRequests--;
// If this was the only remaining pending request, check if we need to write
// state and if so update the child processes.
- if (!sPendingBlocklistStateRequests &&
- sPluginBlocklistStatesChangedSinceLastWrite) {
- sPluginBlocklistStatesChangedSinceLastWrite = false;
-
- RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
- // Write the changed list to disk:
- host->WritePluginInfo();
-
- // We update blocklist info in content processes asynchronously
- // by just sending a new plugin list to content.
- host->IncrementChromeEpoch();
- host->SendPluginsToContent();
+ if (!sPendingBlocklistStateRequests) {
+ if (sPluginBlocklistStatesChangedSinceLastWrite) {
+ sPluginBlocklistStatesChangedSinceLastWrite = false;
+
+ RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
+ // Write the changed list to disk:
+ host->WritePluginInfo();
+
+ // We update blocklist info in content processes asynchronously
+ // by just sending a new plugin list to content.
+ host->IncrementChromeEpoch();
+ host->SendPluginsToContent();
+ }
+
+ // Now notify observers that we're done updating plugin state.
+ nsCOMPtr<nsIObserverService> obsService =
+ mozilla::services::GetObserverService();
+ if (obsService) {
+ obsService->NotifyObservers(nullptr, "plugin-blocklist-updates-finished", nullptr);
+ }
}
}
void
ResolvedCallback(JSContext *aCx, JS::Handle<JS::Value> aValue) override
{
if (!aValue.isInt32()) {
MOZ_ASSERT(false, "Blocklist should always return int32");
@@ -368,17 +376,17 @@ nsPluginHost::nsPluginHost()
Preferences::AddStrongObserver(this, "plugin.disable");
nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService();
if (obsService) {
obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
if (XRE_IsParentProcess()) {
- obsService->AddObserver(this, "blocklist-updated", false);
+ obsService->AddObserver(this, "plugin-blocklist-updated", false);
}
}
#ifdef PLUGIN_LOGGING
MOZ_LOG(nsPluginLogging::gNPNLog, PLUGIN_LOG_ALWAYS,("NPN Logging Active!\n"));
MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_ALWAYS,("General Plugin Logging Active! (nsPluginHost::ctor)\n"));
MOZ_LOG(nsPluginLogging::gNPPLog, PLUGIN_LOG_ALWAYS,("NPP Logging Active!\n"));
@@ -3524,17 +3532,17 @@ NS_IMETHODIMP nsPluginHost::Observe(nsIS
mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
// Unload or load plugins as needed
if (mPluginsDisabled) {
UnloadPlugins();
} else {
LoadPlugins();
}
}
- if (XRE_IsParentProcess() && !strcmp("blocklist-updated", aTopic)) {
+ if (XRE_IsParentProcess() && !strcmp("plugin-blocklist-updated", aTopic)) {
// The blocklist has updated. Asynchronously get blocklist state for all items.
// The promise resolution handler takes care of checking if anything changed,
// and writing an updated state to file, as well as sending data to child processes.
nsPluginTag* plugin = mPlugins;
while (plugin) {
UpdatePluginBlocklistState(plugin);
plugin = plugin->mNext;
}
--- a/services/common/blocklist-clients.js
+++ b/services/common/blocklist-clients.js
@@ -13,22 +13,16 @@ const { OS } = ChromeUtils.import("resou
ChromeUtils.defineModuleGetter(this, "RemoteSettings", "resource://services-settings/remote-settings.js");
ChromeUtils.defineModuleGetter(this, "jexlFilterFunc", "resource://services-settings/remote-settings.js");
const PREF_BLOCKLIST_BUCKET = "services.blocklist.bucket";
const PREF_BLOCKLIST_ONECRL_COLLECTION = "services.blocklist.onecrl.collection";
const PREF_BLOCKLIST_ONECRL_CHECKED_SECONDS = "services.blocklist.onecrl.checked";
const PREF_BLOCKLIST_ONECRL_SIGNER = "services.blocklist.onecrl.signer";
-const PREF_BLOCKLIST_ADDONS_COLLECTION = "services.blocklist.addons.collection";
-const PREF_BLOCKLIST_ADDONS_CHECKED_SECONDS = "services.blocklist.addons.checked";
-const PREF_BLOCKLIST_ADDONS_SIGNER = "services.blocklist.addons.signer";
-const PREF_BLOCKLIST_PLUGINS_COLLECTION = "services.blocklist.plugins.collection";
-const PREF_BLOCKLIST_PLUGINS_CHECKED_SECONDS = "services.blocklist.plugins.checked";
-const PREF_BLOCKLIST_PLUGINS_SIGNER = "services.blocklist.plugins.signer";
const PREF_BLOCKLIST_PINNING_ENABLED = "services.blocklist.pinning.enabled";
const PREF_BLOCKLIST_PINNING_BUCKET = "services.blocklist.pinning.bucket";
const PREF_BLOCKLIST_PINNING_COLLECTION = "services.blocklist.pinning.collection";
const PREF_BLOCKLIST_PINNING_CHECKED_SECONDS = "services.blocklist.pinning.checked";
const PREF_BLOCKLIST_PINNING_SIGNER = "services.blocklist.pinning.signer";
/**
* Revoke the appropriate certificates based on the records from the blocklist.
@@ -96,41 +90,16 @@ async function updatePinningList({ data:
// prevent errors relating to individual preload entries from causing
// sync to fail. We will accumulate telemetry for such failures in bug
// 1254099.
}
}
}
/**
- * Write list of records into JSON file, and notify nsBlocklistService.
- *
- * @param {Object} client RemoteSettingsClient instance
- * @param {Object} data Current records in the local db.
- */
-async function updateJSONBlocklist(client, { data: { current: records } }) {
- // Write JSON dump for synchronous load at startup.
- const path = OS.Path.join(OS.Constants.Path.profileDir, client.filename);
- const blocklistFolder = OS.Path.dirname(path);
-
- await OS.File.makeDir(blocklistFolder, {from: OS.Constants.Path.profileDir});
-
- const serialized = JSON.stringify({data: records}, null, 2);
- try {
- await OS.File.writeAtomic(path, serialized, {tmpPath: path + ".tmp"});
- // Notify change to `nsBlocklistService`
- const eventData = {filename: client.filename};
- Services.cpmm.sendAsyncMessage("Blocklist:reload-from-disk", eventData);
- } catch (e) {
- Cu.reportError(e);
- }
-}
-
-
-/**
* This custom filter function is used to limit the entries returned
* by `RemoteSettings("...").get()` depending on the target app information
* defined on entries.
*/
async function targetAppFilter(entry, environment) {
// If the entry has a JEXL filter expression, it should prevail.
// The legacy target app mechanism will be kept in place for old entries.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1463377
@@ -186,42 +155,25 @@ async function targetAppFilter(entry, en
}
// Skip this entry.
return null;
}
var AddonBlocklistClient;
var OneCRLBlocklistClient;
var PinningBlocklistClient;
-var PluginBlocklistClient;
function initialize() {
OneCRLBlocklistClient = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_ONECRL_COLLECTION), {
bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET),
lastCheckTimePref: PREF_BLOCKLIST_ONECRL_CHECKED_SECONDS,
signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_ONECRL_SIGNER),
});
OneCRLBlocklistClient.on("sync", updateCertBlocklist);
- AddonBlocklistClient = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_ADDONS_COLLECTION), {
- bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET),
- lastCheckTimePref: PREF_BLOCKLIST_ADDONS_CHECKED_SECONDS,
- signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_ADDONS_SIGNER),
- filterFunc: targetAppFilter,
- });
- AddonBlocklistClient.on("sync", updateJSONBlocklist.bind(null, AddonBlocklistClient));
-
- PluginBlocklistClient = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_COLLECTION), {
- bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET),
- lastCheckTimePref: PREF_BLOCKLIST_PLUGINS_CHECKED_SECONDS,
- signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_SIGNER),
- filterFunc: targetAppFilter,
- });
- PluginBlocklistClient.on("sync", updateJSONBlocklist.bind(null, PluginBlocklistClient));
-
PinningBlocklistClient = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_COLLECTION), {
bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_BUCKET),
lastCheckTimePref: PREF_BLOCKLIST_PINNING_CHECKED_SECONDS,
signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_PINNING_SIGNER),
});
PinningBlocklistClient.on("sync", updatePinningList);
}
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm
@@ -277,17 +277,17 @@ const PREF_SEARCH_COHORT = "browser.sear
const COMPOSITOR_CREATED_TOPIC = "compositor:created";
const COMPOSITOR_PROCESS_ABORTED_TOPIC = "compositor:process-aborted";
const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC = "distribution-customization-complete";
const GFX_FEATURES_READY_TOPIC = "gfx-features-ready";
const SEARCH_ENGINE_MODIFIED_TOPIC = "browser-search-engine-modified";
const SEARCH_SERVICE_TOPIC = "browser-search-service";
const SESSIONSTORE_WINDOWS_RESTORED_TOPIC = "sessionstore-windows-restored";
const PREF_CHANGED_TOPIC = "nsPref:changed";
-const BLOCKLIST_LOADED_TOPIC = "blocklist-loaded";
+const BLOCKLIST_LOADED_TOPIC = "plugin-blocklist-loaded";
/**
* Enforces the parameter to a boolean value.
* @param aValue The input value.
* @return {Boolean|Object} If aValue is a boolean or a number, returns its truthfulness
* value. Otherwise, return null.
*/
function enforceBoolean(aValue) {
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -31,22 +31,16 @@ const PREF_EM_CHECK_UPDATE_SECURITY =
const PREF_SYS_ADDON_UPDATE_ENABLED = "extensions.systemAddon.update.enabled";
const PREF_MIN_WEBEXT_PLATFORM_VERSION = "extensions.webExtensionsMinPlatformVersion";
const PREF_WEBAPI_TESTING = "extensions.webapi.testing";
const PREF_WEBEXT_PERM_PROMPTS = "extensions.webextPermissionPrompts";
const UPDATE_REQUEST_VERSION = 2;
-const XMLURI_BLOCKLIST = "http://www.mozilla.org/2006/addons-blocklist";
-
-const KEY_PROFILEDIR = "ProfD";
-const KEY_APPDIR = "XCurProcD";
-const FILE_BLOCKLIST = "blocklist.xml";
-
const DEFAULT_THEME_ID = "default-theme@mozilla.org";
const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi;
const PREF_EM_CHECK_COMPATIBILITY_BASE = "extensions.checkCompatibility";
var PREF_EM_CHECK_COMPATIBILITY = MOZ_COMPATIBILITY_NIGHTLY ?
PREF_EM_CHECK_COMPATIBILITY_BASE + ".nightly" :
undefined;
@@ -60,22 +54,21 @@ const WEBAPI_TEST_INSTALL_HOSTS = [
];
const URI_XPINSTALL_DIALOG = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/AsyncShutdown.jsm");
-XPCOMUtils.defineLazyGlobalGetters(this, ["DOMParser", "Element"]);
+XPCOMUtils.defineLazyGlobalGetters(this, ["Element"]);
XPCOMUtils.defineLazyModuleGetters(this, {
AddonRepository: "resource://gre/modules/addons/AddonRepository.jsm",
Extension: "resource://gre/modules/Extension.jsm",
- FileUtils: "resource://gre/modules/FileUtils.jsm",
LightweightThemeManager: "resource://gre/modules/LightweightThemeManager.jsm",
PromptUtils: "resource://gre/modules/SharedPromptUtils.jsm",
});
XPCOMUtils.defineLazyPreferenceGetter(this, "WEBEXT_PERMISSION_PROMPTS",
PREF_WEBEXT_PERM_PROMPTS, false);
// Initialize the WebExtension process script service as early as possible,
@@ -554,92 +547,16 @@ var AddonManagerInternal = {
// Store telemetry details per addon provider
telemetryDetails: {},
upgradeListeners: new Map(),
recordTimestamp(name, value) {
this.TelemetryTimestamps.add(name, value);
},
- validateBlocklist() {
- let appBlocklist = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]);
-
- // If there is no application shipped blocklist then there is nothing to do
- if (!appBlocklist.exists())
- return;
-
- let profileBlocklist = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]);
-
- // If there is no blocklist in the profile then copy the application shipped
- // one there
- if (!profileBlocklist.exists()) {
- try {
- appBlocklist.copyTo(profileBlocklist.parent, FILE_BLOCKLIST);
- } catch (e) {
- logger.warn("Failed to copy the application shipped blocklist to the profile", e);
- }
- return;
- }
-
- let fileStream = Cc["@mozilla.org/network/file-input-stream;1"].
- createInstance(Ci.nsIFileInputStream);
- try {
- let cstream = Cc["@mozilla.org/intl/converter-input-stream;1"].
- createInstance(Ci.nsIConverterInputStream);
- fileStream.init(appBlocklist, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
- cstream.init(fileStream, "UTF-8", 0, 0);
-
- let data = "";
- let str = {};
- let read = 0;
- do {
- read = cstream.readString(0xffffffff, str);
- data += str.value;
- } while (read != 0);
-
- let parser = new DOMParser();
- var doc = parser.parseFromString(data, "text/xml");
- } catch (e) {
- logger.warn("Application shipped blocklist could not be loaded", e);
- return;
- } finally {
- try {
- fileStream.close();
- } catch (e) {
- logger.warn("Unable to close blocklist file stream", e);
- }
- }
-
- // If the namespace is incorrect then ignore the application shipped
- // blocklist
- if (doc.documentElement.namespaceURI != XMLURI_BLOCKLIST) {
- logger.warn("Application shipped blocklist has an unexpected namespace (" +
- doc.documentElement.namespaceURI + ")");
- return;
- }
-
- // If there is no lastupdate information then ignore the application shipped
- // blocklist
- if (!doc.documentElement.hasAttribute("lastupdate"))
- return;
-
- // If the application shipped blocklist is older than the profile blocklist
- // then do nothing
- if (doc.documentElement.getAttribute("lastupdate") <=
- profileBlocklist.lastModifiedTime)
- return;
-
- // Otherwise copy the application shipped blocklist to the profile
- try {
- appBlocklist.copyTo(profileBlocklist.parent, FILE_BLOCKLIST);
- } catch (e) {
- logger.warn("Failed to copy the application shipped blocklist to the profile", e);
- }
- },
-
/**
* Start up a provider, and register its shutdown hook if it has one
*
* @param {string} aProvider - An add-on provider.
* @param {boolean} aAppChanged - Whether or not the app version has changed since last session.
* @param {string} aOldAppVersion - Previous application version, if changed.
* @param {string} aOldPlatformVersion - Previous platform version, if changed.
*
@@ -721,17 +638,16 @@ var AddonManagerInternal = {
if (appChanged !== false) {
logger.debug("Application has been upgraded");
Services.prefs.setCharPref(PREF_EM_LAST_APP_VERSION,
Services.appinfo.version);
Services.prefs.setCharPref(PREF_EM_LAST_PLATFORM_VERSION,
Services.appinfo.platformVersion);
Services.prefs.setIntPref(PREF_BLOCKLIST_PINGCOUNTVERSION,
(appChanged === undefined ? 0 : -1));
- this.validateBlocklist();
}
if (!MOZ_COMPATIBILITY_NIGHTLY) {
PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE + "." +
Services.appinfo.version.replace(BRANCH_REGEXP, "$1");
}
gCheckCompatibility = Services.prefs.getBoolPref(PREF_EM_CHECK_COMPATIBILITY,
--- a/toolkit/mozapps/extensions/Blocklist.jsm
+++ b/toolkit/mozapps/extensions/Blocklist.jsm
@@ -8,135 +8,216 @@
/* eslint "valid-jsdoc": [2, {requireReturn: false}] */
var EXPORTED_SYMBOLS = ["Blocklist"];
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
-XPCOMUtils.defineLazyGlobalGetters(this, ["XMLHttpRequest"]);
ChromeUtils.defineModuleGetter(this, "AddonManager",
"resource://gre/modules/AddonManager.jsm");
ChromeUtils.defineModuleGetter(this, "AddonManagerPrivate",
"resource://gre/modules/AddonManager.jsm");
ChromeUtils.defineModuleGetter(this, "CertUtils",
"resource://gre/modules/CertUtils.jsm");
-ChromeUtils.defineModuleGetter(this, "FileUtils",
- "resource://gre/modules/FileUtils.jsm");
ChromeUtils.defineModuleGetter(this, "UpdateUtils",
"resource://gre/modules/UpdateUtils.jsm");
-ChromeUtils.defineModuleGetter(this, "OS",
- "resource://gre/modules/osfile.jsm");
ChromeUtils.defineModuleGetter(this, "ServiceRequest",
"resource://gre/modules/ServiceRequest.jsm");
- /**
-# The blocklist XML file looks something like this:
-#
-# <blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
-# <emItems>
-# <emItem id="item_1@domain" blockID="i1">
-# <prefs>
-# <pref>accessibility.accesskeycausesactivation</pref>
-# <pref>accessibility.blockautorefresh</pref>
-# </prefs>
-# <versionRange minVersion="1.0" maxVersion="2.0.*">
-# <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-# <versionRange minVersion="1.5" maxVersion="1.5.*"/>
-# <versionRange minVersion="1.7" maxVersion="1.7.*"/>
-# </targetApplication>
-# <targetApplication id="toolkit@mozilla.org">
-# <versionRange minVersion="1.9" maxVersion="1.9.*"/>
-# </targetApplication>
-# </versionRange>
-# <versionRange minVersion="3.0" maxVersion="3.0.*">
-# <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-# <versionRange minVersion="1.5" maxVersion="1.5.*"/>
-# </targetApplication>
-# <targetApplication id="toolkit@mozilla.org">
-# <versionRange minVersion="1.9" maxVersion="1.9.*"/>
-# </targetApplication>
-# </versionRange>
-# </emItem>
-# <emItem id="item_2@domain" blockID="i2">
-# <versionRange minVersion="3.1" maxVersion="4.*"/>
-# </emItem>
-# <emItem id="item_3@domain">
-# <versionRange>
-# <targetApplication id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}">
-# <versionRange minVersion="1.5" maxVersion="1.5.*"/>
-# </targetApplication>
-# </versionRange>
-# </emItem>
-# <emItem id="item_4@domain" blockID="i3">
-# <versionRange>
-# <targetApplication>
-# <versionRange minVersion="1.5" maxVersion="1.5.*"/>
-# </targetApplication>
-# </versionRange>
-# <emItem id="/@badperson\.com$/"/>
-# </emItems>
-# <pluginItems>
-# <pluginItem blockID="i4">
-# <!-- All match tags must match a plugin to blocklist a plugin -->
-# <match name="name" exp="some plugin"/>
-# <match name="description" exp="1[.]2[.]3"/>
-# </pluginItem>
-# </pluginItems>
-# </blocklist>
- */
-
// The remote settings updater is the new system in charge of fetching remote data
// securely and efficiently. It will replace the current XML-based system.
// See Bug 1257565 and Bug 1252456.
ChromeUtils.defineModuleGetter(this, "BlocklistRemoteSettings",
"resource://services-common/blocklist-clients.js");
XPCOMUtils.defineLazyGetter(this, "RemoteSettings", function() {
// Instantiate blocklist clients.
BlocklistRemoteSettings.initialize();
// Import RemoteSettings for ``pollChanges()``
const { RemoteSettings } = ChromeUtils.import("resource://services-settings/remote-settings.js", {});
return RemoteSettings;
});
const TOOLKIT_ID = "toolkit@mozilla.org";
-const KEY_PROFILEDIR = "ProfD";
-const KEY_APPDIR = "XCurProcD";
-const FILE_BLOCKLIST = "blocklist.xml";
const PREF_BLOCKLIST_LASTUPDATETIME = "app.update.lastUpdateTime.blocklist-background-update-timer";
const PREF_BLOCKLIST_URL = "extensions.blocklist.url";
const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL";
const PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled";
const PREF_BLOCKLIST_LAST_MODIFIED = "extensions.blocklist.lastModified";
const PREF_BLOCKLIST_LEVEL = "extensions.blocklist.level";
const PREF_BLOCKLIST_PINGCOUNTTOTAL = "extensions.blocklist.pingCountTotal";
const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion";
const PREF_BLOCKLIST_SUPPRESSUI = "extensions.blocklist.suppressUI";
const PREF_BLOCKLIST_UPDATE_ENABLED = "services.blocklist.update_enabled";
const PREF_APP_DISTRIBUTION = "distribution.id";
const PREF_APP_DISTRIBUTION_VERSION = "distribution.version";
const PREF_EM_LOGGING_ENABLED = "extensions.logging.enabled";
-const XMLURI_BLOCKLIST = "http://www.mozilla.org/2006/addons-blocklist";
const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml";
const URI_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
const DEFAULT_SEVERITY = 3;
const DEFAULT_LEVEL = 2;
const MAX_BLOCK_LEVEL = 3;
const SEVERITY_OUTDATED = 0;
const VULNERABILITYSTATUS_NONE = 0;
const VULNERABILITYSTATUS_UPDATE_AVAILABLE = 1;
const VULNERABILITYSTATUS_NO_UPDATE = 2;
// Kinto blocklist constants
const PREF_BLOCKLIST_BUCKET = "services.blocklist.bucket";
const PREF_BLOCKLIST_GFX_COLLECTION = "services.blocklist.gfx.collection";
const PREF_BLOCKLIST_GFX_CHECKED_SECONDS = "services.blocklist.gfx.checked";
const PREF_BLOCKLIST_GFX_SIGNER = "services.blocklist.gfx.signer";
+const PREF_BLOCKLIST_PLUGINS_COLLECTION = "services.blocklist.plugins.collection";
+const PREF_BLOCKLIST_PLUGINS_CHECKED_SECONDS = "services.blocklist.plugins.checked";
+const PREF_BLOCKLIST_PLUGINS_SIGNER = "services.blocklist.plugins.signer";
+const PREF_BLOCKLIST_ADDONS_COLLECTION = "services.blocklist.addons.collection";
+const PREF_BLOCKLIST_ADDONS_CHECKED_SECONDS = "services.blocklist.addons.checked";
+const PREF_BLOCKLIST_ADDONS_SIGNER = "services.blocklist.addons.signer";
+
+const Utils = {
+ /**
+ * Checks whether this entry is valid for the current OS and ABI.
+ * If the entry has an "os" property then the current OS must appear in
+ * its comma separated list for it to be valid. Similarly for the
+ * xpcomabi property.
+ *
+ * @param {Object} item
+ * The blocklist item.
+ * @returns {bool}
+ * Whether the entry matches the current OS.
+ */
+ matchesOSABI(item) {
+ if (item.os) {
+ let os = item.os.split(",");
+ if (!os.includes(gAppOS)) {
+ return false;
+ }
+ }
+
+ if (item.xpcomabi) {
+ let xpcomabi = item.xpcomabi.split(",");
+ if (!xpcomabi.includes(gApp.XPCOMABI)) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /**
+ * 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 {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.
+ */
+ versionInRange(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 this versionRange matches the item specified, and has a matching
+ * targetApplication id and version.
+ * @param {Object} versionRange
+ * The versionRange to check against
+ * @param {string} itemVersion
+ * The version of the actual addon/plugin to test for.
+ * @param {string} appVersion
+ * The version of the application to test for.
+ * @param {string} toolkitVersion
+ * The version of toolkit to check for.
+ * @returns {boolean}
+ * True if this version range covers the item and app/toolkit version given.
+ */
+ versionsMatch(versionRange, itemVersion, appVersion, toolkitVersion) {
+ // Some platforms have no version for plugins, these don't match if there
+ // was a min/maxVersion provided
+ if (!itemVersion && (versionRange.minVersion || versionRange.maxVersion))
+ return false;
+
+ // Check if the item version matches
+ if (!this.versionInRange(itemVersion, versionRange.minVersion, versionRange.maxVersion))
+ return false;
+
+ // Check if the application or toolkit version matches
+ for (let tA of versionRange.targetApplication) {
+ if (tA.guid == gAppID && this.versionInRange(appVersion, tA.minVersion, tA.maxVersion)) {
+ return true;
+ }
+ if (tA.guid == TOOLKIT_ID &&
+ this.versionInRange(toolkitVersion, tA.minVersion, tA.maxVersion)) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /**
+ * Given a blocklist JS object entry, ensure it has a versionRange property, where
+ * each versionRange property has valid severity and vulnerabilityStatus properties,
+ * and at least 1 valid targetApplication.
+ * If it didn't have a valid targetApplication array before and/or it was empty,
+ * fill it with an entry with null min/maxVersion properties, which will match
+ * every version.
+ *
+ * If there *are* targetApplications, if any of them don't have a guid property,
+ * assign them the current app's guid.
+ *
+ * @param {Object} entry
+ * blocklist entry object.
+ */
+ ensureVersionRangeIsSane(entry) {
+ if (!entry.versionRange.length) {
+ entry.versionRange.push({});
+ }
+ for (let vr of entry.versionRange) {
+ if (!vr.hasOwnProperty("severity")) {
+ vr.severity = DEFAULT_SEVERITY;
+ }
+ if (!vr.hasOwnProperty("vulnerabilityStatus")) {
+ vr.vulnerabilityStatus = VULNERABILITYSTATUS_NONE;
+ }
+
+ if (!Array.isArray(vr.targetApplication)) {
+ vr.targetApplication = [];
+ }
+ if (!vr.targetApplication.length) {
+ vr.targetApplication.push({minVersion: null, maxVersion: null});
+ }
+ vr.targetApplication.forEach(tA => {
+ if (!tA.guid) {
+ tA.guid = gAppID;
+ }
+ });
+ }
+ },
+
+ /**
+ * Create a blocklist URL for the given blockID
+ * @param {String} id the blockID to use
+ * @returns {String} the blocklist URL.
+ */
+ _createBlocklistURL(id) {
+ let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL);
+ return url.replace(/%blockID%/g, id);
+ },
+
+};
/**
* The Graphics blocklist implementation. The JSON objects for graphics blocks look
* something like:
*
* {
* "blockID": "g35",
* "os": "WINNT 6.1",
@@ -250,16 +331,586 @@ this.GfxBlocklist = {
}
Services.obs.notifyObservers(null, "blocklist-data-gfxItems", payload.join("\n"));
}
// The return value is only used by tests.
return entries;
},
};
+/**
+ * The plugins blocklist implementation. The JSON objects for plugin blocks look
+ * something like:
+ *
+ * {
+ * "blockID":"p906",
+ * "details": {
+ * "bug":"https://bugzilla.mozilla.org/show_bug.cgi?id=1159917",
+ * "who":"Which users it affects",
+ * "why":"Why it's being blocklisted",
+ * "name":"Java Plugin 7 update 45 to 78 (click-to-play), Windows",
+ * "created":"2015-05-19T09:02:45Z"
+ * },
+ * "enabled":true,
+ * "infoURL":"https://java.com/",
+ * "matchName":"Java\\(TM\\) Platform SE 7 U(4[5-9]|(5|6)\\d|7[0-8])(\\s[^\\d\\._U]|$)",
+ * "versionRange":[
+ * {
+ * "severity":0,
+ * "targetApplication":[
+ * {
+ * "guid":"{ec8030f7-c20a-464f-9b0e-13a3a9e97384}",
+ * "maxVersion":"57.0.*",
+ * "minVersion":"0"
+ * }
+ * ],
+ * "vulnerabilityStatus":1
+ * }
+ * ],
+ * "matchFilename":"npjp2\\.dll",
+ * "id":"f254e5bc-12c7-7954-fe6b-8f1fdab0ae88",
+ * "last_modified":1519390914542,
+ * }
+ *
+ * Note: we assign to the global to allow tests to reach the object directly.
+ */
+this.PluginBlocklist = {
+ _matchProps: {
+ "matchDescription": "description",
+ "matchFilename": "filename",
+ "matchName": "name",
+ },
+
+ async _ensureEntries() {
+ await this._ensureInitialized();
+ if (!this._entries && gBlocklistEnabled) {
+ await this._updateEntries();
+
+ // Dispatch to mainthread because consumers may try to construct nsIPluginHost
+ // again based on this notification, while we were called from nsIPluginHost
+ // anyway, leading to re-entrancy.
+ Services.tm.dispatchToMainThread(function() {
+ Services.obs.notifyObservers(null, "plugin-blocklist-loaded");
+ });
+ }
+ },
+
+ async _updateEntries() {
+ this._entries = await this._client.get().catch(ex => Cu.reportError(ex));
+ // Handle error silently. This can happen if our request to fetch data is aborted,
+ // e.g. by application shutdown.
+ if (!this._entries) {
+ this._entries = [];
+ return;
+ }
+ this._entries.forEach(entry => {
+ entry.matches = {};
+ for (let k of Object.keys(this._matchProps)) {
+ if (entry[k]) {
+ try {
+ entry.matches[this._matchProps[k]] = new RegExp(entry[k], "m");
+ } catch (ex) { /* Ignore invalid regexes */ }
+ }
+ }
+ Utils.ensureVersionRangeIsSane(entry);
+ });
+ },
+
+ async _filterItem(entry) {
+ if (!(await BlocklistRemoteSettings.targetAppFilter(entry, {appID: gAppID, version: gApp.version}))) {
+ return null;
+ }
+ if (!Utils.matchesOSABI(entry)) {
+ Cu.reportError("OSABI mismatch " + entry.matchName);
+ return null;
+ }
+ if (!entry.matchFilename && !entry.matchName && !entry.matchDescription) {
+ Cu.reportError("Nothing to filter on");
+ return null;
+ }
+ return entry;
+ },
+
+ async _ensureInitialized() {
+ if (!gBlocklistEnabled || this._initialized) {
+ return;
+ }
+ this._initialized = true;
+ this._client = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_COLLECTION), {
+ bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET),
+ lastCheckTimePref: PREF_BLOCKLIST_PLUGINS_CHECKED_SECONDS,
+ signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_PLUGINS_SIGNER),
+ filterFunc: this._filterItem,
+ });
+ this._client.on("sync", () => {
+ this._onUpdate();
+ });
+ },
+
+ async _onUpdate() {
+ let oldEntries = this._entries || [];
+ await this._updateEntries();
+ const pluginHost = Cc["@mozilla.org/plugin/host;1"].
+ getService(Ci.nsIPluginHost);
+ const plugins = pluginHost.getPluginTags();
+
+ let blockedItems = [];
+
+ for (let plugin of plugins) {
+ let oldState = this._getState(plugin, oldEntries);
+ let state = this._getState(plugin, this._entries);
+ LOG("Blocklist state for " + plugin.name + " changed from " +
+ oldState + " to " + state);
+ // We don't want to re-warn about items
+ if (state == oldState)
+ continue;
+
+ if (oldState == Ci.nsIBlocklistService.STATE_BLOCKED) {
+ if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
+ plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
+ } else if (!plugin.disabled && state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
+ if (state != Ci.nsIBlocklistService.STATE_OUTDATED &&
+ state != Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE &&
+ state != Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE) {
+ blockedItems.push({
+ name: plugin.name,
+ version: plugin.version,
+ icon: "chrome://mozapps/skin/plugins/pluginGeneric.svg",
+ disable: false,
+ blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
+ item: plugin,
+ url: await this.getURL(plugin),
+ });
+ }
+ }
+ }
+
+ if (blockedItems.length) {
+ this._showBlockedPluginsPrompt(blockedItems);
+ } else {
+ this._notifyUpdate();
+ }
+ },
+
+ _showBlockedPluginsPrompt(blockedPlugins) {
+ if ("@mozilla.org/addons/blocklist-prompt;1" in Cc) {
+ try {
+ let blockedPrompter = Cc["@mozilla.org/addons/blocklist-prompt;1"]
+ .getService().wrappedJSObject;
+ blockedPrompter.prompt(blockedPlugins);
+ } catch (e) {
+ LOG(e);
+ }
+ this._notifyUpdate();
+ return;
+ }
+
+ let args = {
+ restart: false,
+ list: blockedPlugins
+ };
+ // This lets the dialog get the raw js object
+ args.wrappedJSObject = args;
+
+ /*
+ Some tests run without UI, so the async code listens to a message
+ that can be sent programatically
+ */
+ let applyBlocklistChanges = async () => {
+ Services.obs.removeObserver(applyBlocklistChanges, "addon-blocklist-closed");
+
+ for (let blockedData of blockedPlugins) {
+ if (!blockedData.disable)
+ continue;
+
+ // This will disable all the plugins immediately.
+ if (blockedData.item instanceof Ci.nsIPluginTag) {
+ blockedData.item.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
+ }
+ }
+
+ if (!args.restart) {
+ this._notifyUpdate();
+ return;
+ }
+
+ // We need to ensure the new blocklist state is written to disk before restarting.
+ // We'll notify about the blocklist update, then wait for nsIPluginHost
+ // to finish processing it, then restart the browser.
+ let pluginUpdatesFinishedPromise = new Promise(resolve => {
+ Services.obs.addObserver(function updatesFinished() {
+ Services.obs.removeObserver(updatesFinished, "plugin-blocklist-updates-finished");
+ resolve();
+ }, "plugin-blocklist-updates-finished");
+ });
+ this._notifyUpdate();
+ await pluginUpdatesFinishedPromise;
+
+ // Notify all windows that an application quit has been requested.
+ var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].
+ createInstance(Ci.nsISupportsPRBool);
+ Services.obs.notifyObservers(cancelQuit, "quit-application-requested");
+
+ // Something aborted the quit process.
+ if (cancelQuit.data)
+ return;
+
+ Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
+ };
+
+ Services.obs.addObserver(applyBlocklistChanges, "addon-blocklist-closed");
+
+ if (Services.prefs.getBoolPref(PREF_BLOCKLIST_SUPPRESSUI, false)) {
+ applyBlocklistChanges();
+ return;
+ }
+
+ function blocklistUnloadHandler(event) {
+ if (event.target.location == URI_BLOCKLIST_DIALOG) {
+ applyBlocklistChanges();
+ blocklistWindow.removeEventListener("unload", blocklistUnloadHandler);
+ }
+ }
+
+ let blocklistWindow = Services.ww.openWindow(null, URI_BLOCKLIST_DIALOG, "",
+ "chrome,centerscreen,dialog,titlebar", args);
+ if (blocklistWindow)
+ blocklistWindow.addEventListener("unload", blocklistUnloadHandler);
+ },
+
+ _notifyUpdate() {
+ Services.obs.notifyObservers(null, "plugin-blocklist-updated");
+ },
+
+ async getURL(plugin) {
+ await this._ensureEntries();
+ let r = this._getEntry(plugin, this._entries);
+ if (!r) {
+ return null;
+ }
+ let blockEntry = r.entry;
+ if (!blockEntry.blockID) {
+ return null;
+ }
+
+ return blockEntry.infoURL || Utils._createBlocklistURL(blockEntry.blockID);
+ },
+
+ async getState(plugin, appVersion, toolkitVersion) {
+ if (AppConstants.platform == "android") {
+ return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
+ }
+ await this._ensureEntries();
+ return this._getState(plugin, this._entries, appVersion, toolkitVersion);
+ },
+
+ async getEntry(plugin, appVersion, toolkitVersion) {
+ await this._ensureEntries();
+ return this._getEntry(plugin, this._entries, appVersion, toolkitVersion);
+ },
+
+ /**
+ * Private helper to get the blocklist entry for a plugin given a set of
+ * blocklist entries and versions.
+ *
+ * @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.
+ */
+ _getEntry(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;
+
+ if (!appVersion)
+ appVersion = gApp.version;
+ if (!toolkitVersion)
+ toolkitVersion = gApp.platformVersion;
+
+ const pluginProperties = {
+ description: plugin.description,
+ filename: plugin.filename,
+ name: plugin.name,
+ version: plugin.version,
+ };
+ if (!pluginEntries) {
+ Cu.reportError(new Error("Hi"));
+ }
+ for (let blockEntry of pluginEntries) {
+ var matchFailed = false;
+ for (var name in blockEntry.matches) {
+ let pluginProperty = pluginProperties[name];
+ if (typeof pluginProperty != "string" ||
+ !blockEntry.matches[name].test(pluginProperty)) {
+ matchFailed = true;
+ break;
+ }
+ }
+
+ if (matchFailed)
+ continue;
+
+ for (let versionRange of blockEntry.versionRange) {
+ if (Utils.versionsMatch(versionRange, pluginProperties.version,
+ appVersion, toolkitVersion)) {
+ return {entry: blockEntry, version: versionRange};
+ }
+ }
+ }
+
+ return null;
+ },
+
+
+ /**
+ * Private version of getState that allows the caller to pass in
+ * the plugin blocklist entries.
+ *
+ * @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.
+ */
+ _getState(plugin, pluginEntries, appVersion, toolkitVersion) {
+ let r = this._getEntry(plugin, pluginEntries, appVersion, toolkitVersion);
+ if (!r) {
+ return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
+ }
+
+ let {version: versionRange} = r;
+
+ if (versionRange.severity >= gBlocklistLevel)
+ return Ci.nsIBlocklistService.STATE_BLOCKED;
+ if (versionRange.severity == SEVERITY_OUTDATED) {
+ let vulnerabilityStatus = versionRange.vulnerabilityStatus;
+ if (vulnerabilityStatus == VULNERABILITYSTATUS_UPDATE_AVAILABLE)
+ return Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE;
+ if (vulnerabilityStatus == VULNERABILITYSTATUS_NO_UPDATE)
+ return Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE;
+ return Ci.nsIBlocklistService.STATE_OUTDATED;
+ }
+ return Ci.nsIBlocklistService.STATE_SOFTBLOCKED;
+ },
+
+};
+
+/**
+ * The extensions blocklist implementation. The JSON objects for extension
+ * blocks look something like:
+ *
+ * FIXME needs example.
+ *
+ * Note: we assign to the global to allow tests to reach the object directly.
+ */
+this.ExtensionBlocklist = {
+ async _ensureEntries() {
+ await this._ensureInitialized();
+ if (!this._entries && gBlocklistEnabled) {
+ await this._updateEntries();
+ }
+ },
+
+ async _updateEntries() {
+ this._entries = await this._client.get().catch(ex => Cu.reportError(ex));
+ // Handle error silently. This can happen if our request to fetch data is aborted,
+ // e.g. by application shutdown.
+ if (!this._entries) {
+ this._entries = [];
+ return;
+ }
+ this._entries.forEach(entry => {
+ function getCriteria(str) {
+ if (!str.startsWith("/")) {
+ return str;
+ }
+ let lastSlash = str.lastIndexOf("/");
+ let pattern = str.slice(1, lastSlash);
+ let flags = str.slice(lastSlash + 1);
+ return new RegExp(pattern, flags);
+ }
+ entry.matches = {};
+ if (entry.guid) {
+ entry.matches.id = getCriteria(entry.guid);
+ }
+ for (let key of EXTENSION_BLOCK_FILTERS) {
+ if (key == "id" || !entry[key]) {
+ continue;
+ }
+ entry.matches[key] = getCriteria(entry[key]);
+ }
+ Utils.ensureVersionRangeIsSane(entry);
+ });
+ },
+
+ async _filterItem(entry) {
+ if (!(await BlocklistRemoteSettings.targetAppFilter(entry, {appID: gAppID, version: gApp.version}))) {
+ Cu.reportError("RS ditched " + entry.guid);
+ return null;
+ }
+ if (!Utils.matchesOSABI(entry)) {
+ Cu.reportError("OSABI mismatch " + entry.guid);
+ return null;
+ }
+ // Need something to filter on - at least a guid or name (either could be a regex):
+ if (!entry.guid && !entry.name) {
+ Cu.reportError("No guid/name");
+ return null;
+ }
+ return entry;
+ },
+
+ async _ensureInitialized() {
+ if (!gBlocklistEnabled || this._initialized) {
+ return;
+ }
+ this._initialized = true;
+ this._client = RemoteSettings(Services.prefs.getCharPref(PREF_BLOCKLIST_ADDONS_COLLECTION), {
+ bucketName: Services.prefs.getCharPref(PREF_BLOCKLIST_BUCKET),
+ lastCheckTimePref: PREF_BLOCKLIST_ADDONS_CHECKED_SECONDS,
+ signerName: Services.prefs.getCharPref(PREF_BLOCKLIST_ADDONS_SIGNER),
+ filterFunc: this._filterItem,
+ });
+ this._client.on("sync", () => {
+ this._onUpdate();
+ });
+ },
+
+ async _onUpdate() {
+ let oldEntries = this._entries || [];
+ await this._updateEntries();
+
+ const types = ["extension", "theme", "locale", "dictionary", "service"];
+ let addons = await AddonManager.getAddonsByTypes(types);
+ for (let addon of addons) {
+ let oldState = addon.blocklistState;
+ if (addon.updateBlocklistState) {
+ await addon.updateBlocklistState(false);
+ } else if (oldEntries) {
+ let oldEntry = this._getEntry(addon, oldEntries);
+ oldState = oldEntry ? oldEntry.state : Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
+ } else {
+ oldState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
+ }
+ 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;
+
+ // Ensure that softDisabled is false if the add-on is not soft blocked
+ if (state != Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
+ addon.softDisabled = false;
+
+ // If an add-on has dropped from hard to soft blocked just mark it as
+ // soft disabled and don't warn about it.
+ if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED &&
+ oldState == Ci.nsIBlocklistService.STATE_BLOCKED) {
+ addon.softDisabled = true;
+ }
+
+ if (state == Ci.nsIBlocklistService.STATE_BLOCKED ||
+ state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED) {
+ // Mark it as softblocked if necessary. Note that we avoid setting
+ // softDisabled at the same time as userDisabled to make it clear
+ // which was the original cause of the add-on becoming disabled in a
+ // way that the user can change.
+ if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED && !addon.userDisabled)
+ addon.softDisabled = true;
+ // It's a block. We must reset certain preferences.
+ let entry = this._getEntry(addon, this._entries);
+ if (entry.prefs && entry.prefs.length) {
+ for (let pref of entry.prefs) {
+ Services.prefs.clearUserPref(pref);
+ }
+ }
+ }
+ }
+
+ AddonManagerPrivate.updateAddonAppDisabledStates();
+ },
+
+ async getState(addon, appVersion, toolkitVersion) {
+ let entry = await this.getEntry(addon, appVersion, toolkitVersion);
+ return entry ? entry.state : Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
+ },
+
+ async getEntry(addon, appVersion, toolkitVersion) {
+ await this._ensureEntries();
+ return this._getEntry(addon, this._entries, appVersion, toolkitVersion);
+ },
+
+ _getEntry(addon, addonEntries, appVersion, toolkitVersion) {
+ if (!gBlocklistEnabled || !addon)
+ 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;
+
+ let addonProps = {};
+ for (let key of EXTENSION_BLOCK_FILTERS) {
+ addonProps[key] = addon[key];
+ }
+ if (addonProps.creator)
+ addonProps.creator = addonProps.creator.name;
+
+ let propMatches = ([k, v]) => {
+ return !v || addonProps[k] == v || ((v instanceof RegExp) && v.test(addonProps[k]));
+ };
+ for (let entry of addonEntries) {
+ // First check if it matches our properties. If not, just skip to the next item.
+ if (!Object.entries(entry.matches).every(propMatches)) {
+ continue;
+ }
+ // If those match, check the app or toolkit version works:
+ for (let versionRange of entry.versionRange) {
+ if (Utils.versionsMatch(versionRange, addon.version,
+ appVersion, toolkitVersion)) {
+ return {
+ state: versionRange.severity >= gBlocklistLevel ?
+ Ci.nsIBlocklistService.STATE_BLOCKED : Ci.nsIBlocklistService.STATE_SOFTBLOCKED,
+ url: entry.blockID && Utils._createBlocklistURL(entry.blockID),
+ };
+ }
+ }
+ }
+ return null;
+ },
+};
+
const EXTENSION_BLOCK_FILTERS = ["id", "name", "creator", "homepageURL", "updateURL"];
var gLoggingEnabled = null;
var gBlocklistEnabled = true;
var gBlocklistLevel = DEFAULT_LEVEL;
/**
* @class nsIBlocklistPrompt
@@ -303,29 +954,25 @@ XPCOMUtils.defineLazyGetter(this, "gApp"
throw ex;
}
return appinfo;
});
XPCOMUtils.defineLazyGetter(this, "gAppID", function() {
return gApp.ID;
});
-
XPCOMUtils.defineLazyGetter(this, "gAppVersion", function() {
return gApp.version;
});
+XPCOMUtils.defineLazyGetter(this, "gAppOS", function() {
+ return gApp.OS;
+});
-XPCOMUtils.defineLazyGetter(this, "gABI", function() {
- let abi = null;
- try {
- abi = gApp.XPCOMABI;
- } catch (e) {
- LOG("BlockList Global gABI: XPCOM ABI unknown.");
- }
- return abi;
+XPCOMUtils.defineLazyGetter(this, "gXPCOMABI", function() {
+ return gApp.XPCOMABI;
});
XPCOMUtils.defineLazyGetter(this, "gOSVersion", function() {
let osVersion;
try {
osVersion = Services.sysinfo.getProperty("name") + " " + Services.sysinfo.getProperty("version");
} catch (e) {
LOG("BlockList Global gOSVersion: OS Version unknown.");
@@ -349,70 +996,16 @@ XPCOMUtils.defineLazyGetter(this, "gOSVe
*/
function LOG(string) {
if (gLoggingEnabled) {
dump("*** " + string + "\n");
Services.console.logStringMessage(string);
}
}
-// Restarts the application checking in with observers first
-function restartApp() {
- // Notify all windows that an application quit has been requested.
- var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].
- createInstance(Ci.nsISupportsPRBool);
- Services.obs.notifyObservers(cancelQuit, "quit-application-requested");
-
- // Something aborted the quit process.
- if (cancelQuit.data)
- return;
-
- 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) {
- let os = blocklistElement.getAttribute("os");
- if (os) {
- let choices = os.split(",");
- if (choices.length > 0 && !choices.includes(gApp.OS))
- return false;
- }
-
- let xpcomabi = blocklistElement.getAttribute("xpcomabi");
- if (xpcomabi) {
- let choices = xpcomabi.split(",");
- if (choices.length > 0 && !choices.includes(gApp.XPCOMABI))
- return false;
- }
-
- 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");
}
/**
* Manages the Blocklist. The Blocklist is a representation of the contents of
* blocklist.xml and allows us to remotely disable / re-enable blocklisted
@@ -428,93 +1021,62 @@ var 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);
// If the stub blocklist service deferred any queries because we
// weren't loaded yet, execute them now.
for (let entry of Services.blocklist.pluginQueries.splice(0)) {
- entry.resolve(this.getPluginBlocklistState(entry.plugin,
- entry.appVersion,
- entry.toolkitVersion));
+ entry.resolve(PluginBlocklist.getState(entry.plugin, entry.appVersion, entry.toolkitVersion));
}
},
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)
- * 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 = *)
- */
- _addonEntries: null,
- _pluginEntries: null,
-
shutdown() {
Services.obs.removeObserver(this, "xpcom-shutdown");
Services.prefs.removeObserver("extensions.blocklist.", this);
Services.prefs.removeObserver(PREF_EM_LOGGING_ENABLED, this);
},
observe(aSubject, aTopic, aData) {
switch (aTopic) {
case "xpcom-shutdown":
this.shutdown();
break;
case "profile-after-change":
- // We're only called here on non-Desktop-Firefox, and use this opportunity to try to
- // load the blocklist asynchronously. On desktop Firefox, we load the list from
+ // We're only called here on non-Desktop-Firefox, and use this opportunity to
+ // start gfx blocklist checks. On desktop Firefox, we do so from
// nsBrowserGlue after sessionstore-windows-restored.
- this.loadBlocklistAsync();
this.checkForGfxBlocklistEntries();
break;
case "nsPref:changed":
switch (aData) {
case PREF_EM_LOGGING_ENABLED:
gLoggingEnabled = Services.prefs.getBoolPref(PREF_EM_LOGGING_ENABLED, false);
break;
case PREF_BLOCKLIST_ENABLED:
gBlocklistEnabled = Services.prefs.getBoolPref(PREF_BLOCKLIST_ENABLED, true);
- // This is a bit messy. Especially in tests, but in principle also by users toggling
- // this preference repeatedly, plugin loads could race with each other if we don't
- // enforce that they are applied sequentially.
- // So we only update once the previous `_blocklistUpdated` call finishes running.
- let lastUpdate = this._lastUpdate || undefined;
- let newUpdate = this._lastUpdate = (async () => {
- await lastUpdate;
- this._clear();
- await this.loadBlocklistAsync();
- await this._blocklistUpdated(null, null);
- this.checkForGfxBlocklistEntries();
- if (newUpdate == this._lastUpdate) {
- delete this._lastUpdate;
- }
- })().catch(Cu.reportError);
+ // Re-run gfx initialization in case we're now enabled. If we were disabled,
+ // the kinto component will continue running, but we'll not do anything when
+ // updates happen. We'll stop initializing next time Firefox is restarted.
+ this.checkForGfxBlocklistEntries();
+ // We don't need to do this for plugin/addon items, they'll just start
+ // returning data the next time they're called (or not, as the case may be).
break;
case PREF_BLOCKLIST_LEVEL:
gBlocklistLevel = Math.min(Services.prefs.getIntPref(PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL),
MAX_BLOCK_LEVEL);
- this._blocklistUpdated(null, null);
+ // FIXME need to do something here?
break;
}
break;
}
},
checkForGfxBlocklistEntries() {
GfxBlocklist.checkForEntries();
@@ -530,67 +1092,17 @@ var Blocklist = {
* 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.
*/
async getAddonBlocklistState(addon, appVersion, toolkitVersion) {
- await this.loadBlocklistAsync();
- return this._getAddonBlocklistState(addon, this._addonEntries,
- appVersion, toolkitVersion);
- },
-
- /**
- * Returns a matching blocklist entry for the given add-on, if one
- * exists.
- *
- * @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).
- if (!appVersion && !gAppVersion)
- return null;
-
- if (!appVersion)
- appVersion = gAppVersion;
- 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;
+ return ExtensionBlocklist.getState(addon, appVersion, 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.
@@ -604,101 +1116,17 @@ var Blocklist = {
* 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 {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} 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)
- return null;
- // Returns true if the params object passes the constraints set by entry.
- // (For every non-null property in entry, the same key must exist in
- // params and value must be the same)
- function checkEntry(entry, params) {
- for (let [key, value] of Object.entries(entry)) {
- if (value === null || value === undefined)
- continue;
- if (params[key]) {
- if (value instanceof RegExp) {
- if (!value.test(params[key])) {
- return false;
- }
- } else if (value !== params[key]) {
- return false;
- }
- } else {
- return false;
- }
- }
- return true;
- }
-
- let params = {};
- for (let filter of EXTENSION_BLOCK_FILTERS) {
- params[filter] = aAddon[filter];
- }
- if (params.creator)
- params.creator = params.creator.name;
- for (let entry of aAddonEntries) {
- if (checkEntry(entry.attributes, params)) {
- return entry;
- }
- }
- return null;
- },
-
- _createBlocklistURL(id) {
- let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL);
- return url.replace(/%blockID%/g, id);
+ return ExtensionBlocklist.getEntry(addon, appVersion, toolkitVersion);
},
notify(aTimer) {
if (!gBlocklistEnabled)
return;
try {
var dsURI = Services.prefs.getCharPref(PREF_BLOCKLIST_URL);
@@ -734,19 +1162,19 @@ var Blocklist = {
pingCountVersion = 1;
if (pingCountTotal < 1)
pingCountTotal = 1;
let replacements = {
APP_ID: gAppID,
PRODUCT: gApp.name,
BUILD_ID: gApp.appBuildID,
- BUILD_TARGET: gApp.OS + "_" + gABI,
+ BUILD_TARGET: gAppOS + "_" + gXPCOMABI,
OS_VERSION: gOSVersion,
- LOCALE: getLocale(),
+ LOCALE: Services.locale.getRequestedLocale(),
CHANNEL: UpdateUtils.UpdateChannel,
PLATFORM_VERSION: gApp.platformVersion,
DISTRIBUTION: getDistributionPrefValue(PREF_APP_DISTRIBUTION),
DISTRIBUTION_VERSION: getDistributionPrefValue(PREF_APP_DISTRIBUTION_VERSION),
PING_COUNT: pingCountVersion,
TOTAL_PING_COUNT: pingCountTotal,
DAYS_SINCE_LAST_PING: daysSinceLastPing,
};
@@ -848,35 +1276,16 @@ var Blocklist = {
if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR) {
LOG("Blocklist::onXMLLoad: there was an error during load, we got invalid XML");
return;
}
// Save current blocklist timestamp to pref.
const lastModified = request.getResponseHeader("Last-Modified") || "";
Services.prefs.setCharPref(PREF_BLOCKLIST_LAST_MODIFIED, lastModified);
-
- if (!this.isLoaded) {
- await this.loadBlocklistAsync();
- }
-
- var oldAddonEntries = this._addonEntries;
- var oldPluginEntries = this._pluginEntries;
-
- await this._loadBlocklistFromXML(responseXML);
- // We don't inform the users when the graphics blocklist changed at runtime.
- // However addons and plugins blocking status is refreshed.
- this._blocklistUpdated(oldAddonEntries, oldPluginEntries);
-
- try {
- let path = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST);
- await OS.File.writeAtomic(path, request.responseText, {tmpPath: path + ".tmp"});
- } catch (e) {
- LOG("Blocklist::onXMLLoad: " + e);
- }
},
onXMLError(aEvent) {
try {
var request = aEvent.target;
// the following may throw (e.g. a local file or timeout)
var status = request.status;
} catch (e) {
@@ -894,719 +1303,22 @@ var Blocklist = {
LOG("Blocklist:onError: There was an error loading the blocklist file\r\n" +
statusText);
},
/**
* Whether or not we've finished loading the blocklist.
*/
get isLoaded() {
- return this._addonEntries != null && this._pluginEntries != null;
- },
-
- /* Used for testing */
- _clear() {
- this._addonEntries = null;
- this._pluginEntries = null;
- delete this._loadPromise;
- },
-
- /**
- * Trigger loading the blocklist content asynchronously.
- */
- async loadBlocklistAsync() {
- if (this.isLoaded) {
- return;
- }
- if (!this._loadPromise) {
- this._loadPromise = this._loadBlocklistAsyncInternal();
- }
- await this._loadPromise;
- },
-
- async _loadBlocklistAsyncInternal() {
- try {
- // Get the path inside the try...catch because there's no profileDir in e.g. xpcshell tests.
- let profFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]);
- await this._loadFileInternal(profFile);
- return;
- } catch (e) {
- LOG("Blocklist::loadBlocklistAsync: Failed to load XML file " + e);
- }
-
- var appFile = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]);
- try {
- await this._loadFileInternal(appFile);
- return;
- } catch (e) {
- LOG("Blocklist::loadBlocklistAsync: Failed to load XML file " + e);
- }
-
- LOG("Blocklist::loadBlocklistAsync: no XML File found");
- // Neither file is present, so we just add empty lists, to avoid JS errors fetching
- // blocklist information otherwise.
- this._addonEntries = [];
- this._pluginEntries = [];
- },
-
- async _loadFileInternal(file) {
- if (this.isLoaded) {
- return;
- }
-
- if (!gBlocklistEnabled) {
- LOG("Blocklist::_loadFileInternal: blocklist is disabled");
- return;
- }
-
- let xmlDoc = await new Promise((resolve, reject) => {
- let request = new XMLHttpRequest();
- request.open("GET", Services.io.newFileURI(file).spec, true);
- request.overrideMimeType("text/xml");
- request.addEventListener("error", reject);
- request.addEventListener("load", function() {
- let {status} = request;
- if (status != 200 && status != 0) {
- LOG("_loadFileInternal: there was an error during load, got status: " + status);
- reject(new Error("Couldn't load blocklist file"));
- return;
- }
- let doc = request.responseXML;
- if (doc.documentElement.namespaceURI != XMLURI_BLOCKLIST) {
- LOG("Blocklist::_loadBlocklistFromString: aborting due to incorrect " +
- "XML Namespace.\nExpected: " + XMLURI_BLOCKLIST + "\n" +
- "Received: " + doc.documentElement.namespaceURI);
- reject(new Error("Local blocklist file has the wrong namespace!"));
- return;
- }
- resolve(doc);
- });
- request.send(null);
- });
-
- await new Promise(resolve => {
- ChromeUtils.idleDispatch(async () => {
- if (!this.isLoaded) {
- await this._loadBlocklistFromXML(xmlDoc);
- }
- resolve();
- });
- });
- },
-
- async _loadBlocklistFromXML(doc) {
- this._addonEntries = [];
- this._pluginEntries = [];
- try {
- var children = doc.documentElement.children;
- for (let element of children) {
- switch (element.localName) {
- case "emItems":
- this._addonEntries = await this._processItemNodes(element.children, "emItem",
- this._handleEmItemNode);
- break;
- case "pluginItems":
- this._pluginEntries = await this._processItemNodes(element.children, "pluginItem",
- this._handlePluginItemNode);
- break;
- default:
- LOG("Blocklist::_loadBlocklistFromXML: ignored entries " + element.localName);
- }
- }
- } catch (e) {
- LOG("Blocklist::_loadBlocklistFromXML: Error constructing blocklist " + e);
- }
- // Dispatch to mainthread because consumers may try to construct nsIPluginHost
- // again based on this notification, while we were called from nsIPluginHost
- // anyway, leading to re-entrancy.
- Services.tm.dispatchToMainThread(function() {
- Services.obs.notifyObservers(null, "blocklist-loaded");
- });
- },
-
- async _processItemNodes(items, itemName, handler) {
- var result = [];
- let deadline = await new Promise(ChromeUtils.idleDispatch);
- for (let item of items) {
- if (item.localName == itemName) {
- handler(item, result);
- }
- if (!deadline || deadline.didTimeout || deadline.timeRemaining() < 1) {
- deadline = await new Promise(ChromeUtils.idleDispatch);
- }
- }
- return result;
- },
-
- _handleEmItemNode(blocklistElement, result) {
- if (!matchesOSABI(blocklistElement))
- return;
-
- let blockEntry = {
- versions: [],
- prefs: [],
- blockID: null,
- attributes: {},
- // Atleast one of EXTENSION_BLOCK_FILTERS must get added to attributes
- };
-
- for (let filter of EXTENSION_BLOCK_FILTERS) {
- let attr = blocklistElement.getAttribute(filter);
- if (attr) {
- // Any filter starting with '/' is interpreted as a regex. So if an attribute
- // starts with a '/' it must be checked via a regex.
- if (attr.startsWith("/")) {
- let lastSlash = attr.lastIndexOf("/");
- let pattern = attr.slice(1, lastSlash);
- let flags = attr.slice(lastSlash + 1);
- blockEntry.attributes[filter] = new RegExp(pattern, flags);
- } else {
- blockEntry.attributes[filter] = attr;
- }
- }
- }
-
- var children = blocklistElement.children;
-
- for (let childElement of children) {
- let localName = childElement.localName;
- if (localName == "prefs" && childElement.hasChildNodes) {
- let prefElements = childElement.children;
- for (let prefElement of prefElements) {
- if (prefElement.localName == "pref") {
- blockEntry.prefs.push(prefElement.textContent);
- }
- }
- } else if (localName == "versionRange") {
- blockEntry.versions.push(new BlocklistItemData(childElement));
- }
- }
- // if only the extension ID is specified block all versions of the
- // extension for the current application.
- if (blockEntry.versions.length == 0)
- blockEntry.versions.push(new BlocklistItemData(null));
-
- blockEntry.blockID = blocklistElement.getAttribute("blockID");
-
- result.push(blockEntry);
- },
-
- _handlePluginItemNode(blocklistElement, result) {
- if (!matchesOSABI(blocklistElement))
- return;
-
- let children = blocklistElement.children;
- var blockEntry = {
- matches: {},
- versions: [],
- blockID: null,
- infoURL: null,
- };
- var hasMatch = false;
- for (let childElement of children) {
- switch (childElement.localName) {
- case "match":
- var name = childElement.getAttribute("name");
- var exp = childElement.getAttribute("exp");
- try {
- blockEntry.matches[name] = new RegExp(exp, "m");
- hasMatch = true;
- } catch (e) {
- // Ignore invalid regular expressions
- }
- break;
- case "versionRange":
- blockEntry.versions.push(new BlocklistItemData(childElement));
- break;
- case "infoURL":
- blockEntry.infoURL = childElement.textContent;
- break;
- }
- }
- // Plugin entries require *something* to match to an actual plugin
- if (!hasMatch)
- return;
- // Add a default versionRange if there wasn't one specified
- if (blockEntry.versions.length == 0)
- blockEntry.versions.push(new BlocklistItemData(null));
-
- blockEntry.blockID = blocklistElement.getAttribute("blockID");
-
- result.push(blockEntry);
+ return PluginBlocklist.isLoaded;
},
/* See nsIBlocklistService */
async getPluginBlocklistState(plugin, appVersion, toolkitVersion) {
- if (AppConstants.platform == "android") {
- return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
- }
- await this.loadBlocklistAsync();
- 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 {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 && !gAppVersion)
- return Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
-
- if (!appVersion)
- appVersion = gAppVersion;
- if (!toolkitVersion)
- toolkitVersion = gApp.platformVersion;
-
- const pluginProperties = {
- description: plugin.description,
- filename: plugin.filename,
- name: plugin.name,
- version: plugin.version,
- };
- for (var blockEntry of pluginEntries) {
- var matchFailed = false;
- for (var name in blockEntry.matches) {
- let pluginProperty = pluginProperties[name];
- if (typeof(pluginProperty) !== "string" ||
- !blockEntry.matches[name].test(pluginProperty)) {
- matchFailed = true;
- break;
- }
- }
-
- if (matchFailed)
- continue;
-
- for (let blockEntryVersion of blockEntry.versions) {
- if (blockEntryVersion.includesItem(pluginProperties.version, appVersion,
- toolkitVersion)) {
- return {entry: blockEntry, version: blockEntryVersion};
- }
- }
- }
-
- return null;
- },
-
- /**
- * Private version of getPluginBlocklistState that allows the caller to pass in
- * the plugin blocklist entries.
- *
- * @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;
- }
-
- let {version: blockEntryVersion} = r;
-
- if (blockEntryVersion.severity >= gBlocklistLevel)
- return Ci.nsIBlocklistService.STATE_BLOCKED;
- if (blockEntryVersion.severity == SEVERITY_OUTDATED) {
- let vulnerabilityStatus = blockEntryVersion.vulnerabilityStatus;
- if (vulnerabilityStatus == VULNERABILITYSTATUS_UPDATE_AVAILABLE)
- return Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE;
- if (vulnerabilityStatus == VULNERABILITYSTATUS_NO_UPDATE)
- return Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE;
- return Ci.nsIBlocklistService.STATE_OUTDATED;
- }
- return Ci.nsIBlocklistService.STATE_SOFTBLOCKED;
+ return PluginBlocklist.getState(plugin, appVersion, toolkitVersion);
},
async getPluginBlockURL(plugin) {
- await this.loadBlocklistAsync();
-
- let r = this._getPluginBlocklistEntry(plugin, this._pluginEntries);
- if (!r) {
- return null;
- }
- let blockEntry = r.entry;
- if (!blockEntry.blockID) {
- return null;
- }
-
- return blockEntry.infoURL || this._createBlocklistURL(blockEntry.blockID);
- },
-
- _notifyObserversBlocklistUpdated() {
- Services.obs.notifyObservers(this, "blocklist-updated");
- },
-
- async _blocklistUpdated(oldAddonEntries, oldPluginEntries) {
- var addonList = [];
-
- // A helper function that reverts the prefs passed to default values.
- function resetPrefs(prefs) {
- for (let pref of prefs)
- Services.prefs.clearUserPref(pref);
- }
- const types = ["extension", "theme", "locale", "dictionary", "service"];
- let addons = await AddonManager.getAddonsByTypes(types);
- for (let addon of addons) {
- let oldState = addon.blocklistState;
- if (addon.updateBlocklistState) {
- await addon.updateBlocklistState(false);
- } else if (oldAddonEntries) {
- oldState = this._getAddonBlocklistState(addon, oldAddonEntries);
- } else {
- oldState = Ci.nsIBlocklistService.STATE_NOT_BLOCKED;
- }
- 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;
-
- // If an add-on has dropped from hard to soft blocked just mark it as
- // soft disabled and don't warn about it.
- if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED &&
- oldState == Ci.nsIBlocklistService.STATE_BLOCKED) {
- addon.softDisabled = true;
- continue;
- }
-
- // If the add-on is already disabled for some reason then don't warn
- // about it
- if (!addon.isActive) {
- // But mark it as softblocked if necessary. Note that we avoid setting
- // softDisabled at the same time as userDisabled to make it clear
- // which was the original cause of the add-on becoming disabled in a
- // way that the user can change.
- if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED && !addon.userDisabled)
- addon.softDisabled = true;
- continue;
- }
-
- let entry = this._getAddonBlocklistEntry(addon, this._addonEntries);
- addonList.push({
- name: addon.name,
- version: addon.version,
- icon: addon.iconURL,
- disable: false,
- blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
- item: addon,
- url: entry && entry.url,
- });
- }
-
- 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);
- let state = this._getPluginBlocklistState(plugin, this._pluginEntries);
- LOG("Blocklist state for " + plugin.name + " changed from " +
- oldState + " to " + state);
- // We don't want to re-warn about items
- if (state == oldState)
- continue;
-
- if (oldState == Ci.nsIBlocklistService.STATE_BLOCKED) {
- if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
- plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
- } else if (!plugin.disabled && state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
- if (state != Ci.nsIBlocklistService.STATE_OUTDATED &&
- state != Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE &&
- state != Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE) {
- addonList.push({
- name: plugin.name,
- version: plugin.version,
- icon: "chrome://mozapps/skin/plugins/pluginGeneric.svg",
- disable: false,
- blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
- item: plugin,
- url: await this.getPluginBlockURL(plugin),
- });
- }
- }
- }
-
- 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().wrappedJSObject;
- blockedPrompter.prompt(addonList);
- } catch (e) {
- LOG(e);
- }
- this._notifyObserversBlocklistUpdated();
- return;
- }
-
- var args = {
- restart: false,
- list: addonList
- };
- // This lets the dialog get the raw js object
- args.wrappedJSObject = args;
-
- /*
- Some tests run without UI, so the async code listens to a message
- that can be sent programatically
- */
- let applyBlocklistChanges = () => {
- for (let addon of addonList) {
- if (!addon.disable)
- continue;
-
- if (addon.item instanceof Ci.nsIPluginTag)
- addon.item.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
- else {
- // This add-on is softblocked.
- addon.item.softDisabled = true;
- // We must revert certain prefs.
- let prefs = this._getAddonPrefs(addon.item);
- resetPrefs(prefs);
- }
- }
-
- if (args.restart)
- restartApp();
-
- this._notifyObserversBlocklistUpdated();
- Services.obs.removeObserver(applyBlocklistChanges, "addon-blocklist-closed");
- };
-
- Services.obs.addObserver(applyBlocklistChanges, "addon-blocklist-closed");
-
- if (Services.prefs.getBoolPref(PREF_BLOCKLIST_SUPPRESSUI, false)) {
- applyBlocklistChanges();
- return;
- }
-
- function blocklistUnloadHandler(event) {
- if (event.target.location == URI_BLOCKLIST_DIALOG) {
- applyBlocklistChanges();
- blocklistWindow.removeEventListener("unload", blocklistUnloadHandler);
- }
- }
-
- let blocklistWindow = Services.ww.openWindow(null, URI_BLOCKLIST_DIALOG, "",
- "chrome,centerscreen,dialog,titlebar", args);
- if (blocklistWindow)
- blocklistWindow.addEventListener("unload", blocklistUnloadHandler);
+ return PluginBlocklist.getURL(plugin);
},
};
-/*
- * Helper for constructing a blocklist.
- */
-function BlocklistItemData(versionRangeElement) {
- this.targetApps = {};
- let foundTarget = false;
- this.severity = DEFAULT_SEVERITY;
- this.vulnerabilityStatus = VULNERABILITYSTATUS_NONE;
- if (versionRangeElement) {
- let versionRange = this.getBlocklistVersionRange(versionRangeElement);
- this.minVersion = versionRange.minVersion;
- this.maxVersion = versionRange.maxVersion;
- if (versionRangeElement.hasAttribute("severity"))
- this.severity = versionRangeElement.getAttribute("severity");
- if (versionRangeElement.hasAttribute("vulnerabilitystatus")) {
- this.vulnerabilityStatus = versionRangeElement.getAttribute("vulnerabilitystatus");
- }
- for (let targetAppElement of versionRangeElement.children) {
- if (targetAppElement.localName == "targetApplication") {
- foundTarget = true;
- // default to the current application if id is not provided.
- let appID = targetAppElement.id || gAppID;
- this.targetApps[appID] = this.getBlocklistAppVersions(targetAppElement);
- }
- }
- } else {
- this.minVersion = this.maxVersion = null;
- }
-
- // Default to all versions of the current application when no targetApplication
- // elements were found
- if (!foundTarget)
- this.targetApps[gAppID] = [{minVersion: null, maxVersion: 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 {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
- if (!this.matchesRange(version, this.minVersion, this.maxVersion))
- return false;
-
- // Check if the application version matches
- if (this.matchesTargetRange(gAppID, appVersion))
- return true;
-
- // 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 {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 {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))
- return true;
- }
-
- return false;
- },
-
- /**
- * Retrieves a version range (e.g. minVersion and maxVersion) for a
- * blocklist item's targetApplication element.
- * @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 (let versionRangeElement of targetAppElement.children) {
- if (versionRangeElement.localName == "versionRange") {
- appVersions.push(this.getBlocklistVersionRange(versionRangeElement));
- }
- }
- }
- // return minVersion = null and maxVersion = null if no specific versionRange
- // elements were found
- if (appVersions.length == 0)
- appVersions.push({minVersion: null, maxVersion: null});
- return appVersions;
- },
-
- /**
- * Retrieves a version range (e.g. minVersion and maxVersion) for a blocklist
- * versionRange element.
- *
- * @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) {
- // getAttribute returns null if the attribute is not present.
- let minVersion = versionRangeElement.getAttribute("minVersion");
- let maxVersion = versionRangeElement.getAttribute("maxVersion");
-
- return { minVersion, maxVersion };
- }
-};
-
Blocklist._init();
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
@@ -727,16 +727,69 @@ var AddonTestUtils = {
*/
overrideBlocklist(addons) {
let mock = new MockBlocklist(addons);
mock.register();
return mock;
},
/**
+ * Load the following data into the *real* blocklist providers.
+ * While `overrideBlocklist` replaces the blocklist entirely with a mock
+ * that returns dummy data, this method instead loads data into the actual
+ * blocklist, fires update methods as would happen if this data came from
+ * an actual blocklist update, etc.
+ *
+ * @param {nsIFile} dir
+ * The directory in which the files live.
+ * @param {string} prefix
+ * a prefix for the files which ought to be loaded.
+ * This method will suffix -extensions.json and -plugins.json
+ * to the prefix it is given, and attempt to load both.
+ * Insofar as either exists, their data will be dumped into
+ * the respective store, and the respective update handlers
+ * will be called.
+ */
+ async loadBlocklistData(dir, prefix) {
+ const bsPass = ChromeUtils.import("resource://gre/modules/Blocklist.jsm", {});
+ const blocklistMapping = {
+ "extensions": bsPass.ExtensionBlocklist,
+ "plugins": bsPass.PluginBlocklist,
+ };
+
+ for (const [fileSuffix, blocklistObj] of Object.entries(blocklistMapping)) {
+ const fileName = prefix + "-" + fileSuffix + ".json";
+ let jsonStr = await OS.File.read(OS.Path.join(dir.path, fileName), {encoding: "UTF-8"}).catch(() => "");
+ if (!jsonStr) {
+ continue;
+ }
+ Cu.reportError("Loading " + prefix + " " + fileSuffix);
+
+ let newData = JSON.parse(jsonStr);
+ if (!Array.isArray(newData)) {
+ throw new Error("Expected an array of new items to put in the " + fileSuffix + " blocklist!");
+ }
+ for (let item of newData) {
+ if (!item.id) {
+ item.id = uuidGen.generateUUID().number.slice(1, -1);
+ }
+ if (!item.last_modified) {
+ item.last_modified = Date.now();
+ }
+ }
+ let collection = await blocklistObj._client.openCollection();
+ await collection.clear();
+ await collection.loadDump(newData);
+ // We manually call _onUpdate... which is evil, but at the moment kinto doesn't have
+ // a better abstraction unless you want to mock your own http server to do the update.
+ await blocklistObj._onUpdate();
+ }
+ },
+
+ /**
* Starts up the add-on manager as if it was started by the application.
*
* @param {string} [newVersion]
* If provided, the application version is changed to this string
* before the AddonManager is started.
*/
async promiseStartupManager(newVersion) {
if (this.addonIntegrationService)
--- a/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
@@ -1,23 +1,24 @@
const gHttpTestRoot = "http://127.0.0.1:8888/" + RELATIVE_DIR + "/";
function updateBlocklist(aCallback) {
var blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"]
.getService(Ci.nsITimerCallback);
var observer = function() {
- Services.obs.removeObserver(observer, "blocklist-updated");
+ Services.obs.removeObserver(observer, "plugin-blocklist-updated");
SimpleTest.executeSoon(aCallback);
};
- Services.obs.addObserver(observer, "blocklist-updated");
+ Services.obs.addObserver(observer, "plugin-blocklist-updated");
blocklistNotifier.notify(null);
}
var _originalBlocklistURL = null;
function setAndUpdateBlocklist(aURL, aCallback) {
+ // FIXME needs to change blocklist differently.
if (!_originalBlocklistURL) {
_originalBlocklistURL = Services.prefs.getCharPref("extensions.blocklist.url");
}
Services.prefs.setCharPref("extensions.blocklist.url", aURL);
updateBlocklist(aCallback);
}
function resetBlocklist(aCallback) {
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_app-extensions.json
@@ -0,0 +1,336 @@
+[
+ {
+ "_comment": "Always blocked",
+ "guid": "test_bug449027_2@tests.mozilla.org",
+ "versionRange": []
+ },
+ {
+ "_comment": "Always blocked",
+ "guid": "test_bug449027_3@tests.mozilla.org",
+ "versionRange": [
+ {}
+ ]
+ },
+ {
+ "_comment": "Not blocked since neither version range matches",
+ "guid": "test_bug449027_4@tests.mozilla.org",
+ "versionRange": [
+ {
+ "minVersion": "6"
+ },
+ {
+ "maxVersion": "4"
+ }
+ ]
+ },
+ {
+ "_comment": "Invalid version range, should not block",
+ "guid": "test_bug449027_5@tests.mozilla.org",
+ "versionRange": [
+ {
+ "maxVersion": "4",
+ "minVersion": "6"
+ }
+ ]
+ },
+ {
+ "_comment": "Should block all of these",
+ "guid": "test_bug449027_6@tests.mozilla.org",
+ "versionRange": [
+ {
+ "maxVersion": "8",
+ "minVersion": "7"
+ },
+ {
+ "maxVersion": "6",
+ "minVersion": "5"
+ },
+ {
+ "maxVersion": "4"
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_7@tests.mozilla.org",
+ "versionRange": [
+ {
+ "maxVersion": "4"
+ },
+ {
+ "maxVersion": "5",
+ "minVersion": "4"
+ },
+ {
+ "maxVersion": "7",
+ "minVersion": "6"
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_8@tests.mozilla.org",
+ "versionRange": [
+ {
+ "maxVersion": "2",
+ "minVersion": "2"
+ },
+ {
+ "maxVersion": "6",
+ "minVersion": "4"
+ },
+ {
+ "maxVersion": "8",
+ "minVersion": "7"
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_9@tests.mozilla.org",
+ "versionRange": [
+ {
+ "minVersion": "4"
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_10@tests.mozilla.org",
+ "versionRange": [
+ {
+ "minVersion": "5"
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_11@tests.mozilla.org",
+ "versionRange": [
+ {
+ "maxVersion": "6"
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_12@tests.mozilla.org",
+ "versionRange": [
+ {
+ "maxVersion": "5"
+ }
+ ]
+ },
+ {
+ "_comment": "This should block all versions for any application",
+ "guid": "test_bug449027_13@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {}
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Shouldn't block",
+ "guid": "test_bug449027_14@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "foo@bar.com"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Should block for any version of the app",
+ "guid": "test_bug449027_15@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Should still block",
+ "guid": "test_bug449027_16@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Not blocked since neither version range matches",
+ "guid": "test_bug449027_17@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "minVersion": "4"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "2"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Invalid version range, should not block",
+ "guid": "test_bug449027_18@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "4",
+ "minVersion": "6"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Should block all of these",
+ "guid": "test_bug449027_19@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "foo@bar.com"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "6",
+ "minVersion": "5"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "4",
+ "minVersion": "3"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "2"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_20@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "2"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "3",
+ "minVersion": "2"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "5",
+ "minVersion": "4"
+ },
+ {
+ "guid": "foo@bar.com"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_21@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "1",
+ "minVersion": "1"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "4",
+ "minVersion": "2"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "6",
+ "minVersion": "5"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_22@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "foo@bar.com"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "minVersion": "3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_23@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "minVersion": "2"
+ },
+ {
+ "guid": "foo@bar.com"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_24@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "guid": "test_bug449027_25@tests.mozilla.org",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "4"
+ }
+ ]
+ }
+ ]
+ }
+]
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_app-plugins.json
@@ -0,0 +1,336 @@
+[
+ {
+ "_comment": "Always blocked",
+ "matchName": "^test_bug449027_2$",
+ "versionRange": []
+ },
+ {
+ "_comment": "Always blocked",
+ "matchName": "^test_bug449027_3$",
+ "versionRange": [
+ {}
+ ]
+ },
+ {
+ "_comment": "Not blocked since neither version range matches",
+ "matchName": "^test_bug449027_4$",
+ "versionRange": [
+ {
+ "minVersion": "6"
+ },
+ {
+ "maxVersion": "4"
+ }
+ ]
+ },
+ {
+ "_comment": "Invalid version range, should not block",
+ "matchName": "^test_bug449027_5$",
+ "versionRange": [
+ {
+ "maxVersion": "4",
+ "minVersion": "6"
+ }
+ ]
+ },
+ {
+ "_comment": "Should block all of these",
+ "matchName": "^test_bug449027_6$",
+ "versionRange": [
+ {
+ "maxVersion": "8",
+ "minVersion": "7"
+ },
+ {
+ "maxVersion": "6",
+ "minVersion": "5"
+ },
+ {
+ "maxVersion": "4"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_7$",
+ "versionRange": [
+ {
+ "maxVersion": "4"
+ },
+ {
+ "maxVersion": "5",
+ "minVersion": "4"
+ },
+ {
+ "maxVersion": "7",
+ "minVersion": "6"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_8$",
+ "versionRange": [
+ {
+ "maxVersion": "2",
+ "minVersion": "2"
+ },
+ {
+ "maxVersion": "6",
+ "minVersion": "4"
+ },
+ {
+ "maxVersion": "8",
+ "minVersion": "7"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_9$",
+ "versionRange": [
+ {
+ "minVersion": "4"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_10$",
+ "versionRange": [
+ {
+ "minVersion": "5"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_11$",
+ "versionRange": [
+ {
+ "maxVersion": "6"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_12$",
+ "versionRange": [
+ {
+ "maxVersion": "5"
+ }
+ ]
+ },
+ {
+ "_comment": "This should block all versions for any application",
+ "matchName": "^test_bug449027_13$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {}
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Shouldn't block",
+ "matchName": "^test_bug449027_14$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "foo@bar.com"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Should block for any version of the app",
+ "matchName": "^test_bug449027_15$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Should still block",
+ "matchName": "^test_bug449027_16$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Not blocked since neither version range matches",
+ "matchName": "^test_bug449027_17$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "minVersion": "4"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "2"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Invalid version range, should not block",
+ "matchName": "^test_bug449027_18$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "4",
+ "minVersion": "6"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Should block all of these",
+ "matchName": "^test_bug449027_19$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "foo@bar.com"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "6",
+ "minVersion": "5"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "4",
+ "minVersion": "3"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "2"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_20$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "2"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "3",
+ "minVersion": "2"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "5",
+ "minVersion": "4"
+ },
+ {
+ "guid": "foo@bar.com"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_21$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "1",
+ "minVersion": "1"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "4",
+ "minVersion": "2"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "6",
+ "minVersion": "5"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_22$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "foo@bar.com"
+ },
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "minVersion": "3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_23$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "minVersion": "2"
+ },
+ {
+ "guid": "foo@bar.com"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_24$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "3"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "matchName": "^test_bug449027_25$",
+ "versionRange": [
+ {
+ "targetApplication": [
+ {
+ "guid": "xpcshell@tests.mozilla.org",
+ "maxVersion": "4"
+ }
+ ]
+ }
+ ]
+ }
+]
\ No newline at end of file
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_app.xml
+++ /dev/null
@@ -1,333 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
- <emItems>
- <!-- All extensions are version 5 and tests run against appVersion 3 -->
-
- <!-- Test 1 not listed, should never get blocked -->
- <!-- Always blocked -->
- <emItem id="test_bug449027_2@tests.mozilla.org"/>
- <!-- Always blocked -->
- <emItem id="test_bug449027_3@tests.mozilla.org">
- <versionRange/>
- </emItem>
- <!-- Not blocked since neither version range matches -->
- <emItem id="test_bug449027_4@tests.mozilla.org">
- <versionRange minVersion="6"/>
- <versionRange maxVersion="4"/>
- </emItem>
- <!-- Invalid version range, should not block -->
- <emItem id="test_bug449027_5@tests.mozilla.org">
- <versionRange minVersion="6" maxVersion="4"/>
- </emItem>
- <!-- Should block all of these -->
- <emItem id="test_bug449027_6@tests.mozilla.org">
- <versionRange minVersion="7" maxVersion="8"/>
- <versionRange minVersion="5" maxVersion="6"/>
- <versionRange maxVersion="4"/>
- </emItem>
- <emItem id="test_bug449027_7@tests.mozilla.org">
- <versionRange maxVersion="4"/>
- <versionRange minVersion="4" maxVersion="5"/>
- <versionRange minVersion="6" maxVersion="7"/>
- </emItem>
- <emItem id="test_bug449027_8@tests.mozilla.org">
- <versionRange minVersion="2" maxVersion="2"/>
- <versionRange minVersion="4" maxVersion="6"/>
- <versionRange minVersion="7" maxVersion="8"/>
- </emItem>
- <emItem id="test_bug449027_9@tests.mozilla.org">
- <versionRange minVersion="4"/>
- </emItem>
- <emItem id="test_bug449027_10@tests.mozilla.org">
- <versionRange minVersion="5"/>
- </emItem>
- <emItem id="test_bug449027_11@tests.mozilla.org">
- <versionRange maxVersion="6"/>
- </emItem>
- <emItem id="test_bug449027_12@tests.mozilla.org">
- <versionRange maxVersion="5"/>
- </emItem>
-
- <!-- This should block all versions for any application -->
- <emItem id="test_bug449027_13@tests.mozilla.org">
- <versionRange>
- <targetApplication/>
- </versionRange>
- </emItem>
- <!-- Shouldn't block -->
- <emItem id="test_bug449027_14@tests.mozilla.org">
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </emItem>
- <!-- Should block for any version of the app -->
- <emItem id="test_bug449027_15@tests.mozilla.org">
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org"/>
- </versionRange>
- </emItem>
- <!-- Should still block -->
- <emItem id="test_bug449027_16@tests.mozilla.org">
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange/>
- </targetApplication>
- </versionRange>
- </emItem>
- <!-- Not blocked since neither version range matches -->
- <emItem id="test_bug449027_17@tests.mozilla.org">
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="4"/>
- <versionRange maxVersion="2"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <!-- Invalid version range, should not block -->
- <emItem id="test_bug449027_18@tests.mozilla.org">
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="6" maxVersion="4"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <!-- Should block all of these -->
- <emItem id="test_bug449027_19@tests.mozilla.org">
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="5" maxVersion="6"/>
- <versionRange minVersion="3" maxVersion="4"/>
- <versionRange maxVersion="2"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_20@tests.mozilla.org">
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange maxVersion="2"/>
- <versionRange minVersion="2" maxVersion="3"/>
- <versionRange minVersion="4" maxVersion="5"/>
- </targetApplication>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_21@tests.mozilla.org">
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="1" maxVersion="1"/>
- <versionRange minVersion="2" maxVersion="4"/>
- <versionRange minVersion="5" maxVersion="6"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_22@tests.mozilla.org">
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="3"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_23@tests.mozilla.org">
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="2"/>
- </targetApplication>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_24@tests.mozilla.org">
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange maxVersion="3"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_25@tests.mozilla.org">
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange maxVersion="4"/>
- </targetApplication>
- </versionRange>
- </emItem>
- </emItems>
- <pluginItems>
- <!-- All plugins are version 5 and tests run against appVersion 3 -->
-
- <!-- Test 1 not listed, should never get blocked -->
- <!-- Always blocked -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_2$"/>
- </pluginItem>
- <!-- Always blocked -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_3$"/>
- <versionRange/>
- </pluginItem>
- <!-- Not blocked since neither version range matches -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_4$"/>
- <versionRange minVersion="6"/>
- <versionRange maxVersion="4"/>
- </pluginItem>
- <!-- Invalid version range, should not block -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_5$"/>
- <versionRange minVersion="6" maxVersion="4"/>
- </pluginItem>
- <!-- Should block all of these -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_6$"/>
- <versionRange minVersion="7" maxVersion="8"/>
- <versionRange minVersion="5" maxVersion="6"/>
- <versionRange maxVersion="4"/>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_7$"/>
- <versionRange maxVersion="4"/>
- <versionRange minVersion="4" maxVersion="5"/>
- <versionRange minVersion="6" maxVersion="7"/>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_8$"/>
- <versionRange minVersion="2" maxVersion="2"/>
- <versionRange minVersion="4" maxVersion="6"/>
- <versionRange minVersion="7" maxVersion="8"/>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_9$"/>
- <versionRange minVersion="4"/>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_10$"/>
- <versionRange minVersion="5"/>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_11$"/>
- <versionRange maxVersion="6"/>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_12$"/>
- <versionRange maxVersion="5"/>
- </pluginItem>
-
- <!-- This should block all versions for any application -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_13$"/>
- <versionRange>
- <targetApplication/>
- </versionRange>
- </pluginItem>
- <!-- Shouldn't block -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_14$"/>
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </pluginItem>
- <!-- Should block for any version of the app -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_15$"/>
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org"/>
- </versionRange>
- </pluginItem>
- <!-- Should still block -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_16$"/>
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <!-- Not blocked since neither version range matches -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_17$"/>
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="4"/>
- <versionRange maxVersion="2"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <!-- Invalid version range, should not block -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_18$"/>
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="6" maxVersion="4"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <!-- Should block all of these -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_19$"/>
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="5" maxVersion="6"/>
- <versionRange minVersion="3" maxVersion="4"/>
- <versionRange maxVersion="2"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_20$"/>
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange maxVersion="2"/>
- <versionRange minVersion="2" maxVersion="3"/>
- <versionRange minVersion="4" maxVersion="5"/>
- </targetApplication>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_21$"/>
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="1" maxVersion="1"/>
- <versionRange minVersion="2" maxVersion="4"/>
- <versionRange minVersion="5" maxVersion="6"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_22$"/>
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="3"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_23$"/>
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange minVersion="2"/>
- </targetApplication>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_24$"/>
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange maxVersion="3"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_25$"/>
- <versionRange>
- <targetApplication id="xpcshell@tests.mozilla.org">
- <versionRange maxVersion="4"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- </pluginItems>
-</blocklist>
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_toolkit-extensions.json
@@ -0,0 +1,154 @@
+[
+ {
+ "_general_comment": "All extensions are version 5 and tests run against toolkitVersion 8",
+ "_general_comment2": "Test 1-14 not listed, should never get blocked",
+
+ "_comment": "Should block for any version of the app",
+ "guid": "test_bug449027_15@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [{"guid": "toolkit@mozilla.org"}]
+ }]
+ },
+ {
+ "_comment": "Should still block",
+ "guid": "test_bug449027_16@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [{"guid": "toolkit@mozilla.org"}]
+ }]
+ },
+ {
+ "_comment": "Not blocked since neither version range matches",
+ "guid": "test_bug449027_17@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [{
+ "minVersion": "9",
+ "guid": "toolkit@mozilla.org"
+ },{
+ "maxVersion": "7",
+ "guid": "toolkit@mozilla.org"
+ }]
+ }]
+ },
+ {
+ "_comment": "Invalid version range, should not block",
+ "guid": "test_bug449027_18@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [{
+ "minVersion": "11",
+ "maxVersion": "9",
+ "guid": "toolkit@mozilla.org"
+ }]
+ }]
+ },
+ {
+ "_comment": "Should block all of the following",
+ "guid": "test_bug449027_19@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [
+ {
+ "guid": "foo@bar.com"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "10",
+ "maxVersion": "11"
+ },
+ {
+ "minVersion": "8",
+ "maxVersion": "9"
+ },
+ {
+ "maxVersion": "7"
+ }
+ ]
+ }]
+ },
+ {
+ "guid": "test_bug449027_20@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [
+ {
+ "guid": "toolkit@mozilla.org",
+ "maxVersion": "7"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "7",
+ "maxVersion": "8"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "9",
+ "maxVersion": "10"
+ },
+ {
+ "guid": "foo@bar.com"
+ }
+ ]
+ }]
+ },
+ {
+ "guid": "test_bug449027_21@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "6",
+ "maxVersion": "6"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "7",
+ "maxVersion": "9"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "10",
+ "maxVersion": "11"
+ }
+ ]
+ }]
+ },
+ {
+ "guid": "test_bug449027_22@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [{
+ "guid": "foo@bar.com"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "8"
+ }]
+ }]
+ },
+ {
+ "guid": "test_bug449027_23@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [{
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "7"
+ },
+ {
+ "guid": "foo@bar.com"
+ }]
+ }]
+ },
+ {
+ "guid": "test_bug449027_24@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [{
+ "maxVersion": "8",
+ "guid": "toolkit@mozilla.org"
+ }]
+ }]
+ },
+ {
+ "guid": "test_bug449027_25@tests.mozilla.org",
+ "versionRange": [{
+ "targetApplication": [{
+ "guid": "toolkit@mozilla.org",
+ "maxVersion": "9"
+ }]
+ }]
+ }
+]
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_toolkit-plugins.json
@@ -0,0 +1,155 @@
+[
+ {
+ "_general_comment": "All plugins are version 5 and tests run against appVersion 3",
+ "_general_comment2": "Test 1-14 not listed, should never get blocked",
+
+ "_comment": "Should block for any version of the app",
+ "matchName": "^test_bug449027_15$",
+ "versionRange": [{
+ "targetApplication": [{"guid": "toolkit@mozilla.org"}]
+ }]
+ },
+ {
+ "_comment": "Should still block",
+ "matchName": "^test_bug449027_16$",
+ "versionRange": [{
+ "targetApplication": [{"guid": "toolkit@mozilla.org"}]
+ }]
+ },
+ {
+ "_comment": "Not blocked since neither version range matches",
+ "matchName": "^test_bug449027_17$",
+ "versionRange": [{
+ "targetApplication": [{
+ "minVersion": "9",
+ "guid": "toolkit@mozilla.org"
+ },{
+ "maxVersion": "7",
+ "guid": "toolkit@mozilla.org"
+ }]
+ }]
+ },
+ {
+ "_comment": "Invalid version range, should not block",
+ "matchName": "^test_bug449027_18$",
+ "versionRange": [{
+ "targetApplication": [{
+ "minVersion": "11",
+ "maxVersion": "9",
+ "guid": "toolkit@mozilla.org"
+ }]
+ }]
+ },
+ {
+ "_comment": "Should block all of the following",
+ "matchName": "^test_bug449027_19$",
+ "versionRange": [{
+ "targetApplication": [
+ {
+ "guid": "foo@bar.com"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "10",
+ "maxVersion": "11"
+ },
+ {
+ "minVersion": "8",
+ "maxVersion": "9"
+ },
+ {
+ "maxVersion": "7"
+ }
+ ]
+ }]
+ },
+ {
+ "matchName": "^test_bug449027_20$",
+ "versionRange": [{
+ "targetApplication": [
+ {
+ "guid": "toolkit@mozilla.org",
+ "maxVersion": "7"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "7",
+ "maxVersion": "8"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "9",
+ "maxVersion": "10"
+ },
+ {
+ "guid": "foo@bar.com"
+ }
+ ]
+ }]
+ },
+ {
+ "matchName": "^test_bug449027_21$",
+ "versionRange": [{
+ "targetApplication": [
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "6",
+ "maxVersion": "6"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "7",
+ "maxVersion": "9"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "10",
+ "maxVersion": "11"
+ }
+ ]
+ }]
+ },
+ {
+ "matchName": "^test_bug449027_22$",
+ "versionRange": [{
+ "targetApplication": [{
+ "guid": "foo@bar.com"
+ },
+ {
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "8"
+ }]
+ }]
+ },
+ {
+ "matchName": "^test_bug449027_23$",
+ "versionRange": [{
+ "targetApplication": [{
+ "guid": "toolkit@mozilla.org",
+ "minVersion": "7"
+ },
+ {
+ "guid": "foo@bar.com"
+ }]
+ }]
+ },
+ {
+ "matchName": "^test_bug449027_24$",
+ "versionRange": [{
+ "targetApplication": [{
+ "maxVersion": "8",
+ "guid": "toolkit@mozilla.org"
+ }]
+ }]
+ },
+ {
+ "matchName": "^test_bug449027_25$",
+ "versionRange": [{
+ "targetApplication": [{
+ "guid": "toolkit@mozilla.org",
+ "maxVersion": "9"
+ }]
+ }]
+ }
+]
+
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_bug449027_toolkit.xml
+++ /dev/null
@@ -1,208 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist">
- <emItems>
- <!-- All extensions are version 5 and tests run against toolkitVersion 8 -->
-
- <!-- Test 1-14 not listed, should never get blocked -->
-
- <!-- Should block for any version of the app -->
- <emItem id="test_bug449027_15@tests.mozilla.org">
- <versionRange>
- <targetApplication id="toolkit@mozilla.org"/>
- </versionRange>
- </emItem>
- <!-- Should still block -->
- <emItem id="test_bug449027_16@tests.mozilla.org">
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange/>
- </targetApplication>
- </versionRange>
- </emItem>
- <!-- Not blocked since neither version range matches -->
- <emItem id="test_bug449027_17@tests.mozilla.org">
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="9"/>
- <versionRange maxVersion="7"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <!-- Invalid version range, should not block -->
- <emItem id="test_bug449027_18@tests.mozilla.org">
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="11" maxVersion="9"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <!-- Should block all of these -->
- <emItem id="test_bug449027_19@tests.mozilla.org">
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="10" maxVersion="11"/>
- <versionRange minVersion="8" maxVersion="9"/>
- <versionRange maxVersion="7"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_20@tests.mozilla.org">
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange maxVersion="7"/>
- <versionRange minVersion="7" maxVersion="8"/>
- <versionRange minVersion="9" maxVersion="10"/>
- </targetApplication>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_21@tests.mozilla.org">
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="6" maxVersion="6"/>
- <versionRange minVersion="7" maxVersion="9"/>
- <versionRange minVersion="10" maxVersion="11"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_22@tests.mozilla.org">
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="8"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_23@tests.mozilla.org">
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="7"/>
- </targetApplication>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_24@tests.mozilla.org">
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange maxVersion="8"/>
- </targetApplication>
- </versionRange>
- </emItem>
- <emItem id="test_bug449027_25@tests.mozilla.org">
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange maxVersion="9"/>
- </targetApplication>
- </versionRange>
- </emItem>
- </emItems>
- <pluginItems>
- <!-- All plugins are version 5 and tests run against appVersion 3 -->
-
- <!-- Test 1-14 not listed, should never get blocked -->
- <!-- Should block for any version of the app -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_15$"/>
- <versionRange>
- <targetApplication id="toolkit@mozilla.org"/>
- </versionRange>
- </pluginItem>
- <!-- Should still block -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_16$"/>
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <!-- Not blocked since neither version range matches -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_17$"/>
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="9"/>
- <versionRange maxVersion="7"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <!-- Invalid version range, should not block -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_18$"/>
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="11" maxVersion="9"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <!-- Should block all of these -->
- <pluginItem>
- <match name="name" exp="^test_bug449027_19$"/>
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="10" maxVersion="11"/>
- <versionRange minVersion="8" maxVersion="9"/>
- <versionRange maxVersion="7"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_20$"/>
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange maxVersion="7"/>
- <versionRange minVersion="7" maxVersion="8"/>
- <versionRange minVersion="9" maxVersion="10"/>
- </targetApplication>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_21$"/>
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="6" maxVersion="6"/>
- <versionRange minVersion="7" maxVersion="9"/>
- <versionRange minVersion="10" maxVersion="11"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_22$"/>
- <versionRange>
- <targetApplication id="foo@bar.com"/>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="8"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_23$"/>
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange minVersion="7"/>
- </targetApplication>
- <targetApplication id="foo@bar.com"/>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_24$"/>
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange maxVersion="8"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- <pluginItem>
- <match name="name" exp="^test_bug449027_25$"/>
- <versionRange>
- <targetApplication id="toolkit@mozilla.org">
- <versionRange maxVersion="9"/>
- </targetApplication>
- </versionRange>
- </pluginItem>
- </pluginItems>
-</blocklist>
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_pluginBlocklistCtp-plugins.json
@@ -0,0 +1,56 @@
+[
+ {
+ "matchName": "^test_plugin_0",
+ "versionRange": [
+ {
+ "maxVersion": "*",
+ "minVersion": "0",
+ "severity": "0",
+ "vulnerabilityStatus": "0"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_plugin_1",
+ "versionRange": [
+ {
+ "maxVersion": "*",
+ "minVersion": "0",
+ "severity": "0",
+ "vulnerabilityStatus": "1"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_plugin_2",
+ "versionRange": [
+ {
+ "maxVersion": "*",
+ "minVersion": "0",
+ "severity": "0",
+ "vulnerabilityStatus": "2"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_plugin_3",
+ "versionRange": [
+ {
+ "maxVersion": "*",
+ "minVersion": "0",
+ "vulnerabilityStatus": "2"
+ }
+ ]
+ },
+ {
+ "matchName": "^test_plugin_4",
+ "versionRange": [
+ {
+ "maxVersion": "*",
+ "minVersion": "0",
+ "severity": "1",
+ "vulnerabilityStatus": "2"
+ }
+ ]
+ }
+]
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_pluginBlocklistCtpUndo-plugins.json
@@ -0,0 +1,13 @@
+[
+ {
+ "matchName": "^Test Plug-in",
+ "versionRange": [
+ {
+ "maxVersion": "*",
+ "minVersion": "0",
+ "severity": "0",
+ "vulnerabilityStatus": "2"
+ }
+ ]
+ }
+]
\ No newline at end of file
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_appversion.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_appversion.js
@@ -1,15 +1,16 @@
/* 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/.
*/
const Cm = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
+// FIXME need to change how these blocklists are updated
var testserver = AddonTestUtils.createHttpServer({hosts: ["example.com"]});
testserver.registerDirectory("/data/", do_get_file("data"));
var ADDONS = [{
id: "test_bug449027_1@tests.mozilla.org",
name: "Bug 449027 Addon Test 1",
version: "5",
start: false,
@@ -232,26 +233,16 @@ var BlocklistPrompt = {
prompt(list) {
gNewBlocks = list.map(item => `${item.name} ${item.version}`);
},
QueryInterface: ChromeUtils.generateQI([]),
};
-async function loadBlocklist(file) {
- let blocklistUpdated = TestUtils.topicObserved("blocklist-updated");
-
- Services.prefs.setCharPref("extensions.blocklist.url",
- "http://example.com/data/" + file);
- Blocklist.notify();
-
- await blocklistUpdated;
-}
-
let factory = XPCOMUtils.generateSingletonFactory(function() { return BlocklistPrompt; });
Cm.registerFactory(Components.ID("{26d32654-30c7-485d-b983-b4d2568aebba}"),
"Blocklist Prompt",
"@mozilla.org/addons/blocklist-prompt;1", factory);
function createAddon(addon) {
return promiseInstallXPI({
name: addon.name,
@@ -319,21 +310,21 @@ add_task(async function test() {
await checkState("start");
});
/**
* Load the toolkit based blocks
*/
add_task(async function test_pt2() {
- await loadBlocklist("test_bug449027_toolkit.xml");
+ await AddonTestUtils.loadBlocklistData(do_get_file("data/"), "test_bug449027_toolkit");
await checkState("toolkitBlocks", "start");
});
/**
* Load the application based blocks
*/
add_task(async function test_pt3() {
- await loadBlocklist("test_bug449027_app.xml");
+ await AddonTestUtils.loadBlocklistData(do_get_file("data/"), "test_bug449027_app");
await checkState("appBlocks", "toolkitBlocks");
});
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_metadata_filters.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_metadata_filters.js
@@ -1,50 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests blocking of extensions by ID, name, creator, homepageURL, updateURL
// and RegExps for each. See bug 897735.
-const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
-
-ChromeUtils.import("resource://testing-common/MockRegistrar.jsm");
var testserver = AddonTestUtils.createHttpServer({hosts: ["example.com"]});
gPort = testserver.identity.primaryPort;
testserver.registerDirectory("/data/", do_get_file("data"));
const profileDir = gProfD.clone();
profileDir.append("extensions");
-// Don't need the full interface, attempts to call other methods will just
-// throw which is just fine
-var WindowWatcher = {
- openWindow(parent, url, name, features, args) {
- // Should be called to list the newly blocklisted items
- Assert.equal(url, URI_EXTENSION_BLOCKLIST_DIALOG);
-
- // Simulate auto-disabling any softblocks
- var list = args.wrappedJSObject.list;
- list.forEach(function(aItem) {
- if (!aItem.blocked)
- aItem.disable = true;
- });
-
- // run the code after the blocklist is closed
- Services.obs.notifyObservers(null, "addon-blocklist-closed");
-
- },
-
- QueryInterface: ChromeUtils.generateQI(["nsIWindowWatcher"])
-};
-
-MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher);
-
function load_blocklist(aFile, aCallback) {
Services.obs.addObserver(function observer() {
Services.obs.removeObserver(observer, "blocklist-updated");
executeSoon(aCallback);
}, "blocklist-updated");
Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" +
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_plugin_outdated.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_plugin_outdated.js
@@ -47,17 +47,18 @@ var BlocklistPrompt = {
Assert.notEqual(item.name, "test_bug514327_outdated");
},
QueryInterface: ChromeUtils.generateQI([]),
};
async function loadBlocklist(file) {
- let blocklistUpdated = TestUtils.topicObserved("blocklist-updated");
+ // FIXME needs to load blocklist differently.
+ let blocklistUpdated = TestUtils.topicObserved("plugin-blocklist-updated");
Services.prefs.setCharPref("extensions.blocklist.url",
"http://example.com/data/" + file);
Blocklist.notify();
await blocklistUpdated;
}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_prefs.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_prefs.js
@@ -1,51 +1,23 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Tests resetting of preferences in blocklist entry when an add-on is blocked.
// See bug 802434.
-const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
-
-ChromeUtils.import("resource://testing-common/MockRegistrar.jsm");
var testserver = AddonTestUtils.createHttpServer({hosts: ["example.com"]});
gPort = testserver.identity.primaryPort;
testserver.registerDirectory("/data/", do_get_file("data"));
const profileDir = gProfD.clone();
profileDir.append("extensions");
-// A window watcher to handle the blocklist UI.
-// Don't need the full interface, attempts to call other methods will just
-// throw which is just fine
-var WindowWatcher = {
- openWindow(parent, url, name, features, args) {
- // Should be called to list the newly blocklisted items
- Assert.equal(url, URI_EXTENSION_BLOCKLIST_DIALOG);
-
- // Simulate auto-disabling any softblocks
- var list = args.wrappedJSObject.list;
- list.forEach(function(aItem) {
- if (!aItem.blocked)
- aItem.disable = true;
- });
-
- // run the code after the blocklist is closed
- Services.obs.notifyObservers(null, "addon-blocklist-closed");
-
- },
-
- QueryInterface: ChromeUtils.generateQI(["nsIWindowWatcher"])
-};
-
-MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher);
-
function load_blocklist(aFile, aCallback) {
Services.obs.addObserver(function observer() {
Services.obs.removeObserver(observer, "blocklist-updated");
executeSoon(aCallback);
}, "blocklist-updated");
Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" +
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_regexp.js
@@ -1,52 +1,24 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Checks that blocklist entries using RegExp work as expected. This only covers
// behavior specific to RegExp entries - general behavior is already tested
// in test_blocklistchange.js.
-const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
-
-ChromeUtils.import("resource://testing-common/MockRegistrar.jsm");
var testserver = AddonTestUtils.createHttpServer({hosts: ["example.com"]});
gPort = testserver.identity.primaryPort;
testserver.registerDirectory("/data/", do_get_file("data"));
const profileDir = gProfD.clone();
profileDir.append("extensions");
-// Don't need the full interface, attempts to call other methods will just
-// throw which is just fine
-var WindowWatcher = {
- openWindow(parent, url, name, features, args) {
- // Should be called to list the newly blocklisted items
- Assert.equal(url, URI_EXTENSION_BLOCKLIST_DIALOG);
-
- // Simulate auto-disabling any softblocks
- var list = args.wrappedJSObject.list;
- list.forEach(function(aItem) {
- if (!aItem.blocked)
- aItem.disable = true;
- });
-
- // run the code after the blocklist is closed
- Services.obs.notifyObservers(null, "addon-blocklist-closed");
-
- },
-
- QueryInterface: ChromeUtils.generateQI(["nsIWindowWatcher"])
-};
-
-MockRegistrar.register("@mozilla.org/embedcomp/window-watcher;1", WindowWatcher);
-
-
function load_blocklist(aFile, aCallback) {
Services.obs.addObserver(function observer() {
Services.obs.removeObserver(observer, "blocklist-updated");
executeSoon(aCallback);
}, "blocklist-updated");
Services.prefs.setCharPref("extensions.blocklist.url", "http://localhost:" +
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_severities.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_severities.js
@@ -5,16 +5,17 @@
const URI_EXTENSION_BLOCKLIST_DIALOG = "chrome://mozapps/content/extensions/blocklist.xul";
ChromeUtils.import("resource://testing-common/MockRegistrar.jsm");
var gTestserver = AddonTestUtils.createHttpServer({hosts: ["example.com"]});
gTestserver.registerDirectory("/data/", do_get_file("data"));
+// FIXME gather updates differently
// Workaround for Bug 658720 - URL formatter can leak during xpcshell tests
const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL";
Services.prefs.setCharPref(PREF_BLOCKLIST_ITEM_URL, "http://example.com/blocklist/%blockID%");
async function getAddonBlocklistURL(addon) {
let entry = await Blocklist.getAddonBlocklistEntry(addon);
return entry && entry.url;
}
@@ -129,17 +130,17 @@ function createAddon(addon) {
targetApplications: [{
id: "xpcshell@tests.mozilla.org",
minVersion: addon.appVersion,
maxVersion: addon.appVersion}],
});
}
async function loadBlocklist(file, callback) {
- let blocklistUpdated = TestUtils.topicObserved("blocklist-updated");
+ let blocklistUpdated = TestUtils.topicObserved("plugin-blocklist-updated");
gNotificationCheck = callback;
Services.prefs.setCharPref("extensions.blocklist.url",
"http://example.com/data/" + file);
Blocklist.notify();
await blocklistUpdated;
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js
@@ -487,16 +487,17 @@ var regexpblock_3 = {
updateURL: "http://example.com/data/blocklistchange/addon_update3.json",
targetApplications: [{
id: "xpcshell@tests.mozilla.org",
minVersion: "1",
maxVersion: "3"
}]
};
+// FIXME this window-watchers for add-ons.
const ADDON_IDS = ["softblock1@tests.mozilla.org",
"softblock2@tests.mozilla.org",
"softblock3@tests.mozilla.org",
"softblock4@tests.mozilla.org",
"hardblock@tests.mozilla.org",
"regexpblock@tests.mozilla.org"];
// Don't need the full interface, attempts to call other methods will just
--- a/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginBlocklistCtp.js
@@ -1,15 +1,14 @@
/* 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/. */
const nsIBLS = Ci.nsIBlocklistService;
-var gNotifier = null;
var gPluginHost = null;
var gTestserver = AddonTestUtils.createHttpServer({hosts: ["example.com"]});
gTestserver.registerDirectory("/data/", do_get_file("data"));
var PLUGINS = [{
// severity=0, vulnerabilitystatus=0 -> outdated
name: "test_plugin_0",
@@ -48,44 +47,39 @@ var PLUGINS = [{
{
// not in the blocklist -> not blocked
name: "test_plugin_5",
version: "5",
disabled: false,
blocklisted: false
}];
-async function updateBlocklist(blocklistURL) {
- if (blocklistURL) {
- Services.prefs.setCharPref("extensions.blocklist.url", blocklistURL);
- }
- let blocklistUpdated = TestUtils.topicObserved("blocklist-updated");
- gNotifier.notify(null);
+async function updateBlocklist(file) {
+ let blocklistUpdated = TestUtils.topicObserved("plugin-blocklist-updated");
+ AddonTestUtils.loadBlocklistData(do_get_file("data/"), file);
return blocklistUpdated;
}
add_task(async function setup() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
- Services.prefs.setCharPref("extensions.blocklist.url", "http://example.com/data/test_pluginBlocklistCtp.xml");
Services.prefs.setBoolPref("plugin.load_flash_only", false);
+ gPluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
await promiseStartupManager();
- gPluginHost = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
- gNotifier = Cc["@mozilla.org/extensions/blocklist;1"].getService(Ci.nsITimerCallback);
registerCleanupFunction(function() {
- Services.prefs.clearUserPref("extensions.blocklist.url");
Services.prefs.clearUserPref("extensions.blocklist.enabled");
+ Services.prefs.clearUserPref("plugin.load_flash_only");
Services.prefs.clearUserPref("plugins.click_to_play");
});
});
add_task(async function basic() {
- await updateBlocklist();
+ await updateBlocklist("test_pluginBlocklistCtp");
var {blocklist} = Services;
Assert.equal(await blocklist.getPluginBlocklistState(PLUGINS[0], "1", "1.9"),
nsIBLS.STATE_OUTDATED);
Assert.equal(await blocklist.getPluginBlocklistState(PLUGINS[1], "1", "1.9"),
nsIBLS.STATE_VULNERABLE_UPDATE_AVAILABLE);
@@ -103,53 +97,53 @@ add_task(async function basic() {
});
function get_test_plugin() {
for (var plugin of gPluginHost.getPluginTags()) {
if (plugin.name == "Test Plug-in")
return plugin;
}
- Assert.ok(false);
+ Assert.ok(false, "Should have found the test plugin!");
return null;
}
// At this time, the blocklist does not have an entry for the test plugin,
// so it shouldn't be click-to-play.
add_task(async function test_is_not_clicktoplay() {
var plugin = get_test_plugin();
var blocklistState = await Blocklist.getPluginBlocklistState(plugin, "1", "1.9");
Assert.notEqual(blocklistState, Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE);
Assert.notEqual(blocklistState, Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE);
});
// Here, we've updated the blocklist to have a block for the test plugin,
// so it should be click-to-play.
add_task(async function test_is_clicktoplay() {
- await updateBlocklist("http://example.com/data/test_pluginBlocklistCtpUndo.xml");
+ await updateBlocklist("test_pluginBlocklistCtpUndo");
var plugin = get_test_plugin();
var blocklistState = await Blocklist.getPluginBlocklistState(plugin, "1", "1.9");
Assert.equal(blocklistState, Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE);
});
// But now we've removed that entry from the blocklist (really we've gone back
// to the old one), so the plugin shouldn't be click-to-play any more.
add_task(async function test_is_not_clicktoplay2() {
- await updateBlocklist("http://example.com/data/test_pluginBlocklistCtp.xml");
+ await updateBlocklist("test_pluginBlocklistCtp");
var plugin = get_test_plugin();
var blocklistState = await Blocklist.getPluginBlocklistState(plugin, "1", "1.9");
Assert.notEqual(blocklistState, Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE);
Assert.notEqual(blocklistState, Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE);
});
// Test that disabling the blocklist when a plugin is ctp-blocklisted will
// result in the plugin not being click-to-play.
add_task(async function test_disable_blocklist() {
- await updateBlocklist("http://example.com/data/test_pluginBlocklistCtpUndo.xml");
+ await updateBlocklist("test_pluginBlocklistCtpUndo");
var plugin = get_test_plugin();
var blocklistState = await Blocklist.getPluginBlocklistState(plugin, "1", "1.9");
Assert.equal(blocklistState, Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE);
Services.prefs.setBoolPref("extensions.blocklist.enabled", false);
blocklistState = await Blocklist.getPluginBlocklistState(plugin, "1", "1.9");
Assert.notEqual(blocklistState, Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE);
Assert.notEqual(blocklistState, Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_softblocked.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_softblocked.js
@@ -9,16 +9,17 @@ ChromeUtils.import("resource://testing-c
// Allow insecure updates
Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
const testserver = createHttpServer();
gPort = testserver.identity.primaryPort;
testserver.registerDirectory("/data/", do_get_file("data"));
+// FIXME addon window watcher
// Don't need the full interface, attempts to call other methods will just
// throw which is just fine
var WindowWatcher = {
openWindow(parent, url, name, features, openArgs) {
// Should be called to list the newly blocklisted items
Assert.equal(url, URI_EXTENSION_BLOCKLIST_DIALOG);
// Simulate auto-disabling any softblocks