--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -185,19 +185,16 @@ pref("app.update.service.enabled", true)
// extensions.{GUID}.update.url
// .. etc ..
//
pref("extensions.update.enabled", true);
pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
pref("extensions.update.background.url", "https://versioncheck-bg.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%¤tAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
pref("extensions.update.interval", 86400); // Check for updates to Extensions and
// Themes every day
-// Non-symmetric (not shared by extensions) extension-specific [update] preferences
-pref("extensions.dss.switchPending", false); // Non-dynamic switch pending after next
- // restart.
pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name", "chrome://browser/locale/browser.properties");
pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description", "chrome://browser/locale/browser.properties");
pref("extensions.webextensions.themes.enabled", true);
pref("extensions.webextensions.themes.icons.buttons", "back,forward,reload,stop,bookmark_star,bookmark_menu,downloads,home,app_menu,cut,copy,paste,new_window,new_private_window,save_page,print,history,full_screen,find,options,addons,developer,synced_tabs,open_file,sidebars,share_page,subscribe,text_encoding,email_link,forget,pocket");
pref("lightweightThemes.update.enabled", true);
@@ -217,18 +214,16 @@ pref("browser.uitour.requireSecure", tru
pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/");
pref("browser.uitour.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tour/");
// How long to show a Hearbeat survey (two hours, in seconds)
pref("browser.uitour.surveyDuration", 7200);
pref("keyword.enabled", true);
pref("browser.fixup.domainwhitelist.localhost", true);
-pref("general.skins.selectedSkin", "classic/1.0");
-
pref("general.smoothScroll", true);
#ifdef UNIX_BUT_NOT_MAC
pref("general.autoScroll", false);
#else
pref("general.autoScroll", true);
#endif
pref("browser.stopReloadAnimation.enabled", true);
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -99,20 +99,16 @@ function CustomizeMode(aWindow) {
this.areas = new Set();
// There are two palettes - there's the palette that can be overlayed with
// toolbar items in browser.xul. This is invisible, and never seen by the
// user. Then there's the visible palette, which gets populated and displayed
// to the user when in customizing mode.
this.visiblePalette = this.document.getElementById(kPaletteId);
this.pongArena = this.document.getElementById("customization-pong-arena");
- if (Services.prefs.getCharPref("general.skins.selectedSkin") != "classic/1.0") {
- let lwthemeButton = this.document.getElementById("customization-lwtheme-button");
- lwthemeButton.setAttribute("hidden", "true");
- }
if (AppConstants.CAN_DRAW_IN_TITLEBAR) {
this._updateTitlebarCheckbox();
this._updateDragSpaceCheckbox();
Services.prefs.addObserver(kDrawInTitlebarPref, this);
Services.prefs.addObserver(kExtraDragSpacePref, this);
}
this.window.addEventListener("unload", this);
}
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -191,17 +191,16 @@ pref("xpinstall.whitelist.add", "https:/
pref("xpinstall.signatures.required", true);
pref("extensions.enabledScopes", 1);
pref("extensions.autoupdate.enabled", true);
pref("extensions.autoupdate.interval", 86400);
pref("extensions.update.enabled", true);
pref("extensions.update.interval", 86400);
pref("extensions.dss.enabled", false);
-pref("extensions.dss.switchPending", false);
pref("extensions.ignoreMTimeChanges", false);
pref("extensions.logging.enabled", false);
pref("extensions.hideInstallButton", true);
pref("extensions.showMismatchUI", false);
pref("extensions.hideUpdateButton", false);
pref("extensions.strictCompatibility", false);
pref("extensions.minCompatibleAppVersion", "11.0");
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -8,18 +8,16 @@ var EXPORTED_SYMBOLS = ["LightweightThem
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
/* globals AddonManagerPrivate*/
ChromeUtils.import("resource://gre/modules/Services.jsm");
const ID_SUFFIX = "@personas.mozilla.org";
const PREF_LWTHEME_TO_SELECT = "extensions.lwThemeToSelect";
-const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin";
-const PREF_SKIN_TO_SELECT = "extensions.lastSelectedSkin";
const ADDON_TYPE = "theme";
const ADDON_TYPE_WEBEXT = "webextension-theme";
const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties";
const DEFAULT_MAX_USED_THEMES_COUNT = 30;
const MAX_PREVIEW_SECONDS = 30;
@@ -509,20 +507,16 @@ AddonWrapper.prototype = {
get pendingOperations() {
let pending = AddonManager.PENDING_NONE;
if (this.isActive == this.userDisabled)
pending |= this.isActive ? AddonManager.PENDING_DISABLE : AddonManager.PENDING_ENABLE;
return pending;
},
get operationsRequiringRestart() {
- // 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))
- return AddonManager.OP_NEEDS_RESTART_ENABLE;
return AddonManager.OP_NEEDS_RESTART_NONE;
},
get size() {
// The size changes depending on whether the theme is in use or not, this is
// probably not worth exposing.
return null;
},
@@ -655,19 +649,16 @@ function _getInternalID(id) {
if (len > 0 && id.substring(len) == ID_SUFFIX)
return id.substring(0, len);
return null;
}
function _setCurrentTheme(aData, aLocal) {
aData = _sanitizeTheme(aData, null, aLocal);
- let needsRestart = (ADDON_TYPE == "theme") &&
- Services.prefs.prefHasUserValue(PREF_GENERAL_SKINS_SELECTEDSKIN);
-
let cancel = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
cancel.data = false;
Services.obs.notifyObservers(cancel, "lightweight-theme-change-requested",
JSON.stringify(aData));
let notify = true;
if (aData) {
@@ -687,34 +678,33 @@ function _setCurrentTheme(aData, aLocal)
AddonManagerPrivate.callAddonListeners("onInstalling", wrapper, false);
}
let current = LightweightThemeManager.currentTheme;
let usedThemes = _usedThemesExceptId(aData.id);
if (current && current.id != aData.id) {
usedThemes.splice(1, 0, aData);
} else {
- if (current && current.id == aData.id && !needsRestart &&
- !Services.prefs.prefHasUserValue(PREF_SKIN_TO_SELECT)) {
+ if (current && current.id == aData.id) {
notify = false;
}
usedThemes.unshift(aData);
}
_updateUsedThemes(usedThemes);
if (isInstall)
AddonManagerPrivate.callAddonListeners("onInstalled", wrapper);
}
if (cancel.data)
return null;
if (notify) {
AddonManagerPrivate.notifyAddonChanged(aData ? aData.id + ID_SUFFIX : null,
- ADDON_TYPE, needsRestart);
+ ADDON_TYPE, false);
}
return LightweightThemeManager.currentTheme;
}
function _sanitizeTheme(aData, aBaseURI, aLocal) {
if (!aData || typeof aData != "object")
return null;
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -57,16 +57,18 @@ XPCOMUtils.defineLazyServiceGetter(this,
ChromeUtils.defineModuleGetter(this, "XPIInternal",
"resource://gre/modules/addons/XPIProvider.jsm");
ChromeUtils.defineModuleGetter(this, "XPIProvider",
"resource://gre/modules/addons/XPIProvider.jsm");
const PREF_ALLOW_NON_RESTARTLESS = "extensions.legacy.non-restartless.enabled";
+const DEFAULT_SKIN = "classic/1.0";
+
/* globals AddonInternal, BOOTSTRAP_REASONS, KEY_APP_SYSTEM_ADDONS, KEY_APP_SYSTEM_DEFAULTS, KEY_APP_TEMPORARY, TEMPORARY_ADDON_SUFFIX, SIGNED_TYPES, TOOLKIT_ID, XPIDatabase, XPIStates, getExternalType, isTheme, isUsableAddon, isWebExtension, mustSign, recordAddonTelemetry */
const XPI_INTERNAL_SYMBOLS = [
"AddonInternal",
"BOOTSTRAP_REASONS",
"KEY_APP_SYSTEM_ADDONS",
"KEY_APP_SYSTEM_DEFAULTS",
"KEY_APP_TEMPORARY",
"SIGNED_TYPES",
@@ -660,17 +662,17 @@ async function loadManifestFromRDF(aUri,
addon.targetPlatforms.push(platform);
}
// A theme's userDisabled value is true if the theme is not the selected skin
// or if there is an active lightweight theme. We ignore whether softblocking
// is in effect since it would change the active theme.
if (isTheme(addon.type)) {
addon.userDisabled = !!LightweightThemeManager.currentTheme ||
- addon.internalName != XPIProvider.selectedSkin;
+ addon.internalName != DEFAULT_SKIN;
} else if (addon.type == "experiment") {
// Experiments are disabled by default. It is up to the Experiments Manager
// to enable them (it drives installation).
addon.userDisabled = true;
} else {
addon.userDisabled = false;
}
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -57,19 +57,16 @@ Cu.importGlobalProperties(["URL"]);
const nsIFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile",
"initWithPath");
const PREF_DB_SCHEMA = "extensions.databaseSchema";
const PREF_XPI_STATE = "extensions.xpiState";
const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL";
const PREF_BOOTSTRAP_ADDONS = "extensions.bootstrappedAddons";
const PREF_PENDING_OPERATIONS = "extensions.pendingOperations";
-const PREF_SKIN_SWITCHPENDING = "extensions.dss.switchPending";
-const PREF_SKIN_TO_SELECT = "extensions.lastSelectedSkin";
-const PREF_GENERAL_SKINS_SELECTEDSKIN = "general.skins.selectedSkin";
const PREF_EM_EXTENSION_FORMAT = "extensions.";
const PREF_EM_ENABLED_SCOPES = "extensions.enabledScopes";
const PREF_EM_STARTUP_SCAN_SCOPES = "extensions.startupScanScopes";
const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI";
const PREF_XPI_ENABLED = "xpinstall.enabled";
const PREF_XPI_WHITELIST_REQUIRED = "xpinstall.whitelist.required";
const PREF_XPI_DIRECT_WHITELISTED = "xpinstall.whitelist.directRequest";
const PREF_XPI_FILE_WHITELISTED = "xpinstall.whitelist.fileRequest";
@@ -86,16 +83,18 @@ const PREF_SYSTEM_ADDON_SET =
const PREF_SYSTEM_ADDON_UPDATE_URL = "extensions.systemAddon.update.url";
const PREF_ALLOW_LEGACY = "extensions.legacy.enabled";
const PREF_EM_MIN_COMPAT_APP_VERSION = "extensions.minCompatibleAppVersion";
const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion";
const PREF_EM_LAST_APP_BUILD_ID = "extensions.lastAppBuildId";
+const DEFAULT_SKIN = "classic/1.0";
+
// Specify a list of valid built-in add-ons to load.
const BUILT_IN_ADDONS_URI = "chrome://browser/content/built_in_addons.json";
const OBSOLETE_PREFERENCES = [
"extensions.bootstrappedAddons",
"extensions.enabledAddons",
"extensions.xpiState",
"extensions.installCache",
@@ -105,17 +104,16 @@ const URI_EXTENSION_STRINGS =
const DIR_EXTENSIONS = "extensions";
const DIR_SYSTEM_ADDONS = "features";
const DIR_STAGE = "staged";
const DIR_TRASH = "trash";
const FILE_XPI_STATES = "addonStartup.json.lz4";
const FILE_DATABASE = "extensions.json";
-const FILE_OLD_CACHE = "extensions.cache";
const FILE_RDF_MANIFEST = "install.rdf";
const FILE_WEB_MANIFEST = "manifest.json";
const FILE_XPI_ADDONS_LIST = "extensions.ini";
const ADDON_ID_DEFAULT_THEME = "{972ce4c6-7e08-4474-a285-3208198ce6fd}";
const KEY_PROFILEDIR = "ProfD";
const KEY_ADDON_APP_DIR = "XREAddonAppDir";
@@ -296,16 +294,17 @@ function loadLazyObjects() {
wantGlobalProperties: ["ChromeUtils", "TextDecoder"],
});
Object.assign(scope, {
ADDON_SIGNING: AddonSettings.ADDON_SIGNING,
SIGNED_TYPES,
BOOTSTRAP_REASONS,
DB_SCHEMA,
+ DEFAULT_SKIN,
AddonInternal,
XPIProvider,
XPIStates,
syncLoadManifestFromFile,
isUsableAddon,
recordAddonTelemetry,
flushChromeCaches,
descriptorToPath,
@@ -795,19 +794,18 @@ function isDisabledLegacy(addon) {
/**
* Calculates whether an add-on should be appDisabled or not.
*
* @param aAddon
* The add-on to check
* @return true if the add-on should not be appDisabled
*/
function isUsableAddon(aAddon) {
- // Hack to ensure the default theme is always usable
- if (aAddon.type == "theme" && aAddon.internalName == XPIProvider.defaultSkin)
- return true;
+ if (aAddon.type == "theme")
+ return aAddon.internalName == DEFAULT_SKIN;
if (mustSign(aAddon.type) && !aAddon.isCorrectlySigned) {
logger.warn(`Add-on ${aAddon.id} is not correctly signed.`);
if (Services.prefs.getBoolPref(PREF_XPI_SIGNATURES_DEV_ROOT, false)) {
logger.warn(`Preference ${PREF_XPI_SIGNATURES_DEV_ROOT} is set.`);
}
return false;
}
@@ -1286,17 +1284,17 @@ class XPIState {
// did a full recursive scan in that case, so we don't need to do it again.
// We don't use aDBAddon.active here because it's not updated until after restart.
let mustGetMod = (aDBAddon.visible && !aDBAddon.disabled && !this.enabled);
// We need to treat XUL themes specially here, since lightweight
// themes require the default theme's chrome to be registered even
// though we report it as disabled for UI purposes.
if (aDBAddon.type == "theme") {
- this.enabled = aDBAddon.internalName == XPIProvider.selectedSkin;
+ this.enabled = aDBAddon.internalName == DEFAULT_SKIN;
} else {
this.enabled = aDBAddon.visible && !aDBAddon.disabled;
}
this.version = aDBAddon.version;
this.type = aDBAddon.type;
this.startupData = aDBAddon.startupData;
@@ -1773,24 +1771,16 @@ var XPIProvider = {
BOOTSTRAP_REASONS: Object.freeze(BOOTSTRAP_REASONS),
// An array of known install locations
installLocations: null,
// A dictionary of known install locations by name
installLocationsByName: null,
// An array of currently active AddonInstalls
installs: null,
- // The default skin for the application
- defaultSkin: "classic/1.0",
- // The current skin used by the application
- currentSkin: null,
- // The selected skin to be used by the application when it is restarted. This
- // 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 minCompatibleAppVersion preference
minCompatibleAppVersion: null,
// The value of the minCompatiblePlatformVersion preference
minCompatiblePlatformVersion: null,
// A Map of active addons to their bootstrapScope by ID
activeAddons: new Map(),
// True if the platform could have activated extensions
extensionsActive: false,
@@ -2059,24 +2049,16 @@ var XPIProvider = {
AddonManager.SCOPE_SYSTEM, true);
if (hasRegistry) {
addRegistryInstallLocation("winreg-app-global",
Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE,
AddonManager.SCOPE_SYSTEM);
}
}
- let defaultPrefs = Services.prefs.getDefaultBranch("");
- this.defaultSkin = defaultPrefs.getStringPref(PREF_GENERAL_SKINS_SELECTEDSKIN,
- "classic/1.0");
- this.currentSkin = Services.prefs.getStringPref(PREF_GENERAL_SKINS_SELECTEDSKIN,
- this.defaultSkin);
- this.selectedSkin = this.currentSkin;
- this.applyThemeChange();
-
this.minCompatibleAppVersion = Services.prefs.getStringPref(PREF_EM_MIN_COMPAT_APP_VERSION,
null);
this.minCompatiblePlatformVersion = Services.prefs.getStringPref(PREF_EM_MIN_COMPAT_PLATFORM_VERSION,
null);
Services.prefs.addObserver(PREF_EM_MIN_COMPAT_APP_VERSION, this);
Services.prefs.addObserver(PREF_EM_MIN_COMPAT_PLATFORM_VERSION, this);
if (!AppConstants.MOZ_REQUIRE_SIGNING || Cu.isInAutomation)
@@ -2085,19 +2067,16 @@ var XPIProvider = {
Services.prefs.addObserver(PREF_ALLOW_LEGACY, this);
Services.obs.addObserver(this, NOTIFICATION_FLUSH_PERMISSIONS);
Services.obs.addObserver(this, NOTIFICATION_TOOLBOX_CONNECTION_CHANGE);
let flushCaches = this.checkForChanges(aAppChanged, aOldAppVersion,
aOldPlatformVersion);
- // Changes to installed extensions may have changed which theme is selected
- this.applyThemeChange();
-
AddonManagerPrivate.markProviderSafe(this);
if (aAppChanged && !this.allAppGlobal &&
Services.prefs.getBoolPref(PREF_EM_SHOW_MISMATCH_UI, true) &&
AddonManager.updateEnabled) {
let addonsToUpdate = this.shouldForceUpdateCheck(aAppChanged);
if (addonsToUpdate) {
this.noLegacyStartupCheck(addonsToUpdate);
@@ -2113,17 +2092,17 @@ var XPIProvider = {
// effect
Services.obs.notifyObservers(null, "chrome-flush-skin-caches");
Services.obs.notifyObservers(null, "chrome-flush-caches");
}
if (AppConstants.MOZ_CRASHREPORTER) {
// Annotate the crash report with relevant add-on information.
try {
- Services.appinfo.annotateCrashReport("Theme", this.currentSkin);
+ Services.appinfo.annotateCrashReport("Theme", DEFAULT_SKIN);
} catch (e) { }
try {
Services.appinfo.annotateCrashReport("EMCheckCompatibility",
AddonManager.checkCompatibility);
} catch (e) { }
this.addAddonsToCrashReporter();
}
@@ -2331,37 +2310,16 @@ var XPIProvider = {
let method = callUpdate ? "update" : "install";
this.callBootstrapMethod(newAddon, file, method, reason, data);
}
}
}
},
/**
- * Applies any pending theme change to the preferences.
- */
- applyThemeChange() {
- if (!Services.prefs.getBoolPref(PREF_SKIN_SWITCHPENDING, false))
- return;
-
- // Tell the Chrome Registry which Skin to select
- try {
- this.selectedSkin = Services.prefs.getCharPref(PREF_SKIN_TO_SELECT);
- Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN,
- this.selectedSkin);
- Services.prefs.clearUserPref(PREF_SKIN_TO_SELECT);
- logger.debug("Changed skin to " + this.selectedSkin);
- this.currentSkin = this.selectedSkin;
- } catch (e) {
- logger.error("Error applying theme change", e);
- }
- Services.prefs.clearUserPref(PREF_SKIN_SWITCHPENDING);
- },
-
- /**
* If the application has been upgraded and there are add-ons outside the
* application directory then we may need to synchronize compatibility
* information but only if the mismatch UI isn't disabled.
*
* @returns null if no update check is needed, otherwise an array of add-on
* IDs to check for updates.
*/
shouldForceUpdateCheck(aAppChanged) {
@@ -3192,36 +3150,16 @@ var XPIProvider = {
aOldAppVersion,
aOldPlatformVersion,
updateReasons.includes("schemaChanged"));
} catch (e) {
logger.error("Failed to process extension changes at startup", e);
}
}
- if (aAppChanged) {
- // When upgrading the app and using a custom skin make sure it is still
- // compatible otherwise switch back the default
- if (this.currentSkin != this.defaultSkin) {
- let oldSkin = XPIDatabase.getVisibleAddonForInternalName(this.currentSkin);
- if (!oldSkin || oldSkin.disabled)
- this.enableDefaultTheme();
- }
-
- // When upgrading remove the old extensions cache to force older
- // versions to rescan the entire list of extensions
- let oldCache = FileUtils.getFile(KEY_PROFILEDIR, [FILE_OLD_CACHE], true);
- try {
- if (oldCache.exists())
- oldCache.remove(true);
- } catch (e) {
- logger.warn("Unable to remove old extension cache " + oldCache.path, e);
- }
- }
-
if (Services.appinfo.inSafeMode) {
aomStartup.initializeExtensions(this.getSafeModeExtensions());
logger.debug("Initialized safe mode add-ons");
return false;
}
// If the application crashed before completing any pending operations then
// we should perform them now.
@@ -3757,55 +3695,24 @@ var XPIProvider = {
* @param aType
* The type of the newly enabled add-on
*/
addonChanged(aId, aType) {
// We only care about themes in this provider
if (!isTheme(aType))
return;
- if (!aId) {
- // Fallback to the default theme when no theme was enabled
- this.enableDefaultTheme();
- return;
- }
-
- // Look for the previously enabled theme and find the internalName of the
- // currently selected theme
- let previousTheme = null;
- let newSkin = this.defaultSkin;
let addons = XPIDatabase.getAddonsByType("theme", "webextension-theme");
for (let theme of addons) {
- if (!theme.visible)
- return;
- let isChangedAddon = (theme.id == aId);
- if (isWebExtension(theme.type)) {
- if (!isChangedAddon)
- this.updateAddonDisabledState(theme, true, undefined);
- } else if (isChangedAddon) {
- newSkin = theme.internalName;
- } else if (!theme.userDisabled && !theme.pendingUninstall) {
- previousTheme = theme;
- }
- }
-
- if (newSkin != this.currentSkin) {
- Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN, newSkin);
- this.currentSkin = newSkin;
- }
- this.selectedSkin = newSkin;
-
- // Flush the preferences to disk so they don't get out of sync with the
- // database
- Services.prefs.savePrefFile(null);
-
- // Mark the previous theme as disabled. This won't cause recursion since
- // only enabled calls notifyAddonChanged.
- if (previousTheme)
- this.updateAddonDisabledState(previousTheme, true, undefined);
+ if (isWebExtension(theme.type) && theme.visible && theme.id != aId)
+ this.updateAddonDisabledState(theme, true, undefined);
+ }
+
+ let defaultTheme = XPIDatabase.getVisibleAddonForInternalName(DEFAULT_SKIN);
+ this.updateAddonDisabledState(defaultTheme, aId && aId != defaultTheme.id);
},
/**
* Update the appDisabled property for all add-ons.
*/
updateAddonAppDisabledStates() {
let addons = XPIDatabase.getAddons();
for (let addon of addons) {
@@ -3842,43 +3749,16 @@ var XPIProvider = {
}
notifyComplete();
});
}
});
},
- /**
- * When the previously selected theme is removed this method will be called
- * to enable the default theme.
- */
- enableDefaultTheme() {
- logger.debug("Activating default theme");
- let addon = XPIDatabase.getVisibleAddonForInternalName(this.defaultSkin);
- if (addon) {
- if (addon.userDisabled) {
- this.updateAddonDisabledState(addon, false);
- } else if (!this.extensionsActive) {
- // During startup we may end up trying to enable the default theme when
- // the database thinks it is already enabled (see f.e. bug 638847). In
- // this case just force the theme preferences to be correct
- Services.prefs.setCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN,
- addon.internalName);
- this.currentSkin = this.selectedSkin = addon.internalName;
- Services.prefs.clearUserPref(PREF_SKIN_TO_SELECT);
- Services.prefs.clearUserPref(PREF_SKIN_SWITCHPENDING);
- } else {
- logger.warn("Attempting to activate an already active default theme");
- }
- } else {
- logger.warn("Unable to activate the default theme");
- }
- },
-
onDebugConnectionChange({what, connection}) {
if (what != "opened")
return;
for (let [id, val] of this.activeAddons) {
connection.setAddonOptions(
id, { global: val.bootstrapScope });
}
@@ -5054,17 +4934,17 @@ AddonWrapper.prototype = {
icons[32] = icons[48] = this.getResourceURI("icon.png").spec;
}
if (this.hasResource("icon64.png")) {
icons[64] = this.getResourceURI("icon64.png").spec;
}
}
let canUseIconURLs = this.isActive ||
- (addon.type == "theme" && addon.internalName == XPIProvider.defaultSkin);
+ (addon.type == "theme" && addon.internalName == DEFAULT_SKIN);
if (canUseIconURLs && addon.iconURL) {
icons[32] = addon.iconURL;
icons[48] = addon.iconURL;
}
if (canUseIconURLs && addon.icon64URL) {
icons[64] = addon.icon64URL;
}
@@ -5223,19 +5103,21 @@ AddonWrapper.prototype = {
let addon = addonFor(this);
if (val == this.userDisabled) {
return val;
}
if (addon.inDatabase) {
let theme = isTheme(addon.type);
if (theme && val) {
- if (addon.internalName == XPIProvider.defaultSkin)
+ if (addon.internalName == DEFAULT_SKIN)
throw new Error("Cannot disable the default theme");
- XPIProvider.enableDefaultTheme();
+
+ let defaultTheme = XPIDatabase.getVisibleAddonForInternalName(DEFAULT_SKIN);
+ XPIProvider.updateAddonDisabledState(defaultTheme, false);
}
if (!(theme && val) || isWebExtension(addon.type)) {
// hidden and system add-ons should not be user disasbled,
// as there is no UI to re-enable them.
if (this.hidden) {
throw new Error(`Cannot disable hidden add-on ${addon.id}`);
}
XPIProvider.updateAddonDisabledState(addon, val);
@@ -5253,19 +5135,18 @@ AddonWrapper.prototype = {
set softDisabled(val) {
let addon = addonFor(this);
if (val == addon.softDisabled)
return val;
if (addon.inDatabase) {
// When softDisabling a theme just enable the active theme
if (isTheme(addon.type) && val && !addon.userDisabled) {
- if (addon.internalName == XPIProvider.defaultSkin)
+ if (addon.internalName == DEFAULT_SKIN)
throw new Error("Cannot disable the default theme");
- XPIProvider.enableDefaultTheme();
if (isWebExtension(addon.type))
XPIProvider.updateAddonDisabledState(addon, undefined, val);
} else {
XPIProvider.updateAddonDisabledState(addon, undefined, val);
}
} else if (!addon.userDisabled) {
// Only set softDisabled if not already disabled
addon.softDisabled = val;
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -3,17 +3,17 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// These are injected from XPIProvider.jsm
/* globals ADDON_SIGNING, SIGNED_TYPES, BOOTSTRAP_REASONS, DB_SCHEMA,
AddonInternal, XPIProvider, XPIStates, syncLoadManifestFromFile,
isUsableAddon, recordAddonTelemetry,
- flushChromeCaches, descriptorToPath */
+ flushChromeCaches, descriptorToPath, DEFAULT_SKIN */
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetters(this, {
AddonManager: "resource://gre/modules/AddonManager.jsm",
AddonManagerPrivate: "resource://gre/modules/AddonManager.jsm",
AddonRepository: "resource://gre/modules/addons/AddonRepository.jsm",
DeferredTask: "resource://gre/modules/DeferredTask.jsm",
@@ -1173,17 +1173,17 @@ this.XPIDatabaseReconcile = {
aNewAddon.foreignInstall = isDetectedInstall &&
aInstallLocation.name != KEY_APP_SYSTEM_ADDONS &&
aInstallLocation.name != KEY_APP_SYSTEM_DEFAULTS;
// appDisabled depends on whether the add-on is a foreignInstall so update
aNewAddon.appDisabled = !isUsableAddon(aNewAddon);
// The default theme is never a foreign install
- if (aNewAddon.type == "theme" && aNewAddon.internalName == XPIProvider.defaultSkin)
+ if (aNewAddon.type == "theme" && aNewAddon.internalName == DEFAULT_SKIN)
aNewAddon.foreignInstall = false;
if (isDetectedInstall && aNewAddon.foreignInstall) {
// If the add-on is a foreign install and is in a scope where add-ons
// that were dropped in should default to disabled then disable it
let disablingScopes = Services.prefs.getIntPref(PREF_EM_AUTO_DISABLED_SCOPES, 0);
if (aInstallLocation.scope & disablingScopes) {
logger.warn("Disabling foreign installed add-on " + aNewAddon.id + " in "
@@ -1519,17 +1519,16 @@ this.XPIDatabaseReconcile = {
if (!systemAddonLocation.isValid(addons)) {
// Hide the system add-on updates if any are invalid.
logger.info("One or more updated system add-ons invalid, falling back to defaults.");
hideLocation = KEY_APP_SYSTEM_ADDONS;
}
let previousVisible = this.getVisibleAddons(previousAddons);
let currentVisible = this.flattenByID(currentAddons, hideLocation);
- let sawActiveTheme = false;
// Pass over the new set of visible add-ons, record any changes that occured
// during startup and call bootstrap install/uninstall scripts as necessary
for (let [id, currentAddon] of currentVisible) {
let previousAddon = previousVisible.get(id);
// Note if any visible add-on is not in the application install location
if (currentAddon._installLocation.name != KEY_APP_GLOBAL)
@@ -1543,20 +1542,23 @@ this.XPIDatabaseReconcile = {
// so wasn't something recovered from a corrupt database
let wasStaged = !!loadedManifest(currentAddon._installLocation, id);
// We might be recovering from a corrupt database, if so use the
// list of known active add-ons to update the new add-on
if (!wasStaged && XPIDatabase.activeBundles) {
// For themes we know which is active by the current skin setting
if (currentAddon.type == "theme")
- isActive = currentAddon.internalName == XPIProvider.currentSkin;
+ isActive = currentAddon.internalName == DEFAULT_SKIN;
else
isActive = XPIDatabase.activeBundles.includes(currentAddon.path);
+ if (currentAddon.type == "webextension-theme")
+ currentAddon.userDisabled = !isActive;
+
// If the add-on wasn't active and it isn't already disabled in some way
// then it was probably either softDisabled or userDisabled
if (!isActive && !currentAddon.disabled) {
// If the add-on is softblocked then assume it is softDisabled
if (currentAddon.blocklistState == Blocklist.STATE_SOFTBLOCKED)
currentAddon.softDisabled = true;
else
currentAddon.userDisabled = true;
@@ -1615,19 +1617,16 @@ this.XPIDatabaseReconcile = {
let change = isActive ? AddonManager.STARTUP_CHANGE_ENABLED
: AddonManager.STARTUP_CHANGE_DISABLED;
AddonManagerPrivate.addStartupChange(change, id);
}
}
XPIDatabase.makeAddonVisible(currentAddon);
currentAddon.active = isActive;
-
- if (currentAddon.active && currentAddon.internalName == XPIProvider.selectedSkin)
- sawActiveTheme = true;
}
// Pass over the set of previously visible add-ons that have now gone away
// and record the change.
for (let [id, previousAddon] of previousVisible) {
if (currentVisible.has(id))
continue;
@@ -1651,23 +1650,16 @@ this.XPIDatabaseReconcile = {
let locationAddonMap = currentAddons.get(hideLocation);
if (locationAddonMap) {
for (let addon of locationAddonMap.values()) {
addon.visible = false;
addon.active = false;
}
}
- // If a custom theme is selected and it wasn't seen in the new list of
- // active add-ons then enable the default theme
- if (XPIProvider.selectedSkin != XPIProvider.defaultSkin && !sawActiveTheme) {
- logger.info("Didn't see selected skin " + XPIProvider.selectedSkin);
- XPIProvider.enableDefaultTheme();
- }
-
// Finally update XPIStates to match everything
for (let [locationName, locationAddonMap] of currentAddons) {
for (let [id, addon] of locationAddonMap) {
let xpiState = XPIStates.getAddon(locationName, id);
xpiState.syncWithDB(addon);
}
}
XPIStates.save();
--- a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js
@@ -196,43 +196,43 @@ const ADDONS = {
userDisabled: true,
appDisabled: false,
pendingOperations: 0,
},
},
// The default theme
"theme1@tests.mozilla.org": {
- "install.rdf": {
- id: "theme1@tests.mozilla.org",
- version: "1.0",
+ manifest: {
+ manifest_version: 2,
name: "Theme 1",
- internalName: "classic/1.0",
- targetApplications: [{
- id: "xpcshell@tests.mozilla.org",
- minVersion: "2",
- maxVersion: "2"
- }]
+ version: "1.0",
+ theme: { images: { headerURL: "example.png" } },
+ applications: {
+ gecko: {
+ id: "theme1@tests.mozilla.org",
+ },
+ },
},
afterRestart: {
isActive: false,
userDisabled: true,
appDisabled: false,
pendingOperations: 0,
},
// Should be correctly recovered
afterCorruption: {
- isActive: true,
- userDisabled: false,
+ isActive: false,
+ userDisabled: true,
appDisabled: false,
pendingOperations: 0,
},
afterSecondRestart: {
- isActive: true,
- userDisabled: false,
+ isActive: false,
+ userDisabled: true,
appDisabled: false,
pendingOperations: 0,
},
},
"theme2@tests.mozilla.org": {
manifest: {
manifest_version: 2,
@@ -252,23 +252,23 @@ const ADDONS = {
isActive: true,
userDisabled: false,
appDisabled: false,
pendingOperations: 0,
},
// Should be correctly recovered
afterCorruption: {
isActive: true,
- // userDisabled: false,
+ userDisabled: false,
appDisabled: false,
- // pendingOperations: 0,
+ pendingOperations: 0,
},
afterSecondRestart: {
- isActive: false,
- // userDisabled: false,
+ isActive: true,
+ userDisabled: false,
appDisabled: false,
pendingOperations: 0,
},
},
};
const IDS = Object.keys(ADDONS);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_legacy.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_legacy.js
@@ -13,23 +13,16 @@ add_task(async function test_disable() {
bootstrap: true,
},
{
id: "apiexperiment@tests.mozilla.org",
name: "WebExtension Experiment",
version: "1.0",
type: 256,
},
- {
- id: "theme@tests.mozilla.org",
- name: "Theme",
- version: "1.0",
- type: 4,
- internalName: "mytheme/1.0",
- },
];
let nonLegacy = [
{
id: "webextension@tests.mozilla.org",
manifest: {
applications: {gecko: {id: "webextension@tests.mozilla.org"}},
},