From f86673741dce0580a73d37b6f72418877b7380d6 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Tue, 15 May 2018 05:06:42 -0400 Subject: Issue #347 - TychoAM nsBlocklistService does not support gfxBlacklist --- toolkit/mozapps/extensions/extensions.manifest | 4 - toolkit/mozapps/extensions/moz.build | 1 - toolkit/mozapps/extensions/nsBlocklistService.js | 1478 ----------------- toolkit/mozapps/webextensions/extensions.manifest | 7 - toolkit/mozapps/webextensions/moz.build | 2 - .../mozapps/webextensions/nsBlocklistService.js | 1658 -------------------- .../webextensions/nsBlocklistServiceContent.js | 113 -- 7 files changed, 3263 deletions(-) delete mode 100644 toolkit/mozapps/extensions/nsBlocklistService.js delete mode 100644 toolkit/mozapps/webextensions/nsBlocklistService.js delete mode 100644 toolkit/mozapps/webextensions/nsBlocklistServiceContent.js (limited to 'toolkit/mozapps') diff --git a/toolkit/mozapps/extensions/extensions.manifest b/toolkit/mozapps/extensions/extensions.manifest index 14aca3ff6..7efb74a9d 100644 --- a/toolkit/mozapps/extensions/extensions.manifest +++ b/toolkit/mozapps/extensions/extensions.manifest @@ -1,7 +1,3 @@ -component {66354bc9-7ed1-4692-ae1d-8da97d6b205e} nsBlocklistService.js -contract @mozilla.org/extensions/blocklist;1 {66354bc9-7ed1-4692-ae1d-8da97d6b205e} -category profile-after-change nsBlocklistService @mozilla.org/extensions/blocklist;1 -category update-timer nsBlocklistService @mozilla.org/extensions/blocklist;1,getService,blocklist-background-update-timer,extensions.blocklist.interval,86400 component {4399533d-08d1-458c-a87a-235f74451cfa} addonManager.js contract @mozilla.org/addons/integration;1 {4399533d-08d1-458c-a87a-235f74451cfa} category update-timer addonManager @mozilla.org/addons/integration;1,getService,addon-background-update-timer,extensions.update.interval,86400 diff --git a/toolkit/mozapps/extensions/moz.build b/toolkit/mozapps/extensions/moz.build index 19f449210..ca04d74a0 100644 --- a/toolkit/mozapps/extensions/moz.build +++ b/toolkit/mozapps/extensions/moz.build @@ -25,7 +25,6 @@ EXTRA_COMPONENTS += [ EXTRA_PP_COMPONENTS += [ 'extensions.manifest', - 'nsBlocklistService.js', ] EXTRA_JS_MODULES += [ diff --git a/toolkit/mozapps/extensions/nsBlocklistService.js b/toolkit/mozapps/extensions/nsBlocklistService.js deleted file mode 100644 index 487dae8e5..000000000 --- a/toolkit/mozapps/extensions/nsBlocklistService.js +++ /dev/null @@ -1,1478 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cr = Components.results; - -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource://gre/modules/Services.jsm"); - -try { - // AddonManager.jsm doesn't allow itself to be imported in the child - // process. We're used in the child process (for now), so guard against - // this. - Components.utils.import("resource://gre/modules/AddonManager.jsm"); -} catch (e) { -} - -XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", - "resource://gre/modules/FileUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel", - "resource://gre/modules/UpdateChannel.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "OS", - "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); - -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_INTERVAL = "extensions.blocklist.interval"; -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_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser"; -const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale"; -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 UNKNOWN_XPCOM_ABI = "unknownABI"; -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; - -const EXTENSION_BLOCK_FILTERS = ["id", "name", "creator", "homepageURL", "updateURL"]; - -var gLoggingEnabled = null; -var gBlocklistEnabled = true; -var gBlocklistLevel = DEFAULT_LEVEL; - -XPCOMUtils.defineLazyServiceGetter(this, "gConsole", - "@mozilla.org/consoleservice;1", - "nsIConsoleService"); - -XPCOMUtils.defineLazyServiceGetter(this, "gVersionChecker", - "@mozilla.org/xpcom/version-comparator;1", - "nsIVersionComparator"); - -XPCOMUtils.defineLazyServiceGetter(this, "gCertBlocklistService", - "@mozilla.org/security/certblocklist;1", - "nsICertBlocklist"); - -XPCOMUtils.defineLazyGetter(this, "gPref", function bls_gPref() { - return Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService). - QueryInterface(Ci.nsIPrefBranch); -}); - -XPCOMUtils.defineLazyGetter(this, "gApp", function bls_gApp() { - return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo). - QueryInterface(Ci.nsIXULRuntime); -}); - -XPCOMUtils.defineLazyGetter(this, "gABI", function bls_gABI() { - let abi = null; - try { - abi = gApp.XPCOMABI; - } - catch (e) { - LOG("BlockList Global gABI: XPCOM ABI unknown."); - } -#ifdef XP_MACOSX - // Mac universal build should report a different ABI than either macppc - // or mactel. - let macutils = Cc["@mozilla.org/xpcom/mac-utils;1"]. - getService(Ci.nsIMacUtils); - - if (macutils.isUniversalBinary) - abi += "-u-" + macutils.architecturesInBinary; -#endif - return abi; -}); - -XPCOMUtils.defineLazyGetter(this, "gOSVersion", function bls_gOSVersion() { - let osVersion; - let sysInfo = Cc["@mozilla.org/system-info;1"]. - getService(Ci.nsIPropertyBag2); - try { - osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version"); - } - catch (e) { - LOG("BlockList Global gOSVersion: OS Version unknown."); - } - - if (osVersion) { - try { - osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")"; - } - catch (e) { - // Not all platforms have a secondary widget library, so an error is nothing to worry about. - } - osVersion = encodeURIComponent(osVersion); - } - return osVersion; -}); - -// shared code for suppressing bad cert dialogs -XPCOMUtils.defineLazyGetter(this, "gCertUtils", function bls_gCertUtils() { - let temp = { }; - Components.utils.import("resource://gre/modules/CertUtils.jsm", temp); - return temp; -}); - -/** - * Logs a string to the error console. - * @param string - * The string to write to the error console.. - */ -function LOG(string) { - if (gLoggingEnabled) { - dump("*** " + string + "\n"); - gConsole.logStringMessage(string); - } -} - -/** - * Gets a preference value, handling the case where there is no default. - * @param func - * The name of the preference function to call, on nsIPrefBranch - * @param preference - * The name of the preference - * @param defaultValue - * The default value to return in the event the preference has - * no setting - * @returns The value of the preference, or undefined if there was no - * user or default value. - */ -function getPref(func, preference, defaultValue) { - try { - return gPref[func](preference); - } - catch (e) { - } - return defaultValue; -} - -/** - * Constructs a URI to a spec. - * @param spec - * The spec to construct a URI to - * @returns The nsIURI constructed. - */ -function newURI(spec) { - var ioServ = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ioServ.newURI(spec, null, null); -} - -// Restarts the application checking in with observers first -function restartApp() { - // Notify all windows that an application quit has been requested. - var os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]. - createInstance(Ci.nsISupportsPRBool); - os.notifyObservers(cancelQuit, "quit-application-requested", null); - - // Something aborted the quit process. - if (cancelQuit.data) - return; - - var as = Cc["@mozilla.org/toolkit/app-startup;1"]. - getService(Ci.nsIAppStartup); - as.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. - */ -function matchesOSABI(blocklistElement) { - if (blocklistElement.hasAttribute("os")) { - var choices = blocklistElement.getAttribute("os").split(","); - if (choices.length > 0 && choices.indexOf(gApp.OS) < 0) - return false; - } - - if (blocklistElement.hasAttribute("xpcomabi")) { - choices = blocklistElement.getAttribute("xpcomabi").split(","); - if (choices.length > 0 && choices.indexOf(gApp.XPCOMABI) < 0) - 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. - */ -function getLocale() { - try { - // Get the default branch - var defaultPrefs = gPref.getDefaultBranch(null); - return defaultPrefs.getComplexValue(PREF_GENERAL_USERAGENT_LOCALE, - Ci.nsIPrefLocalizedString).data; - } catch (e) {} - - return gPref.getCharPref(PREF_GENERAL_USERAGENT_LOCALE); -} - -/* Get the distribution pref values, from defaults only */ -function getDistributionPrefValue(aPrefName) { - var prefValue = "default"; - - var defaults = gPref.getDefaultBranch(null); - try { - prefValue = defaults.getCharPref(aPrefName); - } catch (e) { - // use default when pref not found - } - - return prefValue; -} - -/** - * Parse a string representation of a regular expression. Needed because we - * use the /pattern/flags form (because it's detectable), which is only - * supported as a literal in JS. - * - * @param aStr - * String representation of regexp - * @return RegExp instance - */ -function parseRegExp(aStr) { - let lastSlash = aStr.lastIndexOf("/"); - let pattern = aStr.slice(1, lastSlash); - let flags = aStr.slice(lastSlash + 1); - return new RegExp(pattern, flags); -} - -/** - * Helper function to test if the blockEntry matches with the plugin. - * - * @param blockEntry - * The plugin blocklist entries to compare against. - * @param plugin - * The nsIPluginTag to get the blocklist state for. - * @returns True if the blockEntry matches the plugin, false otherwise. - */ -function matchesAllPluginNames(blockEntry, plugin) { - for (let name in blockEntry.matches) { - if (!(name in plugin) || - typeof(plugin[name]) != "string" || - !blockEntry.matches[name].test(plugin[name])) { - return false; - } - } - return true; -} - -/** - * Manages the Blocklist. The Blocklist is a representation of the contents of - * blocklist.xml and allows us to remotely disable / re-enable blocklisted - * items managed by the Extension Manager with an item's appDisabled property. - * It also blocklists plugins with data from blocklist.xml. - */ - -function Blocklist() { - Services.obs.addObserver(this, "xpcom-shutdown", false); - Services.obs.addObserver(this, "sessionstore-windows-restored", false); - gLoggingEnabled = getPref("getBoolPref", PREF_EM_LOGGING_ENABLED, false); - gBlocklistEnabled = getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true); - gBlocklistLevel = Math.min(getPref("getIntPref", PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL), - MAX_BLOCK_LEVEL); - gPref.addObserver("extensions.blocklist.", this, false); - gPref.addObserver(PREF_EM_LOGGING_ENABLED, this, false); - this.wrappedJSObject = this; -} - -Blocklist.prototype = { - /** - * 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, - - observe: function Blocklist_observe(aSubject, aTopic, aData) { - switch (aTopic) { - case "xpcom-shutdown": - Services.obs.removeObserver(this, "xpcom-shutdown"); - gPref.removeObserver("extensions.blocklist.", this); - gPref.removeObserver(PREF_EM_LOGGING_ENABLED, this); - break; - case "nsPref:changed": - switch (aData) { - case PREF_EM_LOGGING_ENABLED: - gLoggingEnabled = getPref("getBoolPref", PREF_EM_LOGGING_ENABLED, false); - break; - case PREF_BLOCKLIST_ENABLED: - gBlocklistEnabled = getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true); - this._loadBlocklist(); - this._blocklistUpdated(null, null); - break; - case PREF_BLOCKLIST_LEVEL: - gBlocklistLevel = Math.min(getPref("getIntPref", PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL), - MAX_BLOCK_LEVEL); - this._blocklistUpdated(null, null); - break; - } - break; - case "sessionstore-windows-restored": - Services.obs.removeObserver(this, "sessionstore-windows-restored"); - this._preloadBlocklist(); - break; - } - }, - - /* See nsIBlocklistService */ - isAddonBlocklisted: function Blocklist_isAddonBlocklisted(addon, appVersion, toolkitVersion) { - return this.getAddonBlocklistState(addon, appVersion, toolkitVersion) == - Ci.nsIBlocklistService.STATE_BLOCKED; - }, - - /* See nsIBlocklistService */ - getAddonBlocklistState: function Blocklist_getAddonBlocklistState(addon, appVersion, toolkitVersion) { - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - return this._getAddonBlocklistState(addon, this._addonEntries, - appVersion, toolkitVersion); - }, - - /** - * Private version of getAddonBlocklistState that allows the caller to pass in - * the add-on blocklist entries to compare against. - * - * @param id - * The ID of the item to get the blocklist state for. - * @param version - * The version of the item to get the blocklist state for. - * @param addonEntries - * The add-on blocklist entries to compare against. - * @param appVersion - * The application version to compare to, will use the current - * version if null. - * @param toolkitVersion - * The toolkit version to compare to, will use the current version if - * null. - * @returns The blocklist state for the item, one of the STATE constants as - * defined in nsIBlocklistService. - */ - _getAddonBlocklistState: function Blocklist_getAddonBlocklistStateCall(addon, - addonEntries, appVersion, toolkitVersion) { - if (!gBlocklistEnabled) - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - - if (!appVersion) - appVersion = gApp.version; - if (!toolkitVersion) - toolkitVersion = gApp.platformVersion; - - var blItem = this._findMatchingAddonEntry(addonEntries, addon); - if (!blItem) - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - - for (let currentblItem of blItem.versions) { - if (currentblItem.includesItem(addon.version, appVersion, toolkitVersion)) - return currentblItem.severity >= gBlocklistLevel ? Ci.nsIBlocklistService.STATE_BLOCKED : - Ci.nsIBlocklistService.STATE_SOFTBLOCKED; - } - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - }, - - /** - * Returns the set of prefs of the add-on stored in the blocklist file - * (probably to revert them on disabling). - * @param addon - * The add-on whose to-be-reset prefs are to be found. - */ - _getAddonPrefs: function Blocklist_getAddonPrefs(addon) { - let entry = this._findMatchingAddonEntry(this._addonEntries, addon); - return entry.prefs.slice(0); - }, - - _findMatchingAddonEntry: function Blocklist_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 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; - }, - - /* See nsIBlocklistService */ - getAddonBlocklistURL: function Blocklist_getAddonBlocklistURL(addon, appVersion, toolkitVersion) { - if (!gBlocklistEnabled) - return ""; - - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - - let blItem = this._findMatchingAddonEntry(this._addonEntries, addon); - if (!blItem || !blItem.blockID) - return null; - - return this._createBlocklistURL(blItem.blockID); - }, - - _createBlocklistURL: function Blocklist_createBlocklistURL(id) { - let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL); - url = url.replace(/%blockID%/g, id); - - return url; - }, - - notify: function Blocklist_notify(aTimer) { - if (!gBlocklistEnabled) - return; - - try { - var dsURI = gPref.getCharPref(PREF_BLOCKLIST_URL); - } - catch (e) { - LOG("Blocklist::notify: The " + PREF_BLOCKLIST_URL + " preference" + - " is missing!"); - return; - } - - var pingCountVersion = getPref("getIntPref", PREF_BLOCKLIST_PINGCOUNTVERSION, 0); - var pingCountTotal = getPref("getIntPref", PREF_BLOCKLIST_PINGCOUNTTOTAL, 1); - var daysSinceLastPing = 0; - if (pingCountVersion == 0) { - daysSinceLastPing = "new"; - } - else { - // Seconds in one day is used because nsIUpdateTimerManager stores the - // last update time in seconds. - let secondsInDay = 60 * 60 * 24; - let lastUpdateTime = getPref("getIntPref", PREF_BLOCKLIST_LASTUPDATETIME, 0); - if (lastUpdateTime == 0) { - daysSinceLastPing = "invalid"; - } - else { - let now = Math.round(Date.now() / 1000); - daysSinceLastPing = Math.floor((now - lastUpdateTime) / secondsInDay); - } - - if (daysSinceLastPing == 0 || daysSinceLastPing == "invalid") { - pingCountVersion = pingCountTotal = "invalid"; - } - } - - if (pingCountVersion < 1) - pingCountVersion = 1; - if (pingCountTotal < 1) - pingCountTotal = 1; - - dsURI = dsURI.replace(/%APP_ID%/g, gApp.ID); - dsURI = dsURI.replace(/%APP_VERSION%/g, gApp.version); - dsURI = dsURI.replace(/%PRODUCT%/g, gApp.name); - dsURI = dsURI.replace(/%VERSION%/g, gApp.version); - dsURI = dsURI.replace(/%BUILD_ID%/g, gApp.appBuildID); - dsURI = dsURI.replace(/%BUILD_TARGET%/g, gApp.OS + "_" + gABI); - dsURI = dsURI.replace(/%OS_VERSION%/g, gOSVersion); - dsURI = dsURI.replace(/%LOCALE%/g, getLocale()); - dsURI = dsURI.replace(/%CHANNEL%/g, UpdateChannel.get()); - dsURI = dsURI.replace(/%PLATFORM_VERSION%/g, gApp.platformVersion); - dsURI = dsURI.replace(/%DISTRIBUTION%/g, - getDistributionPrefValue(PREF_APP_DISTRIBUTION)); - dsURI = dsURI.replace(/%DISTRIBUTION_VERSION%/g, - getDistributionPrefValue(PREF_APP_DISTRIBUTION_VERSION)); - dsURI = dsURI.replace(/%PING_COUNT%/g, pingCountVersion); - dsURI = dsURI.replace(/%TOTAL_PING_COUNT%/g, pingCountTotal); - dsURI = dsURI.replace(/%DAYS_SINCE_LAST_PING%/g, daysSinceLastPing); - dsURI = dsURI.replace(/\+/g, "%2B"); - - // Under normal operations it will take around 5,883,516 years before the - // preferences used to store pingCountVersion and pingCountTotal will rollover - // so this code doesn't bother trying to do the "right thing" here. - if (pingCountVersion != "invalid") { - pingCountVersion++; - if (pingCountVersion > 2147483647) { - // Rollover to -1 if the value is greater than what is support by an - // integer preference. The -1 indicates that the counter has been reset. - pingCountVersion = -1; - } - gPref.setIntPref(PREF_BLOCKLIST_PINGCOUNTVERSION, pingCountVersion); - } - - if (pingCountTotal != "invalid") { - pingCountTotal++; - if (pingCountTotal > 2147483647) { - // Rollover to 1 if the value is greater than what is support by an - // integer preference. - pingCountTotal = -1; - } - gPref.setIntPref(PREF_BLOCKLIST_PINGCOUNTTOTAL, pingCountTotal); - } - - // Verify that the URI is valid - try { - var uri = newURI(dsURI); - } - catch (e) { - LOG("Blocklist::notify: There was an error creating the blocklist URI\r\n" + - "for: " + dsURI + ", error: " + e); - return; - } - - LOG("Blocklist::notify: Requesting " + uri.spec); - var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. - createInstance(Ci.nsIXMLHttpRequest); - request.open("GET", uri.spec, true); - request.channel.notificationCallbacks = new gCertUtils.BadCertHandler(); - request.overrideMimeType("text/xml"); - request.setRequestHeader("Cache-Control", "no-cache"); - request.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest); - - var self = this; - request.addEventListener("error", function errorEventListener(event) { - self.onXMLError(event); }, false); - request.addEventListener("load", function loadEventListener(event) { - self.onXMLLoad(event); }, false); - request.send(null); - - // When the blocklist loads we need to compare it to the current copy so - // make sure we have loaded it. - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - }, - - onXMLLoad: Task.async(function* (aEvent) { - let request = aEvent.target; - try { - gCertUtils.checkCert(request.channel); - } - catch (e) { - LOG("Blocklist::onXMLLoad: " + e); - return; - } - let responseXML = request.responseXML; - if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR || - (request.status != 200 && request.status != 0)) { - LOG("Blocklist::onXMLLoad: there was an error during load"); - return; - } - - var oldAddonEntries = this._addonEntries; - var oldPluginEntries = this._pluginEntries; - this._addonEntries = []; - this._pluginEntries = []; - - this._loadBlocklistFromString(request.responseText); - this._blocklistUpdated(oldAddonEntries, oldPluginEntries); - - try { - let path = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST); - yield OS.File.writeAtomic(path, request.responseText, {tmpPath: path + ".tmp"}); - } catch (e) { - LOG("Blocklist::onXMLLoad: " + e); - } - }), - - onXMLError: function Blocklist_onXMLError(aEvent) { - try { - var request = aEvent.target; - // the following may throw (e.g. a local file or timeout) - var status = request.status; - } - catch (e) { - request = aEvent.target.channel.QueryInterface(Ci.nsIRequest); - status = request.status; - } - var statusText = "nsIXMLHttpRequest channel unavailable"; - // When status is 0 we don't have a valid channel. - if (status != 0) { - try { - statusText = request.statusText; - } catch (e) { - } - } - LOG("Blocklist:onError: There was an error loading the blocklist file\r\n" + - statusText); - }, - - /** - * Finds the newest blocklist file from the application and the profile and - * load it or does nothing if neither exist. - */ - _loadBlocklist: function Blocklist_loadBlocklist() { - this._addonEntries = []; - this._pluginEntries = []; - var profFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]); - if (profFile.exists()) { - this._loadBlocklistFromFile(profFile); - return; - } - var appFile = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]); - if (appFile.exists()) { - this._loadBlocklistFromFile(appFile); - return; - } - LOG("Blocklist::_loadBlocklist: no XML File found"); - }, - - /** -# The blocklist XML file looks something like this: -# -# -# -# -# -# accessibility.accesskeycausesactivation -# accessibility.blockautorefresh -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# AkHVNA== -# -# -# - */ - - _loadBlocklistFromFile: function Blocklist_loadBlocklistFromFile(file) { - if (!gBlocklistEnabled) { - LOG("Blocklist::_loadBlocklistFromFile: blocklist is disabled"); - return; - } - - let telemetry = Services.telemetry; - - if (this._isBlocklistPreloaded()) { - telemetry.getHistogramById("BLOCKLIST_SYNC_FILE_LOAD").add(false); - this._loadBlocklistFromString(this._preloadedBlocklistContent); - delete this._preloadedBlocklistContent; - return; - } - - if (!file.exists()) { - LOG("Blocklist::_loadBlocklistFromFile: XML File does not exist " + file.path); - return; - } - - telemetry.getHistogramById("BLOCKLIST_SYNC_FILE_LOAD").add(true); - - let text = ""; - let fstream = null; - let cstream = null; - - try { - fstream = Components.classes["@mozilla.org/network/file-input-stream;1"] - .createInstance(Components.interfaces.nsIFileInputStream); - cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"] - .createInstance(Components.interfaces.nsIConverterInputStream); - - fstream.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0); - cstream.init(fstream, "UTF-8", 0, 0); - - let str = {}; - let read = 0; - - do { - read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value - text += str.value; - } while (read != 0); - } catch (e) { - LOG("Blocklist::_loadBlocklistFromFile: Failed to load XML file " + e); - } finally { - if (cstream) - cstream.close(); - if (fstream) - fstream.close(); - } - - if (text) - this._loadBlocklistFromString(text); - }, - - _isBlocklistLoaded: function() { - return this._addonEntries != null && this._pluginEntries != null; - }, - - _isBlocklistPreloaded: function() { - return this._preloadedBlocklistContent != null; - }, - - /* Used for testing */ - _clear: function() { - this._addonEntries = null; - this._pluginEntries = null; - this._preloadedBlocklistContent = null; - }, - - _preloadBlocklist: Task.async(function*() { - let profPath = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST); - try { - yield this._preloadBlocklistFile(profPath); - return; - } catch (e) { - LOG("Blocklist::_preloadBlocklist: Failed to load XML file " + e) - } - - var appFile = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]); - try{ - yield this._preloadBlocklistFile(appFile.path); - return; - } catch (e) { - LOG("Blocklist::_preloadBlocklist: Failed to load XML file " + e) - } - - LOG("Blocklist::_preloadBlocklist: no XML File found"); - }), - - _preloadBlocklistFile: Task.async(function* (path){ - if (this._addonEntries) { - // The file has been already loaded. - return; - } - - if (!gBlocklistEnabled) { - LOG("Blocklist::_preloadBlocklistFile: blocklist is disabled"); - return; - } - - let text = yield OS.File.read(path, { encoding: "utf-8" }); - - if (!this._addonEntries) { - // Store the content only if a sync load has not been performed in the meantime. - this._preloadedBlocklistContent = text; - } - }), - - _loadBlocklistFromString : function Blocklist_loadBlocklistFromString(text) { - try { - var parser = Cc["@mozilla.org/xmlextras/domparser;1"]. - createInstance(Ci.nsIDOMParser); - var doc = parser.parseFromString(text, "text/xml"); - if (doc.documentElement.namespaceURI != XMLURI_BLOCKLIST) { - LOG("Blocklist::_loadBlocklistFromFile: aborting due to incorrect " + - "XML Namespace.\r\nExpected: " + XMLURI_BLOCKLIST + "\r\n" + - "Received: " + doc.documentElement.namespaceURI); - return; - } - - var childNodes = doc.documentElement.childNodes; - for (let element of childNodes) { - if (!(element instanceof Ci.nsIDOMElement)) - continue; - switch (element.localName) { - case "emItems": - this._addonEntries = this._processItemNodes(element.childNodes, "em", - this._handleEmItemNode); - break; - case "pluginItems": - this._pluginEntries = this._processItemNodes(element.childNodes, "plugin", - this._handlePluginItemNode); - break; - case "certItems": - this._processItemNodes(element.childNodes, "cert", - this._handleCertItemNode.bind(this)); - break; - default: - Services.obs.notifyObservers(element, - "blocklist-data-" + element.localName, - null); - } - } - gCertBlocklistService.saveEntries(); - } - catch (e) { - LOG("Blocklist::_loadBlocklistFromFile: Error constructing blocklist " + e); - return; - } - }, - - _processItemNodes: function Blocklist_processItemNodes(itemNodes, prefix, handler) { - var result = []; - var itemName = prefix + "Item"; - for (var i = 0; i < itemNodes.length; ++i) { - var blocklistElement = itemNodes.item(i); - if (!(blocklistElement instanceof Ci.nsIDOMElement) || - blocklistElement.localName != itemName) - continue; - - handler(blocklistElement, result); - } - return result; - }, - - _handleCertItemNode: function Blocklist_handleCertItemNode(blocklistElement, - result) { - let issuer = blocklistElement.getAttribute("issuerName"); - for (let snElement of blocklistElement.children) { - try { - gCertBlocklistService.revokeCertByIssuerAndSerial(issuer, snElement.textContent); - } catch (e) { - // we want to keep trying other elements since missing all items - // is worse than missing one - LOG("Blocklist::_handleCertItemNode: Error adding revoked cert " + e); - } - } - }, - - _handleEmItemNode: function Blocklist_handleEmItemNode(blocklistElement, result) { - if (!matchesOSABI(blocklistElement)) - return; - - let blockEntry = { - versions: [], - prefs: [], - blockID: null, - attributes: new Map() - // Atleast one of EXTENSION_BLOCK_FILTERS must get added to attributes - }; - - // Any filter starting with '/' is interpreted as a regex. So if an attribute - // starts with a '/' it must be checked via a regex. - function regExpCheck(attr) { - return attr.startsWith("/") ? parseRegExp(attr) : attr; - } - - for (let filter of EXTENSION_BLOCK_FILTERS) { - let attr = blocklistElement.getAttribute(filter); - if (attr) - blockEntry.attributes.set(filter, regExpCheck(attr)); - } - - var childNodes = blocklistElement.childNodes; - - for (let x = 0; x < childNodes.length; x++) { - var childElement = childNodes.item(x); - if (!(childElement instanceof Ci.nsIDOMElement)) - continue; - if (childElement.localName === "prefs") { - let prefElements = childElement.childNodes; - for (let i = 0; i < prefElements.length; i++) { - let prefElement = prefElements.item(i); - if (!(prefElement instanceof Ci.nsIDOMElement) || - prefElement.localName !== "pref") - continue; - blockEntry.prefs.push(prefElement.textContent); - } - } - else if (childElement.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: function Blocklist_handlePluginItemNode(blocklistElement, result) { - if (!matchesOSABI(blocklistElement)) - return; - - var matchNodes = blocklistElement.childNodes; - var blockEntry = { - matches: {}, - versions: [], - blockID: null, - infoURL: null, - }; - var hasMatch = false; - for (var x = 0; x < matchNodes.length; ++x) { - var matchElement = matchNodes.item(x); - if (!(matchElement instanceof Ci.nsIDOMElement)) - continue; - if (matchElement.localName == "match") { - var name = matchElement.getAttribute("name"); - var exp = matchElement.getAttribute("exp"); - try { - blockEntry.matches[name] = new RegExp(exp, "m"); - hasMatch = true; - } catch (e) { - // Ignore invalid regular expressions - } - } - if (matchElement.localName == "versionRange") { - blockEntry.versions.push(new BlocklistItemData(matchElement)); - } - else if (matchElement.localName == "infoURL") { - blockEntry.infoURL = matchElement.textContent; - } - } - // 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); - }, - - /* See nsIBlocklistService */ - getPluginBlocklistState: function Blocklist_getPluginBlocklistState(plugin, - appVersion, toolkitVersion) { - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - return this._getPluginBlocklistState(plugin, this._pluginEntries, - appVersion, toolkitVersion); - }, - - /** - * Private version of getPluginBlocklistState that allows the caller to pass in - * the plugin blocklist entries. - * - * @param plugin - * The nsIPluginTag to get the blocklist state for. - * @param pluginEntries - * The plugin blocklist entries to compare against. - * @param appVersion - * The application version to compare to, will use the current - * version if null. - * @param toolkitVersion - * The toolkit version to compare to, will use the current version if - * null. - * @returns The blocklist state for the item, one of the STATE constants as - * defined in nsIBlocklistService. - */ - _getPluginBlocklistState: function Blocklist_getPluginBlocklistState(plugin, - pluginEntries, appVersion, toolkitVersion) { - if (!gBlocklistEnabled) - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - - if (!appVersion) - appVersion = gApp.version; - if (!toolkitVersion) - toolkitVersion = gApp.platformVersion; - - for each (var blockEntry in pluginEntries) { - var matchFailed = false; - for (var name in blockEntry.matches) { - if (!(name in plugin) || - typeof(plugin[name]) != "string" || - !blockEntry.matches[name].test(plugin[name])) { - matchFailed = true; - break; - } - } - - if (matchFailed) - continue; - - for (let blockEntryVersion of blockEntry.versions) { - if (blockEntryVersion.includesItem(plugin.version, appVersion, - toolkitVersion)) { - 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 Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - }, - - /** - * Get the matching blocklist entry for the passed plugin, if - * available. - * @param plugin The plugin to find the block entry for. - * @returns The block entry which matches the passed plugin, null - * otherwise. - */ - _getPluginBlockEntry: function (plugin) { - if (!gBlocklistEnabled) - return null; - - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - - for each (let blockEntry in this._pluginEntries) { - if (matchesAllPluginNames(blockEntry, plugin)) { - return blockEntry; - } - } - - return null; - }, - - /* See nsIBlocklistService */ - getPluginBlocklistURL: function Blocklist_getPluginBlocklistURL(plugin) { - let blockEntry = this._getPluginBlockEntry(plugin); - if (!blockEntry || !blockEntry.blockID) { - return null; - } - - return this._createBlocklistURL(blockEntry.blockID); - }, - - /* See nsIBlocklistService */ - getPluginInfoURL: function (plugin) { - let blockEntry = this._getPluginBlockEntry(plugin); - if (!blockEntry || !blockEntry.blockID) { - return null; - } - - return blockEntry.infoURL; - }, - - _blocklistUpdated: function Blocklist_blocklistUpdated(oldAddonEntries, oldPluginEntries) { - var addonList = []; - - // A helper function that reverts the prefs passed to default values. - function resetPrefs(prefs) { - for (let pref of prefs) - gPref.clearUserPref(pref); - } - var self = this; - const types = ["extension", "theme", "locale", "dictionary", "service"]; - AddonManager.getAddonsByTypes(types, function blocklistUpdated_getAddonsByTypes(addons) { - - for (let addon of addons) { - let oldState = Ci.nsIBlocklistService.STATE_NOTBLOCKED; - if (oldAddonEntries) - oldState = self._getAddonBlocklistState(addon, oldAddonEntries); - let state = self.getAddonBlocklistState(addon); - - 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 = self._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) - continue; - - addonList.push({ - name: addon.name, - version: addon.version, - icon: addon.iconURL, - disable: false, - blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED, - item: addon, - url: self.getAddonBlocklistURL(addon), - }); - } - - AddonManagerPrivate.updateAddonAppDisabledStates(); - - var phs = Cc["@mozilla.org/plugin/host;1"]. - getService(Ci.nsIPluginHost); - var plugins = phs.getPluginTags(); - - for (let plugin of plugins) { - let oldState = -1; - if (oldPluginEntries) - oldState = self._getPluginBlocklistState(plugin, oldPluginEntries); - let state = self.getPluginBlocklistState(plugin); - 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) { - gPref.setBoolPref(PREF_PLUGINS_NOTIFYUSER, true); - } - else if (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.png", - disable: false, - blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED, - item: plugin, - url: self.getPluginBlocklistURL(plugin), - }); - } - } - } - - if (addonList.length == 0) { - Services.obs.notifyObservers(self, "blocklist-updated", ""); - return; - } - - if ("@mozilla.org/addons/blocklist-prompt;1" in Cc) { - try { - let blockedPrompter = Cc["@mozilla.org/addons/blocklist-prompt;1"] - .getService(Ci.nsIBlocklistPrompt); - blockedPrompter.prompt(addonList); - } catch (e) { - LOG(e); - } - Services.obs.notifyObservers(self, "blocklist-updated", ""); - 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 = function blocklistUpdated_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 = self._getAddonPrefs(addon.item); - resetPrefs(prefs); - } - } - - if (args.restart) - restartApp(); - - Services.obs.notifyObservers(self, "blocklist-updated", ""); - Services.obs.removeObserver(applyBlocklistChanges, "addon-blocklist-closed"); - } - - Services.obs.addObserver(applyBlocklistChanges, "addon-blocklist-closed", false); - - if (getPref("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, false); - }); - }, - - classID: Components.ID("{66354bc9-7ed1-4692-ae1d-8da97d6b205e}"), - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, - Ci.nsIBlocklistService, - Ci.nsITimerCallback]), -}; - -/** - * Helper for constructing a blocklist. - */ -function BlocklistItemData(versionRangeElement) { - var versionRange = this.getBlocklistVersionRange(versionRangeElement); - this.minVersion = versionRange.minVersion; - this.maxVersion = versionRange.maxVersion; - if (versionRangeElement && versionRangeElement.hasAttribute("severity")) - this.severity = versionRangeElement.getAttribute("severity"); - else - this.severity = DEFAULT_SEVERITY; - if (versionRangeElement && versionRangeElement.hasAttribute("vulnerabilitystatus")) { - this.vulnerabilityStatus = versionRangeElement.getAttribute("vulnerabilitystatus"); - } else { - this.vulnerabilityStatus = VULNERABILITYSTATUS_NONE; - } - this.targetApps = { }; - var found = false; - - if (versionRangeElement) { - for (var i = 0; i < versionRangeElement.childNodes.length; ++i) { - var targetAppElement = versionRangeElement.childNodes.item(i); - if (!(targetAppElement instanceof Ci.nsIDOMElement) || - targetAppElement.localName != "targetApplication") - continue; - found = true; - // default to the current application if id is not provided. - var appID = targetAppElement.hasAttribute("id") ? targetAppElement.getAttribute("id") : gApp.ID; - this.targetApps[appID] = this.getBlocklistAppVersions(targetAppElement); - } - } - // Default to all versions of the current application when no targetApplication - // elements were found - if (!found) - this.targetApps[gApp.ID] = this.getBlocklistAppVersions(null); -} - -BlocklistItemData.prototype = { - /** - * Tests if a version of an item is included in the version range and target - * application information represented by this BlocklistItemData using the - * provided application and toolkit versions. - * @param version - * The version of the item being tested. - * @param appVersion - * The application version to test with. - * @param toolkitVersion - * The toolkit version to test with. - * @returns True if the version range covers the item version and application - * or toolkit version. - */ - includesItem: function BlocklistItemData_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(gApp.ID, 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 version - * The version to test. - * @param minVersion - * The minimum version. If null it is assumed that version is always - * larger. - * @param maxVersion - * The maximum version. If null it is assumed that version is always - * smaller. - */ - matchesRange: function BlocklistItemData_matchesRange(version, minVersion, maxVersion) { - if (minVersion && gVersionChecker.compare(version, minVersion) < 0) - return false; - if (maxVersion && gVersionChecker.compare(version, maxVersion) > 0) - return false; - return true; - }, - - /** - * Tests if there is a matching range for the given target application id and - * version. - * @param appID - * The application ID to test for, may be for an application or toolkit - * @param appVersion - * The version of the application to test for. - * @returns True if this version range covers the application version given. - */ - matchesTargetRange: function BlocklistItemData_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 targetAppElement - * A targetApplication blocklist element. - * @returns 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: function BlocklistItemData_getBlocklistAppVersions(targetAppElement) { - var appVersions = [ ]; - - if (targetAppElement) { - for (var i = 0; i < targetAppElement.childNodes.length; ++i) { - var versionRangeElement = targetAppElement.childNodes.item(i); - if (!(versionRangeElement instanceof Ci.nsIDOMElement) || - versionRangeElement.localName != "versionRange") - continue; - appVersions.push(this.getBlocklistVersionRange(versionRangeElement)); - } - } - // return minVersion = null and maxVersion = null if no specific versionRange - // elements were found - if (appVersions.length == 0) - appVersions.push(this.getBlocklistVersionRange(null)); - return appVersions; - }, - - /** - * Retrieves a version range (e.g. minVersion and maxVersion) for a blocklist - * versionRange element. - * @param versionRangeElement - * The versionRange blocklist element. - * @returns A JS object with the following properties: - * "minVersion" The minimum version in a version range (default = null). - * "maxVersion" The maximum version in a version range (default = null). - */ - getBlocklistVersionRange: function BlocklistItemData_getBlocklistVersionRange(versionRangeElement) { - var minVersion = null; - var maxVersion = null; - if (!versionRangeElement) - return { minVersion: minVersion, maxVersion: maxVersion }; - - if (versionRangeElement.hasAttribute("minVersion")) - minVersion = versionRangeElement.getAttribute("minVersion"); - if (versionRangeElement.hasAttribute("maxVersion")) - maxVersion = versionRangeElement.getAttribute("maxVersion"); - - return { minVersion: minVersion, maxVersion: maxVersion }; - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Blocklist]); diff --git a/toolkit/mozapps/webextensions/extensions.manifest b/toolkit/mozapps/webextensions/extensions.manifest index 7ce20c3ec..2129012ab 100644 --- a/toolkit/mozapps/webextensions/extensions.manifest +++ b/toolkit/mozapps/webextensions/extensions.manifest @@ -1,10 +1,3 @@ -component {66354bc9-7ed1-4692-ae1d-8da97d6b205e} nsBlocklistService.js process=main -contract @mozilla.org/extensions/blocklist;1 {66354bc9-7ed1-4692-ae1d-8da97d6b205e} process=main -category profile-after-change nsBlocklistService @mozilla.org/extensions/blocklist;1 process=main -component {e0a106ed-6ad4-47a4-b6af-2f1c8aa4712d} nsBlocklistServiceContent.js process=content -contract @mozilla.org/extensions/blocklist;1 {e0a106ed-6ad4-47a4-b6af-2f1c8aa4712d} process=content - -category update-timer nsBlocklistService @mozilla.org/extensions/blocklist;1,getService,blocklist-background-update-timer,extensions.blocklist.interval,86400 component {4399533d-08d1-458c-a87a-235f74451cfa} addonManager.js contract @mozilla.org/addons/integration;1 {4399533d-08d1-458c-a87a-235f74451cfa} #ifndef MOZ_WIDGET_ANDROID diff --git a/toolkit/mozapps/webextensions/moz.build b/toolkit/mozapps/webextensions/moz.build index b92915ae8..30152676a 100644 --- a/toolkit/mozapps/webextensions/moz.build +++ b/toolkit/mozapps/webextensions/moz.build @@ -24,8 +24,6 @@ EXTRA_COMPONENTS += [ 'amInstallTrigger.js', 'amWebAPI.js', 'amWebInstallListener.js', - 'nsBlocklistService.js', - 'nsBlocklistServiceContent.js', ] EXTRA_PP_COMPONENTS += [ diff --git a/toolkit/mozapps/webextensions/nsBlocklistService.js b/toolkit/mozapps/webextensions/nsBlocklistService.js deleted file mode 100644 index 268c197fc..000000000 --- a/toolkit/mozapps/webextensions/nsBlocklistService.js +++ /dev/null @@ -1,1658 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ - -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cr = Components.results; - -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource://gre/modules/Services.jsm"); -Components.utils.import("resource://gre/modules/AppConstants.jsm"); - -try { - // AddonManager.jsm doesn't allow itself to be imported in the child - // process. We're used in the child process (for now), so guard against - // this. - Components.utils.import("resource://gre/modules/AddonManager.jsm"); - /* globals AddonManagerPrivate*/ -} catch (e) { -} - -XPCOMUtils.defineLazyModuleGetter(this, "FileUtils", - "resource://gre/modules/FileUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", - "resource://gre/modules/UpdateUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "OS", - "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "ServiceRequest", - "resource://gre/modules/ServiceRequest.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); - -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_INTERVAL = "extensions.blocklist.interval"; -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_ONECRL_VIA_AMO = "security.onecrl.via.amo"; -const PREF_BLOCKLIST_UPDATE_ENABLED = "services.blocklist.update_enabled"; -const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale"; -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 UNKNOWN_XPCOM_ABI = "unknownABI"; -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; - -const EXTENSION_BLOCK_FILTERS = ["id", "name", "creator", "homepageURL", "updateURL"]; - -var gLoggingEnabled = null; -var gBlocklistEnabled = true; -var gBlocklistLevel = DEFAULT_LEVEL; - -XPCOMUtils.defineLazyServiceGetter(this, "gConsole", - "@mozilla.org/consoleservice;1", - "nsIConsoleService"); - -XPCOMUtils.defineLazyServiceGetter(this, "gVersionChecker", - "@mozilla.org/xpcom/version-comparator;1", - "nsIVersionComparator"); - -XPCOMUtils.defineLazyServiceGetter(this, "gCertBlocklistService", - "@mozilla.org/security/certblocklist;1", - "nsICertBlocklist"); - -XPCOMUtils.defineLazyGetter(this, "gPref", function() { - return Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService). - QueryInterface(Ci.nsIPrefBranch); -}); - -// From appinfo in Services.jsm. It is not possible to use the one in -// Services.jsm since it will not successfully QueryInterface nsIXULAppInfo in -// xpcshell tests due to other code calling Services.appinfo before the -// nsIXULAppInfo is created by the tests. -XPCOMUtils.defineLazyGetter(this, "gApp", function() { - let appinfo = Cc["@mozilla.org/xre/app-info;1"] - .getService(Ci.nsIXULRuntime); - try { - appinfo.QueryInterface(Ci.nsIXULAppInfo); - } catch (ex) { - // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). - if (!(ex instanceof Components.Exception) || - ex.result != Cr.NS_NOINTERFACE) - throw ex; - } - return appinfo; -}); - -XPCOMUtils.defineLazyGetter(this, "gABI", function() { - let abi = null; - try { - abi = gApp.XPCOMABI; - } - catch (e) { - LOG("BlockList Global gABI: XPCOM ABI unknown."); - } - - if (AppConstants.platform == "macosx") { - // Mac universal build should report a different ABI than either macppc - // or mactel. - let macutils = Cc["@mozilla.org/xpcom/mac-utils;1"]. - getService(Ci.nsIMacUtils); - - if (macutils.isUniversalBinary) - abi += "-u-" + macutils.architecturesInBinary; - } - return abi; -}); - -XPCOMUtils.defineLazyGetter(this, "gOSVersion", function() { - let osVersion; - let sysInfo = Cc["@mozilla.org/system-info;1"]. - getService(Ci.nsIPropertyBag2); - try { - osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version"); - } - catch (e) { - LOG("BlockList Global gOSVersion: OS Version unknown."); - } - - if (osVersion) { - try { - osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")"; - } - catch (e) { - // Not all platforms have a secondary widget library, so an error is nothing to worry about. - } - osVersion = encodeURIComponent(osVersion); - } - return osVersion; -}); - -// shared code for suppressing bad cert dialogs -XPCOMUtils.defineLazyGetter(this, "gCertUtils", function() { - let temp = { }; - Components.utils.import("resource://gre/modules/CertUtils.jsm", temp); - return temp; -}); - -/** - * Logs a string to the error console. - * @param string - * The string to write to the error console.. - */ -function LOG(string) { - if (gLoggingEnabled) { - dump("*** " + string + "\n"); - gConsole.logStringMessage(string); - } -} - -/** - * Gets a preference value, handling the case where there is no default. - * @param func - * The name of the preference function to call, on nsIPrefBranch - * @param preference - * The name of the preference - * @param defaultValue - * The default value to return in the event the preference has - * no setting - * @returns The value of the preference, or undefined if there was no - * user or default value. - */ -function getPref(func, preference, defaultValue) { - try { - return gPref[func](preference); - } - catch (e) { - } - return defaultValue; -} - -/** - * Constructs a URI to a spec. - * @param spec - * The spec to construct a URI to - * @returns The nsIURI constructed. - */ -function newURI(spec) { - var ioServ = Cc["@mozilla.org/network/io-service;1"]. - getService(Ci.nsIIOService); - return ioServ.newURI(spec, null, null); -} - -// Restarts the application checking in with observers first -function restartApp() { - // Notify all windows that an application quit has been requested. - var os = Cc["@mozilla.org/observer-service;1"]. - getService(Ci.nsIObserverService); - var cancelQuit = Cc["@mozilla.org/supports-PRBool;1"]. - createInstance(Ci.nsISupportsPRBool); - os.notifyObservers(cancelQuit, "quit-application-requested", null); - - // Something aborted the quit process. - if (cancelQuit.data) - return; - - var as = Cc["@mozilla.org/toolkit/app-startup;1"]. - getService(Ci.nsIAppStartup); - as.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. - */ -function matchesOSABI(blocklistElement) { - if (blocklistElement.hasAttribute("os")) { - var choices = blocklistElement.getAttribute("os").split(","); - if (choices.length > 0 && choices.indexOf(gApp.OS) < 0) - return false; - } - - if (blocklistElement.hasAttribute("xpcomabi")) { - choices = blocklistElement.getAttribute("xpcomabi").split(","); - if (choices.length > 0 && choices.indexOf(gApp.XPCOMABI) < 0) - 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. - */ -function getLocale() { - try { - // Get the default branch - var defaultPrefs = gPref.getDefaultBranch(null); - return defaultPrefs.getComplexValue(PREF_GENERAL_USERAGENT_LOCALE, - Ci.nsIPrefLocalizedString).data; - } catch (e) {} - - return gPref.getCharPref(PREF_GENERAL_USERAGENT_LOCALE); -} - -/* Get the distribution pref values, from defaults only */ -function getDistributionPrefValue(aPrefName) { - var prefValue = "default"; - - var defaults = gPref.getDefaultBranch(null); - try { - prefValue = defaults.getCharPref(aPrefName); - } catch (e) { - // use default when pref not found - } - - return prefValue; -} - -/** - * Parse a string representation of a regular expression. Needed because we - * use the /pattern/flags form (because it's detectable), which is only - * supported as a literal in JS. - * - * @param aStr - * String representation of regexp - * @return RegExp instance - */ -function parseRegExp(aStr) { - let lastSlash = aStr.lastIndexOf("/"); - let pattern = aStr.slice(1, lastSlash); - let flags = aStr.slice(lastSlash + 1); - return new RegExp(pattern, flags); -} - -/** - * Manages the Blocklist. The Blocklist is a representation of the contents of - * blocklist.xml and allows us to remotely disable / re-enable blocklisted - * items managed by the Extension Manager with an item's appDisabled property. - * It also blocklists plugins with data from blocklist.xml. - */ - -function Blocklist() { - Services.obs.addObserver(this, "xpcom-shutdown", false); - Services.obs.addObserver(this, "sessionstore-windows-restored", false); - gLoggingEnabled = getPref("getBoolPref", PREF_EM_LOGGING_ENABLED, false); - gBlocklistEnabled = getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true); - gBlocklistLevel = Math.min(getPref("getIntPref", PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL), - MAX_BLOCK_LEVEL); - gPref.addObserver("extensions.blocklist.", this, false); - gPref.addObserver(PREF_EM_LOGGING_ENABLED, this, false); - this.wrappedJSObject = this; - // requests from child processes come in here, see receiveMessage. - Services.ppmm.addMessageListener("Blocklist:getPluginBlocklistState", this); - Services.ppmm.addMessageListener("Blocklist:content-blocklist-updated", this); -} - -Blocklist.prototype = { - /** - * 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, - _gfxEntries: null, - _pluginEntries: null, - - shutdown: function() { - Services.obs.removeObserver(this, "xpcom-shutdown"); - Services.ppmm.removeMessageListener("Blocklist:getPluginBlocklistState", this); - Services.ppmm.removeMessageListener("Blocklist:content-blocklist-updated", this); - gPref.removeObserver("extensions.blocklist.", this); - gPref.removeObserver(PREF_EM_LOGGING_ENABLED, this); - }, - - observe: function(aSubject, aTopic, aData) { - switch (aTopic) { - case "xpcom-shutdown": - this.shutdown(); - break; - case "nsPref:changed": - switch (aData) { - case PREF_EM_LOGGING_ENABLED: - gLoggingEnabled = getPref("getBoolPref", PREF_EM_LOGGING_ENABLED, false); - break; - case PREF_BLOCKLIST_ENABLED: - gBlocklistEnabled = getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true); - this._loadBlocklist(); - this._blocklistUpdated(null, null); - break; - case PREF_BLOCKLIST_LEVEL: - gBlocklistLevel = Math.min(getPref("getIntPref", PREF_BLOCKLIST_LEVEL, DEFAULT_LEVEL), - MAX_BLOCK_LEVEL); - this._blocklistUpdated(null, null); - break; - } - break; - case "sessionstore-windows-restored": - Services.obs.removeObserver(this, "sessionstore-windows-restored"); - this._preloadBlocklist(); - break; - } - }, - - // Message manager message handlers - receiveMessage: function(aMsg) { - switch (aMsg.name) { - case "Blocklist:getPluginBlocklistState": - return this.getPluginBlocklistState(aMsg.data.addonData, - aMsg.data.appVersion, - aMsg.data.toolkitVersion); - case "Blocklist:content-blocklist-updated": - Services.obs.notifyObservers(null, "content-blocklist-updated", null); - break; - default: - throw new Error("Unknown blocklist message received from content: " + aMsg.name); - } - return undefined; - }, - - /* See nsIBlocklistService */ - isAddonBlocklisted: function(addon, appVersion, toolkitVersion) { - return this.getAddonBlocklistState(addon, appVersion, toolkitVersion) == - Ci.nsIBlocklistService.STATE_BLOCKED; - }, - - /* See nsIBlocklistService */ - getAddonBlocklistState: function(addon, appVersion, toolkitVersion) { - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - return this._getAddonBlocklistState(addon, this._addonEntries, - appVersion, toolkitVersion); - }, - - /** - * Private version of getAddonBlocklistState that allows the caller to pass in - * the add-on blocklist entries to compare against. - * - * @param id - * The ID of the item to get the blocklist state for. - * @param version - * The version of the item to get the blocklist state for. - * @param addonEntries - * The add-on blocklist entries to compare against. - * @param appVersion - * The application version to compare to, will use the current - * version if null. - * @param toolkitVersion - * The toolkit version to compare to, will use the current version if - * null. - * @returns The blocklist state for the item, one of the STATE constants as - * defined in nsIBlocklistService. - */ - _getAddonBlocklistState: function(addon, addonEntries, appVersion, toolkitVersion) { - if (!gBlocklistEnabled) - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - - // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). - if (!appVersion && !gApp.version) - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - - if (!appVersion) - appVersion = gApp.version; - if (!toolkitVersion) - toolkitVersion = gApp.platformVersion; - - var blItem = this._findMatchingAddonEntry(addonEntries, addon); - if (!blItem) - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - - for (let currentblItem of blItem.versions) { - if (currentblItem.includesItem(addon.version, appVersion, toolkitVersion)) - return currentblItem.severity >= gBlocklistLevel ? Ci.nsIBlocklistService.STATE_BLOCKED : - Ci.nsIBlocklistService.STATE_SOFTBLOCKED; - } - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - }, - - /** - * Returns the set of prefs of the add-on stored in the blocklist file - * (probably to revert them on disabling). - * @param addon - * The add-on whose to-be-reset prefs are to be found. - */ - _getAddonPrefs: function(addon) { - let entry = this._findMatchingAddonEntry(this._addonEntries, addon); - return entry.prefs.slice(0); - }, - - _findMatchingAddonEntry: function(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 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; - }, - - /* See nsIBlocklistService */ - getAddonBlocklistURL: function(addon, appVersion, toolkitVersion) { - if (!gBlocklistEnabled) - return ""; - - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - - let blItem = this._findMatchingAddonEntry(this._addonEntries, addon); - if (!blItem || !blItem.blockID) - return null; - - return this._createBlocklistURL(blItem.blockID); - }, - - _createBlocklistURL: function(id) { - let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL); - url = url.replace(/%blockID%/g, id); - - return url; - }, - - notify: function(aTimer) { - if (!gBlocklistEnabled) - return; - - try { - var dsURI = gPref.getCharPref(PREF_BLOCKLIST_URL); - } - catch (e) { - LOG("Blocklist::notify: The " + PREF_BLOCKLIST_URL + " preference" + - " is missing!"); - return; - } - - var pingCountVersion = getPref("getIntPref", PREF_BLOCKLIST_PINGCOUNTVERSION, 0); - var pingCountTotal = getPref("getIntPref", PREF_BLOCKLIST_PINGCOUNTTOTAL, 1); - var daysSinceLastPing = 0; - if (pingCountVersion == 0) { - daysSinceLastPing = "new"; - } - else { - // Seconds in one day is used because nsIUpdateTimerManager stores the - // last update time in seconds. - let secondsInDay = 60 * 60 * 24; - let lastUpdateTime = getPref("getIntPref", PREF_BLOCKLIST_LASTUPDATETIME, 0); - if (lastUpdateTime == 0) { - daysSinceLastPing = "invalid"; - } - else { - let now = Math.round(Date.now() / 1000); - daysSinceLastPing = Math.floor((now - lastUpdateTime) / secondsInDay); - } - - if (daysSinceLastPing == 0 || daysSinceLastPing == "invalid") { - pingCountVersion = pingCountTotal = "invalid"; - } - } - - if (pingCountVersion < 1) - pingCountVersion = 1; - if (pingCountTotal < 1) - pingCountTotal = 1; - - dsURI = dsURI.replace(/%APP_ID%/g, gApp.ID); - // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). - if (gApp.version) - dsURI = dsURI.replace(/%APP_VERSION%/g, gApp.version); - dsURI = dsURI.replace(/%PRODUCT%/g, gApp.name); - // Not all applications implement nsIXULAppInfo (e.g. xpcshell doesn't). - if (gApp.version) - dsURI = dsURI.replace(/%VERSION%/g, gApp.version); - dsURI = dsURI.replace(/%BUILD_ID%/g, gApp.appBuildID); - dsURI = dsURI.replace(/%BUILD_TARGET%/g, gApp.OS + "_" + gABI); - dsURI = dsURI.replace(/%OS_VERSION%/g, gOSVersion); - dsURI = dsURI.replace(/%LOCALE%/g, getLocale()); - dsURI = dsURI.replace(/%CHANNEL%/g, UpdateUtils.UpdateChannel); - dsURI = dsURI.replace(/%PLATFORM_VERSION%/g, gApp.platformVersion); - dsURI = dsURI.replace(/%DISTRIBUTION%/g, - getDistributionPrefValue(PREF_APP_DISTRIBUTION)); - dsURI = dsURI.replace(/%DISTRIBUTION_VERSION%/g, - getDistributionPrefValue(PREF_APP_DISTRIBUTION_VERSION)); - dsURI = dsURI.replace(/%PING_COUNT%/g, pingCountVersion); - dsURI = dsURI.replace(/%TOTAL_PING_COUNT%/g, pingCountTotal); - dsURI = dsURI.replace(/%DAYS_SINCE_LAST_PING%/g, daysSinceLastPing); - dsURI = dsURI.replace(/\+/g, "%2B"); - - // Under normal operations it will take around 5,883,516 years before the - // preferences used to store pingCountVersion and pingCountTotal will rollover - // so this code doesn't bother trying to do the "right thing" here. - if (pingCountVersion != "invalid") { - pingCountVersion++; - if (pingCountVersion > 2147483647) { - // Rollover to -1 if the value is greater than what is support by an - // integer preference. The -1 indicates that the counter has been reset. - pingCountVersion = -1; - } - gPref.setIntPref(PREF_BLOCKLIST_PINGCOUNTVERSION, pingCountVersion); - } - - if (pingCountTotal != "invalid") { - pingCountTotal++; - if (pingCountTotal > 2147483647) { - // Rollover to 1 if the value is greater than what is support by an - // integer preference. - pingCountTotal = -1; - } - gPref.setIntPref(PREF_BLOCKLIST_PINGCOUNTTOTAL, pingCountTotal); - } - - // Verify that the URI is valid - try { - var uri = newURI(dsURI); - } - catch (e) { - LOG("Blocklist::notify: There was an error creating the blocklist URI\r\n" + - "for: " + dsURI + ", error: " + e); - return; - } - - LOG("Blocklist::notify: Requesting " + uri.spec); - let request = new ServiceRequest(); - request.open("GET", uri.spec, true); - request.channel.notificationCallbacks = new gCertUtils.BadCertHandler(); - request.overrideMimeType("text/xml"); - request.setRequestHeader("Cache-Control", "no-cache"); - request.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest); - - request.addEventListener("error", event => this.onXMLError(event), false); - request.addEventListener("load", event => this.onXMLLoad(event), false); - request.send(null); - - // When the blocklist loads we need to compare it to the current copy so - // make sure we have loaded it. - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - }, - - onXMLLoad: Task.async(function*(aEvent) { - let request = aEvent.target; - try { - gCertUtils.checkCert(request.channel); - } - catch (e) { - LOG("Blocklist::onXMLLoad: " + e); - return; - } - let responseXML = request.responseXML; - if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR || - (request.status != 200 && request.status != 0)) { - LOG("Blocklist::onXMLLoad: there was an error during load"); - return; - } - - var oldAddonEntries = this._addonEntries; - var oldPluginEntries = this._pluginEntries; - this._addonEntries = []; - this._gfxEntries = []; - this._pluginEntries = []; - - this._loadBlocklistFromString(request.responseText); - // 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); - yield OS.File.writeAtomic(path, request.responseText, {tmpPath: path + ".tmp"}); - } catch (e) { - LOG("Blocklist::onXMLLoad: " + e); - } - }), - - onXMLError: function(aEvent) { - try { - var request = aEvent.target; - // the following may throw (e.g. a local file or timeout) - var status = request.status; - } - catch (e) { - request = aEvent.target.channel.QueryInterface(Ci.nsIRequest); - status = request.status; - } - var statusText = "nsIXMLHttpRequest channel unavailable"; - // When status is 0 we don't have a valid channel. - if (status != 0) { - try { - statusText = request.statusText; - } catch (e) { - } - } - LOG("Blocklist:onError: There was an error loading the blocklist file\r\n" + - statusText); - }, - - /** - * Finds the newest blocklist file from the application and the profile and - * load it or does nothing if neither exist. - */ - _loadBlocklist: function() { - this._addonEntries = []; - this._gfxEntries = []; - this._pluginEntries = []; - var profFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]); - if (profFile.exists()) { - this._loadBlocklistFromFile(profFile); - return; - } - var appFile = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]); - if (appFile.exists()) { - this._loadBlocklistFromFile(appFile); - return; - } - LOG("Blocklist::_loadBlocklist: no XML File found"); - }, - - /** -# The blocklist XML file looks something like this: -# -# -# -# -# -# accessibility.accesskeycausesactivation -# accessibility.blockautorefresh -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# -# AkHVNA== -# -# -# -# -# -# - */ - - _loadBlocklistFromFile: function(file) { - if (!gBlocklistEnabled) { - LOG("Blocklist::_loadBlocklistFromFile: blocklist is disabled"); - return; - } - - let telemetry = Services.telemetry; - - if (this._isBlocklistPreloaded()) { - telemetry.getHistogramById("BLOCKLIST_SYNC_FILE_LOAD").add(false); - this._loadBlocklistFromString(this._preloadedBlocklistContent); - delete this._preloadedBlocklistContent; - return; - } - - if (!file.exists()) { - LOG("Blocklist::_loadBlocklistFromFile: XML File does not exist " + file.path); - return; - } - - telemetry.getHistogramById("BLOCKLIST_SYNC_FILE_LOAD").add(true); - - let text = ""; - let fstream = null; - let cstream = null; - - try { - fstream = Components.classes["@mozilla.org/network/file-input-stream;1"] - .createInstance(Components.interfaces.nsIFileInputStream); - cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"] - .createInstance(Components.interfaces.nsIConverterInputStream); - - fstream.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0); - cstream.init(fstream, "UTF-8", 0, 0); - - let str = {}; - let read = 0; - - do { - read = cstream.readString(0xffffffff, str); // read as much as we can and put it in str.value - text += str.value; - } while (read != 0); - } catch (e) { - LOG("Blocklist::_loadBlocklistFromFile: Failed to load XML file " + e); - } finally { - if (cstream) - cstream.close(); - if (fstream) - fstream.close(); - } - - if (text) - this._loadBlocklistFromString(text); - }, - - _isBlocklistLoaded: function() { - return this._addonEntries != null && this._gfxEntries != null && this._pluginEntries != null; - }, - - _isBlocklistPreloaded: function() { - return this._preloadedBlocklistContent != null; - }, - - /* Used for testing */ - _clear: function() { - this._addonEntries = null; - this._gfxEntries = null; - this._pluginEntries = null; - this._preloadedBlocklistContent = null; - }, - - _preloadBlocklist: Task.async(function*() { - let profPath = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST); - try { - yield this._preloadBlocklistFile(profPath); - return; - } catch (e) { - LOG("Blocklist::_preloadBlocklist: Failed to load XML file " + e) - } - - var appFile = FileUtils.getFile(KEY_APPDIR, [FILE_BLOCKLIST]); - try { - yield this._preloadBlocklistFile(appFile.path); - return; - } catch (e) { - LOG("Blocklist::_preloadBlocklist: Failed to load XML file " + e) - } - - LOG("Blocklist::_preloadBlocklist: no XML File found"); - }), - - _preloadBlocklistFile: Task.async(function*(path) { - if (this._addonEntries) { - // The file has been already loaded. - return; - } - - if (!gBlocklistEnabled) { - LOG("Blocklist::_preloadBlocklistFile: blocklist is disabled"); - return; - } - - let text = yield OS.File.read(path, { encoding: "utf-8" }); - - if (!this._addonEntries) { - // Store the content only if a sync load has not been performed in the meantime. - this._preloadedBlocklistContent = text; - } - }), - - _loadBlocklistFromString : function(text) { - try { - var parser = Cc["@mozilla.org/xmlextras/domparser;1"]. - createInstance(Ci.nsIDOMParser); - var doc = parser.parseFromString(text, "text/xml"); - if (doc.documentElement.namespaceURI != XMLURI_BLOCKLIST) { - LOG("Blocklist::_loadBlocklistFromFile: aborting due to incorrect " + - "XML Namespace.\r\nExpected: " + XMLURI_BLOCKLIST + "\r\n" + - "Received: " + doc.documentElement.namespaceURI); - return; - } - - var populateCertBlocklist = getPref("getBoolPref", PREF_ONECRL_VIA_AMO, true); - - var childNodes = doc.documentElement.childNodes; - for (let element of childNodes) { - if (!(element instanceof Ci.nsIDOMElement)) - continue; - switch (element.localName) { - case "emItems": - this._addonEntries = this._processItemNodes(element.childNodes, "emItem", - this._handleEmItemNode); - break; - case "pluginItems": - this._pluginEntries = this._processItemNodes(element.childNodes, "pluginItem", - this._handlePluginItemNode); - break; - case "certItems": - if (populateCertBlocklist) { - this._processItemNodes(element.childNodes, "certItem", - this._handleCertItemNode.bind(this)); - } - break; - case "gfxItems": - // Parse as simple list of objects. - this._gfxEntries = this._processItemNodes(element.childNodes, "gfxBlacklistEntry", - this._handleGfxBlacklistNode); - break; - default: - LOG("Blocklist::_loadBlocklistFromString: ignored entries " + element.localName); - } - } - if (populateCertBlocklist) { - gCertBlocklistService.saveEntries(); - } - if (this._gfxEntries.length > 0) { - this._notifyObserversBlocklistGFX(); - } - } - catch (e) { - LOG("Blocklist::_loadBlocklistFromFile: Error constructing blocklist " + e); - return; - } - }, - - _processItemNodes: function(itemNodes, itemName, handler) { - var result = []; - for (var i = 0; i < itemNodes.length; ++i) { - var blocklistElement = itemNodes.item(i); - if (!(blocklistElement instanceof Ci.nsIDOMElement) || - blocklistElement.localName != itemName) - continue; - - handler(blocklistElement, result); - } - return result; - }, - - _handleCertItemNode: function(blocklistElement, result) { - let issuer = blocklistElement.getAttribute("issuerName"); - if (issuer) { - for (let snElement of blocklistElement.children) { - try { - gCertBlocklistService.revokeCertByIssuerAndSerial(issuer, snElement.textContent); - } catch (e) { - // we want to keep trying other elements since missing all items - // is worse than missing one - LOG("Blocklist::_handleCertItemNode: Error adding revoked cert by Issuer and Serial" + e); - } - } - return; - } - - let pubKeyHash = blocklistElement.getAttribute("pubKeyHash"); - let subject = blocklistElement.getAttribute("subject"); - - if (pubKeyHash && subject) { - try { - gCertBlocklistService.revokeCertBySubjectAndPubKey(subject, pubKeyHash); - } catch (e) { - LOG("Blocklist::_handleCertItemNode: Error adding revoked cert by Subject and PubKey" + e); - } - } - }, - - _handleEmItemNode: function(blocklistElement, result) { - if (!matchesOSABI(blocklistElement)) - return; - - let blockEntry = { - versions: [], - prefs: [], - blockID: null, - attributes: new Map() - // Atleast one of EXTENSION_BLOCK_FILTERS must get added to attributes - }; - - // Any filter starting with '/' is interpreted as a regex. So if an attribute - // starts with a '/' it must be checked via a regex. - function regExpCheck(attr) { - return attr.startsWith("/") ? parseRegExp(attr) : attr; - } - - for (let filter of EXTENSION_BLOCK_FILTERS) { - let attr = blocklistElement.getAttribute(filter); - if (attr) - blockEntry.attributes.set(filter, regExpCheck(attr)); - } - - var childNodes = blocklistElement.childNodes; - - for (let x = 0; x < childNodes.length; x++) { - var childElement = childNodes.item(x); - if (!(childElement instanceof Ci.nsIDOMElement)) - continue; - if (childElement.localName === "prefs") { - let prefElements = childElement.childNodes; - for (let i = 0; i < prefElements.length; i++) { - let prefElement = prefElements.item(i); - if (!(prefElement instanceof Ci.nsIDOMElement) || - prefElement.localName !== "pref") - continue; - blockEntry.prefs.push(prefElement.textContent); - } - } - else if (childElement.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: function(blocklistElement, result) { - if (!matchesOSABI(blocklistElement)) - return; - - var matchNodes = blocklistElement.childNodes; - var blockEntry = { - matches: {}, - versions: [], - blockID: null, - infoURL: null, - }; - var hasMatch = false; - for (var x = 0; x < matchNodes.length; ++x) { - var matchElement = matchNodes.item(x); - if (!(matchElement instanceof Ci.nsIDOMElement)) - continue; - if (matchElement.localName == "match") { - var name = matchElement.getAttribute("name"); - var exp = matchElement.getAttribute("exp"); - try { - blockEntry.matches[name] = new RegExp(exp, "m"); - hasMatch = true; - } catch (e) { - // Ignore invalid regular expressions - } - } - if (matchElement.localName == "versionRange") { - blockEntry.versions.push(new BlocklistItemData(matchElement)); - } - else if (matchElement.localName == "infoURL") { - blockEntry.infoURL = matchElement.textContent; - } - } - // 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); - }, - - // - // WINNT 6.0 - // 14 currently only used for Android - // - // 0x8086 - // - // 0x2582 - // 0x2782 - // - // DIRECT3D_10_LAYERS - // BLOCKED_DRIVER_VERSION - // 8.52.322.2202 - // 8.52.322.2202 - // LESS_THAN_OR_EQUAL - // foo - // foo - // foo - // foo - // - _handleGfxBlacklistNode: function (blocklistElement, result) { - const blockEntry = {}; - - // The blockID attribute is always present in the actual data produced on server - // (see https://github.com/mozilla/addons-server/blob/2016.05.05/src/olympia/blocklist/templates/blocklist/blocklist.xml#L74) - // But it is sometimes missing in test fixtures. - if (blocklistElement.hasAttribute("blockID")) { - blockEntry.blockID = blocklistElement.getAttribute("blockID"); - } - - // Trim helper (spaces, tabs, no-break spaces..) - const trim = (s) => (s || '').replace(/(^[\s\uFEFF\xA0]+)|([\s\uFEFF\xA0]+$)/g, ""); - - for (let i = 0; i < blocklistElement.childNodes.length; ++i) { - var matchElement = blocklistElement.childNodes.item(i); - if (!(matchElement instanceof Ci.nsIDOMElement)) - continue; - - let value; - if (matchElement.localName == "devices") { - value = []; - for (let j = 0; j < matchElement.childNodes.length; j++) { - const childElement = matchElement.childNodes.item(j); - const childValue = trim(childElement.textContent); - // Make sure no empty value is added. - if (childValue) { - if (/,/.test(childValue)) { - // Devices can't contain comma. - // (c.f serialization in _notifyObserversBlocklistGFX) - const e = new Error(`Unsupported device name ${childValue}`); - Components.utils.reportError(e); - } - else { - value.push(childValue); - } - } - } - } else if (matchElement.localName == "versionRange") { - value = {minVersion: trim(matchElement.getAttribute("minVersion")) || "0", - maxVersion: trim(matchElement.getAttribute("maxVersion")) || "*"}; - } else { - value = trim(matchElement.textContent); - } - if (value) { - blockEntry[matchElement.localName] = value; - } - } - result.push(blockEntry); - }, - - /* See nsIBlocklistService */ - getPluginBlocklistState: function(plugin, appVersion, toolkitVersion) { - if (AppConstants.platform == "android") { - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - } - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - return this._getPluginBlocklistState(plugin, this._pluginEntries, - appVersion, toolkitVersion); - }, - - /** - * Private helper to get the blocklist entry for a plugin given a set of - * blocklist entries and versions. - * - * @param plugin - * The nsIPluginTag to get the blocklist state for. - * @param pluginEntries - * The plugin blocklist entries to compare against. - * @param appVersion - * The application version to compare to, will use the current - * version if null. - * @param toolkitVersion - * The toolkit version to compare to, will use the current version if - * null. - * @returns {entry: blocklistEntry, version: blocklistEntryVersion}, - * or null if there is no matching entry. - */ - _getPluginBlocklistEntry: function(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; - - for (var blockEntry of pluginEntries) { - var matchFailed = false; - for (var name in blockEntry.matches) { - if (!(name in plugin) || - typeof(plugin[name]) != "string" || - !blockEntry.matches[name].test(plugin[name])) { - matchFailed = true; - break; - } - } - - if (matchFailed) - continue; - - for (let blockEntryVersion of blockEntry.versions) { - if (blockEntryVersion.includesItem(plugin.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 plugin - * The nsIPluginTag to get the blocklist state for. - * @param pluginEntries - * The plugin blocklist entries to compare against. - * @param appVersion - * The application version to compare to, will use the current - * version if null. - * @param toolkitVersion - * The toolkit version to compare to, will use the current version if - * null. - * @returns The blocklist state for the item, one of the STATE constants as - * defined in nsIBlocklistService. - */ - _getPluginBlocklistState: function(plugin, pluginEntries, appVersion, toolkitVersion) { - - let r = this._getPluginBlocklistEntry(plugin, pluginEntries, - appVersion, toolkitVersion); - if (!r) { - return Ci.nsIBlocklistService.STATE_NOT_BLOCKED; - } - - let {entry: blockEntry, 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; - }, - - /* See nsIBlocklistService */ - getPluginBlocklistURL: function(plugin) { - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - - let r = this._getPluginBlocklistEntry(plugin, this._pluginEntries); - if (!r) { - return null; - } - let {entry: blockEntry, version: blockEntryVersion} = r; - if (!blockEntry.blockID) { - return null; - } - - return this._createBlocklistURL(blockEntry.blockID); - }, - - /* See nsIBlocklistService */ - getPluginInfoURL: function(plugin) { - if (!this._isBlocklistLoaded()) - this._loadBlocklist(); - - let r = this._getPluginBlocklistEntry(plugin, this._pluginEntries); - if (!r) { - return null; - } - let {entry: blockEntry, version: blockEntryVersion} = r; - if (!blockEntry.blockID) { - return null; - } - - return blockEntry.infoURL; - }, - - _notifyObserversBlocklistGFX: function () { - // Notify `GfxInfoBase`, by passing a string serialization. - // This way we avoid spreading XML structure logics there. - const payload = this._gfxEntries.map((r) => { - return Object.keys(r).sort().filter((k) => !/id|last_modified/.test(k)).map((key) => { - let value = r[key]; - if (Array.isArray(value)) { - value = value.join(","); - } else if (value.hasOwnProperty("minVersion")) { - // When XML is parsed, both minVersion and maxVersion are set. - value = `${value.minVersion},${value.maxVersion}`; - } - return `${key}:${value}`; - }).join("\t"); - }).join("\n"); - Services.obs.notifyObservers(null, "blocklist-data-gfxItems", payload); - }, - - _notifyObserversBlocklistUpdated: function() { - Services.obs.notifyObservers(this, "blocklist-updated", ""); - Services.ppmm.broadcastAsyncMessage("Blocklist:blocklistInvalidated", {}); - }, - - _blocklistUpdated: function(oldAddonEntries, oldPluginEntries) { - var addonList = []; - - // A helper function that reverts the prefs passed to default values. - function resetPrefs(prefs) { - for (let pref of prefs) - gPref.clearUserPref(pref); - } - const types = ["extension", "theme", "locale", "dictionary", "service"]; - AddonManager.getAddonsByTypes(types, addons => { - for (let addon of addons) { - let oldState = Ci.nsIBlocklistService.STATE_NOTBLOCKED; - if (oldAddonEntries) - oldState = this._getAddonBlocklistState(addon, oldAddonEntries); - let state = this.getAddonBlocklistState(addon); - - 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; - } - - addonList.push({ - name: addon.name, - version: addon.version, - icon: addon.iconURL, - disable: false, - blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED, - item: addon, - url: this.getAddonBlocklistURL(addon), - }); - } - - AddonManagerPrivate.updateAddonAppDisabledStates(); - - var phs = Cc["@mozilla.org/plugin/host;1"]. - getService(Ci.nsIPluginHost); - var plugins = phs.getPluginTags(); - - for (let plugin of plugins) { - let oldState = -1; - if (oldPluginEntries) - oldState = this._getPluginBlocklistState(plugin, oldPluginEntries); - let state = this.getPluginBlocklistState(plugin); - 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.png", - disable: false, - blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED, - item: plugin, - url: this.getPluginBlocklistURL(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(Ci.nsIBlocklistPrompt); - 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", false); - - if (getPref("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, false); - }); - }, - - classID: Components.ID("{66354bc9-7ed1-4692-ae1d-8da97d6b205e}"), - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, - Ci.nsIBlocklistService, - Ci.nsITimerCallback]), -}; - -/** - * Helper for constructing a blocklist. - */ -function BlocklistItemData(versionRangeElement) { - var versionRange = this.getBlocklistVersionRange(versionRangeElement); - this.minVersion = versionRange.minVersion; - this.maxVersion = versionRange.maxVersion; - if (versionRangeElement && versionRangeElement.hasAttribute("severity")) - this.severity = versionRangeElement.getAttribute("severity"); - else - this.severity = DEFAULT_SEVERITY; - if (versionRangeElement && versionRangeElement.hasAttribute("vulnerabilitystatus")) { - this.vulnerabilityStatus = versionRangeElement.getAttribute("vulnerabilitystatus"); - } else { - this.vulnerabilityStatus = VULNERABILITYSTATUS_NONE; - } - this.targetApps = { }; - var found = false; - - if (versionRangeElement) { - for (var i = 0; i < versionRangeElement.childNodes.length; ++i) { - var targetAppElement = versionRangeElement.childNodes.item(i); - if (!(targetAppElement instanceof Ci.nsIDOMElement) || - targetAppElement.localName != "targetApplication") - continue; - found = true; - // default to the current application if id is not provided. - var appID = targetAppElement.hasAttribute("id") ? targetAppElement.getAttribute("id") : gApp.ID; - this.targetApps[appID] = this.getBlocklistAppVersions(targetAppElement); - } - } - // Default to all versions of the current application when no targetApplication - // elements were found - if (!found) - this.targetApps[gApp.ID] = this.getBlocklistAppVersions(null); -} - -BlocklistItemData.prototype = { - /** - * Tests if a version of an item is included in the version range and target - * application information represented by this BlocklistItemData using the - * provided application and toolkit versions. - * @param version - * The version of the item being tested. - * @param appVersion - * The application version to test with. - * @param toolkitVersion - * The toolkit version to test with. - * @returns True if the version range covers the item version and application - * or toolkit version. - */ - includesItem: function(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(gApp.ID, 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 version - * The version to test. - * @param minVersion - * The minimum version. If null it is assumed that version is always - * larger. - * @param maxVersion - * The maximum version. If null it is assumed that version is always - * smaller. - */ - matchesRange: function(version, minVersion, maxVersion) { - if (minVersion && gVersionChecker.compare(version, minVersion) < 0) - return false; - if (maxVersion && gVersionChecker.compare(version, maxVersion) > 0) - return false; - return true; - }, - - /** - * Tests if there is a matching range for the given target application id and - * version. - * @param appID - * The application ID to test for, may be for an application or toolkit - * @param appVersion - * The version of the application to test for. - * @returns True if this version range covers the application version given. - */ - matchesTargetRange: function(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 targetAppElement - * A targetApplication blocklist element. - * @returns 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: function(targetAppElement) { - var appVersions = [ ]; - - if (targetAppElement) { - for (var i = 0; i < targetAppElement.childNodes.length; ++i) { - var versionRangeElement = targetAppElement.childNodes.item(i); - if (!(versionRangeElement instanceof Ci.nsIDOMElement) || - versionRangeElement.localName != "versionRange") - continue; - appVersions.push(this.getBlocklistVersionRange(versionRangeElement)); - } - } - // return minVersion = null and maxVersion = null if no specific versionRange - // elements were found - if (appVersions.length == 0) - appVersions.push(this.getBlocklistVersionRange(null)); - return appVersions; - }, - - /** - * Retrieves a version range (e.g. minVersion and maxVersion) for a blocklist - * versionRange element. - * @param versionRangeElement - * The versionRange blocklist element. - * @returns A JS object with the following properties: - * "minVersion" The minimum version in a version range (default = null). - * "maxVersion" The maximum version in a version range (default = null). - */ - getBlocklistVersionRange: function(versionRangeElement) { - var minVersion = null; - var maxVersion = null; - if (!versionRangeElement) - return { minVersion: minVersion, maxVersion: maxVersion }; - - if (versionRangeElement.hasAttribute("minVersion")) - minVersion = versionRangeElement.getAttribute("minVersion"); - if (versionRangeElement.hasAttribute("maxVersion")) - maxVersion = versionRangeElement.getAttribute("maxVersion"); - - return { minVersion: minVersion, maxVersion: maxVersion }; - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Blocklist]); diff --git a/toolkit/mozapps/webextensions/nsBlocklistServiceContent.js b/toolkit/mozapps/webextensions/nsBlocklistServiceContent.js deleted file mode 100644 index 1752924b5..000000000 --- a/toolkit/mozapps/webextensions/nsBlocklistServiceContent.js +++ /dev/null @@ -1,113 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cr = Components.results; - -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); -Components.utils.import("resource://gre/modules/Services.jsm"); - -const kMissingAPIMessage = "Unsupported blocklist call in the child process." - -/* - * A lightweight blocklist proxy for the content process that traps plugin - * related blocklist checks and forwards them to the parent. This interface is - * primarily designed to insure overlays work.. it does not control plugin - * or addon loading. - */ - -function Blocklist() { - this.init(); -} - -Blocklist.prototype = { - classID: Components.ID("{e0a106ed-6ad4-47a4-b6af-2f1c8aa4712d}"), - - QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, - Ci.nsIBlocklistService]), - - init: function() { - Services.cpmm.addMessageListener("Blocklist:blocklistInvalidated", this); - Services.obs.addObserver(this, "xpcom-shutdown", false); - }, - - uninit: function() { - Services.cpmm.removeMessageListener("Blocklist:blocklistInvalidated", this); - Services.obs.removeObserver(this, "xpcom-shutdown", false); - }, - - observe: function(aSubject, aTopic, aData) { - switch (aTopic) { - case "xpcom-shutdown": - this.uninit(); - break; - } - }, - - // Message manager message handlers - receiveMessage: function(aMsg) { - switch (aMsg.name) { - case "Blocklist:blocklistInvalidated": - Services.obs.notifyObservers(null, "blocklist-updated", null); - Services.cpmm.sendAsyncMessage("Blocklist:content-blocklist-updated"); - break; - default: - throw new Error("Unknown blocklist message received from content: " + aMsg.name); - } - }, - - /* - * A helper that queries key data from a plugin or addon object - * and generates a simple data wrapper suitable for ipc. We hand - * these directly to the nsBlockListService in the parent which - * doesn't query for much.. allowing us to get away with this. - */ - flattenObject: function(aTag) { - // Based on debugging the nsBlocklistService, these are the props the - // parent side will check on our objects. - let props = ["name", "description", "filename", "version"]; - let dataWrapper = {}; - for (let prop of props) { - dataWrapper[prop] = aTag[prop]; - } - return dataWrapper; - }, - - // We support the addon methods here for completeness, but content currently - // only calls getPluginBlocklistState. - - isAddonBlocklisted: function(aAddon, aAppVersion, aToolkitVersion) { - return true; - }, - - getAddonBlocklistState: function(aAddon, aAppVersion, aToolkitVersion) { - return Components.interfaces.nsIBlocklistService.STATE_BLOCKED; - }, - - // There are a few callers in layout that rely on this. - getPluginBlocklistState: function(aPluginTag, aAppVersion, aToolkitVersion) { - return Services.cpmm.sendSyncMessage("Blocklist:getPluginBlocklistState", { - addonData: this.flattenObject(aPluginTag), - appVersion: aAppVersion, - toolkitVersion: aToolkitVersion - })[0]; - }, - - getAddonBlocklistURL: function(aAddon, aAppVersion, aToolkitVersion) { - throw new Error(kMissingAPIMessage); - }, - - getPluginBlocklistURL: function(aPluginTag) { - throw new Error(kMissingAPIMessage); - }, - - getPluginInfoURL: function(aPluginTag) { - throw new Error(kMissingAPIMessage); - } -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Blocklist]); -- cgit v1.2.3 From fcd7ee3c886c435f178230b13d0b0cb0c9c40c53 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Wed, 23 May 2018 16:31:42 +0200 Subject: Remove the Dark Matter Detector (DMD) Memeory debugger component. This resolves #376. --- toolkit/mozapps/installer/upload-files.mk | 4 ---- 1 file changed, 4 deletions(-) (limited to 'toolkit/mozapps') diff --git a/toolkit/mozapps/installer/upload-files.mk b/toolkit/mozapps/installer/upload-files.mk index 9abfd855a..25103ff37 100644 --- a/toolkit/mozapps/installer/upload-files.mk +++ b/toolkit/mozapps/installer/upload-files.mk @@ -349,10 +349,6 @@ ifndef MOZ_PKG_MANIFEST NO_PKG_FILES += ssltunnel* endif -ifdef MOZ_DMD - NO_PKG_FILES += SmokeDMD -endif - DEFINES += -DDLL_PREFIX=$(DLL_PREFIX) -DDLL_SUFFIX=$(DLL_SUFFIX) -DBIN_SUFFIX=$(BIN_SUFFIX) ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) -- cgit v1.2.3 From 351cf27036d335e207b2a697423638dd4732cd08 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Mon, 28 May 2018 10:05:20 -0400 Subject: [WebExAM] Issue #402 - Make JSON update manifests assume Firefox instead of Toolkit --- .../webextensions/internal/AddonUpdateChecker.jsm | 17 +++++++++++++---- toolkit/mozapps/webextensions/internal/moz.build | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'toolkit/mozapps') diff --git a/toolkit/mozapps/webextensions/internal/AddonUpdateChecker.jsm b/toolkit/mozapps/webextensions/internal/AddonUpdateChecker.jsm index bdd3a81e7..338b8c8bf 100644 --- a/toolkit/mozapps/webextensions/internal/AddonUpdateChecker.jsm +++ b/toolkit/mozapps/webextensions/internal/AddonUpdateChecker.jsm @@ -26,6 +26,12 @@ const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror. const PREF_UPDATE_REQUIREBUILTINCERTS = "extensions.update.requireBuiltInCerts"; +#ifdef MOZ_PHOENIX +const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion"; +const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" +const FIREFOX_APPCOMPATVERSION = "56.9" +#endif + Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); @@ -446,6 +452,10 @@ function parseRDFManifest(aId, aUpdateKey, aRequest, aManifestData) { * @throws if the update manifest is invalid in any way */ function parseJSONManifest(aId, aUpdateKey, aRequest, aManifestData) { +#ifndef MOZ_PHOENIX + throw Components.Exception("This application does not support JSON update manifests"); +#endif + if (aUpdateKey) throw Components.Exception("Update keys are not supported for JSON update manifests"); @@ -515,10 +525,10 @@ function parseJSONManifest(aId, aUpdateKey, aRequest, aManifestData) { let app = getProperty(applications, "gecko", "object"); let appEntry = { - id: TOOLKIT_ID, + id: FIREFOX_ID, minVersion: getProperty(app, "strict_min_version", "string", - AddonManagerPrivate.webExtensionsMinPlatformVersion), - maxVersion: "*", + Services.prefs.getCharPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION)), + maxVersion: FIREFOX_APPCOMPATVERSION, }; let result = { @@ -539,7 +549,6 @@ function parseJSONManifest(aId, aUpdateKey, aRequest, aManifestData) { } appEntry.maxVersion = getProperty(app, "strict_max_version", "string"); - result.strictCompatibility = appEntry.maxVersion != "*"; } else if ("advisory_max_version" in app) { appEntry.maxVersion = getProperty(app, "advisory_max_version", "string"); } diff --git a/toolkit/mozapps/webextensions/internal/moz.build b/toolkit/mozapps/webextensions/internal/moz.build index 28c34f8c9..5a3943e59 100644 --- a/toolkit/mozapps/webextensions/internal/moz.build +++ b/toolkit/mozapps/webextensions/internal/moz.build @@ -8,7 +8,6 @@ EXTRA_JS_MODULES.addons += [ 'AddonLogging.jsm', 'AddonRepository.jsm', 'AddonRepository_SQLiteMigrator.jsm', - 'AddonUpdateChecker.jsm', 'APIExtensionBootstrap.js', 'Content.js', 'E10SAddonsRollout.jsm', @@ -33,4 +32,5 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android': EXTRA_PP_JS_MODULES.addons += [ 'AddonConstants.jsm', + 'AddonUpdateChecker.jsm', ] -- cgit v1.2.3 From 2a36ae70f511d3eaf8594477934f640c6ff50c96 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Mon, 28 May 2018 11:46:54 -0400 Subject: [WebExAM] Follow up to 351cf2703 --- toolkit/mozapps/webextensions/internal/AddonUpdateChecker.jsm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'toolkit/mozapps') diff --git a/toolkit/mozapps/webextensions/internal/AddonUpdateChecker.jsm b/toolkit/mozapps/webextensions/internal/AddonUpdateChecker.jsm index 338b8c8bf..78b52d21a 100644 --- a/toolkit/mozapps/webextensions/internal/AddonUpdateChecker.jsm +++ b/toolkit/mozapps/webextensions/internal/AddonUpdateChecker.jsm @@ -452,10 +452,7 @@ function parseRDFManifest(aId, aUpdateKey, aRequest, aManifestData) { * @throws if the update manifest is invalid in any way */ function parseJSONManifest(aId, aUpdateKey, aRequest, aManifestData) { -#ifndef MOZ_PHOENIX - throw Components.Exception("This application does not support JSON update manifests"); -#endif - +#ifdef MOZ_PHOENIX if (aUpdateKey) throw Components.Exception("Update keys are not supported for JSON update manifests"); @@ -560,6 +557,9 @@ function parseJSONManifest(aId, aUpdateKey, aRequest, aManifestData) { results.push(result); } return results; +#else + throw Components.Exception("This application does not support JSON update manifests"); +#endif } /** -- cgit v1.2.3 From 258eb6ee9ccefc8a6353a73c6389b042054a36fe Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Mon, 28 May 2018 13:27:14 -0400 Subject: [WebExAM] Deduplicate toolkit/mozapps/webextensions --- .../extensions/internal/ProductAddonChecker.jsm | 467 +++++++++++++++++++++ toolkit/mozapps/extensions/internal/moz.build | 2 +- toolkit/mozapps/webextensions/amIAddonManager.idl | 29 -- .../mozapps/webextensions/amIAddonPathService.idl | 37 -- .../webextensions/amIWebInstallListener.idl | 134 ------ toolkit/mozapps/webextensions/amIWebInstaller.idl | 82 ---- .../webextensions/content/OpenH264-license.txt | 59 --- toolkit/mozapps/webextensions/content/about.xul | 57 --- .../mozapps/webextensions/content/blocklist.css | 11 - .../mozapps/webextensions/content/blocklist.xml | 58 --- .../mozapps/webextensions/content/blocklist.xul | 46 -- toolkit/mozapps/webextensions/content/eula.xul | 35 -- toolkit/mozapps/webextensions/content/gmpPrefs.xul | 8 - toolkit/mozapps/webextensions/content/list.xul | 44 -- .../mozapps/webextensions/content/pluginPrefs.xul | 20 - .../mozapps/webextensions/content/updateinfo.xsl | 41 -- .../webextensions/content/xpinstallConfirm.css | 8 - .../webextensions/content/xpinstallConfirm.xul | 37 -- .../webextensions/content/xpinstallItem.xml | 51 --- .../webextensions/internal/ProductAddonChecker.jsm | 467 --------------------- .../internal/SpellCheckDictionaryBootstrap.js | 17 - toolkit/mozapps/webextensions/internal/moz.build | 4 +- toolkit/mozapps/webextensions/jar.mn | 26 +- toolkit/mozapps/webextensions/moz.build | 8 +- 24 files changed, 487 insertions(+), 1261 deletions(-) create mode 100644 toolkit/mozapps/extensions/internal/ProductAddonChecker.jsm delete mode 100644 toolkit/mozapps/webextensions/amIAddonManager.idl delete mode 100644 toolkit/mozapps/webextensions/amIAddonPathService.idl delete mode 100644 toolkit/mozapps/webextensions/amIWebInstallListener.idl delete mode 100644 toolkit/mozapps/webextensions/amIWebInstaller.idl delete mode 100644 toolkit/mozapps/webextensions/content/OpenH264-license.txt delete mode 100644 toolkit/mozapps/webextensions/content/about.xul delete mode 100644 toolkit/mozapps/webextensions/content/blocklist.css delete mode 100644 toolkit/mozapps/webextensions/content/blocklist.xml delete mode 100644 toolkit/mozapps/webextensions/content/blocklist.xul delete mode 100644 toolkit/mozapps/webextensions/content/eula.xul delete mode 100644 toolkit/mozapps/webextensions/content/gmpPrefs.xul delete mode 100644 toolkit/mozapps/webextensions/content/list.xul delete mode 100644 toolkit/mozapps/webextensions/content/pluginPrefs.xul delete mode 100644 toolkit/mozapps/webextensions/content/updateinfo.xsl delete mode 100644 toolkit/mozapps/webextensions/content/xpinstallConfirm.css delete mode 100644 toolkit/mozapps/webextensions/content/xpinstallConfirm.xul delete mode 100644 toolkit/mozapps/webextensions/content/xpinstallItem.xml delete mode 100644 toolkit/mozapps/webextensions/internal/ProductAddonChecker.jsm delete mode 100644 toolkit/mozapps/webextensions/internal/SpellCheckDictionaryBootstrap.js (limited to 'toolkit/mozapps') diff --git a/toolkit/mozapps/extensions/internal/ProductAddonChecker.jsm b/toolkit/mozapps/extensions/internal/ProductAddonChecker.jsm new file mode 100644 index 000000000..f98dd2a94 --- /dev/null +++ b/toolkit/mozapps/extensions/internal/ProductAddonChecker.jsm @@ -0,0 +1,467 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +const LOCAL_EME_SOURCES = [{ + "id": "gmp-eme-adobe", + "src": "chrome://global/content/gmp-sources/eme-adobe.json" +}, { + "id": "gmp-gmpopenh264", + "src": "chrome://global/content/gmp-sources/openh264.json" +}, { + "id": "gmp-widevinecdm", + "src": "chrome://global/content/gmp-sources/widevinecdm.json" +}]; + +this.EXPORTED_SYMBOLS = [ "ProductAddonChecker" ]; + +Cu.importGlobalProperties(["XMLHttpRequest"]); + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/Task.jsm"); +Cu.import("resource://gre/modules/Log.jsm"); +Cu.import("resource://gre/modules/CertUtils.jsm"); +/* globals checkCert, BadCertHandler*/ +Cu.import("resource://gre/modules/FileUtils.jsm"); +Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import("resource://gre/modules/osfile.jsm"); + +/* globals GMPPrefs */ +XPCOMUtils.defineLazyModuleGetter(this, "GMPPrefs", + "resource://gre/modules/GMPUtils.jsm"); + +/* globals OS */ + +XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", + "resource://gre/modules/UpdateUtils.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "ServiceRequest", + "resource://gre/modules/ServiceRequest.jsm"); + +// This exists so that tests can override the XHR behaviour for downloading +// the addon update XML file. +var CreateXHR = function() { + return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]. + createInstance(Ci.nsISupports); +} + +var logger = Log.repository.getLogger("addons.productaddons"); + +/** + * Number of milliseconds after which we need to cancel `downloadXML`. + * + * Bug 1087674 suggests that the XHR we use in `downloadXML` may + * never terminate in presence of network nuisances (e.g. strange + * antivirus behavior). This timeout is a defensive measure to ensure + * that we fail cleanly in such case. + */ +const TIMEOUT_DELAY_MS = 20000; +// Chunk size for the incremental downloader +const DOWNLOAD_CHUNK_BYTES_SIZE = 300000; +// Incremental downloader interval +const DOWNLOAD_INTERVAL = 0; +// How much of a file to read into memory at a time for hashing +const HASH_CHUNK_SIZE = 8192; + +/** + * Gets the status of an XMLHttpRequest either directly or from its underlying + * channel. + * + * @param request + * The XMLHttpRequest. + * @return an integer status value. + */ +function getRequestStatus(request) { + let status = null; + try { + status = request.status; + } + catch (e) { + } + + if (status != null) { + return status; + } + + return request.channel.QueryInterface(Ci.nsIRequest).status; +} + +/** + * Downloads an XML document from a URL optionally testing the SSL certificate + * for certain attributes. + * + * @param url + * The url to download from. + * @param allowNonBuiltIn + * Whether to trust SSL certificates without a built-in CA issuer. + * @param allowedCerts + * The list of certificate attributes to match the SSL certificate + * against or null to skip checks. + * @return a promise that resolves to the DOM document downloaded or rejects + * with a JS exception in case of error. + */ +function downloadXML(url, allowNonBuiltIn = false, allowedCerts = null) { + return new Promise((resolve, reject) => { + let request = CreateXHR(); + // This is here to let unit test code override XHR + if (request.wrappedJSObject) { + request = request.wrappedJSObject; + } + request.open("GET", url, true); + request.channel.notificationCallbacks = new BadCertHandler(allowNonBuiltIn); + // Prevent the request from reading from the cache. + request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE; + // Prevent the request from writing to the cache. + request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING; + // Use conservative TLS settings. See bug 1325501. + // TODO move to ServiceRequest. + if (request.channel instanceof Ci.nsIHttpChannelInternal) { + request.channel.QueryInterface(Ci.nsIHttpChannelInternal).beConservative = true; + } + request.timeout = TIMEOUT_DELAY_MS; + + request.overrideMimeType("text/xml"); + // The Cache-Control header is only interpreted by proxies and the + // final destination. It does not help if a resource is already + // cached locally. + request.setRequestHeader("Cache-Control", "no-cache"); + // HTTP/1.0 servers might not implement Cache-Control and + // might only implement Pragma: no-cache + request.setRequestHeader("Pragma", "no-cache"); + + let fail = (event) => { + let request = event.target; + let status = getRequestStatus(request); + let message = "Failed downloading XML, status: " + status + ", reason: " + event.type; + logger.warn(message); + let ex = new Error(message); + ex.status = status; + reject(ex); + }; + + let success = (event) => { + logger.info("Completed downloading document"); + let request = event.target; + + try { + checkCert(request.channel, allowNonBuiltIn, allowedCerts); + } catch (ex) { + logger.error("Request failed certificate checks: " + ex); + ex.status = getRequestStatus(request); + reject(ex); + return; + } + + resolve(request.responseXML); + }; + + request.addEventListener("error", fail, false); + request.addEventListener("abort", fail, false); + request.addEventListener("timeout", fail, false); + request.addEventListener("load", success, false); + + logger.info("sending request to: " + url); + request.send(null); + }); +} + +function downloadJSON(uri) { + logger.info("fetching config from: " + uri); + return new Promise((resolve, reject) => { + let xmlHttp = new ServiceRequest({mozAnon: true}); + + xmlHttp.onload = function(aResponse) { + resolve(JSON.parse(this.responseText)); + }; + + xmlHttp.onerror = function(e) { + reject("Fetching " + uri + " results in error code: " + e.target.status); + }; + + xmlHttp.open("GET", uri); + xmlHttp.overrideMimeType("application/json"); + xmlHttp.send(); + }); +} + + +/** + * Parses a list of add-ons from a DOM document. + * + * @param document + * The DOM document to parse. + * @return null if there is no element otherwise an object containing + * an array of the addons listed and a field notifying whether the + * fallback was used. + */ +function parseXML(document) { + // Check that the root element is correct + if (document.documentElement.localName != "updates") { + throw new Error("got node name: " + document.documentElement.localName + + ", expected: updates"); + } + + // Check if there are any addons elements in the updates element + let addons = document.querySelector("updates:root > addons"); + if (!addons) { + return null; + } + + let results = []; + let addonList = document.querySelectorAll("updates:root > addons > addon"); + for (let addonElement of addonList) { + let addon = {}; + + for (let name of ["id", "URL", "hashFunction", "hashValue", "version", "size"]) { + if (addonElement.hasAttribute(name)) { + addon[name] = addonElement.getAttribute(name); + } + } + addon.size = Number(addon.size) || undefined; + + results.push(addon); + } + + return { + usedFallback: false, + gmpAddons: results + }; +} + +/** + * If downloading from the network fails (AUS server is down), + * load the sources from local build configuration. + */ +function downloadLocalConfig() { + + if (!GMPPrefs.get(GMPPrefs.KEY_UPDATE_ENABLED, true)) { + logger.info("Updates are disabled via media.gmp-manager.updateEnabled"); + return Promise.resolve({usedFallback: true, gmpAddons: []}); + } + + return Promise.all(LOCAL_EME_SOURCES.map(conf => { + return downloadJSON(conf.src).then(addons => { + + let platforms = addons.vendors[conf.id].platforms; + let target = Services.appinfo.OS + "_" + UpdateUtils.ABI; + let details = null; + + while (!details) { + if (!(target in platforms)) { + // There was no matching platform so return false, this addon + // will be filtered from the results below + logger.info("no details found for: " + target); + return false; + } + // Field either has the details of the binary or is an alias + // to another build target key that does + if (platforms[target].alias) { + target = platforms[target].alias; + } else { + details = platforms[target]; + } + } + + logger.info("found plugin: " + conf.id); + return { + "id": conf.id, + "URL": details.fileUrl, + "hashFunction": addons.hashFunction, + "hashValue": details.hashValue, + "version": addons.vendors[conf.id].version, + "size": details.filesize + }; + }); + })).then(addons => { + + // Some filters may not match this platform so + // filter those out + addons = addons.filter(x => x !== false); + + return { + usedFallback: true, + gmpAddons: addons + }; + }); +} + +/** + * Downloads file from a URL using XHR. + * + * @param url + * The url to download from. + * @return a promise that resolves to the path of a temporary file or rejects + * with a JS exception in case of error. + */ +function downloadFile(url) { + return new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest(); + xhr.onload = function(response) { + logger.info("downloadXHR File download. status=" + xhr.status); + if (xhr.status != 200 && xhr.status != 206) { + reject(Components.Exception("File download failed", xhr.status)); + return; + } + Task.spawn(function* () { + let f = yield OS.File.openUnique(OS.Path.join(OS.Constants.Path.tmpDir, "tmpaddon")); + let path = f.path; + logger.info(`Downloaded file will be saved to ${path}`); + yield f.file.close(); + yield OS.File.writeAtomic(path, new Uint8Array(xhr.response)); + return path; + }).then(resolve, reject); + }; + + let fail = (event) => { + let request = event.target; + let status = getRequestStatus(request); + let message = "Failed downloading via XHR, status: " + status + ", reason: " + event.type; + logger.warn(message); + let ex = new Error(message); + ex.status = status; + reject(ex); + }; + xhr.addEventListener("error", fail); + xhr.addEventListener("abort", fail); + + xhr.responseType = "arraybuffer"; + try { + xhr.open("GET", url); + // Use conservative TLS settings. See bug 1325501. + // TODO move to ServiceRequest. + if (xhr.channel instanceof Ci.nsIHttpChannelInternal) { + xhr.channel.QueryInterface(Ci.nsIHttpChannelInternal).beConservative = true; + } + xhr.send(null); + } catch (ex) { + reject(ex); + } + }); +} + +/** + * Convert a string containing binary values to hex. + */ +function binaryToHex(input) { + let result = ""; + for (let i = 0; i < input.length; ++i) { + let hex = input.charCodeAt(i).toString(16); + if (hex.length == 1) { + hex = "0" + hex; + } + result += hex; + } + return result; +} + +/** + * Calculates the hash of a file. + * + * @param hashFunction + * The type of hash function to use, must be supported by nsICryptoHash. + * @param path + * The path of the file to hash. + * @return a promise that resolves to hash of the file or rejects with a JS + * exception in case of error. + */ +var computeHash = Task.async(function*(hashFunction, path) { + let file = yield OS.File.open(path, { existing: true, read: true }); + try { + let hasher = Cc["@mozilla.org/security/hash;1"]. + createInstance(Ci.nsICryptoHash); + hasher.initWithString(hashFunction); + + let bytes; + do { + bytes = yield file.read(HASH_CHUNK_SIZE); + hasher.update(bytes, bytes.length); + } while (bytes.length == HASH_CHUNK_SIZE); + + return binaryToHex(hasher.finish(false)); + } + finally { + yield file.close(); + } +}); + +/** + * Verifies that a downloaded file matches what was expected. + * + * @param properties + * The properties to check, `size` and `hashFunction` with `hashValue` + * are supported. Any properties missing won't be checked. + * @param path + * The path of the file to check. + * @return a promise that resolves if the file matched or rejects with a JS + * exception in case of error. + */ +var verifyFile = Task.async(function*(properties, path) { + if (properties.size !== undefined) { + let stat = yield OS.File.stat(path); + if (stat.size != properties.size) { + throw new Error("Downloaded file was " + stat.size + " bytes but expected " + properties.size + " bytes."); + } + } + + if (properties.hashFunction !== undefined) { + let expectedDigest = properties.hashValue.toLowerCase(); + let digest = yield computeHash(properties.hashFunction, path); + if (digest != expectedDigest) { + throw new Error("Hash was `" + digest + "` but expected `" + expectedDigest + "`."); + } + } +}); + +const ProductAddonChecker = { + /** + * Downloads a list of add-ons from a URL optionally testing the SSL + * certificate for certain attributes. + * + * @param url + * The url to download from. + * @param allowNonBuiltIn + * Whether to trust SSL certificates without a built-in CA issuer. + * @param allowedCerts + * The list of certificate attributes to match the SSL certificate + * against or null to skip checks. + * @return a promise that resolves to an object containing the list of add-ons + * and whether the local fallback was used, or rejects with a JS + * exception in case of error. + */ + getProductAddonList: function(url, allowNonBuiltIn = false, allowedCerts = null) { + if (!GMPPrefs.get(GMPPrefs.KEY_UPDATE_ENABLED, true)) { + logger.info("Updates are disabled via media.gmp-manager.updateEnabled"); + return Promise.resolve({usedFallback: true, gmpAddons: []}); + } + + return downloadXML(url, allowNonBuiltIn, allowedCerts) + .then(parseXML) + .catch(downloadLocalConfig); + }, + + /** + * Downloads an add-on to a local file and checks that it matches the expected + * file. The caller is responsible for deleting the temporary file returned. + * + * @param addon + * The addon to download. + * @return a promise that resolves to the temporary file downloaded or rejects + * with a JS exception in case of error. + */ + downloadAddon: Task.async(function*(addon) { + let path = yield downloadFile(addon.URL); + try { + yield verifyFile(addon, path); + return path; + } + catch (e) { + yield OS.File.remove(path); + throw e; + } + }) +} diff --git a/toolkit/mozapps/extensions/internal/moz.build b/toolkit/mozapps/extensions/internal/moz.build index efcd2af21..337df3104 100644 --- a/toolkit/mozapps/extensions/internal/moz.build +++ b/toolkit/mozapps/extensions/internal/moz.build @@ -5,12 +5,12 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXTRA_JS_MODULES.addons += [ - '../../webextensions/internal/ProductAddonChecker.jsm', 'AddonLogging.jsm', 'AddonRepository_SQLiteMigrator.jsm', 'Content.js', 'GMPProvider.jsm', 'LightweightThemeImageOptimizer.jsm', + 'ProductAddonChecker.jsm', 'SpellCheckDictionaryBootstrap.js', ] diff --git a/toolkit/mozapps/webextensions/amIAddonManager.idl b/toolkit/mozapps/webextensions/amIAddonManager.idl deleted file mode 100644 index 58a58b62d..000000000 --- a/toolkit/mozapps/webextensions/amIAddonManager.idl +++ /dev/null @@ -1,29 +0,0 @@ -/* 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/. */ - -#include "nsISupports.idl" - -interface nsIURI; - -/** - * A service to make some AddonManager functionality available to C++ callers. - * Javascript callers should still use AddonManager.jsm directly. - */ -[scriptable, function, uuid(7b45d82d-7ad5-48d7-9b05-f32eb9818cd4)] -interface amIAddonManager : nsISupports -{ - /** - * Synchronously map a URI to the corresponding Addon ID. - * - * Mappable URIs are limited to in-application resources belonging to the - * add-on, such as Javascript compartments, XUL windows, XBL bindings, etc. - * but do not include URIs from meta data, such as the add-on homepage. - * - * @param aURI - * The nsIURI to map - * @return - * true if the URI has been mapped successfully to an Addon ID - */ - boolean mapURIToAddonID(in nsIURI aURI, out AUTF8String aID); -}; diff --git a/toolkit/mozapps/webextensions/amIAddonPathService.idl b/toolkit/mozapps/webextensions/amIAddonPathService.idl deleted file mode 100644 index 9c9197a61..000000000 --- a/toolkit/mozapps/webextensions/amIAddonPathService.idl +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsISupports.idl" - -interface nsIURI; - -/** - * This service maps file system paths where add-ons reside to the ID - * of the add-on. Paths are added by the add-on manager. They can - * looked up by anyone. - */ -[scriptable, uuid(fcd9e270-dfb1-11e3-8b68-0800200c9a66)] -interface amIAddonPathService : nsISupports -{ - /** - * Given a path to a file, return the ID of the add-on that the file belongs - * to. Returns an empty string if there is no add-on there. Note that if an - * add-on is located at /a/b/c, then looking up the path /a/b/c/d will return - * that add-on. - */ - AString findAddonId(in AString path); - - /** - * Call this function to inform the service that the given file system path is - * associated with the given add-on ID. - */ - void insertPath(in AString path, in AString addonId); - - /** - * Given a URI to a file, return the ID of the add-on that the file belongs - * to. Returns an empty string if there is no add-on there. - */ - AString mapURIToAddonId(in nsIURI aURI); -}; diff --git a/toolkit/mozapps/webextensions/amIWebInstallListener.idl b/toolkit/mozapps/webextensions/amIWebInstallListener.idl deleted file mode 100644 index eed108097..000000000 --- a/toolkit/mozapps/webextensions/amIWebInstallListener.idl +++ /dev/null @@ -1,134 +0,0 @@ -/* 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/. */ - -#include "nsISupports.idl" - -interface nsIDOMElement; -interface nsIURI; -interface nsIVariant; - -/** - * amIWebInstallInfo is used by the default implementation of - * amIWebInstallListener to communicate with the running application and allow - * it to warn the user about blocked installs and start the installs running. - */ -[scriptable, uuid(fa0b47a3-f819-47ac-bc66-4bd1d7f67b1d)] -interface amIWebInstallInfo : nsISupports -{ - readonly attribute nsIDOMElement browser; - readonly attribute nsIURI originatingURI; - readonly attribute nsIVariant installs; - - /** - * Starts all installs. - */ - void install(); -}; - -/** - * The registered amIWebInstallListener is used to notify about new installs - * triggered by websites. The default implementation displays a confirmation - * dialog when add-ons are ready to install and uses the observer service to - * notify when installations are blocked. - */ -[scriptable, uuid(d9240d4b-6b3a-4cad-b402-de6c93337e0c)] -interface amIWebInstallListener : nsISupports -{ - /** - * Called when installation by websites is currently disabled. - * - * @param aBrowser - * The browser that triggered the installs - * @param aUri - * The URI of the site that triggered the installs - * @param aInstalls - * The AddonInstalls that were blocked - * @param aCount - * The number of AddonInstalls - */ - void onWebInstallDisabled(in nsIDOMElement aBrowser, in nsIURI aUri, - [array, size_is(aCount)] in nsIVariant aInstalls, - [optional] in uint32_t aCount); - - /** - * Called when the website is not allowed to directly prompt the user to - * install add-ons. - * - * @param aBrowser - * The browser that triggered the installs - * @param aUri - * The URI of the site that triggered the installs - * @param aInstalls - * The AddonInstalls that were blocked - * @param aCount - * The number of AddonInstalls - * @return true if the caller should start the installs - */ - boolean onWebInstallBlocked(in nsIDOMElement aBrowser, in nsIURI aUri, - [array, size_is(aCount)] in nsIVariant aInstalls, - [optional] in uint32_t aCount); - - /** - * Called when a website wants to ask the user to install add-ons. - * - * @param aBrowser - * The browser that triggered the installs - * @param aUri - * The URI of the site that triggered the installs - * @param aInstalls - * The AddonInstalls that were requested - * @param aCount - * The number of AddonInstalls - * @return true if the caller should start the installs - */ - boolean onWebInstallRequested(in nsIDOMElement aBrowser, in nsIURI aUri, - [array, size_is(aCount)] in nsIVariant aInstalls, - [optional] in uint32_t aCount); -}; - -[scriptable, uuid(a80b89ad-bb1a-4c43-9cb7-3ae656556f78)] -interface amIWebInstallListener2 : nsISupports -{ - /** - * Called when a non-same-origin resource attempted to initiate an install. - * Installs will have already been cancelled and cannot be restarted. - * - * @param aBrowser - * The browser that triggered the installs - * @param aUri - * The URI of the site that triggered the installs - * @param aInstalls - * The AddonInstalls that were blocked - * @param aCount - * The number of AddonInstalls - */ - boolean onWebInstallOriginBlocked(in nsIDOMElement aBrowser, in nsIURI aUri, - [array, size_is(aCount)] in nsIVariant aInstalls, - [optional] in uint32_t aCount); -}; - -/** - * amIWebInstallPrompt is used, if available, by the default implementation of - * amIWebInstallInfo to display a confirmation UI to the user before running - * installs. - */ -[scriptable, uuid(386906f1-4d18-45bf-bc81-5dcd68e42c3b)] -interface amIWebInstallPrompt : nsISupports -{ - /** - * Get a confirmation that the user wants to start the installs. - * - * @param aBrowser - * The browser that triggered the installs - * @param aUri - * The URI of the site that triggered the installs - * @param aInstalls - * The AddonInstalls that were requested - * @param aCount - * The number of AddonInstalls - */ - void confirm(in nsIDOMElement aBrowser, in nsIURI aUri, - [array, size_is(aCount)] in nsIVariant aInstalls, - [optional] in uint32_t aCount); -}; diff --git a/toolkit/mozapps/webextensions/amIWebInstaller.idl b/toolkit/mozapps/webextensions/amIWebInstaller.idl deleted file mode 100644 index 6c5ebca67..000000000 --- a/toolkit/mozapps/webextensions/amIWebInstaller.idl +++ /dev/null @@ -1,82 +0,0 @@ -/* 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/. */ - -#include "nsISupports.idl" - -interface nsIDOMElement; -interface nsIVariant; -interface nsIURI; - -/** - * A callback function used to notify webpages when a requested install has - * ended. - * - * NOTE: This is *not* the same as InstallListener. - */ -[scriptable, function, uuid(bb22f5c0-3ca1-48f6-873c-54e87987700f)] -interface amIInstallCallback : nsISupports -{ - /** - * Called when an install completes or fails. - * - * @param aUrl - * The url of the add-on being installed - * @param aStatus - * 0 if the install was successful or negative if not - */ - void onInstallEnded(in AString aUrl, in int32_t aStatus); -}; - - -/** - * This interface is used to allow webpages to start installing add-ons. - */ -[scriptable, uuid(658d6c09-15e0-4688-bee8-8551030472a9)] -interface amIWebInstaller : nsISupports -{ - /** - * Checks if installation is enabled for a webpage. - * - * @param aMimetype - * The mimetype for the add-on to be installed - * @param referer - * The URL of the webpage trying to install an add-on - * @return true if installation is enabled - */ - boolean isInstallEnabled(in AString aMimetype, in nsIURI aReferer); - - /** - * Installs an array of add-ons at the request of a webpage - * - * @param aMimetype - * The mimetype for the add-ons - * @param aBrowser - * The browser installing the add-ons. - * @param aReferer - * The URI for the webpage installing the add-ons - * @param aUris - * The URIs of add-ons to be installed - * @param aHashes - * The hashes for the add-ons to be installed - * @param aNames - * The names for the add-ons to be installed - * @param aIcons - * The icons for the add-ons to be installed - * @param aCallback - * An optional callback to notify about installation success and - * failure - * @param aInstallCount - * An optional argument including the number of add-ons to install - * @return true if the installation was successfully started - */ - boolean installAddonsFromWebpage(in AString aMimetype, - in nsIDOMElement aBrowser, - in nsIURI aReferer, - [array, size_is(aInstallCount)] in wstring aUris, - [array, size_is(aInstallCount)] in wstring aHashes, - [array, size_is(aInstallCount)] in wstring aNames, - [array, size_is(aInstallCount)] in wstring aIcons, - [optional] in amIInstallCallback aCallback, - [optional] in uint32_t aInstallCount); -}; diff --git a/toolkit/mozapps/webextensions/content/OpenH264-license.txt b/toolkit/mozapps/webextensions/content/OpenH264-license.txt deleted file mode 100644 index ad37989b8..000000000 --- a/toolkit/mozapps/webextensions/content/OpenH264-license.txt +++ /dev/null @@ -1,59 +0,0 @@ -------------------------------------------------------- -About The Cisco-Provided Binary of OpenH264 Video Codec -------------------------------------------------------- - -Cisco provides this program under the terms of the BSD license. - -Additionally, this binary is licensed under Cisco’s AVC/H.264 Patent Portfolio License from MPEG LA, at no cost to you, provided that the requirements and conditions shown below in the AVC/H.264 Patent Portfolio sections are met. - -As with all AVC/H.264 codecs, you may also obtain your own patent license from MPEG LA or from the individual patent owners, or proceed at your own risk. Your rights from Cisco under the BSD license are not affected by this choice. - -For more information on the OpenH264 binary licensing, please see the OpenH264 FAQ found at http://www.openh264.org/faq.html#binary - -A corresponding source code to this binary program is available under the same BSD terms, which can be found at http://www.openh264.org - ------------ -BSD License ------------ - -Copyright © 2014 Cisco Systems, Inc. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ------------------------------------------ -AVC/H.264 Patent Portfolio License Notice ------------------------------------------ - -The binary form of this Software is distributed by Cisco under the AVC/H.264 Patent Portfolio License from MPEG LA, and is subject to the following requirements, which may or may not be applicable to your use of this software: - -THIS PRODUCT IS LICENSED UNDER THE AVC PATENT PORTFOLIO LICENSE FOR THE PERSONAL USE OF A CONSUMER OR OTHER USES IN WHICH IT DOES NOT RECEIVE REMUNERATION TO (i) ENCODE VIDEO IN COMPLIANCE WITH THE AVC STANDARD (“AVC VIDEO”) AND/OR (ii) DECODE AVC VIDEO THAT WAS ENCODED BY A CONSUMER ENGAGED IN A PERSONAL ACTIVITY AND/OR WAS OBTAINED FROM A VIDEO PROVIDER LICENSED TO PROVIDE AVC VIDEO. NO LICENSE IS GRANTED OR SHALL BE IMPLIED FOR ANY OTHER USE. ADDITIONAL INFORMATION MAY BE OBTAINED FROM MPEG LA, L.L.C. SEE HTTP://WWW.MPEGLA.COM - -Accordingly, please be advised that content providers and broadcasters using AVC/H.264 in their service may be required to obtain a separate use license from MPEG LA, referred to as "(b) sublicenses" in the SUMMARY OF AVC/H.264 LICENSE TERMS from MPEG LA found at http://www.openh264.org/mpegla - ---------------------------------------------- -AVC/H.264 Patent Portfolio License Conditions ---------------------------------------------- - -In addition, the Cisco-provided binary of this Software is licensed under Cisco's license from MPEG LA only if the following conditions are met: - -1. The Cisco-provided binary is separately downloaded to an end user’s device, and not integrated into or combined with third party software prior to being downloaded to the end user’s device; - -2. The end user must have the ability to control (e.g., to enable, disable, or re-enable) the use of the Cisco-provided binary; - -3. Third party software, in the location where end users can control the use of the Cisco-provided binary, must display the following text: - - "OpenH264 Video Codec provided by Cisco Systems, Inc." - -4. Any third-party software that makes use of the Cisco-provided binary must reproduce all of the above text, as well as this last condition, in the EULA and/or in another location where licensing information is to be presented to the end user. - - - - v1.0 diff --git a/toolkit/mozapps/webextensions/content/about.xul b/toolkit/mozapps/webextensions/content/about.xul deleted file mode 100644 index 6effcf37a..000000000 --- a/toolkit/mozapps/webextensions/content/about.xul +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - -