15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/input_method/input_method_manager_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>  // std::find
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/location.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
137879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)#include "base/prefs/pref_service.h"
145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
167879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)#include "chrome/browser/browser_process.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/input_method/candidate_window_controller.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/input_method/input_method_engine_ibus.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/language_preferences.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/dbus_thread_manager.h"
22a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chromeos/dbus/ibus/ibus_client.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/dbus/ibus/ibus_input_context_client.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/ime/component_extension_ime_manager.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/ime/extension_ime_util.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chromeos/ime/input_method_delegate.h"
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/ime/xkeyboard.h"
28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "third_party/icu/source/common/unicode/uloc.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/accelerators/accelerator.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace input_method {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char nacl_mozc_us_id[] =
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us";
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char nacl_mozc_jp_id[] =
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp";
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Contains(const std::vector<std::string>& container,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              const std::string& value) {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::find(container.begin(), container.end(), value) !=
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      container.end();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const struct MigrationInputMethodList {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char* old_input_method;
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char* new_input_method;
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} kMigrationInputMethodList[] = {
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  { "mozc", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  { "mozc-jp", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp" },
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  { "mozc-dv", "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us" },
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "pinyin", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "pinyin-dv", "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabzh-t-i0-pinyin" },
564311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  { "mozc-chewing",
574311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und "},
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:zh:cangjie",
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-hant-t-i0-cangjie-1987" },
604311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  { "_comp_ime_jcffnbbngddhenhcnebafkbdomehdhpdzh-t-i0-wubi-1986",
614311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    "_comp_ime_gjhclobljhjhgoebiipblnmdodbmpdgdzh-t-i0-wubi-1986" },
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // TODO(nona): Remove following migration map in M31.
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:ta:itrans",
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_itrans" },
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:ta:tamil99",
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_tamil99" },
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:ta:typewriter",
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_typewriter" },
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:ta:inscript",
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_phone" },
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:ta:phonetic",
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ta_inscript" },
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:th:pattachote",
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th_pattajoti" },
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:th:tis820", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th_tis" },
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:th:kesmanee",
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_th" },
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:vi:tcvn", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_tcvn" },
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:vi:viqr", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_viqr" },
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:vi:telex",
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_telex" },
82bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  { "m17n:vi:vni",
83bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_vi_vni" },
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:am:sera",
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ethi" },
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:bn:itrans",
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_bn_phone" },
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:gu:itrans",
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_gu_phone" },
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:hi:itrans",
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_deva_phone" },
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:kn:itrans",
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_kn_phone" },
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:ml:itrans",
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ml_phone" },
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:mr:itrans",
97bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_deva_phone" },
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:te:itrans",
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_te_phone" },
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "m17n:fa:isiri", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_fa" },
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  { "m17n:ar:kbd", "_comp_ime_jhffeifommiaekmbkkjlpmilogcfdohpvkd_ar" },
1024311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  // TODO(nona): Remove following migration map in M32
1034311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  { "m17n:zh:quick",
1044311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    "_comp_ime_ekbifjdfhkmdeeajnolmgdlmkllopefizh-hant-t-i0-und" },
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochconst struct MigrationHangulKeyboardToInputMethodID {
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* keyboard_id;
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const char* ime_id;
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} kMigrationHangulKeyboardToInputMethodID[] = {
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "2", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_2set" },
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "3f", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_3setfinal" },
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "39", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_3set390" },
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "3s", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_3setnoshift" },
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  { "ro", "_comp_ime_bdgdidmhaijohebebipajioienkglgfohangul_romaja" },
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
120a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool InputMethodManagerImpl::IsFullLatinKeyboard(
121a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const std::string& layout) const {
122a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  const std::string& lang = util_.GetLanguageCodeFromInputMethodId(layout);
123a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  return full_latin_keyboard_checker.IsFullLatinKeyboard(layout, lang);
124a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
125a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)InputMethodManagerImpl::InputMethodManagerImpl(
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<InputMethodDelegate> delegate)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : delegate_(delegate.Pass()),
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      state_(STATE_LOGIN_SCREEN),
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      util_(delegate_.get(), GetSupportedInputMethods()),
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      component_extension_ime_manager_(new ComponentExtensionIMEManager()),
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IBusDaemonController::GetInstance()->AddObserver(this);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InputMethodManagerImpl::~InputMethodManagerImpl() {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ibus_controller_.get())
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ibus_controller_->RemoveObserver(this);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IBusDaemonController::GetInstance()->RemoveObserver(this);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (candidate_window_controller_.get()) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    candidate_window_controller_->RemoveObserver(this);
142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    candidate_window_controller_->Shutdown();
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::AddObserver(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InputMethodManager::Observer* observer) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::AddCandidateWindowObserver(
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InputMethodManager::CandidateWindowObserver* observer) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  candidate_window_observers_.AddObserver(observer);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::RemoveObserver(
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InputMethodManager::Observer* observer) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::RemoveCandidateWindowObserver(
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InputMethodManager::CandidateWindowObserver* observer) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  candidate_window_observers_.RemoveObserver(observer);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::SetState(State new_state) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const State old_state = state_;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = new_state;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state_) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_LOGIN_SCREEN:
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_BROWSER_SCREEN:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (old_state == STATE_LOCK_SCREEN)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OnScreenUnlocked();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_LOCK_SCREEN:
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OnScreenLocked();
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case STATE_TERMINATING: {
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (candidate_window_controller_.get()) {
181b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        candidate_window_controller_->Shutdown();
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        candidate_window_controller_.reset();
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<InputMethodDescriptors>
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InputMethodManagerImpl::GetSupportedInputMethods() const {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return whitelist_.GetSupportedInputMethods();
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<InputMethodDescriptors>
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)InputMethodManagerImpl::GetActiveInputMethods() const {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<InputMethodDescriptors> result(new InputMethodDescriptors);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build the active input method descriptors from the active input
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // methods cache |active_input_method_ids_|.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& input_method_id = active_input_method_ids_[i];
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const InputMethodDescriptor* descriptor =
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        util_.GetInputMethodDescriptorFromId(input_method_id);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (descriptor) {
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result->push_back(*descriptor);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::map<std::string, InputMethodDescriptor>::const_iterator ix =
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extra_input_methods_.find(input_method_id);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ix != extra_input_methods_.end())
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result->push_back(ix->second);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DVLOG(1) << "Descriptor is not found for: " << input_method_id;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result->empty()) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Initially |active_input_method_ids_| is empty. browser_tests might take
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this path.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->push_back(
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        InputMethodUtil::GetFallbackInputMethodDescriptor());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result.Pass();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
223a3f7b4e666c476898878fa745f637129375cd889Ben Murdochconst std::vector<std::string>&
224a3f7b4e666c476898878fa745f637129375cd889Ben MurdochInputMethodManagerImpl::GetActiveInputMethodIds() const {
225a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  return active_input_method_ids_;
226a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
227a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t InputMethodManagerImpl::GetNumActiveInputMethods() const {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return active_input_method_ids_.size();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::EnableLayouts(const std::string& language_code,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const std::string& initial_layout) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STATE_TERMINATING)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> candidates;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add input methods associated with the language.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  util_.GetInputMethodIdsFromLanguageCode(language_code,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          kKeyboardLayoutsOnly,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          &candidates);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add the hardware keyboard as well. We should always add this so users
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // can use the hardware keyboard on the login screen and the screen locker.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  candidates.push_back(util_.GetHardwareInputMethodId());
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> layouts;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First, add the initial input method ID, if it's requested, to
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // layouts, so it appears first on the list of active input
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // methods at the input language status menu.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (util_.IsValidInputMethodId(initial_layout) &&
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      InputMethodUtil::IsKeyboardLayout(initial_layout)) {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    layouts.push_back(initial_layout);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!initial_layout.empty()) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "EnableLayouts: ignoring non-keyboard or invalid ID: "
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << initial_layout;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add candidates to layouts, while skipping duplicates.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < candidates.size(); ++i) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& candidate = candidates[i];
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not efficient, but should be fine, as the two vectors are very
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // short (2-5 items).
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Contains(layouts, candidate))
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      layouts.push_back(candidate);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_input_method_ids_.swap(layouts);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeInputMethod(initial_layout);  // you can pass empty |initial_layout|.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
271a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// Adds new input method to given list.
272a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool InputMethodManagerImpl::EnableInputMethodImpl(
273a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const std::string& input_method_id,
274a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    std::vector<std::string>& new_active_input_method_ids) const {
275a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (!util_.IsValidInputMethodId(input_method_id)) {
276a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    DVLOG(1) << "EnableInputMethod: Invalid ID: " << input_method_id;
277a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return false;
278a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
279a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
280a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (!Contains(new_active_input_method_ids, input_method_id))
281a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    new_active_input_method_ids.push_back(input_method_id);
282a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
283a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  return true;
284a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
285a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
286a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// Starts or stops the system input method framework as needed.
287a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid InputMethodManagerImpl::ReconfigureIMFramework() {
288a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (component_extension_ime_manager_->IsInitialized())
289a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    LoadNecessaryComponentExtensions();
290a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
291a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (ContainsOnlyKeyboardLayout(active_input_method_ids_)) {
292a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // Do NOT call ibus_controller_->Stop(); here to work around a crash issue
293a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // at crbug.com/27051.
294a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // TODO(yusukes): We can safely call Stop(); here once crbug.com/26443
295a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    // is implemented.
296a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  } else {
297a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    MaybeInitializeCandidateWindowController();
298a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    IBusDaemonController::GetInstance()->Start();
299a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  }
300a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
301a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
302a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool InputMethodManagerImpl::EnableInputMethod(
303a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const std::string& input_method_id) {
304a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (!EnableInputMethodImpl(input_method_id, active_input_method_ids_))
305a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return false;
306a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
307a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  ReconfigureIMFramework();
308a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  return true;
309a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
310a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InputMethodManagerImpl::EnableInputMethods(
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& new_active_input_method_ids) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STATE_TERMINATING)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Filter unknown or obsolete IDs.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> new_active_input_method_ids_filtered;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
319a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  for (size_t i = 0; i < new_active_input_method_ids.size(); ++i)
320a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    EnableInputMethodImpl(new_active_input_method_ids[i],
321a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                          new_active_input_method_ids_filtered);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_active_input_method_ids_filtered.empty()) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "EnableInputMethods: No valid input method ID";
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy extension IDs to |new_active_input_method_ids_filtered|. We have to
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keep relative order of the extension input method IDs.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < active_input_method_ids_.size(); ++i) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& input_method_id = active_input_method_ids_[i];
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (extension_ime_util::IsExtensionIME(input_method_id))
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_active_input_method_ids_filtered.push_back(input_method_id);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_input_method_ids_.swap(new_active_input_method_ids_filtered);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
337a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  ReconfigureIMFramework();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |current_input_method| is no longer in |active_input_method_ids_|,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ChangeInputMethod() picks the first one in |active_input_method_ids_|.
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeInputMethod(current_input_method_.id());
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool InputMethodManagerImpl::MigrateOldInputMethods(
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<std::string>* input_method_ids) {
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool rewritten = false;
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < input_method_ids->size(); ++i) {
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (size_t j = 0; j < ARRAYSIZE_UNSAFE(kMigrationInputMethodList); ++j) {
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (input_method_ids->at(i) ==
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          kMigrationInputMethodList[j].old_input_method) {
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        input_method_ids->at(i).assign(
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            kMigrationInputMethodList[j].new_input_method);
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        rewritten = true;
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
35890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<std::string>::iterator it =
35990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      std::unique(input_method_ids->begin(), input_method_ids->end());
36090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  input_method_ids->resize(std::distance(input_method_ids->begin(), it));
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return rewritten;
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbool InputMethodManagerImpl::MigrateKoreanKeyboard(
365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const std::string& keyboard_id,
366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::vector<std::string>* input_method_ids) {
367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::vector<std::string>::iterator it =
368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      std::find(active_input_method_ids_.begin(),
369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                active_input_method_ids_.end(),
370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                "mozc-hangul");
371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (it == active_input_method_ids_.end())
372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return false;
373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0;
375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       i < ARRAYSIZE_UNSAFE(kMigrationHangulKeyboardToInputMethodID); ++i) {
376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (kMigrationHangulKeyboardToInputMethodID[i].keyboard_id == keyboard_id) {
377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      *it = kMigrationHangulKeyboardToInputMethodID[i].ime_id;
378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      input_method_ids->assign(active_input_method_ids_.begin(),
379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                               active_input_method_ids_.end());
380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return true;
381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return false;
384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InputMethodManagerImpl::SetInputMethodConfig(
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& section,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& config_name,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const InputMethodConfigValue& value) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(section != language_prefs::kGeneralSectionName ||
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         config_name != language_prefs::kPreloadEnginesConfigName);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STATE_TERMINATING)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ibus_controller_->SetInputMethodConfig(section, config_name, value);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::ChangeInputMethod(
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& input_method_id) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeInputMethodInternal(input_method_id, false);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
404a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool InputMethodManagerImpl::ChangeInputMethodInternal(
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& input_method_id,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool show_message) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STATE_TERMINATING)
408a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string input_method_id_to_switch = input_method_id;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity check.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!InputMethodIsActivated(input_method_id)) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods());
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!input_methods->empty());
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    input_method_id_to_switch = input_methods->at(0).id();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!input_method_id.empty()) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "Can't change the current input method to "
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << input_method_id << " since the engine is not enabled. "
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "Switch to " << input_method_id_to_switch << " instead.";
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!component_extension_ime_manager_->IsInitialized() ||
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      (!InputMethodUtil::IsKeyboardLayout(input_method_id_to_switch) &&
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       !IsIBusConnectionAlive())) {
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // We can't change input method before the initialization of component
42890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // extension ime manager or before connection to ibus-daemon is not
42990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // established. ChangeInputMethod will be called with
43090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // |pending_input_method_| when the both initialization is done.
43190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    pending_input_method_ = input_method_id_to_switch;
43290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
43390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
43490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
43590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  pending_input_method_.clear();
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IBusInputContextClient* input_context =
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chromeos::DBusThreadManager::Get()->GetIBusInputContextClient();
438a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string current_input_method_id = current_input_method_.id();
439a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  IBusClient* client = DBusThreadManager::Get()->GetIBusClient();
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (InputMethodUtil::IsKeyboardLayout(input_method_id_to_switch)) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FOR_EACH_OBSERVER(InputMethodManager::Observer,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      observers_,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      InputMethodPropertyChanged(this));
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Hack for fixing http://crosbug.com/p/12798
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should notify IME switching to ibus-daemon, otherwise
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // IBusPreeditFocusMode does not work. To achieve it, change engine to
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // itself if the next engine is XKB layout.
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current_input_method_id.empty() ||
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        InputMethodUtil::IsKeyboardLayout(current_input_method_id)) {
450a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      if (input_context)
451a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        input_context->Reset();
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
453a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      if (client)
454a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        client->SetGlobalEngine(current_input_method_id,
455a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                base::Bind(&base::DoNothing));
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (input_context)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      input_context->SetIsXKBLayout(true);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
460a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    DCHECK(client);
461a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    client->SetGlobalEngine(input_method_id_to_switch,
462a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                            base::Bind(&base::DoNothing));
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (input_context)
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      input_context->SetIsXKBLayout(false);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
467a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (current_input_method_id != input_method_id_to_switch) {
468a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Clear input method properties unconditionally if
469a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // |input_method_id_to_switch| is not equal to |current_input_method_id|.
470a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    //
471a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // When switching to another input method and no text area is focused,
472a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // RegisterProperties signal for the new input method will NOT be sent
473a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // until a text area is focused. Therefore, we have to clear the old input
474a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // method properties here to keep the input method switcher status
475a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // consistent.
476a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    //
477a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // When |input_method_id_to_switch| and |current_input_method_id| are the
478a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // same, the properties shouldn't be cleared. If we do that, something
479a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // wrong happens in step #4 below:
480a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // 1. Enable "xkb:us::eng" and "mozc". Switch to "mozc".
481a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // 2. Focus Omnibox. IME properties for mozc are sent to Chrome.
482a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // 3. Switch to "xkb:us::eng". No function in this file is called.
483a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // 4. Switch back to "mozc". ChangeInputMethod("mozc") is called, but it's
484a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    //    basically NOP since ibus-daemon's current IME is already "mozc".
485a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    //    IME properties are not sent to Chrome for the same reason.
486a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // TODO(nona): Revisit above comment once ibus-daemon is gone.
487a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ibus_controller_->ClearProperties();
488a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const InputMethodDescriptor* descriptor = NULL;
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!extension_ime_util::IsExtensionIME(input_method_id_to_switch)) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      descriptor =
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          util_.GetInputMethodDescriptorFromId(input_method_id_to_switch);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::map<std::string, InputMethodDescriptor>::const_iterator i =
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extra_input_methods_.find(input_method_id_to_switch);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(i != extra_input_methods_.end());
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      descriptor = &(i->second);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(descriptor);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    previous_input_method_ = current_input_method_;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_input_method_ = *descriptor;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Change the keyboard layout to a preferred layout for the input method.
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!xkeyboard_->SetCurrentKeyboardLayoutByName(
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          current_input_method_.GetPreferredKeyboardLayout())) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to change keyboard layout to "
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               << current_input_method_.GetPreferredKeyboardLayout();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update input method indicators (e.g. "US", "DV") in Chrome windows.
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(InputMethodManager::Observer,
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    observers_,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    InputMethodChanged(this, show_message));
516a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return true;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void InputMethodManagerImpl::OnComponentExtensionInitialized(
520c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  component_extension_ime_manager_->Initialize(delegate.Pass());
523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  util_.SetComponentExtensions(
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor());
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LoadNecessaryComponentExtensions();
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
52890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!pending_input_method_.empty())
52990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ChangeInputMethodInternal(pending_input_method_, false);
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void InputMethodManagerImpl::LoadNecessaryComponentExtensions() {
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!component_extension_ime_manager_->IsInitialized())
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Load component extensions but also update |active_input_method_ids_| as
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // some component extension IMEs may have been removed from the Chrome OS
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // image. If specified component extension IME no longer exists, falling back
539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to an existing IME.
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<std::string> unfiltered_input_method_ids =
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      active_input_method_ids_;
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  active_input_method_ids_.clear();
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < unfiltered_input_method_ids.size(); ++i) {
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!component_extension_ime_manager_->IsComponentExtensionIMEId(
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        unfiltered_input_method_ids[i])) {
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Legacy IMEs or xkb layouts are alwayes active.
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      active_input_method_ids_.push_back(unfiltered_input_method_ids[i]);
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else if (component_extension_ime_manager_->IsWhitelisted(
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        unfiltered_input_method_ids[i])) {
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      component_extension_ime_manager_->LoadComponentExtensionIME(
551c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          unfiltered_input_method_ids[i]);
552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      active_input_method_ids_.push_back(unfiltered_input_method_ids[i]);
553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
554c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
555c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
556c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::ActivateInputMethodProperty(
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& key) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!key.empty());
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ibus_controller_->ActivateInputMethodProperty(key);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::AddInputMethodExtension(
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& id,
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name,
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& layouts,
5677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const std::vector<std::string>& languages,
56890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const GURL& options_url,
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InputMethodEngine* engine) {
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STATE_TERMINATING)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!extension_ime_util::IsExtensionIME(id) &&
574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !ComponentExtensionIMEManager::IsComponentExtensionIMEId(id)) {
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << id << " is not a valid extension input method ID.";
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra_input_methods_[id] =
5807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      InputMethodDescriptor(id, name, layouts, languages, options_url);
581b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (Contains(enabled_extension_imes_, id) &&
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !ComponentExtensionIMEManager::IsComponentExtensionIMEId(id)) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!Contains(active_input_method_ids_, id)) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_input_method_ids_.push_back(id);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(1) << "AddInputMethodExtension: alread added: "
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << id << ", " << name;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Call Start() anyway, just in case.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure that the input method daemon is running.
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MaybeInitializeCandidateWindowController();
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IBusDaemonController::GetInstance()->Start();
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra_input_method_instances_[id] =
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<InputMethodEngineIBus*>(engine);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::RemoveInputMethodExtension(const std::string& id) {
601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!extension_ime_util::IsExtensionIME(id))
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << id << " is not a valid extension input method ID.";
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string>::iterator i = std::find(
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_input_method_ids_.begin(), active_input_method_ids_.end(), id);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i != active_input_method_ids_.end())
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_input_method_ids_.erase(i);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  extra_input_methods_.erase(id);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
610a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (ContainsOnlyKeyboardLayout(active_input_method_ids_)) {
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do NOT call ibus_controller_->Stop(); here to work around a crash issue
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // at crosbug.com/27051.
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(yusukes): We can safely call Stop(); here once crosbug.com/26443
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is implemented.
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |current_input_method| is no longer in |active_input_method_ids_|,
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // switch to the first one in |active_input_method_ids_|.
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeInputMethod(current_input_method_.id());
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, InputMethodEngineIBus*>::iterator ite =
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extra_input_method_instances_.find(id);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ite == extra_input_method_instances_.end()) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "The engine instance of " << id << " has already gone.";
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do NOT release the actual instance here. This class does not take an
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // onwership of engine instance.
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extra_input_method_instances_.erase(ite);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::GetInputMethodExtensions(
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InputMethodDescriptors* result) {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build the extension input method descriptors from the extra input
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // methods cache |extra_input_methods_|.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, InputMethodDescriptor>::iterator iter;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (iter = extra_input_methods_.begin(); iter != extra_input_methods_.end();
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++iter) {
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (extension_ime_util::IsExtensionIME(iter->first))
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      result->push_back(iter->second);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
644b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void InputMethodManagerImpl::SetEnabledExtensionImes(
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string>* ids) {
646b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  enabled_extension_imes_.clear();
647b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  enabled_extension_imes_.insert(enabled_extension_imes_.end(),
648b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                 ids->begin(),
649b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                 ids->end());
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool active_imes_changed = false;
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::map<std::string, InputMethodDescriptor>::iterator extra_iter =
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       extra_input_methods_.begin(); extra_iter != extra_input_methods_.end();
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++extra_iter) {
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (ComponentExtensionIMEManager::IsComponentExtensionIMEId(
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        extra_iter->first))
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;  // Do not filter component extension.
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string>::iterator active_iter = std::find(
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        active_input_method_ids_.begin(), active_input_method_ids_.end(),
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        extra_iter->first);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool active = active_iter != active_input_method_ids_.end();
664b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    bool enabled = Contains(enabled_extension_imes_, extra_iter->first);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
666b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (active && !enabled)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_input_method_ids_.erase(active_iter);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
669b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!active && enabled)
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_input_method_ids_.push_back(extra_iter->first);
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (active == !enabled)
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      active_imes_changed = true;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_imes_changed) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MaybeInitializeCandidateWindowController();
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    IBusDaemonController::GetInstance()->Start();
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If |current_input_method| is no longer in |active_input_method_ids_|,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // switch to the first one in |active_input_method_ids_|.
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeInputMethod(current_input_method_.id());
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6867879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)void InputMethodManagerImpl::SetInputMethodDefault() {
6877879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)  // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty
6887879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)  // and US dvorak keyboard layouts.
6897879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)  if (g_browser_process && g_browser_process->local_state()) {
6907879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)    const std::string locale = g_browser_process->GetApplicationLocale();
6917879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)    // If the preferred keyboard for the login screen has been saved, use it.
6927879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)    PrefService* prefs = g_browser_process->local_state();
6937879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)    std::string initial_input_method_id =
6947879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)        prefs->GetString(chromeos::language_prefs::kPreferredKeyboardLayout);
6957879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)    if (initial_input_method_id.empty()) {
6967879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)      // If kPreferredKeyboardLayout is not specified, use the hardware layout.
6977879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)      initial_input_method_id =
6987879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)          GetInputMethodUtil()->GetHardwareInputMethodId();
6997879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)    }
7007879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)    EnableLayouts(locale, initial_input_method_id);
7017879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)  }
7027879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)}
7037879b4e35bc0616056661d21ed48d28e6cecd0a0Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InputMethodManagerImpl::SwitchToNextInputMethod() {
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity checks.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_input_method_ids_.empty()) {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "active input method is empty";
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_input_method_.id().empty()) {
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "current_input_method_ is unknown";
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Do not consume key event if there is only one input method is enabled.
716a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Ctrl+Space or Alt+Shift may be used by other application.
717a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (active_input_method_ids_.size() == 1)
718a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
719a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the next input method and switch to it.
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SwitchToNextInputMethodInternal(active_input_method_ids_,
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  current_input_method_.id());
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
726a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool InputMethodManagerImpl::SwitchToPreviousInputMethod(
727a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    const ui::Accelerator& accelerator) {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity check.
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_input_method_ids_.empty()) {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "active input method is empty";
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
734a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Do not consume key event if there is only one input method is enabled.
735a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Ctrl+Space or Alt+Shift may be used by other application.
736a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (active_input_method_ids_.size() == 1)
737a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
738a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
739a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  if (accelerator.type() == ui::ET_KEY_RELEASED)
740a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch    return true;
741a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_input_method_.id().empty() ||
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      previous_input_method_.id() == current_input_method_.id()) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SwitchToNextInputMethod();
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string>::const_iterator iter =
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(active_input_method_ids_.begin(),
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                active_input_method_ids_.end(),
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                previous_input_method_.id());
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == active_input_method_ids_.end()) {
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // previous_input_method_ is not supported.
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SwitchToNextInputMethod();
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeInputMethodInternal(*iter, true);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InputMethodManagerImpl::SwitchInputMethod(
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ui::Accelerator& accelerator) {
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity check.
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (active_input_method_ids_.empty()) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "active input method is empty";
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the list of input method ids for the |accelerator|. For example, get
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // { "mozc-hangul", "xkb:kr:kr104:kor" } for ui::VKEY_DBE_SBCSCHAR.
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> input_method_ids_to_switch;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (accelerator.key_code()) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_CONVERT:  // Henkan key on JP106 keyboard
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      input_method_ids_to_switch.push_back(nacl_mozc_jp_id);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_NONCONVERT:  // Muhenkan key on JP106 keyboard
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      input_method_ids_to_switch.push_back("xkb:jp::jpn");
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_DBE_SBCSCHAR:  // ZenkakuHankaku key on JP106 keyboard
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case ui::VKEY_DBE_DBCSCHAR:
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      input_method_ids_to_switch.push_back(nacl_mozc_jp_id);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      input_method_ids_to_switch.push_back("xkb:jp::jpn");
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (input_method_ids_to_switch.empty()) {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Unexpected VKEY: " << accelerator.key_code();
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the intersection of input_method_ids_to_switch and
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // active_input_method_ids_. The order of IDs in active_input_method_ids_ is
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preserved.
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> ids;
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < input_method_ids_to_switch.size(); ++i) {
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& id = input_method_ids_to_switch[i];
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Contains(active_input_method_ids_, id))
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ids.push_back(id);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ids.empty()) {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No input method for the accelerator is active. For example, we should
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // just ignore VKEY_HANGUL when mozc-hangul is not active.
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SwitchToNextInputMethodInternal(ids, current_input_method_.id());
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;  // consume the accelerator.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::SwitchToNextInputMethodInternal(
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& input_method_ids,
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& current_input_method_id) {
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string>::const_iterator iter =
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(input_method_ids.begin(),
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                input_method_ids.end(),
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                current_input_method_id);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter != input_method_ids.end())
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++iter;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter == input_method_ids.end())
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter = input_method_ids.begin();
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeInputMethodInternal(*iter, true);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InputMethodDescriptor InputMethodManagerImpl::GetCurrentInputMethod() const {
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (current_input_method_.id().empty())
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return InputMethodUtil::GetFallbackInputMethodDescriptor();
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return current_input_method_;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InputMethodPropertyList
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InputMethodManagerImpl::GetCurrentInputMethodProperties() const {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This check is necessary since an IME property (e.g. for Pinyin) might be
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // sent from ibus-daemon AFTER the current input method is switched to XKB.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (InputMethodUtil::IsKeyboardLayout(GetCurrentInputMethod().id()))
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return InputMethodPropertyList();
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ibus_controller_->GetCurrentProperties();
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)XKeyboard* InputMethodManagerImpl::GetXKeyboard() {
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return xkeyboard_.get();
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InputMethodUtil* InputMethodManagerImpl::GetInputMethodUtil() {
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &util_;
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ComponentExtensionIMEManager*
848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    InputMethodManagerImpl::GetComponentExtensionIMEManager() {
849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return component_extension_ime_manager_.get();
851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::OnConnected() {
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::map<std::string, InputMethodEngineIBus*>::iterator ite =
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extra_input_method_instances_.begin();
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ite != extra_input_method_instances_.end();
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ite++) {
858a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (Contains(enabled_extension_imes_, ite->first) ||
859a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        (component_extension_ime_manager_->IsInitialized() &&
860a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)         component_extension_ime_manager_->IsWhitelisted(ite->first))) {
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ite->second->OnConnected();
862a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    }
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
86590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!pending_input_method_.empty())
86690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ChangeInputMethodInternal(pending_input_method_, false);
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::OnDisconnected() {
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::map<std::string, InputMethodEngineIBus*>::iterator ite =
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          extra_input_method_instances_.begin();
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ite != extra_input_method_instances_.end();
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ite++) {
874b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (Contains(enabled_extension_imes_, ite->first))
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ite->second->OnDisconnected();
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void InputMethodManagerImpl::InitializeComponentExtension() {
880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ComponentExtensionIMEManagerImpl* impl =
881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      new ComponentExtensionIMEManagerImpl();
882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate(impl);
883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  impl->InitializeAsync(base::Bind(
884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       &InputMethodManagerImpl::OnComponentExtensionInitialized,
885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(),
886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                       base::Passed(&delegate)));
887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void InputMethodManagerImpl::Init(base::SequencedTaskRunner* ui_task_runner) {
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!ibus_controller_.get());
891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ibus_controller_.reset(IBusController::Create());
894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  xkeyboard_.reset(XKeyboard::Create());
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ibus_controller_->AddObserver(this);
896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We can't call impl->Initialize here, because file thread is not available
898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // at this moment.
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ui_task_runner->PostTask(
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&InputMethodManagerImpl::InitializeComponentExtension,
902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 weak_ptr_factory_.GetWeakPtr()));
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::SetIBusControllerForTesting(
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IBusController* ibus_controller) {
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ibus_controller_.reset(ibus_controller);
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ibus_controller_->AddObserver(this);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::SetCandidateWindowControllerForTesting(
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CandidateWindowController* candidate_window_controller) {
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  candidate_window_controller_.reset(candidate_window_controller);
914b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  candidate_window_controller_->Init();
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  candidate_window_controller_->AddObserver(this);
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::SetXKeyboardForTesting(XKeyboard* xkeyboard) {
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xkeyboard_.reset(xkeyboard);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
922c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void InputMethodManagerImpl::InitializeComponentExtensionForTesting(
923c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate) {
924c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  OnComponentExtensionInitialized(delegate.Pass());
925c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
926c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::PropertyChanged() {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(InputMethodManager::Observer,
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    observers_,
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    InputMethodPropertyChanged(this));
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::CandidateWindowOpened() {
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver,
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    candidate_window_observers_,
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    CandidateWindowOpened(this));
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::CandidateWindowClosed() {
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver,
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    candidate_window_observers_,
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    CandidateWindowClosed(this));
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::OnScreenLocked() {
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  saved_previous_input_method_ = previous_input_method_;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  saved_current_input_method_ = current_input_method_;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  saved_active_input_method_ids_ = active_input_method_ids_;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string hardware_keyboard_id = util_.GetHardwareInputMethodId();
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We'll add the hardware keyboard if it's not included in
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |active_input_method_list| so that the user can always use the hardware
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keyboard on the screen locker.
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool should_add_hardware_keyboard = true;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_input_method_ids_.clear();
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < saved_active_input_method_ids_.size(); ++i) {
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& input_method_id = saved_active_input_method_ids_[i];
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Skip if it's not a keyboard layout. Drop input methods including
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extension ones.
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!InputMethodUtil::IsKeyboardLayout(input_method_id))
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_input_method_ids_.push_back(input_method_id);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (input_method_id == hardware_keyboard_id)
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      should_add_hardware_keyboard = false;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_add_hardware_keyboard)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_input_method_ids_.push_back(hardware_keyboard_id);
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeInputMethod(current_input_method_.id());
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::OnScreenUnlocked() {
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  previous_input_method_ = saved_previous_input_method_;
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_input_method_ = saved_current_input_method_;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  active_input_method_ids_ = saved_active_input_method_ids_;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeInputMethod(current_input_method_.id());
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool InputMethodManagerImpl::InputMethodIsActivated(
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& input_method_id) {
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Contains(active_input_method_ids_, input_method_id);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
986a3f7b4e666c476898878fa745f637129375cd889Ben Murdochbool InputMethodManagerImpl::ContainsOnlyKeyboardLayout(
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& value) {
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < value.size(); ++i) {
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!InputMethodUtil::IsKeyboardLayout(value[i]))
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void InputMethodManagerImpl::MaybeInitializeCandidateWindowController() {
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (candidate_window_controller_.get())
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  candidate_window_controller_.reset(
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CandidateWindowController::CreateCandidateWindowController());
1001b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (candidate_window_controller_->Init())
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    candidate_window_controller_->AddObserver(this);
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "Failed to initialize the candidate window controller";
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1007a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool InputMethodManagerImpl::IsIBusConnectionAlive() {
1008a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return DBusThreadManager::Get() && DBusThreadManager::Get()->GetIBusClient();
1009a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
1010a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace input_method
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
1013