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

Side by Side Diff: chrome/browser/resources/chromeos/chromevox/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: Address comments. Created 6 years, 2 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
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 goog.require('cvox.TabsApiHandler'); 13 goog.require('cvox.TabsApiHandler');
14 goog.require('cvox2.AutomationPredicates');
15 goog.require('cvox2.AutomationUtil');
16 goog.require('cvox2.Dir');
14 17
15 /** Classic Chrome accessibility API. */ 18 /** Classic Chrome accessibility API. */
16 cvox2.global.accessibility = 19 cvox2.global.accessibility =
17 chrome.accessibilityPrivate || chrome.experimental.accessibility; 20 chrome.accessibilityPrivate || chrome.experimental.accessibility;
18 21
19 /** 22 /**
20 * ChromeVox2 background page. 23 * ChromeVox2 background page.
21 */ 24 */
22 cvox2.Background = function() { 25 cvox2.Background = function() {
23 /** 26 /**
24 * A list of site substring patterns to use with ChromeVox next. Keep these 27 * A list of site substring patterns to use with ChromeVox next. Keep these
25 * strings relatively specific. 28 * strings relatively specific.
26 * @type {!Array.<string>} 29 * @type {!Array.<string>}
27 */ 30 */
28 this.whitelist_ = ['http://www.chromevox.com/', 'chromevox_next_test']; 31 this.whitelist_ = ['http://www.chromevox.com/', 'chromevox_next_test'];
29 32
30 /** @type {cvox.TabsApiHandler} @private */ 33 /** @type {cvox.TabsApiHandler} @private */
31 this.tabsHandler_ = new cvox.TabsApiHandler(cvox.ChromeVox.tts, 34 this.tabsHandler_ = new cvox.TabsApiHandler(cvox.ChromeVox.tts,
32 cvox.ChromeVox.braille, 35 cvox.ChromeVox.braille,
33 cvox.ChromeVox.earcons); 36 cvox.ChromeVox.earcons);
34 37
38 /** @type {AutomationNode} @private */
39 this.currentNode_ = null;
40
41 /** @type {cvox.TabsApiHandler} @private */
42 this.tabsHandler_ = new cvox.TabsApiHandler(cvox.ChromeVox.tts,
43 cvox.ChromeVox.braille,
44 cvox.ChromeVox.earcons);
45
35 // Only needed with unmerged ChromeVox classic loaded before. 46 // Only needed with unmerged ChromeVox classic loaded before.
36 cvox2.global.accessibility.setAccessibilityEnabled(false); 47 cvox2.global.accessibility.setAccessibilityEnabled(false);
37 48
38 // Manually bind all functions to |this|. 49 // Manually bind all functions to |this|.
39 for (var func in this) { 50 for (var func in this) {
40 if (typeof(this[func]) == 'function') 51 if (typeof(this[func]) == 'function')
41 this[func] = this[func].bind(this); 52 this[func] = this[func].bind(this);
42 } 53 }
43 54
44 // Register listeners for ... 55 // Register listeners for ...
(...skipping 14 matching lines...) Expand all
59 chrome.tabs.get(tabId, function(tab) { 70 chrome.tabs.get(tabId, function(tab) {
60 if (!tab.url) 71 if (!tab.url)
61 return; 72 return;
62 73
63 if (!this.isWhitelisted_(tab.url)) { 74 if (!this.isWhitelisted_(tab.url)) {
64 chrome.commands.onCommand.removeListener(this.onGotCommand); 75 chrome.commands.onCommand.removeListener(this.onGotCommand);
65 cvox.ChromeVox.background.injectChromeVoxIntoTabs([tab], true); 76 cvox.ChromeVox.background.injectChromeVoxIntoTabs([tab], true);
66 return; 77 return;
67 } 78 }
68 79
69 if (!chrome.commands.onCommand.hasListeners()) { 80 if (!chrome.commands.onCommand.hasListeners())
70 chrome.commands.onCommand.addListener(this.onGotCommand); 81 chrome.commands.onCommand.addListener(this.onGotCommand);
71 }
72 82
73 this.disableClassicChromeVox_(tab.id); 83 this.disableClassicChromeVox_(tab.id);
74 84
75 chrome.automation.getTree(this.onGotTree.bind(this)); 85 chrome.automation.getTree(this.onGotTree.bind(this));
76 }.bind(this)); 86 }.bind(this));
77 }, 87 },
78 88
79 /** 89 /**
80 * Handles all setup once a new automation tree appears. 90 * Handles all setup once a new automation tree appears.
81 * @param {AutomationTree} tree The new automation tree. 91 * @param {AutomationTree} tree The new automation tree.
82 */ 92 */
83 onGotTree: function(root) { 93 onGotTree: function(root) {
84 // Register all automation event listeners. 94 // Register all automation event listeners.
85 root.addEventListener(chrome.automation.EventType.focus, 95 root.addEventListener(chrome.automation.EventType.focus,
86 this.onAutomationEvent.bind(this), 96 this.onFocus,
87 true); 97 true);
88 }, 98 root.addEventListener(chrome.automation.EventType.loadComplete,
99 this.onLoadComplete,
100 true);
89 101
90 /** 102 if (root.attributes.docLoaded)
91 * A generic handler for all desktop automation events. 103 this.onLoadComplete({target: root});
92 * @param {AutomationEvent} evt The event.
93 */
94 onAutomationEvent: function(evt) {
95 var output = evt.target.attributes.name + ' ' + evt.target.role;
96 cvox.ChromeVox.tts.speak(output, cvox.AbstractTts.QUEUE_MODE_FLUSH);
97 cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output));
98 chrome.accessibilityPrivate.setFocusRing([evt.target.location]);
99 }, 104 },
100 105
101 /** 106 /**
102 * Handles chrome.commands.onCommand. 107 * Handles chrome.commands.onCommand.
103 * @param {string} command 108 * @param {string} command
104 */ 109 */
105 onGotCommand: function(command) { 110 onGotCommand: function(command) {
111 if (!this.current_)
112 return;
113
114 var previous = this.current_;
115 var current = this.current_;
116
117 var dir = cvox2.Dir.FORWARD;
118 var pred = null;
119 switch (command) {
120 case 'nextHeading':
121 dir = cvox2.Dir.FORWARD;
122 pred = cvox2.AutomationPredicates.heading;
123 break;
124 case 'previousHeading':
125 dir = cvox2.Dir.BACKWARD;
126 pred = cvox2.AutomationPredicates.heading;
127 break;
128 case 'nextLine':
129 dir = cvox2.Dir.FORWARD;
130 pred = cvox2.AutomationPredicates.inlineTextBox;
131 break;
132 case 'previousLine':
133 dir = cvox2.Dir.BACKWARD;
134 pred = cvox2.AutomationPredicates.inlineTextBox;
135 break;
136 case 'nextLink':
137 dir = cvox2.Dir.FORWARD;
138 pred = cvox2.AutomationPredicates.link;
139 break;
140 case 'previousLink':
141 dir = cvox2.Dir.BACKWARD;
142 pred = cvox2.AutomationPredicates.link;
143 break;
144 case 'nextElement':
145 current = current.role == chrome.automation.RoleType.inlineTextBox ?
146 current.parent() : current;
147 current = cvox2.AutomationUtil.findNextNode(current,
148 cvox2.Dir.FORWARD,
149 cvox2.AutomationPredicates.inlineTextBox);
150 current = current ? current.parent() : current;
151 break;
152 case 'previousElement':
153 current = current.role == chrome.automation.RoleType.inlineTextBox ?
154 current.parent() : current;
155 current = cvox2.AutomationUtil.findNextNode(current,
156 cvox2.Dir.BACKWARD,
157 cvox2.AutomationPredicates.inlineTextBox);
158 current = current ? current.parent() : current;
159 break;
160 }
161
162 if (pred)
163 current = cvox2.AutomationUtil.findNextNode(current, dir, pred);
164
165 if (current)
166 current.focus();
167
168 this.onFocus({target: current || previous});
106 }, 169 },
107 170
108 /** 171 /**
172 * Provides all feedback once ChromeVox's focus changes.
173 * @param {Object} evt
174 */
175 onFocus: function(evt) {
176 var node = evt.target;
177 if (!node)
178 return;
179 var container = node;
180 while (container && (container.role == 'inlineTextBox' ||
181 container.role == 'staticText'))
182 container = container.parent();
183
184 var role = container ? container.role : node.role;
185
186 var output =
187 [node.attributes.name, node.attributes.value, role].join(', ');
188 cvox.ChromeVox.tts.speak(output, cvox.AbstractTts.QUEUE_MODE_FLUSH);
189 cvox.ChromeVox.braille.write(cvox.NavBraille.fromText(output));
190 chrome.accessibilityPrivate.setFocusRing([evt.target.location]);
191
192 this.current_ = node;
193 },
194
195 /**
196 * Provides all feedback once a load complete event fires.
197 * @param {Object} evt
198 */
199 onLoadComplete: function(evt) {
200 this.current_ = cvox2.AutomationUtil.findNodePost(evt.target,
201 cvox2.Dir.FORWARD,
202 cvox2.AutomationPredicates.inlineTextBox);
203 this.onFocus({target: this.current_});
204 },
205
206 /**
109 * @private 207 * @private
110 * @param {string} url 208 * @param {string} url
111 * @return {boolean} Whether the given |url| is whitelisted. 209 * @return {boolean} Whether the given |url| is whitelisted.
112 */ 210 */
113 isWhitelisted_: function(url) { 211 isWhitelisted_: function(url) {
114 return this.whitelist_.some(function(item) { 212 return this.whitelist_.some(function(item) {
115 return url.indexOf(item) != -1; 213 return url.indexOf(item) != -1;
116 }.bind(this)); 214 }.bind(this));
117 }, 215 },
118 216
119 /** 217 /**
120 * Disables classic ChromeVox. 218 * Disables classic ChromeVox.
121 * @param {number} tabId The tab where ChromeVox classic is running. 219 * @param {number} tabId The tab where ChromeVox classic is running in.
122 */ 220 */
123 disableClassicChromeVox_: function(tabId) { 221 disableClassicChromeVox_: function(tabId) {
124 chrome.tabs.executeScript( 222 chrome.tabs.executeScript(
125 tabId, 223 tabId,
126 {'code': 'try { window.disableChromeVox(); } catch(e) { }\n', 224 {'code': 'try { window.disableChromeVox(); } catch(e) { }\n',
127 'allFrames': true}); 225 'allFrames': true});
128 } 226 }
129 }; 227 };
130 228
131 /** @type {cvox2.Background} */ 229 /** @type {cvox2.Background} */
132 cvox2.global.backgroundObj = new cvox2.Background(); 230 cvox2.global.backgroundObj = new cvox2.Background();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698