• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Gets the input method category according to the given input method id.
59 // This is used for sorting a list of input methods.
GetInputMethodCategory(const std::string & id)60 int GetInputMethodCategory(const std::string& id) {
61   const std::string engine_id =
62       chromeos::extension_ime_util::GetComponentIDByInputMethodID(id);
63   if (StartsWithASCII(engine_id, "xkb:", true))
64     return 0;
65   if (StartsWithASCII(engine_id, "vkd_", true))
66     return 1;
67   if (engine_id.find("-t-i0-") != std::string::npos &&
68       !StartsWithASCII(engine_id, "zh-", true)) {
69     return 2;
70   }
71   return 3;
72 }
73 
InputMethodCompare(const input_method::InputMethodDescriptor & im1,const input_method::InputMethodDescriptor & im2)74 bool InputMethodCompare(const input_method::InputMethodDescriptor& im1,
75                         const input_method::InputMethodDescriptor& im2) {
76   return GetInputMethodCategory(im1.id()) < GetInputMethodCategory(im2.id());
77 }
78 
79 } // namespace
80 
ComponentExtensionEngine()81 ComponentExtensionEngine::ComponentExtensionEngine() {
82 }
83 
~ComponentExtensionEngine()84 ComponentExtensionEngine::~ComponentExtensionEngine() {
85 }
86 
ComponentExtensionIME()87 ComponentExtensionIME::ComponentExtensionIME() {
88 }
89 
~ComponentExtensionIME()90 ComponentExtensionIME::~ComponentExtensionIME() {
91 }
92 
ComponentExtensionIMEManagerDelegate()93 ComponentExtensionIMEManagerDelegate::ComponentExtensionIMEManagerDelegate() {
94 }
95 
~ComponentExtensionIMEManagerDelegate()96 ComponentExtensionIMEManagerDelegate::~ComponentExtensionIMEManagerDelegate() {
97 }
98 
ComponentExtensionIMEManager()99 ComponentExtensionIMEManager::ComponentExtensionIMEManager() {
100   for (size_t i = 0; i < arraysize(kLoginLayoutWhitelist); ++i) {
101     login_layout_set_.insert(kLoginLayoutWhitelist[i]);
102   }
103 }
104 
~ComponentExtensionIMEManager()105 ComponentExtensionIMEManager::~ComponentExtensionIMEManager() {
106 }
107 
Initialize(scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate)108 void ComponentExtensionIMEManager::Initialize(
109     scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
110   delegate_ = delegate.Pass();
111   std::vector<ComponentExtensionIME> ext_list = delegate_->ListIME();
112   for (size_t i = 0; i < ext_list.size(); ++i) {
113     ComponentExtensionIME& ext = ext_list[i];
114     bool extension_exists = IsWhitelistedExtension(ext.id);
115     if (!extension_exists)
116       component_extension_imes_[ext.id] = ext;
117     for (size_t j = 0; j < ext.engines.size(); ++j) {
118       ComponentExtensionEngine& ime = ext.engines[j];
119       const std::string input_method_id =
120           extension_ime_util::GetComponentInputMethodID(ext.id, ime.engine_id);
121       if (extension_exists && !IsWhitelisted(input_method_id))
122         component_extension_imes_[ext.id].engines.push_back(ime);
123       input_method_id_set_.insert(input_method_id);
124     }
125   }
126 }
127 
LoadComponentExtensionIME(Profile * profile,const std::string & input_method_id)128 bool ComponentExtensionIMEManager::LoadComponentExtensionIME(
129     Profile* profile,
130     const std::string& input_method_id) {
131   ComponentExtensionIME ime;
132   if (FindEngineEntry(input_method_id, &ime)) {
133     delegate_->Load(profile, ime.id, ime.manifest, ime.path);
134     return true;
135   }
136   return false;
137 }
138 
UnloadComponentExtensionIME(Profile * profile,const std::string & input_method_id)139 bool ComponentExtensionIMEManager::UnloadComponentExtensionIME(
140     Profile* profile,
141     const std::string& input_method_id) {
142   ComponentExtensionIME ime;
143   if (!FindEngineEntry(input_method_id, &ime))
144     return false;
145   delegate_->Unload(profile, ime.id, ime.path);
146   return true;
147 }
148 
IsWhitelisted(const std::string & input_method_id)149 bool ComponentExtensionIMEManager::IsWhitelisted(
150     const std::string& input_method_id) {
151   return input_method_id_set_.find(input_method_id) !=
152          input_method_id_set_.end();
153 }
154 
IsWhitelistedExtension(const std::string & extension_id)155 bool ComponentExtensionIMEManager::IsWhitelistedExtension(
156     const std::string& extension_id) {
157   return component_extension_imes_.find(extension_id) !=
158          component_extension_imes_.end();
159 }
160 
161 input_method::InputMethodDescriptors
GetAllIMEAsInputMethodDescriptor()162     ComponentExtensionIMEManager::GetAllIMEAsInputMethodDescriptor() {
163   input_method::InputMethodDescriptors result;
164   for (std::map<std::string, ComponentExtensionIME>::const_iterator it =
165           component_extension_imes_.begin();
166        it != component_extension_imes_.end(); ++it) {
167     const ComponentExtensionIME& ext = it->second;
168     for (size_t j = 0; j < ext.engines.size(); ++j) {
169       const ComponentExtensionEngine& ime = ext.engines[j];
170       const std::string input_method_id =
171           extension_ime_util::GetComponentInputMethodID(
172               ext.id, ime.engine_id);
173       const std::vector<std::string>& layouts = ime.layouts;
174       result.push_back(
175           input_method::InputMethodDescriptor(
176               input_method_id,
177               ime.display_name,
178               std::string(), // TODO(uekawa): Set short name.
179               layouts,
180               ime.language_codes,
181               // Enables extension based xkb keyboards on login screen.
182               extension_ime_util::IsKeyboardLayoutExtension(
183                   input_method_id) && IsInLoginLayoutWhitelist(layouts),
184               ime.options_page_url,
185               ime.input_view_url));
186     }
187   }
188   std::stable_sort(result.begin(), result.end(), InputMethodCompare);
189   return result;
190 }
191 
192 input_method::InputMethodDescriptors
GetXkbIMEAsInputMethodDescriptor()193 ComponentExtensionIMEManager::GetXkbIMEAsInputMethodDescriptor() {
194   input_method::InputMethodDescriptors result;
195   const input_method::InputMethodDescriptors& descriptors =
196       GetAllIMEAsInputMethodDescriptor();
197   for (size_t i = 0; i < descriptors.size(); ++i) {
198     if (extension_ime_util::IsKeyboardLayoutExtension(descriptors[i].id()))
199       result.push_back(descriptors[i]);
200   }
201   return result;
202 }
203 
FindEngineEntry(const std::string & input_method_id,ComponentExtensionIME * out_extension)204 bool ComponentExtensionIMEManager::FindEngineEntry(
205     const std::string& input_method_id,
206     ComponentExtensionIME* out_extension) {
207   if (!IsWhitelisted(input_method_id))
208     return false;
209 
210   std::string extension_id =
211       extension_ime_util::GetExtensionIDFromInputMethodID(input_method_id);
212   std::map<std::string, ComponentExtensionIME>::iterator it =
213       component_extension_imes_.find(extension_id);
214   if (it == component_extension_imes_.end())
215     return false;
216 
217   if (out_extension)
218     *out_extension = it->second;
219   return true;
220 }
221 
IsInLoginLayoutWhitelist(const std::vector<std::string> & layouts)222 bool ComponentExtensionIMEManager::IsInLoginLayoutWhitelist(
223     const std::vector<std::string>& layouts) {
224   for (size_t i = 0; i < layouts.size(); ++i) {
225     if (login_layout_set_.find(layouts[i]) != login_layout_set_.end())
226       return true;
227   }
228   return false;
229 }
230 
231 }  // namespace chromeos
232