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.
5 #include "ui/base/ime/chromeos/component_extension_ime_manager.h"
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 "ui/base/ime/chromeos/extension_ime_util.h"
17 // The whitelist for enabling extension based xkb keyboards at login session.
18 const char* kLoginLayoutWhitelist
[] = {
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))
69 if (StartsWithASCII(engine_id
, "vkd_", true))
71 if (engine_id
.find("-t-i0-") != std::string::npos
&&
72 !StartsWithASCII(engine_id
, "zh-", true)) {
78 bool InputMethodCompare(const input_method::InputMethodDescriptor
& im1
,
79 const input_method::InputMethodDescriptor
& im2
) {
80 return GetInputMethodCategory(im1
.id()) < GetInputMethodCategory(im2
.id());
85 ComponentExtensionEngine::ComponentExtensionEngine() {
88 ComponentExtensionEngine::~ComponentExtensionEngine() {
91 ComponentExtensionIME::ComponentExtensionIME() {
94 ComponentExtensionIME::~ComponentExtensionIME() {
97 ComponentExtensionIMEManagerDelegate::ComponentExtensionIMEManagerDelegate() {
100 ComponentExtensionIMEManagerDelegate::~ComponentExtensionIMEManagerDelegate() {
103 ComponentExtensionIMEManager::ComponentExtensionIMEManager() {
104 for (size_t i
= 0; i
< arraysize(kLoginLayoutWhitelist
); ++i
) {
105 login_layout_set_
.insert(kLoginLayoutWhitelist
[i
]);
109 ComponentExtensionIMEManager::~ComponentExtensionIMEManager() {
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
);
132 bool ComponentExtensionIMEManager::LoadComponentExtensionIME(
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
);
143 bool ComponentExtensionIMEManager::UnloadComponentExtensionIME(
145 const std::string
& input_method_id
) {
146 ComponentExtensionIME ime
;
147 if (!FindEngineEntry(input_method_id
, &ime
))
149 delegate_
->Unload(profile
, ime
.id
, ime
.path
);
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();
159 bool ComponentExtensionIMEManager::IsWhitelistedExtension(
160 const std::string
& extension_id
) {
161 return component_extension_imes_
.find(extension_id
) !=
162 component_extension_imes_
.end();
165 input_method::InputMethodDescriptors
166 ComponentExtensionIMEManager::GetAllIMEAsInputMethodDescriptor() {
167 bool enable_new_korean_ime
=
168 base::CommandLine::ForCurrentProcess()->HasSwitch(
169 switches::kEnableNewKoreanIme
);
170 input_method::InputMethodDescriptors result
;
171 for (std::map
<std::string
, ComponentExtensionIME
>::const_iterator it
=
172 component_extension_imes_
.begin();
173 it
!= component_extension_imes_
.end(); ++it
) {
174 const ComponentExtensionIME
& ext
= it
->second
;
175 for (size_t j
= 0; j
< ext
.engines
.size(); ++j
) {
176 const ComponentExtensionEngine
& ime
= ext
.engines
[j
];
177 // Filter out new Korean IME if the experimental flag is OFF.
178 if (!enable_new_korean_ime
&& ime
.engine_id
== "ko-t-i0-und")
180 const std::string input_method_id
=
181 extension_ime_util::GetComponentInputMethodID(
182 ext
.id
, ime
.engine_id
);
183 const std::vector
<std::string
>& layouts
= ime
.layouts
;
185 input_method::InputMethodDescriptor(
191 // Enables extension based xkb keyboards on login screen.
192 extension_ime_util::IsKeyboardLayoutExtension(
193 input_method_id
) && IsInLoginLayoutWhitelist(layouts
),
194 ime
.options_page_url
,
195 ime
.input_view_url
));
198 std::stable_sort(result
.begin(), result
.end(), InputMethodCompare
);
202 input_method::InputMethodDescriptors
203 ComponentExtensionIMEManager::GetXkbIMEAsInputMethodDescriptor() {
204 input_method::InputMethodDescriptors result
;
205 const input_method::InputMethodDescriptors
& descriptors
=
206 GetAllIMEAsInputMethodDescriptor();
207 for (size_t i
= 0; i
< descriptors
.size(); ++i
) {
208 if (extension_ime_util::IsKeyboardLayoutExtension(descriptors
[i
].id()))
209 result
.push_back(descriptors
[i
]);
214 bool ComponentExtensionIMEManager::FindEngineEntry(
215 const std::string
& input_method_id
,
216 ComponentExtensionIME
* out_extension
) {
217 if (!IsWhitelisted(input_method_id
))
220 std::string extension_id
=
221 extension_ime_util::GetExtensionIDFromInputMethodID(input_method_id
);
222 std::map
<std::string
, ComponentExtensionIME
>::iterator it
=
223 component_extension_imes_
.find(extension_id
);
224 if (it
== component_extension_imes_
.end())
228 *out_extension
= it
->second
;
232 bool ComponentExtensionIMEManager::IsInLoginLayoutWhitelist(
233 const std::vector
<std::string
>& layouts
) {
234 for (size_t i
= 0; i
< layouts
.size(); ++i
) {
235 if (login_layout_set_
.find(layouts
[i
]) != login_layout_set_
.end())
241 } // namespace chromeos