Commit 0021c75d authored by dmazzoni's avatar dmazzoni Committed by Commit bot

Get rid of deprecated live regions code from ChromeVox

BUG=none

Review URL: https://codereview.chromium.org/611473004

Cr-Commit-Position: refs/heads/master@{#297526}
parent 6bbd041d
...@@ -25,7 +25,6 @@ goog.require('cvox.DomUtil'); ...@@ -25,7 +25,6 @@ goog.require('cvox.DomUtil');
goog.require('cvox.Focuser'); goog.require('cvox.Focuser');
goog.require('cvox.History'); goog.require('cvox.History');
goog.require('cvox.LiveRegions'); goog.require('cvox.LiveRegions');
goog.require('cvox.LiveRegionsDeprecated');
goog.require('cvox.Memoize'); goog.require('cvox.Memoize');
goog.require('cvox.NavigationSpeaker'); goog.require('cvox.NavigationSpeaker');
goog.require('cvox.PlatformFilter'); // TODO: Find a better place for this. goog.require('cvox.PlatformFilter'); // TODO: Find a better place for this.
...@@ -59,26 +58,6 @@ cvox.ChromeVoxEventWatcher.MAX_WAIT_TIME_MS_ = 50; ...@@ -59,26 +58,6 @@ cvox.ChromeVoxEventWatcher.MAX_WAIT_TIME_MS_ = 50;
*/ */
cvox.ChromeVoxEventWatcher.WAIT_TIME_MS_ = 10; cvox.ChromeVoxEventWatcher.WAIT_TIME_MS_ = 10;
/**
* Amount of time in ms to wait before considering a subtree modified event to
* be the start of a new burst of subtree modified events.
* @const
* @type {number}
* @private
*/
cvox.ChromeVoxEventWatcher.SUBTREE_MODIFIED_BURST_DURATION_ = 1000;
/**
* Number of subtree modified events that are part of the same burst to process
* before we give up on processing any more events from that burst.
* @const
* @type {number}
* @private
*/
cvox.ChromeVoxEventWatcher.SUBTREE_MODIFIED_BURST_COUNT_LIMIT_ = 3;
/** /**
* Maximum number of live regions that we will attempt to process. * Maximum number of live regions that we will attempt to process.
* @const * @const
...@@ -246,20 +225,6 @@ cvox.ChromeVoxEventWatcher.secondPassThroughKeyUp_ = false; ...@@ -246,20 +225,6 @@ cvox.ChromeVoxEventWatcher.secondPassThroughKeyUp_ = false;
cvox.ChromeVoxEventWatcher.textMutationObserver_ = null; cvox.ChromeVoxEventWatcher.textMutationObserver_ = null;
cvox.ChromeVoxEventWatcher.addEventListeners_(doc); cvox.ChromeVoxEventWatcher.addEventListeners_(doc);
/**
* The time when the last burst of subtree modified events started
* @type {number}
* @private
*/
cvox.ChromeVoxEventWatcher.lastSubtreeModifiedEventBurstTime_ = 0;
/**
* The number of subtree modified events in the current burst.
* @type {number}
* @private
*/
cvox.ChromeVoxEventWatcher.subtreeModifiedEventsCount_ = 0;
}; };
...@@ -414,31 +379,26 @@ cvox.ChromeVoxEventWatcher.addEventListeners_ = function(doc) { ...@@ -414,31 +379,26 @@ cvox.ChromeVoxEventWatcher.addEventListeners_ = function(doc) {
cvox.ChromeVoxEventWatcher.addEventListener_(doc, cvox.ChromeVoxEventWatcher.addEventListener_(doc,
'click', cvox.ChromeVoxEventWatcher.mouseClickEventWatcher, true); 'click', cvox.ChromeVoxEventWatcher.mouseClickEventWatcher, true);
if (typeof(window.WebKitMutationObserver) != 'undefined') { cvox.ChromeVoxEventWatcher.mutationObserver_ =
cvox.ChromeVoxEventWatcher.mutationObserver_ = new window.WebKitMutationObserver(
new window.WebKitMutationObserver( cvox.ChromeVoxEventWatcher.mutationHandler);
cvox.ChromeVoxEventWatcher.mutationHandler); var observerTarget = null;
var observerTarget = null; if (doc.documentElement) {
if (doc.documentElement) { observerTarget = doc.documentElement;
observerTarget = doc.documentElement; } else if (doc.document && doc.document.documentElement) {
} else if (doc.document && doc.document.documentElement) { observerTarget = doc.document.documentElement;
observerTarget = doc.document.documentElement; }
} if (observerTarget) {
if (observerTarget) { cvox.ChromeVoxEventWatcher.mutationObserver_.observe(
cvox.ChromeVoxEventWatcher.mutationObserver_.observe( observerTarget,
observerTarget, /** @type {!MutationObserverInit} */ ({
/** @type {!MutationObserverInit} */ ({ childList: true,
childList: true, attributes: true,
attributes: true, characterData: true,
characterData: true, subtree: true,
subtree: true, attributeOldValue: true,
attributeOldValue: true, characterDataOldValue: true
characterDataOldValue: true }));
}));
}
} else {
cvox.ChromeVoxEventWatcher.addEventListener_(doc, 'DOMSubtreeModified',
cvox.ChromeVoxEventWatcher.subtreeModifiedEventWatcher, true);
} }
}; };
...@@ -951,20 +911,6 @@ cvox.ChromeVoxEventWatcher.selectEventWatcher = function(evt) { ...@@ -951,20 +911,6 @@ cvox.ChromeVoxEventWatcher.selectEventWatcher = function(evt) {
return true; return true;
}; };
/**
* Watches for DOM subtree modified events.
*
* @param {Event} evt The event to add to the queue.
* @return {boolean} True if the default action should be performed.
*/
cvox.ChromeVoxEventWatcher.subtreeModifiedEventWatcher = function(evt) {
if (!evt || !evt.target) {
return true;
}
cvox.ChromeVoxEventWatcher.addEvent(evt);
return true;
};
/** /**
* Listens for WebKit visibility change events. * Listens for WebKit visibility change events.
*/ */
...@@ -1000,47 +946,6 @@ cvox.ChromeVoxEventWatcher.speakLiveRegion_ = function( ...@@ -1000,47 +946,6 @@ cvox.ChromeVoxEventWatcher.speakLiveRegion_ = function(
descSpeaker.speakDescriptionArray(messages, queueMode, null); descSpeaker.speakDescriptionArray(messages, queueMode, null);
}; };
/**
* Handles DOM subtree modified events passed to it from the events queue.
* If the change involves an ARIA live region, then speak it.
*
* @param {Event} evt The event to handle.
*/
cvox.ChromeVoxEventWatcher.subtreeModifiedHandler = function(evt) {
// Subtree modified events can happen in bursts. If several events happen at
// the same time, trying to process all of them will slow ChromeVox to
// a crawl and make the page itself unresponsive (ie, Google+).
// Before processing subtree modified events, make sure that it is not part of
// a large burst of events.
// TODO (clchen): Revisit this after the DOM mutation events are
// available in Chrome.
var currentTime = new Date().getTime();
if ((cvox.ChromeVoxEventWatcher.lastSubtreeModifiedEventBurstTime_ +
cvox.ChromeVoxEventWatcher.SUBTREE_MODIFIED_BURST_DURATION_) >
currentTime) {
cvox.ChromeVoxEventWatcher.subtreeModifiedEventsCount_++;
if (cvox.ChromeVoxEventWatcher.subtreeModifiedEventsCount_ >
cvox.ChromeVoxEventWatcher.SUBTREE_MODIFIED_BURST_COUNT_LIMIT_) {
return;
}
} else {
cvox.ChromeVoxEventWatcher.lastSubtreeModifiedEventBurstTime_ = currentTime;
cvox.ChromeVoxEventWatcher.subtreeModifiedEventsCount_ = 1;
}
if (!evt || !evt.target) {
return;
}
var target = /** @type {Element} */ (evt.target);
var regions = cvox.AriaUtil.getLiveRegions(target);
for (var i = 0; (i < regions.length) &&
(i < cvox.ChromeVoxEventWatcher.MAX_LIVE_REGIONS_); i++) {
cvox.LiveRegionsDeprecated.updateLiveRegion(
regions[i], cvox.ChromeVoxEventWatcher.queueMode_(), false);
}
};
/** /**
* Sets up the text handler. * Sets up the text handler.
* @return {boolean} True if an editable text control has focus. * @return {boolean} True if an editable text control has focus.
...@@ -1443,8 +1348,7 @@ cvox.ChromeVoxEventWatcher.doProcessQueue_ = function() { ...@@ -1443,8 +1348,7 @@ cvox.ChromeVoxEventWatcher.doProcessQueue_ = function() {
cvox.ChromeVoxEventWatcher.events_ = []; cvox.ChromeVoxEventWatcher.events_ = [];
for (i = 0; evt = events[i]; i++) { for (i = 0; evt = events[i]; i++) {
var prevEvt = events[i - 1] || {}; var prevEvt = events[i - 1] || {};
if ((i >= lastFocusIndex || evt.type == 'LiveRegion' || if ((i >= lastFocusIndex || evt.type == 'LiveRegion') &&
evt.type == 'DOMSubtreeModified') &&
(prevEvt.type != 'focus' || evt.type != 'change')) { (prevEvt.type != 'focus' || evt.type != 'change')) {
cvox.ChromeVoxEventWatcher.events_.push(evt); cvox.ChromeVoxEventWatcher.events_.push(evt);
} }
...@@ -1454,9 +1358,6 @@ cvox.ChromeVoxEventWatcher.doProcessQueue_ = function() { ...@@ -1454,9 +1358,6 @@ cvox.ChromeVoxEventWatcher.doProcessQueue_ = function() {
if (b.type != 'LiveRegion' && a.type == 'LiveRegion') { if (b.type != 'LiveRegion' && a.type == 'LiveRegion') {
return 1; return 1;
} }
if (b.type != 'DOMSubtreeModified' && a.type == 'DOMSubtreeModified') {
return 1;
}
return -1; return -1;
}); });
...@@ -1534,9 +1435,6 @@ cvox.ChromeVoxEventWatcher.handleEvent_ = function(evt) { ...@@ -1534,9 +1435,6 @@ cvox.ChromeVoxEventWatcher.handleEvent_ = function(evt) {
cvox.ChromeVoxEventWatcher.speakLiveRegion_( cvox.ChromeVoxEventWatcher.speakLiveRegion_(
evt.assertive, evt.navDescriptions); evt.assertive, evt.navDescriptions);
break; break;
case 'DOMSubtreeModified':
cvox.ChromeVoxEventWatcher.subtreeModifiedHandler(evt);
break;
} }
}; };
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Keeps track of live regions on the page and speaks updates
* when they change.
*
*/
goog.provide('cvox.LiveRegionsDeprecated');
goog.require('cvox.AriaUtil');
goog.require('cvox.ChromeVox');
goog.require('cvox.DescriptionUtil');
goog.require('cvox.DomUtil');
goog.require('cvox.NavDescription');
/**
* @constructor
*/
cvox.LiveRegionsDeprecated = function() {
};
/**
* An array of all of the elements on the page that are live regions.
* @type {Array.<Element>}
*/
cvox.LiveRegionsDeprecated.trackedRegions = [];
/**
* A parallel array to trackedRegions that stores the previous value of
* each live region, represented as an array of NavDescriptions.
* @type {Array.<Array.<cvox.NavDescription> >}
*/
cvox.LiveRegionsDeprecated.previousRegionValue = [];
/**
* @type {Date}
*/
cvox.LiveRegionsDeprecated.pageLoadTime = null;
/**
* Time in milliseconds after initial page load to ignore live region
* updates, to avoid announcing regions as they're initially created.
* The exception is alerts, they're announced when a page is loaded.
* @type {number}
* @const
*/
cvox.LiveRegionsDeprecated.INITIAL_SILENCE_MS = 2000;
/**
* @param {Date} pageLoadTime The time the page was loaded. Live region
* updates within the first INITIAL_SILENCE_MS milliseconds are ignored.
* @param {number} queueMode Interrupt or flush. Polite live region
* changes always queue.
* @param {boolean} disableSpeak true if change announcement should be disabled.
* @return {boolean} true if any regions announced.
*/
cvox.LiveRegionsDeprecated.init = function(pageLoadTime, queueMode, disableSpeak) {
if (queueMode == undefined) {
queueMode = cvox.AbstractTts.QUEUE_MODE_FLUSH;
}
cvox.LiveRegionsDeprecated.pageLoadTime = pageLoadTime;
var anyRegionsAnnounced = false;
var regions = cvox.AriaUtil.getLiveRegions(document.body);
for (var i = 0; i < regions.length; i++) {
if (cvox.LiveRegionsDeprecated.updateLiveRegion(regions[i], queueMode,
disableSpeak)) {
anyRegionsAnnounced = true;
queueMode = cvox.AbstractTts.QUEUE_MODE_QUEUE;
}
}
return anyRegionsAnnounced;
};
/**
* Speak relevant changes to a live region.
*
* @param {Node} region The live region node that changed.
* @param {number} queueMode Interrupt or queue. Polite live region
* changes always queue.
* @param {boolean} disableSpeak true if change announcement should be disabled.
* @return {boolean} true if the region announced a change.
*/
cvox.LiveRegionsDeprecated.updateLiveRegion = function(region, queueMode, disableSpeak) {
if (cvox.AriaUtil.getAriaBusy(region)) {
return false;
}
// Make sure it's visible.
if (!cvox.DomUtil.isVisible(region)) {
return false;
}
// Retrieve the previous value of this region if we've tracked it
// before, otherwise start tracking it.
var regionIndex = cvox.LiveRegionsDeprecated.trackedRegions.indexOf(region);
var previousValue;
if (regionIndex >= 0) {
previousValue = cvox.LiveRegionsDeprecated.previousRegionValue[regionIndex];
} else {
regionIndex = cvox.LiveRegionsDeprecated.trackedRegions.length;
previousValue = [];
cvox.LiveRegionsDeprecated.trackedRegions.push(region);
cvox.LiveRegionsDeprecated.previousRegionValue.push([]);
}
// Get the new value.
var currentValue = cvox.LiveRegionsDeprecated.buildCurrentLiveRegionValue(region);
// If the page just loaded and this is any region type other than 'alert',
// keep track of the new value but don't announce anything. Alerts are
// the exception, they're announced on page load.
var deltaTime = new Date() - cvox.LiveRegionsDeprecated.pageLoadTime;
if (cvox.AriaUtil.getRoleAttribute(region) != 'alert' &&
deltaTime < cvox.LiveRegionsDeprecated.INITIAL_SILENCE_MS) {
cvox.LiveRegionsDeprecated.previousRegionValue[regionIndex] = currentValue;
return false;
}
// Don't announce alerts on page load if their text and values consist of
// just whitespace.
if (cvox.AriaUtil.getRoleAttribute(region) == 'alert' &&
deltaTime < cvox.LiveRegionsDeprecated.INITIAL_SILENCE_MS) {
var regionText = '';
for (var i = 0; i < currentValue.length; i++) {
regionText += currentValue[i].text;
regionText += currentValue[i].userValue;
}
if (cvox.DomUtil.collapseWhitespace(regionText) == '') {
cvox.LiveRegionsDeprecated.previousRegionValue[regionIndex] = currentValue;
return false;
}
}
// Create maps of values in the live region for fast hash lookup.
var previousValueMap = {};
for (var i = 0; i < previousValue.length; i++) {
previousValueMap[previousValue[i].toString()] = true;
}
var currentValueMap = {};
for (i = 0; i < currentValue.length; i++) {
currentValueMap[currentValue[i].toString()] = true;
}
// Figure out the additions and removals.
var additions = [];
if (cvox.AriaUtil.getAriaRelevant(region, 'additions')) {
for (i = 0; i < currentValue.length; i++) {
if (!previousValueMap[currentValue[i].toString()]) {
additions.push(currentValue[i]);
}
}
}
var removals = [];
if (cvox.AriaUtil.getAriaRelevant(region, 'removals')) {
for (i = 0; i < previousValue.length; i++) {
if (!currentValueMap[previousValue[i].toString()]) {
removals.push(previousValue[i]);
}
}
}
// Only speak removals if they're the only change. Otherwise, when one or
// more removals and additions happen concurrently, treat it as a change
// and just speak any additions (which includes changed nodes).
var messages = [];
if (additions.length == 0 && removals.length > 0) {
messages = [new cvox.NavDescription({
context: cvox.ChromeVox.msgs.getMsg('live_regions_removed'), text: ''
})].concat(removals);
} else {
messages = additions;
}
// Store the new value of the live region.
cvox.LiveRegionsDeprecated.previousRegionValue[regionIndex] = currentValue;
// Return if speak is disabled or there's nothing to announce.
if (disableSpeak || messages.length == 0) {
return false;
}
// Announce the changes with the appropriate politeness level.
var live = cvox.AriaUtil.getAriaLive(region);
if (live == 'polite') {
queueMode = cvox.AbstractTts.QUEUE_MODE_QUEUE;
}
for (i = 0; i < messages.length; i++) {
messages[i].speak(queueMode);
queueMode = cvox.AbstractTts.QUEUE_MODE_QUEUE;
}
return true;
};
/**
* Recursively build up the value of a live region and return it as
* an array of NavDescriptions. Each atomic portion of the region gets a
* single string, otherwise each leaf node gets its own string. When a region
* changes, the sets of strings before and after are searched to determine
* which have changed.
*
* @param {Node} node The root node.
* @return {Array.<cvox.NavDescription>} An array of NavDescriptions
* describing atomic nodes or leaf nodes in the subtree rooted
* at this node.
*/
cvox.LiveRegionsDeprecated.buildCurrentLiveRegionValue = function(node) {
if (cvox.AriaUtil.getAriaAtomic(node) ||
cvox.DomUtil.isLeafNode(node)) {
var description = cvox.DescriptionUtil.getDescriptionFromAncestors(
[node], true, cvox.ChromeVox.verbosity);
if (!description.isEmpty()) {
return [description];
} else {
return [];
}
}
var result = [];
// Start with the description of this node.
var description = cvox.DescriptionUtil.getDescriptionFromAncestors(
[node], false, cvox.ChromeVox.verbosity);
if (!description.isEmpty()) {
result.push(description);
}
// Recursively add descriptions of child nodes.
for (var i = 0; i < node.childNodes.length; i++) {
var child = node.childNodes[i];
if (cvox.DomUtil.isVisible(child, {checkAncestors: false}) &&
!cvox.AriaUtil.isHidden(child)) {
var recursiveArray = cvox.LiveRegionsDeprecated.buildCurrentLiveRegionValue(child);
result = result.concat(recursiveArray);
}
}
return result;
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment