1 // Copyright 2013 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 #include "chromeos/ime/component_extension_ime_manager.h"
6
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "chromeos/ime/extension_ime_util.h"
10
11 namespace chromeos {
12
13 namespace {
14
15 // The whitelist for enabling extension based xkb keyboards at login session.
16 const char* kLoginLayoutWhitelist[] = {
17 "be",
18 "br",
19 "ca",
20 "ca(eng)",
21 "ca(multix)",
22 "ch",
23 "ch(fr)",
24 "cz",
25 "cz(qwerty)",
26 "de",
27 "de(neo)",
28 "dk",
29 "ee",
30 "es",
31 "es(cat)",
32 "fi",
33 "fr",
34 "gb(dvorak)",
35 "gb(extd)",
36 "hr",
37 "hu",
38 "is",
39 "it",
40 "jp",
41 "latam",
42 "lt",
43 "lv(apostrophe)",
44 "no",
45 "pl",
46 "pt",
47 "ro",
48 "se",
49 "si",
50 "tr",
51 "us",
52 "us(altgr-intl)",
53 "us(colemak)",
54 "us(dvorak)",
55 "us(intl)"
56 };
57
58 } // namespace
59
ComponentExtensionEngine()60 ComponentExtensionEngine::ComponentExtensionEngine() {
61 }
62
~ComponentExtensionEngine()63 ComponentExtensionEngine::~ComponentExtensionEngine() {
64 }
65
ComponentExtensionIME()66 ComponentExtensionIME::ComponentExtensionIME() {
67 }
68
~ComponentExtensionIME()69 ComponentExtensionIME::~ComponentExtensionIME() {
70 }
71
ComponentExtensionIMEManagerDelegate()72 ComponentExtensionIMEManagerDelegate::ComponentExtensionIMEManagerDelegate() {
73 }
74
~ComponentExtensionIMEManagerDelegate()75 ComponentExtensionIMEManagerDelegate::~ComponentExtensionIMEManagerDelegate() {
76 }
77
ComponentExtensionIMEManager()78 ComponentExtensionIMEManager::ComponentExtensionIMEManager()
79 : is_initialized_(false), was_initialization_notified_(false) {
80 for (size_t i = 0; i < arraysize(kLoginLayoutWhitelist); ++i) {
81 login_layout_set_.insert(kLoginLayoutWhitelist[i]);
82 }
83 }
84
~ComponentExtensionIMEManager()85 ComponentExtensionIMEManager::~ComponentExtensionIMEManager() {
86 }
87
Initialize(scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate)88 void ComponentExtensionIMEManager::Initialize(
89 scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
90 delegate_ = delegate.Pass();
91 component_extension_imes_ = delegate_->ListIME();
92 is_initialized_ = true;
93 }
94
NotifyInitialized()95 void ComponentExtensionIMEManager::NotifyInitialized() {
96 if (is_initialized_ && !was_initialization_notified_) {
97 FOR_EACH_OBSERVER(
98 Observer, observers_, OnImeComponentExtensionInitialized());
99 was_initialization_notified_ = true;
100 }
101 }
102
IsInitialized()103 bool ComponentExtensionIMEManager::IsInitialized() {
104 return is_initialized_;
105 }
106
LoadComponentExtensionIME(const std::string & input_method_id)107 bool ComponentExtensionIMEManager::LoadComponentExtensionIME(
108 const std::string& input_method_id) {
109 ComponentExtensionIME ime;
110 if (FindEngineEntry(input_method_id, &ime, NULL))
111 return delegate_->Load(ime.id, ime.manifest, ime.path);
112 else
113 return false;
114 }
115
UnloadComponentExtensionIME(const std::string & input_method_id)116 bool ComponentExtensionIMEManager::UnloadComponentExtensionIME(
117 const std::string& input_method_id) {
118 ComponentExtensionIME ime;
119 if (!FindEngineEntry(input_method_id, &ime, NULL))
120 return false;
121 delegate_->Unload(ime.id, ime.path);
122 return true;
123 }
124
IsWhitelisted(const std::string & input_method_id)125 bool ComponentExtensionIMEManager::IsWhitelisted(
126 const std::string& input_method_id) {
127 return extension_ime_util::IsComponentExtensionIME(input_method_id) &&
128 FindEngineEntry(input_method_id, NULL, NULL);
129 }
130
IsWhitelistedExtension(const std::string & extension_id)131 bool ComponentExtensionIMEManager::IsWhitelistedExtension(
132 const std::string& extension_id) {
133 for (size_t i = 0; i < component_extension_imes_.size(); ++i) {
134 if (component_extension_imes_[i].id == extension_id)
135 return true;
136 }
137 return false;
138 }
139
GetId(const std::string & extension_id,const std::string & engine_id)140 std::string ComponentExtensionIMEManager::GetId(
141 const std::string& extension_id,
142 const std::string& engine_id) {
143 ComponentExtensionEngine engine;
144 const std::string& input_method_id =
145 extension_ime_util::GetComponentInputMethodID(extension_id, engine_id);
146 if (!FindEngineEntry(input_method_id, NULL, &engine))
147 return "";
148 return input_method_id;
149 }
150
GetName(const std::string & input_method_id)151 std::string ComponentExtensionIMEManager::GetName(
152 const std::string& input_method_id) {
153 ComponentExtensionEngine engine;
154 if (!FindEngineEntry(input_method_id, NULL, &engine))
155 return "";
156 return engine.display_name;
157 }
158
GetDescription(const std::string & input_method_id)159 std::string ComponentExtensionIMEManager::GetDescription(
160 const std::string& input_method_id) {
161 ComponentExtensionEngine engine;
162 if (!FindEngineEntry(input_method_id, NULL, &engine))
163 return "";
164 return engine.description;
165 }
166
ListIMEByLanguage(const std::string & language)167 std::vector<std::string> ComponentExtensionIMEManager::ListIMEByLanguage(
168 const std::string& language) {
169 std::vector<std::string> result;
170 for (size_t i = 0; i < component_extension_imes_.size(); ++i) {
171 for (size_t j = 0; j < component_extension_imes_[i].engines.size(); ++j) {
172 const ComponentExtensionIME& ime = component_extension_imes_[i];
173 if (std::find(ime.engines[j].language_codes.begin(),
174 ime.engines[j].language_codes.end(),
175 language) != ime.engines[j].language_codes.end()) {
176 result.push_back(extension_ime_util::GetComponentInputMethodID(
177 ime.id,
178 ime.engines[j].engine_id));
179 }
180 }
181 }
182 return result;
183 }
184
185 input_method::InputMethodDescriptors
GetAllIMEAsInputMethodDescriptor()186 ComponentExtensionIMEManager::GetAllIMEAsInputMethodDescriptor() {
187 input_method::InputMethodDescriptors result;
188 for (size_t i = 0; i < component_extension_imes_.size(); ++i) {
189 for (size_t j = 0; j < component_extension_imes_[i].engines.size(); ++j) {
190 const std::string input_method_id =
191 extension_ime_util::GetComponentInputMethodID(
192 component_extension_imes_[i].id,
193 component_extension_imes_[i].engines[j].engine_id);
194 const std::vector<std::string>& layouts =
195 component_extension_imes_[i].engines[j].layouts;
196 result.push_back(
197 input_method::InputMethodDescriptor(
198 input_method_id,
199 component_extension_imes_[i].engines[j].display_name,
200 std::string(), // TODO(uekawa): Set short name.
201 layouts,
202 component_extension_imes_[i].engines[j].language_codes,
203 // Enables extension based xkb keyboards on login screen.
204 extension_ime_util::IsKeyboardLayoutExtension(
205 input_method_id) && IsInLoginLayoutWhitelist(layouts),
206 component_extension_imes_[i].engines[j].options_page_url,
207 component_extension_imes_[i].engines[j].input_view_url));
208 }
209 }
210 return result;
211 }
212
213 input_method::InputMethodDescriptors
GetXkbIMEAsInputMethodDescriptor()214 ComponentExtensionIMEManager::GetXkbIMEAsInputMethodDescriptor() {
215 input_method::InputMethodDescriptors result;
216 const input_method::InputMethodDescriptors& descriptors =
217 GetAllIMEAsInputMethodDescriptor();
218 for (size_t i = 0; i < descriptors.size(); ++i) {
219 if (extension_ime_util::IsKeyboardLayoutExtension(descriptors[i].id()))
220 result.push_back(descriptors[i]);
221 }
222 return result;
223 }
224
AddObserver(Observer * observer)225 void ComponentExtensionIMEManager::AddObserver(Observer* observer) {
226 observers_.AddObserver(observer);
227 }
228
RemoveObserver(Observer * observer)229 void ComponentExtensionIMEManager::RemoveObserver(Observer* observer) {
230 observers_.RemoveObserver(observer);
231 }
232
FindEngineEntry(const std::string & input_method_id,ComponentExtensionIME * out_extension,ComponentExtensionEngine * out_engine)233 bool ComponentExtensionIMEManager::FindEngineEntry(
234 const std::string& input_method_id,
235 ComponentExtensionIME* out_extension,
236 ComponentExtensionEngine* out_engine) {
237 if (!extension_ime_util::IsComponentExtensionIME(input_method_id))
238 return false;
239 for (size_t i = 0; i < component_extension_imes_.size(); ++i) {
240 const std::string extension_id = component_extension_imes_[i].id;
241 const std::vector<ComponentExtensionEngine>& engines =
242 component_extension_imes_[i].engines;
243
244 for (size_t j = 0; j < engines.size(); ++j) {
245 const std::string trial_ime_id =
246 extension_ime_util::GetComponentInputMethodID(
247 extension_id, engines[j].engine_id);
248 if (trial_ime_id != input_method_id)
249 continue;
250
251 if (out_extension)
252 *out_extension = component_extension_imes_[i];
253 if (out_engine)
254 *out_engine = component_extension_imes_[i].engines[j];
255 return true;
256 }
257 }
258 return false;
259 }
260
IsInLoginLayoutWhitelist(const std::vector<std::string> & layouts)261 bool ComponentExtensionIMEManager::IsInLoginLayoutWhitelist(
262 const std::vector<std::string>& layouts) {
263 for (size_t i = 0; i < layouts.size(); ++i) {
264 if (login_layout_set_.find(layouts[i]) != login_layout_set_.end())
265 return true;
266 }
267 return false;
268 }
269
270 } // namespace chromeos
271