1// Copyright (c) 2012 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.
4
5#ifndef CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_UTIL_H_
6#define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_UTIL_H_
7
8#include <cstddef>
9#include <map>
10#include <string>
11#include <vector>
12
13#include "base/containers/hash_tables.h"
14#include "base/memory/scoped_ptr.h"
15#include "base/strings/string16.h"
16#include "base/threading/thread_checker.h"
17#include "chromeos/ime/input_method_descriptor.h"
18
19namespace chromeos {
20namespace input_method {
21
22class InputMethodDelegate;
23
24enum InputMethodType {
25  kKeyboardLayoutsOnly,
26  kAllInputMethods,
27};
28
29// A class which provides miscellaneous input method utility functions.
30class InputMethodUtil {
31 public:
32  explicit InputMethodUtil(InputMethodDelegate* delegate);
33  ~InputMethodUtil();
34
35  // Converts a string sent from IBus IME engines, which is written in English,
36  // into Chrome's string ID, then pulls internationalized resource string from
37  // the resource bundle and returns it. These functions are not thread-safe.
38  // Non-UI threads are not allowed to call them.
39  // The english_string to should be a xkb id with "xkb:...:...:..." format.
40  // TODO(shuchen): this method should be removed when finish the wrapping of
41  // xkb to extension.
42  base::string16 TranslateString(const std::string& english_string) const;
43
44  // Converts an input method ID to a language code of the IME. Returns "Eng"
45  // when |input_method_id| is unknown.
46  // Example: "hangul" => "ko"
47  std::string GetLanguageCodeFromInputMethodId(
48      const std::string& input_method_id) const;
49
50  // Converts an input method ID to a display name of the IME. Returns
51  // an empty strng when |input_method_id| is unknown.
52  // Examples: "pinyin" => "Pinyin"
53  std::string GetInputMethodDisplayNameFromId(
54      const std::string& input_method_id) const;
55
56  base::string16 GetInputMethodShortName(
57      const InputMethodDescriptor& input_method) const;
58  base::string16 GetInputMethodMediumName(
59      const InputMethodDescriptor& input_method) const;
60  base::string16 GetInputMethodLongName(
61      const InputMethodDescriptor& input_method) const;
62
63  // Converts an input method ID to an input method descriptor. Returns NULL
64  // when |input_method_id| is unknown.
65  // Example: "pinyin" => { id: "pinyin", display_name: "Pinyin",
66  //                        keyboard_layout: "us", language_code: "zh" }
67  const InputMethodDescriptor* GetInputMethodDescriptorFromId(
68      const std::string& input_method_id) const;
69
70  // Gets input method IDs that belong to |language_code|.
71  // If |type| is |kKeyboardLayoutsOnly|, the function does not return input
72  // methods that are not for keybord layout switching. Returns true on success.
73  // Note that the function might return false or |language_code| is unknown.
74  //
75  // The retured input method IDs are sorted by populalirty per
76  // chromeos/platform/assets/input_methods/whitelist.txt.
77  bool GetInputMethodIdsFromLanguageCode(
78      const std::string& language_code,
79      InputMethodType type,
80      std::vector<std::string>* out_input_method_ids) const;
81
82  // Gets the input method IDs suitable for the first user login, based on
83  // the given language code (UI language), and the descriptor of the
84  // current input method.
85  void GetFirstLoginInputMethodIds(
86      const std::string& language_code,
87      const InputMethodDescriptor& current_input_method,
88      std::vector<std::string>* out_input_method_ids) const;
89
90  // Gets the language codes associated with the given input method IDs.
91  // The returned language codes won't have duplicates.
92  void GetLanguageCodesFromInputMethodIds(
93      const std::vector<std::string>& input_method_ids,
94      std::vector<std::string>* out_language_codes) const;
95
96  // Gets first input method associated with the language.
97  // Returns empty string on error.
98  std::string GetLanguageDefaultInputMethodId(const std::string& language_code);
99
100  // Migrates the legacy xkb id to extension based xkb id.
101  // Returns true if the given input method id list is modified,
102  // returns false otherwise.
103  // This method should not be removed because it's required to transfer XKB
104  // input method ID from VPD into extension-based XKB input method ID.
105  bool MigrateInputMethods(std::vector<std::string>* input_method_ids);
106
107  // Updates the internal cache of hardware layouts.
108  void UpdateHardwareLayoutCache();
109
110  // Set hardware keyboard layout for testing purpose. This is for simulating
111  // "keyboard_layout" entry in VPD values.
112  void SetHardwareKeyboardLayoutForTesting(const std::string& layout);
113
114  // Fills the input method IDs of the hardware keyboard. e.g. "xkb:us::eng"
115  // for US Qwerty keyboard or "xkb:ru::rus" for Russian keyboard.
116  const std::vector<std::string>& GetHardwareInputMethodIds();
117
118  // Returns the login-allowed input method ID of the hardware keyboard, e.g.
119  // "xkb:us::eng" but not include non-login keyboard like "xkb:ru::rus". Please
120  // note that this is not a subset of returned value of
121  // GetHardwareInputMethodIds. If GetHardwareInputMethodIds returns only
122  // non-login keyboard, this function will returns "xkb:us::eng" as the
123  // fallback keyboard.
124  const std::vector<std::string>& GetHardwareLoginInputMethodIds();
125
126  // Returns true if given input method can be used to input login data.
127  bool IsLoginKeyboard(const std::string& input_method_id) const;
128
129  // Returns true if the given input method id is supported.
130  bool IsValidInputMethodId(const std::string& input_method_id) const;
131
132  // Returns true if the given input method id is for a keyboard layout.
133  static bool IsKeyboardLayout(const std::string& input_method_id);
134
135  // Resets the list of component extension IMEs.
136  void ResetInputMethods(const InputMethodDescriptors& imes);
137
138  // Appends the additional list of component extension IMEs.
139  void AppendInputMethods(const InputMethodDescriptors& imes);
140
141  // Initializes the extension based xkb IMEs for testing.
142  void InitXkbInputMethodsForTesting();
143
144  // Map from input method ID to associated input method descriptor.
145  typedef std::map<
146    std::string, InputMethodDescriptor> InputMethodIdToDescriptorMap;
147
148  // Gets the id to desctiptor map for testing.
149  const InputMethodIdToDescriptorMap& GetIdToDesciptorMapForTesting();
150
151  // Returns the fallback input method descriptor (the very basic US
152  // keyboard). This function is mostly used for testing, but may be used
153  // as the fallback, when there is no other choice.
154  static InputMethodDescriptor GetFallbackInputMethodDescriptor();
155
156 protected:
157  // protected: for unit testing as well.
158  bool GetInputMethodIdsFromLanguageCodeInternal(
159      const std::multimap<std::string, std::string>& language_code_to_ids,
160      const std::string& normalized_language_code,
161      InputMethodType type,
162      std::vector<std::string>* out_input_method_ids) const;
163
164  // Gets the keyboard layout name from the given input method ID.
165  // If the ID is invalid, an empty string will be returned.
166  // This function only supports xkb layouts.
167  //
168  // Examples:
169  //
170  // "xkb:us::eng"       => "us"
171  // "xkb:us:dvorak:eng" => "us(dvorak)"
172  // "xkb:gb::eng"       => "gb"
173  // "pinyin"            => "us" (because Pinyin uses US keyboard layout)
174  std::string GetKeyboardLayoutName(const std::string& input_method_id) const;
175
176 private:
177  bool TranslateStringInternal(const std::string& english_string,
178                               base::string16 *out_string) const;
179
180  // Map from language code to associated input method IDs, etc.
181  typedef std::multimap<std::string, std::string> LanguageCodeToIdsMap;
182
183  LanguageCodeToIdsMap language_code_to_ids_;
184  InputMethodIdToDescriptorMap id_to_descriptor_;
185  std::map<std::string, std::string> xkb_layout_to_indicator_;
186
187  typedef base::hash_map<std::string, int> HashType;
188  HashType english_to_resource_id_;
189
190  InputMethodDelegate* delegate_;
191
192  base::ThreadChecker thread_checker_;
193  std::vector<std::string> hardware_layouts_;
194  std::vector<std::string> hardware_login_layouts_;
195  std::vector<std::string> cached_hardware_layouts_;
196
197  DISALLOW_COPY_AND_ASSIGN(InputMethodUtil);
198};
199
200}  // namespace input_method
201}  // namespace chromeos
202
203#endif  // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_UTIL_H_
204