Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(641)

Side by Side Diff: chrome/browser/chromeos/input_method/input_method_manager_impl.cc

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

Powered by Google App Engine
This is Rietveld 408576698