summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps/extensions/LightweightThemeManager.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/mozapps/extensions/LightweightThemeManager.jsm')
-rw-r--r--toolkit/mozapps/extensions/LightweightThemeManager.jsm389
1 files changed, 145 insertions, 244 deletions
diff --git a/toolkit/mozapps/extensions/LightweightThemeManager.jsm b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
index 5dd41831d..5856bfa91 100644
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -11,7 +11,6 @@ const Ci = Components.interfaces;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/AddonManager.jsm");
-/* globals AddonManagerPrivate*/
Components.utils.import("resource://gre/modules/Services.jsm");
const ID_SUFFIX = "@personas.mozilla.org";
@@ -42,31 +41,26 @@ const PERSIST_FILES = {
XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeImageOptimizer",
"resource://gre/modules/addons/LightweightThemeImageOptimizer.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "ServiceRequest",
- "resource://gre/modules/ServiceRequest.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "_prefs", () => {
- return Services.prefs.getBranch("lightweightThemes.");
+this.__defineGetter__("_prefs", function prefsGetter() {
+ delete this._prefs;
+ return this._prefs = Services.prefs.getBranch("lightweightThemes.");
});
-Object.defineProperty(this, "_maxUsedThemes", {
- get: function() {
- delete this._maxUsedThemes;
- try {
- this._maxUsedThemes = _prefs.getIntPref("maxUsedThemes");
- }
- catch (e) {
- this._maxUsedThemes = DEFAULT_MAX_USED_THEMES_COUNT;
- }
- return this._maxUsedThemes;
- },
+this.__defineGetter__("_maxUsedThemes", function maxUsedThemesGetter() {
+ delete this._maxUsedThemes;
+ try {
+ this._maxUsedThemes = _prefs.getIntPref("maxUsedThemes");
+ }
+ catch (e) {
+ this._maxUsedThemes = DEFAULT_MAX_USED_THEMES_COUNT;
+ }
+ return this._maxUsedThemes;
+});
- set: function(val) {
- delete this._maxUsedThemes;
- return this._maxUsedThemes = val;
- },
- configurable: true,
+this.__defineSetter__("_maxUsedThemes", function maxUsedThemesSetter(aVal) {
+ delete this._maxUsedThemes;
+ return this._maxUsedThemes = aVal;
});
// Holds the ID of the theme being enabled or disabled while sending out the
@@ -75,60 +69,25 @@ Object.defineProperty(this, "_maxUsedThemes", {
var _themeIDBeingEnabled = null;
var _themeIDBeingDisabled = null;
-// Convert from the old storage format (in which the order of usedThemes
-// was combined with isThemeSelected to determine which theme was selected)
-// to the new one (where a selectedThemeID determines which theme is selected).
-(function() {
- let wasThemeSelected = false;
- try {
- wasThemeSelected = _prefs.getBoolPref("isThemeSelected");
- } catch (e) { }
-
- if (wasThemeSelected) {
- _prefs.clearUserPref("isThemeSelected");
- let themes = [];
- try {
- themes = JSON.parse(_prefs.getComplexValue("usedThemes",
- Ci.nsISupportsString).data);
- } catch (e) { }
-
- if (Array.isArray(themes) && themes[0]) {
- _prefs.setCharPref("selectedThemeID", themes[0].id);
- }
- }
-})();
-
this.LightweightThemeManager = {
- get name() {
- return "LightweightThemeManager";
- },
-
- // Themes that can be added for an application. They can't be removed, and
- // will always show up at the top of the list.
- _builtInThemes: new Map(),
+ get name() "LightweightThemeManager",
get usedThemes () {
- let themes = [];
try {
- themes = JSON.parse(_prefs.getComplexValue("usedThemes",
- Ci.nsISupportsString).data);
- } catch (e) { }
-
- themes.push(...this._builtInThemes.values());
- return themes;
+ return JSON.parse(_prefs.getComplexValue("usedThemes",
+ Ci.nsISupportsString).data);
+ } catch (e) {
+ return [];
+ }
},
get currentTheme () {
- let selectedThemeID = null;
try {
- selectedThemeID = _prefs.getCharPref("selectedThemeID");
+ if (_prefs.getBoolPref("isThemeSelected"))
+ var data = this.usedThemes[0];
} catch (e) {}
- let data = null;
- if (selectedThemeID) {
- data = this.getUsedTheme(selectedThemeID);
- }
- return data;
+ return data || null;
},
get currentThemeForDisplay () {
@@ -151,11 +110,11 @@ this.LightweightThemeManager = {
return _setCurrentTheme(aData, false);
},
- setLocalTheme: function(aData) {
+ setLocalTheme: function LightweightThemeManager_setLocalTheme(aData) {
_setCurrentTheme(aData, true);
},
- getUsedTheme: function(aId) {
+ getUsedTheme: function LightweightThemeManager_getUsedTheme(aId) {
var usedThemes = this.usedThemes;
for (let usedTheme of usedThemes) {
if (usedTheme.id == aId)
@@ -164,9 +123,9 @@ this.LightweightThemeManager = {
return null;
},
- forgetUsedTheme: function(aId) {
+ forgetUsedTheme: function LightweightThemeManager_forgetUsedTheme(aId) {
let theme = this.getUsedTheme(aId);
- if (!theme || LightweightThemeManager._builtInThemes.has(theme.id))
+ if (!theme)
return;
let wrapper = new AddonWrapper(theme);
@@ -182,35 +141,7 @@ this.LightweightThemeManager = {
AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper);
},
- addBuiltInTheme: function(theme) {
- if (!theme || !theme.id || this.usedThemes.some(t => t.id == theme.id)) {
- throw new Error("Trying to add invalid builtIn theme");
- }
-
- this._builtInThemes.set(theme.id, theme);
-
- if (_prefs.getCharPref("selectedThemeID") == theme.id) {
- this.currentTheme = theme;
- }
- },
-
- forgetBuiltInTheme: function(id) {
- if (!this._builtInThemes.has(id)) {
- let currentTheme = this.currentTheme;
- if (currentTheme && currentTheme.id == id) {
- this.currentTheme = null;
- }
- }
- return this._builtInThemes.delete(id);
- },
-
- clearBuiltInThemes: function() {
- for (let id of this._builtInThemes.keys()) {
- this.forgetBuiltInTheme(id);
- }
- },
-
- previewTheme: function(aData) {
+ previewTheme: function LightweightThemeManager_previewTheme(aData) {
let cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
cancel.data = false;
Services.obs.notifyObservers(cancel, "lightweight-theme-preview-requested",
@@ -229,7 +160,7 @@ this.LightweightThemeManager = {
_notifyWindows(aData);
},
- resetPreview: function() {
+ resetPreview: function LightweightThemeManager_resetPreview() {
if (_previewTimer) {
_previewTimer.cancel();
_previewTimer = null;
@@ -237,7 +168,7 @@ this.LightweightThemeManager = {
}
},
- parseTheme: function(aString, aBaseURI) {
+ parseTheme: function LightweightThemeManager_parseTheme(aString, aBaseURI) {
try {
return _sanitizeTheme(JSON.parse(aString), aBaseURI, false);
} catch (e) {
@@ -245,7 +176,7 @@ this.LightweightThemeManager = {
}
},
- updateCurrentTheme: function() {
+ updateCurrentTheme: function LightweightThemeManager_updateCurrentTheme() {
try {
if (!_prefs.getBoolPref("update.enabled"))
return;
@@ -257,7 +188,8 @@ this.LightweightThemeManager = {
if (!theme || !theme.updateURL)
return;
- var req = new ServiceRequest();
+ var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
+ .createInstance(Ci.nsIXMLHttpRequest);
req.mozBackgroundRequest = true;
req.overrideMimeType("text/plain");
@@ -267,19 +199,20 @@ this.LightweightThemeManager = {
// Prevent the request from writing to the cache.
req.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
- req.addEventListener("load", () => {
+ var self = this;
+ req.addEventListener("load", function loadEventListener() {
if (req.status != 200)
return;
- let newData = this.parseTheme(req.responseText, theme.updateURL);
+ let newData = self.parseTheme(req.responseText, theme.updateURL);
if (!newData ||
newData.id != theme.id ||
_version(newData) == _version(theme))
return;
- var currentTheme = this.currentTheme;
+ var currentTheme = self.currentTheme;
if (currentTheme && currentTheme.id == theme.id)
- this.currentTheme = newData;
+ self.currentTheme = newData;
}, false);
req.send(null);
@@ -291,7 +224,7 @@ this.LightweightThemeManager = {
* @param aData
* The lightweight theme to switch to
*/
- themeChanged: function(aData) {
+ themeChanged: function LightweightThemeManager_themeChanged(aData) {
if (_previewTimer) {
_previewTimer.cancel();
_previewTimer = null;
@@ -303,17 +236,13 @@ this.LightweightThemeManager = {
_updateUsedThemes(usedThemes);
if (PERSIST_ENABLED) {
LightweightThemeImageOptimizer.purge();
- _persistImages(aData, function() {
+ _persistImages(aData, function themeChanged_persistImages() {
_notifyWindows(this.currentThemeForDisplay);
}.bind(this));
}
}
- if (aData)
- _prefs.setCharPref("selectedThemeID", aData.id);
- else
- _prefs.setCharPref("selectedThemeID", "");
-
+ _prefs.setBoolPref("isThemeSelected", aData != null);
_notifyWindows(aData);
Services.obs.notifyObservers(null, "lightweight-theme-changed", null);
},
@@ -322,7 +251,7 @@ this.LightweightThemeManager = {
* Starts the Addons provider and enables the new lightweight theme if
* necessary.
*/
- startup: function() {
+ startup: function LightweightThemeManager_startup() {
if (Services.prefs.prefHasUserValue(PREF_LWTHEME_TO_SELECT)) {
let id = Services.prefs.getCharPref(PREF_LWTHEME_TO_SELECT);
if (id)
@@ -338,7 +267,7 @@ this.LightweightThemeManager = {
/**
* Shuts down the provider.
*/
- shutdown: function() {
+ shutdown: function LightweightThemeManager_shutdown() {
_prefs.removeObserver("", _prefObserver);
},
@@ -354,7 +283,7 @@ this.LightweightThemeManager = {
* true if the newly enabled add-on will only become enabled after a
* restart
*/
- addonChanged: function(aId, aType, aPendingRestart) {
+ addonChanged: function LightweightThemeManager_addonChanged(aId, aType, aPendingRestart) {
if (aType != ADDON_TYPE)
return;
@@ -371,10 +300,12 @@ this.LightweightThemeManager = {
AddonManagerPrivate.callAddonListeners("onOperationCancelled",
new AddonWrapper(this.getUsedTheme(next)));
}
- else if (id == current.id) {
- AddonManagerPrivate.callAddonListeners("onOperationCancelled",
- new AddonWrapper(current));
- return;
+ else {
+ if (id == current.id) {
+ AddonManagerPrivate.callAddonListeners("onOperationCancelled",
+ new AddonWrapper(current));
+ return;
+ }
}
}
catch (e) {
@@ -425,7 +356,7 @@ this.LightweightThemeManager = {
* @param aCallback
* A callback to pass the Addon to
*/
- getAddonByID: function(aId, aCallback) {
+ getAddonByID: function LightweightThemeManager_getAddonByID(aId, aCallback) {
let id = _getInternalID(aId);
if (!id) {
aCallback(null);
@@ -449,70 +380,72 @@ this.LightweightThemeManager = {
* @param aCallback
* A callback to pass an array of Addons to
*/
- getAddonsByTypes: function(aTypes, aCallback) {
+ getAddonsByTypes: function LightweightThemeManager_getAddonsByTypes(aTypes, aCallback) {
if (aTypes && aTypes.indexOf(ADDON_TYPE) == -1) {
aCallback([]);
return;
}
- aCallback(this.usedThemes.map(a => new AddonWrapper(a)));
+ // Tycho: aCallback([new AddonWrapper(a) for each (a in this.usedThemes)]);
+ let result = [];
+ for each(let a in this.usedThemes) {
+ result.push(new AddonWrapper(a));
+ }
+
+ aCallback(result);
},
};
-const wrapperMap = new WeakMap();
-let themeFor = wrapper => wrapperMap.get(wrapper);
-
/**
* The AddonWrapper wraps lightweight theme to provide the data visible to
* consumers of the AddonManager API.
*/
function AddonWrapper(aTheme) {
- wrapperMap.set(this, aTheme);
-}
-
-AddonWrapper.prototype = {
- get id() {
- return themeFor(this).id + ID_SUFFIX;
- },
-
- get type() {
- return ADDON_TYPE;
- },
-
- get isActive() {
+ this.__defineGetter__("id", function AddonWrapper_idGetter() aTheme.id + ID_SUFFIX);
+ this.__defineGetter__("type", function AddonWrapper_typeGetter() ADDON_TYPE);
+ this.__defineGetter__("isActive", function AddonWrapper_isActiveGetter() {
let current = LightweightThemeManager.currentTheme;
if (current)
- return themeFor(this).id == current.id;
+ return aTheme.id == current.id;
return false;
- },
+ });
- get name() {
- return themeFor(this).name;
- },
+ this.__defineGetter__("name", function AddonWrapper_nameGetter() aTheme.name);
+ this.__defineGetter__("version", function AddonWrapper_versionGetter() {
+ return "version" in aTheme ? aTheme.version : "";
+ });
- get version() {
- let theme = themeFor(this);
- return "version" in theme ? theme.version : "";
- },
+ ["description", "homepageURL", "iconURL"].forEach(function(prop) {
+ this.__defineGetter__(prop, function AddonWrapper_optionalPropGetter() {
+ return prop in aTheme ? aTheme[prop] : null;
+ });
+ }, this);
- get creator() {
- let theme = themeFor(this);
- return "author" in theme ? new AddonManagerPrivate.AddonAuthor(theme.author) : null;
- },
+ ["installDate", "updateDate"].forEach(function(prop) {
+ this.__defineGetter__(prop, function AddonWrapper_datePropGetter() {
+ return prop in aTheme ? new Date(aTheme[prop]) : null;
+ });
+ }, this);
- get screenshots() {
- let url = themeFor(this).previewURL;
+ this.__defineGetter__("creator", function AddonWrapper_creatorGetter() {
+ return new AddonManagerPrivate.AddonAuthor(aTheme.author);
+ });
+
+ this.__defineGetter__("screenshots", function AddonWrapper_screenshotsGetter() {
+ let url = aTheme.previewURL;
return [new AddonManagerPrivate.AddonScreenshot(url)];
- },
+ });
- get pendingOperations() {
+ this.__defineGetter__("pendingOperations",
+ function AddonWrapper_pendingOperationsGetter() {
let pending = AddonManager.PENDING_NONE;
if (this.isActive == this.userDisabled)
pending |= this.isActive ? AddonManager.PENDING_DISABLE : AddonManager.PENDING_ENABLE;
return pending;
- },
+ });
- get operationsRequiringRestart() {
+ this.__defineGetter__("operationsRequiringRestart",
+ function AddonWrapper_operationsRequiringRestartGetter() {
// If a non-default theme is in use then a restart will be required to
// enable lightweight themes unless dynamic theme switching is enabled
if (Services.prefs.prefHasUserValue(PREF_GENERAL_SKINS_SELECTEDSKIN)) {
@@ -526,56 +459,65 @@ AddonWrapper.prototype = {
}
return AddonManager.OP_NEEDS_RESTART_NONE;
- },
+ });
- get size() {
+ this.__defineGetter__("size", function AddonWrapper_sizeGetter() {
// The size changes depending on whether the theme is in use or not, this is
// probably not worth exposing.
return null;
- },
-
- get permissions() {
- let permissions = 0;
+ });
- // Do not allow uninstall of builtIn themes.
- if (!LightweightThemeManager._builtInThemes.has(themeFor(this).id))
- permissions = AddonManager.PERM_CAN_UNINSTALL;
+ this.__defineGetter__("permissions", function AddonWrapper_permissionsGetter() {
+ let permissions = AddonManager.PERM_CAN_UNINSTALL;
if (this.userDisabled)
permissions |= AddonManager.PERM_CAN_ENABLE;
else
permissions |= AddonManager.PERM_CAN_DISABLE;
return permissions;
- },
+ });
- get userDisabled() {
- let id = themeFor(this).id;
- if (_themeIDBeingEnabled == id)
+ this.__defineGetter__("userDisabled", function AddonWrapper_userDisabledGetter() {
+ if (_themeIDBeingEnabled == aTheme.id)
return false;
- if (_themeIDBeingDisabled == id)
+ if (_themeIDBeingDisabled == aTheme.id)
return true;
try {
let toSelect = Services.prefs.getCharPref(PREF_LWTHEME_TO_SELECT);
- return id != toSelect;
+ return aTheme.id != toSelect;
}
catch (e) {
let current = LightweightThemeManager.currentTheme;
- return !current || current.id != id;
+ return !current || current.id != aTheme.id;
}
- },
+ });
- set userDisabled(val) {
+ this.__defineSetter__("userDisabled", function AddonWrapper_userDisabledSetter(val) {
if (val == this.userDisabled)
return val;
if (val)
LightweightThemeManager.currentTheme = null;
else
- LightweightThemeManager.currentTheme = themeFor(this);
+ LightweightThemeManager.currentTheme = aTheme;
return val;
- },
+ });
+
+ this.uninstall = function AddonWrapper_uninstall() {
+ LightweightThemeManager.forgetUsedTheme(aTheme.id);
+ };
+
+ this.cancelUninstall = function AddonWrapper_cancelUninstall() {
+ throw new Error("Theme is not marked to be uninstalled");
+ };
+
+ this.findUpdates = function AddonWrapper_findUpdates(listener, reason, appVersion, platformVersion) {
+ AddonManagerPrivate.callNoUpdateListeners(this, listener, reason, appVersion, platformVersion);
+ };
+}
+AddonWrapper.prototype = {
// Lightweight themes are never disabled by the application
get appDisabled() {
return false;
@@ -598,20 +540,8 @@ AddonWrapper.prototype = {
return false;
},
- uninstall: function() {
- LightweightThemeManager.forgetUsedTheme(themeFor(this).id);
- },
-
- cancelUninstall: function() {
- throw new Error("Theme is not marked to be uninstalled");
- },
-
- findUpdates: function(listener, reason, appVersion, platformVersion) {
- AddonManagerPrivate.callNoUpdateListeners(this, listener, reason, appVersion, platformVersion);
- },
-
// Lightweight themes are always compatible
- isCompatibleWith: function(appVersion, platformVersion) {
+ isCompatibleWith: function AddonWrapper_isCompatibleWith(appVersion, platformVersion) {
return true;
},
@@ -626,26 +556,6 @@ AddonWrapper.prototype = {
}
};
-["description", "homepageURL", "iconURL"].forEach(function(prop) {
- Object.defineProperty(AddonWrapper.prototype, prop, {
- get: function() {
- let theme = themeFor(this);
- return prop in theme ? theme[prop] : null;
- },
- enumarable: true,
- });
-});
-
-["installDate", "updateDate"].forEach(function(prop) {
- Object.defineProperty(AddonWrapper.prototype, prop, {
- get: function() {
- let theme = themeFor(this);
- return prop in theme ? new Date(theme[prop]) : null;
- },
- enumarable: true,
- });
-});
-
/**
* Converts the ID used by the public AddonManager API to an lightweight theme
* ID.
@@ -702,7 +612,7 @@ function _setCurrentTheme(aData, aLocal) {
_updateUsedThemes(usedThemes);
if (isInstall)
- AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
+ AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
}
if (cancel.data)
@@ -764,24 +674,17 @@ function _sanitizeTheme(aData, aBaseURI, aLocal) {
return result;
}
-function _usedThemesExceptId(aId) {
- return LightweightThemeManager.usedThemes.filter(function(t) {
- return "id" in t && t.id != aId;
- });
-}
+function _usedThemesExceptId(aId)
+ LightweightThemeManager.usedThemes.filter(
+ function usedThemesExceptId_filterID(t) "id" in t && t.id != aId);
-function _version(aThemeData) {
- return aThemeData.version || "";
-}
+function _version(aThemeData)
+ aThemeData.version || "";
-function _makeURI(aURL, aBaseURI) {
- return Services.io.newURI(aURL, null, aBaseURI);
-}
+function _makeURI(aURL, aBaseURI)
+ Services.io.newURI(aURL, null, aBaseURI);
function _updateUsedThemes(aList) {
- // Remove app-specific themes before saving them to the usedThemes pref.
- aList = aList.filter(theme => !LightweightThemeManager._builtInThemes.has(theme.id));
-
// Send uninstall events for all themes that need to be removed.
while (aList.length > _maxUsedThemes) {
let wrapper = new AddonWrapper(aList[aList.length - 1]);
@@ -805,7 +708,7 @@ function _notifyWindows(aThemeData) {
var _previewTimer;
var _previewTimerCallback = {
- notify: function() {
+ notify: function _previewTimerCallback_notify() {
LightweightThemeManager.resetPreview();
}
};
@@ -829,17 +732,15 @@ function _prefObserver(aSubject, aTopic, aData) {
}
function _persistImages(aData, aCallback) {
- function onSuccess(key) {
- return function () {
- let current = LightweightThemeManager.currentTheme;
- if (current && current.id == aData.id) {
- _prefs.setBoolPref("persisted." + key, true);
- }
- if (--numFilesToPersist == 0 && aCallback) {
- aCallback();
- }
- };
- }
+ function onSuccess(key) function () {
+ let current = LightweightThemeManager.currentTheme;
+ if (current && current.id == aData.id) {
+ _prefs.setBoolPref("persisted." + key, true);
+ }
+ if (--numFilesToPersist == 0 && aCallback) {
+ aCallback();
+ }
+ };
let numFilesToPersist = 0;
for (let key in PERSIST_FILES) {
@@ -882,11 +783,11 @@ function _persistImage(sourceURL, localFileName, successCallback) {
}
function _persistProgressListener(successCallback) {
- this.onLocationChange = function() {};
- this.onProgressChange = function() {};
- this.onStatusChange = function() {};
- this.onSecurityChange = function() {};
- this.onStateChange = function(aWebProgress, aRequest, aStateFlags, aStatus) {
+ this.onLocationChange = function persistProgressListener_onLocationChange() {};
+ this.onProgressChange = function persistProgressListener_onProgressChange() {};
+ this.onStatusChange = function persistProgressListener_onStatusChange() {};
+ this.onSecurityChange = function persistProgressListener_onSecurityChange() {};
+ this.onStateChange = function persistProgressListener_onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
if (aRequest &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {