Bug 510909: Integrate most recently used lightweight themes into the themes list in the add-ons manager. r=robstrong, r=dao

This commit is contained in:
Dave Townsend 2009-09-17 10:03:33 +01:00
parent 976f60e4ce
commit 5c1da30332
11 changed files with 612 additions and 59 deletions

View File

@ -62,9 +62,13 @@ function init()
// Version
var versionArc = rdfs.GetResource(EM_NS("version"));
var version = gExtensionDB.GetTarget(extension, versionArc, true);
version = version.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
if (version)
version = version.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
// Description
var descriptionArc = rdfs.GetResource(EM_NS("description"));
if (gExtensionDB.hasArcOut(extension, rdfs.GetResource(EM_NS("lwtheme"))))
var descriptionArc = rdfs.GetResource(EM_NS("lwdescription"));
else
descriptionArc = rdfs.GetResource(EM_NS("description"));
var description = gExtensionDB.GetTarget(extension, descriptionArc, true);
if (description)
description = description.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
@ -96,10 +100,16 @@ function init()
var extensionName = document.getElementById("extensionName");
extensionName.setAttribute("value", name);
var extensionVersion = document.getElementById("extensionVersion");
extensionVersion.setAttribute("value", extensionsStrings.getFormattedString("aboutWindowVersionString", [version]));
if (version)
extensionVersion.setAttribute("value", extensionsStrings.getFormattedString("aboutWindowVersionString", [version]));
else
extensionVersion.hidden = true;
var extensionDescription = document.getElementById("extensionDescription");
extensionDescription.appendChild(document.createTextNode(description));
if (description)
extensionDescription.appendChild(document.createTextNode(description));
else
extensionDescription.hidden = true;
var extensionCreator = document.getElementById("extensionCreator");
extensionCreator.setAttribute("value", creator);

View File

@ -52,8 +52,6 @@ var gView = null;
var gExtensionManager = null;
var gExtensionsView = null;
var gExtensionStrings = null;
var gCurrentTheme = "classic/1.0";
var gDefaultTheme = "classic/1.0";
var gDownloadManager = null;
var gObserverIndex = -1;
var gInSafeMode = false;
@ -68,6 +66,7 @@ var gPendingActions = false;
var gPlugins = null;
var gPluginsDS = null;
var gSearchDS = null;
var gLWThemeDS = null;
var gAddonRepository = null;
var gShowGetAddonsPane = false;
var gRetrievedResults = false;
@ -76,6 +75,20 @@ var gRDF = null;
var gPendingInstalls = {};
var gNewAddons = [];
// The default heavyweight theme for the app.
var gDefaultTheme = null;
// The heavyweight theme currently in use.
var gCurrentTheme = null;
// The heavyweight theme to switch to after the application is restarted.
// This will be equal to gCurrentTheme if no theme change is pending.
var gThemeToSelect = null;
// The lightweight theme to switch to after the application is restarted.
// This will be equal to LightweightThemeManager.currentTheme if no lightweight
// theme change is pending or null if lightweight theme should be turned off
// after the restart.
var gLWThemeToSelect = null;
const PREF_EM_CHECK_COMPATIBILITY = "extensions.checkCompatibility";
const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
const PREF_EXTENSIONS_GETMORETHEMESURL = "extensions.getMoreThemesURL";
@ -85,6 +98,7 @@ const PREF_EXTENSIONS_DSS_ENABLED = "extensions.dss.enabled";
const PREF_EXTENSIONS_DSS_SWITCHPENDING = "extensions.dss.switchPending";
const PREF_EXTENSIONS_HIDE_INSTALL_BTN = "extensions.hideInstallButton";
const PREF_DSS_SKIN_TO_SELECT = "extensions.lastSelectedSkin";
const PREF_LWTHEME_TO_SELECT = "extensions.lwThemeToSelect";
const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin";
const PREF_UPDATE_NOTIFYUSER = "extensions.update.notifyUser";
const PREF_GETADDONS_SHOWPANE = "extensions.getAddons.showPane";
@ -104,6 +118,7 @@ const URI_NOTIFICATION_ICON_WARNING = "chrome://global/skin/icons/warning-16.p
const RDFURI_ITEM_ROOT = "urn:mozilla:item:root";
const PREFIX_ITEM_URI = "urn:mozilla:item:";
const PREFIX_LWTHEME_URI = "urn:mozilla:lwtheme:";
const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#";
const kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml"
@ -117,6 +132,7 @@ const OP_NEEDS_DISABLE = "needs-disable";
Components.utils.import("resource://gre/modules/PluralForm.jsm");
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm");
///////////////////////////////////////////////////////////////////////////////
// Utility Functions
@ -143,6 +159,12 @@ function getItemForInternalName(aInternalName) {
return null;
}
function getActivedThemeItem() {
if (gLWThemeToSelect)
return document.getElementById(PREFIX_LWTHEME_URI + gLWThemeToSelect.id);
return getItemForInternalName(gThemeToSelect);
}
function isSafeURI(aURI) {
try {
var uri = makeURI(aURI);
@ -308,6 +330,7 @@ function showView(aView) {
["iconURL", "?iconURL"],
["internalName", "?internalName"],
["locked", "?locked"],
["lwtheme", "?lwtheme"],
["name", "?name"],
["optionsURL", "?optionsURL"],
["opType", "?opType"],
@ -483,7 +506,7 @@ function showView(aView) {
if (aView == "updates" || aView == "installs")
gExtensionsView.selectedItem = gExtensionsView.children[0];
else if (isThemes)
gExtensionsView.selectedItem = getItemForInternalName(gCurrentTheme);
gExtensionsView.selectedItem = getActivedThemeItem();
if (showSkip) {
var button = document.getElementById("installUpdatesAllButton");
@ -530,10 +553,6 @@ function updateLastSelected(aView) {
viewGroup.setAttribute("last-selected", aView);
}
function LOG(msg) {
dump("*** " + msg + "\n");
}
function getIDFromResourceURI(aURI)
{
if (aURI.substring(0, PREFIX_ITEM_URI.length) == PREFIX_ITEM_URI)
@ -868,6 +887,100 @@ function initSearchDS() {
retrieveRepositoryAddons(document.getElementById("searchfield").value);
}
function initLWThemeDS() {
gLWThemeDS = Components.classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"]
.createInstance(Components.interfaces.nsIRDFDataSource);
rebuildLWThemeDS();
}
function rebuildLWThemeDS() {
var rdfCU = Components.classes["@mozilla.org/rdf/container-utils;1"]
.getService(Components.interfaces.nsIRDFContainerUtils);
var rootctr = rdfCU.MakeSeq(gLWThemeDS, gRDF.GetResource(RDFURI_ITEM_ROOT));
var themes = LightweightThemeManager.usedThemes;
// Running in a batch stops the template builder from running
gLWThemeDS.beginUpdateBatch();
cleanDataSource(gLWThemeDS, rootctr);
for (var i = 0; i < themes.length; i++) {
var theme = themes[i];
var themeNode = gRDF.GetResource(PREFIX_LWTHEME_URI + theme.id);
rootctr.AppendElement(themeNode);
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "name"),
gRDF.GetLiteral(theme.name),
true);
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "addonID"),
gRDF.GetLiteral(theme.id),
true);
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "isDisabled"),
gRDF.GetLiteral("false"),
true);
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "blocklisted"),
gRDF.GetLiteral("false"),
true);
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "blocklistedsoft"),
gRDF.GetLiteral("false"),
true);
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "compatible"),
gRDF.GetLiteral("true"),
true);
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "lwtheme"),
gRDF.GetLiteral("true"),
true);
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "type"),
gRDF.GetIntLiteral(nsIUpdateItem.TYPE_THEME),
true);
if (theme.author) {
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "description"),
gRDF.GetLiteral(getExtensionString("lightweightThemeDescription",
[theme.author])),
true);
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "creator"),
gRDF.GetLiteral(theme.author),
true);
}
if (theme.description) {
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "lwdescription"),
gRDF.GetLiteral(theme.description),
true);
}
if (theme.homepageURL) {
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "homepageURL"),
gRDF.GetLiteral(theme.homepageURL),
true);
}
if (theme.previewURL) {
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "previewImage"),
gRDF.GetLiteral(theme.previewURL),
true);
}
if (theme.iconURL) {
gLWThemeDS.Assert(themeNode,
gRDF.GetResource(PREFIX_NS_EM + "iconURL"),
gRDF.GetLiteral(theme.iconURL),
true);
}
}
gLWThemeDS.endUpdateBatch();
}
function initPluginsDS()
{
gPluginsDS = Components.classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"]
@ -998,13 +1111,24 @@ function Startup()
var defaultPref = gPref.QueryInterface(Components.interfaces.nsIPrefService)
.getDefaultBranch(null);
try {
gCurrentTheme = gPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
gThemeToSelect = gCurrentTheme = gPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
gDefaultTheme = defaultPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
if (gPref.getBoolPref(PREF_EXTENSIONS_DSS_SWITCHPENDING))
gCurrentTheme = gPref.getCharPref(PREF_DSS_SKIN_TO_SELECT);
gThemeToSelect = gPref.getCharPref(PREF_DSS_SKIN_TO_SELECT);
}
catch (e) { }
if (gPref.prefHasUserValue(PREF_LWTHEME_TO_SELECT)) {
var id = gPref.getCharPref(PREF_LWTHEME_TO_SELECT);
if (id)
gLWThemeToSelect = LightweightThemeManager.getUsedTheme(id);
else
gLWThemeToSelect = null;
}
else {
gLWThemeToSelect = LightweightThemeManager.currentTheme;
}
gExtensionsView = document.getElementById("extensionsView");
gExtensionManager = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(nsIExtensionManager);
@ -1038,6 +1162,8 @@ function Startup()
initPluginsDS();
gExtensionsView.database.AddDataSource(gPluginsDS);
initLWThemeDS();
gExtensionsView.database.AddDataSource(gLWThemeDS);
if (gShowGetAddonsPane)
initSearchDS();
gExtensionsView.database.AddDataSource(gExtensionManager.datasource);
@ -1058,6 +1184,8 @@ function Startup()
os.addObserver(gDownloadManager, "xpinstall-download-started", false);
os.addObserver(gAddonsMsgObserver, "addons-message-notification", false);
os.addObserver(gPluginObserver, "plugins-list-updated", false);
os.addObserver(gLWThemeObserver, "lightweight-theme-list-changed", false);
os.addObserver(gLWThemeObserver, "lightweight-theme-changed", false);
gObserverIndex = gExtensionManager.addInstallListener(gDownloadManager);
@ -1236,6 +1364,8 @@ function Shutdown()
os.removeObserver(gAddonsMsgObserver, "addons-message-notification");
os.removeObserver(gDownloadManager, "xpinstall-download-started");
os.removeObserver(gPluginObserver, "plugins-list-updated");
os.removeObserver(gLWThemeObserver, "lightweight-theme-list-changed");
os.removeObserver(gLWThemeObserver, "lightweight-theme-changed");
var currentNotification = document.getElementById("addonsMsg").currentNotification;
if (currentNotification && currentNotification.value == "addons-no-updates")
window.removeEventListener("select", noUpdatesDismiss, true);
@ -1257,7 +1387,7 @@ var TemplateBuilderListener = {
if (gView == "themes") {
if (gPref.getBoolPref(PREF_EXTENSIONS_DSS_SWITCHPENDING)) {
var item = getItemForInternalName(gCurrentTheme);
var item = getActivedThemeItem();
if (item)
setRestartMessage(item);
}
@ -1636,6 +1766,13 @@ function onAddonSelect(aEvent)
}
}
function onPreviewImageError(aEvent) {
var previewImageDeck = document.getElementById("previewImageDeck");
var previewImage = document.getElementById("previewImage");
previewImageDeck.selectedIndex = 1;
previewImage.removeAttribute("src");
}
/**
* Manages the retrieval of update information and the xsl stylesheet
* used to format the inforation into chrome.
@ -2037,14 +2174,14 @@ const gPrefObserver = {
{
if (aData == PREF_GENERAL_SKINS_SELECTEDSKIN) {
// Changed as the result of a dynamic theme switch
gCurrentTheme = gPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
gThemeToSelect = gPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
}
else if (aData == PREF_DSS_SKIN_TO_SELECT) {
// Either a new skin has been selected or the switch has been cancelled
if (gPref.getBoolPref(PREF_EXTENSIONS_DSS_SWITCHPENDING))
gCurrentTheme = gPref.getCharPref(PREF_DSS_SKIN_TO_SELECT);
gThemeToSelect = gPref.getCharPref(PREF_DSS_SKIN_TO_SELECT);
else
gCurrentTheme = gPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
gThemeToSelect = gPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
updateOptionalViews();
updateGlobalCommands();
}
@ -2058,6 +2195,18 @@ const gPluginObserver = {
}
};
const gLWThemeObserver = {
observe: function (aSubject, aTopic, aData) {
if (aTopic == "lightweight-theme-list-changed") {
rebuildLWThemeDS();
}
else if (aTopic == "lightweight-theme-changed") {
gLWThemeToSelect = LightweightThemeManager.currentTheme;
gPref.clearUserPref(PREF_LWTHEME_TO_SELECT);
}
}
};
function isXPInstallEnabled() {
var enabled = false;
var locked = false;
@ -2444,10 +2593,14 @@ var gExtensionsViewController = {
return selectedItem.getAttribute("action") == "" ||
selectedItem.getAttribute("action") == "failed";
case "cmd_useTheme":
if (selectedItem.hasAttribute("lwtheme"))
return !gLWThemeToSelect ||
selectedItem.getAttribute("addonID") != gLWThemeToSelect.id;
return selectedItem.type == nsIUpdateItem.TYPE_THEME &&
!selectedItem.isDisabled &&
selectedItem.opType != OP_NEEDS_UNINSTALL &&
gCurrentTheme != selectedItem.getAttribute("internalName");
(gLWThemeToSelect ||
gThemeToSelect != selectedItem.getAttribute("internalName"));
case "cmd_options":
return selectedItem.type == nsIUpdateItem.TYPE_EXTENSION &&
!selectedItem.isDisabled &&
@ -2460,6 +2613,8 @@ var gExtensionsViewController = {
case "cmd_homepage":
return selectedItem.getAttribute("homepageURL") != "";
case "cmd_uninstall":
if (selectedItem.hasAttribute("lwtheme"))
return true;
return (selectedItem.type != nsIUpdateItem.TYPE_THEME ||
selectedItem.type == nsIUpdateItem.TYPE_THEME &&
selectedItem.getAttribute("internalName") != gDefaultTheme) &&
@ -2574,29 +2729,46 @@ var gExtensionsViewController = {
cmd_useTheme: function (aSelectedItem)
{
gCurrentTheme = aSelectedItem.getAttribute("internalName");
if (aSelectedItem.hasAttribute("lwtheme")) {
let newTheme = LightweightThemeManager.getUsedTheme(aSelectedItem.getAttribute("addonID"));
LightweightThemeManager.currentTheme = gLWThemeToSelect = newTheme;
// If choosing the current skin just reset the pending change
if (gCurrentTheme == gPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN)) {
gPref.clearUserPref(PREF_EXTENSIONS_DSS_SWITCHPENDING);
gPref.clearUserPref(PREF_DSS_SKIN_TO_SELECT);
clearRestartMessage();
}
else {
if (gPref.getBoolPref(PREF_EXTENSIONS_DSS_ENABLED)) {
gPref.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, gCurrentTheme);
}
else {
// Theme change will happen on next startup, this flag tells
// the Theme Manager that it needs to show "This theme will
// be selected after a restart" text in the selected theme
// item.
gPref.setBoolPref(PREF_EXTENSIONS_DSS_SWITCHPENDING, true);
gPref.setCharPref(PREF_DSS_SKIN_TO_SELECT, gCurrentTheme);
if (gPref.prefHasUserValue(PREF_LWTHEME_TO_SELECT)) {
clearRestartMessage();
setRestartMessage(aSelectedItem);
}
}
else {
gThemeToSelect = aSelectedItem.getAttribute("internalName");
// If choosing the current skin just reset the pending change
if (gThemeToSelect == gCurrentTheme) {
gPref.clearUserPref(PREF_EXTENSIONS_DSS_SWITCHPENDING);
gPref.clearUserPref(PREF_DSS_SKIN_TO_SELECT);
gLWThemeToSelect = LightweightThemeManager.currentTheme = null;
clearRestartMessage();
}
else {
if (gPref.getBoolPref(PREF_EXTENSIONS_DSS_ENABLED)) {
gPref.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, gThemeToSelect);
gLWThemeToSelect = LightweightThemeManager.currentTheme = null;
}
else {
// Theme change will happen on next startup, this flag tells
// the Theme Manager that it needs to show "This theme will
// be selected after a restart" text in the selected theme
// item.
gPref.setBoolPref(PREF_EXTENSIONS_DSS_SWITCHPENDING, true);
gPref.setCharPref(PREF_DSS_SKIN_TO_SELECT, gThemeToSelect);
if (gLWThemeToSelect) {
gLWThemeToSelect = null;
gPref.setCharPref(PREF_LWTHEME_TO_SELECT, "");
}
clearRestartMessage();
setRestartMessage(aSelectedItem);
}
}
}
// Flush preference change to disk
gPref.QueryInterface(Components.interfaces.nsIPrefService)
@ -2698,18 +2870,31 @@ var gExtensionsViewController = {
{
// Confirm the uninstall
var name = aSelectedItem.getAttribute("name");
var id = getIDFromResourceURI(aSelectedItem.id);
var dependentItems = gExtensionManager.getDependentItemListForID(id, true, { });
var dependentItems = [];
if (!aSelectedItem.hasAttribute("lwtheme")) {
var id = getIDFromResourceURI(aSelectedItem.id);
dependentItems = gExtensionManager.getDependentItemListForID(id, true, { });
}
var result = confirmOperation(name, "uninstallTitle", "uninstallQueryMessage",
"uninstallButton", "cancelButton",
"uninstallWarnDependMsg", dependentItems);
if (!result)
return;
if (aSelectedItem.hasAttribute("lwtheme")) {
let lwid = aSelectedItem.getAttribute("addonID");
LightweightThemeManager.forgetUsedTheme(lwid);
if (gLWThemeToSelect && lwid == gLWThemeToSelect.id) {
gLWThemeToSelect = LightweightThemeManager.currentTheme;
gPref.clearUserPref(PREF_LWTHEME_TO_SELECT);
}
return;
}
if (aSelectedItem.type == nsIUpdateItem.TYPE_THEME) {
var theme = aSelectedItem.getAttribute("internalName");
var selectedTheme = gPref.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
if (theme == gCurrentTheme) {
if (theme == gThemeToSelect) {
if (gPref.getBoolPref(PREF_EXTENSIONS_DSS_SWITCHPENDING)) {
var item = getItemForInternalName(selectedTheme);
if (item && item.getAttribute("opType") == OP_NEEDS_UNINSTALL) {

View File

@ -214,7 +214,7 @@
</vbox>
<vbox id="previewImageContainer" align="center" pack="center">
<hbox>
<image id="previewImage"/>
<image id="previewImage" onerror="onPreviewImageError(event)"/>
</hbox>
</vbox>
<vbox id="infoNoAddonSelected" align="center" pack="center">

View File

@ -59,21 +59,29 @@ var LightweightThemeManager = {
},
set currentTheme (aData) {
let cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
cancel.data = false;
_observerService.notifyObservers(cancel, "lightweight-theme-change-requested",
JSON.stringify(aData));
if (aData) {
let usedThemes = _usedThemesExceptId(aData.id);
if (cancel.data && _prefs.getBoolPref("isThemeSelected"))
usedThemes.splice(1, 0, aData);
else
usedThemes.unshift(aData);
_updateUsedThemes(usedThemes);
}
if (cancel.data)
return null;
if (_previewTimer) {
_previewTimer.cancel();
_previewTimer = null;
}
if (aData) {
let usedThemes = _usedThemesExceptId(aData.id);
usedThemes.unshift(aData);
_updateUsedThemes(usedThemes);
_prefs.setBoolPref("isThemeSelected", true);
} else {
_prefs.setBoolPref("isThemeSelected", false);
}
_prefs.setBoolPref("isThemeSelected", aData != null);
_notifyWindows(aData);
return aData;
@ -100,6 +108,13 @@ var LightweightThemeManager = {
if (!aData)
return;
let cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
cancel.data = false;
_observerService.notifyObservers(cancel, "lightweight-theme-preview-requested",
JSON.stringify(aData));
if (cancel.data)
return;
if (_previewTimer)
_previewTimer.cancel();
else

View File

@ -53,6 +53,7 @@ const Ci = Components.interfaces;
const Cr = Components.results;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm");
const PREF_EM_CHECK_COMPATIBILITY = "extensions.checkCompatibility";
const PREF_EM_CHECK_UPDATE_SECURITY = "extensions.checkUpdateSecurity";
@ -72,6 +73,7 @@ const PREF_EM_ITEM_UPDATE_URL = "extensions.%UUID%.update.url";
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_LWTHEME_TO_SELECT = "extensions.lwThemeToSelect";
const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin";
const PREF_EM_LOGGING_ENABLED = "extensions.logging.enabled";
const PREF_EM_UPDATE_INTERVAL = "extensions.update.interval";
@ -141,6 +143,10 @@ const URI_DOWNLOADS_PROPERTIES = "chrome://mozapps/locale/downloads/downl
const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul";
const URI_EXTENSION_LIST_DIALOG = "chrome://mozapps/content/extensions/list.xul";
const URI_EXTENSION_MANAGER = "chrome://mozapps/content/extensions/extensions.xul";
const FEATURES_EXTENSION_MANAGER = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
const FEATURES_EXTENSION_UPDATES = "chrome,centerscreen,extra-chrome,dialog,resizable,modal";
/**
* Constants that internal code can use to indicate the reason for an add-on
* update check. external code uses other constants in nsIExtensionManager.idl.
@ -198,6 +204,7 @@ var gFirstRun = false;
var gAllowFlush = true;
var gDSNeedsFlush = false;
var gManifestNeedsFlush = false;
var gDefaultTheme = "classic/1.0";
/**
* Valid GUIDs fit this pattern.
@ -2163,11 +2170,16 @@ function ExtensionManager() {
gXPCOMABI = UNKNOWN_XPCOM_ABI;
}
gPref = Cc["@mozilla.org/preferences-service;1"].
getService(Ci.nsIPrefBranch2);
getService(Ci.nsIPrefBranch2).
QueryInterface(Ci.nsIPrefService);
var defaults = gPref.getDefaultBranch("");
gDefaultTheme = defaults.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
gOS = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
gOS.addObserver(this, "xpcom-shutdown", false);
gOS.addObserver(this, "lightweight-theme-preview-requested", false);
gOS.addObserver(this, "lightweight-theme-change-requested", false);
gConsole = Cc["@mozilla.org/consoleservice;1"].
getService(Ci.nsIConsoleService);
@ -2278,6 +2290,57 @@ ExtensionManager.prototype = {
case "offline-requested":
this._confirmCancelDownloadsOnOffline(subject);
break;
case "lightweight-theme-preview-requested":
if (gPref.prefHasUserValue(PREF_GENERAL_SKINS_SELECTEDSKIN)) {
let cancel = subject.QueryInterface(Ci.nsISupportsPRBool);
cancel.data = true;
}
break;
case "lightweight-theme-change-requested":
let theme = JSON.parse(data);
if (!theme)
return;
if (gPref.prefHasUserValue(PREF_GENERAL_SKINS_SELECTEDSKIN)) {
if (getPref("getBoolPref", PREF_EM_DSS_ENABLED, false)) {
gPref.clearUserPref(PREF_GENERAL_SKINS_SELECTEDSKIN);
return;
}
let cancel = subject.QueryInterface(Ci.nsISupportsPRBool);
cancel.data = true;
gPref.setBoolPref(PREF_DSS_SWITCHPENDING, true);
gPref.setCharPref(PREF_DSS_SKIN_TO_SELECT, gDefaultTheme);
gPref.setCharPref(PREF_LWTHEME_TO_SELECT, theme.id);
// Open the UI so the user can see that a restart is necessary
var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
getService(Ci.nsIWindowMediator);
var win = wm.getMostRecentWindow("Extension:Manager");
if (win) {
win.showView("themes");
return;
}
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
var param = Cc["@mozilla.org/supports-array;1"].
createInstance(Ci.nsISupportsArray);
var arg = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
arg.data = "themes";
param.AppendElement(arg);
ww.openWindow(null, URI_EXTENSION_MANAGER, null, FEATURES_EXTENSION_MANAGER, param);
return;
}
else {
// Cancel any pending theme change and allow the lightweight theme
// change to go ahead
gPref.clearUserPref(PREF_DSS_SWITCHPENDING);
gPref.clearUserPref(PREF_DSS_SKIN_TO_SELECT);
}
break;
case "xpcom-shutdown":
this._shutdown();
break;
@ -2355,6 +2418,22 @@ ExtensionManager.prototype = {
gPref.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, toSelect);
gPref.clearUserPref(PREF_DSS_SWITCHPENDING);
gPref.clearUserPref(PREF_DSS_SKIN_TO_SELECT);
// If we've changed to a non-default theme make sure there is no
// lightweight theme selected
if (toSelect != gDefaultTheme) {
gPref.clearUserPref(PREF_LWTHEME_TO_SELECT);
LightweightThemeManager.currentTheme = null;
}
}
if (gPref.prefHasUserValue(PREF_LWTHEME_TO_SELECT)) {
var id = gPref.getCharPref(PREF_LWTHEME_TO_SELECT);
if (id)
LightweightThemeManager.currentTheme = LightweightThemeManager.getUsedTheme(id);
else
LightweightThemeManager.currentTheme = null;
gPref.clearUserPref(PREF_LWTHEME_TO_SELECT);
}
}
catch (e) {
@ -2389,9 +2468,6 @@ ExtensionManager.prototype = {
if (!getPref("getBoolPref", PREF_UPDATE_NOTIFYUSER, false))
return;
const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
const EMFEATURES = "chrome,centerscreen,extra-chrome,dialog,resizable,modal";
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
var param = Cc["@mozilla.org/supports-array;1"].
@ -2400,7 +2476,7 @@ ExtensionManager.prototype = {
createInstance(Ci.nsISupportsString);
arg.data = "updates-only";
param.AppendElement(arg);
ww.openWindow(null, EMURL, null, EMFEATURES, param);
ww.openWindow(null, URI_EXTENSION_MANAGER, null, FEATURES_EXTENSION_UPDATES, param);
},
/**
@ -2427,6 +2503,8 @@ ExtensionManager.prototype = {
}
gOS.removeObserver(this, "xpcom-shutdown");
gOS.removeObserver(this, "lightweight-theme-preview-requested");
gOS.removeObserver(this, "lightweight-theme-change-requested");
// Release strongly held services.
gOS = null;
@ -5519,9 +5597,6 @@ BackgroundUpdateCheckListener.prototype = {
gPref.setBoolPref(PREF_UPDATE_NOTIFYUSER, false);
}
else {
const EMURL = "chrome://mozapps/content/extensions/extensions.xul";
const EMFEATURES = "chrome,menubar,extra-chrome,toolbar,dialog=no,resizable";
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
getService(Ci.nsIWindowWatcher);
var param = Cc["@mozilla.org/supports-array;1"].
@ -5530,7 +5605,7 @@ BackgroundUpdateCheckListener.prototype = {
createInstance(Ci.nsISupportsString);
arg.data = "updates";
param.AppendElement(arg);
ww.openWindow(null, EMURL, null, EMFEATURES, param);
ww.openWindow(null, URI_EXTENSION_MANAGER, null, FEATURES_EXTENSION_MANAGER, param);
}
},

View File

@ -48,6 +48,10 @@ include $(DEPTH)/config/autoconf.mk
MODULE = test_extensionmanager
DIRS = \
browser \
$(NULL)
XPCSHELL_TESTS = \
unit \
$(NULL)

View File

@ -0,0 +1,53 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Extension Manager.
#
# The Initial Developer of the Original Code is
# Dave Townsend <dtownsend@oxymoronical.com>.
#
# Portions created by the Initial Developer are Copyright (C) 2009
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either of the GNU General Public License Version 2 or later (the "GPL"),
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = toolkit/mozapps/extensions/test
include $(DEPTH)/config/autoconf.mk
_TEST_FILES = \
browser_bug510909.js
$(NULL)
include $(topsrcdir)/config/rules.mk
libs:: $(_TEST_FILES)
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)

View File

@ -0,0 +1,199 @@
Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm");
var win = null;
function WindowListener(url) {
this.url = url;
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
wm.addListener(this);
}
WindowListener.prototype = {
url: null,
onWindowTitleChange: function(window, title) {
},
onOpenWindow: function(window) {
var domwindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindowInternal);
var self = this;
domwindow.addEventListener("load", function() {
self.windowLoad(domwindow);
}, false);
},
// Window open handling
windowLoad: function(window) {
// Allow any other load handlers to execute
var self = this;
executeSoon(function() { self.windowReady(window); } );
},
windowReady: function(win) {
is(win.document.location.href, this.url, "Should have seen the right window");
win.document.documentElement.acceptDialog();
},
onCloseWindow: function(window) {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
wm.removeListener(this);
},
QueryInterface: function(iid) {
if (iid.equals(Components.interfaces.nsIWindowMediatorListener) ||
iid.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
}
}
function test() {
is(LightweightThemeManager.usedThemes.length, 0, "Should be no themes there");
ok(LightweightThemeManager.currentTheme == null, "Should not have a theme selected");
// Load up some lightweight themes
LightweightThemeManager.currentTheme = {
"id":"2",
"name":"Dirty Red",
"accentcolor":"#ffffff",
"textcolor":"#ffa0a0",
"description":null,
"author":"Mozilla",
"headerURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"footerURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"previewURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"iconURL":null
};
LightweightThemeManager.currentTheme = {
"id":"1",
"name":"Abstract Black",
"accentcolor":"#ffffff",
"textcolor":"#000000",
"description":null,
"author":"Mozilla",
"headerURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"footerURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"previewURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"iconURL":null
};
LightweightThemeManager.currentTheme = {
"id":"3",
"name":"Morose Mauve",
"accentcolor":"#ffffff",
"textcolor":"#e0b0ff",
"description":null,
"author":"Mozilla",
"headerURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"footerURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"iconURL":null
};
is(LightweightThemeManager.usedThemes.length, 3, "Should be all the themes there");
ok(LightweightThemeManager.currentTheme != null, "Should have selected a theme");
is(LightweightThemeManager.currentTheme.id, 3, "Should have selected the right theme");
win = window.openDialog("chrome://mozapps/content/extensions/extensions.xul", "",
"chrome,menubar,extra-chrome,toolbar,dialog=no,resizable");
win.addEventListener("load", function() { executeSoon(loaded); }, false);
waitForExplicitFinish();
}
function loaded() {
win.showView("themes");
is(win.gExtensionsView.childNodes.length,
LightweightThemeManager.usedThemes.length + 2,
"Should be all the lightweight themes and the default theme and the template");
is(win.gExtensionsView.childNodes[1].getAttribute("addonID"), 1,
"Themes should be in the right order");
is(win.gExtensionsView.childNodes[2].getAttribute("addonID"), "{972ce4c6-7e08-4474-a285-3208198ce6fd}",
"Themes should be in the right order");
is(win.gExtensionsView.childNodes[3].getAttribute("addonID"), 2,
"Themes should be in the right order");
is(win.gExtensionsView.childNodes[4].getAttribute("addonID"), 3,
"Themes should be in the right order");
var selected = win.gExtensionsView.selectedItem;
is(selected.getAttribute("addonID"),
LightweightThemeManager.currentTheme.id,
"Should have selected the current theme");
is(win.document.getElementById("previewImageDeck").selectedIndex, 1,
"Should be no preview to display");
var btn = win.document.getAnonymousElementByAttribute(selected, "command", "cmd_useTheme");
ok(btn.disabled, "Should not be able to switch to the current theme");
selected = win.gExtensionsView.selectedItem = win.gExtensionsView.childNodes[1];
is(win.document.getElementById("previewImageDeck").selectedIndex, 2,
"Should be a preview to display");
btn = win.document.getAnonymousElementByAttribute(selected, "command", "cmd_useTheme");
ok(!btn.disabled, "Should be able to switch to a different lightweight theme");
EventUtils.synthesizeMouse(btn, btn.boxObject.width / 2, btn.boxObject.height / 2, {}, win);
is(LightweightThemeManager.currentTheme.id, 1,
"Should have changed theme");
// A list rebuild happens so get the selected item again
selected = win.gExtensionsView.selectedItem;
btn = win.document.getAnonymousElementByAttribute(selected, "command", "cmd_useTheme");
ok(btn.disabled, "Should not be able to switch to the current theme");
selected = win.gExtensionsView.selectedItem = win.gExtensionsView.childNodes[2];
btn = win.document.getAnonymousElementByAttribute(selected, "command", "cmd_useTheme");
ok(!btn.disabled, "Should be able to switch to the default theme");
EventUtils.synthesizeMouse(btn, btn.boxObject.width / 2, btn.boxObject.height / 2, {}, win);
is(LightweightThemeManager.currentTheme, null,
"Should have disabled lightweight themes");
ok(btn.disabled, "Should not be able to switch to the current theme");
selected = win.gExtensionsView.selectedItem = win.gExtensionsView.childNodes[3];
btn = win.document.getAnonymousElementByAttribute(selected, "command", "cmd_useTheme");
ok(!btn.disabled, "Should be able to switch to a different lightweight theme");
EventUtils.synthesizeMouse(btn, btn.boxObject.width / 2, btn.boxObject.height / 2, {}, win);
is(LightweightThemeManager.currentTheme.id, 2,
"Should have changed theme");
// A list rebuild happens so get the selected item again
selected = win.gExtensionsView.selectedItem;
btn = win.document.getAnonymousElementByAttribute(selected, "command", "cmd_useTheme");
ok(btn.disabled, "Should not be able to switch to the current theme");
btn = win.document.getAnonymousElementByAttribute(selected, "command", "cmd_uninstall");
ok(!btn.disabled, "Should be able to uninstall a lightweight theme");
new WindowListener("chrome://mozapps/content/extensions/list.xul");
EventUtils.synthesizeMouse(btn, btn.boxObject.width / 2, btn.boxObject.height / 2, {}, win);
is(LightweightThemeManager.currentTheme, null,
"Should have turned off the lightweight theme");
is(LightweightThemeManager.usedThemes.length, 2, "Should have removed the theme");
is(win.gExtensionsView.childNodes.length,
LightweightThemeManager.usedThemes.length + 2,
"Should have updated the list");
LightweightThemeManager.currentTheme = {
"id":"2",
"name":"Dirty Red",
"accentcolor":"#ffffff",
"textcolor":"#ffa0a0",
"description":null,
"author":"Mozilla",
"headerURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"footerURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"previewURL":"http://example.com/browser/toolkit/mozapps/extensions/test/blank.png",
"iconURL":null
};
is(LightweightThemeManager.usedThemes.length, 3, "Should have added the theme");
is(win.gExtensionsView.childNodes.length,
LightweightThemeManager.usedThemes.length + 2,
"Should have updated the list");
win.close();
endTest();
}
function endTest() {
var themes = LightweightThemeManager.usedThemes;
themes.forEach(function(theme) {
LightweightThemeManager.forgetUsedTheme(theme.id);
});
is(LightweightThemeManager.usedThemes.length, 0, "Should be no themes left");
ok(LightweightThemeManager.currentTheme == null, "Should be no theme selected");
finish();
}

View File

@ -142,6 +142,10 @@ richlistitem[plugin] .addonIcon > image {
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.png");
}
richlistitem[lwtheme] .addonIcon > image {
list-style-image: url("chrome://mozapps/skin/extensions/themeGeneric.png");
}
.updateBadge,
.notifyBadge {
width: 16px;

View File

@ -134,6 +134,10 @@ richlistitem[plugin] .addonIcon > image {
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.png");
}
richlistitem[lwtheme] .addonIcon > image {
list-style-image: url("chrome://mozapps/skin/extensions/themeGeneric.png");
}
.updateBadge,
.notifyBadge {
width: 16px;

View File

@ -132,6 +132,10 @@ richlistitem[plugin] .addonIcon > image {
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.png");
}
richlistitem[lwtheme] .addonIcon > image {
list-style-image: url("chrome://mozapps/skin/extensions/themeGeneric.png");
}
.updateBadge,
.notifyBadge {
width: 16px;