Bug 1254194: Add XPCOMUtils.defineLazyPreferenceGetter. r=billm

MozReview-Commit-ID: JBVelZ0Xg2H

--HG--
extra : rebase_source : 3909e75aa6b24ed2a1d2663c11be69c27f4de1e7
This commit is contained in:
Kris Maglione 2016-04-14 16:37:30 -07:00
parent c7733098d7
commit bd8adfebce
2 changed files with 101 additions and 0 deletions

View File

@ -283,6 +283,63 @@ this.XPCOMUtils = {
});
},
/**
* Defines a getter on a specified object for preference value. The
* preference is read the first time that the property is accessed,
* and is thereafter kept up-to-date using a preference observer.
*
* @param aObject
* The object to define the lazy getter on.
* @param aName
* The name of the getter property to define on aObject.
* @param aPreference
* The name of the preference to read.
* @param aDefaultValue
* The default value to use, if the preference is not defined.
*/
defineLazyPreferenceGetter: function XPCU_defineLazyPreferenceGetter(
aObject, aName, aPreference, aDefaultValue = null)
{
// Note: We need to keep a reference to this observer alive as long
// as aObject is alive. This means that all of our getters need to
// explicitly close over the variable that holds the object, and we
// cannot define a value in place of a getter after we read the
// preference.
let observer = {
QueryInterface: this.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
value: undefined,
observe(subject, topic, data) {
if (data == aPreference) {
this.value = undefined;
}
},
}
let defineGetter = get => {
Object.defineProperty(aObject, aName, {
configurable: true,
enumerable: true,
get,
});
};
function lazyGetter() {
if (observer.value === undefined) {
observer.value = Preferences.get(aPreference, aDefaultValue);
}
return observer.value;
}
defineGetter(() => {
Services.prefs.addObserver(aPreference, observer, true);
defineGetter(lazyGetter);
return lazyGetter();
});
},
/**
* Convenience access to category manager
*/
@ -382,6 +439,11 @@ this.XPCOMUtils = {
},
};
XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
"resource://gre/modules/Preferences.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
/**
* Helper for XPCOMUtils.generateQI to avoid leaks - see bug 381651#c1
*/

View File

@ -8,6 +8,7 @@
* This file tests the methods on XPCOMUtils.jsm.
*/
Components.utils.import("resource://gre/modules/Preferences.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const Cc = Components.classes;
@ -116,6 +117,44 @@ add_test(function test_defineLazyServiceGetter()
});
add_test(function test_defineLazyPreferenceGetter()
{
const PREF = "xpcomutils.test.pref";
let obj = {};
XPCOMUtils.defineLazyPreferenceGetter(obj, "pref", PREF, "defaultValue");
equal(obj.pref, "defaultValue", "Should return the default value before pref is set");
Preferences.set(PREF, "currentValue");
do_print("Create second getter on new object");
obj = {};
XPCOMUtils.defineLazyPreferenceGetter(obj, "pref", PREF, "defaultValue");
equal(obj.pref, "currentValue", "Should return the current value on initial read when pref is already set");
Preferences.set(PREF, "newValue");
equal(obj.pref, "newValue", "Should return new value after preference change");
Preferences.set(PREF, "currentValue");
equal(obj.pref, "currentValue", "Should return new value after second preference change");
Preferences.reset(PREF);
equal(obj.pref, "defaultValue", "Should return default value after pref is reset");
run_next_test();
});
add_test(function test_categoryRegistration()
{
const CATEGORY_NAME = "test-cat";