Bug 1344926 - make sure that WebExtension theme data is persisted across windows when they open and image data is persisted to disk as well. r?Mossop draft
authorMike de Boer <mdeboer@mozilla.com>
Tue, 14 Mar 2017 18:36:18 +0100
changeset 498417 147984254597cbce9f46e9dd1aada944bc8de632
parent 497875 6d38ad302429c98115c354d643e81987ecec5d3c
child 498418 acb4ffbb07f28a4f2f0dabe6fca5da5e65eb8c42
push id49174
push usermdeboer@mozilla.com
push dateTue, 14 Mar 2017 17:50:14 +0000
reviewersMossop
bugs1344926
milestone55.0a1
Bug 1344926 - make sure that WebExtension theme data is persisted across windows when they open and image data is persisted to disk as well. r?Mossop MozReview-Commit-ID: 5UUjajCa8nK
toolkit/components/extensions/ext-theme.js
toolkit/mozapps/extensions/LightweightThemeManager.jsm
toolkit/mozapps/extensions/internal/XPIProvider.jsm
--- a/toolkit/components/extensions/ext-theme.js
+++ b/toolkit/components/extensions/ext-theme.js
@@ -1,14 +1,16 @@
 "use strict";
 
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
                                   "resource://gre/modules/Preferences.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
+                                  "resource://gre/modules/LightweightThemeManager.jsm");
 
 // WeakMap[Extension -> Theme]
 let themeMap = new WeakMap();
 
 const ICONS = Preferences.get("extensions.webextensions.themes.icons.buttons", "").split(",");
 
 /** Class representing a theme. */
 class Theme {
@@ -45,16 +47,17 @@ class Theme {
     if (details.icons) {
       this.loadIcons(details.icons);
     }
 
     // Lightweight themes require all properties to be defined.
     if (this.lwtStyles.headerURL &&
         this.lwtStyles.accentcolor &&
         this.lwtStyles.textcolor) {
+      LightweightThemeManager.fallbackThemeData = this.lwtStyles;
       Services.obs.notifyObservers(null,
         "lightweight-theme-styling-update",
         JSON.stringify(this.lwtStyles));
     }
   }
 
   /**
    * Helper method for loading colors found in the extension's manifest.
@@ -137,16 +140,17 @@ class Theme {
       accentcolor: "",
       textcolor: "",
       icons: {},
     };
 
     for (let icon of ICONS) {
       lwtStyles.icons[`--${icon}--icon`] = "";
     }
+    LightweightThemeManager.fallbackThemeData = null;
     Services.obs.notifyObservers(null,
       "lightweight-theme-styling-update",
       JSON.stringify(lwtStyles));
   }
 }
 
 /* eslint-disable mozilla/balanced-listeners */
 extensions.on("manifest_theme", (type, directive, extension, manifest) => {
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -66,16 +66,20 @@ Object.defineProperty(this, "_maxUsedThe
 });
 
 // Holds the ID of the theme being enabled or disabled while sending out the
 // events so cached AddonWrapper instances can return correct values for
 // permissions and pendingOperations
 var _themeIDBeingEnabled = null;
 var _themeIDBeingDisabled = null;
 
+// Holds optional fallback theme data that will be returned when no data for an
+// active theme can be found. This the case for WebExtension Themes, for example.
+var _fallbackThemeData = 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 = _prefs.getBoolPref("isThemeSelected", false);
 
   if (wasThemeSelected) {
     _prefs.clearUserPref("isThemeSelected");
@@ -91,16 +95,29 @@ var _themeIDBeingDisabled = null;
   }
 })();
 
 this.LightweightThemeManager = {
   get name() {
     return "LightweightThemeManager";
   },
 
+  set fallbackThemeData(data) {
+    if (data && Object.getOwnPropertyNames(data).length) {
+      _fallbackThemeData = Object.assign({}, data);
+      if (PERSIST_ENABLED) {
+        LightweightThemeImageOptimizer.purge();
+        _persistImages(_fallbackThemeData, () => {});
+      }
+    } else {
+      _fallbackThemeData = null;
+    }
+    return _fallbackThemeData;
+  },
+
   // 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 {
       themes = JSON.parse(_prefs.getComplexValue("usedThemes",
@@ -118,16 +135,18 @@ this.LightweightThemeManager = {
     if (selectedThemeID) {
       data = this.getUsedTheme(selectedThemeID);
     }
     return data;
   },
 
   get currentThemeForDisplay() {
     var data = this.currentTheme;
+    if (!data && _fallbackThemeData)
+      data = _fallbackThemeData;
 
     if (data && PERSIST_ENABLED) {
       for (let key in PERSIST_FILES) {
         try {
           if (data[key] && _prefs.getBoolPref("persisted." + key))
             data[key] = _getLocalImageURI(PERSIST_FILES[key]).spec
                         + "?" + data.id + ";" + _version(data);
         } catch (e) {}
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -7525,17 +7525,17 @@ AddonWrapper.prototype = {
   },
   set userDisabled(val) {
     let addon = addonFor(this);
     if (val == this.userDisabled) {
       return val;
     }
 
     if (addon.inDatabase) {
-      let theme = isTheme(addon.type)
+      let theme = isTheme(addon.type);
       if (theme && val) {
         if (addon.internalName == XPIProvider.defaultSkin)
           throw new Error("Cannot disable the default theme");
         XPIProvider.enableDefaultTheme();
       }
       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.