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
3 // found in the LICENSE file.
5 var CLOSURE_NO_DEPS
=true;
10 * Armed callback to be triggered when a keyset changes.
11 * @type {{string:target function:callback}}
14 var keysetChangeListener_
;
17 * Registers a function, which may override a preexisting implementation.
18 * @param {string} path Full path for the function name.
19 * @param {function=} opt_fn Optional function definition. If not specified,
20 * the default implementation prettyprints the method call with arguments.
21 * @return {function} Registered function, which may be a mock implementation.
23 function registerFunction(path
, opt_fn
) {
24 var parts
= path
.split('.');
30 var prettyprint = function(arg
) {
31 if (arg
instanceof Array
) {
33 for (var i
= 0; i
< arg
.length
; i
++) {
34 terms
.push(prettyprint(arg
[i
]));
36 return '[' + terms
.join(', ') + ']';
37 } else if (typeof arg
== 'object') {
39 for (var key
in arg
) {
40 properties
.push(key
+ ': ' + prettyprint(arg
[key
]));
42 return '{' + properties
.join(', ') + '}';
47 // The property 'arguments' is an array-like object. Convert to a true
48 // array for prettyprinting.
49 var args
= Array
.prototype.slice
.call(arguments
);
50 console
.log('Call to ' + path
+ ': ' + prettyprint(args
));
53 for (var i
= 0; i
< parts
.length
- 1; i
++) {
60 base
[parts
[parts
.length
- 1]] = fn
;
65 * The chrome.i18n API is not compatible with component extensions due to the
66 * way component extensions are loaded (crbug/66834).
68 function overrideGetMessage() {
69 var originalGetMessage
= chrome
.i18n
.getMessage
;
72 * Localize a string resource.
73 * @param {string} key The message key to localize.
74 * @return {string} Translated resource.
76 chrome
.i18n
.getMessage = function(key
) {
77 if (key
.indexOf('@@') == 0)
78 return originalGetMessage(key
);
80 // TODO(kevers): Add support for other locales.
81 var table
= i18n
.input
.chrome
.inputview
.TranslationTable
;
82 var entry
= table
[key
];
84 entry
= table
[key
.toLowerCase()];
85 return entry
? entry
.message
|| '' : '';
90 * Overrides call to switch keysets in order to catch when the keyboard
91 * is ready for input. Used to synchronize the start of automated
92 * virtual keyboard tests.
94 function overrideSwitchToKeyset() {
95 var KeyboardContainer
= i18n
.input
.chrome
.inputview
.KeyboardContainer
;
96 var switcher
= KeyboardContainer
.prototype.switchToKeyset
;
97 KeyboardContainer
.prototype.switchToKeyset = function() {
98 var success
= switcher
.apply(this, arguments
);
100 // The first resize call forces resizing of the keyboard window.
101 // The second resize call forces a clean layout for chrome://keyboard.
102 controller
.resize(false);
103 controller
.resize(true);
104 var settings
= controller
.model_
.settings
;
105 settings
.supportCompact
= true;
106 if (keysetChangeListener_
&&
107 keysetChangeListener_
.target
== arguments
[0]) {
108 var callback
= keysetChangeListener_
.callback
;
109 keysetChangeListener_
= undefined;
110 // TODO (rsadam): Get rid of this hack. Currently this is needed to
111 // ensure the keyset was fully loaded before carrying on with the test.
112 setTimeout(callback
, 0);
120 * Arms a one time callback to invoke when the VK switches to the target keyset.
121 * Only one keyset change callback may be armed at any time. Used to synchronize
122 * tests and to track initial load time for the virtual keyboard.
123 * @param {string} keyset The target keyset.
124 * @param {function} callback The callback to invoke when the keyset becomes
127 function onSwitchToKeyset(keyset
, callback
) {
128 if (keysetChangeListener_
) {
129 console
.error('A keyset change listener is already armed.');
132 keysetChangeListener_
= {
139 * Spatial data is used in conjunction with a language model to offer
140 * corrections for 'fat finger' typing and is not needed for the system VK.
142 function overrideGetSpatialData() {
143 var Controller
= i18n
.input
.chrome
.inputview
.Controller
;
144 Controller
.prototype.getSpatialData_ = function() {};
147 // Plug in for API calls.
148 function registerInputviewApi() {
150 // Flag values for ctrl, alt and shift as defined by EventFlags
151 // in "event_constants.h".
160 // Mapping from keyName to keyCode (see ui::KeyEvent).
161 var nonAlphaNumericKeycodes
= {
177 * Displays a console message containing the last runtime error.
180 function logIfError_() {
181 if (chrome
.runtime
.lastError
) {
182 console
.log(chrome
.runtime
.lastError
);
186 function commitText_(text
) {
187 chrome
.virtualKeyboardPrivate
.insertText(text
, logIfError_
);
191 * Retrieve the preferred keyboard configuration.
192 * @param {function} callback The callback function for processing the
193 * keyboard configuration.
196 function getKeyboardConfig_(callback
) {
197 chrome
.virtualKeyboardPrivate
.getKeyboardConfig(callback
);
201 * Retrieve a list of all enabled input methods.
202 * @param {function} callback The callback function for processing the list
203 * of enabled input methods.
206 function getInputMethods_(callback
) {
207 if (chrome
.inputMethodPrivate
)
208 chrome
.inputMethodPrivate
.getInputMethods(callback
);
214 * Retrieve the name of the active input method.
215 * @param {function} callback The callback function for processing the
216 * name of the active input mehtod.
219 function getCurrentInputMethod_(callback
) {
220 if (chrome
.inputMethodPrivate
)
221 chrome
.inputMethodPrivate
.getCurrentInputMethod(callback
);
227 * Retrieve the current input method configuration.
228 * @param {function} callback The callback function for processing the
229 * name of the active input mehtod.
232 function getInputMethodConfig_(callback
) {
233 if (chrome
.inputMethodPrivate
)
234 chrome
.inputMethodPrivate
.getInputMethodConfig(callback
);
240 * Changes the active input method.
241 * @param {string} inputMethodId The id of the input method to activate.
244 function switchToInputMethod_(inputMethodId
) {
245 if (chrome
.inputMethodPrivate
)
246 chrome
.inputMethodPrivate
.setCurrentInputMethod(inputMethodId
)
250 * Opens the language settings for specifying and configuring input methods.
253 function openSettings_() {
254 chrome
.virtualKeyboardPrivate
.openSettings();
258 * Dispatches a virtual key event. The system VK does not use the IME
259 * API as its primary role is to work in conjunction with a non-VK aware
260 * IME. Some reformatting of the key data is required to work with the
261 * virtualKeyboardPrivate API.
262 * @param {!Object} keyData Description of the key event.
264 function sendKeyEvent_(keyData
) {
265 keyData
.forEach(function(data
) {
266 var charValue
= data
.key
.length
== 1 ? data
.key
.charCodeAt(0) : 0;
267 var keyCode
= data
.keyCode
? data
.keyCode
:
268 getKeyCode_(data
.key
, data
.code
);
271 charValue
: charValue
,
274 modifiers
: Modifier
.NONE
277 event
.modifiers
|= Modifier
.ALT
;
279 event
.modifiers
|= Modifier
.CONTROL
;
280 if (data
.shiftKey
|| data
.capsLock
)
281 event
.modifiers
|= Modifier
.SHIFT
;
283 chrome
.virtualKeyboardPrivate
.sendKeyEvent(event
, logIfError_
);
288 * Computes keyCodes for use with ui::KeyEvent.
289 * @param {string} keyChar Character being typed.
290 * @param {string} keyName w3c name of the character.
292 function getKeyCode_(keyChar
, keyName
) {
293 var keyCode
= nonAlphaNumericKeycodes
[keyName
];
297 var match
= /Key([A-Z])/.exec(keyName
);
299 return match
[1].charCodeAt(0);
301 match
= /Digit([0-9])/.exec(keyName
);
303 return match
[1].charCodeAt(0);
305 if (keyChar
.length
== 1) {
306 if (keyChar
>= 'a' && keyChar
<= 'z')
307 return keyChar
.charCodeAt(0) - 32;
308 if (keyChar
>= 'A' && keyChar
<= 'Z')
309 return keyChar
.charCodeAt(0);
310 if (keyChar
>= '0' && keyChar
<= '9')
311 return keyChar
.charCodeAt(0);
317 commitText
: commitText_
,
318 getKeyboardConfig
: getKeyboardConfig_
,
319 getInputMethods
: getInputMethods_
,
320 getCurrentInputMethod
: getCurrentInputMethod_
,
321 getInputMethodConfig
: getInputMethodConfig_
,
322 switchToInputMethod
: switchToInputMethod_
,
323 openSettings
: openSettings_
326 registerFunction('chrome.input.ime.hideInputView', function() {
327 chrome
.virtualKeyboardPrivate
.hideKeyboard();
328 chrome
.virtualKeyboardPrivate
.lockKeyboard(false);
331 var defaultSendMessage
= registerFunction('chrome.runtime.sendMessage');
332 registerFunction('chrome.runtime.sendMessage', function(message
) {
333 if (message
.type
== 'send_key_event')
334 sendKeyEvent_(message
.keyData
);
335 else if (message
.type
== 'commit_text')
336 commitText_(message
.text
);
338 defaultSendMessage(message
);
344 registerFunction('chrome.runtime.getBackgroundPage', function() {
345 var callback
= arguments
[0];
348 registerFunction('chrome.runtime.sendMessage');
349 registerFunction('chrome.runtime.onMessage.addListener');
353 chrome
.i18n
.getMessage = function(name
) {
360 * Trigger loading the virtual keyboard on completion of page load.
362 window
.onload = function() {
364 var matches
= window
.location
.href
.match(/[#?].*$/);
365 if (matches
&& matches
.length
> 0) {
366 matches
[0].slice(1).split('&').forEach(function(s
) {
367 var pair
= s
.split('=');
368 params
[pair
[0]] = pair
[1];
372 var keyset
= params
['id'] || 'us.compact.qwerty';
373 var languageCode
= params
['language'] || 'en';
374 var passwordLayout
= params
['passwordLayout'] || 'us';
375 var name
= params
['name'] || 'English';
377 overrideGetMessage();
378 overrideSwitchToKeyset();
379 overrideGetSpatialData();
380 registerInputviewApi();
381 i18n
.input
.chrome
.inputview
.Controller
.DEV
= true;
382 i18n
.input
.chrome
.inputview
.Adapter
.prototype.isSwitching = function() {
386 if (keyset
!= 'none') {
387 window
.initializeVirtualKeyboard(keyset
, languageCode
, passwordLayout
,
395 window
.onbeforeunload = function() {
397 goog
.dispose(controller
);
401 * Loads a virtual keyboard. If a keyboard was previously loaded, it is
402 * reinitialized with the new configuration.
403 * @param {string} keyset The keyboard keyset.
404 * @param {string} languageCode The language code for this keyboard.
405 * @param {string} passwordLayout The layout for password box.
406 * @param {string} name The input tool name.
407 * @param {Object=} opt_config Optional configuration settings.
409 window
.initializeVirtualKeyboard = function(keyset
, languageCode
,
410 passwordLayout
, name
, opt_config
) {
411 var Controller
= i18n
.input
.chrome
.inputview
.Controller
;
412 Controller
.DISABLE_HWT
= !(opt_config
&& opt_config
.enableHwtForTesting
);
413 onSwitchToKeyset(keyset
, function() {
414 chrome
.virtualKeyboardPrivate
.keyboardLoaded();
417 controller
.initialize(keyset
, languageCode
, passwordLayout
, name
);
419 controller
= new Controller(keyset
, languageCode
, passwordLayout
, name
);