diff --git a/accessible/src/jsat/AccessFu.jsm b/accessible/src/jsat/AccessFu.jsm index 6b2048776996..806eba8f11ef 100644 --- a/accessible/src/jsat/AccessFu.jsm +++ b/accessible/src/jsat/AccessFu.jsm @@ -28,10 +28,6 @@ this.AccessFu = { attach: function attach(aWindow) { Utils.init(aWindow); - this.prefsBranch = Cc['@mozilla.org/preferences-service;1'] - .getService(Ci.nsIPrefService).getBranch('accessibility.accessfu.'); - this.prefsBranch.addObserver('activate', this, false); - try { Cc['@mozilla.org/android/bridge;1']. getService(Ci.nsIAndroidBridge).handleGeckoMessage( @@ -44,21 +40,8 @@ this.AccessFu = { } } - try { - this._activatePref = this.prefsBranch.getIntPref('activate'); - } catch (x) { - this._activatePref = ACCESSFU_DISABLE; - } - - try { - this._notifyOutput = this.prefsBranch.getBoolPref('notify_output'); - } catch (x) { - this._notifyOutput = false; - } - - this.Input.quickNavMode.updateModes(this.prefsBranch); - - this._enableOrDisable(); + this._activatePref = new PrefCache( + 'accessibility.accessfu.activate', this._enableOrDisable.bind(this), true); }, /** @@ -76,7 +59,7 @@ this.AccessFu = { 'mozContentEvent', this); Utils.win.removeEventListener('ContentStart', this); } - this.prefsBranch.removeObserver('activate', this); + delete this._activatePref; Utils.uninit(); }, @@ -107,6 +90,20 @@ this.AccessFu = { Utils.win.document.insertBefore(stylesheet, Utils.win.document.firstChild); this.stylesheet = Cu.getWeakReference(stylesheet); + + // Populate quicknav modes + this._quicknavModesPref = + new PrefCache( + 'accessibility.accessfu.quicknav_modes', + (aName, aValue) => { + this.Input.quickNavMode.updateModes(aValue); + }, true); + + // Check for output notification + this._notifyOutputPref = + new PrefCache('accessibility.accessfu.notify_output'); + + this.Input.start(); Output.start(); TouchAdapter.start(); @@ -168,8 +165,9 @@ this.AccessFu = { _enableOrDisable: function _enableOrDisable() { try { - if (this._activatePref == ACCESSFU_ENABLE || - this._systemPref && this._activatePref == ACCESSFU_AUTO) + let activatePref = this._activatePref.value; + if (activatePref == ACCESSFU_ENABLE || + this._systemPref && activatePref == ACCESSFU_AUTO) this._enable(); else this._disable(); @@ -211,7 +209,7 @@ this.AccessFu = { } } - if (this._notifyOutput) { + if (this._notifyOutputPref.value) { Services.obs.notifyObservers(null, 'accessfu-output', JSON.stringify(aPresentationData)); } @@ -272,22 +270,6 @@ this.AccessFu = { {action: 'whereIsIt', move: true}); } break; - case 'nsPref:changed': - switch (aData) { - case 'activate': - this._activatePref = this.prefsBranch.getIntPref('activate'); - this._enableOrDisable(); - break; - case 'quicknav_modes': - this.Input.quickNavMode.updateModes(this.prefsBranch); - break; - case 'notify_output': - this._notifyOutput = this.prefsBranch.getBoolPref('notify_output'); - break; - default: - break; - } - break; case 'remote-browser-frame-shown': case 'in-process-browser-or-app-frame-shown': { @@ -738,11 +720,10 @@ var Input = { this._currentIndex = 0; }, - updateModes: function updateModes(aPrefsBranch) { - try { - this.modes = aPrefsBranch.getCharPref('quicknav_modes').split(','); - } catch (x) { - // Fallback + updateModes: function updateModes(aModes) { + if (aModes) { + this.modes = aModes.split(','); + } else { this.modes = []; } }, diff --git a/accessible/src/jsat/Utils.jsm b/accessible/src/jsat/Utils.jsm index 8fd2ac0375b4..47b9d450ca15 100644 --- a/accessible/src/jsat/Utils.jsm +++ b/accessible/src/jsat/Utils.jsm @@ -8,10 +8,13 @@ const Cu = Components.utils; const Cc = Components.classes; const Ci = Components.interfaces; -Cu.import('resource://gre/modules/Services.jsm'); -Cu.import('resource://gre/modules/Geometry.jsm'); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, 'Services', + 'resource://gre/modules/Services.jsm'); +XPCOMUtils.defineLazyModuleGetter(this, 'Rect', + 'resource://gre/modules/Geometry.jsm'); -this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext']; +this.EXPORTED_SYMBOLS = ['Utils', 'Logger', 'PivotContext', 'PrefCache']; this.Utils = { _buildAppMap: { @@ -426,4 +429,55 @@ PivotContext.prototype = { return true; } } +}; + +this.PrefCache = function PrefCache(aName, aCallback, aRunCallbackNow) { + this.name = aName; + this.callback = aCallback; + + let branch = Services.prefs; + this.value = this._getValue(branch); + + if (this.callback && aRunCallbackNow) { + try { + this.callback(this.name, this.value); + } catch (x) { + Logger.logException(x); + } + } + + branch.addObserver(aName, this, true); +}; + +PrefCache.prototype = { + _getValue: function _getValue(aBranch) { + if (!this.type) { + this.type = aBranch.getPrefType(this.name); + } + + switch (this.type) { + case Ci.nsIPrefBranch.PREF_STRING: + return aBranch.getCharPref(this.name); + case Ci.nsIPrefBranch.PREF_INT: + return aBranch.getIntPref(this.name); + case Ci.nsIPrefBranch.PREF_BOOL: + return aBranch.getBoolPref(this.name); + default: + return null; + } + }, + + observe: function observe(aSubject, aTopic, aData) { + this.value = this._getValue(aSubject.QueryInterface(Ci.nsIPrefBranch)); + if (this.callback) { + try { + this.callback(this.name, this.value); + } catch (x) { + Logger.logException(x); + } + } + }, + + QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver, + Ci.nsISupportsWeakReference]) }; \ No newline at end of file diff --git a/accessible/src/jsat/UtteranceGenerator.jsm b/accessible/src/jsat/UtteranceGenerator.jsm index 4852554943ca..bbb9e03f5f30 100644 --- a/accessible/src/jsat/UtteranceGenerator.jsm +++ b/accessible/src/jsat/UtteranceGenerator.jsm @@ -15,29 +15,16 @@ const INCLUDE_CUSTOM = 0x04; const UTTERANCE_DESC_FIRST = 0; -// Read and observe changes to a setting for utterance order. -let gUtteranceOrder; -let prefsBranch = Cc['@mozilla.org/preferences-service;1'] - .getService(Ci.nsIPrefService).getBranch('accessibility.accessfu.'); -let observeUtterance = function observeUtterance(aSubject, aTopic, aData) { - try { - gUtteranceOrder = prefsBranch.getIntPref('utterance'); - } catch (x) { - gUtteranceOrder = UTTERANCE_DESC_FIRST; - } -}; -// Set initial gUtteranceOrder. -observeUtterance(); -prefsBranch.addObserver('utterance', observeUtterance, false); +Cu.import('resource://gre/modules/accessibility/Utils.jsm'); + +let gUtteranceOrder = new PrefCache('accessibility.accessfu.utterance'); var gStringBundle = Cc['@mozilla.org/intl/stringbundle;1']. getService(Ci.nsIStringBundleService). createBundle('chrome://global/locale/AccessFu.properties'); - this.EXPORTED_SYMBOLS = ['UtteranceGenerator']; -Cu.import('resource://gre/modules/accessibility/Utils.jsm'); /** * Generates speech utterances from objects, actions and state changes. @@ -88,7 +75,9 @@ this.UtteranceGenerator = { UtteranceGenerator.genForObject(aAccessible)); }; - if (gUtteranceOrder === UTTERANCE_DESC_FIRST) { + let utteranceOrder = gUtteranceOrder.value || UTTERANCE_DESC_FIRST; + + if (utteranceOrder === UTTERANCE_DESC_FIRST) { aContext.newAncestry.forEach(addUtterance); addUtterance(aContext.accessible); aContext.subtreePreorder.forEach(addUtterance); @@ -117,7 +106,7 @@ this.UtteranceGenerator = { let func = this.objectUtteranceFunctions[roleString] || this.objectUtteranceFunctions.defaultFunc; - let flags = this.verbosityRoleMap[roleString] || 0; + let flags = this.verbosityRoleMap[roleString] || UTTERANCE_DESC_FIRST; if (aAccessible.childCount == 0) flags |= INCLUDE_NAME; @@ -326,8 +315,10 @@ this.UtteranceGenerator = { _addName: function _addName(utterance, aAccessible, aFlags) { let name = (aFlags & INCLUDE_NAME) ? (aAccessible.name || '') : ''; + let utteranceOrder = gUtteranceOrder.value || 0; + if (name) { - utterance[gUtteranceOrder === UTTERANCE_DESC_FIRST ? + utterance[utteranceOrder === UTTERANCE_DESC_FIRST ? "push" : "unshift"](name); } },