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

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

Issue 1561773002: Implement ChromeVox Next menus. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@panel_view_type
Patch Set: Fix Ozone by only activating panel when fullscreen Created 4 years, 10 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');
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698