OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/input_method/input_method_manager_impl.h" | 5 #include "chrome/browser/chromeos/input_method/input_method_manager_impl.h" |
6 | 6 |
7 #include <algorithm> // std::find | 7 #include <algorithm> // std::find |
8 | 8 |
| 9 #include <sstream> |
| 10 |
9 #include "ash/ime/input_method_menu_item.h" | 11 #include "ash/ime/input_method_menu_item.h" |
10 #include "ash/ime/input_method_menu_manager.h" | 12 #include "ash/ime/input_method_menu_manager.h" |
11 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
12 #include "base/bind.h" | 14 #include "base/bind.h" |
13 #include "base/location.h" | 15 #include "base/location.h" |
14 #include "base/memory/scoped_ptr.h" | 16 #include "base/memory/scoped_ptr.h" |
15 #include "base/prefs/pref_service.h" | 17 #include "base/prefs/pref_service.h" |
16 #include "base/strings/string_split.h" | 18 #include "base/strings/string_split.h" |
17 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
18 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
19 #include "base/sys_info.h" | 21 #include "base/sys_info.h" |
20 #include "chrome/browser/browser_process.h" | 22 #include "chrome/browser/browser_process.h" |
21 #include "chrome/browser/chromeos/input_method/candidate_window_controller.h" | 23 #include "chrome/browser/chromeos/input_method/candidate_window_controller.h" |
22 #include "chrome/browser/chromeos/input_method/component_extension_ime_manager_i
mpl.h" | 24 #include "chrome/browser/chromeos/input_method/component_extension_ime_manager_i
mpl.h" |
23 #include "chrome/browser/chromeos/input_method/input_method_engine.h" | 25 #include "chrome/browser/chromeos/input_method/input_method_engine.h" |
24 #include "chrome/browser/chromeos/language_preferences.h" | 26 #include "chrome/browser/chromeos/language_preferences.h" |
| 27 #include "chrome/browser/chromeos/login/session/user_session_manager.h" |
| 28 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
25 #include "chrome/browser/profiles/profile_manager.h" | 29 #include "chrome/browser/profiles/profile_manager.h" |
26 #include "chrome/common/pref_names.h" | 30 #include "chrome/common/pref_names.h" |
27 #include "chromeos/ime/component_extension_ime_manager.h" | 31 #include "chromeos/ime/component_extension_ime_manager.h" |
28 #include "chromeos/ime/extension_ime_util.h" | 32 #include "chromeos/ime/extension_ime_util.h" |
29 #include "chromeos/ime/fake_ime_keyboard.h" | 33 #include "chromeos/ime/fake_ime_keyboard.h" |
30 #include "chromeos/ime/ime_keyboard.h" | 34 #include "chromeos/ime/ime_keyboard.h" |
31 #include "chromeos/ime/input_method_delegate.h" | 35 #include "chromeos/ime/input_method_delegate.h" |
| 36 #include "components/user_manager/user_manager.h" |
32 #include "third_party/icu/source/common/unicode/uloc.h" | 37 #include "third_party/icu/source/common/unicode/uloc.h" |
33 #include "ui/base/accelerators/accelerator.h" | 38 #include "ui/base/accelerators/accelerator.h" |
34 | 39 |
35 namespace chromeos { | 40 namespace chromeos { |
36 namespace input_method { | 41 namespace input_method { |
37 | 42 |
38 namespace { | 43 namespace { |
39 | 44 |
40 bool Contains(const std::vector<std::string>& container, | 45 bool Contains(const std::vector<std::string>& container, |
41 const std::string& value) { | 46 const std::string& value) { |
42 return std::find(container.begin(), container.end(), value) != | 47 return std::find(container.begin(), container.end(), value) != |
43 container.end(); | 48 container.end(); |
44 } | 49 } |
45 | 50 |
46 } // namespace | 51 } // namespace |
47 | 52 |
48 bool InputMethodManagerImpl::IsLoginKeyboard( | 53 // ------------------------ InputMethodManagerImpl::StateImpl |
49 const std::string& layout) const { | 54 |
50 return util_.IsLoginKeyboard(layout); | 55 InputMethodManagerImpl::StateImpl::StateImpl(InputMethodManagerImpl* manager, |
| 56 Profile* profile) |
| 57 : profile(profile), manager_(manager) { |
51 } | 58 } |
52 | 59 |
53 bool InputMethodManagerImpl::MigrateInputMethods( | 60 InputMethodManagerImpl::StateImpl::~StateImpl() { |
54 std::vector<std::string>* input_method_ids) { | |
55 return util_.MigrateInputMethods(input_method_ids); | |
56 } | 61 } |
57 | 62 |
58 InputMethodManagerImpl::InputMethodManagerImpl( | 63 void InputMethodManagerImpl::StateImpl::InitFrom(const StateImpl& other) { |
59 scoped_ptr<InputMethodDelegate> delegate, bool enable_extension_loading) | 64 previous_input_method = other.previous_input_method; |
60 : delegate_(delegate.Pass()), | 65 current_input_method = other.current_input_method; |
61 state_(STATE_LOGIN_SCREEN), | |
62 util_(delegate_.get()), | |
63 component_extension_ime_manager_(new ComponentExtensionIMEManager()), | |
64 enable_extension_loading_(enable_extension_loading) { | |
65 if (base::SysInfo::IsRunningOnChromeOS()) | |
66 keyboard_.reset(ImeKeyboard::Create()); | |
67 else | |
68 keyboard_.reset(new FakeImeKeyboard()); | |
69 | 66 |
70 // Initializes the system IME list. | 67 active_input_method_ids = other.active_input_method_ids; |
71 scoped_ptr<ComponentExtensionIMEManagerDelegate> comp_delegate( | 68 |
72 new ComponentExtensionIMEManagerImpl()); | 69 pending_input_method_id = other.pending_input_method_id; |
73 component_extension_ime_manager_->Initialize(comp_delegate.Pass()); | 70 |
74 util_.ResetInputMethods( | 71 enabled_extension_imes = other.enabled_extension_imes; |
75 component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor()); | 72 extra_input_methods = other.extra_input_methods; |
76 } | 73 } |
77 | 74 |
78 InputMethodManagerImpl::~InputMethodManagerImpl() { | 75 bool InputMethodManagerImpl::StateImpl::IsActive() const { |
79 if (candidate_window_controller_.get()) | 76 return manager_->state_.get() == this; |
80 candidate_window_controller_->RemoveObserver(this); | |
81 } | 77 } |
82 | 78 |
83 void InputMethodManagerImpl::AddObserver( | 79 std::string InputMethodManagerImpl::StateImpl::Dump() const { |
84 InputMethodManager::Observer* observer) { | 80 std::ostringstream os; |
85 observers_.AddObserver(observer); | 81 |
| 82 os << "################# " |
| 83 << (profile ? profile->GetProfileName() : std::string("NULL")) |
| 84 << " #################\n"; |
| 85 |
| 86 os << "previous_input_method: '" |
| 87 << previous_input_method.GetPreferredKeyboardLayout() << "'\n"; |
| 88 os << "current_input_method: '" |
| 89 << current_input_method.GetPreferredKeyboardLayout() << "'\n"; |
| 90 os << "active_input_method_ids (size=" << active_input_method_ids.size() |
| 91 << "):"; |
| 92 for (size_t i = 0; i < active_input_method_ids.size(); ++i) { |
| 93 os << " '" << active_input_method_ids[i] << "',"; |
| 94 } |
| 95 os << "\n"; |
| 96 os << "enabled_extension_imes (size=" << enabled_extension_imes.size() |
| 97 << "):"; |
| 98 for (size_t i = 0; i < enabled_extension_imes.size(); ++i) { |
| 99 os << " '" << enabled_extension_imes[i] << "'\n"; |
| 100 } |
| 101 os << "\n"; |
| 102 os << "extra_input_methods (size=" << extra_input_methods.size() << "):"; |
| 103 for (std::map<std::string, InputMethodDescriptor>::const_iterator it = |
| 104 extra_input_methods.begin(); |
| 105 it != extra_input_methods.end(); |
| 106 ++it) { |
| 107 os << " '" << it->first << "' => '" << it->second.id() << "',\n"; |
| 108 } |
| 109 os << "pending_input_method_id: '" << pending_input_method_id << "'\n"; |
| 110 |
| 111 return os.str(); |
86 } | 112 } |
87 | 113 |
88 void InputMethodManagerImpl::AddCandidateWindowObserver( | 114 scoped_refptr<InputMethodManager::State> |
89 InputMethodManager::CandidateWindowObserver* observer) { | 115 InputMethodManagerImpl::StateImpl::Clone() const { |
90 candidate_window_observers_.AddObserver(observer); | 116 scoped_refptr<StateImpl> new_state(new StateImpl(this->manager_, profile)); |
91 } | 117 new_state->InitFrom(*this); |
92 | 118 return scoped_refptr<InputMethodManager::State>(new_state.get()); |
93 void InputMethodManagerImpl::RemoveObserver( | |
94 InputMethodManager::Observer* observer) { | |
95 observers_.RemoveObserver(observer); | |
96 } | |
97 | |
98 void InputMethodManagerImpl::RemoveCandidateWindowObserver( | |
99 InputMethodManager::CandidateWindowObserver* observer) { | |
100 candidate_window_observers_.RemoveObserver(observer); | |
101 } | |
102 | |
103 InputMethodManager::State InputMethodManagerImpl::GetState() { | |
104 return state_; | |
105 } | |
106 | |
107 void InputMethodManagerImpl::SetState(State new_state) { | |
108 const State old_state = state_; | |
109 state_ = new_state; | |
110 switch (state_) { | |
111 case STATE_LOGIN_SCREEN: | |
112 break; | |
113 case STATE_BROWSER_SCREEN: | |
114 if (old_state == STATE_LOCK_SCREEN) | |
115 OnScreenUnlocked(); | |
116 break; | |
117 case STATE_LOCK_SCREEN: | |
118 OnScreenLocked(); | |
119 break; | |
120 case STATE_TERMINATING: { | |
121 if (candidate_window_controller_.get()) | |
122 candidate_window_controller_.reset(); | |
123 break; | |
124 } | |
125 } | |
126 } | 119 } |
127 | 120 |
128 scoped_ptr<InputMethodDescriptors> | 121 scoped_ptr<InputMethodDescriptors> |
129 InputMethodManagerImpl::GetSupportedInputMethods() const { | 122 InputMethodManagerImpl::StateImpl::GetActiveInputMethods() const { |
130 return scoped_ptr<InputMethodDescriptors>(new InputMethodDescriptors).Pass(); | |
131 } | |
132 | |
133 scoped_ptr<InputMethodDescriptors> | |
134 InputMethodManagerImpl::GetActiveInputMethods() const { | |
135 scoped_ptr<InputMethodDescriptors> result(new InputMethodDescriptors); | 123 scoped_ptr<InputMethodDescriptors> result(new InputMethodDescriptors); |
136 // Build the active input method descriptors from the active input | 124 // Build the active input method descriptors from the active input |
137 // methods cache |active_input_method_ids_|. | 125 // methods cache |active_input_method_ids|. |
138 for (size_t i = 0; i < active_input_method_ids_.size(); ++i) { | 126 for (size_t i = 0; i < active_input_method_ids.size(); ++i) { |
139 const std::string& input_method_id = active_input_method_ids_[i]; | 127 const std::string& input_method_id = active_input_method_ids[i]; |
140 const InputMethodDescriptor* descriptor = | 128 const InputMethodDescriptor* descriptor = |
141 util_.GetInputMethodDescriptorFromId(input_method_id); | 129 manager_->util_.GetInputMethodDescriptorFromId(input_method_id); |
142 if (descriptor) { | 130 if (descriptor) { |
143 result->push_back(*descriptor); | 131 result->push_back(*descriptor); |
144 } else { | 132 } else { |
145 std::map<std::string, InputMethodDescriptor>::const_iterator ix = | 133 std::map<std::string, InputMethodDescriptor>::const_iterator ix = |
146 extra_input_methods_.find(input_method_id); | 134 extra_input_methods.find(input_method_id); |
147 if (ix != extra_input_methods_.end()) | 135 if (ix != extra_input_methods.end()) |
148 result->push_back(ix->second); | 136 result->push_back(ix->second); |
149 else | 137 else |
150 DVLOG(1) << "Descriptor is not found for: " << input_method_id; | 138 DVLOG(1) << "Descriptor is not found for: " << input_method_id; |
151 } | 139 } |
152 } | 140 } |
153 if (result->empty()) { | 141 if (result->empty()) { |
154 // Initially |active_input_method_ids_| is empty. browser_tests might take | 142 // Initially |active_input_method_ids| is empty. browser_tests might take |
155 // this path. | 143 // this path. |
156 result->push_back( | 144 result->push_back( |
157 InputMethodUtil::GetFallbackInputMethodDescriptor()); | 145 InputMethodUtil::GetFallbackInputMethodDescriptor()); |
158 } | 146 } |
159 return result.Pass(); | 147 return result.Pass(); |
160 } | 148 } |
161 | 149 |
162 const std::vector<std::string>& | 150 const std::vector<std::string>& |
163 InputMethodManagerImpl::GetActiveInputMethodIds() const { | 151 InputMethodManagerImpl::StateImpl::GetActiveInputMethodIds() const { |
164 return active_input_method_ids_; | 152 return active_input_method_ids; |
165 } | 153 } |
166 | 154 |
167 size_t InputMethodManagerImpl::GetNumActiveInputMethods() const { | 155 size_t InputMethodManagerImpl::StateImpl::GetNumActiveInputMethods() const { |
168 return active_input_method_ids_.size(); | 156 return active_input_method_ids.size(); |
169 } | 157 } |
170 | 158 |
171 const InputMethodDescriptor* InputMethodManagerImpl::GetInputMethodFromId( | 159 const InputMethodDescriptor* |
| 160 InputMethodManagerImpl::StateImpl::GetInputMethodFromId( |
172 const std::string& input_method_id) const { | 161 const std::string& input_method_id) const { |
173 const InputMethodDescriptor* ime = util_.GetInputMethodDescriptorFromId( | 162 const InputMethodDescriptor* ime = |
174 input_method_id); | 163 manager_->util_.GetInputMethodDescriptorFromId(input_method_id); |
175 if (!ime) { | 164 if (!ime) { |
176 std::map<std::string, InputMethodDescriptor>::const_iterator ix = | 165 std::map<std::string, InputMethodDescriptor>::const_iterator ix = |
177 extra_input_methods_.find(input_method_id); | 166 extra_input_methods.find(input_method_id); |
178 if (ix != extra_input_methods_.end()) | 167 if (ix != extra_input_methods.end()) |
179 ime = &ix->second; | 168 ime = &ix->second; |
180 } | 169 } |
181 return ime; | 170 return ime; |
182 } | 171 } |
183 | 172 |
184 void InputMethodManagerImpl::EnableLoginLayouts( | 173 void InputMethodManagerImpl::StateImpl::EnableLoginLayouts( |
185 const std::string& language_code, | 174 const std::string& language_code, |
186 const std::vector<std::string>& initial_layouts) { | 175 const std::vector<std::string>& initial_layouts) { |
187 if (state_ == STATE_TERMINATING) | 176 if (manager_->ui_session_ == STATE_TERMINATING) |
188 return; | 177 return; |
189 | 178 |
190 // First, hardware keyboard layout should be shown. | 179 // First, hardware keyboard layout should be shown. |
191 std::vector<std::string> candidates = | 180 std::vector<std::string> candidates = |
192 util_.GetHardwareLoginInputMethodIds(); | 181 manager_->util_.GetHardwareLoginInputMethodIds(); |
193 | 182 |
194 // Seocnd, locale based input method should be shown. | 183 // Second, locale based input method should be shown. |
195 // Add input methods associated with the language. | 184 // Add input methods associated with the language. |
196 std::vector<std::string> layouts_from_locale; | 185 std::vector<std::string> layouts_from_locale; |
197 util_.GetInputMethodIdsFromLanguageCode(language_code, | 186 manager_->util_.GetInputMethodIdsFromLanguageCode( |
198 kKeyboardLayoutsOnly, | 187 language_code, kKeyboardLayoutsOnly, &layouts_from_locale); |
199 &layouts_from_locale); | |
200 candidates.insert(candidates.end(), layouts_from_locale.begin(), | 188 candidates.insert(candidates.end(), layouts_from_locale.begin(), |
201 layouts_from_locale.end()); | 189 layouts_from_locale.end()); |
202 | 190 |
203 std::vector<std::string> layouts; | 191 std::vector<std::string> layouts; |
204 // First, add the initial input method ID, if it's requested, to | 192 // First, add the initial input method ID, if it's requested, to |
205 // layouts, so it appears first on the list of active input | 193 // layouts, so it appears first on the list of active input |
206 // methods at the input language status menu. | 194 // methods at the input language status menu. |
207 for (size_t i = 0; i < initial_layouts.size(); ++i) { | 195 for (size_t i = 0; i < initial_layouts.size(); ++i) { |
208 if (util_.IsValidInputMethodId(initial_layouts[i])) { | 196 if (manager_->util_.IsValidInputMethodId(initial_layouts[i])) { |
209 if (IsLoginKeyboard(initial_layouts[i])) { | 197 if (manager_->IsLoginKeyboard(initial_layouts[i])) { |
210 layouts.push_back(initial_layouts[i]); | 198 layouts.push_back(initial_layouts[i]); |
211 } else { | 199 } else { |
212 DVLOG(1) | 200 DVLOG(1) |
213 << "EnableLoginLayouts: ignoring non-login initial keyboard layout:" | 201 << "EnableLoginLayouts: ignoring non-login initial keyboard layout:" |
214 << initial_layouts[i]; | 202 << initial_layouts[i]; |
215 } | 203 } |
216 } else if (!initial_layouts[i].empty()) { | 204 } else if (!initial_layouts[i].empty()) { |
217 DVLOG(1) << "EnableLoginLayouts: ignoring non-keyboard or invalid ID: " | 205 DVLOG(1) << "EnableLoginLayouts: ignoring non-keyboard or invalid ID: " |
218 << initial_layouts[i]; | 206 << initial_layouts[i]; |
219 } | 207 } |
220 } | 208 } |
221 | 209 |
222 // Add candidates to layouts, while skipping duplicates. | 210 // Add candidates to layouts, while skipping duplicates. |
223 for (size_t i = 0; i < candidates.size(); ++i) { | 211 for (size_t i = 0; i < candidates.size(); ++i) { |
224 const std::string& candidate = candidates[i]; | 212 const std::string& candidate = candidates[i]; |
225 // Not efficient, but should be fine, as the two vectors are very | 213 // Not efficient, but should be fine, as the two vectors are very |
226 // short (2-5 items). | 214 // short (2-5 items). |
227 if (!Contains(layouts, candidate) && IsLoginKeyboard(candidate)) | 215 if (!Contains(layouts, candidate) && manager_->IsLoginKeyboard(candidate)) |
228 layouts.push_back(candidate); | 216 layouts.push_back(candidate); |
229 } | 217 } |
230 | 218 |
231 MigrateInputMethods(&layouts); | 219 manager_->MigrateInputMethods(&layouts); |
232 active_input_method_ids_.swap(layouts); | 220 active_input_method_ids.swap(layouts); |
233 | 221 |
234 // Initialize candidate window controller and widgets such as | 222 if (IsActive()) { |
235 // candidate window, infolist and mode indicator. Note, mode | 223 // Initialize candidate window controller and widgets such as |
236 // indicator is used by only keyboard layout input methods. | 224 // candidate window, infolist and mode indicator. Note, mode |
237 if (active_input_method_ids_.size() > 1) | 225 // indicator is used by only keyboard layout input methods. |
238 MaybeInitializeCandidateWindowController(); | 226 if (active_input_method_ids.size() > 1) |
| 227 manager_->MaybeInitializeCandidateWindowController(); |
239 | 228 |
240 // you can pass empty |initial_layout|. | 229 // you can pass empty |initial_layout|. |
241 ChangeInputMethod(initial_layouts.empty() ? "" : | 230 ChangeInputMethod(initial_layouts.empty() |
242 extension_ime_util::GetInputMethodIDByEngineID(initial_layouts[0])); | 231 ? std::string() |
| 232 : extension_ime_util::GetInputMethodIDByEngineID( |
| 233 initial_layouts[0]), |
| 234 false); |
| 235 } |
| 236 } |
| 237 |
| 238 void InputMethodManagerImpl::StateImpl::EnableLockScreenLayouts() { |
| 239 std::set<std::string> added_ids; |
| 240 |
| 241 const std::vector<std::string>& hardware_keyboard_ids = |
| 242 manager_->util_.GetHardwareLoginInputMethodIds(); |
| 243 |
| 244 std::vector<std::string> new_active_input_method_ids; |
| 245 for (size_t i = 0; i < active_input_method_ids.size(); ++i) { |
| 246 const std::string& input_method_id = active_input_method_ids[i]; |
| 247 // Skip if it's not a keyboard layout. Drop input methods including |
| 248 // extension ones. |
| 249 if (!manager_->IsLoginKeyboard(input_method_id) || |
| 250 added_ids.count(input_method_id)) { |
| 251 continue; |
| 252 } |
| 253 new_active_input_method_ids.push_back(input_method_id); |
| 254 added_ids.insert(input_method_id); |
| 255 } |
| 256 |
| 257 // We'll add the hardware keyboard if it's not included in |
| 258 // |active_input_method_ids| so that the user can always use the hardware |
| 259 // keyboard on the screen locker. |
| 260 for (size_t i = 0; i < hardware_keyboard_ids.size(); ++i) { |
| 261 if (added_ids.count(hardware_keyboard_ids[i])) |
| 262 continue; |
| 263 new_active_input_method_ids.push_back(hardware_keyboard_ids[i]); |
| 264 added_ids.insert(hardware_keyboard_ids[i]); |
| 265 } |
| 266 |
| 267 active_input_method_ids.swap(new_active_input_method_ids); |
| 268 |
| 269 // Re-check current_input_method. |
| 270 ChangeInputMethod(current_input_method.id(), false); |
243 } | 271 } |
244 | 272 |
245 // Adds new input method to given list. | 273 // Adds new input method to given list. |
246 bool InputMethodManagerImpl::EnableInputMethodImpl( | 274 bool InputMethodManagerImpl::StateImpl::EnableInputMethodImpl( |
247 const std::string& input_method_id, | 275 const std::string& input_method_id, |
248 std::vector<std::string>* new_active_input_method_ids) const { | 276 std::vector<std::string>* new_active_input_method_ids) const { |
249 DCHECK(new_active_input_method_ids); | 277 DCHECK(new_active_input_method_ids); |
250 if (!util_.IsValidInputMethodId(input_method_id)) { | 278 if (!manager_->util_.IsValidInputMethodId(input_method_id)) { |
251 DVLOG(1) << "EnableInputMethod: Invalid ID: " << input_method_id; | 279 DVLOG(1) << "EnableInputMethod: Invalid ID: " << input_method_id; |
252 return false; | 280 return false; |
253 } | 281 } |
254 | 282 |
255 if (!Contains(*new_active_input_method_ids, input_method_id)) | 283 if (!Contains(*new_active_input_method_ids, input_method_id)) |
256 new_active_input_method_ids->push_back(input_method_id); | 284 new_active_input_method_ids->push_back(input_method_id); |
257 | 285 |
258 return true; | 286 return true; |
259 } | 287 } |
260 | 288 |
261 // Starts or stops the system input method framework as needed. | 289 bool InputMethodManagerImpl::StateImpl::EnableInputMethod( |
262 void InputMethodManagerImpl::ReconfigureIMFramework() { | |
263 LoadNecessaryComponentExtensions(); | |
264 | |
265 // Initialize candidate window controller and widgets such as | |
266 // candidate window, infolist and mode indicator. Note, mode | |
267 // indicator is used by only keyboard layout input methods. | |
268 MaybeInitializeCandidateWindowController(); | |
269 } | |
270 | |
271 bool InputMethodManagerImpl::EnableInputMethod( | |
272 const std::string& input_method_id) { | 290 const std::string& input_method_id) { |
273 if (!EnableInputMethodImpl(input_method_id, &active_input_method_ids_)) | 291 if (!EnableInputMethodImpl(input_method_id, &active_input_method_ids)) |
274 return false; | 292 return false; |
275 | 293 |
276 ReconfigureIMFramework(); | 294 manager_->ReconfigureIMFramework(this); |
277 return true; | 295 return true; |
278 } | 296 } |
279 | 297 |
280 bool InputMethodManagerImpl::ReplaceEnabledInputMethods( | 298 bool InputMethodManagerImpl::StateImpl::ReplaceEnabledInputMethods( |
281 const std::vector<std::string>& new_active_input_method_ids) { | 299 const std::vector<std::string>& new_active_input_method_ids) { |
282 if (state_ == STATE_TERMINATING) | 300 if (manager_->ui_session_ == STATE_TERMINATING) |
283 return false; | 301 return false; |
284 | 302 |
285 // Filter unknown or obsolete IDs. | 303 // Filter unknown or obsolete IDs. |
286 std::vector<std::string> new_active_input_method_ids_filtered; | 304 std::vector<std::string> new_active_input_method_ids_filtered; |
287 | 305 |
288 for (size_t i = 0; i < new_active_input_method_ids.size(); ++i) | 306 for (size_t i = 0; i < new_active_input_method_ids.size(); ++i) |
289 EnableInputMethodImpl(new_active_input_method_ids[i], | 307 EnableInputMethodImpl(new_active_input_method_ids[i], |
290 &new_active_input_method_ids_filtered); | 308 &new_active_input_method_ids_filtered); |
291 | 309 |
292 if (new_active_input_method_ids_filtered.empty()) { | 310 if (new_active_input_method_ids_filtered.empty()) { |
293 DVLOG(1) << "ReplaceEnabledInputMethods: No valid input method ID"; | 311 DVLOG(1) << "ReplaceEnabledInputMethods: No valid input method ID"; |
294 return false; | 312 return false; |
295 } | 313 } |
296 | 314 |
297 // Copy extension IDs to |new_active_input_method_ids_filtered|. We have to | 315 // Copy extension IDs to |new_active_input_method_ids_filtered|. We have to |
298 // keep relative order of the extension input method IDs. | 316 // keep relative order of the extension input method IDs. |
299 for (size_t i = 0; i < active_input_method_ids_.size(); ++i) { | 317 for (size_t i = 0; i < active_input_method_ids.size(); ++i) { |
300 const std::string& input_method_id = active_input_method_ids_[i]; | 318 const std::string& input_method_id = active_input_method_ids[i]; |
301 if (extension_ime_util::IsExtensionIME(input_method_id)) | 319 if (extension_ime_util::IsExtensionIME(input_method_id)) |
302 new_active_input_method_ids_filtered.push_back(input_method_id); | 320 new_active_input_method_ids_filtered.push_back(input_method_id); |
303 } | 321 } |
304 active_input_method_ids_.swap(new_active_input_method_ids_filtered); | 322 active_input_method_ids.swap(new_active_input_method_ids_filtered); |
305 MigrateInputMethods(&active_input_method_ids_); | 323 manager_->MigrateInputMethods(&active_input_method_ids); |
306 | 324 |
307 ReconfigureIMFramework(); | 325 manager_->ReconfigureIMFramework(this); |
308 | 326 |
309 // If |current_input_method| is no longer in |active_input_method_ids_|, | 327 // If |current_input_method| is no longer in |active_input_method_ids|, |
310 // ChangeInputMethod() picks the first one in |active_input_method_ids_|. | 328 // ChangeInputMethod() picks the first one in |active_input_method_ids|. |
311 ChangeInputMethod(current_input_method_.id()); | 329 ChangeInputMethod(current_input_method.id(), false); |
312 return true; | 330 return true; |
313 } | 331 } |
314 | 332 |
315 void InputMethodManagerImpl::ChangeInputMethod( | 333 void InputMethodManagerImpl::StateImpl::ChangeInputMethod( |
316 const std::string& input_method_id) { | 334 const std::string& input_method_id, |
317 ChangeInputMethodInternal(input_method_id, false); | 335 bool show_message) { |
| 336 if (manager_->ui_session_ == STATE_TERMINATING) |
| 337 return; |
| 338 |
| 339 bool notify_menu = false; |
| 340 // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes |
| 341 // happens after activating the 3rd party IME. |
| 342 // So here to record the 3rd party IME to be activated, and activate it |
| 343 // when SetEnabledExtensionImes happens later. |
| 344 if (MethodAwaitsExtensionLoad(input_method_id)) |
| 345 pending_input_method_id = input_method_id; |
| 346 |
| 347 // Always lookup input method, even if it is the same as |
| 348 // |current_input_method| because If it is no longer in |
| 349 // |active_input_method_ids|, pick the first one in |
| 350 // |active_input_method_ids|. |
| 351 const InputMethodDescriptor* descriptor = |
| 352 manager_->LookupInputMethod(input_method_id, this); |
| 353 if (descriptor->id() != current_input_method.id()) { |
| 354 previous_input_method = current_input_method; |
| 355 current_input_method = *descriptor; |
| 356 notify_menu = true; |
| 357 } |
| 358 |
| 359 // Always change input method even if it is the same. |
| 360 // TODO(komatsu): Revisit if this is neccessary. |
| 361 if (IsActive()) |
| 362 manager_->ChangeInputMethodInternal(*descriptor, show_message, notify_menu); |
318 } | 363 } |
319 | 364 |
320 bool InputMethodManagerImpl::ChangeInputMethodInternal( | 365 bool InputMethodManagerImpl::StateImpl::MethodAwaitsExtensionLoad( |
321 const std::string& input_method_id, | 366 const std::string& input_method_id) const { |
322 bool show_message) { | 367 // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes |
323 if (state_ == STATE_TERMINATING) | 368 // happens after activating the 3rd party IME. |
324 return false; | 369 // So here to record the 3rd party IME to be activated, and activate it |
325 | 370 // when SetEnabledExtensionImes happens later. |
326 std::string input_method_id_to_switch = input_method_id; | 371 return !InputMethodIsActivated(input_method_id) && |
327 | 372 extension_ime_util::IsExtensionIME(input_method_id); |
328 // Sanity check. | |
329 if (!InputMethodIsActivated(input_method_id)) { | |
330 // For 3rd party IME, when the user just logged in, SetEnabledExtensionImes | |
331 // happens after activating the 3rd party IME. | |
332 // So here to record the 3rd party IME to be activated, and activate it | |
333 // when SetEnabledExtensionImes happens later. | |
334 if (extension_ime_util::IsExtensionIME(input_method_id)) | |
335 pending_input_method_id_ = input_method_id; | |
336 | |
337 scoped_ptr<InputMethodDescriptors> input_methods(GetActiveInputMethods()); | |
338 DCHECK(!input_methods->empty()); | |
339 input_method_id_to_switch = input_methods->at(0).id(); | |
340 if (!input_method_id.empty()) { | |
341 DVLOG(1) << "Can't change the current input method to " | |
342 << input_method_id << " since the engine is not enabled. " | |
343 << "Switch to " << input_method_id_to_switch << " instead."; | |
344 } | |
345 } | |
346 | |
347 // Hide candidate window and info list. | |
348 if (candidate_window_controller_.get()) | |
349 candidate_window_controller_->Hide(); | |
350 | |
351 // TODO(komatsu): Check if it is necessary to perform the above routine | |
352 // when the current input method is equal to |input_method_id_to_swich|. | |
353 if (current_input_method_.id() != input_method_id_to_switch) { | |
354 // Clear property list. Property list would be updated by | |
355 // extension IMEs via InputMethodEngine::(Set|Update)MenuItems. | |
356 // If the current input method is a keyboard layout, empty | |
357 // properties are sufficient. | |
358 const ash::ime::InputMethodMenuItemList empty_menu_item_list; | |
359 ash::ime::InputMethodMenuManager* input_method_menu_manager = | |
360 ash::ime::InputMethodMenuManager::GetInstance(); | |
361 input_method_menu_manager->SetCurrentInputMethodMenuItemList( | |
362 empty_menu_item_list); | |
363 | |
364 const InputMethodDescriptor* descriptor = NULL; | |
365 if (extension_ime_util::IsExtensionIME(input_method_id_to_switch)) { | |
366 DCHECK(extra_input_methods_.find(input_method_id_to_switch) != | |
367 extra_input_methods_.end()); | |
368 descriptor = &(extra_input_methods_[input_method_id_to_switch]); | |
369 } else { | |
370 descriptor = | |
371 util_.GetInputMethodDescriptorFromId(input_method_id_to_switch); | |
372 if (!descriptor) | |
373 LOG(ERROR) << "Unknown input method id: " << input_method_id_to_switch; | |
374 } | |
375 DCHECK(descriptor); | |
376 | |
377 previous_input_method_ = current_input_method_; | |
378 current_input_method_ = *descriptor; | |
379 } | |
380 | |
381 // Disable the current engine handler. | |
382 IMEEngineHandlerInterface* engine = | |
383 IMEBridge::Get()->GetCurrentEngineHandler(); | |
384 if (engine) | |
385 engine->Disable(); | |
386 | |
387 // Configure the next engine handler. | |
388 // This must be after |current_input_method_| has been set to new input | |
389 // method, because engine's Enable() method needs to access it. | |
390 const std::string& extension_id = | |
391 extension_ime_util::GetExtensionIDFromInputMethodID( | |
392 input_method_id_to_switch); | |
393 const std::string& component_id = | |
394 extension_ime_util::GetComponentIDByInputMethodID( | |
395 input_method_id_to_switch); | |
396 engine = engine_map_[extension_id]; | |
397 IMEBridge::Get()->SetCurrentEngineHandler(engine); | |
398 if (engine) | |
399 engine->Enable(component_id); | |
400 | |
401 // Change the keyboard layout to a preferred layout for the input method. | |
402 if (!keyboard_->SetCurrentKeyboardLayoutByName( | |
403 current_input_method_.GetPreferredKeyboardLayout())) { | |
404 LOG(ERROR) << "Failed to change keyboard layout to " | |
405 << current_input_method_.GetPreferredKeyboardLayout(); | |
406 } | |
407 | |
408 // Update input method indicators (e.g. "US", "DV") in Chrome windows. | |
409 FOR_EACH_OBSERVER(InputMethodManager::Observer, | |
410 observers_, | |
411 InputMethodChanged(this, show_message)); | |
412 return true; | |
413 } | 373 } |
414 | 374 |
415 void InputMethodManagerImpl::LoadNecessaryComponentExtensions() { | 375 void InputMethodManagerImpl::StateImpl::AddInputMethodExtension( |
416 // Load component extensions but also update |active_input_method_ids_| as | |
417 // some component extension IMEs may have been removed from the Chrome OS | |
418 // image. If specified component extension IME no longer exists, falling back | |
419 // to an existing IME. | |
420 std::vector<std::string> unfiltered_input_method_ids; | |
421 unfiltered_input_method_ids.swap(active_input_method_ids_); | |
422 for (size_t i = 0; i < unfiltered_input_method_ids.size(); ++i) { | |
423 if (!extension_ime_util::IsComponentExtensionIME( | |
424 unfiltered_input_method_ids[i])) { | |
425 // Legacy IMEs or xkb layouts are alwayes active. | |
426 active_input_method_ids_.push_back(unfiltered_input_method_ids[i]); | |
427 } else if (component_extension_ime_manager_->IsWhitelisted( | |
428 unfiltered_input_method_ids[i])) { | |
429 if (enable_extension_loading_) | |
430 component_extension_ime_manager_->LoadComponentExtensionIME( | |
431 unfiltered_input_method_ids[i]); | |
432 active_input_method_ids_.push_back(unfiltered_input_method_ids[i]); | |
433 } | |
434 } | |
435 } | |
436 | |
437 void InputMethodManagerImpl::ActivateInputMethodMenuItem( | |
438 const std::string& key) { | |
439 DCHECK(!key.empty()); | |
440 | |
441 if (ash::ime::InputMethodMenuManager::GetInstance()-> | |
442 HasInputMethodMenuItemForKey(key)) { | |
443 IMEEngineHandlerInterface* engine = | |
444 IMEBridge::Get()->GetCurrentEngineHandler(); | |
445 if (engine) | |
446 engine->PropertyActivate(key); | |
447 return; | |
448 } | |
449 | |
450 DVLOG(1) << "ActivateInputMethodMenuItem: unknown key: " << key; | |
451 } | |
452 | |
453 void InputMethodManagerImpl::AddInputMethodExtension( | |
454 const std::string& extension_id, | 376 const std::string& extension_id, |
455 const InputMethodDescriptors& descriptors, | 377 const InputMethodDescriptors& descriptors, |
456 InputMethodEngineInterface* engine) { | 378 InputMethodEngineInterface* engine) { |
457 if (state_ == STATE_TERMINATING) | 379 if (manager_->ui_session_ == STATE_TERMINATING) |
458 return; | 380 return; |
459 | 381 |
460 DCHECK(engine); | 382 DCHECK(engine); |
461 | 383 |
462 engine_map_[extension_id] = engine; | 384 manager_->engine_map_[extension_id] = engine; |
463 | |
464 if (extension_id == extension_ime_util::GetExtensionIDFromInputMethodID( | |
465 current_input_method_.id())) { | |
466 IMEBridge::Get()->SetCurrentEngineHandler(engine); | |
467 engine->Enable(extension_ime_util::GetComponentIDByInputMethodID( | |
468 current_input_method_.id())); | |
469 } | |
470 | 385 |
471 bool contain = false; | 386 bool contain = false; |
472 for (size_t i = 0; i < descriptors.size(); i++) { | 387 for (size_t i = 0; i < descriptors.size(); i++) { |
473 const InputMethodDescriptor& descriptor = descriptors[i]; | 388 const InputMethodDescriptor& descriptor = descriptors[i]; |
474 const std::string& id = descriptor.id(); | 389 const std::string& id = descriptor.id(); |
475 extra_input_methods_[id] = descriptor; | 390 extra_input_methods[id] = descriptor; |
476 if (Contains(enabled_extension_imes_, id)) { | 391 if (Contains(enabled_extension_imes, id)) { |
477 if (!Contains(active_input_method_ids_, id)) { | 392 if (!Contains(active_input_method_ids, id)) { |
478 active_input_method_ids_.push_back(id); | 393 active_input_method_ids.push_back(id); |
479 } else { | 394 } else { |
480 DVLOG(1) << "AddInputMethodExtension: already added: " << id << ", " | 395 DVLOG(1) << "AddInputMethodExtension: already added: " << id << ", " |
481 << descriptor.name(); | 396 << descriptor.name(); |
482 } | 397 } |
483 contain = true; | 398 contain = true; |
484 } | 399 } |
485 } | 400 } |
486 | 401 |
487 // Ensure that the input method daemon is running. | 402 if (IsActive()) { |
488 if (contain) | 403 if (extension_id == extension_ime_util::GetExtensionIDFromInputMethodID( |
489 MaybeInitializeCandidateWindowController(); | 404 current_input_method.id())) { |
| 405 IMEBridge::Get()->SetCurrentEngineHandler(engine); |
| 406 engine->Enable(extension_ime_util::GetComponentIDByInputMethodID( |
| 407 current_input_method.id())); |
| 408 } |
| 409 |
| 410 // Ensure that the input method daemon is running. |
| 411 if (contain) |
| 412 manager_->MaybeInitializeCandidateWindowController(); |
| 413 } |
490 } | 414 } |
491 | 415 |
492 void InputMethodManagerImpl::RemoveInputMethodExtension( | 416 void InputMethodManagerImpl::StateImpl::RemoveInputMethodExtension( |
493 const std::string& extension_id) { | 417 const std::string& extension_id) { |
494 // Remove the active input methods with |extension_id|. | 418 // Remove the active input methods with |extension_id|. |
495 std::vector<std::string> new_active_input_method_ids; | 419 std::vector<std::string> new_active_input_method_ids; |
496 for (size_t i = 0; i < active_input_method_ids_.size(); ++i) { | 420 for (size_t i = 0; i < active_input_method_ids.size(); ++i) { |
497 if (extension_id != extension_ime_util::GetExtensionIDFromInputMethodID( | 421 if (extension_id != extension_ime_util::GetExtensionIDFromInputMethodID( |
498 active_input_method_ids_[i])) | 422 active_input_method_ids[i])) |
499 new_active_input_method_ids.push_back(active_input_method_ids_[i]); | 423 new_active_input_method_ids.push_back(active_input_method_ids[i]); |
500 } | 424 } |
501 active_input_method_ids_.swap(new_active_input_method_ids); | 425 active_input_method_ids.swap(new_active_input_method_ids); |
502 | 426 |
503 // Remove the extra input methods with |extension_id|. | 427 // Remove the extra input methods with |extension_id|. |
504 std::map<std::string, InputMethodDescriptor> new_extra_input_methods; | 428 std::map<std::string, InputMethodDescriptor> new_extra_input_methods; |
505 for (std::map<std::string, InputMethodDescriptor>::iterator i = | 429 for (std::map<std::string, InputMethodDescriptor>::iterator i = |
506 extra_input_methods_.begin(); | 430 extra_input_methods.begin(); |
507 i != extra_input_methods_.end(); | 431 i != extra_input_methods.end(); |
508 ++i) { | 432 ++i) { |
509 if (extension_id != | 433 if (extension_id != |
510 extension_ime_util::GetExtensionIDFromInputMethodID(i->first)) | 434 extension_ime_util::GetExtensionIDFromInputMethodID(i->first)) |
511 new_extra_input_methods[i->first] = i->second; | 435 new_extra_input_methods[i->first] = i->second; |
512 } | 436 } |
513 extra_input_methods_.swap(new_extra_input_methods); | 437 extra_input_methods.swap(new_extra_input_methods); |
514 | 438 |
515 if (IMEBridge::Get()->GetCurrentEngineHandler() == engine_map_[extension_id]) | 439 if (IsActive()) { |
516 IMEBridge::Get()->SetCurrentEngineHandler(NULL); | 440 if (IMEBridge::Get()->GetCurrentEngineHandler() == |
517 engine_map_.erase(extension_id); | 441 manager_->engine_map_[extension_id]) { |
| 442 IMEBridge::Get()->SetCurrentEngineHandler(NULL); |
| 443 } |
| 444 manager_->engine_map_.erase(extension_id); |
| 445 } |
518 | 446 |
519 // No need to switch input method when terminating. | 447 // If |current_input_method| is no longer in |active_input_method_ids|, |
520 if (state_ != STATE_TERMINATING) { | 448 // switch to the first one in |active_input_method_ids|. |
521 // If |current_input_method| is no longer in |active_input_method_ids_|, | 449 ChangeInputMethod(current_input_method.id(), false); |
522 // switch to the first one in |active_input_method_ids_|. | |
523 ChangeInputMethod(current_input_method_.id()); | |
524 } | |
525 } | 450 } |
526 | 451 |
527 void InputMethodManagerImpl::GetInputMethodExtensions( | 452 void InputMethodManagerImpl::StateImpl::GetInputMethodExtensions( |
528 InputMethodDescriptors* result) { | 453 InputMethodDescriptors* result) { |
529 // Build the extension input method descriptors from the extra input | 454 // Build the extension input method descriptors from the extra input |
530 // methods cache |extra_input_methods_|. | 455 // methods cache |extra_input_methods|. |
531 std::map<std::string, InputMethodDescriptor>::iterator iter; | 456 std::map<std::string, InputMethodDescriptor>::iterator iter; |
532 for (iter = extra_input_methods_.begin(); iter != extra_input_methods_.end(); | 457 for (iter = extra_input_methods.begin(); iter != extra_input_methods.end(); |
533 ++iter) { | 458 ++iter) { |
534 if (extension_ime_util::IsExtensionIME(iter->first)) | 459 if (extension_ime_util::IsExtensionIME(iter->first)) |
535 result->push_back(iter->second); | 460 result->push_back(iter->second); |
536 } | 461 } |
537 } | 462 } |
538 | 463 |
539 void InputMethodManagerImpl::SetEnabledExtensionImes( | 464 void InputMethodManagerImpl::StateImpl::SetEnabledExtensionImes( |
540 std::vector<std::string>* ids) { | 465 std::vector<std::string>* ids) { |
541 enabled_extension_imes_.clear(); | 466 enabled_extension_imes.clear(); |
542 enabled_extension_imes_.insert(enabled_extension_imes_.end(), | 467 enabled_extension_imes.insert( |
543 ids->begin(), | 468 enabled_extension_imes.end(), ids->begin(), ids->end()); |
544 ids->end()); | |
545 | |
546 bool active_imes_changed = false; | 469 bool active_imes_changed = false; |
547 bool switch_to_pending = false; | 470 bool switch_to_pending = false; |
548 | 471 |
549 for (std::map<std::string, InputMethodDescriptor>::iterator extra_iter = | 472 for (std::map<std::string, InputMethodDescriptor>::iterator extra_iter = |
550 extra_input_methods_.begin(); extra_iter != extra_input_methods_.end(); | 473 extra_input_methods.begin(); |
| 474 extra_iter != extra_input_methods.end(); |
551 ++extra_iter) { | 475 ++extra_iter) { |
552 if (extension_ime_util::IsComponentExtensionIME( | 476 if (extension_ime_util::IsComponentExtensionIME(extra_iter->first)) |
553 extra_iter->first)) | |
554 continue; // Do not filter component extension. | 477 continue; // Do not filter component extension. |
555 | 478 |
556 if (pending_input_method_id_ == extra_iter->first) | 479 if (pending_input_method_id == extra_iter->first) |
557 switch_to_pending = true; | 480 switch_to_pending = true; |
558 | 481 |
559 std::vector<std::string>::iterator active_iter = std::find( | 482 std::vector<std::string>::iterator active_iter = |
560 active_input_method_ids_.begin(), active_input_method_ids_.end(), | 483 std::find(active_input_method_ids.begin(), |
561 extra_iter->first); | 484 active_input_method_ids.end(), |
| 485 extra_iter->first); |
562 | 486 |
563 bool active = active_iter != active_input_method_ids_.end(); | 487 bool active = active_iter != active_input_method_ids.end(); |
564 bool enabled = Contains(enabled_extension_imes_, extra_iter->first); | 488 bool enabled = Contains(enabled_extension_imes, extra_iter->first); |
565 | 489 |
566 if (active && !enabled) | 490 if (active && !enabled) |
567 active_input_method_ids_.erase(active_iter); | 491 active_input_method_ids.erase(active_iter); |
568 | 492 |
569 if (!active && enabled) | 493 if (!active && enabled) |
570 active_input_method_ids_.push_back(extra_iter->first); | 494 active_input_method_ids.push_back(extra_iter->first); |
571 | 495 |
572 if (active == !enabled) | 496 if (active == !enabled) |
573 active_imes_changed = true; | 497 active_imes_changed = true; |
574 } | 498 } |
575 | 499 |
576 if (active_imes_changed) { | 500 if (IsActive() && active_imes_changed) { |
577 MaybeInitializeCandidateWindowController(); | 501 manager_->MaybeInitializeCandidateWindowController(); |
578 | 502 |
579 if (switch_to_pending) { | 503 if (switch_to_pending) { |
580 ChangeInputMethod(pending_input_method_id_); | 504 ChangeInputMethod(pending_input_method_id, false); |
581 pending_input_method_id_.clear(); | 505 pending_input_method_id.clear(); |
582 } else { | 506 } else { |
583 // If |current_input_method| is no longer in |active_input_method_ids_|, | 507 // If |current_input_method| is no longer in |active_input_method_ids_|, |
584 // switch to the first one in |active_input_method_ids_|. | 508 // switch to the first one in |active_input_method_ids_|. |
585 ChangeInputMethod(current_input_method_.id()); | 509 ChangeInputMethod(current_input_method.id(), false); |
586 } | 510 } |
587 } | 511 } |
588 } | 512 } |
589 | 513 |
590 void InputMethodManagerImpl::SetInputMethodLoginDefaultFromVPD( | 514 void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefaultFromVPD( |
591 const std::string& locale, const std::string& oem_layout) { | 515 const std::string& locale, |
| 516 const std::string& oem_layout) { |
592 std::string layout; | 517 std::string layout; |
593 if (!oem_layout.empty()) { | 518 if (!oem_layout.empty()) { |
594 // If the OEM layout information is provided, use it. | 519 // If the OEM layout information is provided, use it. |
595 layout = oem_layout; | 520 layout = oem_layout; |
596 } else { | 521 } else { |
597 // Otherwise, determine the hardware keyboard from the locale. | 522 // Otherwise, determine the hardware keyboard from the locale. |
598 std::vector<std::string> input_method_ids; | 523 std::vector<std::string> input_method_ids; |
599 if (util_.GetInputMethodIdsFromLanguageCode( | 524 if (manager_->util_.GetInputMethodIdsFromLanguageCode( |
600 locale, | 525 locale, |
601 chromeos::input_method::kKeyboardLayoutsOnly, | 526 chromeos::input_method::kKeyboardLayoutsOnly, |
602 &input_method_ids)) { | 527 &input_method_ids)) { |
603 // The output list |input_method_ids| is sorted by popularity, hence | 528 // The output list |input_method_ids| is sorted by popularity, hence |
604 // input_method_ids[0] now contains the most popular keyboard layout | 529 // input_method_ids[0] now contains the most popular keyboard layout |
605 // for the given locale. | 530 // for the given locale. |
606 DCHECK_GE(input_method_ids.size(), 1U); | 531 DCHECK_GE(input_method_ids.size(), 1U); |
607 layout = input_method_ids[0]; | 532 layout = input_method_ids[0]; |
608 } | 533 } |
609 } | 534 } |
610 | 535 |
611 if (layout.empty()) | 536 if (layout.empty()) |
612 return; | 537 return; |
613 | 538 |
614 std::vector<std::string> layouts; | 539 std::vector<std::string> layouts; |
615 base::SplitString(layout, ',', &layouts); | 540 base::SplitString(layout, ',', &layouts); |
616 MigrateInputMethods(&layouts); | 541 manager_->MigrateInputMethods(&layouts); |
617 | 542 |
618 PrefService* prefs = g_browser_process->local_state(); | 543 PrefService* prefs = g_browser_process->local_state(); |
619 prefs->SetString(prefs::kHardwareKeyboardLayout, JoinString(layouts, ",")); | 544 prefs->SetString(prefs::kHardwareKeyboardLayout, JoinString(layouts, ",")); |
620 | 545 |
621 // This asks the file thread to save the prefs (i.e. doesn't block). | 546 // This asks the file thread to save the prefs (i.e. doesn't block). |
622 // The latest values of Local State reside in memory so we can safely | 547 // The latest values of Local State reside in memory so we can safely |
623 // get the value of kHardwareKeyboardLayout even if the data is not | 548 // get the value of kHardwareKeyboardLayout even if the data is not |
624 // yet saved to disk. | 549 // yet saved to disk. |
625 prefs->CommitPendingWrite(); | 550 prefs->CommitPendingWrite(); |
626 | 551 |
627 util_.UpdateHardwareLayoutCache(); | 552 manager_->util_.UpdateHardwareLayoutCache(); |
628 | 553 |
629 EnableLoginLayouts(locale, layouts); | 554 EnableLoginLayouts(locale, layouts); |
630 LoadNecessaryComponentExtensions(); | 555 manager_->LoadNecessaryComponentExtensions(this); |
631 } | 556 } |
632 | 557 |
633 void InputMethodManagerImpl::SetInputMethodLoginDefault() { | 558 void InputMethodManagerImpl::StateImpl::SetInputMethodLoginDefault() { |
634 // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty | 559 // Set up keyboards. For example, when |locale| is "en-US", enable US qwerty |
635 // and US dvorak keyboard layouts. | 560 // and US dvorak keyboard layouts. |
636 if (g_browser_process && g_browser_process->local_state()) { | 561 if (g_browser_process && g_browser_process->local_state()) { |
637 const std::string locale = g_browser_process->GetApplicationLocale(); | 562 const std::string locale = g_browser_process->GetApplicationLocale(); |
638 // If the preferred keyboard for the login screen has been saved, use it. | 563 // If the preferred keyboard for the login screen has been saved, use it. |
639 PrefService* prefs = g_browser_process->local_state(); | 564 PrefService* prefs = g_browser_process->local_state(); |
640 std::string initial_input_method_id = | 565 std::string initial_input_method_id = |
641 prefs->GetString(chromeos::language_prefs::kPreferredKeyboardLayout); | 566 prefs->GetString(chromeos::language_prefs::kPreferredKeyboardLayout); |
642 std::vector<std::string> input_methods_to_be_enabled; | 567 std::vector<std::string> input_methods_to_be_enabled; |
643 if (initial_input_method_id.empty()) { | 568 if (initial_input_method_id.empty()) { |
644 // If kPreferredKeyboardLayout is not specified, use the hardware layout. | 569 // If kPreferredKeyboardLayout is not specified, use the hardware layout. |
645 input_methods_to_be_enabled = util_.GetHardwareLoginInputMethodIds(); | 570 input_methods_to_be_enabled = |
| 571 manager_->util_.GetHardwareLoginInputMethodIds(); |
646 } else { | 572 } else { |
647 input_methods_to_be_enabled.push_back(initial_input_method_id); | 573 input_methods_to_be_enabled.push_back(initial_input_method_id); |
648 } | 574 } |
649 EnableLoginLayouts(locale, input_methods_to_be_enabled); | 575 EnableLoginLayouts(locale, input_methods_to_be_enabled); |
650 LoadNecessaryComponentExtensions(); | 576 manager_->LoadNecessaryComponentExtensions(this); |
651 } | 577 } |
652 } | 578 } |
653 | 579 |
654 bool InputMethodManagerImpl::SwitchToNextInputMethod() { | 580 bool InputMethodManagerImpl::StateImpl::SwitchToNextInputMethod() { |
655 // Sanity checks. | 581 // Sanity checks. |
656 if (active_input_method_ids_.empty()) { | 582 if (active_input_method_ids.empty()) { |
657 DVLOG(1) << "active input method is empty"; | 583 DVLOG(1) << "active input method is empty"; |
658 return false; | 584 return false; |
659 } | 585 } |
660 | 586 |
661 if (current_input_method_.id().empty()) { | 587 if (current_input_method.id().empty()) { |
662 DVLOG(1) << "current_input_method_ is unknown"; | 588 DVLOG(1) << "current_input_method is unknown"; |
663 return false; | 589 return false; |
664 } | 590 } |
665 | 591 |
666 // Do not consume key event if there is only one input method is enabled. | 592 // Do not consume key event if there is only one input method is enabled. |
667 // Ctrl+Space or Alt+Shift may be used by other application. | 593 // Ctrl+Space or Alt+Shift may be used by other application. |
668 if (active_input_method_ids_.size() == 1) | 594 if (active_input_method_ids.size() == 1) |
669 return false; | 595 return false; |
670 | 596 |
671 // Find the next input method and switch to it. | 597 // Find the next input method and switch to it. |
672 SwitchToNextInputMethodInternal(active_input_method_ids_, | 598 SwitchToNextInputMethodInternal(active_input_method_ids, |
673 current_input_method_.id()); | 599 current_input_method.id()); |
674 return true; | 600 return true; |
675 } | 601 } |
676 | 602 |
677 bool InputMethodManagerImpl::SwitchToPreviousInputMethod( | 603 bool InputMethodManagerImpl::StateImpl::SwitchToPreviousInputMethod( |
678 const ui::Accelerator& accelerator) { | 604 const ui::Accelerator& accelerator) { |
679 // Sanity check. | 605 // Sanity check. |
680 if (active_input_method_ids_.empty()) { | 606 if (active_input_method_ids.empty()) { |
681 DVLOG(1) << "active input method is empty"; | 607 DVLOG(1) << "active input method is empty"; |
682 return false; | 608 return false; |
683 } | 609 } |
684 | 610 |
685 // Do not consume key event if there is only one input method is enabled. | 611 // Do not consume key event if there is only one input method is enabled. |
686 // Ctrl+Space or Alt+Shift may be used by other application. | 612 // Ctrl+Space or Alt+Shift may be used by other application. |
687 if (active_input_method_ids_.size() == 1) | 613 if (active_input_method_ids.size() == 1) |
688 return false; | 614 return false; |
689 | 615 |
690 if (accelerator.type() == ui::ET_KEY_RELEASED) | 616 if (accelerator.type() == ui::ET_KEY_RELEASED) |
691 return true; | 617 return true; |
692 | 618 |
693 if (previous_input_method_.id().empty() || | 619 if (previous_input_method.id().empty() || |
694 previous_input_method_.id() == current_input_method_.id()) { | 620 previous_input_method.id() == current_input_method.id()) { |
695 return SwitchToNextInputMethod(); | 621 return SwitchToNextInputMethod(); |
696 } | 622 } |
697 | 623 |
698 std::vector<std::string>::const_iterator iter = | 624 std::vector<std::string>::const_iterator iter = |
699 std::find(active_input_method_ids_.begin(), | 625 std::find(active_input_method_ids.begin(), |
700 active_input_method_ids_.end(), | 626 active_input_method_ids.end(), |
701 previous_input_method_.id()); | 627 previous_input_method.id()); |
702 if (iter == active_input_method_ids_.end()) { | 628 if (iter == active_input_method_ids.end()) { |
703 // previous_input_method_ is not supported. | 629 // previous_input_method is not supported. |
704 return SwitchToNextInputMethod(); | 630 return SwitchToNextInputMethod(); |
705 } | 631 } |
706 ChangeInputMethodInternal(*iter, true); | 632 ChangeInputMethod(*iter, true); |
| 633 |
707 return true; | 634 return true; |
708 } | 635 } |
709 | 636 |
710 bool InputMethodManagerImpl::SwitchInputMethod( | 637 bool InputMethodManagerImpl::StateImpl::SwitchInputMethod( |
711 const ui::Accelerator& accelerator) { | 638 const ui::Accelerator& accelerator) { |
712 // Sanity check. | 639 // Sanity check. |
713 if (active_input_method_ids_.empty()) { | 640 if (active_input_method_ids.empty()) { |
714 DVLOG(1) << "active input method is empty"; | 641 DVLOG(1) << "active input method is empty"; |
715 return false; | 642 return false; |
716 } | 643 } |
717 | 644 |
718 // Get the list of input method ids for the |accelerator|. For example, get | 645 // Get the list of input method ids for the |accelerator|. For example, get |
719 // { "mozc-hangul", "xkb:kr:kr104:kor" } for ui::VKEY_DBE_SBCSCHAR. | 646 // { "mozc-hangul", "xkb:kr:kr104:kor" } for ui::VKEY_DBE_SBCSCHAR. |
720 std::vector<std::string> input_method_ids_to_switch; | 647 std::vector<std::string> input_method_ids_to_switch; |
721 switch (accelerator.key_code()) { | 648 switch (accelerator.key_code()) { |
722 case ui::VKEY_CONVERT: // Henkan key on JP106 keyboard | 649 case ui::VKEY_CONVERT: // Henkan key on JP106 keyboard |
723 input_method_ids_to_switch.push_back( | 650 input_method_ids_to_switch.push_back( |
(...skipping 13 matching lines...) Expand all Loading... |
737 default: | 664 default: |
738 NOTREACHED(); | 665 NOTREACHED(); |
739 break; | 666 break; |
740 } | 667 } |
741 if (input_method_ids_to_switch.empty()) { | 668 if (input_method_ids_to_switch.empty()) { |
742 DVLOG(1) << "Unexpected VKEY: " << accelerator.key_code(); | 669 DVLOG(1) << "Unexpected VKEY: " << accelerator.key_code(); |
743 return false; | 670 return false; |
744 } | 671 } |
745 | 672 |
746 // Obtain the intersection of input_method_ids_to_switch and | 673 // Obtain the intersection of input_method_ids_to_switch and |
747 // active_input_method_ids_. The order of IDs in active_input_method_ids_ is | 674 // active_input_method_ids. The order of IDs in active_input_method_ids is |
748 // preserved. | 675 // preserved. |
749 std::vector<std::string> ids; | 676 std::vector<std::string> ids; |
750 for (size_t i = 0; i < input_method_ids_to_switch.size(); ++i) { | 677 for (size_t i = 0; i < input_method_ids_to_switch.size(); ++i) { |
751 const std::string& id = input_method_ids_to_switch[i]; | 678 const std::string& id = input_method_ids_to_switch[i]; |
752 if (Contains(active_input_method_ids_, id)) | 679 if (Contains(active_input_method_ids, id)) |
753 ids.push_back(id); | 680 ids.push_back(id); |
754 } | 681 } |
755 if (ids.empty()) { | 682 if (ids.empty()) { |
756 // No input method for the accelerator is active. For example, we should | 683 // No input method for the accelerator is active. For example, we should |
757 // just ignore VKEY_HANGUL when mozc-hangul is not active. | 684 // just ignore VKEY_HANGUL when mozc-hangul is not active. |
758 return false; | 685 return false; |
759 } | 686 } |
760 | 687 |
761 SwitchToNextInputMethodInternal(ids, current_input_method_.id()); | 688 SwitchToNextInputMethodInternal(ids, current_input_method.id()); |
762 return true; // consume the accelerator. | 689 return true; // consume the accelerator. |
763 } | 690 } |
764 | 691 |
765 void InputMethodManagerImpl::SwitchToNextInputMethodInternal( | 692 void InputMethodManagerImpl::StateImpl::SwitchToNextInputMethodInternal( |
766 const std::vector<std::string>& input_method_ids, | 693 const std::vector<std::string>& input_method_ids, |
767 const std::string& current_input_method_id) { | 694 const std::string& current_input_methodid) { |
768 std::vector<std::string>::const_iterator iter = | 695 std::vector<std::string>::const_iterator iter = std::find( |
769 std::find(input_method_ids.begin(), | 696 input_method_ids.begin(), input_method_ids.end(), current_input_methodid); |
770 input_method_ids.end(), | |
771 current_input_method_id); | |
772 if (iter != input_method_ids.end()) | 697 if (iter != input_method_ids.end()) |
773 ++iter; | 698 ++iter; |
774 if (iter == input_method_ids.end()) | 699 if (iter == input_method_ids.end()) |
775 iter = input_method_ids.begin(); | 700 iter = input_method_ids.begin(); |
776 ChangeInputMethodInternal(*iter, true); | 701 ChangeInputMethod(*iter, true); |
777 } | 702 } |
778 | 703 |
779 InputMethodDescriptor InputMethodManagerImpl::GetCurrentInputMethod() const { | 704 InputMethodDescriptor InputMethodManagerImpl::StateImpl::GetCurrentInputMethod() |
780 if (current_input_method_.id().empty()) | 705 const { |
| 706 if (current_input_method.id().empty()) |
781 return InputMethodUtil::GetFallbackInputMethodDescriptor(); | 707 return InputMethodUtil::GetFallbackInputMethodDescriptor(); |
782 | 708 |
783 return current_input_method_; | 709 return current_input_method; |
| 710 } |
| 711 |
| 712 bool InputMethodManagerImpl::StateImpl::InputMethodIsActivated( |
| 713 const std::string& input_method_id) const { |
| 714 return Contains(active_input_method_ids, input_method_id); |
| 715 } |
| 716 |
| 717 // ------------------------ InputMethodManagerImpl |
| 718 bool InputMethodManagerImpl::IsLoginKeyboard( |
| 719 const std::string& layout) const { |
| 720 return util_.IsLoginKeyboard(layout); |
| 721 } |
| 722 |
| 723 bool InputMethodManagerImpl::MigrateInputMethods( |
| 724 std::vector<std::string>* input_method_ids) { |
| 725 return util_.MigrateInputMethods(input_method_ids); |
| 726 } |
| 727 |
| 728 // Starts or stops the system input method framework as needed. |
| 729 void InputMethodManagerImpl::ReconfigureIMFramework( |
| 730 InputMethodManagerImpl::StateImpl* state) { |
| 731 LoadNecessaryComponentExtensions(state); |
| 732 |
| 733 // Initialize candidate window controller and widgets such as |
| 734 // candidate window, infolist and mode indicator. Note, mode |
| 735 // indicator is used by only keyboard layout input methods. |
| 736 if (state_.get() == state) |
| 737 MaybeInitializeCandidateWindowController(); |
| 738 } |
| 739 |
| 740 void InputMethodManagerImpl::SetState( |
| 741 scoped_refptr<InputMethodManager::State> state) { |
| 742 DCHECK(state); |
| 743 InputMethodManagerImpl::StateImpl* new_impl_state = |
| 744 static_cast<InputMethodManagerImpl::StateImpl*>(state.get()); |
| 745 const bool need_update_current_input_method = |
| 746 (state_ ? state_->current_input_method.id() != |
| 747 new_impl_state->current_input_method.id() |
| 748 : true); |
| 749 state_ = new_impl_state; |
| 750 |
| 751 if (state_ && state_->active_input_method_ids.size()) { |
| 752 // Initialize candidate window controller and widgets such as |
| 753 // candidate window, infolist and mode indicator. Note, mode |
| 754 // indicator is used by only keyboard layout input methods. |
| 755 MaybeInitializeCandidateWindowController(); |
| 756 |
| 757 if (need_update_current_input_method) |
| 758 ChangeInputMethodInternal(state_->current_input_method, |
| 759 false /* show_message */, |
| 760 true /* notify_menu */); |
| 761 } |
| 762 } |
| 763 |
| 764 scoped_refptr<InputMethodManager::State> |
| 765 InputMethodManagerImpl::GetActiveIMEState() { |
| 766 return scoped_refptr<InputMethodManager::State>(state_.get()); |
| 767 } |
| 768 |
| 769 InputMethodManagerImpl::InputMethodManagerImpl( |
| 770 scoped_ptr<InputMethodDelegate> delegate, |
| 771 bool enable_extension_loading) |
| 772 : delegate_(delegate.Pass()), |
| 773 ui_session_(STATE_LOGIN_SCREEN), |
| 774 state_(NULL), |
| 775 util_(delegate_.get()), |
| 776 component_extension_ime_manager_(new ComponentExtensionIMEManager()), |
| 777 enable_extension_loading_(enable_extension_loading) { |
| 778 if (base::SysInfo::IsRunningOnChromeOS()) |
| 779 keyboard_.reset(ImeKeyboard::Create()); |
| 780 else |
| 781 keyboard_.reset(new FakeImeKeyboard()); |
| 782 |
| 783 // Initializes the system IME list. |
| 784 scoped_ptr<ComponentExtensionIMEManagerDelegate> comp_delegate( |
| 785 new ComponentExtensionIMEManagerImpl()); |
| 786 component_extension_ime_manager_->Initialize(comp_delegate.Pass()); |
| 787 util_.ResetInputMethods( |
| 788 component_extension_ime_manager_->GetAllIMEAsInputMethodDescriptor()); |
| 789 } |
| 790 |
| 791 InputMethodManagerImpl::~InputMethodManagerImpl() { |
| 792 if (candidate_window_controller_.get()) |
| 793 candidate_window_controller_->RemoveObserver(this); |
| 794 } |
| 795 |
| 796 void InputMethodManagerImpl::AddObserver( |
| 797 InputMethodManager::Observer* observer) { |
| 798 observers_.AddObserver(observer); |
| 799 } |
| 800 |
| 801 void InputMethodManagerImpl::AddCandidateWindowObserver( |
| 802 InputMethodManager::CandidateWindowObserver* observer) { |
| 803 candidate_window_observers_.AddObserver(observer); |
| 804 } |
| 805 |
| 806 void InputMethodManagerImpl::RemoveObserver( |
| 807 InputMethodManager::Observer* observer) { |
| 808 observers_.RemoveObserver(observer); |
| 809 } |
| 810 |
| 811 void InputMethodManagerImpl::RemoveCandidateWindowObserver( |
| 812 InputMethodManager::CandidateWindowObserver* observer) { |
| 813 candidate_window_observers_.RemoveObserver(observer); |
| 814 } |
| 815 |
| 816 InputMethodManager::UISessionState InputMethodManagerImpl::GetUISessionState() { |
| 817 return ui_session_; |
| 818 } |
| 819 |
| 820 void InputMethodManagerImpl::SetUISessionState(UISessionState new_ui_session) { |
| 821 ui_session_ = new_ui_session; |
| 822 switch (ui_session_) { |
| 823 case STATE_LOGIN_SCREEN: |
| 824 break; |
| 825 case STATE_BROWSER_SCREEN: |
| 826 break; |
| 827 case STATE_LOCK_SCREEN: |
| 828 break; |
| 829 case STATE_TERMINATING: { |
| 830 if (candidate_window_controller_.get()) |
| 831 candidate_window_controller_.reset(); |
| 832 break; |
| 833 } |
| 834 } |
| 835 } |
| 836 |
| 837 scoped_ptr<InputMethodDescriptors> |
| 838 InputMethodManagerImpl::GetSupportedInputMethods() const { |
| 839 return scoped_ptr<InputMethodDescriptors>(new InputMethodDescriptors).Pass(); |
| 840 } |
| 841 |
| 842 const InputMethodDescriptor* InputMethodManagerImpl::LookupInputMethod( |
| 843 const std::string& input_method_id, |
| 844 InputMethodManagerImpl::StateImpl* state) { |
| 845 DCHECK(state); |
| 846 |
| 847 std::string input_method_id_to_switch = input_method_id; |
| 848 |
| 849 // Sanity check |
| 850 if (!state->InputMethodIsActivated(input_method_id)) { |
| 851 scoped_ptr<InputMethodDescriptors> input_methods( |
| 852 state->GetActiveInputMethods()); |
| 853 DCHECK(!input_methods->empty()); |
| 854 input_method_id_to_switch = input_methods->at(0).id(); |
| 855 if (!input_method_id.empty()) { |
| 856 DVLOG(1) << "Can't change the current input method to " |
| 857 << input_method_id << " since the engine is not enabled. " |
| 858 << "Switch to " << input_method_id_to_switch << " instead."; |
| 859 } |
| 860 } |
| 861 |
| 862 const InputMethodDescriptor* descriptor = NULL; |
| 863 if (extension_ime_util::IsExtensionIME(input_method_id_to_switch)) { |
| 864 DCHECK(state->extra_input_methods.find(input_method_id_to_switch) != |
| 865 state->extra_input_methods.end()); |
| 866 descriptor = &(state->extra_input_methods[input_method_id_to_switch]); |
| 867 } else { |
| 868 descriptor = |
| 869 util_.GetInputMethodDescriptorFromId(input_method_id_to_switch); |
| 870 if (!descriptor) |
| 871 LOG(ERROR) << "Unknown input method id: " << input_method_id_to_switch; |
| 872 } |
| 873 DCHECK(descriptor); |
| 874 return descriptor; |
| 875 } |
| 876 |
| 877 void InputMethodManagerImpl::ChangeInputMethodInternal( |
| 878 const InputMethodDescriptor& descriptor, |
| 879 bool show_message, |
| 880 bool notify_menu) { |
| 881 // No need to switch input method when terminating. |
| 882 if (ui_session_ == STATE_TERMINATING) |
| 883 return; |
| 884 |
| 885 if (candidate_window_controller_.get()) |
| 886 candidate_window_controller_->Hide(); |
| 887 |
| 888 if (notify_menu) { |
| 889 // Clear property list. Property list would be updated by |
| 890 // extension IMEs via InputMethodEngine::(Set|Update)MenuItems. |
| 891 // If the current input method is a keyboard layout, empty |
| 892 // properties are sufficient. |
| 893 const ash::ime::InputMethodMenuItemList empty_menu_item_list; |
| 894 ash::ime::InputMethodMenuManager* input_method_menu_manager = |
| 895 ash::ime::InputMethodMenuManager::GetInstance(); |
| 896 input_method_menu_manager->SetCurrentInputMethodMenuItemList( |
| 897 empty_menu_item_list); |
| 898 } |
| 899 |
| 900 // Disable the current engine handler. |
| 901 IMEEngineHandlerInterface* engine = |
| 902 IMEBridge::Get()->GetCurrentEngineHandler(); |
| 903 if (engine) |
| 904 engine->Disable(); |
| 905 |
| 906 // Configure the next engine handler. |
| 907 // This must be after |current_input_method| has been set to new input |
| 908 // method, because engine's Enable() method needs to access it. |
| 909 const std::string& extension_id = |
| 910 extension_ime_util::GetExtensionIDFromInputMethodID(descriptor.id()); |
| 911 const std::string& component_id = |
| 912 extension_ime_util::GetComponentIDByInputMethodID(descriptor.id()); |
| 913 engine = engine_map_[extension_id]; |
| 914 |
| 915 IMEBridge::Get()->SetCurrentEngineHandler(engine); |
| 916 |
| 917 if (engine) |
| 918 engine->Enable(component_id); |
| 919 |
| 920 // Change the keyboard layout to a preferred layout for the input method. |
| 921 if (!keyboard_->SetCurrentKeyboardLayoutByName( |
| 922 descriptor.GetPreferredKeyboardLayout())) { |
| 923 LOG(ERROR) << "Failed to change keyboard layout to " |
| 924 << descriptor.GetPreferredKeyboardLayout(); |
| 925 } |
| 926 |
| 927 // Update input method indicators (e.g. "US", "DV") in Chrome windows. |
| 928 FOR_EACH_OBSERVER(InputMethodManager::Observer, |
| 929 observers_, |
| 930 InputMethodChanged(this, show_message)); |
| 931 } |
| 932 |
| 933 void InputMethodManagerImpl::LoadNecessaryComponentExtensions( |
| 934 InputMethodManagerImpl::StateImpl* state) { |
| 935 // Load component extensions but also update |active_input_method_ids| as |
| 936 // some component extension IMEs may have been removed from the Chrome OS |
| 937 // image. If specified component extension IME no longer exists, falling back |
| 938 // to an existing IME. |
| 939 DCHECK(state); |
| 940 std::vector<std::string> unfiltered_input_method_ids; |
| 941 unfiltered_input_method_ids.swap(state->active_input_method_ids); |
| 942 for (size_t i = 0; i < unfiltered_input_method_ids.size(); ++i) { |
| 943 if (!extension_ime_util::IsComponentExtensionIME( |
| 944 unfiltered_input_method_ids[i])) { |
| 945 // Legacy IMEs or xkb layouts are alwayes active. |
| 946 state->active_input_method_ids.push_back(unfiltered_input_method_ids[i]); |
| 947 } else if (component_extension_ime_manager_->IsWhitelisted( |
| 948 unfiltered_input_method_ids[i])) { |
| 949 if (enable_extension_loading_) { |
| 950 component_extension_ime_manager_->LoadComponentExtensionIME( |
| 951 state->profile, unfiltered_input_method_ids[i]); |
| 952 } |
| 953 |
| 954 state->active_input_method_ids.push_back(unfiltered_input_method_ids[i]); |
| 955 } |
| 956 } |
| 957 } |
| 958 |
| 959 void InputMethodManagerImpl::ActivateInputMethodMenuItem( |
| 960 const std::string& key) { |
| 961 DCHECK(!key.empty()); |
| 962 |
| 963 if (ash::ime::InputMethodMenuManager::GetInstance()-> |
| 964 HasInputMethodMenuItemForKey(key)) { |
| 965 IMEEngineHandlerInterface* engine = |
| 966 IMEBridge::Get()->GetCurrentEngineHandler(); |
| 967 if (engine) |
| 968 engine->PropertyActivate(key); |
| 969 return; |
| 970 } |
| 971 |
| 972 DVLOG(1) << "ActivateInputMethodMenuItem: unknown key: " << key; |
784 } | 973 } |
785 | 974 |
786 bool InputMethodManagerImpl::IsISOLevel5ShiftUsedByCurrentInputMethod() const { | 975 bool InputMethodManagerImpl::IsISOLevel5ShiftUsedByCurrentInputMethod() const { |
787 return keyboard_->IsISOLevel5ShiftAvailable(); | 976 return keyboard_->IsISOLevel5ShiftAvailable(); |
788 } | 977 } |
789 | 978 |
790 bool InputMethodManagerImpl::IsAltGrUsedByCurrentInputMethod() const { | 979 bool InputMethodManagerImpl::IsAltGrUsedByCurrentInputMethod() const { |
791 return keyboard_->IsAltGrAvailable(); | 980 return keyboard_->IsAltGrAvailable(); |
792 } | 981 } |
793 | 982 |
794 ImeKeyboard* InputMethodManagerImpl::GetImeKeyboard() { | 983 ImeKeyboard* InputMethodManagerImpl::GetImeKeyboard() { |
795 return keyboard_.get(); | 984 return keyboard_.get(); |
796 } | 985 } |
797 | 986 |
798 InputMethodUtil* InputMethodManagerImpl::GetInputMethodUtil() { | 987 InputMethodUtil* InputMethodManagerImpl::GetInputMethodUtil() { |
799 return &util_; | 988 return &util_; |
800 } | 989 } |
801 | 990 |
802 ComponentExtensionIMEManager* | 991 ComponentExtensionIMEManager* |
803 InputMethodManagerImpl::GetComponentExtensionIMEManager() { | 992 InputMethodManagerImpl::GetComponentExtensionIMEManager() { |
804 return component_extension_ime_manager_.get(); | 993 return component_extension_ime_manager_.get(); |
805 } | 994 } |
806 | 995 |
| 996 scoped_refptr<InputMethodManager::State> InputMethodManagerImpl::CreateNewState( |
| 997 Profile* profile) { |
| 998 return scoped_refptr<InputMethodManager::State>(new StateImpl(this, profile)); |
| 999 } |
| 1000 |
807 void InputMethodManagerImpl::SetCandidateWindowControllerForTesting( | 1001 void InputMethodManagerImpl::SetCandidateWindowControllerForTesting( |
808 CandidateWindowController* candidate_window_controller) { | 1002 CandidateWindowController* candidate_window_controller) { |
809 candidate_window_controller_.reset(candidate_window_controller); | 1003 candidate_window_controller_.reset(candidate_window_controller); |
810 candidate_window_controller_->AddObserver(this); | 1004 candidate_window_controller_->AddObserver(this); |
811 } | 1005 } |
812 | 1006 |
813 void InputMethodManagerImpl::SetImeKeyboardForTesting(ImeKeyboard* keyboard) { | 1007 void InputMethodManagerImpl::SetImeKeyboardForTesting(ImeKeyboard* keyboard) { |
814 keyboard_.reset(keyboard); | 1008 keyboard_.reset(keyboard); |
815 } | 1009 } |
816 | 1010 |
(...skipping 16 matching lines...) Expand all Loading... |
833 candidate_window_observers_, | 1027 candidate_window_observers_, |
834 CandidateWindowOpened(this)); | 1028 CandidateWindowOpened(this)); |
835 } | 1029 } |
836 | 1030 |
837 void InputMethodManagerImpl::CandidateWindowClosed() { | 1031 void InputMethodManagerImpl::CandidateWindowClosed() { |
838 FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver, | 1032 FOR_EACH_OBSERVER(InputMethodManager::CandidateWindowObserver, |
839 candidate_window_observers_, | 1033 candidate_window_observers_, |
840 CandidateWindowClosed(this)); | 1034 CandidateWindowClosed(this)); |
841 } | 1035 } |
842 | 1036 |
843 void InputMethodManagerImpl::OnScreenLocked() { | |
844 saved_previous_input_method_ = previous_input_method_; | |
845 saved_current_input_method_ = current_input_method_; | |
846 saved_active_input_method_ids_ = active_input_method_ids_; | |
847 | |
848 std::set<std::string> added_ids_; | |
849 | |
850 const std::vector<std::string>& hardware_keyboard_ids = | |
851 util_.GetHardwareLoginInputMethodIds(); | |
852 | |
853 active_input_method_ids_.clear(); | |
854 for (size_t i = 0; i < saved_active_input_method_ids_.size(); ++i) { | |
855 const std::string& input_method_id = saved_active_input_method_ids_[i]; | |
856 // Skip if it's not a keyboard layout. Drop input methods including | |
857 // extension ones. | |
858 if (!IsLoginKeyboard(input_method_id) || | |
859 added_ids_.find(input_method_id) != added_ids_.end()) | |
860 continue; | |
861 active_input_method_ids_.push_back(input_method_id); | |
862 added_ids_.insert(input_method_id); | |
863 } | |
864 | |
865 // We'll add the hardware keyboard if it's not included in | |
866 // |active_input_method_ids_| so that the user can always use the hardware | |
867 // keyboard on the screen locker. | |
868 for (size_t i = 0; i < hardware_keyboard_ids.size(); ++i) { | |
869 if (added_ids_.find(hardware_keyboard_ids[i]) == added_ids_.end()) { | |
870 active_input_method_ids_.push_back(hardware_keyboard_ids[i]); | |
871 added_ids_.insert(hardware_keyboard_ids[i]); | |
872 } | |
873 } | |
874 | |
875 ChangeInputMethod(current_input_method_.id()); | |
876 } | |
877 | |
878 void InputMethodManagerImpl::OnScreenUnlocked() { | |
879 previous_input_method_ = saved_previous_input_method_; | |
880 current_input_method_ = saved_current_input_method_; | |
881 active_input_method_ids_ = saved_active_input_method_ids_; | |
882 | |
883 ChangeInputMethod(current_input_method_.id()); | |
884 } | |
885 | |
886 bool InputMethodManagerImpl::InputMethodIsActivated( | |
887 const std::string& input_method_id) { | |
888 return Contains(active_input_method_ids_, input_method_id); | |
889 } | |
890 | |
891 void InputMethodManagerImpl::MaybeInitializeCandidateWindowController() { | 1037 void InputMethodManagerImpl::MaybeInitializeCandidateWindowController() { |
892 if (candidate_window_controller_.get()) | 1038 if (candidate_window_controller_.get()) |
893 return; | 1039 return; |
894 | 1040 |
895 candidate_window_controller_.reset( | 1041 candidate_window_controller_.reset( |
896 CandidateWindowController::CreateCandidateWindowController()); | 1042 CandidateWindowController::CreateCandidateWindowController()); |
897 candidate_window_controller_->AddObserver(this); | 1043 candidate_window_controller_->AddObserver(this); |
898 } | 1044 } |
899 | 1045 |
900 } // namespace input_method | 1046 } // namespace input_method |
901 } // namespace chromeos | 1047 } // namespace chromeos |
OLD | NEW |