OLD | NEW |
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'); |
11 goog.provide('global'); | 11 goog.provide('global'); |
12 | 12 |
13 goog.require('AutomationPredicate'); | 13 goog.require('AutomationPredicate'); |
14 goog.require('AutomationUtil'); | 14 goog.require('AutomationUtil'); |
15 goog.require('ChromeVoxState'); | 15 goog.require('ChromeVoxState'); |
16 goog.require('LiveRegions'); | 16 goog.require('LiveRegions'); |
17 goog.require('NextEarcons'); | 17 goog.require('NextEarcons'); |
18 goog.require('Output'); | 18 goog.require('Output'); |
19 goog.require('Output.EventType'); | 19 goog.require('Output.EventType'); |
20 goog.require('PanelCommand'); | |
21 goog.require('constants'); | 20 goog.require('constants'); |
22 goog.require('cursors.Cursor'); | 21 goog.require('cursors.Cursor'); |
23 goog.require('cvox.BrailleKeyCommand'); | 22 goog.require('cvox.BrailleKeyCommand'); |
24 goog.require('cvox.ChromeVoxEditableTextBase'); | 23 goog.require('cvox.ChromeVoxEditableTextBase'); |
25 goog.require('cvox.ChromeVoxKbHandler'); | 24 goog.require('cvox.ChromeVoxKbHandler'); |
26 goog.require('cvox.ClassicEarcons'); | 25 goog.require('cvox.ClassicEarcons'); |
27 goog.require('cvox.ExtensionBridge'); | 26 goog.require('cvox.ExtensionBridge'); |
28 goog.require('cvox.NavBraille'); | 27 goog.require('cvox.NavBraille'); |
29 | 28 |
30 goog.scope(function() { | 29 goog.scope(function() { |
(...skipping 26 matching lines...) Expand all Loading... |
57 this.classicBlacklistRegExp_ = Background.globsToRegExp_( | 56 this.classicBlacklistRegExp_ = Background.globsToRegExp_( |
58 chrome.runtime.getManifest()['content_scripts'][0]['exclude_globs']); | 57 chrome.runtime.getManifest()['content_scripts'][0]['exclude_globs']); |
59 | 58 |
60 /** | 59 /** |
61 * @type {cursors.Range} | 60 * @type {cursors.Range} |
62 * @private | 61 * @private |
63 */ | 62 */ |
64 this.currentRange_ = null; | 63 this.currentRange_ = null; |
65 | 64 |
66 /** | 65 /** |
67 * @type {cursors.Range} | |
68 * @private | |
69 */ | |
70 this.savedRange_ = null; | |
71 | |
72 /** | |
73 * Which variant of ChromeVox is active. | 66 * Which variant of ChromeVox is active. |
74 * @type {ChromeVoxMode} | 67 * @type {ChromeVoxMode} |
75 * @private | 68 * @private |
76 */ | 69 */ |
77 this.mode_ = ChromeVoxMode.COMPAT; | 70 this.mode_ = ChromeVoxMode.COMPAT; |
78 | 71 |
79 // Manually bind all functions to |this|. | 72 // Manually bind all functions to |this|. |
80 for (var func in this) { | 73 for (var func in this) { |
81 if (typeof(this[func]) == 'function') | 74 if (typeof(this[func]) == 'function') |
82 this[func] = this[func].bind(this); | 75 this[func] = this[func].bind(this); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 }.bind(this)); | 187 }.bind(this)); |
195 | 188 |
196 // If switching out of a ChromeVox Next mode, make sure we cancel | 189 // If switching out of a ChromeVox Next mode, make sure we cancel |
197 // the progress loading sound just in case. | 190 // the progress loading sound just in case. |
198 if ((this.mode_ === ChromeVoxMode.NEXT || | 191 if ((this.mode_ === ChromeVoxMode.NEXT || |
199 this.mode_ === ChromeVoxMode.FORCE_NEXT) && | 192 this.mode_ === ChromeVoxMode.FORCE_NEXT) && |
200 this.mode_ != mode) { | 193 this.mode_ != mode) { |
201 cvox.ChromeVox.earcons.cancelEarcon(cvox.Earcon.PAGE_START_LOADING); | 194 cvox.ChromeVox.earcons.cancelEarcon(cvox.Earcon.PAGE_START_LOADING); |
202 } | 195 } |
203 | 196 |
204 if (mode === ChromeVoxMode.NEXT || | |
205 mode === ChromeVoxMode.FORCE_NEXT) { | |
206 (new PanelCommand(PanelCommandType.ENABLE_MENUS)).send(); | |
207 } else { | |
208 (new PanelCommand(PanelCommandType.DISABLE_MENUS)).send(); | |
209 } | |
210 | |
211 this.mode_ = mode; | 197 this.mode_ = mode; |
212 }, | 198 }, |
213 | 199 |
214 /** | 200 /** |
215 * Mode refreshes takes into account both |url| and the current ChromeVox | 201 * Mode refreshes takes into account both |url| and the current ChromeVox |
216 * range. The latter gets used to decide if the user is or isn't in web | 202 * range. The latter gets used to decide if the user is or isn't in web |
217 * content. The focused state also needs to be set for this info to be | 203 * content. The focused state also needs to be set for this info to be |
218 * reliable. | 204 * reliable. |
219 * @override | 205 * @override |
220 */ | 206 */ |
(...skipping 21 matching lines...) Expand all Loading... |
242 return this.currentRange_; | 228 return this.currentRange_; |
243 }, | 229 }, |
244 | 230 |
245 /** | 231 /** |
246 * @override | 232 * @override |
247 */ | 233 */ |
248 setCurrentRange: function(newRange) { | 234 setCurrentRange: function(newRange) { |
249 if (!newRange) | 235 if (!newRange) |
250 return; | 236 return; |
251 | 237 |
252 var panelUrl = chrome.extension.getURL('cvox2/background/panel.html'); | |
253 if (newRange.start.node.root.docUrl.indexOf(panelUrl) != 0) | |
254 this.savedRange_ = new cursors.Range(newRange.start, newRange.end); | |
255 | |
256 this.currentRange_ = newRange; | 238 this.currentRange_ = newRange; |
257 | 239 |
258 if (this.currentRange_) | 240 if (this.currentRange_) |
259 this.currentRange_.start.node.makeVisible(); | 241 this.currentRange_.start.node.makeVisible(); |
260 }, | 242 }, |
261 | 243 |
262 /** Forces ChromeVox Next to be active for all tabs. */ | 244 /** Forces ChromeVox Next to be active for all tabs. */ |
263 forceChromeVoxNextActive: function() { | 245 forceChromeVoxNextActive: function() { |
264 this.setMode(ChromeVoxMode.FORCE_NEXT); | 246 this.setMode(ChromeVoxMode.FORCE_NEXT); |
265 }, | 247 }, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 case 'nextButton': | 288 case 'nextButton': |
307 dir = Dir.FORWARD; | 289 dir = Dir.FORWARD; |
308 pred = AutomationPredicate.button; | 290 pred = AutomationPredicate.button; |
309 predErrorMsg = 'no_next_button'; | 291 predErrorMsg = 'no_next_button'; |
310 break; | 292 break; |
311 case 'previousButton': | 293 case 'previousButton': |
312 dir = Dir.BACKWARD; | 294 dir = Dir.BACKWARD; |
313 pred = AutomationPredicate.button; | 295 pred = AutomationPredicate.button; |
314 predErrorMsg = 'no_previous_button'; | 296 predErrorMsg = 'no_previous_button'; |
315 break; | 297 break; |
316 case 'nextCheckbox': | 298 case 'nextCheckBox': |
317 dir = Dir.FORWARD; | 299 dir = Dir.FORWARD; |
318 pred = AutomationPredicate.checkBox; | 300 pred = AutomationPredicate.checkBox; |
319 predErrorMsg = 'no_next_checkbox'; | 301 predErrorMsg = 'no_next_checkbox'; |
320 break; | 302 break; |
321 case 'previousCheckbox': | 303 case 'previousCheckBox': |
322 dir = Dir.BACKWARD; | 304 dir = Dir.BACKWARD; |
323 pred = AutomationPredicate.checkBox; | 305 pred = AutomationPredicate.checkBox; |
324 predErrorMsg = 'no_previous_checkbox'; | 306 predErrorMsg = 'no_previous_checkbox'; |
325 break; | 307 break; |
326 case 'nextComboBox': | 308 case 'nextComboBox': |
327 dir = Dir.FORWARD; | 309 dir = Dir.FORWARD; |
328 pred = AutomationPredicate.comboBox; | 310 pred = AutomationPredicate.comboBox; |
329 predErrorMsg = 'no_next_combo_box'; | 311 predErrorMsg = 'no_next_combo_box'; |
330 break; | 312 break; |
331 case 'previousComboBox': | 313 case 'previousComboBox': |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 dir = Dir.FORWARD; | 369 dir = Dir.FORWARD; |
388 pred = AutomationPredicate.visitedLink; | 370 pred = AutomationPredicate.visitedLink; |
389 predErrorMsg = 'no_next_visited_link'; | 371 predErrorMsg = 'no_next_visited_link'; |
390 break; | 372 break; |
391 case 'previousVisitedLink': | 373 case 'previousVisitedLink': |
392 dir = Dir.BACKWARD; | 374 dir = Dir.BACKWARD; |
393 pred = AutomationPredicate.visitedLink; | 375 pred = AutomationPredicate.visitedLink; |
394 predErrorMsg = 'no_previous_visited_link'; | 376 predErrorMsg = 'no_previous_visited_link'; |
395 break; | 377 break; |
396 case 'right': | 378 case 'right': |
397 case 'nextObject': | 379 case 'nextElement': |
398 current = current.move(cursors.Unit.DOM_NODE, Dir.FORWARD); | 380 current = current.move(cursors.Unit.DOM_NODE, Dir.FORWARD); |
399 break; | 381 break; |
400 case 'left': | 382 case 'left': |
401 case 'previousObject': | 383 case 'previousElement': |
402 current = current.move(cursors.Unit.DOM_NODE, Dir.BACKWARD); | 384 current = current.move(cursors.Unit.DOM_NODE, Dir.BACKWARD); |
403 break; | 385 break; |
404 case 'jumpToTop': | 386 case 'goToBeginning': |
405 var node = | 387 var node = |
406 AutomationUtil.findNodePost(current.start.node.root, | 388 AutomationUtil.findNodePost(current.start.node.root, |
407 Dir.FORWARD, | 389 Dir.FORWARD, |
408 AutomationPredicate.leaf); | 390 AutomationPredicate.leaf); |
409 if (node) | 391 if (node) |
410 current = cursors.Range.fromNode(node); | 392 current = cursors.Range.fromNode(node); |
411 break; | 393 break; |
412 case 'jumpToBottom': | 394 case 'goToEnd': |
413 var node = | 395 var node = |
414 AutomationUtil.findNodePost(current.start.node.root, | 396 AutomationUtil.findNodePost(current.start.node.root, |
415 Dir.BACKWARD, | 397 Dir.BACKWARD, |
416 AutomationPredicate.leaf); | 398 AutomationPredicate.leaf); |
417 if (node) | 399 if (node) |
418 current = cursors.Range.fromNode(node); | 400 current = cursors.Range.fromNode(node); |
419 break; | 401 break; |
420 case 'forceClickOnCurrentItem': | 402 case 'forceClickOnCurrentItem': |
421 case 'performDefaultAction': | 403 case 'doDefault': |
422 if (this.currentRange_) { | 404 if (this.currentRange_) { |
423 var actionNode = this.currentRange_.start.node; | 405 var actionNode = this.currentRange_.start.node; |
424 if (actionNode.role == RoleType.inlineTextBox) | 406 if (actionNode.role == RoleType.inlineTextBox) |
425 actionNode = actionNode.parent; | 407 actionNode = actionNode.parent; |
426 actionNode.doDefault(); | 408 actionNode.doDefault(); |
427 } | 409 } |
428 // Skip all other processing; if focus changes, we should get an event | 410 // Skip all other processing; if focus changes, we should get an event |
429 // for that. | 411 // for that. |
430 return false; | 412 return false; |
431 case 'readFromHere': | 413 case 'continuousRead': |
432 global.isReadingContinuously = true; | 414 global.isReadingContinuously = true; |
433 var continueReading = function() { | 415 var continueReading = function() { |
434 if (!global.isReadingContinuously || !this.currentRange_) | 416 if (!global.isReadingContinuously || !this.currentRange_) |
435 return; | 417 return; |
436 | 418 |
437 var prevRange = this.currentRange_; | 419 var prevRange = this.currentRange_; |
438 var newRange = | 420 var newRange = |
439 this.currentRange_.move(cursors.Unit.DOM_NODE, Dir.FORWARD); | 421 this.currentRange_.move(cursors.Unit.DOM_NODE, Dir.FORWARD); |
440 | 422 |
441 // Stop if we've wrapped back to the document. | 423 // Stop if we've wrapped back to the document. |
(...skipping 11 matching lines...) Expand all Loading... |
453 .onSpeechEnd(continueReading) | 435 .onSpeechEnd(continueReading) |
454 .go(); | 436 .go(); |
455 }.bind(this); | 437 }.bind(this); |
456 | 438 |
457 new Output().withSpeechAndBraille( | 439 new Output().withSpeechAndBraille( |
458 this.currentRange_, null, Output.EventType.NAVIGATE) | 440 this.currentRange_, null, Output.EventType.NAVIGATE) |
459 .onSpeechEnd(continueReading) | 441 .onSpeechEnd(continueReading) |
460 .go(); | 442 .go(); |
461 | 443 |
462 return false; | 444 return false; |
463 case 'contextMenu': | 445 case 'showContextMenu': |
464 if (this.currentRange_) { | 446 if (this.currentRange_) { |
465 var actionNode = this.currentRange_.start.node; | 447 var actionNode = this.currentRange_.start.node; |
466 if (actionNode.role == RoleType.inlineTextBox) | 448 if (actionNode.role == RoleType.inlineTextBox) |
467 actionNode = actionNode.parent; | 449 actionNode = actionNode.parent; |
468 actionNode.showContextMenu(); | 450 actionNode.showContextMenu(); |
469 return false; | 451 return false; |
470 } | 452 } |
471 break; | 453 break; |
472 case 'showOptionsPage': | 454 case 'showOptionsPage': |
473 chrome.runtime.openOptionsPage(); | 455 chrome.runtime.openOptionsPage(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
508 if (cvox.ChromeVox.isStickyPrefOn) | 490 if (cvox.ChromeVox.isStickyPrefOn) |
509 chrome.accessibilityPrivate.setKeyboardListener(true, true); | 491 chrome.accessibilityPrivate.setKeyboardListener(true, true); |
510 else | 492 else |
511 chrome.accessibilityPrivate.setKeyboardListener(true, false); | 493 chrome.accessibilityPrivate.setKeyboardListener(true, false); |
512 return false; | 494 return false; |
513 case 'passThroughMode': | 495 case 'passThroughMode': |
514 cvox.ChromeVox.passThroughMode = true; | 496 cvox.ChromeVox.passThroughMode = true; |
515 cvox.ChromeVox.tts.speak( | 497 cvox.ChromeVox.tts.speak( |
516 Msgs.getMsg('pass_through_key'), cvox.QueueMode.QUEUE); | 498 Msgs.getMsg('pass_through_key'), cvox.QueueMode.QUEUE); |
517 return true; | 499 return true; |
518 case 'openChromeVoxMenus': | |
519 (new PanelCommand(PanelCommandType.OPEN_MENUS)).send(); | |
520 break; | |
521 case 'decreaseTtsRate': | |
522 this.increaseOrDecreaseSpeechProperty_(cvox.AbstractTts.RATE, false); | |
523 break; | |
524 case 'increaseTtsRate': | |
525 this.increaseOrDecreaseSpeechProperty_(cvox.AbstractTts.RATE, true); | |
526 break; | |
527 case 'decreaseTtsPitch': | |
528 this.increaseOrDecreaseSpeechProperty_(cvox.AbstractTts.PITCH, false); | |
529 break; | |
530 case 'increaseTtsPitch': | |
531 this.increaseOrDecreaseSpeechProperty_(cvox.AbstractTts.PITCH, true); | |
532 break; | |
533 case 'decreaseTtsVolume': | |
534 this.increaseOrDecreaseSpeechProperty_(cvox.AbstractTts.VOLUME, false); | |
535 break; | |
536 case 'increaseTtsVolume': | |
537 this.increaseOrDecreaseSpeechProperty_(cvox.AbstractTts.VOLUME, true); | |
538 break; | |
539 default: | 500 default: |
540 return true; | 501 return true; |
541 } | 502 } |
542 | 503 |
543 if (pred) { | 504 if (pred) { |
544 var node = AutomationUtil.findNextNode( | 505 var node = AutomationUtil.findNextNode( |
545 current.getBound(dir).node, dir, pred); | 506 current.getBound(dir).node, dir, pred); |
546 | 507 |
547 if (node) { | 508 if (node) { |
548 current = cursors.Range.fromNode(node); | 509 current = cursors.Range.fromNode(node); |
549 } else { | 510 } else { |
550 if (predErrorMsg) { | 511 if (predErrorMsg) { |
551 cvox.ChromeVox.tts.speak(Msgs.getMsg(predErrorMsg), | 512 cvox.ChromeVox.tts.speak(Msgs.getMsg(predErrorMsg), |
552 cvox.QueueMode.FLUSH); | 513 cvox.QueueMode.FLUSH); |
553 } | 514 } |
554 return false; | 515 return false; |
555 } | 516 } |
556 } | 517 } |
557 | 518 |
558 if (current) | 519 if (current) { |
559 this.navigateToRange_(current); | 520 // TODO(dtseng): Figure out what it means to focus a range. |
| 521 var actionNode = current.start.node; |
| 522 if (actionNode.role == RoleType.inlineTextBox) |
| 523 actionNode = actionNode.parent; |
| 524 |
| 525 // Iframes, when focused, causes the child webArea to fire focus event. |
| 526 // This can result in getting stuck when navigating backward. |
| 527 if (actionNode.role != RoleType.iframe && !actionNode.state.focused) |
| 528 actionNode.focus(); |
| 529 |
| 530 var prevRange = this.currentRange_; |
| 531 this.setCurrentRange(current); |
| 532 |
| 533 new Output().withSpeechAndBraille( |
| 534 this.currentRange_, prevRange, Output.EventType.NAVIGATE) |
| 535 .withQueueMode(cvox.QueueMode.FLUSH) |
| 536 .go(); |
| 537 } |
560 | 538 |
561 return false; | 539 return false; |
562 }, | 540 }, |
563 | 541 |
564 /** | 542 /** |
565 * Increase or decrease a speech property and make an announcement. | |
566 * @param {string} propertyName The name of the property to change. | |
567 * @param {boolean} increase If true, increases the property value by one | |
568 * step size, otherwise decreases. | |
569 */ | |
570 increaseOrDecreaseSpeechProperty_: function(propertyName, increase) { | |
571 cvox.ChromeVox.tts.increaseOrDecreaseProperty(propertyName, increase); | |
572 var announcement; | |
573 var valueAsPercent = Math.round( | |
574 cvox.ChromeVox.tts.propertyToPercentage(propertyName) * 100); | |
575 switch (propertyName) { | |
576 case cvox.AbstractTts.RATE: | |
577 announcement = Msgs.getMsg('announce_rate', [valueAsPercent]); | |
578 break; | |
579 case cvox.AbstractTts.PITCH: | |
580 announcement = Msgs.getMsg('announce_pitch', [valueAsPercent]); | |
581 break; | |
582 case cvox.AbstractTts.VOLUME: | |
583 announcement = Msgs.getMsg('announce_volume', [valueAsPercent]); | |
584 break; | |
585 } | |
586 if (announcement) { | |
587 cvox.ChromeVox.tts.speak( | |
588 announcement, cvox.QueueMode.FLUSH, | |
589 cvox.AbstractTts.PERSONALITY_ANNOTATION); | |
590 } | |
591 }, | |
592 | |
593 /** | |
594 * Navigate to the given range - it both sets the range and outputs it. | |
595 * @param {!cursors.Range} range The new range. | |
596 * @private | |
597 */ | |
598 navigateToRange_: function(range) { | |
599 // TODO(dtseng): Figure out what it means to focus a range. | |
600 var actionNode = range.start.node; | |
601 if (actionNode.role == RoleType.inlineTextBox) | |
602 actionNode = actionNode.parent; | |
603 | |
604 // Iframes, when focused, causes the child webArea to fire focus event. | |
605 // This can result in getting stuck when navigating backward. | |
606 if (actionNode.role != RoleType.iframe && !actionNode.state.focused) | |
607 actionNode.focus(); | |
608 | |
609 var prevRange = this.currentRange_; | |
610 this.setCurrentRange(range); | |
611 | |
612 new Output().withSpeechAndBraille( | |
613 range, prevRange, Output.EventType.NAVIGATE) | |
614 .withQueueMode(cvox.QueueMode.FLUSH) | |
615 .go(); | |
616 }, | |
617 | |
618 /** | |
619 * Handles key down events. | 543 * Handles key down events. |
620 * @param {Event} evt The key down event to process. | 544 * @param {Event} evt The key down event to process. |
621 * @return {boolean} True if the default action should be performed. | 545 * @return {boolean} True if the default action should be performed. |
622 */ | 546 */ |
623 onKeyDown: function(evt) { | 547 onKeyDown: function(evt) { |
624 evt.stickyMode = cvox.ChromeVox.isStickyModeOn() && cvox.ChromeVox.isActive; | 548 evt.stickyMode = cvox.ChromeVox.isStickyModeOn() && cvox.ChromeVox.isActive; |
625 if (cvox.ChromeVox.passThroughMode) | 549 if (cvox.ChromeVox.passThroughMode) |
626 return false; | 550 return false; |
627 | 551 |
628 if (this.mode_ != ChromeVoxMode.CLASSIC && | 552 if (this.mode_ != ChromeVoxMode.CLASSIC && |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 * @param {!cvox.BrailleKeyEvent} evt | 590 * @param {!cvox.BrailleKeyEvent} evt |
667 * @param {!cvox.NavBraille} content | 591 * @param {!cvox.NavBraille} content |
668 * @return {boolean} True if evt was processed. | 592 * @return {boolean} True if evt was processed. |
669 */ | 593 */ |
670 onBrailleKeyEvent: function(evt, content) { | 594 onBrailleKeyEvent: function(evt, content) { |
671 if (this.mode_ === ChromeVoxMode.CLASSIC) | 595 if (this.mode_ === ChromeVoxMode.CLASSIC) |
672 return false; | 596 return false; |
673 | 597 |
674 switch (evt.command) { | 598 switch (evt.command) { |
675 case cvox.BrailleKeyCommand.PAN_LEFT: | 599 case cvox.BrailleKeyCommand.PAN_LEFT: |
676 this.onGotCommand('previousObject'); | 600 this.onGotCommand('previousElement'); |
677 break; | 601 break; |
678 case cvox.BrailleKeyCommand.PAN_RIGHT: | 602 case cvox.BrailleKeyCommand.PAN_RIGHT: |
679 this.onGotCommand('nextObject'); | 603 this.onGotCommand('nextElement'); |
680 break; | 604 break; |
681 case cvox.BrailleKeyCommand.LINE_UP: | 605 case cvox.BrailleKeyCommand.LINE_UP: |
682 this.onGotCommand('previousLine'); | 606 this.onGotCommand('previousLine'); |
683 break; | 607 break; |
684 case cvox.BrailleKeyCommand.LINE_DOWN: | 608 case cvox.BrailleKeyCommand.LINE_DOWN: |
685 this.onGotCommand('nextLine'); | 609 this.onGotCommand('nextLine'); |
686 break; | 610 break; |
687 case cvox.BrailleKeyCommand.TOP: | 611 case cvox.BrailleKeyCommand.TOP: |
688 this.onGotCommand('jumpToTop'); | 612 this.onGotCommand('goToBeginning'); |
689 break; | 613 break; |
690 case cvox.BrailleKeyCommand.BOTTOM: | 614 case cvox.BrailleKeyCommand.BOTTOM: |
691 this.onGotCommand('jumpToBottom'); | 615 this.onGotCommand('goToEnd'); |
692 break; | 616 break; |
693 case cvox.BrailleKeyCommand.ROUTING: | 617 case cvox.BrailleKeyCommand.ROUTING: |
694 this.brailleRoutingCommand_( | 618 this.brailleRoutingCommand_( |
695 content.text, | 619 content.text, |
696 // Cast ok since displayPosition is always defined in this case. | 620 // Cast ok since displayPosition is always defined in this case. |
697 /** @type {number} */ (evt.displayPosition)); | 621 /** @type {number} */ (evt.displayPosition)); |
698 break; | 622 break; |
699 default: | 623 default: |
700 return false; | 624 return false; |
701 } | 625 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
792 target: 'next', | 716 target: 'next', |
793 isClassicEnabled: isClassicEnabled | 717 isClassicEnabled: isClassicEnabled |
794 }); | 718 }); |
795 } else if (action == 'onCommand') { | 719 } else if (action == 'onCommand') { |
796 this.onGotCommand(msg['command']); | 720 this.onGotCommand(msg['command']); |
797 } else if (action == 'flushNextUtterance') { | 721 } else if (action == 'flushNextUtterance') { |
798 Output.flushNextSpeechUtterance(); | 722 Output.flushNextSpeechUtterance(); |
799 } | 723 } |
800 break; | 724 break; |
801 } | 725 } |
802 }, | 726 } |
803 | |
804 /** | |
805 * Restore the range to the last range that was *not* in the ChromeVox | |
806 * panel. This is used when the ChromeVox Panel closes. | |
807 */ | |
808 restoreCurrentRange: function() { | |
809 if (this.savedRange_) { | |
810 var containingWebView = this.savedRange_.start.node; | |
811 while (containingWebView && containingWebView.role != RoleType.webView) | |
812 containingWebView = containingWebView.parent; | |
813 if (containingWebView) | |
814 containingWebView.focus(); | |
815 | |
816 this.navigateToRange_(this.savedRange_); | |
817 this.savedRange_ = null; | |
818 } | |
819 }, | |
820 }; | 727 }; |
821 | 728 |
822 /** | 729 /** |
823 * Converts a list of globs, as used in the extension manifest, to a regular | 730 * Converts a list of globs, as used in the extension manifest, to a regular |
824 * expression that matches if and only if any of the globs in the list matches. | 731 * expression that matches if and only if any of the globs in the list matches. |
825 * @param {!Array<string>} globs | 732 * @param {!Array<string>} globs |
826 * @return {!RegExp} | 733 * @return {!RegExp} |
827 * @private | 734 * @private |
828 */ | 735 */ |
829 Background.globsToRegExp_ = function(globs) { | 736 Background.globsToRegExp_ = function(globs) { |
830 return new RegExp('^(' + globs.map(function(glob) { | 737 return new RegExp('^(' + globs.map(function(glob) { |
831 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&') | 738 return glob.replace(/[.+^$(){}|[\]\\]/g, '\\$&') |
832 .replace(/\*/g, '.*') | 739 .replace(/\*/g, '.*') |
833 .replace(/\?/g, '.'); | 740 .replace(/\?/g, '.'); |
834 }).join('|') + ')$'); | 741 }).join('|') + ')$'); |
835 }; | 742 }; |
836 | 743 |
837 /** @type {Background} */ | 744 /** @type {Background} */ |
838 global.backgroundObj = new Background(); | 745 global.backgroundObj = new Background(); |
839 | 746 |
840 }); // goog.scope | 747 }); // goog.scope |
OLD | NEW |