#include "chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h"
#include "chrome/browser/chromeos/input_method/input_method_engine.h"
#include "chrome/browser/chromeos/language_preferences.h"
-#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"
#include "chromeos/ime/component_extension_ime_manager.h"
}
InputMethodManagerImpl::InputMethodManagerImpl(
- scoped_ptr<InputMethodDelegate> delegate)
+ scoped_ptr<InputMethodDelegate> delegate, bool enable_extension_loading)
: delegate_(delegate.Pass()),
state_(STATE_LOGIN_SCREEN),
- util_(delegate_.get(), whitelist_.GetSupportedInputMethods()),
+ util_(delegate_.get()),
component_extension_ime_manager_(new ComponentExtensionIMEManager()),
- weak_ptr_factory_(this) {
+ enable_extension_loading_(enable_extension_loading) {
+ if (base::SysInfo::IsRunningOnChromeOS())
+ keyboard_.reset(ImeKeyboard::Create());
+ else
+ keyboard_.reset(new FakeImeKeyboard());
+
+ // Initializes the system IME list.
+ scoped_ptr<ComponentExtensionIMEManagerDelegate> comp_delegate(
+ new ComponentExtensionIMEManagerImpl());
+ component_extension_ime_manager_->Initialize(comp_delegate.Pass());
+ util_.ResetInputMethods(
+ component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor());
}
InputMethodManagerImpl::~InputMethodManagerImpl() {
candidate_window_observers_.RemoveObserver(observer);
}
+InputMethodManager::State InputMethodManagerImpl::GetState() {
+ return state_;
+}
+
void InputMethodManagerImpl::SetState(State new_state) {
const State old_state = state_;
state_ = new_state;
scoped_ptr<InputMethodDescriptors>
InputMethodManagerImpl::GetSupportedInputMethods() const {
- if (!IsXkbComponentExtensionAvailable())
- return whitelist_.GetSupportedInputMethods().Pass();
return scoped_ptr<InputMethodDescriptors>(new InputMethodDescriptors).Pass();
}
// Sanity check.
if (!InputMethodIsActivated(input_method_id)) {
+ // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes
+ // happens after activating the 3rd party IME.
+ // So here to record the 3rd party IME to be activated, and activate it
+ // when SetEnabledExtensionImes happens later.
+ if (extension_ime_util::IsExtensionIME(input_method_id))
+ pending_input_method_id_ = input_method_id;
+
scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
DCHECK(!input_methods->empty());
input_method_id_to_switch = input_methods->at(0).id();
}
}
- if (!component_extension_ime_manager_->IsInitialized() &&
- !InputMethodUtil::IsKeyboardLayout(input_method_id_to_switch)) {
- // We can't change input method before the initialization of
- // component extension ime manager. ChangeInputMethod will be
- // called with |pending_input_method_| when the initialization is
- // done.
- pending_input_method_ = input_method_id_to_switch;
- return false;
- }
- pending_input_method_.clear();
-
// Hide candidate window and info list.
if (candidate_window_controller_.get())
candidate_window_controller_->Hide();
- // Disable the current engine handler.
- IMEEngineHandlerInterface* engine =
- IMEBridge::Get()->GetCurrentEngineHandler();
- if (engine)
- engine->Disable();
-
- // Configure the next engine handler.
- if (InputMethodUtil::IsKeyboardLayout(input_method_id_to_switch) &&
- !extension_ime_util::IsKeyboardLayoutExtension(
- input_method_id_to_switch)) {
- IMEBridge::Get()->SetCurrentEngineHandler(NULL);
- } else {
- IMEEngineHandlerInterface* next_engine =
- profile_engine_map_[GetProfile()][input_method_id_to_switch];
- if (next_engine) {
- IMEBridge::Get()->SetCurrentEngineHandler(next_engine);
- next_engine->Enable();
- }
- }
-
// TODO(komatsu): Check if it is necessary to perform the above routine
// when the current input method is equal to |input_method_id_to_swich|.
if (current_input_method_.id() != input_method_id_to_switch) {
current_input_method_ = *descriptor;
}
+ // Disable the current engine handler.
+ IMEEngineHandlerInterface* engine =
+ IMEBridge::Get()->GetCurrentEngineHandler();
+ if (engine)
+ engine->Disable();
+
+ // Configure the next engine handler.
+ // This must be after |current_input_method_| has been set to new input
+ // method, because engine's Enable() method needs to access it.
+ const std::string& extension_id =
+ extension_ime_util::GetExtensionIDFromInputMethodID(
+ input_method_id_to_switch);
+ const std::string& component_id =
+ extension_ime_util::GetComponentIDByInputMethodID(
+ input_method_id_to_switch);
+ engine = engine_map_[extension_id];
+ IMEBridge::Get()->SetCurrentEngineHandler(engine);
+ if (engine)
+ engine->Enable(component_id);
+
// Change the keyboard layout to a preferred layout for the input method.
if (!keyboard_->SetCurrentKeyboardLayoutByName(
current_input_method_.GetPreferredKeyboardLayout())) {
return true;
}
-bool InputMethodManagerImpl::IsXkbComponentExtensionAvailable() const {
- if (!component_extension_ime_manager_->IsInitialized())
- return false;
- InputMethodDescriptors imes =
- component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor();
- for (size_t i = 0; i < imes.size(); ++i) {
- if (StartsWithASCII(extension_ime_util::MaybeGetLegacyXkbId(
- imes[i].id()), "xkb:", true))
- return true;
- }
- return false;
-}
-
-void InputMethodManagerImpl::OnComponentExtensionInitialized(
- scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
- DCHECK(thread_checker_.CalledOnValidThread());
- component_extension_ime_manager_->Initialize(delegate.Pass());
- InputMethodDescriptors imes =
- component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor();
- // In case of XKB extension is not available (e.g. linux_chromeos), don't
- // reset the input methods in InputMethodUtil, Instead append input methods.
- if (IsXkbComponentExtensionAvailable())
- util_.ResetInputMethods(imes);
- else
- util_.AppendInputMethods(imes);
-
- LoadNecessaryComponentExtensions();
-
- if (!pending_input_method_.empty())
- ChangeInputMethodInternal(pending_input_method_, false);
-}
-
void InputMethodManagerImpl::LoadNecessaryComponentExtensions() {
- if (!component_extension_ime_manager_->IsInitialized())
- return;
// Load component extensions but also update |active_input_method_ids_| as
// some component extension IMEs may have been removed from the Chrome OS
// image. If specified component extension IME no longer exists, falling back
active_input_method_ids_.push_back(unfiltered_input_method_ids[i]);
} else if (component_extension_ime_manager_->IsWhitelisted(
unfiltered_input_method_ids[i])) {
- component_extension_ime_manager_->LoadComponentExtensionIME(
- unfiltered_input_method_ids[i]);
+ if (enable_extension_loading_)
+ component_extension_ime_manager_->LoadComponentExtensionIME(
+ unfiltered_input_method_ids[i]);
active_input_method_ids_.push_back(unfiltered_input_method_ids[i]);
}
}
- // TODO(shuchen): move this call in ComponentExtensionIMEManager.
- component_extension_ime_manager_->NotifyInitialized();
}
void InputMethodManagerImpl::ActivateInputMethodMenuItem(
}
void InputMethodManagerImpl::AddInputMethodExtension(
- Profile* profile,
- const std::string& id,
+ const std::string& extension_id,
+ const InputMethodDescriptors& descriptors,
InputMethodEngineInterface* engine) {
if (state_ == STATE_TERMINATING)
return;
DCHECK(engine);
- profile_engine_map_[profile][id] = engine;
+ engine_map_[extension_id] = engine;
- if (id == current_input_method_.id()) {
+ if (extension_id == extension_ime_util::GetExtensionIDFromInputMethodID(
+ current_input_method_.id())) {
IMEBridge::Get()->SetCurrentEngineHandler(engine);
- engine->Enable();
- }
-
- if (extension_ime_util::IsComponentExtensionIME(id))
- return;
-
- CHECK(extension_ime_util::IsExtensionIME(id))
- << id << "is not a valid extension input method ID";
-
- const InputMethodDescriptor& descriptor = engine->GetDescriptor();
- extra_input_methods_[id] = descriptor;
-
- if (Contains(enabled_extension_imes_, id)) {
- if (!Contains(active_input_method_ids_, id)) {
- active_input_method_ids_.push_back(id);
- } else {
- DVLOG(1) << "AddInputMethodExtension: alread added: "
- << id << ", " << descriptor.name();
+ engine->Enable(extension_ime_util::GetComponentIDByInputMethodID(
+ current_input_method_.id()));
+ }
+
+ bool contain = false;
+ for (size_t i = 0; i < descriptors.size(); i++) {
+ const InputMethodDescriptor& descriptor = descriptors[i];
+ const std::string& id = descriptor.id();
+ extra_input_methods_[id] = descriptor;
+ if (Contains(enabled_extension_imes_, id)) {
+ if (!Contains(active_input_method_ids_, id)) {
+ active_input_method_ids_.push_back(id);
+ } else {
+ DVLOG(1) << "AddInputMethodExtension: already added: " << id << ", "
+ << descriptor.name();
+ }
+ contain = true;
}
+ }
- // Ensure that the input method daemon is running.
+ // Ensure that the input method daemon is running.
+ if (contain)
MaybeInitializeCandidateWindowController();
- }
}
-void InputMethodManagerImpl::RemoveInputMethodExtension(Profile* profile,
- const std::string& id) {
- if (!extension_ime_util::IsExtensionIME(id))
- DVLOG(1) << id << " is not a valid extension input method ID.";
+void InputMethodManagerImpl::RemoveInputMethodExtension(
+ const std::string& extension_id) {
+ // Remove the active input methods with |extension_id|.
+ std::vector<std::string> new_active_input_method_ids;
+ for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
+ if (extension_id != extension_ime_util::GetExtensionIDFromInputMethodID(
+ active_input_method_ids_[i]))
+ new_active_input_method_ids.push_back(active_input_method_ids_[i]);
+ }
+ active_input_method_ids_.swap(new_active_input_method_ids);
- std::vector<std::string>::iterator i = std::find(
- active_input_method_ids_.begin(), active_input_method_ids_.end(), id);
- if (i != active_input_method_ids_.end())
- active_input_method_ids_.erase(i);
- extra_input_methods_.erase(id);
+ // Remove the extra input methods with |extension_id|.
+ std::map<std::string, InputMethodDescriptor> new_extra_input_methods;
+ for (std::map<std::string, InputMethodDescriptor>::iterator i =
+ extra_input_methods_.begin();
+ i != extra_input_methods_.end();
+ ++i) {
+ if (extension_id !=
+ extension_ime_util::GetExtensionIDFromInputMethodID(i->first))
+ new_extra_input_methods[i->first] = i->second;
+ }
+ extra_input_methods_.swap(new_extra_input_methods);
- EngineMap& engine_map = profile_engine_map_[profile];
- if (IMEBridge::Get()->GetCurrentEngineHandler() == engine_map[id])
+ if (IMEBridge::Get()->GetCurrentEngineHandler() == engine_map_[extension_id])
IMEBridge::Get()->SetCurrentEngineHandler(NULL);
- engine_map.erase(id);
+ engine_map_.erase(extension_id);
// No need to switch input method when terminating.
if (state_ != STATE_TERMINATING) {
ids->end());
bool active_imes_changed = false;
+ bool switch_to_pending = false;
for (std::map<std::string, InputMethodDescriptor>::iterator extra_iter =
extra_input_methods_.begin(); extra_iter != extra_input_methods_.end();
if (extension_ime_util::IsComponentExtensionIME(
extra_iter->first))
continue; // Do not filter component extension.
+
+ if (pending_input_method_id_ == extra_iter->first)
+ switch_to_pending = true;
+
std::vector<std::string>::iterator active_iter = std::find(
active_input_method_ids_.begin(), active_input_method_ids_.end(),
extra_iter->first);
if (active_imes_changed) {
MaybeInitializeCandidateWindowController();
- // If |current_input_method| is no longer in |active_input_method_ids_|,
- // switch to the first one in |active_input_method_ids_|.
- ChangeInputMethod(current_input_method_.id());
+ if (switch_to_pending) {
+ ChangeInputMethod(pending_input_method_id_);
+ pending_input_method_id_.clear();
+ } else {
+ // If |current_input_method| is no longer in |active_input_method_ids_|,
+ // switch to the first one in |active_input_method_ids_|.
+ ChangeInputMethod(current_input_method_.id());
+ }
}
}
util_.UpdateHardwareLayoutCache();
EnableLoginLayouts(locale, layouts);
+ LoadNecessaryComponentExtensions();
}
void InputMethodManagerImpl::SetInputMethodLoginDefault() {
input_methods_to_be_enabled.push_back(initial_input_method_id);
}
EnableLoginLayouts(locale, input_methods_to_be_enabled);
+ LoadNecessaryComponentExtensions();
}
}
ComponentExtensionIMEManager*
InputMethodManagerImpl::GetComponentExtensionIMEManager() {
- DCHECK(thread_checker_.CalledOnValidThread());
return component_extension_ime_manager_.get();
}
-void InputMethodManagerImpl::InitializeComponentExtension() {
- ComponentExtensionIMEManagerImpl* impl =
- new ComponentExtensionIMEManagerImpl();
- scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate(impl);
- impl->InitializeAsync(base::Bind(
- &InputMethodManagerImpl::OnComponentExtensionInitialized,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(&delegate)));
-}
-
-void InputMethodManagerImpl::Init(base::SequencedTaskRunner* ui_task_runner) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- if (base::SysInfo::IsRunningOnChromeOS())
- keyboard_.reset(ImeKeyboard::Create());
- else
- keyboard_.reset(new FakeImeKeyboard());
-
- // We can't call impl->Initialize here, because file thread is not available
- // at this moment.
- ui_task_runner->PostTask(
- FROM_HERE,
- base::Bind(&InputMethodManagerImpl::InitializeComponentExtension,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
void InputMethodManagerImpl::SetCandidateWindowControllerForTesting(
CandidateWindowController* candidate_window_controller) {
candidate_window_controller_.reset(candidate_window_controller);
void InputMethodManagerImpl::InitializeComponentExtensionForTesting(
scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
- OnComponentExtensionInitialized(delegate.Pass());
+ component_extension_ime_manager_->Initialize(delegate.Pass());
+ util_.ResetInputMethods(
+ component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor());
}
void InputMethodManagerImpl::CandidateClicked(int index) {
candidate_window_controller_->AddObserver(this);
}
-Profile* InputMethodManagerImpl::GetProfile() const {
- return ProfileManager::GetActiveUserProfile();
-}
-
} // namespace input_method
} // namespace chromeos