Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / remoting / webapp / app_remoting / js / keyboard_layouts_menu.js
blob165063447f6f470583a54ccb07bc2d802ed92887
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 /**
6  * @fileoverview
7  * Class managing the host's available keyboard layouts, allowing the user to
8  * select one that matches the local layout, or auto-selecting based on the
9  * current locale.
10  */
12 'use strict';
14 /** @suppress {duplicate} */
15 var remoting = remoting || {};
17 /**
18  * @param {remoting.ContextMenuAdapter} adapter
19  * @constructor
20  */
21 remoting.KeyboardLayoutsMenu = function(adapter) {
22   /** @private {remoting.ContextMenuAdapter} */
23   this.adapter_ = adapter;
24   /** @private {remoting.SubmenuManager} */
25   this.submenuManager_ = new remoting.SubmenuManager(
26       adapter,
27       chrome.i18n.getMessage(/*i18n-content*/'KEYBOARD_LAYOUTS_SUBMENU_TITLE'),
28       true);
29   /** @private {string} */
30   this.currentLayout_ = '';
32   /** @private {function(string, string)} */
33   this.sendExtensionMessage_ = base.doNothing;
35   adapter.addListener(this.onContextMenu_.bind(this));
38 /**
39  * @param {Array<string>} layouts The keyboard layouts available on the host,
40  *   for example en-US, de-DE
41  * @param {string} currentLayout The layout currently active on the host.
42  */
43 remoting.KeyboardLayoutsMenu.prototype.setLayouts =
44     function(layouts, currentLayout) {
45   this.submenuManager_.removeAll();
46   this.currentLayout_ = '';
47   for (var i = 0; i < layouts.length; ++i) {
48     this.submenuManager_.add(this.makeMenuId_(layouts[i]), layouts[i]);
49   }
50   // Pick a suitable default layout.
51   this.getBestLayout_(layouts, currentLayout,
52                       this.setLayout_.bind(this, false));
55 /** @param {function(string, string)} callback */
56 remoting.KeyboardLayoutsMenu.prototype.setExtensionMessageSender =
57     function(callback) {
58   this.sendExtensionMessage_ = callback;
61 /**
62  * Notify the host that a new keyboard layout has been selected.
63  *
64  * @param {boolean} saveToLocalStorage If true, save the specified layout to
65  *     local storage.
66  * @param {string} layout The new keyboard layout.
67  * @private
68  */
69 remoting.KeyboardLayoutsMenu.prototype.setLayout_ =
70     function(saveToLocalStorage, layout) {
71   if (this.currentLayout_ != '') {
72     this.adapter_.updateCheckState(
73         this.makeMenuId_(this.currentLayout_), false);
74   }
75   this.adapter_.updateCheckState(this.makeMenuId_(layout), true);
76   this.currentLayout_ = layout;
78   console.log("Setting the keyboard layout to '" + layout + "'");
79   this.sendExtensionMessage_('setKeyboardLayout',
80                              JSON.stringify({layout: layout}));
81   if (saveToLocalStorage) {
82     var params = {};
83     params[remoting.KeyboardLayoutsMenu.KEY_] = layout;
84     chrome.storage.local.set(params);
85   }
88 /**
89  * Choose the best keyboard from the alternatives, based on the following
90  * algorithm:
91  *   - Search local storage by for a preferred keyboard layout for the app;
92  *     if it is found, prefer it over the current locale, falling back on the
93  *     latter only if no match is found.
94  *   - If the candidate layout matches one of the supported layouts, use it.
95  *   - Otherwise, if the language portion of the candidate matches that of
96  *     any of the supported layouts, use the first such layout (e.g, en-AU
97  *     will match either en-US or en-GB, whichever appears first).
98  *   - Otherwise, use the host's current layout.
99  *
100  * @param {Array<string>} layouts
101  * @param {string} currentHostLayout
102  * @param {function(string):void} onDone
103  * @private
104  */
105 remoting.KeyboardLayoutsMenu.prototype.getBestLayout_ =
106     function(layouts, currentHostLayout, onDone) {
107   /**
108    * Extract the language id from a string that is either "language" (e.g.
109    * "de") or "language-region" (e.g. "en-US").
110    *
111    * @param {string} layout
112    * @return {string}
113    */
114   var getLanguage = function(layout) {
115     var languageAndRegion = layout.split('-');
116     switch (languageAndRegion.length) {
117       case 1:
118       case 2:
119         return languageAndRegion[0];
120       default:
121         return '';
122     }
123   };
125   /** @param {Object<string>} storage */
126   var chooseLayout = function(storage) {
127     var configuredLayout = storage[remoting.KeyboardLayoutsMenu.KEY_];
128     var tryLayouts = [ chrome.i18n.getUILanguage() ];
129     if (configuredLayout && typeof(configuredLayout) == 'string') {
130       tryLayouts.unshift(configuredLayout);
131     }
132     for (var i = 0; i < tryLayouts.length; ++i) {
133       if (layouts.indexOf(tryLayouts[i]) != -1) {
134         onDone(tryLayouts[i]);
135         return;
136       }
137       var language = getLanguage(tryLayouts[i]);
138       if (language) {
139         for (var j = 0; j < layouts.length; ++j) {
140           if (language == getLanguage(layouts[j])) {
141             onDone(layouts[j]);
142             return;
143           }
144         }
145       }
146     }
147     // Neither the stored layout nor UI locale was suitable.
148     onDone(currentHostLayout);
149   };
151   chrome.storage.local.get(remoting.KeyboardLayoutsMenu.KEY_, chooseLayout);
155  * Create a menu id from the given keyboard layout.
157  * @param {string} layout Keyboard layout
158  * @return {string}
159  * @private
160  */
161 remoting.KeyboardLayoutsMenu.prototype.makeMenuId_ = function(layout) {
162   return 'layout@' + layout;
166  * Handle a click on the application's context menu.
168  * @param {OnClickData=} info
169  * @private
170  */
171 remoting.KeyboardLayoutsMenu.prototype.onContextMenu_ = function(info) {
172   var menuItemId = info.menuItemId.toString();
173   var components = menuItemId.split('@');
174   if (components.length == 2 &&
175       this.makeMenuId_(components[1]) === menuItemId) {
176     this.setLayout_(true, components[1]);
177   }
181  * @type {string}
182  * @private
183  */
184 remoting.KeyboardLayoutsMenu.KEY_ = 'preferred-keyboard-layout';