| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 ChromeVox commands. | 6 * @fileoverview ChromeVox commands. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 goog.provide('CommandHandler'); | 9 goog.provide('CommandHandler'); |
| 10 | 10 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 if (!focusedNode) | 38 if (!focusedNode) |
| 39 ChromeVoxState.instance.setCurrentRange(null); | 39 ChromeVoxState.instance.setCurrentRange(null); |
| 40 }); | 40 }); |
| 41 | 41 |
| 42 // These commands don't require a current range and work in all modes. | 42 // These commands don't require a current range and work in all modes. |
| 43 switch (command) { | 43 switch (command) { |
| 44 case 'speakTimeAndDate': | 44 case 'speakTimeAndDate': |
| 45 chrome.automation.getDesktop(function(d) { | 45 chrome.automation.getDesktop(function(d) { |
| 46 // First, try speaking the on-screen time. | 46 // First, try speaking the on-screen time. |
| 47 var allTime = d.findAll({role: RoleType.TIME}); | 47 var allTime = d.findAll({role: RoleType.TIME}); |
| 48 allTime.filter(function(t) { return t.root.role == RoleType.DESKTOP; }); | 48 allTime.filter(function(t) { |
| 49 return t.root.role == RoleType.DESKTOP; |
| 50 }); |
| 49 | 51 |
| 50 var timeString = ''; | 52 var timeString = ''; |
| 51 allTime.forEach(function(t) { | 53 allTime.forEach(function(t) { |
| 52 if (t.name) timeString = t.name; | 54 if (t.name) |
| 55 timeString = t.name; |
| 53 }); | 56 }); |
| 54 if (timeString) { | 57 if (timeString) { |
| 55 cvox.ChromeVox.tts.speak(timeString, cvox.QueueMode.FLUSH); | 58 cvox.ChromeVox.tts.speak(timeString, cvox.QueueMode.FLUSH); |
| 56 } else { | 59 } else { |
| 57 // Fallback to the old way of speaking time. | 60 // Fallback to the old way of speaking time. |
| 58 var output = new Output(); | 61 var output = new Output(); |
| 59 var dateTime = new Date(); | 62 var dateTime = new Date(); |
| 60 output | 63 output |
| 61 .withString( | 64 .withString( |
| 62 dateTime.toLocaleTimeString() + ', ' + | 65 dateTime.toLocaleTimeString() + ', ' + |
| (...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 pred = AutomationPredicate.group; | 463 pred = AutomationPredicate.group; |
| 461 break; | 464 break; |
| 462 case 'nextGroup': | 465 case 'nextGroup': |
| 463 skipSync = true; | 466 skipSync = true; |
| 464 dir = Dir.FORWARD; | 467 dir = Dir.FORWARD; |
| 465 pred = AutomationPredicate.group; | 468 pred = AutomationPredicate.group; |
| 466 break; | 469 break; |
| 467 case 'jumpToTop': | 470 case 'jumpToTop': |
| 468 var node = AutomationUtil.findNodePost( | 471 var node = AutomationUtil.findNodePost( |
| 469 current.start.node.root, Dir.FORWARD, AutomationPredicate.leaf); | 472 current.start.node.root, Dir.FORWARD, AutomationPredicate.leaf); |
| 470 if (node) | 473 if (node) |
| 471 current = cursors.Range.fromNode(node); | 474 current = cursors.Range.fromNode(node); |
| 472 break; | 475 break; |
| 473 case 'jumpToBottom': | 476 case 'jumpToBottom': |
| 474 var node = AutomationUtil.findNodePost( | 477 var node = AutomationUtil.findNodePost( |
| 475 current.start.node.root, Dir.BACKWARD, AutomationPredicate.leaf); | 478 current.start.node.root, Dir.BACKWARD, AutomationPredicate.leaf); |
| 476 if (node) | 479 if (node) |
| 477 current = cursors.Range.fromNode(node); | 480 current = cursors.Range.fromNode(node); |
| 478 break; | 481 break; |
| 479 case 'forceClickOnCurrentItem': | 482 case 'forceClickOnCurrentItem': |
| 480 if (ChromeVoxState.instance.currentRange) { | 483 if (ChromeVoxState.instance.currentRange) { |
| 481 var actionNode = ChromeVoxState.instance.currentRange.start.node; | 484 var actionNode = ChromeVoxState.instance.currentRange.start.node; |
| 482 while (actionNode.role == RoleType.INLINE_TEXT_BOX || | 485 while (actionNode.role == RoleType.INLINE_TEXT_BOX || |
| 483 actionNode.role == RoleType.STATIC_TEXT) | 486 actionNode.role == RoleType.STATIC_TEXT) |
| 484 actionNode = actionNode.parent; | 487 actionNode = actionNode.parent; |
| 485 if (actionNode.inPageLinkTarget) { | 488 if (actionNode.inPageLinkTarget) { |
| 486 ChromeVoxState.instance.navigateToRange( | 489 ChromeVoxState.instance.navigateToRange( |
| 487 cursors.Range.fromNode(actionNode.inPageLinkTarget)); | 490 cursors.Range.fromNode(actionNode.inPageLinkTarget)); |
| 488 } else { | 491 } else { |
| 489 actionNode.doDefault(); | 492 actionNode.doDefault(); |
| 490 } | 493 } |
| 491 } | 494 } |
| 492 // Skip all other processing; if focus changes, we should get an event | 495 // Skip all other processing; if focus changes, we should get an event |
| 493 // for that. | 496 // for that. |
| 494 return false; | 497 return false; |
| 495 case 'readFromHere': | 498 case 'readFromHere': |
| 496 ChromeVoxState.isReadingContinuously = true; | 499 ChromeVoxState.isReadingContinuously = true; |
| 497 var continueReading = function() { | 500 var continueReading = function() { |
| 498 if (!ChromeVoxState.isReadingContinuously || | 501 if (!ChromeVoxState.isReadingContinuously || |
| 499 !ChromeVoxState.instance.currentRange_) | 502 !ChromeVoxState.instance.currentRange_) |
| 500 return; | 503 return; |
| 501 | 504 |
| 502 var prevRange = ChromeVoxState.instance.currentRange_; | 505 var prevRange = ChromeVoxState.instance.currentRange_; |
| 503 var newRange = | 506 var newRange = ChromeVoxState.instance.currentRange_.move( |
| 504 ChromeVoxState.instance.currentRange_.move( | 507 cursors.Unit.NODE, Dir.FORWARD); |
| 505 cursors.Unit.NODE, Dir.FORWARD); | |
| 506 | 508 |
| 507 // Stop if we've wrapped back to the document. | 509 // Stop if we've wrapped back to the document. |
| 508 var maybeDoc = newRange.start.node; | 510 var maybeDoc = newRange.start.node; |
| 509 if (maybeDoc.role == RoleType.ROOT_WEB_AREA && | 511 if (maybeDoc.role == RoleType.ROOT_WEB_AREA && |
| 510 maybeDoc.parent.root.role == RoleType.DESKTOP) { | 512 maybeDoc.parent.root.role == RoleType.DESKTOP) { |
| 511 ChromeVoxState.isReadingContinuously = false; | 513 ChromeVoxState.isReadingContinuously = false; |
| 512 return; | 514 return; |
| 513 } | 515 } |
| 514 | 516 |
| 515 ChromeVoxState.instance.setCurrentRange(newRange); | 517 ChromeVoxState.instance.setCurrentRange(newRange); |
| 516 | 518 |
| 517 new Output() | 519 new Output() |
| 518 .withRichSpeechAndBraille(ChromeVoxState.instance.currentRange_, | 520 .withRichSpeechAndBraille( |
| 519 prevRange, | 521 ChromeVoxState.instance.currentRange_, prevRange, |
| 520 Output.EventType.NAVIGATE) | 522 Output.EventType.NAVIGATE) |
| 521 .onSpeechEnd(continueReading) | 523 .onSpeechEnd(continueReading) |
| 522 .go(); | 524 .go(); |
| 523 }.bind(this); | 525 }.bind(this); |
| 524 | 526 |
| 525 new Output() | 527 new Output() |
| 526 .withRichSpeechAndBraille(ChromeVoxState.instance.currentRange_, | 528 .withRichSpeechAndBraille( |
| 527 null, | 529 ChromeVoxState.instance.currentRange_, null, |
| 528 Output.EventType.NAVIGATE) | 530 Output.EventType.NAVIGATE) |
| 529 .onSpeechEnd(continueReading) | 531 .onSpeechEnd(continueReading) |
| 530 .go(); | 532 .go(); |
| 531 | 533 |
| 532 return false; | 534 return false; |
| 533 case 'contextMenu': | 535 case 'contextMenu': |
| 534 if (ChromeVoxState.instance.currentRange_) { | 536 if (ChromeVoxState.instance.currentRange_) { |
| 535 var actionNode = ChromeVoxState.instance.currentRange_.start.node; | 537 var actionNode = ChromeVoxState.instance.currentRange_.start.node; |
| 536 if (actionNode.role == RoleType.INLINE_TEXT_BOX) | 538 if (actionNode.role == RoleType.INLINE_TEXT_BOX) |
| 537 actionNode = actionNode.parent; | 539 actionNode = actionNode.parent; |
| 538 actionNode.showContextMenu(); | 540 actionNode.showContextMenu(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 563 case 'readCurrentTitle': | 565 case 'readCurrentTitle': |
| 564 var target = ChromeVoxState.instance.currentRange_.start.node; | 566 var target = ChromeVoxState.instance.currentRange_.start.node; |
| 565 var output = new Output(); | 567 var output = new Output(); |
| 566 | 568 |
| 567 if (target.root.role == RoleType.ROOT_WEB_AREA) { | 569 if (target.root.role == RoleType.ROOT_WEB_AREA) { |
| 568 // Web. | 570 // Web. |
| 569 target = target.root; | 571 target = target.root; |
| 570 output.withString(target.name || target.docUrl); | 572 output.withString(target.name || target.docUrl); |
| 571 } else { | 573 } else { |
| 572 // Views. | 574 // Views. |
| 573 while (target.role != RoleType.WINDOW) target = target.parent; | 575 while (target.role != RoleType.WINDOW) |
| 576 target = target.parent; |
| 574 if (target) | 577 if (target) |
| 575 output.withString(target.name || ''); | 578 output.withString(target.name || ''); |
| 576 } | 579 } |
| 577 output.go(); | 580 output.go(); |
| 578 return false; | 581 return false; |
| 579 case 'readCurrentURL': | 582 case 'readCurrentURL': |
| 580 var output = new Output(); | 583 var output = new Output(); |
| 581 var target = ChromeVoxState.instance.currentRange_.start.node.root; | 584 var target = ChromeVoxState.instance.currentRange_.start.node.root; |
| 582 output.withString(target.docUrl || '').go(); | 585 output.withString(target.docUrl || '').go(); |
| 583 return false; | 586 return false; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 predErrorMsg = 'no_cell_right'; | 657 predErrorMsg = 'no_cell_right'; |
| 655 rootPred = AutomationPredicate.row; | 658 rootPred = AutomationPredicate.row; |
| 656 break; | 659 break; |
| 657 case 'goToRowFirstCell': | 660 case 'goToRowFirstCell': |
| 658 case 'goToRowLastCell': | 661 case 'goToRowLastCell': |
| 659 var node = current.start.node; | 662 var node = current.start.node; |
| 660 while (node && node.role != RoleType.ROW) | 663 while (node && node.role != RoleType.ROW) |
| 661 node = node.parent; | 664 node = node.parent; |
| 662 if (!node) | 665 if (!node) |
| 663 break; | 666 break; |
| 664 var end = AutomationUtil.findNodePost(node, | 667 var end = AutomationUtil.findNodePost( |
| 665 command == 'goToRowLastCell' ? Dir.BACKWARD : Dir.FORWARD, | 668 node, command == 'goToRowLastCell' ? Dir.BACKWARD : Dir.FORWARD, |
| 666 AutomationPredicate.leaf); | 669 AutomationPredicate.leaf); |
| 667 if (end) | 670 if (end) |
| 668 current = cursors.Range.fromNode(end); | 671 current = cursors.Range.fromNode(end); |
| 669 break; | 672 break; |
| 670 case 'goToColFirstCell': | 673 case 'goToColFirstCell': |
| 671 dir = Dir.FORWARD; | 674 dir = Dir.FORWARD; |
| 672 var node = current.start.node; | 675 var node = current.start.node; |
| 673 while (node && node.role != RoleType.TABLE) | 676 while (node && node.role != RoleType.TABLE) |
| 674 node = node.parent; | 677 node = node.parent; |
| 675 if (!node || !node.firstChild) | 678 if (!node || !node.firstChild) |
| (...skipping 21 matching lines...) Expand all Loading... |
| 697 predErrorMsg = 'no_cell_below'; | 700 predErrorMsg = 'no_cell_below'; |
| 698 rootPred = AutomationPredicate.table; | 701 rootPred = AutomationPredicate.table; |
| 699 break; | 702 break; |
| 700 case 'goToFirstCell': | 703 case 'goToFirstCell': |
| 701 case 'goToLastCell': | 704 case 'goToLastCell': |
| 702 node = current.start.node; | 705 node = current.start.node; |
| 703 while (node && node.role != RoleType.TABLE) | 706 while (node && node.role != RoleType.TABLE) |
| 704 node = node.parent; | 707 node = node.parent; |
| 705 if (!node) | 708 if (!node) |
| 706 break; | 709 break; |
| 707 var end = AutomationUtil.findNodePost(node, | 710 var end = AutomationUtil.findNodePost( |
| 708 command == 'goToLastCell' ? Dir.BACKWARD : Dir.FORWARD, | 711 node, command == 'goToLastCell' ? Dir.BACKWARD : Dir.FORWARD, |
| 709 AutomationPredicate.leaf); | 712 AutomationPredicate.leaf); |
| 710 if (end) | 713 if (end) |
| 711 current = cursors.Range.fromNode(end); | 714 current = cursors.Range.fromNode(end); |
| 712 break; | 715 break; |
| 713 default: | 716 default: |
| 714 return true; | 717 return true; |
| 715 } | 718 } |
| 716 | 719 |
| 717 if (didNavigate) | 720 if (didNavigate) |
| 718 chrome.metricsPrivate.recordUserAction('Accessibility.ChromeVox.Navigate'); | 721 chrome.metricsPrivate.recordUserAction('Accessibility.ChromeVox.Navigate'); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 733 | 736 |
| 734 if (node) { | 737 if (node) { |
| 735 current = cursors.Range.fromNode(node); | 738 current = cursors.Range.fromNode(node); |
| 736 } else { | 739 } else { |
| 737 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP); | 740 cvox.ChromeVox.earcons.playEarcon(cvox.Earcon.WRAP); |
| 738 var root = AutomationUtil.getTopLevelRoot(bound) || bound.root; | 741 var root = AutomationUtil.getTopLevelRoot(bound) || bound.root; |
| 739 if (dir == Dir.FORWARD) { | 742 if (dir == Dir.FORWARD) { |
| 740 bound = root; | 743 bound = root; |
| 741 } else { | 744 } else { |
| 742 bound = AutomationUtil.findNodePost( | 745 bound = AutomationUtil.findNodePost( |
| 743 root, dir, AutomationPredicate.leaf) || bound; | 746 root, dir, AutomationPredicate.leaf) || |
| 747 bound; |
| 744 } | 748 } |
| 745 node = AutomationUtil.findNextNode( | 749 node = AutomationUtil.findNextNode( |
| 746 bound, dir, pred, {skipInitialAncestry: true}); | 750 bound, dir, pred, {skipInitialAncestry: true}); |
| 747 | 751 |
| 748 if (node && !skipSync) { | 752 if (node && !skipSync) { |
| 749 node = AutomationUtil.findNodePre( | 753 node = AutomationUtil.findNodePre( |
| 750 node, Dir.FORWARD, AutomationPredicate.object) || node; | 754 node, Dir.FORWARD, AutomationPredicate.object) || |
| 751 } | 755 node; |
| 756 } |
| 752 | 757 |
| 753 if (node) { | 758 if (node) { |
| 754 current = cursors.Range.fromNode(node); | 759 current = cursors.Range.fromNode(node); |
| 755 } else if (predErrorMsg) { | 760 } else if (predErrorMsg) { |
| 756 cvox.ChromeVox.tts.speak( | 761 cvox.ChromeVox.tts.speak( |
| 757 Msgs.getMsg(predErrorMsg), cvox.QueueMode.FLUSH); | 762 Msgs.getMsg(predErrorMsg), cvox.QueueMode.FLUSH); |
| 758 return false; | 763 return false; |
| 759 } | 764 } |
| 760 } | 765 } |
| 761 } | 766 } |
| 762 } | 767 } |
| 763 | 768 |
| 764 if (current) | 769 if (current) |
| 765 ChromeVoxState.instance.navigateToRange(current, undefined, speechProps); | 770 ChromeVoxState.instance.navigateToRange(current, undefined, speechProps); |
| 766 | 771 |
| 767 return false; | 772 return false; |
| 768 }; | 773 }; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 785 chrome.commands.onCommand.addListener(CommandHandler.onCommand); | 790 chrome.commands.onCommand.addListener(CommandHandler.onCommand); |
| 786 }; | 791 }; |
| 787 | 792 |
| 788 /** | 793 /** |
| 789 * Increase or decrease a speech property and make an announcement. | 794 * Increase or decrease a speech property and make an announcement. |
| 790 * @param {string} propertyName The name of the property to change. | 795 * @param {string} propertyName The name of the property to change. |
| 791 * @param {boolean} increase If true, increases the property value by one | 796 * @param {boolean} increase If true, increases the property value by one |
| 792 * step size, otherwise decreases. | 797 * step size, otherwise decreases. |
| 793 * @private | 798 * @private |
| 794 */ | 799 */ |
| 795 CommandHandler.increaseOrDecreaseSpeechProperty_ = | 800 CommandHandler.increaseOrDecreaseSpeechProperty_ = function( |
| 796 function(propertyName, increase) { | 801 propertyName, increase) { |
| 797 cvox.ChromeVox.tts.increaseOrDecreaseProperty(propertyName, increase); | 802 cvox.ChromeVox.tts.increaseOrDecreaseProperty(propertyName, increase); |
| 798 var announcement; | 803 var announcement; |
| 799 var valueAsPercent = Math.round( | 804 var valueAsPercent = |
| 800 cvox.ChromeVox.tts.propertyToPercentage(propertyName) * 100); | 805 Math.round(cvox.ChromeVox.tts.propertyToPercentage(propertyName) * 100); |
| 801 switch (propertyName) { | 806 switch (propertyName) { |
| 802 case cvox.AbstractTts.RATE: | 807 case cvox.AbstractTts.RATE: |
| 803 announcement = Msgs.getMsg('announce_rate', [valueAsPercent]); | 808 announcement = Msgs.getMsg('announce_rate', [valueAsPercent]); |
| 804 break; | 809 break; |
| 805 case cvox.AbstractTts.PITCH: | 810 case cvox.AbstractTts.PITCH: |
| 806 announcement = Msgs.getMsg('announce_pitch', [valueAsPercent]); | 811 announcement = Msgs.getMsg('announce_pitch', [valueAsPercent]); |
| 807 break; | 812 break; |
| 808 case cvox.AbstractTts.VOLUME: | 813 case cvox.AbstractTts.VOLUME: |
| 809 announcement = Msgs.getMsg('announce_volume', [valueAsPercent]); | 814 announcement = Msgs.getMsg('announce_volume', [valueAsPercent]); |
| 810 break; | 815 break; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 826 * Called when an image frame is received on a node. | 831 * Called when an image frame is received on a node. |
| 827 * @param {!(AutomationEvent|CustomAutomationEvent)} event The event. | 832 * @param {!(AutomationEvent|CustomAutomationEvent)} event The event. |
| 828 * @private | 833 * @private |
| 829 */ | 834 */ |
| 830 CommandHandler.onImageFrameUpdated_ = function(event) { | 835 CommandHandler.onImageFrameUpdated_ = function(event) { |
| 831 var target = event.target; | 836 var target = event.target; |
| 832 if (target != CommandHandler.imageNode_) | 837 if (target != CommandHandler.imageNode_) |
| 833 return; | 838 return; |
| 834 | 839 |
| 835 if (!AutomationUtil.isDescendantOf( | 840 if (!AutomationUtil.isDescendantOf( |
| 836 ChromeVoxState.instance.currentRange.start.node, | 841 ChromeVoxState.instance.currentRange.start.node, |
| 837 CommandHandler.imageNode_)) { | 842 CommandHandler.imageNode_)) { |
| 838 CommandHandler.imageNode_.removeEventListener( | 843 CommandHandler.imageNode_.removeEventListener( |
| 839 EventType.IMAGE_FRAME_UPDATED, | 844 EventType.IMAGE_FRAME_UPDATED, CommandHandler.onImageFrameUpdated_, |
| 840 CommandHandler.onImageFrameUpdated_, false); | 845 false); |
| 841 CommandHandler.imageNode_ = null; | 846 CommandHandler.imageNode_ = null; |
| 842 return; | 847 return; |
| 843 } | 848 } |
| 844 | 849 |
| 845 if (target.imageDataUrl) { | 850 if (target.imageDataUrl) { |
| 846 cvox.ChromeVox.braille.writeRawImage(target.imageDataUrl); | 851 cvox.ChromeVox.braille.writeRawImage(target.imageDataUrl); |
| 847 cvox.ChromeVox.braille.freeze(); | 852 cvox.ChromeVox.braille.freeze(); |
| 848 } | 853 } |
| 849 }; | 854 }; |
| 850 | 855 |
| 851 /** | 856 /** |
| 852 * Handle the command to view the first graphic within the current range | 857 * Handle the command to view the first graphic within the current range |
| 853 * as braille. | 858 * as braille. |
| 854 * @param {!AutomationNode} current The current range. | 859 * @param {!AutomationNode} current The current range. |
| 855 * @private | 860 * @private |
| 856 */ | 861 */ |
| 857 CommandHandler.viewGraphicAsBraille_ = function(current) { | 862 CommandHandler.viewGraphicAsBraille_ = function(current) { |
| 858 if (CommandHandler.imageNode_) { | 863 if (CommandHandler.imageNode_) { |
| 859 CommandHandler.imageNode_.removeEventListener( | 864 CommandHandler.imageNode_.removeEventListener( |
| 860 EventType.IMAGE_FRAME_UPDATED, | 865 EventType.IMAGE_FRAME_UPDATED, CommandHandler.onImageFrameUpdated_, |
| 861 CommandHandler.onImageFrameUpdated_, false); | 866 false); |
| 862 CommandHandler.imageNode_ = null; | 867 CommandHandler.imageNode_ = null; |
| 863 } | 868 } |
| 864 | 869 |
| 865 // Find the first node within the current range that supports image data. | 870 // Find the first node within the current range that supports image data. |
| 866 var imageNode = AutomationUtil.findNodePost( | 871 var imageNode = AutomationUtil.findNodePost( |
| 867 current.start.node, Dir.FORWARD, | 872 current.start.node, Dir.FORWARD, AutomationPredicate.supportsImageData); |
| 868 AutomationPredicate.supportsImageData); | |
| 869 if (!imageNode) | 873 if (!imageNode) |
| 870 return; | 874 return; |
| 871 | 875 |
| 872 imageNode.addEventListener(EventType.IMAGE_FRAME_UPDATED, | 876 imageNode.addEventListener( |
| 873 this.onImageFrameUpdated_, false); | 877 EventType.IMAGE_FRAME_UPDATED, this.onImageFrameUpdated_, false); |
| 874 CommandHandler.imageNode_ = imageNode; | 878 CommandHandler.imageNode_ = imageNode; |
| 875 if (imageNode.imageDataUrl) { | 879 if (imageNode.imageDataUrl) { |
| 876 var event = new CustomAutomationEvent( | 880 var event = new CustomAutomationEvent( |
| 877 EventType.IMAGE_FRAME_UPDATED, imageNode, 'page'); | 881 EventType.IMAGE_FRAME_UPDATED, imageNode, 'page'); |
| 878 CommandHandler.onImageFrameUpdated_(event); | 882 CommandHandler.onImageFrameUpdated_(event); |
| 879 } else { | 883 } else { |
| 880 imageNode.getImageData(0, 0); | 884 imageNode.getImageData(0, 0); |
| 881 } | 885 } |
| 882 }; | 886 }; |
| 883 | 887 |
| 884 /** | 888 /** |
| 885 * Performs global initialization. | 889 * Performs global initialization. |
| 886 * @private | 890 * @private |
| 887 */ | 891 */ |
| 888 CommandHandler.init_ = function() { | 892 CommandHandler.init_ = function() { |
| 889 var firstRunId = 'jdgcneonijmofocbhmijhacgchbihela'; | 893 var firstRunId = 'jdgcneonijmofocbhmijhacgchbihela'; |
| 890 chrome.runtime.onMessageExternal.addListener( | 894 chrome.runtime.onMessageExternal.addListener(function( |
| 891 function(request, sender, sendResponse) { | 895 request, sender, sendResponse) { |
| 892 if (sender.id != firstRunId) | 896 if (sender.id != firstRunId) |
| 893 return; | 897 return; |
| 894 | 898 |
| 895 if (request.openTutorial) { | 899 if (request.openTutorial) { |
| 896 var launchTutorial = function(desktop, evt) { | 900 var launchTutorial = function(desktop, evt) { |
| 897 desktop.removeEventListener( | 901 desktop.removeEventListener( |
| 898 chrome.automation.EventType.FOCUS, launchTutorial, true); | 902 chrome.automation.EventType.FOCUS, launchTutorial, true); |
| 899 CommandHandler.onCommand('help'); | 903 CommandHandler.onCommand('help'); |
| 900 }; | 904 }; |
| 901 | 905 |
| 902 // Since we get this command early on ChromeVox launch, the first run | 906 // Since we get this command early on ChromeVox launch, the first run |
| 903 // UI is not yet shown. Monitor for when first run gets focused, and | 907 // UI is not yet shown. Monitor for when first run gets focused, and |
| 904 // show our tutorial. | 908 // show our tutorial. |
| 905 chrome.automation.getDesktop(function(desktop) { | 909 chrome.automation.getDesktop(function(desktop) { |
| 906 launchTutorial = launchTutorial.bind(this, desktop); | 910 launchTutorial = launchTutorial.bind(this, desktop); |
| 907 desktop.addEventListener( | 911 desktop.addEventListener( |
| 908 chrome.automation.EventType.FOCUS, launchTutorial, true); | 912 chrome.automation.EventType.FOCUS, launchTutorial, true); |
| 909 }); | |
| 910 } | |
| 911 }); | 913 }); |
| 914 } |
| 915 }); |
| 912 }; | 916 }; |
| 913 | 917 |
| 914 CommandHandler.init_(); | 918 CommandHandler.init_(); |
| 915 | 919 |
| 916 }); // goog.scope | 920 }); // goog.scope |
| OLD | NEW |