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