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

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 * @type {?ChromeVoxMode}
138 */
139 this.mode_ = null;
140 if (localStorage['useNext'] == 'true')
dmazzoni 2016/06/22 05:23:33 nit: maybe a blank line before this to better asso
141 this.setCurrentRangeToFocus_();
142 else
143 this.setCurrentRange(null);
144
142 if (!chrome.accessibilityPrivate.setKeyboardListener) 145 if (!chrome.accessibilityPrivate.setKeyboardListener)
143 chrome.accessibilityPrivate.setKeyboardListener = function() {}; 146 chrome.accessibilityPrivate.setKeyboardListener = function() {};
144 147
145 if (cvox.ChromeVox.isChromeOS) { 148 if (cvox.ChromeVox.isChromeOS) {
146 chrome.accessibilityPrivate.onAccessibilityGesture.addListener( 149 chrome.accessibilityPrivate.onAccessibilityGesture.addListener(
147 this.onAccessibilityGesture_); 150 this.onAccessibilityGesture_);
148 151
149 Notifications.onStartup(); 152 Notifications.onStartup();
150 }}; 153 }};
151 154
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
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;
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
dmazzoni 2016/06/22 05:23:33 Docstring for this maybe saying it can be null to
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);
221 } else { 254
255 if (cvox.ChromeVox.isChromeOS)
256 chrome.accessibilityPrivate.setFocusRing([]);
257 } else if (oldMode) {
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 if (oldMode) {
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 if (oldMode) {
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.setCurrentRangeToFocus_();
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_;
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. */
375 forceChromeVoxNextActive: function() {
376 this.setMode(ChromeVoxMode.FORCE_NEXT);
377 },
378
379 /** 378 /**
380 * Handles ChromeVox Next commands. 379 * Handles ChromeVox Next commands.
381 * @param {string} command 380 * @param {string} command
382 * @param {boolean=} opt_bypassModeCheck Always tries to execute the command 381 * @param {boolean=} opt_bypassModeCheck Always tries to execute the command
383 * regardless of mode. 382 * regardless of mode.
384 * @return {boolean} True if the command should propagate. 383 * @return {boolean} True if the command should propagate.
385 */ 384 */
386 onGotCommand: function(command, opt_bypassModeCheck) { 385 onGotCommand: function(command, opt_bypassModeCheck) {
387 // Check for loss of focus which results in us invalidating our current 386 // Check for loss of focus which results in us invalidating our current
388 // range. Note this call is synchronis. 387 // range. Note this call is synchronis.
389 chrome.automation.getFocus(function(focusedNode) { 388 chrome.automation.getFocus(function(focusedNode) {
390 if (this.currentRange_ && !this.currentRange_.isValid()) 389 if (this.currentRange_ && !this.currentRange_.isValid())
391 this.currentRange_ = cursors.Range.fromNode(focusedNode); 390 this.currentRange_ = cursors.Range.fromNode(focusedNode);
392 if (!focusedNode) 391 if (!focusedNode)
393 this.currentRange_ = null; 392 this.currentRange_ = null;
394 }.bind(this)); 393 }.bind(this));
395 394
396 if (!this.currentRange_) 395 if (!this.currentRange_)
397 return true; 396 return true;
398 397
399 if (this.mode_ == ChromeVoxMode.CLASSIC && !opt_bypassModeCheck) 398 if (this.mode == ChromeVoxMode.CLASSIC && !opt_bypassModeCheck)
400 return true; 399 return true;
401 400
402 var current = this.currentRange_; 401 var current = this.currentRange_;
403 var dir = Dir.FORWARD; 402 var dir = Dir.FORWARD;
404 var pred = null; 403 var pred = null;
405 var predErrorMsg = undefined; 404 var predErrorMsg = undefined;
406 var speechProps = {}; 405 var speechProps = {};
407 switch (command) { 406 switch (command) {
408 case 'nextCharacter': 407 case 'nextCharacter':
409 speechProps['phoneticCharacters'] = true; 408 speechProps['phoneticCharacters'] = true;
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 return false; 599 return false;
601 600
602 cvox.ChromeVox.isActive = !cvox.ChromeVox.isActive; 601 cvox.ChromeVox.isActive = !cvox.ChromeVox.isActive;
603 if (!cvox.ChromeVox.isActive) { 602 if (!cvox.ChromeVox.isActive) {
604 var msg = Msgs.getMsg('chromevox_inactive'); 603 var msg = Msgs.getMsg('chromevox_inactive');
605 cvox.ChromeVox.tts.speak(msg, cvox.QueueMode.FLUSH); 604 cvox.ChromeVox.tts.speak(msg, cvox.QueueMode.FLUSH);
606 return false; 605 return false;
607 } 606 }
608 break; 607 break;
609 case 'toggleChromeVoxVersion': 608 case 'toggleChromeVoxVersion':
610 var newMode; 609 if (!this.toggleNext())
611 if (this.mode_ == ChromeVoxMode.FORCE_NEXT) { 610 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; 611 break;
631 case 'toggleStickyMode': 612 case 'toggleStickyMode':
632 cvox.ChromeVoxBackground.setPref('sticky', 613 cvox.ChromeVoxBackground.setPref('sticky',
633 !cvox.ChromeVox.isStickyPrefOn, 614 !cvox.ChromeVox.isStickyPrefOn,
634 true); 615 true);
635 616
636 if (cvox.ChromeVox.isStickyPrefOn) 617 if (cvox.ChromeVox.isStickyPrefOn)
637 chrome.accessibilityPrivate.setKeyboardListener(true, true); 618 chrome.accessibilityPrivate.setKeyboardListener(true, true);
638 else 619 else
639 chrome.accessibilityPrivate.setKeyboardListener(true, false); 620 chrome.accessibilityPrivate.setKeyboardListener(true, false);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 output.go(); 761 output.go();
781 return false; 762 return false;
782 case 'readCurrentURL': 763 case 'readCurrentURL':
783 var output = new Output(); 764 var output = new Output();
784 var target = this.currentRange_.start.node.root; 765 var target = this.currentRange_.start.node.root;
785 output.withString(target.docUrl || '').go(); 766 output.withString(target.docUrl || '').go();
786 return false; 767 return false;
787 case 'reportIssue': 768 case 'reportIssue':
788 var url = Background.ISSUE_URL; 769 var url = Background.ISSUE_URL;
789 var description = {}; 770 var description = {};
790 description['Mode'] = this.mode_; 771 description['Mode'] = this.mode;
791 description['Version'] = chrome.app.getDetails().version; 772 description['Version'] = chrome.app.getDetails().version;
792 description['Reproduction Steps'] = '%0a1.%0a2.%0a3.'; 773 description['Reproduction Steps'] = '%0a1.%0a2.%0a3.';
793 for (var key in description) 774 for (var key in description)
794 url += key + ':%20' + description[key] + '%0a'; 775 url += key + ':%20' + description[key] + '%0a';
795 chrome.tabs.create({url: url}); 776 chrome.tabs.create({url: url});
796 return false; 777 return false;
797 case 'toggleBrailleCaptions': 778 case 'toggleBrailleCaptions':
798 cvox.BrailleCaptionsBackground.setActive( 779 cvox.BrailleCaptionsBackground.setActive(
799 !cvox.BrailleCaptionsBackground.isEnabled()); 780 !cvox.BrailleCaptionsBackground.isEnabled());
800 return false; 781 return false;
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
901 /** 882 /**
902 * Handles key down events. 883 * Handles key down events.
903 * @param {Event} evt The key down event to process. 884 * @param {Event} evt The key down event to process.
904 * @return {boolean} True if the default action should be performed. 885 * @return {boolean} True if the default action should be performed.
905 */ 886 */
906 onKeyDown: function(evt) { 887 onKeyDown: function(evt) {
907 evt.stickyMode = cvox.ChromeVox.isStickyModeOn() && cvox.ChromeVox.isActive; 888 evt.stickyMode = cvox.ChromeVox.isStickyModeOn() && cvox.ChromeVox.isActive;
908 if (cvox.ChromeVox.passThroughMode) 889 if (cvox.ChromeVox.passThroughMode)
909 return false; 890 return false;
910 891
911 if (this.mode_ != ChromeVoxMode.CLASSIC && 892 if (this.mode != ChromeVoxMode.CLASSIC &&
912 !cvox.ChromeVoxKbHandler.basicKeyDownActionsListener(evt)) { 893 !cvox.ChromeVoxKbHandler.basicKeyDownActionsListener(evt)) {
913 evt.preventDefault(); 894 evt.preventDefault();
914 evt.stopPropagation(); 895 evt.stopPropagation();
915 } 896 }
916 Output.flushNextSpeechUtterance(); 897 Output.flushNextSpeechUtterance();
917 return false; 898 return false;
918 }, 899 },
919 900
920 /** 901 /**
921 * Handles key up events. 902 * Handles key up events.
(...skipping 22 matching lines...) Expand all
944 chrome.tabs.create(optionsPage); 925 chrome.tabs.create(optionsPage);
945 }, 926 },
946 927
947 /** 928 /**
948 * Handles a braille command. 929 * Handles a braille command.
949 * @param {!cvox.BrailleKeyEvent} evt 930 * @param {!cvox.BrailleKeyEvent} evt
950 * @param {!cvox.NavBraille} content 931 * @param {!cvox.NavBraille} content
951 * @return {boolean} True if evt was processed. 932 * @return {boolean} True if evt was processed.
952 */ 933 */
953 onBrailleKeyEvent: function(evt, content) { 934 onBrailleKeyEvent: function(evt, content) {
954 if (this.mode_ === ChromeVoxMode.CLASSIC) 935 if (this.mode === ChromeVoxMode.CLASSIC)
955 return false; 936 return false;
956 937
957 switch (evt.command) { 938 switch (evt.command) {
958 case cvox.BrailleKeyCommand.PAN_LEFT: 939 case cvox.BrailleKeyCommand.PAN_LEFT:
959 this.onGotCommand('previousObject'); 940 this.onGotCommand('previousObject');
960 break; 941 break;
961 case cvox.BrailleKeyCommand.PAN_RIGHT: 942 case cvox.BrailleKeyCommand.PAN_RIGHT:
962 this.onGotCommand('nextObject'); 943 this.onGotCommand('nextObject');
963 break; 944 break;
964 case cvox.BrailleKeyCommand.LINE_UP: 945 case cvox.BrailleKeyCommand.LINE_UP:
(...skipping 19 matching lines...) Expand all
984 } 965 }
985 return true; 966 return true;
986 }, 967 },
987 968
988 /** 969 /**
989 * Returns true if the url should have Classic running. 970 * Returns true if the url should have Classic running.
990 * @return {boolean} 971 * @return {boolean}
991 * @private 972 * @private
992 */ 973 */
993 shouldEnableClassicForUrl_: function(url) { 974 shouldEnableClassicForUrl_: function(url) {
994 return this.mode_ != ChromeVoxMode.FORCE_NEXT && 975 return this.mode != ChromeVoxMode.FORCE_NEXT &&
995 !this.isBlacklistedForClassic_(url) && 976 !this.isBlacklistedForClassic_(url) &&
996 !this.isWhitelistedForNext_(url); 977 !this.isWhitelistedForNext_(url);
997 }, 978 },
998 979
999 /** 980 /**
981 * Compat mode is on if any of the following are true:
982 * 1. a url is blacklisted for Classic.
983 * 2. the current range is not within web content.
984 * @param {string} url
985 */
986 isWhitelistedForCompat_: function(url) {
987 return this.isBlacklistedForClassic_(url) || (this.getCurrentRange() &&
988 !this.getCurrentRange().isWebRange() &&
989 this.getCurrentRange().start.node.state.focused);
990 },
991
992 /**
1000 * @param {string} url 993 * @param {string} url
1001 * @return {boolean} 994 * @return {boolean}
1002 * @private 995 * @private
1003 */ 996 */
1004 isBlacklistedForClassic_: function(url) { 997 isBlacklistedForClassic_: function(url) {
1005 return this.classicBlacklistRegExp_.test(url); 998 return this.classicBlacklistRegExp_.test(url);
1006 }, 999 },
1007 1000
1008 /** 1001 /**
1009 * @param {string} url 1002 * @param {string} url
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 /** 1136 /**
1144 * Handles accessibility gestures from the touch screen. 1137 * Handles accessibility gestures from the touch screen.
1145 * @param {string} gesture The gesture to handle, based on the AXGesture enum 1138 * @param {string} gesture The gesture to handle, based on the AXGesture enum
1146 * defined in ui/accessibility/ax_enums.idl 1139 * defined in ui/accessibility/ax_enums.idl
1147 * @private 1140 * @private
1148 */ 1141 */
1149 onAccessibilityGesture_: function(gesture) { 1142 onAccessibilityGesture_: function(gesture) {
1150 // If we're in classic mode, some gestures need to be handled by the 1143 // 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 1144 // content script. Other gestures are universal and will be handled in
1152 // this function. 1145 // this function.
1153 if (this.mode_ == ChromeVoxMode.CLASSIC) { 1146 if (this.mode == ChromeVoxMode.CLASSIC) {
1154 if (this.handleClassicGesture_(gesture)) 1147 if (this.handleClassicGesture_(gesture))
1155 return; 1148 return;
1156 } 1149 }
1157 1150
1158 var command = Background.GESTURE_NEXT_COMMAND_MAP[gesture]; 1151 var command = Background.GESTURE_NEXT_COMMAND_MAP[gesture];
1159 if (command) 1152 if (command)
1160 this.onGotCommand(command); 1153 this.onGotCommand(command);
1161 }, 1154 },
1162 1155
1163 /** 1156 /**
1164 * Handles accessibility gestures from the touch screen when in CLASSIC 1157 * Handles accessibility gestures from the touch screen when in CLASSIC
1165 * mode, by forwarding a command to the content script. 1158 * mode, by forwarding a command to the content script.
1166 * @param {string} gesture The gesture to handle, based on the AXGesture enum 1159 * @param {string} gesture The gesture to handle, based on the AXGesture enum
1167 * defined in ui/accessibility/ax_enums.idl 1160 * defined in ui/accessibility/ax_enums.idl
1168 * @return {boolean} True if this gesture was handled. 1161 * @return {boolean} True if this gesture was handled.
1169 * @private 1162 * @private
1170 */ 1163 */
1171 handleClassicGesture_: function(gesture) { 1164 handleClassicGesture_: function(gesture) {
1172 var command = Background.GESTURE_CLASSIC_COMMAND_MAP[gesture]; 1165 var command = Background.GESTURE_CLASSIC_COMMAND_MAP[gesture];
1173 if (!command) 1166 if (!command)
1174 return false; 1167 return false;
1175 1168
1176 var msg = { 1169 var msg = {
1177 'message': 'USER_COMMAND', 1170 'message': 'USER_COMMAND',
1178 'command': command 1171 'command': command
1179 }; 1172 };
1180 cvox.ExtensionBridge.send(msg); 1173 cvox.ExtensionBridge.send(msg);
1181 return true; 1174 return true;
1182 }, 1175 },
1176
1177 /** @private */
1178 setCurrentRangeToFocus_: function() {
1179 chrome.automation.getFocus(function(focus) {
1180 if (focus)
1181 this.setCurrentRange(cursors.Range.fromNode(focus));
1182 else
1183 this.setCurrentRange(null);
1184 }.bind(this));
1185 },
1183 }; 1186 };
1184 1187
1185 /** 1188 /**
1186 * Converts a list of globs, as used in the extension manifest, to a regular 1189 * Converts a list of globs, as used in the extension manifest, to a regular
1187 * expression that matches if and only if any of the globs in the list matches. 1190 * expression that matches if and only if any of the globs in the list matches.
1188 * @param {!Array<string>} globs 1191 * @param {!Array<string>} globs
1189 * @return {!RegExp} 1192 * @return {!RegExp}
1190 * @private 1193 * @private
1191 */ 1194 */
1192 Background.globsToRegExp_ = function(globs) { 1195 Background.globsToRegExp_ = function(globs) {
1193 return new RegExp('^(' + globs.map(function(glob) { 1196 return new RegExp('^(' + globs.map(function(glob) {
1194 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&') 1197 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&')
1195 .replace(/\*/g, '.*') 1198 .replace(/\*/g, '.*')
1196 .replace(/\?/g, '.'); 1199 .replace(/\?/g, '.');
1197 }).join('|') + ')$'); 1200 }).join('|') + ')$');
1198 }; 1201 };
1199 1202
1200 /** @type {Background} */ 1203 /** @type {Background} */
1201 global.backgroundObj = new Background(); 1204 global.backgroundObj = new Background();
1202 1205
1203 }); // goog.scope 1206 }); // goog.scope
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698