Bug 798353 - Make SettingsListener reuse the lock. r=fabrice
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -1,72 +1,90 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict;"
+"use strict";
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
#ifdef MOZ_WIDGET_GONK
XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
Cu.import("resource://gre/modules/systemlibs.js");
return libcutils;
});
#endif
-// Once Bug 731746 - Allow chrome JS object to implement nsIDOMEventTarget
-// is resolved this helper could be removed.
var SettingsListener = {
- _callbacks: {},
+ // Timer to remove the lock.
+ _timer: null,
+
+ // lock stores here
+ _lock: null,
- init: function sl_init() {
- if ('mozSettings' in navigator && navigator.mozSettings) {
- navigator.mozSettings.onsettingchange = this.onchange.bind(this);
- }
- },
+ /**
+ * getSettingsLock: create a lock or retrieve one that we saved.
+ * mozSettings.createLock() is expensive and lock should be reused
+ * whenever possible.
+ */
+ getSettingsLock: function sl_getSettingsLock() {
+ // Each time there is a getSettingsLock call, we postpone the removal.
+ clearTimeout(this._timer);
+ this._timer = setTimeout((function() {
+ this._lock = null;
+ }).bind(this), 0);
- onchange: function sl_onchange(evt) {
- var callback = this._callbacks[evt.settingName];
- if (callback) {
- callback(evt.settingValue);
+ // If there is a lock present we return that.
+ if (this._lock) {
+ return this._lock;
}
+
+ // If there isn't we create a new one.
+ let settings = window.navigator.mozSettings;
+
+ return (this._lock = settings.createLock());
},
observe: function sl_observe(name, defaultValue, callback) {
- var settings = window.navigator.mozSettings;
- if (!settings) {
- window.setTimeout(function() { callback(defaultValue); });
- return;
+ let settings = window.navigator.mozSettings;
+
+ let req;
+ try {
+ req = this.getSettingsLock().get(name);
+ } catch (e) {
+ // It is possible (but rare) for getSettingsLock() to return
+ // a SettingsLock object that is no longer valid.
+ // Until https://bugzilla.mozilla.org/show_bug.cgi?id=793239
+ // is fixed, we just catch the resulting exception and try
+ // again with a fresh lock
+ console.warn('Stale lock in settings.js.',
+ 'See https://bugzilla.mozilla.org/show_bug.cgi?id=793239');
+ this._lock = null;
+ req = this.getSettingsLock().get(name);
}
- if (!callback || typeof callback !== 'function') {
- throw new Error('Callback is not a function');
- }
-
- var req = settings.createLock().get(name);
req.addEventListener('success', (function onsuccess() {
callback(typeof(req.result[name]) != 'undefined' ?
req.result[name] : defaultValue);
}));
- this._callbacks[name] = callback;
+ settings.addObserver(name, function settingChanged(evt) {
+ callback(evt.settingValue);
+ });
}
};
-SettingsListener.init();
-
// =================== Console ======================
SettingsListener.observe('debug.console.enabled', true, function(value) {
Services.prefs.setBoolPref('consoleservice.enabled', value);
Services.prefs.setBoolPref('layout.css.report_errors', value);
});
// =================== Languages ====================