From d91e6148b0ccd3df752969c7ef98bd66024acdca Mon Sep 17 00:00:00 2001 From: Yura Zenevich Date: Thu, 28 Aug 2014 09:07:30 -0400 Subject: [PATCH] Bug 1054454 - added support for aria-hidden attribute changes. Added output filter wh when presenting aria-hidden elements. r=eeejay --- accessible/jsat/AccessFu.jsm | 4 + accessible/jsat/EventManager.jsm | 92 ++++++++++----- accessible/jsat/Utils.jsm | 14 ++- .../mochitest/jsat/doc_content_integration.html | 17 +++ .../mochitest/jsat/test_content_integration.html | 67 +++++++++++ .../tests/mochitest/jsat/test_live_regions.html | 129 ++++++++++++++++++++- 6 files changed, 287 insertions(+), 36 deletions(-) --- accessible/jsat/AccessFu.jsm | 4 + accessible/jsat/EventManager.jsm | 92 +++++++++---- accessible/jsat/Utils.jsm | 14 +- .../jsat/doc_content_integration.html | 17 +++ .../jsat/test_content_integration.html | 67 +++++++++ .../mochitest/jsat/test_live_regions.html | 129 +++++++++++++++++- 6 files changed, 287 insertions(+), 36 deletions(-) diff --git a/accessible/jsat/AccessFu.jsm b/accessible/jsat/AccessFu.jsm index abe46cd5a29..56e3049f629 100644 --- a/accessible/jsat/AccessFu.jsm +++ b/accessible/jsat/AccessFu.jsm @@ -235,6 +235,10 @@ this.AccessFu = { // jshint ignore:line }, _output: function _output(aPresentationData, aBrowser) { + if (!Utils.isAliveAndVisible( + Utils.AccRetrieval.getAccessibleFor(aBrowser))) { + return; + } for (let presenter of aPresentationData) { if (!presenter) { continue; diff --git a/accessible/jsat/EventManager.jsm b/accessible/jsat/EventManager.jsm index 50f0ed007d5..35630b523e3 100644 --- a/accessible/jsat/EventManager.jsm +++ b/accessible/jsat/EventManager.jsm @@ -225,43 +225,30 @@ this.EventManager.prototype = { this.editState = editState; break; } + case Events.OBJECT_ATTRIBUTE_CHANGED: + { + let evt = aEvent.QueryInterface( + Ci.nsIAccessibleObjectAttributeChangedEvent); + if (evt.changedAttribute.toString() !== 'aria-hidden') { + // Only handle aria-hidden attribute change. + break; + } + if (Utils.isHidden(aEvent.accessible)) { + this._handleHide(evt); + } else { + this._handleShow(aEvent); + } + break; + } case Events.SHOW: { - let {liveRegion, isPolite} = this._handleLiveRegion(aEvent, - ['additions', 'all']); - // Only handle show if it is a relevant live region. - if (!liveRegion) { - break; - } - // Show for text is handled by the EVENT_TEXT_INSERTED handler. - if (aEvent.accessible.role === Roles.TEXT_LEAF) { - break; - } - this._dequeueLiveEvent(Events.HIDE, liveRegion); - this.present(Presentation.liveRegion(liveRegion, isPolite, false)); + this._handleShow(aEvent); break; } case Events.HIDE: { let evt = aEvent.QueryInterface(Ci.nsIAccessibleHideEvent); - let {liveRegion, isPolite} = this._handleLiveRegion( - evt, ['removals', 'all']); - if (liveRegion) { - // Hide for text is handled by the EVENT_TEXT_REMOVED handler. - if (aEvent.accessible.role === Roles.TEXT_LEAF) { - break; - } - this._queueLiveEvent(Events.HIDE, liveRegion, isPolite); - } else { - let vc = Utils.getVirtualCursor(this.contentScope.content.document); - if (vc.position && - (Utils.getState(vc.position).contains(States.DEFUNCT) || - Utils.isInSubtree(vc.position, aEvent.accessible))) { - this.contentControl.autoMove( - evt.targetPrevSibling || evt.targetParent, - { moveToFocused: true, delay: 500 }); - } - } + this._handleHide(evt); break; } case Events.TEXT_INSERTED: @@ -306,6 +293,51 @@ this.EventManager.prototype = { } }, + _handleShow: function _handleShow(aEvent) { + let {liveRegion, isPolite} = this._handleLiveRegion(aEvent, + ['additions', 'all']); + // Only handle show if it is a relevant live region. + if (!liveRegion) { + return; + } + // Show for text is handled by the EVENT_TEXT_INSERTED handler. + if (aEvent.accessible.role === Roles.TEXT_LEAF) { + return; + } + this._dequeueLiveEvent(Events.HIDE, liveRegion); + this.present(Presentation.liveRegion(liveRegion, isPolite, false)); + }, + + _handleHide: function _handleHide(aEvent) { + let {liveRegion, isPolite} = this._handleLiveRegion( + aEvent, ['removals', 'all']); + let acc = aEvent.accessible; + if (liveRegion) { + // Hide for text is handled by the EVENT_TEXT_REMOVED handler. + if (acc.role === Roles.TEXT_LEAF) { + return; + } + this._queueLiveEvent(Events.HIDE, liveRegion, isPolite); + } else { + let vc = Utils.getVirtualCursor(this.contentScope.content.document); + if (vc.position && + (Utils.getState(vc.position).contains(States.DEFUNCT) || + Utils.isInSubtree(vc.position, acc))) { + let position = aEvent.targetPrevSibling || aEvent.targetParent; + if (!position) { + try { + position = acc.previousSibling; + } catch (x) { + // Accessible is unattached from the accessible tree. + position = acc.parent; + } + } + this.contentControl.autoMove(position, + { moveToFocused: true, delay: 500 }); + } + } + }, + _handleText: function _handleText(aEvent, aLiveRegion, aIsPolite) { let event = aEvent.QueryInterface(Ci.nsIAccessibleTextChangeEvent); let isInserted = event.isInserted; diff --git a/accessible/jsat/Utils.jsm b/accessible/jsat/Utils.jsm index 2ef4a2dfe83..bf1ed05592e 100644 --- a/accessible/jsat/Utils.jsm +++ b/accessible/jsat/Utils.jsm @@ -353,10 +353,16 @@ this.Utils = { // jshint ignore:line return false; }, + isHidden: function isHidden(aAccessible) { + // Need to account for aria-hidden, so can't just check for INVISIBLE + // state. + let hidden = Utils.getAttributes(aAccessible).hidden; + return hidden && hidden === 'true'; + }, + inHiddenSubtree: function inHiddenSubtree(aAccessible) { for (let acc=aAccessible; acc; acc=acc.parent) { - let hidden = Utils.getAttributes(acc).hidden; - if (hidden && JSON.parse(hidden)) { + if (this.isHidden(acc)) { return true; } } @@ -789,9 +795,7 @@ PivotContext.prototype = { if (this._includeInvisible) { include = true; } else { - // Need to account for aria-hidden, so can't just check for INVISIBLE - // state. - include = Utils.getAttributes(child).hidden !== 'true'; + include = !Utils.isHidden(child); } if (include) { if (aPreorder) { diff --git a/accessible/tests/mochitest/jsat/doc_content_integration.html b/accessible/tests/mochitest/jsat/doc_content_integration.html index feef05cf2ab..a59b6f8f4f9 100644 --- a/accessible/tests/mochitest/jsat/doc_content_integration.html +++ b/accessible/tests/mochitest/jsat/doc_content_integration.html @@ -24,6 +24,22 @@ document.getElementById('alert').hidden = true; } + function ariaShowBack() { + document.getElementById('back').setAttribute('aria-hidden', false); + } + + function ariaHideBack() { + document.getElementById('back').setAttribute('aria-hidden', true); + } + + function ariaShowIframe() { + document.getElementById('iframe').setAttribute('aria-hidden', false); + } + + function ariaHideIframe() { + document.getElementById('iframe').setAttribute('aria-hidden', true); + } +