Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / chromevox / cvox2 / background / classic_compatibility.js
blob35eb9ca3bad527f9bcd4b9c34a6c48ae49f15646
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6  * @fileoverview Provides a compatibility layer for ChromeVox Classic during the
7  * transition to ChromeVox Next.
8  */
10 goog.provide('ClassicCompatibility');
12 goog.require('cvox.ExtensionBridge');
13 goog.require('cvox.KeyMap');
14 goog.require('cvox.KeySequence');
15 goog.require('cvox.KeyUtil');
16 goog.require('cvox.SimpleKeyEvent');
18 /**
19  * @constructor
20  */
21 var ClassicCompatibility = function() {
22   /**
23    * @type {!Array<{description: string, name: string, shortcut: string}>}
24    * @private
25    */
26   this.commands_ = [];
28   // We grab the list of commands from the manifest because
29   // chrome.commands.getAll is buggy.
30   /** @type {!Object} */
31   var commands = chrome.runtime.getManifest()['commands'];
32   for (var key in commands) {
33     /** @type {{suggested_key: {chromeos: string}}} */
34     var command = commands[key];
35     this.commands_.push({name: key, shortcut: command.suggested_key.chromeos});
36   }
39 ClassicCompatibility.prototype = {
40   /**
41    * Processes a ChromeVox Next command.
42    * @param {string} command
43    * @return {boolean} Whether the command was successfully processed.
44    */
45   onGotCommand: function(command) {
46     var evt = this.buildKeyEvent_(command);
47     if (evt) {
48       this.simulateKeyDownNext_(evt);
49       return true;
50     }
51     cvox.KeyUtil.sequencing = false;
52   },
54   /**
55    * Processes a ChromeVox Next command while in CLASSIC mode.
56    * @param {string} command
57    * @return {boolean} Whether the command was successfully processed.
58    */
59   onGotClassicCommand: function(command) {
60     var evt = this.buildKeyEvent_(command);
61     if (!evt)
62       return false;
63     this.simulateKeyDownClassic_(evt);
64     return true;
65   },
67   /**
68    * @param {string} command
69    * @return {cvox.SimpleKeyEvent?}
70    */
71   buildKeyEvent_: function(command) {
72     var commandInfo = this.commands_.filter(function(c) {
73       return c.name == command;
74     }.bind(this))[0];
75     if (!commandInfo)
76       return null;
77     var shortcut = commandInfo.shortcut;
78     return this.convertCommandShortcutToKeyEvent_(shortcut);
79   },
81   /**
82    * @param {cvox.SimpleKeyEvent} evt
83    * @private
84    */
85   simulateKeyDownNext_: function(evt) {
86     var keySequence = cvox.KeyUtil.keyEventToKeySequence(evt);
87     var classicCommand =
88         cvox.KeyMap.fromCurrentKeyMap().commandForKey(keySequence);
89     if (classicCommand) {
90       var nextCommand = this.getNextCommand_(classicCommand);
91       if (nextCommand)
92         global.backgroundObj.onGotCommand(nextCommand, true);
93     }
94   },
96   /**
97    * @param {cvox.SimpleKeyEvent} evt
98    * @private
99    */
100   simulateKeyDownClassic_: function(evt) {
101     var keySequence = cvox.KeyUtil.keyEventToKeySequence(evt);
102     var classicCommand =
103         cvox.KeyMap.fromCurrentKeyMap().commandForKey(keySequence);
104     if (classicCommand) {
105       cvox.ExtensionBridge.send({
106         'message': 'USER_COMMAND',
107         'command': classicCommand
108       });
109     }
110   },
112   /**
113    * @param {string} shortcut
114    * @return {cvox.SimpleKeyEvent}
115    * @private
116    */
117   convertCommandShortcutToKeyEvent_: function(shortcut) {
118     var evt = {};
119     shortcut.split('+').forEach(function(token) {
120       // Known tokens.
121       switch (token) {
122         case 'Ctrl':
123           evt.ctrlKey = true;
124           break;
125         case 'Shift':
126           evt.shiftKey = true;
127           break;
128         case 'Alt':
129           evt.altKey = true;
130           break;
131         case 'Search':
132           evt.searchKeyHeld = true;
133           break;
134         case 'Space':
135           evt.keyCode = 32;
136           break;
137         case 'Left':
138           evt.keyCode = 37;
139           break;
140         case 'Up':
141           evt.keyCode = 38;
142           break;
143         case 'Right':
144           evt.keyCode = 39;
145           break;
146         case 'Down':
147           evt.keyCode = 40;
148           break;
149         default:
150           evt.keyCode = token.charCodeAt(0);
151       }
152     });
154     return evt;
155   },
157   /**
158    * Maps a Classic command to an approximate equivalent in Next.
159    * @param {string} classicCommand
160    * @return {string}
161    * @private
162    */
163   getNextCommand_: function(classicCommand) {
164     switch (classicCommand) {
165       case 'right':
166         return 'nextElement';
167       case 'forward':
168         return 'nextLine';
169       case 'left':
170         return 'previousElement';
171       case 'backward':
172         return 'previousLine';
173       case 'forceClickOnCurrentItem':
174         return 'doDefault';
175       case 'readFromHere':
176         return 'continuousRead';
177       default:
178         return classicCommand;
179     }
180   }