Bug 1094821 - Make it possible for an application to load extra themes into LightweightThemeManager.usedThemes;r=Gijs

When calling addBuiltInTheme, theme objects are stored in a Map keyed on ID
and are appended onto the usedThemes array.  These aren't removeable and don't
get stored in the pref.
This commit is contained in:
Brian Grinstead 2015-03-23 15:32:43 -07:00
Родитель ac897bf890
Коммит 892a74f728
2 изменённых файлов: 133 добавлений и 12 удалений

Просмотреть файл

@ -95,13 +95,19 @@ var _themeIDBeingDisabled = null;
this.LightweightThemeManager = {
get name() "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 usedThemes () {
let themes = [];
try {
return JSON.parse(_prefs.getComplexValue("usedThemes",
Ci.nsISupportsString).data);
} catch (e) {
return [];
}
themes = JSON.parse(_prefs.getComplexValue("usedThemes",
Ci.nsISupportsString).data);
} catch (e) { }
themes.push(...this._builtInThemes.values());
return themes;
},
get currentTheme () {
@ -152,7 +158,7 @@ this.LightweightThemeManager = {
forgetUsedTheme: function LightweightThemeManager_forgetUsedTheme(aId) {
let theme = this.getUsedTheme(aId);
if (!theme)
if (!theme || LightweightThemeManager._builtInThemes.has(theme.id))
return;
let wrapper = new AddonWrapper(theme);
@ -168,6 +174,30 @@ this.LightweightThemeManager = {
AddonManagerPrivate.callAddonListeners("onUninstalled", wrapper);
},
addBuiltInTheme: function LightweightThemeManager_addBuiltInTheme(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);
},
forgetBuiltInTheme: function LightweightThemeManager_forgetBuiltInTheme(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 LightweightThemeManager_clearBuiltInThemes() {
for (let id of this._builtInThemes.keys()) {
this.forgetBuiltInTheme(id);
}
},
previewTheme: function LightweightThemeManager_previewTheme(aData) {
let cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
cancel.data = false;
@ -493,7 +523,11 @@ function AddonWrapper(aTheme) {
});
this.__defineGetter__("permissions", function AddonWrapper_permissionsGetter() {
let permissions = AddonManager.PERM_CAN_UNINSTALL;
let permissions = 0;
// Do not allow uninstall of builtIn themes.
if (!LightweightThemeManager._builtInThemes.has(aTheme.id))
permissions = AddonManager.PERM_CAN_UNINSTALL;
if (this.userDisabled)
permissions |= AddonManager.PERM_CAN_ENABLE;
else
@ -710,6 +744,9 @@ 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]);

Просмотреть файл

@ -19,18 +19,20 @@ function dummy(id) {
};
}
function hasPermission(aAddon, aPerm) {
var perm = AddonManager["PERM_CAN_" + aPerm.toUpperCase()];
return !!(aAddon.permissions & perm);
}
function run_test() {
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9");
startupManager();
Services.prefs.setIntPref("lightweightThemes.maxUsedThemes", 8);
var temp = {};
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", temp);
do_check_eq(typeof temp.LightweightThemeManager, "object");
var ltm = temp.LightweightThemeManager;
let {LightweightThemeManager: ltm} = Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", {});
do_check_eq(typeof ltm, "object");
do_check_eq(typeof ltm.usedThemes, "object");
do_check_eq(ltm.usedThemes.length, 0);
do_check_eq(ltm.currentTheme, null);
@ -511,4 +513,86 @@ function run_test() {
Services.prefs.clearUserPref("lightweightThemes.maxUsedThemes");
do_check_eq(ltm.usedThemes.length, 30);
let usedThemes = ltm.usedThemes;
for (let theme of usedThemes) {
ltm.forgetUsedTheme(theme.id);
}
// Check builtInTheme functionality for Bug 1094821
do_check_eq(ltm._builtInThemes.toString(), "[object Map]");
do_check_eq([...ltm._builtInThemes.entries()].length, 0);
do_check_eq(ltm.usedThemes.length, 0);
ltm.addBuiltInTheme(dummy("builtInTheme0"));
do_check_eq([...ltm._builtInThemes].length, 1);
do_check_eq(ltm.usedThemes.length, 1);
do_check_eq(ltm.usedThemes[0].id, "builtInTheme0");
ltm.addBuiltInTheme(dummy("builtInTheme1"));
do_check_eq([...ltm._builtInThemes].length, 2);
do_check_eq(ltm.usedThemes.length, 2);
do_check_eq(ltm.usedThemes[1].id, "builtInTheme1");
// Clear all and then re-add
ltm.clearBuiltInThemes();
do_check_eq([...ltm._builtInThemes].length, 0);
do_check_eq(ltm.usedThemes.length, 0);
ltm.addBuiltInTheme(dummy("builtInTheme0"));
ltm.addBuiltInTheme(dummy("builtInTheme1"));
do_check_eq([...ltm._builtInThemes].length, 2);
do_check_eq(ltm.usedThemes.length, 2);
do_test_pending();
AddonManager.getAddonByID("builtInTheme0@personas.mozilla.org", aAddon => {
// App specific theme can't be uninstalled or disabled,
// but can be enabled (since it isn't already applied).
do_check_eq(hasPermission(aAddon, "uninstall"), false);
do_check_eq(hasPermission(aAddon, "disable"), false);
do_check_eq(hasPermission(aAddon, "enable"), true);
ltm.currentTheme = dummy("x0");
do_check_eq([...ltm._builtInThemes].length, 2);
do_check_eq(ltm.usedThemes.length, 3);
do_check_eq(ltm.usedThemes[0].id, "x0");
do_check_eq(ltm.currentTheme.id, "x0");
do_check_eq(ltm.usedThemes[1].id, "builtInTheme0");
do_check_eq(ltm.usedThemes[2].id, "builtInTheme1");
Assert.throws(() => { ltm.addBuiltInTheme(dummy("builtInTheme0")) },
"Exception is thrown adding a duplicate theme");
Assert.throws(() => { ltm.addBuiltInTheme("not a theme object") },
"Exception is thrown adding an invalid theme");
AddonManager.getAddonByID("x0@personas.mozilla.org", aAddon => {
// Currently applied (non-app-specific) can be uninstalled or disabled,
// but can't be enabled (since it's already applied).
do_check_eq(hasPermission(aAddon, "uninstall"), true);
do_check_eq(hasPermission(aAddon, "disable"), true);
do_check_eq(hasPermission(aAddon, "enable"), false);
ltm.forgetUsedTheme("x0");
do_check_eq(ltm.currentTheme, null);
// Removing the currently applied app specific theme should unapply it
ltm.currentTheme = ltm.getUsedTheme("builtInTheme0");
do_check_eq(ltm.currentTheme.id, "builtInTheme0");
do_check_true(ltm.forgetBuiltInTheme("builtInTheme0"));
do_check_eq(ltm.currentTheme, null);
do_check_eq([...ltm._builtInThemes].length, 1);
do_check_eq(ltm.usedThemes.length, 1);
do_check_true(ltm.forgetBuiltInTheme("builtInTheme1"));
do_check_false(ltm.forgetBuiltInTheme("not-an-existing-theme-id"));
do_check_eq([...ltm._builtInThemes].length, 0);
do_check_eq(ltm.usedThemes.length, 0);
do_check_eq(ltm.currentTheme, null);
do_test_finished();
});
});
}