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
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/input_method/input_method_manager_impl.h"
9 #include "ash/ime/input_method_menu_item.h"
10 #include "ash/ime/input_method_menu_manager.h"
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/compiler_specific.h"
15 #include "base/logging.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/run_loop.h"
19 #include "chrome/browser/chromeos/input_method/input_method_engine_interface.h"
20 #include "chrome/browser/chromeos/input_method/mock_candidate_window_controller.h"
21 #include "chrome/browser/chromeos/input_method/mock_input_method_engine.h"
22 #include "chrome/test/base/browser_with_test_window_test.h"
23 #include "chrome/test/base/testing_browser_process.h"
24 #include "chrome/test/base/testing_profile.h"
25 #include "chrome/test/base/testing_profile_manager.h"
26 #include "chromeos/ime/extension_ime_util.h"
27 #include "chromeos/ime/fake_ime_keyboard.h"
28 #include "chromeos/ime/fake_input_method_delegate.h"
29 #include "chromeos/ime/mock_component_extension_ime_manager_delegate.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "ui/base/accelerators/accelerator.h"
32 #include "ui/base/ime/chromeos/mock_ime_engine_handler.h"
33 #include "ui/base/ime/input_method_initializer.h"
34 #include "ui/events/keycodes/keyboard_codes.h"
38 namespace input_method {
41 const char kNaclMozcUsId[] = "nacl_mozc_us";
42 const char kNaclMozcJpId[] = "nacl_mozc_jp";
43 const char kExt2Engine1Id[] = "ext2_engine1-t-i0-engine_id";
44 const char kExt2Engine2Id[] = "ext2_engine2-t-i0-engine_id";
45 const char kPinyinImeId[] = "zh-t-i0-pinyin";
46 const char kExtensionId1[] = "00000000000000000000000000000000";
47 const char kExtensionId2[] = "11111111111111111111111111111111";
49 // Returns true if |descriptors| contain |target|.
50 bool Contain(const InputMethodDescriptors& descriptors,
51 const InputMethodDescriptor& target) {
52 for (size_t i = 0; i < descriptors.size(); ++i) {
53 if (descriptors[i].id() == target.id())
59 std::string ImeIdFromEngineId(const std::string& id) {
60 return extension_ime_util::GetInputMethodIDByEngineID(id);
63 class TestObserver : public InputMethodManager::Observer,
64 public ash::ime::InputMethodMenuManager::Observer {
67 : input_method_changed_count_(0),
68 input_method_menu_item_changed_count_(0),
69 last_show_message_(false) {
71 virtual ~TestObserver() {}
73 virtual void InputMethodChanged(InputMethodManager* manager,
74 bool show_message) override {
75 ++input_method_changed_count_;
76 last_show_message_ = show_message;
78 virtual void InputMethodMenuItemChanged(
79 ash::ime::InputMethodMenuManager* manager) override {
80 ++input_method_menu_item_changed_count_;
83 int input_method_changed_count_;
84 int input_method_menu_item_changed_count_;
85 bool last_show_message_;
88 DISALLOW_COPY_AND_ASSIGN(TestObserver);
91 class TestCandidateWindowObserver
92 : public InputMethodManager::CandidateWindowObserver {
94 TestCandidateWindowObserver()
95 : candidate_window_opened_count_(0),
96 candidate_window_closed_count_(0) {
99 virtual ~TestCandidateWindowObserver() {}
101 virtual void CandidateWindowOpened(InputMethodManager* manager) override {
102 ++candidate_window_opened_count_;
104 virtual void CandidateWindowClosed(InputMethodManager* manager) override {
105 ++candidate_window_closed_count_;
108 int candidate_window_opened_count_;
109 int candidate_window_closed_count_;
112 DISALLOW_COPY_AND_ASSIGN(TestCandidateWindowObserver);
116 class InputMethodManagerImplTest : public BrowserWithTestWindowTest {
118 InputMethodManagerImplTest()
120 candidate_window_controller_(NULL),
123 virtual ~InputMethodManagerImplTest() {}
125 virtual void SetUp() override {
126 profile_manager_.reset(new TestingProfileManager(GetBrowserProcess()));
127 ASSERT_TRUE(profile_manager_->SetUp());
129 ui::InitializeInputMethodForTesting();
131 delegate_ = new FakeInputMethodDelegate();
132 manager_.reset(new InputMethodManagerImpl(
133 scoped_ptr<InputMethodDelegate>(delegate_), false));
134 manager_->GetInputMethodUtil()->UpdateHardwareLayoutCache();
135 candidate_window_controller_ = new MockCandidateWindowController;
136 manager_->SetCandidateWindowControllerForTesting(
137 candidate_window_controller_);
138 keyboard_ = new FakeImeKeyboard;
139 manager_->SetImeKeyboardForTesting(keyboard_);
140 mock_engine_handler_.reset(new MockInputMethodEngine());
141 IMEBridge::Initialize();
142 IMEBridge::Get()->SetCurrentEngineHandler(mock_engine_handler_.get());
144 menu_manager_ = ash::ime::InputMethodMenuManager::GetInstance();
148 BrowserWithTestWindowTest::SetUp();
151 virtual void TearDown() override {
152 BrowserWithTestWindowTest::TearDown();
154 ui::ShutdownInputMethodForTesting();
157 candidate_window_controller_ = NULL;
161 profile_manager_.reset();
165 // Helper function to initialize component extension stuff for testing.
166 void InitComponentExtension() {
167 mock_delegate_ = new MockComponentExtIMEManagerDelegate();
168 mock_delegate_->set_ime_list(ime_list_);
169 scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate(mock_delegate_);
171 // CreateNewState(NULL) returns state with non-empty current_input_method.
172 // So SetState() triggers ChangeInputMethod().
173 manager_->SetState(manager_->CreateNewState(NULL));
175 std::vector<std::string> layouts;
176 layouts.push_back("us");
177 std::vector<std::string> languages;
178 languages.push_back("en-US");
180 // Note, for production, these SetEngineHandler are called when
181 // IMEEngineHandlerInterface is initialized via
182 // InitializeComponentextension.
183 InputMethodDescriptors descriptors;
184 manager_->GetActiveIMEState()->AddInputMethodExtension(
185 ImeIdFromEngineId(kNaclMozcUsId),
187 mock_engine_handler_.get());
188 manager_->GetActiveIMEState()->AddInputMethodExtension(
189 ImeIdFromEngineId(kExt2Engine1Id),
191 mock_engine_handler_.get());
192 manager_->InitializeComponentExtensionForTesting(delegate.Pass());
198 ComponentExtensionIME ext_xkb;
199 ext_xkb.id = extension_ime_util::kXkbExtensionId;
200 ext_xkb.description = "ext_xkb_description";
201 ext_xkb.path = base::FilePath("ext_xkb_file_path");
203 ComponentExtensionEngine ext_xkb_engine_us;
204 ext_xkb_engine_us.engine_id = "xkb:us::eng";
205 ext_xkb_engine_us.display_name = "xkb:us::eng";
206 ext_xkb_engine_us.language_codes.push_back("en-US");
207 ext_xkb_engine_us.layouts.push_back("us");
208 ext_xkb.engines.push_back(ext_xkb_engine_us);
210 ComponentExtensionEngine ext_xkb_engine_intl;
211 ext_xkb_engine_intl.engine_id = "xkb:us:intl:eng";
212 ext_xkb_engine_intl.display_name = "xkb:us:intl:eng";
213 ext_xkb_engine_intl.language_codes.push_back("en-US");
214 ext_xkb_engine_intl.layouts.push_back("us(intl)");
215 ext_xkb.engines.push_back(ext_xkb_engine_intl);
217 ComponentExtensionEngine ext_xkb_engine_altgr_intl;
218 ext_xkb_engine_altgr_intl.engine_id = "xkb:us:altgr-intl:eng";
219 ext_xkb_engine_altgr_intl.display_name = "xkb:us:altgr-intl:eng";
220 ext_xkb_engine_altgr_intl.language_codes.push_back("en-US");
221 ext_xkb_engine_altgr_intl.layouts.push_back("us(altgr-intl)");
222 ext_xkb.engines.push_back(ext_xkb_engine_altgr_intl);
224 ComponentExtensionEngine ext_xkb_engine_dvorak;
225 ext_xkb_engine_dvorak.engine_id = "xkb:us:dvorak:eng";
226 ext_xkb_engine_dvorak.display_name = "xkb:us:dvorak:eng";
227 ext_xkb_engine_dvorak.language_codes.push_back("en-US");
228 ext_xkb_engine_dvorak.layouts.push_back("us(dvorak)");
229 ext_xkb.engines.push_back(ext_xkb_engine_dvorak);
231 ComponentExtensionEngine ext_xkb_engine_colemak;
232 ext_xkb_engine_colemak.engine_id = "xkb:us:colemak:eng";
233 ext_xkb_engine_colemak.display_name = "xkb:us:colemak:eng";
234 ext_xkb_engine_colemak.language_codes.push_back("en-US");
235 ext_xkb_engine_colemak.layouts.push_back("us(colemak)");
236 ext_xkb.engines.push_back(ext_xkb_engine_colemak);
238 ComponentExtensionEngine ext_xkb_engine_fr;
239 ext_xkb_engine_fr.engine_id = "xkb:fr::fra";
240 ext_xkb_engine_fr.display_name = "xkb:fr::fra";
241 ext_xkb_engine_fr.language_codes.push_back("fr");
242 ext_xkb_engine_fr.layouts.push_back("fr");
243 ext_xkb.engines.push_back(ext_xkb_engine_fr);
245 ComponentExtensionEngine ext_xkb_engine_se;
246 ext_xkb_engine_se.engine_id = "xkb:se::swe";
247 ext_xkb_engine_se.display_name = "xkb:se::swe";
248 ext_xkb_engine_se.language_codes.push_back("sv");
249 ext_xkb_engine_se.layouts.push_back("se");
250 ext_xkb.engines.push_back(ext_xkb_engine_se);
252 ComponentExtensionEngine ext_xkb_engine_jp;
253 ext_xkb_engine_jp.engine_id = "xkb:jp::jpn";
254 ext_xkb_engine_jp.display_name = "xkb:jp::jpn";
255 ext_xkb_engine_jp.language_codes.push_back("ja");
256 ext_xkb_engine_jp.layouts.push_back("jp");
257 ext_xkb.engines.push_back(ext_xkb_engine_jp);
259 ComponentExtensionEngine ext_xkb_engine_ru;
260 ext_xkb_engine_ru.engine_id = "xkb:ru::rus";
261 ext_xkb_engine_ru.display_name = "xkb:ru::rus";
262 ext_xkb_engine_ru.language_codes.push_back("ru");
263 ext_xkb_engine_ru.layouts.push_back("ru");
264 ext_xkb.engines.push_back(ext_xkb_engine_ru);
266 ComponentExtensionEngine ext_xkb_engine_hu;
267 ext_xkb_engine_hu.engine_id = "xkb:hu::hun";
268 ext_xkb_engine_hu.display_name = "xkb:hu::hun";
269 ext_xkb_engine_hu.language_codes.push_back("hu");
270 ext_xkb_engine_hu.layouts.push_back("hu");
271 ext_xkb.engines.push_back(ext_xkb_engine_hu);
273 ime_list_.push_back(ext_xkb);
275 ComponentExtensionIME ext1;
276 ext1.id = extension_ime_util::kMozcExtensionId;
277 ext1.description = "ext1_description";
278 ext1.path = base::FilePath("ext1_file_path");
280 ComponentExtensionEngine ext1_engine1;
281 ext1_engine1.engine_id = "nacl_mozc_us";
282 ext1_engine1.display_name = "ext1_engine_1_display_name";
283 ext1_engine1.language_codes.push_back("ja");
284 ext1_engine1.layouts.push_back("us");
285 ext1.engines.push_back(ext1_engine1);
287 ComponentExtensionEngine ext1_engine2;
288 ext1_engine2.engine_id = "nacl_mozc_jp";
289 ext1_engine2.display_name = "ext1_engine_1_display_name";
290 ext1_engine2.language_codes.push_back("ja");
291 ext1_engine2.layouts.push_back("jp");
292 ext1.engines.push_back(ext1_engine2);
294 ime_list_.push_back(ext1);
296 ComponentExtensionIME ext2;
297 ext2.id = extension_ime_util::kT13nExtensionId;
298 ext2.description = "ext2_description";
299 ext2.path = base::FilePath("ext2_file_path");
301 ComponentExtensionEngine ext2_engine1;
302 ext2_engine1.engine_id = kExt2Engine1Id;
303 ext2_engine1.display_name = "ext2_engine_1_display_name";
304 ext2_engine1.language_codes.push_back("en");
305 ext2_engine1.layouts.push_back("us");
306 ext2.engines.push_back(ext2_engine1);
308 ComponentExtensionEngine ext2_engine2;
309 ext2_engine2.engine_id = kExt2Engine2Id;
310 ext2_engine2.display_name = "ext2_engine_2_display_name";
311 ext2_engine2.language_codes.push_back("en");
312 ext2_engine2.layouts.push_back("us(dvorak)");
313 ext2.engines.push_back(ext2_engine2);
315 ime_list_.push_back(ext2);
318 TestingBrowserProcess* GetBrowserProcess() {
319 return TestingBrowserProcess::GetGlobal();
322 scoped_ptr<TestingProfileManager> profile_manager_;
323 scoped_ptr<InputMethodManagerImpl> manager_;
324 FakeInputMethodDelegate* delegate_;
325 MockCandidateWindowController* candidate_window_controller_;
326 scoped_ptr<MockInputMethodEngine> mock_engine_handler_;
327 FakeImeKeyboard* keyboard_;
328 MockComponentExtIMEManagerDelegate* mock_delegate_;
329 std::vector<ComponentExtensionIME> ime_list_;
330 ash::ime::InputMethodMenuManager* menu_manager_;
333 DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImplTest);
336 TEST_F(InputMethodManagerImplTest, TestGetImeKeyboard) {
337 EXPECT_TRUE(manager_->GetImeKeyboard());
338 EXPECT_EQ(keyboard_, manager_->GetImeKeyboard());
341 TEST_F(InputMethodManagerImplTest, TestCandidateWindowObserver) {
342 TestCandidateWindowObserver observer;
343 candidate_window_controller_->NotifyCandidateWindowOpened(); // nop
344 candidate_window_controller_->NotifyCandidateWindowClosed(); // nop
345 manager_->AddCandidateWindowObserver(&observer);
346 candidate_window_controller_->NotifyCandidateWindowOpened();
347 EXPECT_EQ(1, observer.candidate_window_opened_count_);
348 candidate_window_controller_->NotifyCandidateWindowClosed();
349 EXPECT_EQ(1, observer.candidate_window_closed_count_);
350 candidate_window_controller_->NotifyCandidateWindowOpened();
351 EXPECT_EQ(2, observer.candidate_window_opened_count_);
352 candidate_window_controller_->NotifyCandidateWindowClosed();
353 EXPECT_EQ(2, observer.candidate_window_closed_count_);
354 manager_->RemoveCandidateWindowObserver(&observer);
357 TEST_F(InputMethodManagerImplTest, TestObserver) {
358 // For http://crbug.com/19655#c11 - (3). browser_state_monitor_unittest.cc is
359 // also for the scenario.
360 std::vector<std::string> keyboard_layouts;
361 keyboard_layouts.push_back("xkb:us::eng");
363 TestObserver observer;
364 InitComponentExtension();
365 manager_->AddObserver(&observer);
366 menu_manager_->AddObserver(&observer);
367 EXPECT_EQ(0, observer.input_method_changed_count_);
368 manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
369 EXPECT_EQ(5U, manager_->GetActiveIMEState()->GetActiveInputMethods()->size());
370 EXPECT_EQ(1, observer.input_method_changed_count_);
371 // Menu change is triggered only if current input method was actually changed.
372 EXPECT_EQ(0, observer.input_method_menu_item_changed_count_);
373 manager_->GetActiveIMEState()->ChangeInputMethod(
374 ImeIdFromEngineId("xkb:us:dvorak:eng"), false /* show_message */);
375 EXPECT_FALSE(observer.last_show_message_);
376 EXPECT_EQ(2, observer.input_method_changed_count_);
377 EXPECT_EQ(1, observer.input_method_menu_item_changed_count_);
378 manager_->GetActiveIMEState()->ChangeInputMethod(
379 ImeIdFromEngineId("xkb:us:dvorak:eng"), false /* show_message */);
380 EXPECT_FALSE(observer.last_show_message_);
382 // The observer is always notified even when the same input method ID is
383 // passed to ChangeInputMethod() more than twice.
384 // TODO(komatsu): Revisit if this is neccessary.
385 EXPECT_EQ(3, observer.input_method_changed_count_);
387 // If the same input method ID is passed, PropertyChanged() is not
389 EXPECT_EQ(1, observer.input_method_menu_item_changed_count_);
391 manager_->RemoveObserver(&observer);
392 menu_manager_->RemoveObserver(&observer);
395 TEST_F(InputMethodManagerImplTest, TestGetSupportedInputMethods) {
396 InitComponentExtension();
397 InputMethodDescriptors methods;
398 methods = manager_->GetComponentExtensionIMEManager()
399 ->GetXkbIMEAsInputMethodDescriptor();
400 // Try to find random 4-5 layuts and IMEs to make sure the returned list is
402 const InputMethodDescriptor* id_to_find =
403 manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
404 ImeIdFromEngineId(kNaclMozcUsId));
405 id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
406 ImeIdFromEngineId("xkb:us::eng"));
407 EXPECT_TRUE(Contain(methods, *id_to_find));
408 id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
409 ImeIdFromEngineId("xkb:us:dvorak:eng"));
410 EXPECT_TRUE(Contain(methods, *id_to_find));
411 id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
412 ImeIdFromEngineId("xkb:fr::fra"));
413 EXPECT_TRUE(Contain(methods, *id_to_find));
416 TEST_F(InputMethodManagerImplTest, TestEnableLayouts) {
417 // Currently 5 keyboard layouts are supported for en-US, and 1 for ja. See
418 // ibus_input_method.txt.
419 std::vector<std::string> keyboard_layouts;
421 InitComponentExtension();
422 manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
423 EXPECT_EQ(5U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
425 // For http://crbug.com/19655#c11 - (5)
426 // The hardware keyboard layout "xkb:us::eng" is always active, hence 2U.
427 manager_->GetActiveIMEState()->EnableLoginLayouts(
428 "ja", keyboard_layouts); // Japanese
429 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
432 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsAndCurrentInputMethod) {
433 // For http://crbug.com/329061
434 std::vector<std::string> keyboard_layouts;
435 keyboard_layouts.push_back(ImeIdFromEngineId("xkb:se::swe"));
437 InitComponentExtension();
438 manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
439 const std::string im_id =
440 manager_->GetActiveIMEState()->GetCurrentInputMethod().id();
441 EXPECT_EQ(ImeIdFromEngineId("xkb:se::swe"), im_id);
444 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsNonUsHardwareKeyboard) {
445 InitComponentExtension();
446 // The physical layout is French.
447 manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
449 manager_->GetActiveIMEState()->EnableLoginLayouts(
451 manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
454 manager_->GetActiveIMEState()->GetNumActiveInputMethods()); // 5 + French
455 // The physical layout is Japanese.
456 manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
458 manager_->GetActiveIMEState()->EnableLoginLayouts(
459 "ja", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
460 // "xkb:us::eng" is not needed, hence 1.
461 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
463 // The physical layout is Russian.
464 manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
466 manager_->GetActiveIMEState()->EnableLoginLayouts(
467 "ru", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
468 // "xkb:us::eng" only.
469 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
470 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
471 manager_->GetActiveIMEState()->GetActiveInputMethodIds().front());
474 TEST_F(InputMethodManagerImplTest, TestEnableMultipleHardwareKeyboardLayout) {
475 InitComponentExtension();
476 // The physical layouts are French and Hungarian.
477 manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
478 "xkb:fr::fra,xkb:hu::hun");
479 manager_->GetActiveIMEState()->EnableLoginLayouts(
481 manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
482 // 5 + French + Hungarian
483 EXPECT_EQ(7U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
486 TEST_F(InputMethodManagerImplTest,
487 TestEnableMultipleHardwareKeyboardLayout_NoLoginKeyboard) {
488 InitComponentExtension();
489 // The physical layouts are English (US) and Russian.
490 manager_->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
491 "xkb:us::eng,xkb:ru::rus");
492 manager_->GetActiveIMEState()->EnableLoginLayouts(
493 "ru", manager_->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
495 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
498 TEST_F(InputMethodManagerImplTest, TestActiveInputMethods) {
499 InitComponentExtension();
500 std::vector<std::string> keyboard_layouts;
501 manager_->GetActiveIMEState()->EnableLoginLayouts(
502 "ja", keyboard_layouts); // Japanese
503 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
504 scoped_ptr<InputMethodDescriptors> methods(
505 manager_->GetActiveIMEState()->GetActiveInputMethods());
506 ASSERT_TRUE(methods.get());
507 EXPECT_EQ(2U, methods->size());
508 const InputMethodDescriptor* id_to_find =
509 manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
510 ImeIdFromEngineId("xkb:us::eng"));
511 EXPECT_TRUE(id_to_find && Contain(*methods.get(), *id_to_find));
512 id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
513 ImeIdFromEngineId("xkb:jp::jpn"));
514 EXPECT_TRUE(id_to_find && Contain(*methods.get(), *id_to_find));
517 TEST_F(InputMethodManagerImplTest, TestEnableTwoLayouts) {
518 // For http://crbug.com/19655#c11 - (8), step 6.
519 TestObserver observer;
520 InitComponentExtension();
521 manager_->AddObserver(&observer);
522 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
523 std::vector<std::string> ids;
524 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
525 ids.push_back(ImeIdFromEngineId("xkb:us:colemak:eng"));
526 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
527 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
528 // Since all the IDs added avobe are keyboard layouts, Start() should not be
530 EXPECT_EQ(1, observer.input_method_changed_count_);
531 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
532 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
533 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
535 ids.erase(ids.begin());
536 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
537 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
538 EXPECT_EQ(2, observer.input_method_changed_count_);
539 EXPECT_EQ(ImeIdFromEngineId(ids[0]), // colemak
540 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
541 EXPECT_EQ("us(colemak)", keyboard_->last_layout_);
542 manager_->RemoveObserver(&observer);
545 TEST_F(InputMethodManagerImplTest, TestEnableThreeLayouts) {
546 // For http://crbug.com/19655#c11 - (9).
547 TestObserver observer;
548 InitComponentExtension();
549 manager_->AddObserver(&observer);
550 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
551 std::vector<std::string> ids;
552 ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
553 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
554 ids.push_back(ImeIdFromEngineId("xkb:us:colemak:eng"));
555 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
556 EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
557 EXPECT_EQ(1, observer.input_method_changed_count_);
558 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
559 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
560 EXPECT_EQ("us", keyboard_->last_layout_);
562 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
563 EXPECT_EQ(2, observer.input_method_changed_count_);
564 EXPECT_EQ(ImeIdFromEngineId(ids[1]),
565 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
566 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
568 ids.erase(ids.begin() + 1);
569 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
570 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
571 EXPECT_EQ(3, observer.input_method_changed_count_);
572 EXPECT_EQ(ImeIdFromEngineId(ids[0]), // US Qwerty
573 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
574 EXPECT_EQ("us", keyboard_->last_layout_);
575 manager_->RemoveObserver(&observer);
578 TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme) {
579 // For http://crbug.com/19655#c11 - (10).
580 TestObserver observer;
581 InitComponentExtension();
582 manager_->AddObserver(&observer);
583 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
584 std::vector<std::string> ids;
585 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
586 ids.push_back(ImeIdFromEngineId(kNaclMozcUsId));
587 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
588 EXPECT_EQ(1, observer.input_method_changed_count_);
589 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
590 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
591 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
593 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
594 EXPECT_EQ(2, observer.input_method_changed_count_);
595 EXPECT_EQ(ImeIdFromEngineId(ids[1]),
596 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
597 EXPECT_EQ("us", keyboard_->last_layout_);
599 ids.erase(ids.begin() + 1);
600 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
601 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
602 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
603 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
604 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
607 TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme2) {
608 // For http://crbug.com/19655#c11 - (11).
609 TestObserver observer;
610 InitComponentExtension();
611 manager_->AddObserver(&observer);
612 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
613 std::vector<std::string> ids;
614 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
615 ids.push_back(ImeIdFromEngineId(kNaclMozcUsId));
616 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
617 EXPECT_EQ(1, observer.input_method_changed_count_);
618 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
619 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
620 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
623 ids.erase(ids.begin());
624 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
625 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
626 EXPECT_EQ(ImeIdFromEngineId(ids[0]), // Mozc
627 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
628 EXPECT_EQ("us", keyboard_->last_layout_);
629 manager_->RemoveObserver(&observer);
632 TEST_F(InputMethodManagerImplTest, TestEnableImes) {
633 TestObserver observer;
634 InitComponentExtension();
635 manager_->AddObserver(&observer);
636 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
637 std::vector<std::string> ids;
638 ids.push_back(ImeIdFromEngineId(kExt2Engine1Id));
639 ids.push_back("mozc-dv");
640 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
641 EXPECT_EQ(1, observer.input_method_changed_count_);
642 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
643 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
644 EXPECT_EQ("us", keyboard_->last_layout_);
645 manager_->RemoveObserver(&observer);
648 TEST_F(InputMethodManagerImplTest, TestEnableUnknownIds) {
649 TestObserver observer;
650 InitComponentExtension();
651 manager_->AddObserver(&observer);
652 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
653 std::vector<std::string> ids;
654 ids.push_back("xkb:tl::tlh"); // Klingon, which is not supported.
655 ids.push_back("unknown-super-cool-ime");
656 EXPECT_FALSE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
658 // TODO(yusukes): Should we fall back to the hardware keyboard layout in this
660 EXPECT_EQ(0, observer.input_method_changed_count_);
662 manager_->RemoveObserver(&observer);
665 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsThenLock) {
666 // For http://crbug.com/19655#c11 - (14).
667 TestObserver observer;
668 InitComponentExtension();
669 manager_->AddObserver(&observer);
670 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
671 std::vector<std::string> ids;
672 ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
673 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
674 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
675 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
676 EXPECT_EQ(1, observer.input_method_changed_count_);
677 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
678 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
679 EXPECT_EQ("us", keyboard_->last_layout_);
682 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
683 EXPECT_EQ(2, observer.input_method_changed_count_);
684 EXPECT_EQ(ImeIdFromEngineId(ids[1]),
685 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
686 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
689 scoped_refptr<input_method::InputMethodManager::State> saved_ime_state =
690 manager_->GetActiveIMEState();
691 manager_->SetState(saved_ime_state->Clone());
692 manager_->GetActiveIMEState()->EnableLockScreenLayouts();
693 manager_->SetUISessionState(InputMethodManager::STATE_LOCK_SCREEN);
694 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
695 EXPECT_EQ(ImeIdFromEngineId(ids[1]), // still Dvorak
696 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
697 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
698 // Switch back to Qwerty.
699 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
700 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
701 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
702 EXPECT_EQ("us", keyboard_->last_layout_);
704 // Unlock screen. The original state, Dvorak, is restored.
705 manager_->SetState(saved_ime_state);
706 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
707 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
708 EXPECT_EQ(ImeIdFromEngineId(ids[1]),
709 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
710 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
712 manager_->RemoveObserver(&observer);
715 TEST_F(InputMethodManagerImplTest, SwitchInputMethodTest) {
716 // For http://crbug.com/19655#c11 - (15).
717 TestObserver observer;
718 InitComponentExtension();
719 manager_->AddObserver(&observer);
720 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
721 std::vector<std::string> ids;
722 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
723 ids.push_back(ImeIdFromEngineId(kExt2Engine2Id));
724 ids.push_back(ImeIdFromEngineId(kExt2Engine1Id));
725 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
726 EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
727 EXPECT_EQ(1, observer.input_method_changed_count_);
728 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
729 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
730 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
733 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
734 EXPECT_EQ(2, observer.input_method_changed_count_);
735 EXPECT_EQ(ImeIdFromEngineId(ids[1]),
736 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
737 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
740 scoped_refptr<input_method::InputMethodManager::State> saved_ime_state =
741 manager_->GetActiveIMEState();
742 manager_->SetState(saved_ime_state->Clone());
743 manager_->GetActiveIMEState()->EnableLockScreenLayouts();
744 manager_->SetUISessionState(InputMethodManager::STATE_LOCK_SCREEN);
746 manager_->GetActiveIMEState()
747 ->GetNumActiveInputMethods()); // Qwerty+Dvorak.
748 EXPECT_EQ(ImeIdFromEngineId("xkb:us:dvorak:eng"),
749 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
750 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
751 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
752 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), // The hardware keyboard layout.
753 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
754 EXPECT_EQ("us", keyboard_->last_layout_);
756 // Unlock screen. The original state, pinyin-dv, is restored.
757 manager_->SetState(saved_ime_state);
758 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
760 manager_->GetActiveIMEState()
761 ->GetNumActiveInputMethods()); // Dvorak and 2 IMEs.
762 EXPECT_EQ(ImeIdFromEngineId(ids[1]),
763 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
764 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
766 manager_->RemoveObserver(&observer);
769 TEST_F(InputMethodManagerImplTest, TestXkbSetting) {
770 EXPECT_EQ(0, keyboard_->set_current_keyboard_layout_by_name_count_);
771 // For http://crbug.com/19655#c11 - (8), step 7-11.
772 InitComponentExtension();
773 EXPECT_EQ(1, keyboard_->set_current_keyboard_layout_by_name_count_);
774 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
775 std::vector<std::string> ids;
776 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
777 ids.push_back(ImeIdFromEngineId("xkb:us:colemak:eng"));
778 ids.push_back(ImeIdFromEngineId(kNaclMozcJpId));
779 ids.push_back(ImeIdFromEngineId(kNaclMozcUsId));
780 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
781 EXPECT_EQ(4U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
782 EXPECT_EQ(2, keyboard_->set_current_keyboard_layout_by_name_count_);
783 // See input_methods.txt for an expected XKB layout name.
784 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
785 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
786 EXPECT_EQ(3, keyboard_->set_current_keyboard_layout_by_name_count_);
787 EXPECT_EQ("us(colemak)", keyboard_->last_layout_);
788 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
789 EXPECT_EQ(4, keyboard_->set_current_keyboard_layout_by_name_count_);
790 EXPECT_EQ("jp", keyboard_->last_layout_);
791 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
792 EXPECT_EQ(5, keyboard_->set_current_keyboard_layout_by_name_count_);
793 EXPECT_EQ("us", keyboard_->last_layout_);
794 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
795 EXPECT_EQ(6, keyboard_->set_current_keyboard_layout_by_name_count_);
796 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
798 ids.erase(ids.begin());
799 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
800 EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
801 EXPECT_EQ(7, keyboard_->set_current_keyboard_layout_by_name_count_);
802 EXPECT_EQ("us(colemak)", keyboard_->last_layout_);
805 TEST_F(InputMethodManagerImplTest, TestActivateInputMethodMenuItem) {
806 const std::string kKey = "key";
807 ash::ime::InputMethodMenuItemList menu_list;
808 menu_list.push_back(ash::ime::InputMethodMenuItem(
809 kKey, "label", false, false));
810 menu_manager_->SetCurrentInputMethodMenuItemList(menu_list);
812 manager_->ActivateInputMethodMenuItem(kKey);
813 EXPECT_EQ(kKey, mock_engine_handler_->last_activated_property());
815 // Key2 is not registered, so activated property should not be changed.
816 manager_->ActivateInputMethodMenuItem("key2");
817 EXPECT_EQ(kKey, mock_engine_handler_->last_activated_property());
820 TEST_F(InputMethodManagerImplTest, TestGetCurrentInputMethodProperties) {
821 InitComponentExtension();
822 EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty());
824 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
825 std::vector<std::string> ids;
826 ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
827 ids.push_back(ImeIdFromEngineId(kNaclMozcUsId));
828 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
829 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
830 EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty());
831 manager_->GetActiveIMEState()->ChangeInputMethod(
832 ImeIdFromEngineId(kNaclMozcUsId), false /* show_message */);
834 ash::ime::InputMethodMenuItemList current_property_list;
835 current_property_list.push_back(ash::ime::InputMethodMenuItem(
836 "key", "label", false, false));
837 menu_manager_->SetCurrentInputMethodMenuItemList(current_property_list);
839 ASSERT_EQ(1U, menu_manager_->GetCurrentInputMethodMenuItemList().size());
841 menu_manager_->GetCurrentInputMethodMenuItemList().at(0).key);
843 manager_->GetActiveIMEState()->ChangeInputMethod("xkb:us::eng",
844 false /* show_message */);
845 EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty());
848 TEST_F(InputMethodManagerImplTest, TestGetCurrentInputMethodPropertiesTwoImes) {
849 InitComponentExtension();
850 EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty());
852 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
853 std::vector<std::string> ids;
854 ids.push_back(ImeIdFromEngineId(kNaclMozcUsId)); // Japanese
855 ids.push_back(ImeIdFromEngineId(kExt2Engine1Id)); // T-Chinese
856 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
857 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
858 EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty());
860 ash::ime::InputMethodMenuItemList current_property_list;
861 current_property_list.push_back(ash::ime::InputMethodMenuItem("key-mozc",
865 menu_manager_->SetCurrentInputMethodMenuItemList(current_property_list);
867 ASSERT_EQ(1U, menu_manager_->GetCurrentInputMethodMenuItemList().size());
868 EXPECT_EQ("key-mozc",
869 menu_manager_->GetCurrentInputMethodMenuItemList().at(0).key);
871 manager_->GetActiveIMEState()->ChangeInputMethod(
872 ImeIdFromEngineId(kExt2Engine1Id), false /* show_message */);
873 // Since the IME is changed, the property for mozc Japanese should be hidden.
874 EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty());
876 // Asynchronous property update signal from mozc-chewing.
877 current_property_list.clear();
878 current_property_list.push_back(ash::ime::InputMethodMenuItem(
879 "key-chewing", "label", false, false));
880 menu_manager_->SetCurrentInputMethodMenuItemList(current_property_list);
881 ASSERT_EQ(1U, menu_manager_->GetCurrentInputMethodMenuItemList().size());
882 EXPECT_EQ("key-chewing",
883 menu_manager_->GetCurrentInputMethodMenuItemList().at(0).key);
886 TEST_F(InputMethodManagerImplTest, TestNextInputMethod) {
887 TestObserver observer;
888 InitComponentExtension();
889 manager_->AddObserver(&observer);
890 std::vector<std::string> keyboard_layouts;
891 keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng"));
892 // For http://crbug.com/19655#c11 - (1)
893 manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
894 EXPECT_EQ(5U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
895 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
896 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
897 EXPECT_EQ("us", keyboard_->last_layout_);
898 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
899 EXPECT_TRUE(observer.last_show_message_);
900 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
901 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
902 EXPECT_EQ("us(intl)", keyboard_->last_layout_);
903 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
904 EXPECT_TRUE(observer.last_show_message_);
905 EXPECT_EQ(ImeIdFromEngineId("xkb:us:altgr-intl:eng"),
906 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
907 EXPECT_EQ("us(altgr-intl)", keyboard_->last_layout_);
908 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
909 EXPECT_TRUE(observer.last_show_message_);
910 EXPECT_EQ(ImeIdFromEngineId("xkb:us:dvorak:eng"),
911 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
912 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
913 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
914 EXPECT_TRUE(observer.last_show_message_);
915 EXPECT_EQ(ImeIdFromEngineId("xkb:us:colemak:eng"),
916 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
917 EXPECT_EQ("us(colemak)", keyboard_->last_layout_);
918 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
919 EXPECT_TRUE(observer.last_show_message_);
920 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
921 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
922 EXPECT_EQ("us", keyboard_->last_layout_);
924 manager_->RemoveObserver(&observer);
927 TEST_F(InputMethodManagerImplTest, TestPreviousInputMethod) {
928 TestObserver observer;
929 InitComponentExtension();
930 manager_->AddObserver(&observer);
932 ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
933 keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
934 ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
935 keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
937 std::vector<std::string> keyboard_layouts;
938 keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng"));
939 manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
940 EXPECT_EQ(5U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
941 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
942 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
943 EXPECT_EQ("us", keyboard_->last_layout_);
944 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToNextInputMethod());
945 EXPECT_TRUE(observer.last_show_message_);
946 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
947 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
948 EXPECT_EQ("us(intl)", keyboard_->last_layout_);
949 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
950 keydown_accelerator));
951 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
953 EXPECT_TRUE(observer.last_show_message_);
954 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
955 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
956 EXPECT_EQ("us", keyboard_->last_layout_);
957 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
958 keydown_accelerator));
959 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
961 EXPECT_TRUE(observer.last_show_message_);
962 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
963 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
964 EXPECT_EQ("us(intl)", keyboard_->last_layout_);
965 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
966 keydown_accelerator));
967 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
969 EXPECT_TRUE(observer.last_show_message_);
970 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
971 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
972 EXPECT_EQ("us", keyboard_->last_layout_);
973 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToNextInputMethod());
974 EXPECT_TRUE(observer.last_show_message_);
975 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
976 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
977 EXPECT_EQ("us(intl)", keyboard_->last_layout_);
978 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToNextInputMethod());
979 EXPECT_TRUE(observer.last_show_message_);
980 EXPECT_EQ(ImeIdFromEngineId("xkb:us:altgr-intl:eng"),
981 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
982 EXPECT_EQ("us(altgr-intl)", keyboard_->last_layout_);
983 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
984 keydown_accelerator));
985 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
987 EXPECT_TRUE(observer.last_show_message_);
988 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
989 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
990 EXPECT_EQ("us(intl)", keyboard_->last_layout_);
991 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
992 keydown_accelerator));
993 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
995 EXPECT_TRUE(observer.last_show_message_);
996 EXPECT_EQ(ImeIdFromEngineId("xkb:us:altgr-intl:eng"),
997 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
998 EXPECT_EQ("us(altgr-intl)", keyboard_->last_layout_);
1000 manager_->RemoveObserver(&observer);
1003 TEST_F(InputMethodManagerImplTest,
1004 TestSwitchToPreviousInputMethodForOneActiveInputMethod) {
1005 TestObserver observer;
1006 InitComponentExtension();
1007 manager_->AddObserver(&observer);
1009 ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
1010 keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
1011 ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
1012 keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
1014 std::vector<std::string> ids;
1015 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
1016 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
1017 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1019 // Ctrl+Space accelerator should not be consumed if there is only one active
1021 EXPECT_FALSE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
1022 keydown_accelerator));
1023 EXPECT_FALSE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
1024 keyup_accelerator));
1026 manager_->RemoveObserver(&observer);
1029 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithUsLayouts) {
1030 std::string expect_id = ImeIdFromEngineId("xkb:us::eng");
1031 TestObserver observer;
1032 InitComponentExtension();
1033 manager_->AddObserver(&observer);
1034 std::vector<std::string> keyboard_layouts;
1035 keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng"));
1036 manager_->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts);
1037 EXPECT_EQ(5U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1038 EXPECT_EQ(expect_id,
1039 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1040 EXPECT_EQ("us", keyboard_->last_layout_);
1042 // Henkan, Muhenkan, ZenkakuHankaku should be ignored when no Japanese IMEs
1043 // and keyboards are enabled.
1044 EXPECT_FALSE(manager_->GetActiveIMEState()->SwitchInputMethod(
1045 ui::Accelerator(ui::VKEY_CONVERT, ui::EF_NONE)));
1046 EXPECT_FALSE(observer.last_show_message_);
1047 EXPECT_EQ(expect_id,
1048 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1049 EXPECT_EQ("us", keyboard_->last_layout_);
1050 EXPECT_FALSE(manager_->GetActiveIMEState()->SwitchInputMethod(
1051 ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
1052 EXPECT_EQ(expect_id,
1053 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1054 EXPECT_EQ("us", keyboard_->last_layout_);
1055 EXPECT_FALSE(manager_->GetActiveIMEState()->SwitchInputMethod(
1056 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
1057 EXPECT_EQ(expect_id,
1058 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1059 EXPECT_EQ("us", keyboard_->last_layout_);
1060 EXPECT_FALSE(manager_->GetActiveIMEState()->SwitchInputMethod(
1061 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
1062 EXPECT_EQ(expect_id,
1063 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1064 EXPECT_EQ("us", keyboard_->last_layout_);
1066 manager_->RemoveObserver(&observer);
1069 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpLayout) {
1070 // Enable "xkb:jp::jpn" and press Muhenkan/ZenkakuHankaku.
1071 InitComponentExtension();
1073 ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
1074 keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
1075 ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
1076 keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
1078 std::vector<std::string> keyboard_layouts;
1079 keyboard_layouts.push_back(ImeIdFromEngineId("xkb:us::eng"));
1080 manager_->GetActiveIMEState()->EnableLoginLayouts("ja", keyboard_layouts);
1081 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1082 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
1083 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1084 EXPECT_EQ("us", keyboard_->last_layout_);
1085 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1086 ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
1087 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1088 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1089 EXPECT_EQ("jp", keyboard_->last_layout_);
1090 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
1091 keydown_accelerator));
1092 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
1093 keyup_accelerator));
1094 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
1095 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1096 EXPECT_EQ("us", keyboard_->last_layout_);
1097 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1098 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
1099 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1100 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1101 EXPECT_EQ("jp", keyboard_->last_layout_);
1102 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
1103 keydown_accelerator));
1104 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchToPreviousInputMethod(
1105 keyup_accelerator));
1106 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
1107 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1108 EXPECT_EQ("us", keyboard_->last_layout_);
1109 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1110 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
1111 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1112 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1113 EXPECT_EQ("jp", keyboard_->last_layout_);
1116 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpIme) {
1117 InitComponentExtension();
1118 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
1119 std::vector<std::string> ids;
1120 ids.push_back(ImeIdFromEngineId("xkb:jp::jpn"));
1121 ids.push_back(ImeIdFromEngineId(kNaclMozcJpId));
1122 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
1123 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1124 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1125 EXPECT_EQ("jp", keyboard_->last_layout_);
1126 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1127 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
1128 EXPECT_EQ(ImeIdFromEngineId(kNaclMozcJpId),
1129 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1130 EXPECT_EQ("jp", keyboard_->last_layout_);
1131 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1132 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
1133 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1134 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1135 EXPECT_EQ("jp", keyboard_->last_layout_);
1136 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1137 ui::Accelerator(ui::VKEY_CONVERT, ui::EF_NONE)));
1138 EXPECT_EQ(ImeIdFromEngineId(kNaclMozcJpId),
1139 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1140 EXPECT_EQ("jp", keyboard_->last_layout_);
1141 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1142 ui::Accelerator(ui::VKEY_CONVERT, ui::EF_NONE)));
1143 EXPECT_EQ(ImeIdFromEngineId(kNaclMozcJpId),
1144 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1145 EXPECT_EQ("jp", keyboard_->last_layout_);
1146 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1147 ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
1148 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1149 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1150 EXPECT_EQ("jp", keyboard_->last_layout_);
1151 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1152 ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
1153 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1154 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1155 EXPECT_EQ("jp", keyboard_->last_layout_);
1158 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
1159 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
1160 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1161 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1162 EXPECT_EQ("jp", keyboard_->last_layout_);
1163 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1164 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
1165 EXPECT_EQ(ImeIdFromEngineId(kNaclMozcJpId),
1166 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1167 EXPECT_EQ("jp", keyboard_->last_layout_);
1168 EXPECT_TRUE(manager_->GetActiveIMEState()->SwitchInputMethod(
1169 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
1170 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1171 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1172 EXPECT_EQ("jp", keyboard_->last_layout_);
1175 TEST_F(InputMethodManagerImplTest, TestAddRemoveExtensionInputMethods) {
1176 TestObserver observer;
1177 InitComponentExtension();
1178 manager_->AddObserver(&observer);
1179 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
1180 std::vector<std::string> ids;
1181 ids.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
1182 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
1183 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1184 EXPECT_EQ(1, observer.input_method_changed_count_);
1185 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
1186 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1187 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
1189 // Add two Extension IMEs.
1190 std::vector<std::string> layouts;
1191 layouts.push_back("us");
1192 std::vector<std::string> languages;
1193 languages.push_back("en-US");
1195 const std::string ext1_id =
1196 extension_ime_util::GetInputMethodID(kExtensionId1, "engine_id");
1197 const InputMethodDescriptor descriptor1(ext1_id,
1198 "deadbeef input method",
1202 false, // is_login_keyboard
1205 MockInputMethodEngine engine;
1206 InputMethodDescriptors descriptors;
1207 descriptors.push_back(descriptor1);
1208 manager_->GetActiveIMEState()->AddInputMethodExtension(
1209 kExtensionId1, descriptors, &engine);
1211 // Extension IMEs are not enabled by default.
1212 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1214 std::vector<std::string> extension_ime_ids;
1215 extension_ime_ids.push_back(ext1_id);
1216 manager_->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids);
1217 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1220 scoped_ptr<InputMethodDescriptors> methods(
1221 manager_->GetActiveIMEState()->GetActiveInputMethods());
1222 ASSERT_EQ(2U, methods->size());
1223 // Ext IMEs should be at the end of the list.
1224 EXPECT_EQ(ext1_id, methods->at(1).id());
1227 const std::string ext2_id =
1228 extension_ime_util::GetInputMethodID(kExtensionId2, "engine_id");
1229 const InputMethodDescriptor descriptor2(ext2_id,
1230 "cafebabe input method",
1234 false, // is_login_keyboard
1237 descriptors.clear();
1238 descriptors.push_back(descriptor2);
1239 MockInputMethodEngine engine2;
1240 manager_->GetActiveIMEState()->AddInputMethodExtension(
1241 kExtensionId2, descriptors, &engine2);
1242 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1244 extension_ime_ids.push_back(ext2_id);
1245 manager_->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids);
1246 EXPECT_EQ(3U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1248 scoped_ptr<InputMethodDescriptors> methods(
1249 manager_->GetActiveIMEState()->GetActiveInputMethods());
1250 ASSERT_EQ(3U, methods->size());
1251 // Ext IMEs should be at the end of the list.
1252 EXPECT_EQ(ext1_id, methods->at(1).id());
1253 EXPECT_EQ(ext2_id, methods->at(2).id());
1257 manager_->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId1);
1258 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1259 manager_->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId2);
1260 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1263 TEST_F(InputMethodManagerImplTest, TestAddExtensionInputThenLockScreen) {
1264 TestObserver observer;
1265 InitComponentExtension();
1266 manager_->AddObserver(&observer);
1267 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
1268 std::vector<std::string> ids;
1269 ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
1270 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
1271 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1272 EXPECT_EQ(1, observer.input_method_changed_count_);
1273 EXPECT_EQ(ImeIdFromEngineId(ids[0]),
1274 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1275 EXPECT_EQ("us", keyboard_->last_layout_);
1277 // Add an Extension IME.
1278 std::vector<std::string> layouts;
1279 layouts.push_back("us(dvorak)");
1280 std::vector<std::string> languages;
1281 languages.push_back("en-US");
1283 const std::string ext_id =
1284 extension_ime_util::GetInputMethodID(kExtensionId1, "engine_id");
1285 const InputMethodDescriptor descriptor(ext_id,
1286 "deadbeef input method",
1290 false, // is_login_keyboard
1293 MockInputMethodEngine engine;
1294 InputMethodDescriptors descriptors;
1295 descriptors.push_back(descriptor);
1296 manager_->GetActiveIMEState()->AddInputMethodExtension(
1297 kExtensionId1, descriptors, &engine);
1299 // Extension IME is not enabled by default.
1300 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1301 EXPECT_EQ(1, observer.input_method_changed_count_);
1303 std::vector<std::string> extension_ime_ids;
1304 extension_ime_ids.push_back(ext_id);
1305 manager_->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids);
1306 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1308 // Switch to the IME.
1309 manager_->GetActiveIMEState()->SwitchToNextInputMethod();
1310 EXPECT_EQ(3, observer.input_method_changed_count_);
1312 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1313 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
1315 // Lock the screen. This is for crosbug.com/27049.
1316 scoped_refptr<input_method::InputMethodManager::State> saved_ime_state =
1317 manager_->GetActiveIMEState();
1318 manager_->SetState(saved_ime_state->Clone());
1319 manager_->GetActiveIMEState()->EnableLockScreenLayouts();
1320 manager_->SetUISessionState(InputMethodManager::STATE_LOCK_SCREEN);
1322 manager_->GetActiveIMEState()
1323 ->GetNumActiveInputMethods()); // Qwerty. No Ext. IME
1324 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
1325 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1326 EXPECT_EQ("us", keyboard_->last_layout_);
1328 // Unlock the screen.
1329 manager_->SetState(saved_ime_state);
1330 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
1331 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1333 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1334 EXPECT_EQ("us(dvorak)", keyboard_->last_layout_);
1336 // This is for crosbug.com/27052.
1337 scoped_ptr<InputMethodDescriptors> methods(
1338 manager_->GetActiveIMEState()->GetActiveInputMethods());
1339 ASSERT_EQ(2U, methods->size());
1340 // Ext. IMEs should be at the end of the list.
1341 EXPECT_EQ(ext_id, methods->at(1).id());
1343 manager_->RemoveObserver(&observer);
1346 TEST_F(InputMethodManagerImplTest,
1347 ChangeInputMethod_ComponenteExtensionOneIME) {
1348 InitComponentExtension();
1349 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
1350 const std::string ext_id = extension_ime_util::GetComponentInputMethodID(
1352 ime_list_[1].engines[0].engine_id);
1353 std::vector<std::string> ids;
1354 ids.push_back(ext_id);
1355 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
1356 EXPECT_EQ(1U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1358 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1361 TEST_F(InputMethodManagerImplTest,
1362 ChangeInputMethod_ComponenteExtensionTwoIME) {
1363 InitComponentExtension();
1364 manager_->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN);
1365 const std::string ext_id1 = extension_ime_util::GetComponentInputMethodID(
1367 ime_list_[1].engines[0].engine_id);
1368 const std::string ext_id2 = extension_ime_util::GetComponentInputMethodID(
1370 ime_list_[2].engines[0].engine_id);
1371 std::vector<std::string> ids;
1372 ids.push_back(ext_id1);
1373 ids.push_back(ext_id2);
1374 EXPECT_TRUE(manager_->GetActiveIMEState()->ReplaceEnabledInputMethods(ids));
1375 EXPECT_EQ(2U, manager_->GetActiveIMEState()->GetNumActiveInputMethods());
1377 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1378 manager_->GetActiveIMEState()->ChangeInputMethod(ext_id2,
1379 false /* show_message */);
1381 manager_->GetActiveIMEState()->GetCurrentInputMethod().id());
1384 TEST_F(InputMethodManagerImplTest, MigrateInputMethodTest) {
1385 std::vector<std::string> input_method_ids;
1386 input_method_ids.push_back("xkb:us::eng");
1387 input_method_ids.push_back("xkb:fr::fra");
1388 input_method_ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
1389 input_method_ids.push_back("xkb:fr::fra");
1390 input_method_ids.push_back(ImeIdFromEngineId("xkb:us::eng"));
1391 input_method_ids.push_back("_comp_ime_asdf_pinyin");
1392 input_method_ids.push_back(ImeIdFromEngineId(kPinyinImeId));
1394 manager_->MigrateInputMethods(&input_method_ids);
1396 ASSERT_EQ(4U, input_method_ids.size());
1398 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), input_method_ids[0]);
1399 EXPECT_EQ(ImeIdFromEngineId("xkb:fr::fra"), input_method_ids[1]);
1400 EXPECT_EQ("_comp_ime_asdf_pinyin", input_method_ids[2]);
1401 EXPECT_EQ(ImeIdFromEngineId("zh-t-i0-pinyin"), input_method_ids[3]);
1404 } // namespace input_method
1405 } // namespace chromeos