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
[] = {
63 // Gets the input method category according to the given input method id.
64 // This is used for sorting a list of input methods.
65 int GetInputMethodCategory(const std::string
& id
) {
66 const std::string engine_id
=
67 chromeos::extension_ime_util::GetComponentIDByInputMethodID(id
);
68 if (base::StartsWith(engine_id
, "xkb:", base::CompareCase::SENSITIVE
))
70 if (base::StartsWith(engine_id
, "vkd_", base::CompareCase::SENSITIVE
))
72 if (engine_id
.find("-t-i0-") != std::string::npos
&&
73 !base::StartsWith(engine_id
, "zh-", base::CompareCase::SENSITIVE
)) {
79 bool InputMethodCompare(const input_method::InputMethodDescriptor
& im1
,
80 const input_method::InputMethodDescriptor
& im2
) {
81 return GetInputMethodCategory(im1
.id()) < GetInputMethodCategory(im2
.id());
86 ComponentExtensionEngine::ComponentExtensionEngine() {
89 ComponentExtensionEngine::~ComponentExtensionEngine() {
92 ComponentExtensionIME::ComponentExtensionIME() {
95 ComponentExtensionIME::~ComponentExtensionIME() {
98 ComponentExtensionIMEManagerDelegate::ComponentExtensionIMEManagerDelegate() {
101 ComponentExtensionIMEManagerDelegate::~ComponentExtensionIMEManagerDelegate() {
104 ComponentExtensionIMEManager::ComponentExtensionIMEManager() {
105 for (size_t i
= 0; i
< arraysize(kLoginLayoutWhitelist
); ++i
) {
106 login_layout_set_
.insert(kLoginLayoutWhitelist
[i
]);
110 ComponentExtensionIMEManager::~ComponentExtensionIMEManager() {
113 void ComponentExtensionIMEManager::Initialize(
114 scoped_ptr
<ComponentExtensionIMEManagerDelegate
> delegate
) {
115 delegate_
= delegate
.Pass();
116 std::vector
<ComponentExtensionIME
> ext_list
= delegate_
->ListIME();
117 for (size_t i
= 0; i
< ext_list
.size(); ++i
) {
118 ComponentExtensionIME
& ext
= ext_list
[i
];
119 bool extension_exists
= IsWhitelistedExtension(ext
.id
);
120 if (!extension_exists
)
121 component_extension_imes_
[ext
.id
] = ext
;
122 for (size_t j
= 0; j
< ext
.engines
.size(); ++j
) {
123 ComponentExtensionEngine
& ime
= ext
.engines
[j
];
124 const std::string input_method_id
=
125 extension_ime_util::GetComponentInputMethodID(ext
.id
, ime
.engine_id
);
126 if (extension_exists
&& !IsWhitelisted(input_method_id
))
127 component_extension_imes_
[ext
.id
].engines
.push_back(ime
);
128 input_method_id_set_
.insert(input_method_id
);
133 bool ComponentExtensionIMEManager::LoadComponentExtensionIME(
135 const std::string
& input_method_id
) {
136 ComponentExtensionIME ime
;
137 if (FindEngineEntry(input_method_id
, &ime
)) {
138 delegate_
->Load(profile
, ime
.id
, ime
.manifest
, ime
.path
);
144 bool ComponentExtensionIMEManager::UnloadComponentExtensionIME(
146 const std::string
& input_method_id
) {
147 ComponentExtensionIME ime
;
148 if (!FindEngineEntry(input_method_id
, &ime
))
150 delegate_
->Unload(profile
, ime
.id
, ime
.path
);
154 bool ComponentExtensionIMEManager::IsWhitelisted(
155 const std::string
& input_method_id
) {
156 return input_method_id_set_
.find(input_method_id
) !=
157 input_method_id_set_
.end();
160 bool ComponentExtensionIMEManager::IsWhitelistedExtension(
161 const std::string
& extension_id
) {
162 return component_extension_imes_
.find(extension_id
) !=
163 component_extension_imes_
.end();
166 input_method::InputMethodDescriptors
167 ComponentExtensionIMEManager::GetAllIMEAsInputMethodDescriptor() {
168 bool enable_new_korean_ime
=
169 !base::CommandLine::ForCurrentProcess()->HasSwitch(
170 switches::kDisableNewKoreanIme
);
171 input_method::InputMethodDescriptors result
;
172 for (std::map
<std::string
, ComponentExtensionIME
>::const_iterator it
=
173 component_extension_imes_
.begin();
174 it
!= component_extension_imes_
.end(); ++it
) {
175 const ComponentExtensionIME
& ext
= it
->second
;
176 for (size_t j
= 0; j
< ext
.engines
.size(); ++j
) {
177 const ComponentExtensionEngine
& ime
= ext
.engines
[j
];
178 // Filter out new Korean IME if the experimental flag is OFF.
179 if (!enable_new_korean_ime
&& ime
.engine_id
== "ko-t-i0-und")
181 const std::string input_method_id
=
182 extension_ime_util::GetComponentInputMethodID(
183 ext
.id
, ime
.engine_id
);
184 const std::vector
<std::string
>& layouts
= ime
.layouts
;
186 input_method::InputMethodDescriptor(
192 // Enables extension based xkb keyboards on login screen.
193 extension_ime_util::IsKeyboardLayoutExtension(
194 input_method_id
) && IsInLoginLayoutWhitelist(layouts
),
195 ime
.options_page_url
,
196 ime
.input_view_url
));
199 std::stable_sort(result
.begin(), result
.end(), InputMethodCompare
);
203 input_method::InputMethodDescriptors
204 ComponentExtensionIMEManager::GetXkbIMEAsInputMethodDescriptor() {
205 input_method::InputMethodDescriptors result
;
206 const input_method::InputMethodDescriptors
& descriptors
=
207 GetAllIMEAsInputMethodDescriptor();
208 for (size_t i
= 0; i
< descriptors
.size(); ++i
) {
209 if (extension_ime_util::IsKeyboardLayoutExtension(descriptors
[i
].id()))
210 result
.push_back(descriptors
[i
]);
215 bool ComponentExtensionIMEManager::FindEngineEntry(
216 const std::string
& input_method_id
,
217 ComponentExtensionIME
* out_extension
) {
218 if (!IsWhitelisted(input_method_id
))
221 std::string extension_id
=
222 extension_ime_util::GetExtensionIDFromInputMethodID(input_method_id
);
223 std::map
<std::string
, ComponentExtensionIME
>::iterator it
=
224 component_extension_imes_
.find(extension_id
);
225 if (it
== component_extension_imes_
.end())
229 *out_extension
= it
->second
;
233 bool ComponentExtensionIMEManager::IsInLoginLayoutWhitelist(
234 const std::vector
<std::string
>& layouts
) {
235 for (size_t i
= 0; i
< layouts
.size(); ++i
) {
236 if (login_layout_set_
.find(layouts
[i
]) != login_layout_set_
.end())
242 } // namespace chromeos