Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(365)

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/cvox2/background/live_regions.js

Issue 1457683009: Complete live region support in ChromeVox Next. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed last feedback Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * @fileoverview Implements support for live regions in ChromeVox Next.
7 */
8
9 goog.provide('LiveRegions');
10
11 goog.require('ChromeVoxState');
12
13 goog.scope(function() {
14 var AutomationNode = chrome.automation.AutomationNode;
15 var TreeChange = chrome.automation.TreeChange;
16
17 /**
18 * ChromeVox2 live region handler.
19 * @param {!ChromeVoxState} chromeVoxState The ChromeVox state object,
20 * keeping track of the current mode and current range.
21 * @constructor
22 */
23 LiveRegions = function(chromeVoxState) {
24 /**
25 * @type {!ChromeVoxState}
26 * @private
27 */
28 this.chromeVoxState_ = chromeVoxState;
29
30 /**
31 * The time the last live region event was output.
32 * @type {!Date}
33 * @private
34 */
35 this.lastLiveRegionTime_ = new Date(0);
36
37 /**
38 * Set of nodes that have been announced as part of a live region since
39 * |this.lastLiveRegionTime_|, to prevent duplicate announcements.
40 * @type {!WeakSet<AutomationNode>}
41 * @private
42 */
43 this.liveRegionNodeSet_ = new WeakSet();
44
45 chrome.automation.addTreeChangeObserver(
46 'liveRegionTreeChanges', this.onTreeChange.bind(this));
47 };
48
49 /**
50 * Live region events received in fewer than this many milliseconds will
51 * queue, otherwise they'll be output with a category flush.
52 * @type {number}
53 * @const
54 */
55 LiveRegions.LIVE_REGION_QUEUE_TIME_MS = 500;
56
57 /**
58 * Whether live regions from background tabs should be announced or not.
59 * @type {boolean}
60 * @private
61 */
62 LiveRegions.announceLiveRegionsFromBackgroundTabs_ = true;
63
64 LiveRegions.prototype = {
65 /**
66 * Called when the automation tree is changed.
67 * @param {TreeChange} treeChange
68 */
69 onTreeChange: function(treeChange) {
70 var node = treeChange.target;
71 if (!node.containerLiveStatus)
72 return;
73
74 var mode = this.chromeVoxState_.mode;
75 var currentRange = this.chromeVoxState_.currentRange;
76
77 if (mode === ChromeVoxMode.CLASSIC || !cvox.ChromeVox.isActive)
78 return;
79
80 if (!currentRange)
81 return;
82
83 if (!LiveRegions.announceLiveRegionsFromBackgroundTabs_ &&
84 !AutomationUtil.isInSameWebpage(node, currentRange.start.node)) {
85 return;
86 }
87
88 var type = treeChange.type;
89 var relevant = node.containerLiveRelevant;
90 if (relevant.indexOf('additions') >= 0 &&
91 (type == 'nodeCreated' || type == 'subtreeCreated')) {
92 this.outputLiveRegionChange_(node, null);
93 }
94
95 if (relevant.indexOf('text') >= 0 && type == 'nodeChanged')
96 this.outputLiveRegionChange_(node, null);
97
98 if (relevant.indexOf('removals') >= 0 && type == 'nodeRemoved')
99 this.outputLiveRegionChange_(node, '@live_regions_removed');
100 },
101
102 /**
103 * Given a node that needs to be spoken as part of a live region
104 * change and an additional optional format string, output the
105 * live region description.
106 * @param {!AutomationNode} node The changed node.
107 * @param {?string=} opt_prependFormatStr If set, a format string for
108 * cvox2.Output to prepend to the output.
109 * @private
110 */
111 outputLiveRegionChange_: function(node, opt_prependFormatStr) {
112 if (node.containerLiveBusy)
113 return;
114
115 if (node.containerLiveAtomic && !node.liveAtomic) {
116 if (node.parent)
117 this.outputLiveRegionChange_(node.parent, opt_prependFormatStr);
118 return;
119 }
120
121 var range = cursors.Range.fromNode(node);
122 var output = new Output();
123 if (opt_prependFormatStr)
124 output.format(opt_prependFormatStr);
125 output.withSpeech(range, range, Output.EventType.NAVIGATE);
126
127 if (!output.hasSpeech && node.liveAtomic)
128 output.format('$descendants', node);
129
130 output.withSpeechCategory(cvox.TtsCategory.LIVE);
131
132 if (!output.hasSpeech)
133 return;
134
135 // Enqueue live region updates that were received at approximately
136 // the same time, otherwise flush previous live region updates.
137 var currentTime = new Date();
138 var queueTime = LiveRegions.LIVE_REGION_QUEUE_TIME_MS;
139 if (currentTime - this.lastLiveRegionTime_ > queueTime) {
140 this.liveRegionNodeSet_ = new WeakSet();
141 output.withQueueMode(cvox.QueueMode.CATEGORY_FLUSH);
142 this.lastLiveRegionTime_ = currentTime;
143 } else {
144 output.withQueueMode(cvox.QueueMode.QUEUE);
145 }
146
147 var parent = node;
148 while (parent) {
149 if (this.liveRegionNodeSet_.has(parent))
150 return;
151 parent = parent.parent;
152 }
153
154 this.liveRegionNodeSet_.add(node);
155 output.go();
156 },
157 };
158
159 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698