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 "chromeos/ime/component_extension_ime_manager.h"
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "chromeos/ime/extension_ime_util.h"
15 // The whitelist for enabling extension based xkb keyboards at login session.
16 const char* kLoginLayoutWhitelist[] = {
60 ComponentExtensionEngine::ComponentExtensionEngine() {
63 ComponentExtensionEngine::~ComponentExtensionEngine() {
66 ComponentExtensionIME::ComponentExtensionIME() {
69 ComponentExtensionIME::~ComponentExtensionIME() {
72 ComponentExtensionIMEManagerDelegate::ComponentExtensionIMEManagerDelegate() {
75 ComponentExtensionIMEManagerDelegate::~ComponentExtensionIMEManagerDelegate() {
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]);
85 ComponentExtensionIMEManager::~ComponentExtensionIMEManager() {
88 void ComponentExtensionIMEManager::Initialize(
89 scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
90 delegate_ = delegate.Pass();
91 component_extension_imes_ = delegate_->ListIME();
92 is_initialized_ = true;
95 void ComponentExtensionIMEManager::NotifyInitialized() {
96 if (is_initialized_ && !was_initialization_notified_) {
98 Observer, observers_, OnImeComponentExtensionInitialized());
99 was_initialization_notified_ = true;
103 bool ComponentExtensionIMEManager::IsInitialized() {
104 return is_initialized_;
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);
116 bool ComponentExtensionIMEManager::UnloadComponentExtensionIME(
117 const std::string& input_method_id) {
118 ComponentExtensionIME ime;
119 if (!FindEngineEntry(input_method_id, &ime, NULL))
121 delegate_->Unload(ime.id, ime.path);
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);
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)
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))
148 return 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))
156 return engine.display_name;
159 std::string ComponentExtensionIMEManager::GetDescription(
160 const std::string& input_method_id) {
161 ComponentExtensionEngine engine;
162 if (!FindEngineEntry(input_method_id, NULL, &engine))
164 return engine.description;
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(
178 ime.engines[j].engine_id));
185 input_method::InputMethodDescriptors
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;
197 input_method::InputMethodDescriptor(
199 component_extension_imes_[i].engines[j].display_name,
200 std::string(), // TODO(uekawa): Set short name.
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));
213 input_method::InputMethodDescriptors
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]);
225 void ComponentExtensionIMEManager::AddObserver(Observer* observer) {
226 observers_.AddObserver(observer);
229 void ComponentExtensionIMEManager::RemoveObserver(Observer* observer) {
230 observers_.RemoveObserver(observer);
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))
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;
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)
252 *out_extension = component_extension_imes_[i];
254 *out_engine = component_extension_imes_[i].engines[j];
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())
270 } // namespace chromeos