// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chromeos/ime/component_extension_ime_manager.h" #include "base/logging.h" #include "base/strings/string_util.h" #include "chromeos/ime/extension_ime_util.h" namespace chromeos { namespace { // The whitelist for enabling extension based xkb keyboards at login session. const char* kLoginLayoutWhitelist[] = { "be", "br", "ca", "ca(eng)", "ca(multix)", "ch", "ch(fr)", "cz", "cz(qwerty)", "de", "de(neo)", "dk", "ee", "es", "es(cat)", "fi", "fr", "gb(dvorak)", "gb(extd)", "hr", "hu", "is", "it", "jp", "latam", "lt", "lv(apostrophe)", "no", "pl", "pt", "ro", "se", "si", "tr", "us", "us(altgr-intl)", "us(colemak)", "us(dvorak)", "us(intl)" }; } // namespace ComponentExtensionEngine::ComponentExtensionEngine() { } ComponentExtensionEngine::~ComponentExtensionEngine() { } ComponentExtensionIME::ComponentExtensionIME() { } ComponentExtensionIME::~ComponentExtensionIME() { } ComponentExtensionIMEManagerDelegate::ComponentExtensionIMEManagerDelegate() { } ComponentExtensionIMEManagerDelegate::~ComponentExtensionIMEManagerDelegate() { } ComponentExtensionIMEManager::ComponentExtensionIMEManager() : is_initialized_(false), was_initialization_notified_(false) { for (size_t i = 0; i < arraysize(kLoginLayoutWhitelist); ++i) { login_layout_set_.insert(kLoginLayoutWhitelist[i]); } } ComponentExtensionIMEManager::~ComponentExtensionIMEManager() { } void ComponentExtensionIMEManager::Initialize( scoped_ptr delegate) { delegate_ = delegate.Pass(); component_extension_imes_ = delegate_->ListIME(); is_initialized_ = true; } void ComponentExtensionIMEManager::NotifyInitialized() { if (is_initialized_ && !was_initialization_notified_) { FOR_EACH_OBSERVER( Observer, observers_, OnImeComponentExtensionInitialized()); was_initialization_notified_ = true; } } bool ComponentExtensionIMEManager::IsInitialized() { return is_initialized_; } bool ComponentExtensionIMEManager::LoadComponentExtensionIME( const std::string& input_method_id) { ComponentExtensionIME ime; if (FindEngineEntry(input_method_id, &ime, NULL)) return delegate_->Load(ime.id, ime.manifest, ime.path); else return false; } bool ComponentExtensionIMEManager::UnloadComponentExtensionIME( const std::string& input_method_id) { ComponentExtensionIME ime; if (!FindEngineEntry(input_method_id, &ime, NULL)) return false; delegate_->Unload(ime.id, ime.path); return true; } bool ComponentExtensionIMEManager::IsWhitelisted( const std::string& input_method_id) { return extension_ime_util::IsComponentExtensionIME(input_method_id) && FindEngineEntry(input_method_id, NULL, NULL); } bool ComponentExtensionIMEManager::IsWhitelistedExtension( const std::string& extension_id) { for (size_t i = 0; i < component_extension_imes_.size(); ++i) { if (component_extension_imes_[i].id == extension_id) return true; } return false; } std::string ComponentExtensionIMEManager::GetId( const std::string& extension_id, const std::string& engine_id) { ComponentExtensionEngine engine; const std::string& input_method_id = extension_ime_util::GetComponentInputMethodID(extension_id, engine_id); if (!FindEngineEntry(input_method_id, NULL, &engine)) return ""; return input_method_id; } std::string ComponentExtensionIMEManager::GetName( const std::string& input_method_id) { ComponentExtensionEngine engine; if (!FindEngineEntry(input_method_id, NULL, &engine)) return ""; return engine.display_name; } std::string ComponentExtensionIMEManager::GetDescription( const std::string& input_method_id) { ComponentExtensionEngine engine; if (!FindEngineEntry(input_method_id, NULL, &engine)) return ""; return engine.description; } std::vector ComponentExtensionIMEManager::ListIMEByLanguage( const std::string& language) { std::vector result; for (size_t i = 0; i < component_extension_imes_.size(); ++i) { for (size_t j = 0; j < component_extension_imes_[i].engines.size(); ++j) { const ComponentExtensionIME& ime = component_extension_imes_[i]; if (std::find(ime.engines[j].language_codes.begin(), ime.engines[j].language_codes.end(), language) != ime.engines[j].language_codes.end()) { result.push_back(extension_ime_util::GetComponentInputMethodID( ime.id, ime.engines[j].engine_id)); } } } return result; } input_method::InputMethodDescriptors ComponentExtensionIMEManager::GetAllIMEAsInputMethodDescriptor() { input_method::InputMethodDescriptors result; for (size_t i = 0; i < component_extension_imes_.size(); ++i) { for (size_t j = 0; j < component_extension_imes_[i].engines.size(); ++j) { const std::string input_method_id = extension_ime_util::GetComponentInputMethodID( component_extension_imes_[i].id, component_extension_imes_[i].engines[j].engine_id); const std::vector& layouts = component_extension_imes_[i].engines[j].layouts; result.push_back( input_method::InputMethodDescriptor( input_method_id, component_extension_imes_[i].engines[j].display_name, std::string(), // TODO(uekawa): Set short name. layouts, component_extension_imes_[i].engines[j].language_codes, // Enables extension based xkb keyboards on login screen. extension_ime_util::IsKeyboardLayoutExtension( input_method_id) && IsInLoginLayoutWhitelist(layouts), component_extension_imes_[i].engines[j].options_page_url, component_extension_imes_[i].engines[j].input_view_url)); } } return result; } input_method::InputMethodDescriptors ComponentExtensionIMEManager::GetXkbIMEAsInputMethodDescriptor() { input_method::InputMethodDescriptors result; const input_method::InputMethodDescriptors& descriptors = GetAllIMEAsInputMethodDescriptor(); for (size_t i = 0; i < descriptors.size(); ++i) { if (extension_ime_util::IsKeyboardLayoutExtension(descriptors[i].id())) result.push_back(descriptors[i]); } return result; } void ComponentExtensionIMEManager::AddObserver(Observer* observer) { observers_.AddObserver(observer); } void ComponentExtensionIMEManager::RemoveObserver(Observer* observer) { observers_.RemoveObserver(observer); } bool ComponentExtensionIMEManager::FindEngineEntry( const std::string& input_method_id, ComponentExtensionIME* out_extension, ComponentExtensionEngine* out_engine) { if (!extension_ime_util::IsComponentExtensionIME(input_method_id)) return false; for (size_t i = 0; i < component_extension_imes_.size(); ++i) { const std::string extension_id = component_extension_imes_[i].id; const std::vector& engines = component_extension_imes_[i].engines; for (size_t j = 0; j < engines.size(); ++j) { const std::string trial_ime_id = extension_ime_util::GetComponentInputMethodID( extension_id, engines[j].engine_id); if (trial_ime_id != input_method_id) continue; if (out_extension) *out_extension = component_extension_imes_[i]; if (out_engine) *out_engine = component_extension_imes_[i].engines[j]; return true; } } return false; } bool ComponentExtensionIMEManager::IsInLoginLayoutWhitelist( const std::vector& layouts) { for (size_t i = 0; i < layouts.size(); ++i) { if (login_layout_set_.find(layouts[i]) != login_layout_set_.end()) return true; } return false; } } // namespace chromeos