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

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

Issue 586103004: Implement ChromeVox next/previous line, link, and heading. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkcr
Patch Set: Created 6 years, 3 months 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
« no previous file with comments | « chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2 ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 /** 5 /**
6 * @fileoverview The entry point for all ChromeVox2 related code for the 6 * @fileoverview The entry point for all ChromeVox2 related code for the
7 * background page. 7 * background page.
8 */ 8 */
9 9
10 goog.provide('cvox2.Background'); 10 goog.provide('cvox2.Background');
11 goog.provide('cvox2.global'); 11 goog.provide('cvox2.global');
12 12
13 /** Classic Chrome accessibility API. */ 13 /** Classic Chrome accessibility API. */
14 cvox2.global.accessibility = 14 cvox2.global.accessibility =
15 chrome.accessibilityPrivate || chrome.experimental.accessibility; 15 chrome.accessibilityPrivate || chrome.experimental.accessibility;
16 16
17 /** 17 /**
18 * ChromeVox2 background page. 18 * ChromeVox2 background page.
19 */ 19 */
20 cvox2.Background = function() { 20 cvox2.Background = function() {
21 /** 21 /**
22 * A list of site substring patterns to use with ChromeVox next. Keep these 22 * A list of site substring patterns to use with ChromeVox next. Keep these
23 * strings relatively specific. 23 * strings relatively specific.
24 * @type {!Array.<string>} 24 * @type {!Array.<string>}
25 */ 25 */
26 this.whitelist_ = ['http://www.chromevox.com/', 'chromevox_next_test']; 26 this.whitelist_ = ['http://www.chromevox.com/', 'chromevox_next_test'];
27 27
28 /** @type {AutomationElement} @private */
29 this.currentElement_ = null;
30
28 // Only needed with unmerged ChromeVox classic loaded before. 31 // Only needed with unmerged ChromeVox classic loaded before.
29 // TODO(dtseng): Refactor all tabs handlers out of 32 // TODO(dtseng): Refactor all tabs handlers out of
30 // accessibility_api_handler.js. 33 // accessibility_api_handler.js.
31 cvox2.global.accessibility.setAccessibilityEnabled(false); 34 cvox2.global.accessibility.setAccessibilityEnabled(false);
32 35
33 // Manually bind all functions to |this|. 36 // Manually bind all functions to |this|.
34 for (var func in this) { 37 for (var func in this) {
35 if (typeof(this[func]) == 'function') 38 if (typeof(this[func]) == 'function')
36 this[func] = this[func].bind(this); 39 this[func] = this[func].bind(this);
37 } 40 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 root.addEventListener(chrome.automation.EventType.focus, 82 root.addEventListener(chrome.automation.EventType.focus,
80 this.onAutomationEvent.bind(this), 83 this.onAutomationEvent.bind(this),
81 true); 84 true);
82 }, 85 },
83 86
84 /** 87 /**
85 * A generic handler for all desktop automation events. 88 * A generic handler for all desktop automation events.
86 * @param {AutomationEvent} evt The event. 89 * @param {AutomationEvent} evt The event.
87 */ 90 */
88 onAutomationEvent: function(evt) { 91 onAutomationEvent: function(evt) {
89 var output = evt.target.attributes.name + ' ' + evt.target.role; 92 switch (evt.type) {
90 cvox.ChromeVox.tts.speak(output, cvox.AbstractTts.QUEUE_MODE_FLUSH); 93 case 'focus':
91 cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output)); 94 this.onFocus(evt.target);
95 }
92 }, 96 },
93 97
94 /** 98 /**
95 * Handles chrome.commands.onCommand. 99 * Handles chrome.commands.onCommand.
96 * @param {string} command 100 * @param {string} command
97 */ 101 */
98 onGotCommand: function(command) { 102 onGotCommand: function(command) {
103 if (!this.current_)
104 return;
105
106 function find(cur, r, pred) {
107 if (pred(cur))
108 return cur;
109 var child = r ? cur.lastChild() : cur.firstChild();
110 while (child) {
111 var ret = find(child, r, pred);
112 if (ret)
113 return ret;
dmazzoni 2014/09/22 06:44:26 nit: indent
David Tseng 2014/09/22 23:45:34 Done.
114 child = r ? child.previousSibling() : child.nextSibling();
115 }
116 }
117
118 function findNextSubtree(cur, r) {
119 while (cur) {
120 var next = r ? cur.previousSibling() : cur.nextSibling();
121 if (next)
122 return next;
123
124 cur = cur.parent();
125 }
126 }
127
128 function moveNext(cur, r, pred) {
129 var next = cur;
130 do {
131 if (!(next = findNextSubtree(cur, r)))
132 return null;
133 cur = next;
134 next = find(next, r, pred);
135 } while (!next);
136 return next;
137 }
138
139 var previous = this.current_;
140 var current = this.current_;
141 switch (command) {
142 case 'nextHeading':
143 current = moveNext(current, false, function(e) {
144 return e.role == 'heading';
145 });
146 break;
147 case 'previousHeading':
148 current = moveNext(current, true, function(e) {
Peter Lundblad 2014/09/22 09:30:59 I think using predicates like this is nice. I sug
David Tseng 2014/09/22 23:45:34 Done.
149 return e.role == 'heading';
150 });
151 break;
152 case 'nextLine':
153 current = moveNext(current, false, function(e) {
154 return e.role == 'inlineTextBox';
dmazzoni 2014/09/22 06:44:26 FWIW, since inline text boxes aren't actually node
David Tseng 2014/09/22 23:41:29 I actually think leaving them in the tree will sim
155 });
156 break;
157 case 'previousLine':
158 current = moveNext(current, true, function(e) {
159 return e.role == 'inlineTextBox';
160 });
161 break;
162 case 'nextLink':
163 current = moveNext(current, false, function(e) {
164 return e.role == 'link';
165 });
166 break;
167 case 'previousLink':
168 current = moveNext(current, true, function(e) {
169 return e.role == 'link';
170 });
171 break;
172 }
173 if (current)
174 current.focus();
175 this.onFocus(current || previous);
99 }, 176 },
100 177
101 /** 178 /**
179 * Provides all feedback once ChromeVox's focus changes.
180 * @param {AutomationElement} element The newly focused element.
181 */
182 onFocus: function(element) {
183 var container = element;
184 while (container && (container.role == 'inlineTextBox' ||
185 container.role == 'staticText'))
186 container = container.parent();
187
188 var role = container ? container.role : element.role;
189
190 var output =
191 [element.attributes.name, element.attributes.value, role].join(',');
192 cvox.ChromeVox.tts.speak(output, cvox.AbstractTts.QUEUE_MODE_FLUSH);
193 cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output));
194 this.current_ = element;
195 },
196
197 /**
102 * @private 198 * @private
103 * @param {string} url 199 * @param {string} url
104 * @return {boolean} Whether the given |url| is whitelisted. 200 * @return {boolean} Whether the given |url| is whitelisted.
105 */ 201 */
106 isWhitelisted_: function(url) { 202 isWhitelisted_: function(url) {
107 return this.whitelist_.some(function(item) { 203 return this.whitelist_.some(function(item) {
108 return url.indexOf(item) != -1; 204 return url.indexOf(item) != -1;
109 }.bind(this)); 205 }.bind(this));
110 }, 206 },
111 207
112 /** 208 /**
113 * Disables classic ChromeVox. 209 * Disables classic ChromeVox.
114 * @param {number} tabId The tab where ChromeVox classic is running. 210 * @param {number} tabId The tab where ChromeVox classic is running.
115 */ 211 */
116 disableClassicChromeVox_: function(tabId) { 212 disableClassicChromeVox_: function(tabId) {
117 chrome.tabs.executeScript( 213 chrome.tabs.executeScript(
118 tabId, 214 tabId,
119 {'code': 'try { window.disableChromeVox(); } catch(e) { }\n', 215 {'code': 'try { window.disableChromeVox(); } catch(e) { }\n',
120 'allFrames': true}); 216 'allFrames': true});
121 } 217 }
122 }; 218 };
123 219
124 /** @type {cvox2.Background} */ 220 /** @type {cvox2.Background} */
125 cvox2.global.backgroundObj = new cvox2.Background(); 221 cvox2.global.backgroundObj = new cvox2.Background();
OLDNEW
« no previous file with comments | « chrome/browser/resources/chromeos/chromevox/manifest.json.jinja2 ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698