Bug 511108 - Implement manager for recently used lightweight themes. r=dtownsend
authorDão Gottwald <dao@mozilla.com>
Wed, 02 Sep 2009 18:23:40 +0200
changeset 32165 14cf3892b66f47834e877b3f1238b35966967cd6
parent 32164 1fa7bd42a36c1aee109a5968af84a6bfc8d155cd
child 32166 67a8b17ad2a16275375a41c64c0ed93357b5846d
push id8890
push userdgottwald@mozilla.com
push dateWed, 02 Sep 2009 16:24:10 +0000
treeherdermozilla-central@14cf3892b66f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdtownsend
bugs511108
milestone1.9.3a1pre
Bug 511108 - Implement manager for recently used lightweight themes. r=dtownsend
toolkit/mozapps/extensions/src/LightweightThemeManager.jsm
toolkit/mozapps/extensions/src/Makefile.in
toolkit/mozapps/extensions/test/unit/test_LightweightThemeManager.js
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/src/LightweightThemeManager.jsm
@@ -0,0 +1,158 @@
+/* ***** 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 mozilla.org Code.
+ *
+ * The Initial Developer of the Original Code is
+ * Dao Gottwald <dao@mozilla.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 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 ***** */
+
+var EXPORTED_SYMBOLS = ["LightweightThemeManager"];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const MAX_USED_THEMES_COUNT = 8;
+const MAX_PREVIEW_SECONDS = 30;
+
+var LightweightThemeManager = {
+  get usedThemes () {
+    try {
+      return JSON.parse(_prefs.getCharPref("usedThemes"));
+    } catch (e) {
+      return [];
+    }
+  },
+
+  get currentTheme () {
+    try {
+      if (_prefs.getBoolPref("isThemeSelected"))
+        return this.usedThemes[0];
+    } catch (e) {}
+    return null;
+  },
+
+  set currentTheme (aData) {
+    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);
+    }
+
+    _notifyWindows(aData);
+
+    return aData;
+  },
+
+  getUsedTheme: function (aId) {
+    var usedThemes = this.usedThemes;
+    for (let i = 0; i < usedThemes.length; i++) {
+      if (usedThemes[i].id == aId)
+        return usedThemes[i];
+    }
+    return null;
+  },
+
+  forgetUsedTheme: function (aId) {
+    var currentTheme = this.currentTheme;
+    if (currentTheme && currentTheme.id == aId)
+      this.currentTheme = null;
+
+    _updateUsedThemes(_usedThemesExceptId(aId));
+  },
+
+  previewTheme: function (aData) {
+    if (!aData)
+      return;
+
+    if (_previewTimer)
+      _previewTimer.cancel();
+    else
+      _previewTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+    _previewTimer.initWithCallback(_previewTimerCallback,
+                                   MAX_PREVIEW_SECONDS * 1000,
+                                   _previewTimer.TYPE_ONE_SHOT);
+
+    _notifyWindows(aData);
+  },
+
+  resetPreview: function () {
+    if (_previewTimer) {
+      _previewTimer.cancel();
+      _previewTimer = null;
+      _notifyWindows(this.currentTheme);
+    }
+  }
+};
+
+function _usedThemesExceptId(aId)
+  LightweightThemeManager.usedThemes.filter(function (t) t.id != aId);
+
+function _updateUsedThemes(aList) {
+  if (aList.length > MAX_USED_THEMES_COUNT)
+    aList.length = MAX_USED_THEMES_COUNT;
+
+  _prefs.setCharPref("usedThemes", JSON.stringify(aList));
+
+  _observerService.notifyObservers(null, "lightweight-theme-list-changed", null);
+}
+
+function _notifyWindows(aThemeData) {
+  _observerService.notifyObservers(null, "lightweight-theme-changed",
+                                   JSON.stringify(aThemeData));
+}
+
+var _previewTimer;
+var _previewTimerCallback = {
+  notify: function () {
+    LightweightThemeManager.resetPreview();
+  }
+}
+
+__defineGetter__("_prefs", function () {
+  delete this._prefs;
+  return this._prefs =
+         Cc["@mozilla.org/preferences-service;1"]
+           .getService(Ci.nsIPrefService).getBranch("lightweightThemes.");
+});
+
+__defineGetter__("_observerService", function () {
+  delete this._observerService;
+  return this._observerService =
+         Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+});
--- a/toolkit/mozapps/extensions/src/Makefile.in
+++ b/toolkit/mozapps/extensions/src/Makefile.in
@@ -45,15 +45,19 @@ include $(DEPTH)/config/autoconf.mk
 MODULE = extensions
 
 EXTRA_COMPONENTS = nsExtensionManager.js
 EXTRA_PP_COMPONENTS = \
   nsBlocklistService.js \
   nsAddonRepository.js \
   $(NULL)
 
+EXTRA_JS_MODULES = \
+  LightweightThemeManager.jsm \
+  $(NULL)
+
 GARBAGE += nsExtensionManager.js
 
 include $(topsrcdir)/config/rules.mk
 
 nsExtensionManager.js: nsExtensionManager.js.in
 	$(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $^ > $@ 
 
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/unit/test_LightweightThemeManager.js
@@ -0,0 +1,116 @@
+function dummy(id) {
+  return {
+    id: id,
+    name: Math.random(),
+    headerURL: Math.random(),
+    footerURL: Math.random(),
+    textColor: Math.random(),
+    dominantColor: Math.random()
+  };
+}
+
+function run_test() {
+  var temp = {};
+  Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", temp);
+  do_check_eq(typeof temp.LightweightThemeManager, "object");
+
+  var ltm = temp.LightweightThemeManager;
+
+  do_check_eq(typeof ltm.usedThemes, "object");
+  do_check_eq(ltm.usedThemes.length, 0);
+  do_check_eq(ltm.currentTheme, null);
+
+  ltm.previewTheme(dummy("preview0"));
+  do_check_eq(ltm.usedThemes.length, 0);
+  do_check_eq(ltm.currentTheme, null);
+
+  ltm.previewTheme(dummy("preview1"));
+  do_check_eq(ltm.usedThemes.length, 0);
+  do_check_eq(ltm.currentTheme, null);
+  ltm.resetPreview();
+
+  ltm.currentTheme = dummy("x0");
+  do_check_eq(ltm.usedThemes.length, 1);
+  do_check_eq(ltm.currentTheme.id, "x0");
+  do_check_eq(ltm.usedThemes[0].id, "x0");
+  do_check_eq(ltm.getUsedTheme("x0").id, "x0");
+
+  ltm.previewTheme(dummy("preview0"));
+  do_check_eq(ltm.usedThemes.length, 1);
+  do_check_eq(ltm.currentTheme.id, "x0");
+
+  ltm.resetPreview();
+  do_check_eq(ltm.usedThemes.length, 1);
+  do_check_eq(ltm.currentTheme.id, "x0");
+
+  ltm.currentTheme = dummy("x1");
+  do_check_eq(ltm.usedThemes.length, 2);
+  do_check_eq(ltm.currentTheme.id, "x1");
+  do_check_eq(ltm.usedThemes[1].id, "x0");
+
+  ltm.currentTheme = dummy("x2");
+  do_check_eq(ltm.usedThemes.length, 3);
+  do_check_eq(ltm.currentTheme.id, "x2");
+  do_check_eq(ltm.usedThemes[1].id, "x1");
+  do_check_eq(ltm.usedThemes[2].id, "x0");
+
+  ltm.currentTheme = dummy("x3");
+  ltm.currentTheme = dummy("x4");
+  ltm.currentTheme = dummy("x5");
+  ltm.currentTheme = dummy("x6");
+  ltm.currentTheme = dummy("x7");
+  do_check_eq(ltm.usedThemes.length, 8);
+  do_check_eq(ltm.currentTheme.id, "x7");
+  do_check_eq(ltm.usedThemes[1].id, "x6");
+  do_check_eq(ltm.usedThemes[7].id, "x0");
+
+  ltm.currentTheme = dummy("x8");
+  do_check_eq(ltm.usedThemes.length, 8);
+  do_check_eq(ltm.currentTheme.id, "x8");
+  do_check_eq(ltm.usedThemes[1].id, "x7");
+  do_check_eq(ltm.usedThemes[7].id, "x1");
+  do_check_eq(ltm.getUsedTheme("x0"), null);
+
+  ltm.forgetUsedTheme("nonexisting");
+  do_check_eq(ltm.usedThemes.length, 8);
+  do_check_neq(ltm.currentTheme, null);
+
+  ltm.forgetUsedTheme("x8");
+  do_check_eq(ltm.usedThemes.length, 7);
+  do_check_eq(ltm.currentTheme, null);
+  do_check_eq(ltm.usedThemes[0].id, "x7");
+  do_check_eq(ltm.usedThemes[6].id, "x1");
+
+  ltm.forgetUsedTheme("x7");
+  ltm.forgetUsedTheme("x6");
+  ltm.forgetUsedTheme("x5");
+  ltm.forgetUsedTheme("x4");
+  ltm.forgetUsedTheme("x3");
+  do_check_eq(ltm.usedThemes.length, 2);
+  do_check_eq(ltm.currentTheme, null);
+  do_check_eq(ltm.usedThemes[0].id, "x2");
+  do_check_eq(ltm.usedThemes[1].id, "x1");
+
+  ltm.currentTheme = dummy("x1");
+  do_check_eq(ltm.usedThemes.length, 2);
+  do_check_eq(ltm.currentTheme.id, "x1");
+  do_check_eq(ltm.usedThemes[0].id, "x1");
+  do_check_eq(ltm.usedThemes[1].id, "x2");
+
+  ltm.currentTheme = dummy("x2");
+  do_check_eq(ltm.usedThemes.length, 2);
+  do_check_eq(ltm.currentTheme.id, "x2");
+  do_check_eq(ltm.usedThemes[0].id, "x2");
+  do_check_eq(ltm.usedThemes[1].id, "x1");
+
+  ltm.currentTheme = ltm.getUsedTheme("x1");
+  do_check_eq(ltm.usedThemes.length, 2);
+  do_check_eq(ltm.currentTheme.id, "x1");
+  do_check_eq(ltm.usedThemes[0].id, "x1");
+  do_check_eq(ltm.usedThemes[1].id, "x2");
+
+  ltm.forgetUsedTheme("x1");
+  ltm.forgetUsedTheme("x2");
+  do_check_eq(ltm.usedThemes.length, 0);
+  do_check_eq(ltm.currentTheme, null);
+}