Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromeos / ime / component_extension_ime_manager.cc
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/command_line.h"
8 #include "base/logging.h"
9 #include "base/strings/string_util.h"
10 #include "chromeos/chromeos_switches.h"
11 #include "chromeos/ime/extension_ime_util.h"
12
13 namespace chromeos {
14
15 namespace {
16
17 // The whitelist for enabling extension based xkb keyboards at login session.
18 const char* kLoginLayoutWhitelist[] = {
19   "be",
20   "br",
21   "ca",
22   "ca(eng)",
23   "ca(multix)",
24   "ch",
25   "ch(fr)",
26   "cz",
27   "cz(qwerty)",
28   "de",
29   "de(neo)",
30   "dk",
31   "ee",
32   "es",
33   "es(cat)",
34   "fi",
35   "fr",
36   "gb(dvorak)",
37   "gb(extd)",
38   "hr",
39   "hu",
40   "ie",
41   "is",
42   "it",
43   "jp",
44   "latam",
45   "lt",
46   "lv(apostrophe)",
47   "mt",
48   "no",
49   "pl",
50   "pt",
51   "ro",
52   "se",
53   "si",
54   "tr",
55   "us",
56   "us(altgr-intl)",
57   "us(colemak)",
58   "us(dvorak)",
59   "us(intl)"
60 };
61
62 // Gets the input method category according to the given input method id.
63 // This is used for sorting a list of input methods.
64 int GetInputMethodCategory(const std::string& id) {
65   const std::string engine_id =
66       chromeos::extension_ime_util::GetComponentIDByInputMethodID(id);
67   if (StartsWithASCII(engine_id, "xkb:", true))
68     return 0;
69   if (StartsWithASCII(engine_id, "vkd_", true))
70     return 1;
71   if (engine_id.find("-t-i0-") != std::string::npos &&
72       !StartsWithASCII(engine_id, "zh-", true)) {
73     return 2;
74   }
75   return 3;
76 }
77
78 bool InputMethodCompare(const input_method::InputMethodDescriptor& im1,
79                         const input_method::InputMethodDescriptor& im2) {
80   return GetInputMethodCategory(im1.id()) < GetInputMethodCategory(im2.id());
81 }
82
83 } // namespace
84
85 ComponentExtensionEngine::ComponentExtensionEngine() {
86 }
87
88 ComponentExtensionEngine::~ComponentExtensionEngine() {
89 }
90
91 ComponentExtensionIME::ComponentExtensionIME() {
92 }
93
94 ComponentExtensionIME::~ComponentExtensionIME() {
95 }
96
97 ComponentExtensionIMEManagerDelegate::ComponentExtensionIMEManagerDelegate() {
98 }
99
100 ComponentExtensionIMEManagerDelegate::~ComponentExtensionIMEManagerDelegate() {
101 }
102
103 ComponentExtensionIMEManager::ComponentExtensionIMEManager() {
104   for (size_t i = 0; i < arraysize(kLoginLayoutWhitelist); ++i) {
105     login_layout_set_.insert(kLoginLayoutWhitelist[i]);
106   }
107 }
108
109 ComponentExtensionIMEManager::~ComponentExtensionIMEManager() {
110 }
111
112 void ComponentExtensionIMEManager::Initialize(
113     scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
114   delegate_ = delegate.Pass();
115   std::vector<ComponentExtensionIME> ext_list = delegate_->ListIME();
116   for (size_t i = 0; i < ext_list.size(); ++i) {
117     ComponentExtensionIME& ext = ext_list[i];
118     bool extension_exists = IsWhitelistedExtension(ext.id);
119     if (!extension_exists)
120       component_extension_imes_[ext.id] = ext;
121     for (size_t j = 0; j < ext.engines.size(); ++j) {
122       ComponentExtensionEngine& ime = ext.engines[j];
123       const std::string input_method_id =
124           extension_ime_util::GetComponentInputMethodID(ext.id, ime.engine_id);
125       if (extension_exists && !IsWhitelisted(input_method_id))
126         component_extension_imes_[ext.id].engines.push_back(ime);
127       input_method_id_set_.insert(input_method_id);
128     }
129   }
130 }
131
132 bool ComponentExtensionIMEManager::LoadComponentExtensionIME(
133     Profile* profile,
134     const std::string& input_method_id) {
135   ComponentExtensionIME ime;
136   if (FindEngineEntry(input_method_id, &ime)) {
137     delegate_->Load(profile, ime.id, ime.manifest, ime.path);
138     return true;
139   }
140   return false;
141 }
142
143 bool ComponentExtensionIMEManager::UnloadComponentExtensionIME(
144     Profile* profile,
145     const std::string& input_method_id) {
146   ComponentExtensionIME ime;
147   if (!FindEngineEntry(input_method_id, &ime))
148     return false;
149   delegate_->Unload(profile, ime.id, ime.path);
150   return true;
151 }
152
153 bool ComponentExtensionIMEManager::IsWhitelisted(
154     const std::string& input_method_id) {
155   return input_method_id_set_.find(input_method_id) !=
156          input_method_id_set_.end();
157 }
158
159 bool ComponentExtensionIMEManager::IsWhitelistedExtension(
160     const std::string& extension_id) {
161   return component_extension_imes_.find(extension_id) !=
162          component_extension_imes_.end();
163 }
164
165 input_method::InputMethodDescriptors
166     ComponentExtensionIMEManager::GetAllIMEAsInputMethodDescriptor() {
167   bool enable_new_korean_ime = CommandLine::ForCurrentProcess()->HasSwitch(
168       switches::kEnableNewKoreanIme);
169   input_method::InputMethodDescriptors result;
170   for (std::map<std::string, ComponentExtensionIME>::const_iterator it =
171           component_extension_imes_.begin();
172        it != component_extension_imes_.end(); ++it) {
173     const ComponentExtensionIME& ext = it->second;
174     for (size_t j = 0; j < ext.engines.size(); ++j) {
175       const ComponentExtensionEngine& ime = ext.engines[j];
176       // Filter out new Korean IME if the experimental flag is OFF.
177       if (!enable_new_korean_ime && ime.engine_id == "ko-t-i0-und")
178         continue;
179       const std::string input_method_id =
180           extension_ime_util::GetComponentInputMethodID(
181               ext.id, ime.engine_id);
182       const std::vector<std::string>& layouts = ime.layouts;
183       result.push_back(
184           input_method::InputMethodDescriptor(
185               input_method_id,
186               ime.display_name,
187               ime.indicator,
188               layouts,
189               ime.language_codes,
190               // Enables extension based xkb keyboards on login screen.
191               extension_ime_util::IsKeyboardLayoutExtension(
192                   input_method_id) && IsInLoginLayoutWhitelist(layouts),
193               ime.options_page_url,
194               ime.input_view_url));
195     }
196   }
197   std::stable_sort(result.begin(), result.end(), InputMethodCompare);
198   return result;
199 }
200
201 input_method::InputMethodDescriptors
202 ComponentExtensionIMEManager::GetXkbIMEAsInputMethodDescriptor() {
203   input_method::InputMethodDescriptors result;
204   const input_method::InputMethodDescriptors& descriptors =
205       GetAllIMEAsInputMethodDescriptor();
206   for (size_t i = 0; i < descriptors.size(); ++i) {
207     if (extension_ime_util::IsKeyboardLayoutExtension(descriptors[i].id()))
208       result.push_back(descriptors[i]);
209   }
210   return result;
211 }
212
213 bool ComponentExtensionIMEManager::FindEngineEntry(
214     const std::string& input_method_id,
215     ComponentExtensionIME* out_extension) {
216   if (!IsWhitelisted(input_method_id))
217     return false;
218
219   std::string extension_id =
220       extension_ime_util::GetExtensionIDFromInputMethodID(input_method_id);
221   std::map<std::string, ComponentExtensionIME>::iterator it =
222       component_extension_imes_.find(extension_id);
223   if (it == component_extension_imes_.end())
224     return false;
225
226   if (out_extension)
227     *out_extension = it->second;
228   return true;
229 }
230
231 bool ComponentExtensionIMEManager::IsInLoginLayoutWhitelist(
232     const std::vector<std::string>& layouts) {
233   for (size_t i = 0; i < layouts.size(); ++i) {
234     if (login_layout_set_.find(layouts[i]) != login_layout_set_.end())
235       return true;
236   }
237   return false;
238 }
239
240 }  // namespace chromeos