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

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

Issue 2079073002: Make ChromeVox Next a setting in options page. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: m Created 4 years, 6 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('Background'); 10 goog.provide('Background');
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 * @private 63 * @private
64 */ 64 */
65 this.currentRange_ = null; 65 this.currentRange_ = null;
66 66
67 /** 67 /**
68 * @type {cursors.Range} 68 * @type {cursors.Range}
69 * @private 69 * @private
70 */ 70 */
71 this.savedRange_ = null; 71 this.savedRange_ = null;
72 72
73 /**
74 * Which variant of ChromeVox is active.
75 * @type {ChromeVoxMode}
76 * @private
77 */
78 this.mode_ = ChromeVoxMode.COMPAT;
79
80 // Manually bind all functions to |this|. 73 // Manually bind all functions to |this|.
81 for (var func in this) { 74 for (var func in this) {
82 if (typeof(this[func]) == 'function') 75 if (typeof(this[func]) == 'function')
83 this[func] = this[func].bind(this); 76 this[func] = this[func].bind(this);
84 } 77 }
85 78
86 /** @type {!cvox.AbstractEarcons} @private */ 79 /** @type {!cvox.AbstractEarcons} @private */
87 this.classicEarcons_ = cvox.ChromeVox.earcons || new cvox.ClassicEarcons(); 80 this.classicEarcons_ = cvox.ChromeVox.earcons || new cvox.ClassicEarcons();
88 81
89 /** @type {!cvox.AbstractEarcons} @private */ 82 /** @type {!cvox.AbstractEarcons} @private */
90 this.nextEarcons_ = new NextEarcons(); 83 this.nextEarcons_ = new NextEarcons();
91 84
92 // Turn cvox.ChromeVox.earcons into a getter that returns either the 85 // Turn cvox.ChromeVox.earcons into a getter that returns either the
93 // Next earcons or the Classic earcons depending on the current mode. 86 // Next earcons or the Classic earcons depending on the current mode.
94 Object.defineProperty(cvox.ChromeVox, 'earcons', { 87 Object.defineProperty(cvox.ChromeVox, 'earcons', {
95 get: (function() { 88 get: (function() {
96 if (this.mode_ === ChromeVoxMode.FORCE_NEXT || 89 if (this.mode === ChromeVoxMode.FORCE_NEXT ||
97 this.mode_ === ChromeVoxMode.NEXT) { 90 this.mode === ChromeVoxMode.NEXT) {
98 return this.nextEarcons_; 91 return this.nextEarcons_;
99 } else { 92 } else {
100 return this.classicEarcons_; 93 return this.classicEarcons_;
101 } 94 }
102 }).bind(this) 95 }).bind(this)
103 }); 96 });
104 97
105 if (cvox.ChromeVox.isChromeOS) { 98 if (cvox.ChromeVox.isChromeOS) {
106 Object.defineProperty(cvox.ChromeVox, 'modKeyStr', { 99 Object.defineProperty(cvox.ChromeVox, 'modKeyStr', {
107 get: function() { 100 get: function() {
108 return (this.mode_ == ChromeVoxMode.CLASSIC || this.mode_ == 101 return (this.mode == ChromeVoxMode.CLASSIC || this.mode ==
109 ChromeVoxMode.COMPAT) ? 102 ChromeVoxMode.COMPAT) ?
110 'Search+Shift' : 'Search'; 103 'Search+Shift' : 'Search';
111 }.bind(this) 104 }.bind(this)
112 }); 105 });
113 } 106 }
114 107
115 Object.defineProperty(cvox.ChromeVox, 'isActive', { 108 Object.defineProperty(cvox.ChromeVox, 'isActive', {
116 get: function() { 109 get: function() {
117 return localStorage['active'] !== 'false'; 110 return localStorage['active'] !== 'false';
118 }, 111 },
(...skipping 13 matching lines...) Expand all
132 125
133 // Live region handler. 126 // Live region handler.
134 this.liveRegions_ = new LiveRegions(this); 127 this.liveRegions_ = new LiveRegions(this);
135 128
136 /** @type {number} @private */ 129 /** @type {number} @private */
137 this.passThroughKeyUpCount_ = 0; 130 this.passThroughKeyUpCount_ = 0;
138 131
139 /** @type {boolean} @private */ 132 /** @type {boolean} @private */
140 this.inExcursion_ = false; 133 this.inExcursion_ = false;
141 134
135 /**
136 * Stores the mode as computed the last time a current range was set.
137 */
138 this.mode_ = ChromeVoxMode.COMPAT;
dmazzoni 2016/06/21 21:21:02 Can you use getMode() here?
David Tseng 2016/06/21 22:41:32 No, because we always need to perform the basic se
139
142 if (!chrome.accessibilityPrivate.setKeyboardListener) 140 if (!chrome.accessibilityPrivate.setKeyboardListener)
143 chrome.accessibilityPrivate.setKeyboardListener = function() {}; 141 chrome.accessibilityPrivate.setKeyboardListener = function() {};
144 142
145 if (cvox.ChromeVox.isChromeOS) { 143 if (cvox.ChromeVox.isChromeOS) {
146 chrome.accessibilityPrivate.onAccessibilityGesture.addListener( 144 chrome.accessibilityPrivate.onAccessibilityGesture.addListener(
147 this.onAccessibilityGesture_); 145 this.onAccessibilityGesture_);
148 146
147 if (localStorage['useNext'] == 'true')
148 this.forceChromeVoxNextActive();
149 else
150 this.onModeChanged_(ChromeVoxMode.COMPAT, ChromeVoxMode.CLASSIC);
dmazzoni 2016/06/21 21:21:02 It'd be nice if you could just call refreshMode()
David Tseng 2016/06/21 22:41:32 new mode and call onModeChanged automatically base
151
149 Notifications.onStartup(); 152 Notifications.onStartup();
150 }}; 153 }};
151 154
152 /** 155 /**
153 * @const {string} 156 * @const {string}
154 */ 157 */
155 Background.ISSUE_URL = 'https://code.google.com/p/chromium/issues/entry?' + 158 Background.ISSUE_URL = 'https://code.google.com/p/chromium/issues/entry?' +
156 'labels=Type-Bug,Pri-2,cvox2,OS-Chrome&' + 159 'labels=Type-Bug,Pri-2,cvox2,OS-Chrome&' +
157 'components=UI>accessibility&' + 160 'components=UI>accessibility&' +
158 'description='; 161 'description=';
(...skipping 30 matching lines...) Expand all
189 'swipeDown2': 'readFromHere', 192 'swipeDown2': 'readFromHere',
190 }; 193 };
191 194
192 Background.prototype = { 195 Background.prototype = {
193 __proto__: ChromeVoxState.prototype, 196 __proto__: ChromeVoxState.prototype,
194 197
195 /** 198 /**
196 * @override 199 * @override
197 */ 200 */
198 getMode: function() { 201 getMode: function() {
199 return this.mode_; 202 if (localStorage['useNext'] == 'true')
203 return ChromeVoxMode.FORCE_NEXT;
204
205 var target;
206 if (!this.getCurrentRange()) {
207 chrome.automation.getFocus(function(focus) {
208 target = focus;
209 });
210 } else {
211 target = this.getCurrentRange().start.node;
212 }
213
214 if (!target)
215 return ChromeVoxMode.CLASSIC;
216
217 // Closure complains, but clearly, |target| is not null.
218 var root =
219 AutomationUtil.getTopLevelRoot(/** @type {!AutomationNode} */(target));
220 if (!root)
221 return ChromeVoxMode.COMPAT;
dmazzoni 2016/06/21 21:21:02 nit: wrong indent
David Tseng 2016/06/21 22:41:32 Done.
222 if (this.isWhitelistedForCompat_(root.docUrl))
223 return ChromeVoxMode.COMPAT;
224 else if (this.isWhitelistedForNext_(root.docUrl))
225 return ChromeVoxMode.NEXT;
226 else
227 return ChromeVoxMode.CLASSIC;
200 }, 228 },
201 229
202 /** 230 /**
203 * @override 231 * Handles a mode change.
232 * @param {ChromeVoxMode} newMode
233 * @param {ChromeVoxMode} oldMode
234 * @private
204 */ 235 */
205 setMode: function(mode, opt_injectClassic) { 236 onModeChanged_: function(newMode, oldMode) {
206 // Switching key maps potentially affects the key codes that involve 237 // Switching key maps potentially affects the key codes that involve
207 // sequencing. Without resetting this list, potentially stale key codes 238 // sequencing. Without resetting this list, potentially stale key codes
208 // remain. The key codes themselves get pushed in 239 // remain. The key codes themselves get pushed in
209 // cvox.KeySequence.deserialize which gets called by cvox.KeyMap. 240 // cvox.KeySequence.deserialize which gets called by cvox.KeyMap.
210 cvox.ChromeVox.sequenceSwitchKeyCodes = []; 241 cvox.ChromeVox.sequenceSwitchKeyCodes = [];
211 if (mode === ChromeVoxMode.CLASSIC || mode === ChromeVoxMode.COMPAT) 242 if (window['prefs']) {
212 window['prefs'].switchToKeyMap('keymap_classic'); 243 if (newMode === ChromeVoxMode.CLASSIC || newMode === ChromeVoxMode.COMPAT)
213 else 244 window['prefs'].switchToKeyMap('keymap_classic');
214 window['prefs'].switchToKeyMap('keymap_next'); 245 else
246 window['prefs'].switchToKeyMap('keymap_next');
247 }
215 248
216 if (mode == ChromeVoxMode.CLASSIC) { 249 if (newMode == ChromeVoxMode.CLASSIC) {
217 if (chrome.commands && 250 if (chrome.commands &&
218 chrome.commands.onCommand.hasListener(this.onGotCommand)) 251 chrome.commands.onCommand.hasListener(this.onGotCommand))
219 chrome.commands.onCommand.removeListener(this.onGotCommand); 252 chrome.commands.onCommand.removeListener(this.onGotCommand);
220 chrome.accessibilityPrivate.setKeyboardListener(false, false); 253 chrome.accessibilityPrivate.setKeyboardListener(false, false);
254
255 if (cvox.ChromeVox.isChromeOS)
256 chrome.accessibilityPrivate.setFocusRing([]);
221 } else { 257 } else {
222 if (chrome.commands && 258 if (chrome.commands &&
223 !chrome.commands.onCommand.hasListener(this.onGotCommand)) 259 !chrome.commands.onCommand.hasListener(this.onGotCommand))
224 chrome.commands.onCommand.addListener(this.onGotCommand); 260 chrome.commands.onCommand.addListener(this.onGotCommand);
225 chrome.accessibilityPrivate.setKeyboardListener( 261 chrome.accessibilityPrivate.setKeyboardListener(
226 true, cvox.ChromeVox.isStickyPrefOn); 262 true, cvox.ChromeVox.isStickyPrefOn);
227 } 263 }
228 264
229 // note that |this.currentRange_| can *change* because the request is 265 // note that |this.currentRange_| can *change* because the request is
230 // async. Save it to ensure we're looking at the currentRange at this moment 266 // async. Save it to ensure we're looking at the currentRange at this moment
231 // in time. 267 // in time.
232 var cur = this.currentRange_; 268 var cur = this.currentRange_;
233 chrome.tabs.query({active: true}, function(tabs) { 269 chrome.tabs.query({active: true}, function(tabs) {
234 if (mode === ChromeVoxMode.CLASSIC) { 270 if (newMode === ChromeVoxMode.CLASSIC) {
235 // Generally, we don't want to inject classic content scripts as it is 271 // Generally, we don't want to inject classic content scripts as it is
236 // done by the extension system at document load. The exception is when 272 // done by the extension system at document load. The exception is when
237 // we toggle classic on manually as part of a user command. 273 // we toggle classic on manually as part of a user command.
238 if (opt_injectClassic) 274 if (oldMode == ChromeVoxMode.FORCE_NEXT)
239 cvox.ChromeVox.injectChromeVoxIntoTabs(tabs); 275 cvox.ChromeVox.injectChromeVoxIntoTabs(tabs);
240 } else { 276 } else {
241 // When in compat mode, if the focus is within the desktop tree proper, 277 // When in compat mode, if the focus is within the desktop tree proper,
242 // then do not disable content scripts. 278 // then do not disable content scripts.
243 if (cur && !cur.isWebRange()) 279 if (cur && !cur.isWebRange())
244 return; 280 return;
245 281
246 this.disableClassicChromeVox_(); 282 this.disableClassicChromeVox_();
247 } 283 }
248 }.bind(this)); 284 }.bind(this));
249 285
250 // If switching out of a ChromeVox Next mode, make sure we cancel 286 // If switching out of a ChromeVox Next mode, make sure we cancel
251 // the progress loading sound just in case. 287 // the progress loading sound just in case.
252 if ((this.mode_ === ChromeVoxMode.NEXT || 288 if (oldMode === ChromeVoxMode.NEXT ||
253 this.mode_ === ChromeVoxMode.FORCE_NEXT) && 289 oldMode === ChromeVoxMode.FORCE_NEXT)
254 this.mode_ != mode) {
255 cvox.ChromeVox.earcons.cancelEarcon(cvox.Earcon.PAGE_START_LOADING); 290 cvox.ChromeVox.earcons.cancelEarcon(cvox.Earcon.PAGE_START_LOADING);
256 }
257 291
258 if (mode === ChromeVoxMode.NEXT || 292 if (newMode === ChromeVoxMode.NEXT ||
259 mode === ChromeVoxMode.FORCE_NEXT) { 293 newMode === ChromeVoxMode.FORCE_NEXT) {
260 (new PanelCommand(PanelCommandType.ENABLE_MENUS)).send(); 294 (new PanelCommand(PanelCommandType.ENABLE_MENUS)).send();
261 if (cvox.TabsApiHandler) 295 if (cvox.TabsApiHandler)
262 cvox.TabsApiHandler.shouldOutputSpeechAndBraille = false; 296 cvox.TabsApiHandler.shouldOutputSpeechAndBraille = false;
263 } else { 297 } else {
264 (new PanelCommand(PanelCommandType.DISABLE_MENUS)).send(); 298 (new PanelCommand(PanelCommandType.DISABLE_MENUS)).send();
265 if (cvox.TabsApiHandler) 299 if (cvox.TabsApiHandler)
266 cvox.TabsApiHandler.shouldOutputSpeechAndBraille = true; 300 cvox.TabsApiHandler.shouldOutputSpeechAndBraille = true;
267 } 301 }
268
269 // If switching to Classic from any automation-API-based mode,
270 // clear the focus ring.
271 if (mode === ChromeVoxMode.CLASSIC && mode != this.mode_) {
272 if (cvox.ChromeVox.isChromeOS)
273 chrome.accessibilityPrivate.setFocusRing([]);
274 }
275
276 // If switching away from Classic to any automation-API-based mode,
277 // update the range based on what's focused.
278 if (this.mode_ === ChromeVoxMode.CLASSIC && mode != this.mode_) {
279 chrome.automation.getFocus((function(focus) {
280 if (focus)
281 this.setCurrentRange(cursors.Range.fromNode(focus));
282 }).bind(this));
283 }
284
285 this.mode_ = mode;
286 }, 302 },
287 303
288 /** 304 /**
289 * Mode refreshes takes into account both |url| and the current ChromeVox 305 * Toggles between force next and classic/compat modes.
290 * range. The latter gets used to decide if the user is or isn't in web 306 * This toggle automatically handles deciding between classic/compat based on
291 * content. The focused state also needs to be set for this info to be 307 * the start of the current range.
292 * reliable. 308 * @param {boolean=} opt_setValue Directly set to force next (true) or
293 * @override 309 * classic/compat (false).
310 * @return {boolean} True to announce current position.
294 */ 311 */
295 refreshMode: function(node) { 312 toggleNext: function(opt_setValue) {
296 // Mode changes are based upon the top level web root. 313 var useNext;
297 var root = node.root; 314 if (opt_setValue !== undefined)
298 while (root && 315 useNext = opt_setValue;
299 root.parent && 316 else
300 root.parent.root && 317 useNext = localStorage['useNext'] != 'true';
301 root.parent.root.role != RoleType.desktop) {
302 root = root.parent.root;
303 }
304 318
305 var url = ''; 319 localStorage['useNext'] = useNext;
306 if (root && root.role == RoleType.rootWebArea) 320 if (useNext)
307 url = root.docUrl; 321 this.forceChromeVoxNextActive();
322 else
323 this.setCurrentRange(null);
308 324
309 var mode = this.mode_; 325 var announce = Msgs.getMsg(useNext ?
310 if (mode != ChromeVoxMode.FORCE_NEXT) { 326 'switch_to_next' : 'switch_to_classic');
311 if (this.isWhitelistedForNext_(url)) { 327 cvox.ChromeVox.tts.speak(
312 mode = ChromeVoxMode.NEXT; 328 announce, cvox.QueueMode.FLUSH, {doNotInterrupt: true});
313 } else if (this.isBlacklistedForClassic_(url) || (this.currentRange_ && 329 Notifications.onModeChange();
314 !this.currentRange_.isWebRange() &&
315 this.currentRange_.start.node.state.focused)) {
316 mode = ChromeVoxMode.COMPAT;
317 } else {
318 mode = ChromeVoxMode.CLASSIC;
319 }
320 }
321 330
322 this.setMode(mode); 331 // If the new mode is Classic, return false now so we don't announce
332 // anything more.
333 return useNext;
323 }, 334 },
324 335
325 /** 336 /**
326 * @override 337 * @override
327 */ 338 */
328 getCurrentRange: function() { 339 getCurrentRange: function() {
329 if (this.currentRange_ && this.currentRange_.isValid()) 340 if (this.currentRange_ && this.currentRange_.isValid())
330 return this.currentRange_; 341 return this.currentRange_;
331 return null; 342 return null;
332 }, 343 },
333 344
334 /** 345 /**
335 * @override 346 * @override
336 */ 347 */
337 setCurrentRange: function(newRange) { 348 setCurrentRange: function(newRange) {
338 if (!newRange) 349 if (!this.inExcursion_ && newRange)
339 return;
340
341 // Is the range invalid?
342 if (newRange.start.node.role === undefined ||
343 newRange.end.node.role === undefined) {
344 // Restore range to the focused location.
345 chrome.automation.getFocus(function(f) {
346 newRange = cursors.Range.fromNode(f);
347 });
348 }
349
350 if (!this.inExcursion_)
351 this.savedRange_ = new cursors.Range(newRange.start, newRange.end); 350 this.savedRange_ = new cursors.Range(newRange.start, newRange.end);
352 351
353 this.currentRange_ = newRange; 352 this.currentRange_ = newRange;
353 var oldMode = this.mode_;
dmazzoni 2016/06/21 21:21:02 Could these 5 lines be refreshMode()? Then any ca
David Tseng 2016/06/21 22:41:32 I'd like to limit the number of methods exposed by
354 var newMode = this.getMode();
355 if (oldMode != newMode) {
356 this.onModeChanged_(newMode, oldMode);
357 this.mode_ = newMode;
358 }
354 359
355 if (this.currentRange_) { 360 if (this.currentRange_) {
356 var start = this.currentRange_.start.node; 361 var start = this.currentRange_.start.node;
357 start.makeVisible(); 362 start.makeVisible();
358 363
359 var root = start.root; 364 var root = start.root;
360
361 if (!root || root.role == RoleType.desktop) 365 if (!root || root.role == RoleType.desktop)
362 return; 366 return;
363 367
364 var position = {}; 368 var position = {};
365 var loc = start.location; 369 var loc = start.location;
366 position.x = loc.left + loc.width / 2; 370 position.x = loc.left + loc.width / 2;
367 position.y = loc.top + loc.height / 2; 371 position.y = loc.top + loc.height / 2;
368 var url = root.docUrl; 372 var url = root.docUrl;
369 url = url.substring(0, url.indexOf('#')) || url; 373 url = url.substring(0, url.indexOf('#')) || url;
370 cvox.ChromeVox.position[url] = position; 374 cvox.ChromeVox.position[url] = position;
371 } 375 }
372 }, 376 },
373 377
374 /** Forces ChromeVox Next to be active for all tabs. */ 378 /** Forces ChromeVox Next to be active for all tabs. */
375 forceChromeVoxNextActive: function() { 379 forceChromeVoxNextActive: function() {
dmazzoni 2016/06/21 21:21:02 This doesn't actually force it active, it assumes
David Tseng 2016/06/21 22:41:32 Yup; removed and in-lined since there are no exter
376 this.setMode(ChromeVoxMode.FORCE_NEXT); 380 this.onModeChanged_(ChromeVoxMode.FORCE_NEXT, ChromeVoxMode.CLASSIC);
377 }, 381 },
378 382
379 /** 383 /**
380 * Handles ChromeVox Next commands. 384 * Handles ChromeVox Next commands.
381 * @param {string} command 385 * @param {string} command
382 * @param {boolean=} opt_bypassModeCheck Always tries to execute the command 386 * @param {boolean=} opt_bypassModeCheck Always tries to execute the command
383 * regardless of mode. 387 * regardless of mode.
384 * @return {boolean} True if the command should propagate. 388 * @return {boolean} True if the command should propagate.
385 */ 389 */
386 onGotCommand: function(command, opt_bypassModeCheck) { 390 onGotCommand: function(command, opt_bypassModeCheck) {
387 // Check for loss of focus which results in us invalidating our current 391 // Check for loss of focus which results in us invalidating our current
388 // range. Note this call is synchronis. 392 // range. Note this call is synchronis.
389 chrome.automation.getFocus(function(focusedNode) { 393 chrome.automation.getFocus(function(focusedNode) {
390 if (this.currentRange_ && !this.currentRange_.isValid()) 394 if (this.currentRange_ && !this.currentRange_.isValid())
391 this.currentRange_ = cursors.Range.fromNode(focusedNode); 395 this.currentRange_ = cursors.Range.fromNode(focusedNode);
392 if (!focusedNode) 396 if (!focusedNode)
393 this.currentRange_ = null; 397 this.currentRange_ = null;
394 }.bind(this)); 398 }.bind(this));
395 399
396 if (!this.currentRange_) 400 if (!this.currentRange_)
397 return true; 401 return true;
398 402
399 if (this.mode_ == ChromeVoxMode.CLASSIC && !opt_bypassModeCheck) 403 if (this.mode == ChromeVoxMode.CLASSIC && !opt_bypassModeCheck)
400 return true; 404 return true;
401 405
402 var current = this.currentRange_; 406 var current = this.currentRange_;
403 var dir = Dir.FORWARD; 407 var dir = Dir.FORWARD;
404 var pred = null; 408 var pred = null;
405 var predErrorMsg = undefined; 409 var predErrorMsg = undefined;
406 var speechProps = {}; 410 var speechProps = {};
407 switch (command) { 411 switch (command) {
408 case 'nextCharacter': 412 case 'nextCharacter':
409 speechProps['phoneticCharacters'] = true; 413 speechProps['phoneticCharacters'] = true;
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 return false; 604 return false;
601 605
602 cvox.ChromeVox.isActive = !cvox.ChromeVox.isActive; 606 cvox.ChromeVox.isActive = !cvox.ChromeVox.isActive;
603 if (!cvox.ChromeVox.isActive) { 607 if (!cvox.ChromeVox.isActive) {
604 var msg = Msgs.getMsg('chromevox_inactive'); 608 var msg = Msgs.getMsg('chromevox_inactive');
605 cvox.ChromeVox.tts.speak(msg, cvox.QueueMode.FLUSH); 609 cvox.ChromeVox.tts.speak(msg, cvox.QueueMode.FLUSH);
606 return false; 610 return false;
607 } 611 }
608 break; 612 break;
609 case 'toggleChromeVoxVersion': 613 case 'toggleChromeVoxVersion':
610 var newMode; 614 if (!this.toggleNext())
611 if (this.mode_ == ChromeVoxMode.FORCE_NEXT) { 615 return false;
612 var inWeb = current.isWebRange();
613 newMode = inWeb ? ChromeVoxMode.CLASSIC : ChromeVoxMode.COMPAT;
614 } else {
615 newMode = ChromeVoxMode.FORCE_NEXT;
616 }
617 this.setMode(newMode, true);
618
619 var isClassic =
620 newMode == ChromeVoxMode.CLASSIC || newMode == ChromeVoxMode.COMPAT;
621
622 // Leaving unlocalized as 'next' isn't an official name.
623 cvox.ChromeVox.tts.speak(isClassic ?
624 'classic' : 'next', cvox.QueueMode.FLUSH, {doNotInterrupt: true});
625
626 // If the new mode is Classic, return now so we don't announce
627 // anything more.
628 if (newMode == ChromeVoxMode.CLASSIC)
629 return false;
630 break; 616 break;
631 case 'toggleStickyMode': 617 case 'toggleStickyMode':
632 cvox.ChromeVoxBackground.setPref('sticky', 618 cvox.ChromeVoxBackground.setPref('sticky',
633 !cvox.ChromeVox.isStickyPrefOn, 619 !cvox.ChromeVox.isStickyPrefOn,
634 true); 620 true);
635 621
636 if (cvox.ChromeVox.isStickyPrefOn) 622 if (cvox.ChromeVox.isStickyPrefOn)
637 chrome.accessibilityPrivate.setKeyboardListener(true, true); 623 chrome.accessibilityPrivate.setKeyboardListener(true, true);
638 else 624 else
639 chrome.accessibilityPrivate.setKeyboardListener(true, false); 625 chrome.accessibilityPrivate.setKeyboardListener(true, false);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 output.go(); 766 output.go();
781 return false; 767 return false;
782 case 'readCurrentURL': 768 case 'readCurrentURL':
783 var output = new Output(); 769 var output = new Output();
784 var target = this.currentRange_.start.node.root; 770 var target = this.currentRange_.start.node.root;
785 output.withString(target.docUrl || '').go(); 771 output.withString(target.docUrl || '').go();
786 return false; 772 return false;
787 case 'reportIssue': 773 case 'reportIssue':
788 var url = Background.ISSUE_URL; 774 var url = Background.ISSUE_URL;
789 var description = {}; 775 var description = {};
790 description['Mode'] = this.mode_; 776 description['Mode'] = this.mode;
791 description['Version'] = chrome.app.getDetails().version; 777 description['Version'] = chrome.app.getDetails().version;
792 description['Reproduction Steps'] = '%0a1.%0a2.%0a3.'; 778 description['Reproduction Steps'] = '%0a1.%0a2.%0a3.';
793 for (var key in description) 779 for (var key in description)
794 url += key + ':%20' + description[key] + '%0a'; 780 url += key + ':%20' + description[key] + '%0a';
795 chrome.tabs.create({url: url}); 781 chrome.tabs.create({url: url});
796 return false; 782 return false;
797 case 'toggleBrailleCaptions': 783 case 'toggleBrailleCaptions':
798 cvox.BrailleCaptionsBackground.setActive( 784 cvox.BrailleCaptionsBackground.setActive(
799 !cvox.BrailleCaptionsBackground.isEnabled()); 785 !cvox.BrailleCaptionsBackground.isEnabled());
800 return false; 786 return false;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 /** 887 /**
902 * Handles key down events. 888 * Handles key down events.
903 * @param {Event} evt The key down event to process. 889 * @param {Event} evt The key down event to process.
904 * @return {boolean} True if the default action should be performed. 890 * @return {boolean} True if the default action should be performed.
905 */ 891 */
906 onKeyDown: function(evt) { 892 onKeyDown: function(evt) {
907 evt.stickyMode = cvox.ChromeVox.isStickyModeOn() && cvox.ChromeVox.isActive; 893 evt.stickyMode = cvox.ChromeVox.isStickyModeOn() && cvox.ChromeVox.isActive;
908 if (cvox.ChromeVox.passThroughMode) 894 if (cvox.ChromeVox.passThroughMode)
909 return false; 895 return false;
910 896
911 if (this.mode_ != ChromeVoxMode.CLASSIC && 897 if (this.mode != ChromeVoxMode.CLASSIC &&
912 !cvox.ChromeVoxKbHandler.basicKeyDownActionsListener(evt)) { 898 !cvox.ChromeVoxKbHandler.basicKeyDownActionsListener(evt)) {
913 evt.preventDefault(); 899 evt.preventDefault();
914 evt.stopPropagation(); 900 evt.stopPropagation();
915 } 901 }
916 Output.flushNextSpeechUtterance(); 902 Output.flushNextSpeechUtterance();
917 return false; 903 return false;
918 }, 904 },
919 905
920 /** 906 /**
921 * Handles key up events. 907 * Handles key up events.
(...skipping 22 matching lines...) Expand all
944 chrome.tabs.create(optionsPage); 930 chrome.tabs.create(optionsPage);
945 }, 931 },
946 932
947 /** 933 /**
948 * Handles a braille command. 934 * Handles a braille command.
949 * @param {!cvox.BrailleKeyEvent} evt 935 * @param {!cvox.BrailleKeyEvent} evt
950 * @param {!cvox.NavBraille} content 936 * @param {!cvox.NavBraille} content
951 * @return {boolean} True if evt was processed. 937 * @return {boolean} True if evt was processed.
952 */ 938 */
953 onBrailleKeyEvent: function(evt, content) { 939 onBrailleKeyEvent: function(evt, content) {
954 if (this.mode_ === ChromeVoxMode.CLASSIC) 940 if (this.mode === ChromeVoxMode.CLASSIC)
955 return false; 941 return false;
956 942
957 switch (evt.command) { 943 switch (evt.command) {
958 case cvox.BrailleKeyCommand.PAN_LEFT: 944 case cvox.BrailleKeyCommand.PAN_LEFT:
959 this.onGotCommand('previousObject'); 945 this.onGotCommand('previousObject');
960 break; 946 break;
961 case cvox.BrailleKeyCommand.PAN_RIGHT: 947 case cvox.BrailleKeyCommand.PAN_RIGHT:
962 this.onGotCommand('nextObject'); 948 this.onGotCommand('nextObject');
963 break; 949 break;
964 case cvox.BrailleKeyCommand.LINE_UP: 950 case cvox.BrailleKeyCommand.LINE_UP:
(...skipping 19 matching lines...) Expand all
984 } 970 }
985 return true; 971 return true;
986 }, 972 },
987 973
988 /** 974 /**
989 * Returns true if the url should have Classic running. 975 * Returns true if the url should have Classic running.
990 * @return {boolean} 976 * @return {boolean}
991 * @private 977 * @private
992 */ 978 */
993 shouldEnableClassicForUrl_: function(url) { 979 shouldEnableClassicForUrl_: function(url) {
994 return this.mode_ != ChromeVoxMode.FORCE_NEXT && 980 return this.mode != ChromeVoxMode.FORCE_NEXT &&
995 !this.isBlacklistedForClassic_(url) && 981 !this.isBlacklistedForClassic_(url) &&
996 !this.isWhitelistedForNext_(url); 982 !this.isWhitelistedForNext_(url);
997 }, 983 },
998 984
999 /** 985 /**
986 * Compat mode is on if any of the following are true:
987 * 1. a url is blacklisted for Classic.
988 * 2. the current range is not within web content.
989 * @param {string} url
990 */
991 isWhitelistedForCompat_: function(url) {
992 return this.isBlacklistedForClassic_(url) || (this.getCurrentRange() &&
993 !this.getCurrentRange().isWebRange() &&
994 this.getCurrentRange().start.node.state.focused);
995 },
996
997 /**
1000 * @param {string} url 998 * @param {string} url
1001 * @return {boolean} 999 * @return {boolean}
1002 * @private 1000 * @private
1003 */ 1001 */
1004 isBlacklistedForClassic_: function(url) { 1002 isBlacklistedForClassic_: function(url) {
1005 return this.classicBlacklistRegExp_.test(url); 1003 return this.classicBlacklistRegExp_.test(url);
1006 }, 1004 },
1007 1005
1008 /** 1006 /**
1009 * @param {string} url 1007 * @param {string} url
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 /** 1141 /**
1144 * Handles accessibility gestures from the touch screen. 1142 * Handles accessibility gestures from the touch screen.
1145 * @param {string} gesture The gesture to handle, based on the AXGesture enum 1143 * @param {string} gesture The gesture to handle, based on the AXGesture enum
1146 * defined in ui/accessibility/ax_enums.idl 1144 * defined in ui/accessibility/ax_enums.idl
1147 * @private 1145 * @private
1148 */ 1146 */
1149 onAccessibilityGesture_: function(gesture) { 1147 onAccessibilityGesture_: function(gesture) {
1150 // If we're in classic mode, some gestures need to be handled by the 1148 // If we're in classic mode, some gestures need to be handled by the
1151 // content script. Other gestures are universal and will be handled in 1149 // content script. Other gestures are universal and will be handled in
1152 // this function. 1150 // this function.
1153 if (this.mode_ == ChromeVoxMode.CLASSIC) { 1151 if (this.mode == ChromeVoxMode.CLASSIC) {
1154 if (this.handleClassicGesture_(gesture)) 1152 if (this.handleClassicGesture_(gesture))
1155 return; 1153 return;
1156 } 1154 }
1157 1155
1158 var command = Background.GESTURE_NEXT_COMMAND_MAP[gesture]; 1156 var command = Background.GESTURE_NEXT_COMMAND_MAP[gesture];
1159 if (command) 1157 if (command)
1160 this.onGotCommand(command); 1158 this.onGotCommand(command);
1161 }, 1159 },
1162 1160
1163 /** 1161 /**
(...skipping 30 matching lines...) Expand all
1194 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&') 1192 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&')
1195 .replace(/\*/g, '.*') 1193 .replace(/\*/g, '.*')
1196 .replace(/\?/g, '.'); 1194 .replace(/\?/g, '.');
1197 }).join('|') + ')$'); 1195 }).join('|') + ')$');
1198 }; 1196 };
1199 1197
1200 /** @type {Background} */ 1198 /** @type {Background} */
1201 global.backgroundObj = new Background(); 1199 global.backgroundObj = new Background();
1202 1200
1203 }); // goog.scope 1201 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698