Bug 715787 - Refactor common provider-agnostic prefs to be properties of AddonManager. r=dtownsend

This commit is contained in:
Blair McBride 2012-02-15 15:07:29 +13:00
parent 1dc2fe85f2
commit 2b11c8f8ad
8 changed files with 537 additions and 200 deletions

View File

@ -50,6 +50,7 @@ const PREF_EM_LAST_APP_VERSION = "extensions.lastAppVersion";
const PREF_EM_LAST_PLATFORM_VERSION = "extensions.lastPlatformVersion";
const PREF_EM_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault";
const PREF_EM_STRICT_COMPATIBILITY = "extensions.strictCompatibility";
const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
const PREF_EM_UPDATE_URL = "extensions.update.url";
const PREF_APP_UPDATE_ENABLED = "app.update.enabled";
const PREF_APP_UPDATE_AUTO = "app.update.auto";
@ -64,8 +65,13 @@ const PREF_SELECTED_LOCALE = "general.useragent.locale";
const UPDATE_REQUEST_VERSION = 2;
const CATEGORY_UPDATE_PARAMS = "extension-update-params";
// Note: This has to be kept in sync with the same constant in AddonRepository.jsm
const STRICT_COMPATIBILITY_DEFAULT = true;
const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi;
const PREF_EM_CHECK_COMPATIBILITY_BASE = "extensions.checkCompatibility";
#ifdef MOZ_COMPATIBILITY_NIGHTLY
var PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE + ".nightly";
#else
var PREF_EM_CHECK_COMPATIBILITY;
#endif
const TOOLKIT_ID = "toolkit@mozilla.org";
@ -391,13 +397,19 @@ function AddonType(aId, aLocaleURI, aLocaleKey, aViewType, aUIPriority, aFlags)
}
var gStarted = false;
var gStrictCompatibility = STRICT_COMPATIBILITY_DEFAULT;
var gCheckCompatibility = true;
var gStrictCompatibility = true;
var gCheckUpdateSecurityDefault = true;
var gCheckUpdateSecurity = gCheckUpdateSecurityDefault;
var gUpdateEnabled = true;
var gAutoUpdateDefault = true;
/**
* This is the real manager, kept here rather than in AddonManager to keep its
* contents hidden from API users.
*/
var AddonManagerInternal = {
managerListeners: [],
installListeners: [],
addonListeners: [],
typeListeners: [],
@ -485,11 +497,41 @@ var AddonManagerInternal = {
(appChanged === undefined ? 0 : -1));
}
#ifndef MOZ_COMPATIBILITY_NIGHTLY
PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE + "." +
Services.appinfo.version.replace(BRANCH_REGEXP, "$1");
#endif
try {
gCheckCompatibility = Services.prefs.getBoolPref(PREF_EM_CHECK_COMPATIBILITY);
} catch (e) {}
Services.prefs.addObserver(PREF_EM_CHECK_COMPATIBILITY, this, false);
try {
gStrictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY);
} catch (e) {}
Services.prefs.addObserver(PREF_EM_STRICT_COMPATIBILITY, this, false);
try {
let defaultBranch = Services.prefs.getDefaultBranch("");
gCheckUpdateSecurityDefault = defaultBranch.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY);
} catch(e) {}
try {
gCheckUpdateSecurity = Services.prefs.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY);
} catch (e) {}
Services.prefs.addObserver(PREF_EM_CHECK_UPDATE_SECURITY, this, false);
try {
gUpdateEnabled = Services.prefs.getBoolPref(PREF_EM_UPDATE_ENABLED);
} catch (e) {}
Services.prefs.addObserver(PREF_EM_UPDATE_ENABLED, this, false);
try {
gAutoUpdateDefault = Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT);
} catch (e) {}
Services.prefs.addObserver(PREF_EM_AUTOUPDATE_DEFAULT, this, false);
// Ensure all default providers have had a chance to register themselves
DEFAULT_PROVIDERS.forEach(function(url) {
try {
@ -611,12 +653,17 @@ var AddonManagerInternal = {
* up everything in order for automated tests to fake restarts.
*/
shutdown: function AMI_shutdown() {
Services.prefs.removeObserver(PREF_EM_CHECK_COMPATIBILITY, this);
Services.prefs.removeObserver(PREF_EM_STRICT_COMPATIBILITY, this);
Services.prefs.removeObserver(PREF_EM_CHECK_UPDATE_SECURITY, this);
Services.prefs.removeObserver(PREF_EM_UPDATE_ENABLED, this);
Services.prefs.removeObserver(PREF_EM_AUTOUPDATE_DEFAULT, this);
this.providers.forEach(function(provider) {
callProvider(provider, "shutdown");
});
this.managerListeners.splice(0, this.managerListeners.length);
this.installListeners.splice(0, this.installListeners.length);
this.addonListeners.splice(0, this.addonListeners.length);
this.typeListeners.splice(0, this.typeListeners.length);
@ -632,21 +679,76 @@ var AddonManagerInternal = {
*/
observe: function AMI_observe(aSubject, aTopic, aData) {
switch (aData) {
case PREF_EM_STRICT_COMPATIBILITY:
let oldValue = gStrictCompatibility;
try {
gStrictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY);
} catch(e) {
gStrictCompatibility = STRICT_COMPATIBILITY_DEFAULT;
case PREF_EM_CHECK_COMPATIBILITY: {
let oldValue = gCheckCompatibility;
try {
gCheckCompatibility = Services.prefs.getBoolPref(PREF_EM_CHECK_COMPATIBILITY);
} catch(e) {
gCheckCompatibility = true;
}
this.callManagerListeners("onCompatibilityModeChanged");
if (gCheckCompatibility != oldValue)
this.updateAddonAppDisabledStates();
break;
}
case PREF_EM_STRICT_COMPATIBILITY: {
let oldValue = gStrictCompatibility;
try {
gStrictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY);
} catch(e) {
gStrictCompatibility = true;
}
// XXXunf Currently, this won't notify listeners that an addon's
// compatibility status has changed if the addon's appDisabled state
// doesn't change.
if (gStrictCompatibility != oldValue)
this.updateAddonAppDisabledStates();
this.callManagerListeners("onCompatibilityModeChanged");
break;
// XXXunf Currently, this won't notify listeners that an addon's
// compatibility status has changed if the addon's appDisabled state
// doesn't change.
if (gStrictCompatibility != oldValue)
this.updateAddonAppDisabledStates();
break;
}
case PREF_EM_CHECK_UPDATE_SECURITY: {
let oldValue = gCheckUpdateSecurity;
try {
gCheckUpdateSecurity = Services.prefs.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY);
} catch(e) {
gCheckUpdateSecurity = true;
}
this.callManagerListeners("onCheckUpdateSecurityChanged");
if (gCheckUpdateSecurity != oldValue)
this.updateAddonAppDisabledStates();
break;
}
case PREF_EM_UPDATE_ENABLED: {
let oldValue = gUpdateEnabled;
try {
gUpdateEnabled = Services.prefs.getBoolPref(PREF_EM_UPDATE_ENABLED);
} catch(e) {
gUpdateEnabled = true;
}
this.callManagerListeners("onUpdateModeChanged");
break;
}
case PREF_EM_AUTOUPDATE_DEFAULT: {
let oldValue = gAutoUpdateDefault;
try {
gAutoUpdateDefault = Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT);
} catch(e) {
gAutoUpdateDefault = true;
}
this.callManagerListeners("onUpdateModeChanged");
break;
}
}
},
@ -728,9 +830,7 @@ var AddonManagerInternal = {
Services.prefs.getBoolPref(PREF_APP_UPDATE_ENABLED) &&
Services.prefs.getBoolPref(PREF_APP_UPDATE_AUTO);
let checkAddons = Services.prefs.getBoolPref(PREF_EM_UPDATE_ENABLED);
if (!checkAddons && !checkHotfix)
if (!this.updateEnabled && !checkHotfix)
return;
Services.obs.notifyObservers(null, "addons-background-update-start", null);
@ -749,7 +849,7 @@ var AddonManagerInternal = {
}
}
if (checkAddons) {
if (this.updateEnabled) {
let scope = {};
Components.utils.import("resource://gre/modules/AddonRepository.jsm", scope);
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
@ -927,6 +1027,26 @@ var AddonManagerInternal = {
this.startupChanges[aType] = this.startupChanges[aType].filter(function(aItem) aItem != aID);
},
/**
* Calls all registered AddonManagerListeners with an event. Any parameters
* after the method parameter are passed to the listener.
*
* @param aMethod
* The method on the listeners to call
*/
callManagerListeners: function AMI_callManagerListeners(aMethod) {
var args = Array.slice(arguments, 1);
this.managerListeners.forEach(function(listener) {
try {
if (aMethod in listener)
listener[aMethod].apply(listener, args);
}
catch (e) {
WARN("AddonManagerListener threw exception when calling " + aMethod, e);
}
});
},
/**
* Calls all registered InstallListeners with an event. Any parameters after
* the extraListeners parameter are passed to the listener.
@ -1427,6 +1547,33 @@ var AddonManagerInternal = {
});
},
/**
* Adds a new AddonManagerListener if the listener is not already registered.
*
* @param aListener
* The listener to add
*/
addManagerListener: function AMI_addManagerListener(aListener) {
if (!this.managerListeners.some(function(i) { return i == aListener; }))
this.managerListeners.push(aListener);
},
/**
* Removes an AddonManagerListener if the listener is registered.
*
* @param aListener
* The listener to remove
*/
removeManagerListener: function AMI_removeManagerListener(aListener) {
let pos = 0;
while (pos < this.managerListeners.length) {
if (this.managerListeners[pos] == aListener)
this.managerListeners.splice(pos, 1);
else
pos++;
}
},
/**
* Adds a new AddonListener if the listener is not already registered.
*
@ -1474,14 +1621,70 @@ var AddonManagerInternal = {
},
get autoUpdateDefault() {
try {
return Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT);
} catch(e) { }
return true;
return gAutoUpdateDefault;
},
set autoUpdateDefault(aValue) {
aValue = !!aValue;
if (aValue != gAutoUpdateDefault)
Services.prefs.setBoolPref(PREF_EM_AUTOUPDATE_DEFAULT, aValue);
return aValue;
},
get checkCompatibility() {
return gCheckCompatibility;
},
set checkCompatibility(aValue) {
aValue = !!aValue;
if (aValue != gCheckCompatibility) {
if (!aValue)
Services.prefs.setBoolPref(PREF_EM_CHECK_COMPATIBILITY, false);
else
Services.prefs.clearUserPref(PREF_EM_CHECK_COMPATIBILITY);
}
return aValue;
},
get strictCompatibility() {
return gStrictCompatibility;
},
set strictCompatibility(aValue) {
aValue = !!aValue;
if (aValue != gStrictCompatibility)
Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, aValue);
return aValue;
},
get checkUpdateSecurityDefault() {
return gCheckUpdateSecurityDefault;
},
get checkUpdateSecurity() {
return gCheckUpdateSecurity;
},
set checkUpdateSecurity(aValue) {
aValue = !!aValue;
if (aValue != gCheckUpdateSecurity) {
if (aValue != gCheckUpdateSecurityDefault)
Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, aValue);
else
Services.prefs.clearUserPref(PREF_EM_CHECK_UPDATE_SECURITY);
}
return aValue;
},
get updateEnabled() {
return gUpdateEnabled;
},
set updateEnabled(aValue) {
aValue = !!aValue;
if (aValue != gUpdateEnabled)
Services.prefs.setBoolPref(PREF_EM_UPDATE_ENABLED, aValue);
return aValue;
}
};
@ -1772,6 +1975,14 @@ var AddonManager = {
AddonManagerInternal.installAddonsFromWebpage(aType, aSource, aUri, aInstalls);
},
addManagerListener: function AM_addManagerListener(aListener) {
AddonManagerInternal.addManagerListener(aListener);
},
removeManagerListener: function AM_removeManagerListener(aListener) {
AddonManagerInternal.removeManagerListener(aListener);
},
addInstallListener: function AM_addInstallListener(aListener) {
AddonManagerInternal.addInstallListener(aListener);
},
@ -1800,10 +2011,6 @@ var AddonManager = {
return AddonManagerInternal.addonTypes;
},
get autoUpdateDefault() {
return AddonManagerInternal.autoUpdateDefault;
},
shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) {
if (!("applyBackgroundUpdates" in aAddon))
return false;
@ -1814,10 +2021,50 @@ var AddonManager = {
return this.autoUpdateDefault;
},
get checkCompatibility() {
return AddonManagerInternal.checkCompatibility;
},
set checkCompatibility(aValue) {
AddonManagerInternal.checkCompatibility = aValue;
},
get strictCompatibility() {
return AddonManagerInternal.strictCompatibility;
},
set strictCompatibility(aValue) {
AddonManagerInternal.strictCompatibility = aValue;
},
get checkUpdateSecurityDefault() {
return AddonManagerInternal.checkUpdateSecurityDefault;
},
get checkUpdateSecurity() {
return AddonManagerInternal.checkUpdateSecurity;
},
set checkUpdateSecurity(aValue) {
AddonManagerInternal.checkUpdateSecurity = aValue;
},
get updateEnabled() {
return AddonManagerInternal.updateEnabled;
},
set updateEnabled(aValue) {
AddonManagerInternal.updateEnabled = aValue;
},
get autoUpdateDefault() {
return AddonManagerInternal.autoUpdateDefault;
},
set autoUpdateDefault(aValue) {
AddonManagerInternal.autoUpdateDefault = aValue;
},
escapeAddonURI: function AM_escapeAddonURI(aAddon, aUri, aAppVersion) {
return AddonManagerInternal.escapeAddonURI(aAddon, aUri, aAppVersion);
}

View File

@ -63,23 +63,6 @@ const PREF_GETADDONS_GETRECOMMENDED = "extensions.getAddons.recommended.url
const PREF_GETADDONS_BROWSESEARCHRESULTS = "extensions.getAddons.search.browseURL";
const PREF_GETADDONS_GETSEARCHRESULTS = "extensions.getAddons.search.url";
const PREF_CHECK_COMPATIBILITY_BASE = "extensions.checkCompatibility";
const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi;
XPCOMUtils.defineLazyGetter(this, "PREF_CHECK_COMPATIBILITY", function () {
#ifdef MOZ_COMPATIBILITY_NIGHTLY
return PREF_CHECK_COMPATIBILITY_BASE + ".nightly";
#else
return PREF_CHECK_COMPATIBILITY_BASE + "." +
Services.appinfo.version.replace(BRANCH_REGEXP, "$1");
#endif
});
const PREF_EM_STRICT_COMPATIBILITY = "extensions.strictCompatibility";
// Note: This has to be kept in sync with the same constant in AddonManager.jsm
const STRICT_COMPATIBILITY_DEFAULT = true;
const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml";
const API_VERSION = "1.5";
@ -905,19 +888,10 @@ var AddonRepository = {
* The callback to pass results to
*/
searchAddons: function(aSearchTerms, aMaxResults, aCallback) {
let checkCompatibility = true;
try {
checkCompatibility = Services.prefs.getBoolPref(PREF_CHECK_COMPATIBILITY);
} catch(e) { }
let strictCompatibility = STRICT_COMPATIBILITY_DEFAULT;
try {
strictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY);
} catch(e) { }
let compatMode = "normal";
if (!checkCompatibility)
if (!AddonManager.checkCompatibility)
compatMode = "ignore";
else if (strictCompatibility)
else if (AddonManager.strictCompatibility)
compatMode = "strict";
let substitutions = {
@ -1214,16 +1188,6 @@ var AddonRepository = {
let self = this;
let results = [];
let checkCompatibility = true;
try {
checkCompatibility = Services.prefs.getBoolPref(PREF_CHECK_COMPATIBILITY);
} catch(e) { }
let strictCompatibility = STRICT_COMPATIBILITY_DEFAULT;
try {
strictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY);
} catch (e) {}
function isSameApplication(aAppNode) {
return self._getTextContent(aAppNode) == Services.appinfo.ID;
}
@ -1248,13 +1212,13 @@ var AddonRepository = {
let currentVersion = Services.appinfo.version;
return (Services.vc.compare(minVersion, currentVersion) <= 0 &&
((!strictCompatibility) ||
((!AddonManager.strictCompatibility) ||
Services.vc.compare(currentVersion, maxVersion) <= 0));
});
// Ignore add-ons not compatible with this Application
if (!compatible) {
if (checkCompatibility)
if (AddonManager.checkCompatibility)
continue;
if (!Array.some(applications, isSameApplication))

View File

@ -47,6 +47,7 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
var EXPORTED_SYMBOLS = [ "AddonUpdateChecker" ];
@ -62,6 +63,7 @@ const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.
const PREF_UPDATE_REQUIREBUILTINCERTS = "extensions.update.requireBuiltInCerts";
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/AddonRepository.jsm");
// shared code for suppressing bad cert dialogs
Components.utils.import("resource://gre/modules/CertUtils.jsm");
@ -78,6 +80,12 @@ var gRDF = Cc["@mozilla.org/rdf/rdf-service;1"].
});
}, this);
XPCOMUtils.defineLazyGetter(this, "AddonManager", function() {
Cu.import("resource://gre/modules/AddonManager.jsm");
return AddonManager;
});
/**
* A serialisation method for RDF data that produces an identical string
* for matching RDF graphs.
@ -351,14 +359,6 @@ function parseRDFManifest(aId, aType, aUpdateKey, aRequest) {
if (!cu.IsContainer(ds, updates))
throw new Error("Updates property was not an RDF container");
let checkSecurity = true;
try {
checkSecurity = Services.prefs.getBoolPref("extensions.checkUpdateSecurity");
}
catch (e) {
}
let results = [];
let ctr = Cc["@mozilla.org/rdf/container;1"].
createInstance(Ci.nsIRDFContainer);
@ -399,7 +399,7 @@ function parseRDFManifest(aId, aType, aUpdateKey, aRequest) {
targetApplications: [appEntry]
};
if (result.updateURL && checkSecurity &&
if (result.updateURL && AddonManager.checkUpdateSecurity &&
result.updateURL.substring(0, 6) != "https:" &&
(!result.updateHash || result.updateHash.substring(0, 3) != "sha")) {
WARN("updateLink " + result.updateURL + " is not secure and is not verified" +

View File

@ -64,8 +64,6 @@ const PREF_EM_DSS_ENABLED = "extensions.dss.enabled";
const PREF_DSS_SWITCHPENDING = "extensions.dss.switchPending";
const PREF_DSS_SKIN_TO_SELECT = "extensions.lastSelectedSkin";
const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin";
const PREF_EM_CHECK_COMPATIBILITY_BASE = "extensions.checkCompatibility";
const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
const PREF_EM_UPDATE_URL = "extensions.update.url";
const PREF_EM_ENABLED_ADDONS = "extensions.enabledAddons";
const PREF_EM_EXTENSION_FORMAT = "extensions.";
@ -123,18 +121,8 @@ const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#";
const TOOLKIT_ID = "toolkit@mozilla.org";
const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi;
const DB_SCHEMA = 12;
#ifdef MOZ_COMPATIBILITY_NIGHTLY
const PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE +
".nightly";
#else
const PREF_EM_CHECK_COMPATIBILITY = PREF_EM_CHECK_COMPATIBILITY_BASE + "." +
Services.appinfo.version.replace(BRANCH_REGEXP, "$1");
#endif
// Properties that exist in the install manifest
const PROP_METADATA = ["id", "version", "type", "internalName", "updateURL",
"updateKey", "optionsURL", "optionsType", "aboutURL",
@ -536,13 +524,13 @@ function isUsableAddon(aAddon) {
if (aAddon.blocklistState == Ci.nsIBlocklistService.STATE_BLOCKED)
return false;
if (XPIProvider.checkUpdateSecurity && !aAddon.providesUpdatesSecurely)
if (AddonManager.checkUpdateSecurity && !aAddon.providesUpdatesSecurely)
return false;
if (!aAddon.isPlatformCompatible)
return false;
if (XPIProvider.checkCompatibility) {
if (AddonManager.checkCompatibility) {
if (!aAddon.isCompatible)
return false;
}
@ -1181,7 +1169,7 @@ function escapeAddonURI(aAddon, aUri, aUpdateType, aAppVersion)
uri = uri.replace(/%ITEM_MAXAPPVERSION%/g, maxVersion);
let compatMode = "normal";
if (!XPIProvider.checkCompatibility)
if (!AddonManager.checkCompatibility)
compatMode = "ignore";
else if (AddonManager.strictCompatibility)
compatMode = "strict";
@ -1477,10 +1465,6 @@ var XPIProvider = {
// will be the same as currentSkin when it is the skin to be used when the
// application is restarted
selectedSkin: null,
// The value of the checkCompatibility preference
checkCompatibility: true,
// The value of the checkUpdateSecurity preference
checkUpdateSecurity: true,
// The value of the minCompatibleAppVersion preference
minCompatibleAppVersion: null,
// The value of the minCompatiblePlatformVersion preference
@ -1606,18 +1590,12 @@ var XPIProvider = {
this.selectedSkin = this.currentSkin;
this.applyThemeChange();
this.checkCompatibility = Prefs.getBoolPref(PREF_EM_CHECK_COMPATIBILITY,
true)
this.checkUpdateSecurity = Prefs.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY,
true)
this.minCompatibleAppVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_APP_VERSION,
null);
this.minCompatiblePlatformVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION,
null);
this.enabledAddons = [];
Services.prefs.addObserver(PREF_EM_CHECK_COMPATIBILITY, this, false);
Services.prefs.addObserver(PREF_EM_CHECK_UPDATE_SECURITY, this, false);
Services.prefs.addObserver(PREF_EM_MIN_COMPAT_APP_VERSION, this, false);
Services.prefs.addObserver(PREF_EM_MIN_COMPAT_PLATFORM_VERSION, this, false);
@ -1660,7 +1638,7 @@ var XPIProvider = {
} catch (e) { }
try {
Services.appinfo.annotateCrashReport("EMCheckCompatibility",
this.checkCompatibility);
AddonManager.checkCompatibility);
} catch (e) { }
this.addAddonsToCrashReporter();
}
@ -1699,9 +1677,6 @@ var XPIProvider = {
shutdown: function XPI_shutdown() {
LOG("shutdown");
Services.prefs.removeObserver(PREF_EM_CHECK_COMPATIBILITY, this);
Services.prefs.removeObserver(PREF_EM_CHECK_UPDATE_SECURITY, this);
this.bootstrappedAddons = {};
this.bootstrapScopes = {};
this.enabledAddons = null;
@ -3411,14 +3386,8 @@ var XPIProvider = {
*/
observe: function XPI_observe(aSubject, aTopic, aData) {
switch (aData) {
case PREF_EM_CHECK_COMPATIBILITY:
case PREF_EM_CHECK_UPDATE_SECURITY:
case PREF_EM_MIN_COMPAT_APP_VERSION:
case PREF_EM_MIN_COMPAT_PLATFORM_VERSION:
this.checkCompatibility = Prefs.getBoolPref(PREF_EM_CHECK_COMPATIBILITY,
true);
this.checkUpdateSecurity = Prefs.getBoolPref(PREF_EM_CHECK_UPDATE_SECURITY,
true);
this.minCompatibleAppVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_APP_VERSION,
null);
this.minCompatiblePlatformVersion = Prefs.getCharPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION,
@ -6997,7 +6966,7 @@ UpdateChecker.prototype = {
let ignoreMaxVersion = false;
let ignoreStrictCompat = false;
if (!XPIProvider.checkCompatibility) {
if (!AddonManager.checkCompatibility) {
ignoreMaxVersion = true;
ignoreStrictCompat = true;
} else if (this.addon.type == "extension" &&

View File

@ -52,25 +52,11 @@ Cu.import("resource://gre/modules/AddonRepository.jsm");
const PREF_DISCOVERURL = "extensions.webservice.discoverURL";
const PREF_MAXRESULTS = "extensions.getAddons.maxResults";
const PREF_CHECK_COMPATIBILITY_BASE = "extensions.checkCompatibility";
const PREF_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
const PREF_UPDATE_ENABLED = "extensions.update.enabled";
const PREF_AUTOUPDATE_DEFAULT = "extensions.update.autoUpdateDefault";
const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
const PREF_GETADDONS_CACHE_ID_ENABLED = "extensions.%ID%.getAddons.cache.enabled";
const PREF_UI_TYPE_HIDDEN = "extensions.ui.%TYPE%.hidden";
const PREF_UI_LASTCATEGORY = "extensions.ui.lastCategory";
const BRANCH_REGEXP = /^([^\.]+\.[0-9]+[a-z]*).*/gi;
#ifdef MOZ_COMPATIBILITY_NIGHTLY
const PREF_CHECK_COMPATIBILITY = PREF_CHECK_COMPATIBILITY_BASE +
".nightly";
#else
const PREF_CHECK_COMPATIBILITY = PREF_CHECK_COMPATIBILITY_BASE + "." +
Services.appinfo.version.replace(BRANCH_REGEXP, "$1");
#endif
const LOADING_MSG_DELAY = 100;
const SEARCH_SCORE_MULTIPLIER_NAME = 2;
@ -343,14 +329,11 @@ var gEventManager = {
self.delegateInstallEvent(aEvent, Array.splice(arguments, 0));
};
});
AddonManager.addManagerListener(this);
AddonManager.addInstallListener(this);
AddonManager.addAddonListener(this);
Services.prefs.addObserver(PREF_CHECK_COMPATIBILITY, this, false);
Services.prefs.addObserver(PREF_CHECK_UPDATE_SECURITY, this, false);
Services.prefs.addObserver(PREF_UPDATE_ENABLED, this, false);
Services.prefs.addObserver(PREF_AUTOUPDATE_DEFAULT, this, false);
this.refreshGlobalWarning();
this.refreshAutoUpdateDefault();
@ -375,11 +358,7 @@ var gEventManager = {
},
shutdown: function() {
Services.prefs.removeObserver(PREF_CHECK_COMPATIBILITY, this);
Services.prefs.removeObserver(PREF_CHECK_UPDATE_SECURITY, this);
Services.prefs.removeObserver(PREF_UPDATE_ENABLED, this);
Services.prefs.removeObserver(PREF_AUTOUPDATE_DEFAULT, this);
AddonManager.removeManagerListener(this);
AddonManager.removeInstallListener(this);
AddonManager.removeAddonListener(this);
},
@ -461,25 +440,13 @@ var gEventManager = {
return;
}
var checkUpdateSecurity = true;
var checkUpdateSecurityDefault = true;
try {
checkUpdateSecurity = Services.prefs.getBoolPref(PREF_CHECK_UPDATE_SECURITY);
} catch(e) { }
try {
var defaultBranch = Services.prefs.getDefaultBranch("");
checkUpdateSecurityDefault = defaultBranch.getBoolPref(PREF_CHECK_UPDATE_SECURITY);
} catch(e) { }
if (checkUpdateSecurityDefault && !checkUpdateSecurity) {
if (AddonManager.checkUpdateSecurityDefault &&
!AddonManager.checkUpdateSecurity) {
page.setAttribute("warning", "updatesecurity");
return;
}
var checkCompatibility = true;
try {
checkCompatibility = Services.prefs.getBoolPref(PREF_CHECK_COMPATIBILITY);
} catch(e) { }
if (!checkCompatibility) {
if (!AddonManager.checkCompatibility) {
page.setAttribute("warning", "checkcompatibility");
return;
}
@ -488,12 +455,8 @@ var gEventManager = {
},
refreshAutoUpdateDefault: function() {
var updateEnabled = true;
var autoUpdateDefault = true;
try {
updateEnabled = Services.prefs.getBoolPref(PREF_UPDATE_ENABLED);
autoUpdateDefault = Services.prefs.getBoolPref(PREF_AUTOUPDATE_DEFAULT);
} catch(e) { }
var updateEnabled = AddonManager.updateEnabled;
var autoUpdateDefault = AddonManager.autoUpdateDefault;
// The checkbox needs to reflect that both prefs need to be true
// for updates to be checked for and applied automatically
@ -504,17 +467,16 @@ var gEventManager = {
document.getElementById("utils-resetAddonUpdatesToManual").hidden = autoUpdateDefault;
},
observe: function(aSubject, aTopic, aData) {
switch (aData) {
case PREF_CHECK_COMPATIBILITY:
case PREF_CHECK_UPDATE_SECURITY:
this.refreshGlobalWarning();
break;
case PREF_UPDATE_ENABLED:
case PREF_AUTOUPDATE_DEFAULT:
this.refreshAutoUpdateDefault();
break;
}
onCompatibilityModeChanged: function() {
this.refreshGlobalWarning();
},
onCheckUpdateSecurityChanged: function() {
this.refreshGlobalWarning();
},
onUpdateModeChanged: function() {
this.refreshAutoUpdateDefault();
}
};
@ -742,14 +704,14 @@ var gViewController = {
cmd_enableCheckCompatibility: {
isEnabled: function() true,
doCommand: function() {
Services.prefs.clearUserPref(PREF_CHECK_COMPATIBILITY);
AddonManager.checkCompatibility = true;
}
},
cmd_enableUpdateSecurity: {
isEnabled: function() true,
doCommand: function() {
Services.prefs.clearUserPref(PREF_CHECK_UPDATE_SECURITY);
AddonManager.checkUpdateSecurity = true;
}
},
@ -763,23 +725,16 @@ var gViewController = {
cmd_toggleAutoUpdateDefault: {
isEnabled: function() true,
doCommand: function() {
var updateEnabled = true;
var autoUpdateDefault = true;
try {
updateEnabled = Services.prefs.getBoolPref(PREF_UPDATE_ENABLED);
autoUpdateDefault = Services.prefs.getBoolPref(PREF_AUTOUPDATE_DEFAULT);
} catch(e) { }
if (!updateEnabled || !autoUpdateDefault) {
if (!AddonManager.updateEnabled || !AddonManager.autoUpdateDefault) {
// One or both of the prefs is false, i.e. the checkbox is not checked.
// Now toggle both to true. If the user wants us to auto-update
// add-ons, we also need to auto-check for updates.
Services.prefs.setBoolPref(PREF_UPDATE_ENABLED, true);
Services.prefs.setBoolPref(PREF_AUTOUPDATE_DEFAULT, true);
AddonManager.updateEnabled = true;
AddonManager.autoUpdateDefault = true;
} else {
// Both prefs are true, i.e. the checkbox is checked.
// Toggle the auto pref to false, but don't touch the enabled check.
Services.prefs.setBoolPref(PREF_AUTOUPDATE_DEFAULT, false);
AddonManager.autoUpdateDefault = false;
}
}
},
@ -1823,13 +1778,8 @@ var gDiscoverView = {
this._error = document.getElementById("discover-error");
this._browser = document.getElementById("discover-browser");
let checkCompatibility = true;
try {
checkCompatibility = Services.prefs.getBoolPref(PREF_CHECK_COMPATIBILITY);
} catch(e) { }
let compatMode = "normal";
if (!checkCompatibility)
if (!AddonManager.checkCompatibility)
compatMode = "ignore";
else if (AddonManager.strictCompatibility)
compatMode = "strict";
@ -2553,7 +2503,6 @@ var gDetailView = {
node: null,
_addon: null,
_loadingTimer: null,
_updatePrefs: null,
_autoUpdate: null,
initialize: function() {
@ -2565,23 +2514,18 @@ var gDetailView = {
this._autoUpdate.addEventListener("command", function() {
self._addon.applyBackgroundUpdates = self._autoUpdate.value;
}, true);
this._updatePrefs = Services.prefs.getBranch("extensions.update.");
},
shutdown: function() {
this._updatePrefs.removeObserver("", this);
delete this._updatePrefs;
AddonManager.removeManagerListener(this);
},
observe: function(aSubject, aTopic, aData) {
if (aTopic == "nsPref:changed" && aData == "autoUpdateDefault") {
this.onPropertyChanged(["applyBackgroundUpdates"]);
}
onUpdateModeChanged: function() {
this.onPropertyChanged(["applyBackgroundUpdates"]);
},
_updateView: function(aAddon, aIsRemote, aScrollToPreferences) {
this._updatePrefs.addObserver("", this, false);
AddonManager.addManagerListener(this);
this.clearLoading();
this._addon = aAddon;
@ -2809,7 +2753,7 @@ var gDetailView = {
},
hide: function() {
this._updatePrefs.removeObserver("", this);
AddonManager.removeManagerListener(this);
this.clearLoading();
if (this._addon) {
gEventManager.unregisterAddonListener(this, this._addon.id);

View File

@ -402,8 +402,8 @@ function shutdownManager() {
thr.processNextEvent(false);
}
// Force the XPIProvider provider to reload since it defines some constants on
// load that need to change during tests
// Force the XPIProvider provider to reload to better
// simulate real-world usage.
let scope = Components.utils.import("resource://gre/modules/XPIProvider.jsm");
AddonManagerPrivate.unregisterProvider(scope.XPIProvider);
Components.utils.unload("resource://gre/modules/XPIProvider.jsm");

View File

@ -0,0 +1,212 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests the preference-related properties of AddonManager
// eg: AddonManager.checkCompatibility, AddonManager.updateEnabled, etc
var gManagerEventsListener = {
seenEvents: [],
init: function() {
let events = ["onCompatibilityModeChanged", "onCheckUpdateSecurityChanged",
"onUpdateModeChanged"];
events.forEach(function(aEvent) {
this[aEvent] = function() {
do_print("Saw event " + aEvent);
this.seenEvents.push(aEvent);
}
}, this);
AddonManager.addManagerListener(this);
// Try to add twice, to test that the second time silently fails.
AddonManager.addManagerListener(this);
},
shutdown: function() {
AddonManager.removeManagerListener(this);
},
expect: function(aEvents) {
this.expectedEvents = aEvents;
},
checkExpected: function() {
do_print("Checking expected events...");
while (this.expectedEvents.length > 0) {
let event = this.expectedEvents.pop();
do_print("Looking for expected event " + event);
let matchingEvents = this.seenEvents.filter(function(aSeenEvent) {
return aSeenEvent == event;
});
do_check_eq(matchingEvents.length, 1);
}
this.seenEvents = [];
}
}
function run_test() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
Services.prefs.setBoolPref("extensions.update.enabled", true);
Services.prefs.setBoolPref("extensions.update.autoUpdateDefault", true);
Services.prefs.setBoolPref("extensions.strictCompatibility", true);
Services.prefs.setBoolPref("extensions.checkUpdatesecurity", true);
startupManager();
gManagerEventsListener.init();
// AddonManager.updateEnabled
gManagerEventsListener.expect(["onUpdateModeChanged"]);
AddonManager.updateEnabled = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.updateEnabled);
do_check_false(Services.prefs.getBoolPref("extensions.update.enabled"));
gManagerEventsListener.expect([]);
AddonManager.updateEnabled = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.updateEnabled);
do_check_false(Services.prefs.getBoolPref("extensions.update.enabled"));
gManagerEventsListener.expect(["onUpdateModeChanged"]);
AddonManager.updateEnabled = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.updateEnabled);
do_check_true(Services.prefs.getBoolPref("extensions.update.enabled"));
gManagerEventsListener.expect([]);
AddonManager.updateEnabled = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.updateEnabled);
do_check_true(Services.prefs.getBoolPref("extensions.update.enabled"));
// AddonManager.autoUpdateDefault
gManagerEventsListener.expect(["onUpdateModeChanged"]);
AddonManager.autoUpdateDefault = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.autoUpdateDefault);
do_check_false(Services.prefs.getBoolPref("extensions.update.autoUpdateDefault"));
gManagerEventsListener.expect([]);
AddonManager.autoUpdateDefault = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.autoUpdateDefault);
do_check_false(Services.prefs.getBoolPref("extensions.update.autoUpdateDefault"));
gManagerEventsListener.expect(["onUpdateModeChanged"]);
AddonManager.autoUpdateDefault = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.autoUpdateDefault);
do_check_true(Services.prefs.getBoolPref("extensions.update.autoUpdateDefault"));
gManagerEventsListener.expect([]);
AddonManager.autoUpdateDefault = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.autoUpdateDefault);
do_check_true(Services.prefs.getBoolPref("extensions.update.autoUpdateDefault"));
// AddonManager.strictCompatibility
gManagerEventsListener.expect(["onCompatibilityModeChanged"]);
AddonManager.strictCompatibility = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.strictCompatibility);
do_check_false(Services.prefs.getBoolPref("extensions.strictCompatibility"));
gManagerEventsListener.expect([]);
AddonManager.strictCompatibility = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.strictCompatibility);
do_check_false(Services.prefs.getBoolPref("extensions.strictCompatibility"));
gManagerEventsListener.expect(["onCompatibilityModeChanged"]);
AddonManager.strictCompatibility = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.strictCompatibility);
do_check_true(Services.prefs.getBoolPref("extensions.strictCompatibility"));
gManagerEventsListener.expect([]);
AddonManager.strictCompatibility = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.strictCompatibility);
do_check_true(Services.prefs.getBoolPref("extensions.strictCompatibility"));
// AddonManager.checkCompatibility
var channel = "default";
try {
channel = Services.prefs.getCharPref("app.update.channel");
} catch (e) { }
if (channel != "aurora" &&
channel != "beta" &&
channel != "release") {
var version = "nightly";
} else {
version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
}
const COMPATIBILITY_PREF = "extensions.checkCompatibility." + version;
gManagerEventsListener.expect(["onCompatibilityModeChanged"]);
AddonManager.checkCompatibility = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.checkCompatibility);
do_check_false(Services.prefs.getBoolPref(COMPATIBILITY_PREF));
gManagerEventsListener.expect([]);
AddonManager.checkCompatibility = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.checkCompatibility);
do_check_false(Services.prefs.getBoolPref(COMPATIBILITY_PREF));
gManagerEventsListener.expect(["onCompatibilityModeChanged"]);
AddonManager.checkCompatibility = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.checkCompatibility);
do_check_false(Services.prefs.prefHasUserValue(COMPATIBILITY_PREF));
gManagerEventsListener.expect([]);
AddonManager.checkCompatibility = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.checkCompatibility);
do_check_false(Services.prefs.prefHasUserValue(COMPATIBILITY_PREF));
// AddonManager.checkUpdateSecurity
gManagerEventsListener.expect(["onCheckUpdateSecurityChanged"]);
AddonManager.checkUpdateSecurity = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.checkUpdateSecurity);
if (AddonManager.checkUpdateSecurityDefault)
do_check_false(Services.prefs.getBoolPref("extensions.checkUpdateSecurity"));
else
do_check_false(Services.prefs.prefHasUserValue("extensions.checkUpdateSecurity"));
gManagerEventsListener.expect([]);
AddonManager.checkUpdateSecurity = false;
gManagerEventsListener.checkExpected();
do_check_false(AddonManager.checkUpdateSecurity);
if (AddonManager.checkUpdateSecurityDefault)
do_check_false(Services.prefs.getBoolPref("extensions.checkUpdateSecurity"));
else
do_check_false(Services.prefs.prefHasUserValue("extensions.checkUpdateSecurity"));
gManagerEventsListener.expect(["onCheckUpdateSecurityChanged"]);
AddonManager.checkUpdateSecurity = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.checkUpdateSecurity);
if (!AddonManager.checkUpdateSecurityDefault)
do_check_true(Services.prefs.getBoolPref("extensions.checkUpdateSecurity"));
else
do_check_false(Services.prefs.prefHasUserValue("extensions.checkUpdateSecurity"));
gManagerEventsListener.expect([]);
AddonManager.checkUpdateSecurity = true;
gManagerEventsListener.checkExpected();
do_check_true(AddonManager.checkUpdateSecurity);
if (!AddonManager.checkUpdateSecurityDefault)
do_check_true(Services.prefs.getBoolPref("extensions.checkUpdateSecurity"));
else
do_check_false(Services.prefs.prefHasUserValue("extensions.checkUpdateSecurity"));
gManagerEventsListener.shutdown();
// After removing the listener, ensure we get no further events.
gManagerEventsListener.expect([]);
AddonManager.updateEnabled = false;
gManagerEventsListener.checkExpected();
}

View File

@ -183,6 +183,7 @@ skip-if = os == "android"
[test_plugins.js]
# Bug 676992: test consistently fails on Android
fail-if = os == "android"
[test_pref_properties.js]
[test_registry.js]
[test_safemode.js]
[test_startup.js]