Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / input_method / input_method_manager_impl_unittest.cc
blob3fe0b0f645d6e3ae29a40b9c76cf9362414be995
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"
7 #include <algorithm>
9 #include "base/basictypes.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "chrome/browser/chromeos/input_method/input_method_engine_interface.h"
17 #include "chrome/browser/chromeos/input_method/mock_candidate_window_controller.h"
18 #include "chrome/browser/chromeos/input_method/mock_input_method_engine.h"
19 #include "chromeos/ime/extension_ime_util.h"
20 #include "chromeos/ime/fake_input_method_delegate.h"
21 #include "chromeos/ime/mock_component_extension_ime_manager_delegate.h"
22 #include "chromeos/ime/mock_xkeyboard.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "ui/base/accelerators/accelerator.h"
25 #include "ui/base/ime/chromeos/mock_ime_engine_handler.h"
26 #include "ui/events/keycodes/keyboard_codes.h"
28 namespace chromeos {
30 namespace input_method {
31 namespace {
33 const char kNaclMozcUsId[] =
34 "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_us";
35 const char kNaclMozcJpId[] =
36 "_comp_ime_fpfbhcjppmaeaijcidgiibchfbnhbeljnacl_mozc_jp";
37 const char kExt2Engine1Id[] =
38 "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine1_engine_id";
39 const char kExt2Engine2Id[] =
40 "_comp_ime_nmblnjkfdkabgdofidlkienfnnbjhnabext2_engine2_engine_id";
42 // Returns true if |descriptors| contain |target|.
43 bool Contain(const InputMethodDescriptors& descriptors,
44 const InputMethodDescriptor& target) {
45 for (size_t i = 0; i < descriptors.size(); ++i) {
46 if (descriptors[i].id() == target.id())
47 return true;
49 return false;
52 class InputMethodManagerImplTest : public testing::Test {
53 public:
54 InputMethodManagerImplTest()
55 : delegate_(NULL),
56 candidate_window_controller_(NULL),
57 xkeyboard_(NULL) {
59 virtual ~InputMethodManagerImplTest() {}
61 virtual void SetUp() OVERRIDE {
62 delegate_ = new FakeInputMethodDelegate();
63 manager_.reset(new InputMethodManagerImpl(
64 scoped_ptr<InputMethodDelegate>(delegate_)));
65 candidate_window_controller_ = new MockCandidateWindowController;
66 manager_->SetCandidateWindowControllerForTesting(
67 candidate_window_controller_);
68 xkeyboard_ = new MockXKeyboard;
69 manager_->SetXKeyboardForTesting(xkeyboard_);
70 mock_engine_handler_.reset(new MockIMEEngineHandler());
71 IBusBridge::Initialize();
72 IBusBridge::Get()->SetCurrentEngineHandler(mock_engine_handler_.get());
74 ime_list_.clear();
76 ComponentExtensionIME ext1;
77 ext1.id = "fpfbhcjppmaeaijcidgiibchfbnhbelj";
78 ext1.description = "ext1_description";
79 ext1.path = base::FilePath("ext1_file_path");
81 ComponentExtensionEngine ext1_engine1;
82 ext1_engine1.engine_id = "nacl_mozc_us";
83 ext1_engine1.display_name = "ext1_engine_1_display_name";
84 ext1_engine1.language_codes.push_back("ja");
85 ext1_engine1.layouts.push_back("us");
86 ext1.engines.push_back(ext1_engine1);
88 ComponentExtensionEngine ext1_engine2;
89 ext1_engine2.engine_id = "nacl_mozc_jp";
90 ext1_engine2.display_name = "ext1_engine_1_display_name";
91 ext1_engine2.language_codes.push_back("ja");
92 ext1_engine2.layouts.push_back("jp");
93 ext1.engines.push_back(ext1_engine2);
95 ime_list_.push_back(ext1);
97 ComponentExtensionIME ext2;
98 ext2.id = "nmblnjkfdkabgdofidlkienfnnbjhnab";
99 ext2.description = "ext2_description";
100 ext2.path = base::FilePath("ext2_file_path");
102 ComponentExtensionEngine ext2_engine1;
103 ext2_engine1.engine_id = "ext2_engine1_engine_id";
104 ext2_engine1.display_name = "ext2_engine_1_display_name";
105 ext2_engine1.language_codes.push_back("en");
106 ext2_engine1.layouts.push_back("us");
107 ext2.engines.push_back(ext2_engine1);
109 ComponentExtensionEngine ext2_engine2;
110 ext2_engine2.engine_id = "ext2_engine2_engine_id";
111 ext2_engine2.display_name = "ext2_engine_2_display_name";
112 ext2_engine2.language_codes.push_back("en");
113 ext2_engine2.layouts.push_back("us(dvorak)");
114 ext2.engines.push_back(ext2_engine2);
116 ime_list_.push_back(ext2);
119 virtual void TearDown() OVERRIDE {
120 delegate_ = NULL;
121 candidate_window_controller_ = NULL;
122 xkeyboard_ = NULL;
123 manager_.reset();
124 IBusBridge::Get()->SetCurrentEngineHandler(NULL);
125 IBusBridge::Shutdown();
128 protected:
129 // Helper function to initialize component extension stuff for testing.
130 void InitComponentExtension() {
131 mock_delegate_ = new MockComponentExtIMEManagerDelegate();
132 mock_delegate_->set_ime_list(ime_list_);
133 scoped_ptr<ComponentExtensionIMEManagerDelegate> delegate(mock_delegate_);
134 // Note, for production, these SetEngineHandler are called when
135 // IBusEngineHandlerInterface is initialized via
136 // InitializeComponentextension.
137 IBusBridge::Get()->SetEngineHandler(kNaclMozcUsId,
138 mock_engine_handler_.get());
139 IBusBridge::Get()->SetEngineHandler(kNaclMozcJpId,
140 mock_engine_handler_.get());
141 IBusBridge::Get()->SetEngineHandler(kExt2Engine1Id,
142 mock_engine_handler_.get());
143 IBusBridge::Get()->SetEngineHandler(kExt2Engine2Id,
144 mock_engine_handler_.get());
145 manager_->InitializeComponentExtensionForTesting(delegate.Pass());
148 scoped_ptr<InputMethodManagerImpl> manager_;
149 FakeInputMethodDelegate* delegate_;
150 MockCandidateWindowController* candidate_window_controller_;
151 scoped_ptr<MockIMEEngineHandler> mock_engine_handler_;
152 MockXKeyboard* xkeyboard_;
153 base::MessageLoop message_loop_;
154 MockComponentExtIMEManagerDelegate* mock_delegate_;
155 std::vector<ComponentExtensionIME> ime_list_;
157 private:
158 DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImplTest);
161 class TestObserver : public InputMethodManager::Observer {
162 public:
163 TestObserver()
164 : input_method_changed_count_(0),
165 input_method_property_changed_count_(0),
166 last_show_message_(false) {
168 virtual ~TestObserver() {}
170 virtual void InputMethodChanged(InputMethodManager* manager,
171 bool show_message) OVERRIDE {
172 ++input_method_changed_count_;
173 last_show_message_ = show_message;
175 virtual void InputMethodPropertyChanged(
176 InputMethodManager* manager) OVERRIDE {
177 ++input_method_property_changed_count_;
180 int input_method_changed_count_;
181 int input_method_property_changed_count_;
182 bool last_show_message_;
184 private:
185 DISALLOW_COPY_AND_ASSIGN(TestObserver);
188 class TestCandidateWindowObserver
189 : public InputMethodManager::CandidateWindowObserver {
190 public:
191 TestCandidateWindowObserver()
192 : candidate_window_opened_count_(0),
193 candidate_window_closed_count_(0) {
195 virtual ~TestCandidateWindowObserver() {}
197 virtual void CandidateWindowOpened(InputMethodManager* manager) OVERRIDE {
198 ++candidate_window_opened_count_;
200 virtual void CandidateWindowClosed(InputMethodManager* manager) OVERRIDE {
201 ++candidate_window_closed_count_;
204 int candidate_window_opened_count_;
205 int candidate_window_closed_count_;
207 private:
208 DISALLOW_COPY_AND_ASSIGN(TestCandidateWindowObserver);
210 } // namespace
212 TEST_F(InputMethodManagerImplTest, TestGetXKeyboard) {
213 EXPECT_TRUE(manager_->GetXKeyboard());
214 EXPECT_EQ(xkeyboard_, manager_->GetXKeyboard());
217 TEST_F(InputMethodManagerImplTest, TestCandidateWindowObserver) {
218 TestCandidateWindowObserver observer;
219 candidate_window_controller_->NotifyCandidateWindowOpened(); // nop
220 candidate_window_controller_->NotifyCandidateWindowClosed(); // nop
221 manager_->AddCandidateWindowObserver(&observer);
222 candidate_window_controller_->NotifyCandidateWindowOpened();
223 EXPECT_EQ(1, observer.candidate_window_opened_count_);
224 candidate_window_controller_->NotifyCandidateWindowClosed();
225 EXPECT_EQ(1, observer.candidate_window_closed_count_);
226 candidate_window_controller_->NotifyCandidateWindowOpened();
227 EXPECT_EQ(2, observer.candidate_window_opened_count_);
228 candidate_window_controller_->NotifyCandidateWindowClosed();
229 EXPECT_EQ(2, observer.candidate_window_closed_count_);
230 manager_->RemoveCandidateWindowObserver(&observer);
233 TEST_F(InputMethodManagerImplTest, TestObserver) {
234 // For http://crbug.com/19655#c11 - (3). browser_state_monitor_unittest.cc is
235 // also for the scenario.
236 TestObserver observer;
237 InitComponentExtension();
238 manager_->AddObserver(&observer);
239 EXPECT_EQ(0, observer.input_method_changed_count_);
240 manager_->EnableLayouts("en-US", "xkb:us::eng");
241 EXPECT_EQ(1, observer.input_method_changed_count_);
242 EXPECT_EQ(1, observer.input_method_property_changed_count_);
243 manager_->ChangeInputMethod("xkb:us:dvorak:eng");
244 EXPECT_FALSE(observer.last_show_message_);
245 EXPECT_EQ(2, observer.input_method_changed_count_);
246 EXPECT_EQ(2, observer.input_method_property_changed_count_);
247 manager_->ChangeInputMethod("xkb:us:dvorak:eng");
248 EXPECT_FALSE(observer.last_show_message_);
250 // The observer is always notified even when the same input method ID is
251 // passed to ChangeInputMethod() more than twice.
252 // TODO(komatsu): Revisit if this is neccessary.
253 EXPECT_EQ(3, observer.input_method_changed_count_);
255 // If the same input method ID is passed, PropertyChanged() is not
256 // notified.
257 EXPECT_EQ(2, observer.input_method_property_changed_count_);
259 manager_->RemoveObserver(&observer);
262 TEST_F(InputMethodManagerImplTest, TestGetSupportedInputMethods) {
263 InitComponentExtension();
264 scoped_ptr<InputMethodDescriptors> methods(
265 manager_->GetSupportedInputMethods());
266 ASSERT_TRUE(methods.get());
267 // Try to find random 4-5 layuts and IMEs to make sure the returned list is
268 // correct.
269 const InputMethodDescriptor* id_to_find =
270 manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
271 kNaclMozcUsId);
272 id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
273 "xkb:us::eng");
274 EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
275 id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
276 "xkb:us:dvorak:eng");
277 EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
278 id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
279 "xkb:fr::fra");
280 EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
283 TEST_F(InputMethodManagerImplTest, TestEnableLayouts) {
284 // Currently 5 keyboard layouts are supported for en-US, and 1 for ja. See
285 // ibus_input_method.txt.
286 InitComponentExtension();
287 manager_->EnableLayouts("en-US", "");
288 EXPECT_EQ(5U, manager_->GetNumActiveInputMethods());
289 for (size_t i = 0; i < manager_->GetActiveInputMethodIds().size(); ++i)
290 LOG(ERROR) << manager_->GetActiveInputMethodIds().at(i);
292 // For http://crbug.com/19655#c11 - (5)
293 // The hardware keyboard layout "xkb:us::eng" is always active, hence 2U.
294 manager_->EnableLayouts("ja", ""); // Japanese
295 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
298 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsAndCurrentInputMethod) {
299 // For http://crbug.com/329061
300 manager_->EnableLayouts("en-US", "xkb:se::swe");
301 const std::string im_id = manager_->GetCurrentInputMethod().id();
302 EXPECT_EQ("xkb:se::swe", im_id);
305 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsNonUsHardwareKeyboard) {
306 // The physical layout is French.
307 delegate_->set_hardware_keyboard_layout("xkb:fr::fra");
308 manager_->EnableLayouts("en-US", "");
309 EXPECT_EQ(6U, manager_->GetNumActiveInputMethods()); // 5 + French
310 // The physical layout is Japanese.
311 delegate_->set_hardware_keyboard_layout("xkb:jp::jpn");
312 manager_->EnableLayouts("ja", "");
313 // "xkb:us::eng" is not needed, hence 1.
314 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
317 TEST_F(InputMethodManagerImplTest, TestActiveInputMethods) {
318 manager_->EnableLayouts("ja", ""); // Japanese
319 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
320 scoped_ptr<InputMethodDescriptors> methods(
321 manager_->GetActiveInputMethods());
322 ASSERT_TRUE(methods.get());
323 EXPECT_EQ(2U, methods->size());
324 const InputMethodDescriptor* id_to_find =
325 manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
326 "xkb:us::eng");
327 EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
328 id_to_find = manager_->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
329 "xkb:jp::jpn");
330 EXPECT_TRUE(Contain(*methods.get(), *id_to_find));
333 TEST_F(InputMethodManagerImplTest, TestEnableTwoLayouts) {
334 // For http://crbug.com/19655#c11 - (8), step 6.
335 TestObserver observer;
336 manager_->AddObserver(&observer);
337 InitComponentExtension();
338 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
339 std::vector<std::string> ids;
340 ids.push_back("xkb:us:dvorak:eng");
341 ids.push_back("xkb:us:colemak:eng");
342 EXPECT_TRUE(manager_->EnableInputMethods(ids));
343 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
344 // Since all the IDs added avobe are keyboard layouts, Start() should not be
345 // called.
346 EXPECT_EQ(1, observer.input_method_changed_count_);
347 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
348 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
349 // Disable Dvorak.
350 ids.erase(ids.begin());
351 EXPECT_TRUE(manager_->EnableInputMethods(ids));
352 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
353 EXPECT_EQ(2, observer.input_method_changed_count_);
354 EXPECT_EQ(ids[0], // colemak
355 manager_->GetCurrentInputMethod().id());
356 EXPECT_EQ("us(colemak)", xkeyboard_->last_layout_);
357 manager_->RemoveObserver(&observer);
360 TEST_F(InputMethodManagerImplTest, TestEnableThreeLayouts) {
361 // For http://crbug.com/19655#c11 - (9).
362 TestObserver observer;
363 manager_->AddObserver(&observer);
364 InitComponentExtension();
365 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
366 std::vector<std::string> ids;
367 ids.push_back("xkb:us::eng");
368 ids.push_back("xkb:us:dvorak:eng");
369 ids.push_back("xkb:us:colemak:eng");
370 EXPECT_TRUE(manager_->EnableInputMethods(ids));
371 EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());
372 EXPECT_EQ(1, observer.input_method_changed_count_);
373 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
374 EXPECT_EQ("us", xkeyboard_->last_layout_);
375 // Switch to Dvorak.
376 manager_->SwitchToNextInputMethod();
377 EXPECT_EQ(2, observer.input_method_changed_count_);
378 EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
379 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
380 // Disable Dvorak.
381 ids.erase(ids.begin() + 1);
382 EXPECT_TRUE(manager_->EnableInputMethods(ids));
383 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
384 EXPECT_EQ(3, observer.input_method_changed_count_);
385 EXPECT_EQ(ids[0], // US Qwerty
386 manager_->GetCurrentInputMethod().id());
387 EXPECT_EQ("us", xkeyboard_->last_layout_);
388 manager_->RemoveObserver(&observer);
391 TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme) {
392 // For http://crbug.com/19655#c11 - (10).
393 TestObserver observer;
394 manager_->AddObserver(&observer);
395 InitComponentExtension();
396 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
397 std::vector<std::string> ids;
398 ids.push_back("xkb:us:dvorak:eng");
399 ids.push_back(kNaclMozcUsId);
400 EXPECT_TRUE(manager_->EnableInputMethods(ids));
401 EXPECT_EQ(1, observer.input_method_changed_count_);
402 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
403 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
404 // Switch to Mozc
405 manager_->SwitchToNextInputMethod();
406 EXPECT_EQ(2, observer.input_method_changed_count_);
407 EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
408 EXPECT_EQ("us", xkeyboard_->last_layout_);
409 // Disable Mozc.
410 ids.erase(ids.begin() + 1);
411 EXPECT_TRUE(manager_->EnableInputMethods(ids));
412 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
413 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
414 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
417 TEST_F(InputMethodManagerImplTest, TestEnableLayoutAndIme2) {
418 // For http://crbug.com/19655#c11 - (11).
419 TestObserver observer;
420 manager_->AddObserver(&observer);
421 InitComponentExtension();
422 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
423 std::vector<std::string> ids;
424 ids.push_back("xkb:us:dvorak:eng");
425 ids.push_back(kNaclMozcUsId);
426 EXPECT_TRUE(manager_->EnableInputMethods(ids));
427 EXPECT_EQ(1, observer.input_method_changed_count_);
428 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
429 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
431 // Disable Dvorak.
432 ids.erase(ids.begin());
433 EXPECT_TRUE(manager_->EnableInputMethods(ids));
434 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
435 EXPECT_EQ(ids[0], // Mozc
436 manager_->GetCurrentInputMethod().id());
437 EXPECT_EQ("us", xkeyboard_->last_layout_);
438 manager_->RemoveObserver(&observer);
441 TEST_F(InputMethodManagerImplTest, TestEnableImes) {
442 TestObserver observer;
443 manager_->AddObserver(&observer);
444 InitComponentExtension();
445 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
446 std::vector<std::string> ids;
447 ids.push_back(kExt2Engine1Id);
448 ids.push_back("mozc-dv");
449 EXPECT_TRUE(manager_->EnableInputMethods(ids));
450 EXPECT_EQ(1, observer.input_method_changed_count_);
451 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
452 EXPECT_EQ("us", xkeyboard_->last_layout_);
453 manager_->RemoveObserver(&observer);
456 TEST_F(InputMethodManagerImplTest, TestEnableUnknownIds) {
457 TestObserver observer;
458 manager_->AddObserver(&observer);
459 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
460 std::vector<std::string> ids;
461 ids.push_back("xkb:tl::tlh"); // Klingon, which is not supported.
462 ids.push_back("unknown-super-cool-ime");
463 EXPECT_FALSE(manager_->EnableInputMethods(ids));
465 // TODO(yusukes): Should we fall back to the hardware keyboard layout in this
466 // case?
467 EXPECT_EQ(0, observer.input_method_changed_count_);
469 manager_->RemoveObserver(&observer);
472 TEST_F(InputMethodManagerImplTest, TestEnableLayoutsThenLock) {
473 // For http://crbug.com/19655#c11 - (14).
474 TestObserver observer;
475 manager_->AddObserver(&observer);
476 InitComponentExtension();
477 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
478 std::vector<std::string> ids;
479 ids.push_back("xkb:us::eng");
480 ids.push_back("xkb:us:dvorak:eng");
481 EXPECT_TRUE(manager_->EnableInputMethods(ids));
482 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
483 EXPECT_EQ(1, observer.input_method_changed_count_);
484 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
485 EXPECT_EQ("us", xkeyboard_->last_layout_);
487 // Switch to Dvorak.
488 manager_->SwitchToNextInputMethod();
489 EXPECT_EQ(2, observer.input_method_changed_count_);
490 EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
491 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
493 // Lock screen
494 manager_->SetState(InputMethodManager::STATE_LOCK_SCREEN);
495 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
496 EXPECT_EQ(ids[1], // still Dvorak
497 manager_->GetCurrentInputMethod().id());
498 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
499 // Switch back to Qwerty.
500 manager_->SwitchToNextInputMethod();
501 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
502 EXPECT_EQ("us", xkeyboard_->last_layout_);
504 // Unlock screen. The original state, Dvorak, is restored.
505 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
506 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
507 EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
508 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
510 manager_->RemoveObserver(&observer);
513 TEST_F(InputMethodManagerImplTest, SwitchInputMethodTest) {
514 // For http://crbug.com/19655#c11 - (15).
515 TestObserver observer;
516 manager_->AddObserver(&observer);
517 InitComponentExtension();
518 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
519 std::vector<std::string> ids;
520 ids.push_back("xkb:us:dvorak:eng");
521 ids.push_back(kExt2Engine2Id);
522 ids.push_back(kExt2Engine1Id);
523 EXPECT_TRUE(manager_->EnableInputMethods(ids));
524 EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());
525 EXPECT_EQ(1, observer.input_method_changed_count_);
526 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
527 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
529 // Switch to Mozc.
530 manager_->SwitchToNextInputMethod();
531 EXPECT_EQ(2, observer.input_method_changed_count_);
532 EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
533 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
535 // Lock screen
536 manager_->SetState(InputMethodManager::STATE_LOCK_SCREEN);
537 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods()); // Qwerty+Dvorak.
538 EXPECT_EQ("xkb:us:dvorak:eng",
539 manager_->GetCurrentInputMethod().id());
540 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
541 manager_->SwitchToNextInputMethod();
542 EXPECT_EQ("xkb:us::eng", // The hardware keyboard layout.
543 manager_->GetCurrentInputMethod().id());
544 EXPECT_EQ("us", xkeyboard_->last_layout_);
546 // Unlock screen. The original state, pinyin-dv, is restored.
547 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
548 EXPECT_EQ(3U, manager_->GetNumActiveInputMethods()); // Dvorak and 2 IMEs.
549 EXPECT_EQ(ids[1], manager_->GetCurrentInputMethod().id());
550 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
552 manager_->RemoveObserver(&observer);
555 TEST_F(InputMethodManagerImplTest, TestXkbSetting) {
556 // For http://crbug.com/19655#c11 - (8), step 7-11.
557 InitComponentExtension();
558 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
559 std::vector<std::string> ids;
560 ids.push_back("xkb:us:dvorak:eng");
561 ids.push_back("xkb:us:colemak:eng");
562 ids.push_back(kNaclMozcJpId);
563 ids.push_back(kNaclMozcUsId);
564 EXPECT_TRUE(manager_->EnableInputMethods(ids));
565 EXPECT_EQ(4U, manager_->GetNumActiveInputMethods());
566 EXPECT_EQ(1, xkeyboard_->set_current_keyboard_layout_by_name_count_);
567 // See input_methods.txt for an expected XKB layout name.
568 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
569 manager_->SwitchToNextInputMethod();
570 EXPECT_EQ(2, xkeyboard_->set_current_keyboard_layout_by_name_count_);
571 EXPECT_EQ("us(colemak)", xkeyboard_->last_layout_);
572 manager_->SwitchToNextInputMethod();
573 EXPECT_EQ(3, xkeyboard_->set_current_keyboard_layout_by_name_count_);
574 EXPECT_EQ("jp", xkeyboard_->last_layout_);
575 manager_->SwitchToNextInputMethod();
576 EXPECT_EQ(4, xkeyboard_->set_current_keyboard_layout_by_name_count_);
577 EXPECT_EQ("us", xkeyboard_->last_layout_);
578 manager_->SwitchToNextInputMethod();
579 EXPECT_EQ(5, xkeyboard_->set_current_keyboard_layout_by_name_count_);
580 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
581 // Disable Dvorak.
582 ids.erase(ids.begin());
583 EXPECT_TRUE(manager_->EnableInputMethods(ids));
584 EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());
585 EXPECT_EQ(6, xkeyboard_->set_current_keyboard_layout_by_name_count_);
586 EXPECT_EQ("us(colemak)", xkeyboard_->last_layout_);
589 TEST_F(InputMethodManagerImplTest, TestActivateInputMethodProperty) {
590 const std::string kKey = "key";
591 InputMethodPropertyList property_list;
592 property_list.push_back(InputMethodProperty(kKey, "label", false, false));
593 manager_->SetCurrentInputMethodProperties(property_list);
595 manager_->ActivateInputMethodProperty(kKey);
596 EXPECT_EQ(kKey, mock_engine_handler_->last_activated_property());
598 // Key2 is not registered, so activated property should not be changed.
599 manager_->ActivateInputMethodProperty("key2");
600 EXPECT_EQ(kKey, mock_engine_handler_->last_activated_property());
603 TEST_F(InputMethodManagerImplTest, TestGetCurrentInputMethodProperties) {
604 InitComponentExtension();
605 EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
607 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
608 std::vector<std::string> ids;
609 ids.push_back("xkb:us::eng");
610 ids.push_back(kNaclMozcUsId);
611 EXPECT_TRUE(manager_->EnableInputMethods(ids));
612 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
613 EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
614 manager_->ChangeInputMethod(kNaclMozcUsId);
616 InputMethodPropertyList current_property_list;
617 current_property_list.push_back(InputMethodProperty("key",
618 "label",
619 false,
620 false));
621 manager_->SetCurrentInputMethodProperties(current_property_list);
623 ASSERT_EQ(1U, manager_->GetCurrentInputMethodProperties().size());
624 EXPECT_EQ("key", manager_->GetCurrentInputMethodProperties().at(0).key);
626 manager_->ChangeInputMethod("xkb:us::eng");
627 EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
630 TEST_F(InputMethodManagerImplTest, TestGetCurrentInputMethodPropertiesTwoImes) {
631 InitComponentExtension();
632 EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
634 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
635 std::vector<std::string> ids;
636 ids.push_back(kNaclMozcUsId); // Japanese
637 ids.push_back(kExt2Engine1Id); // T-Chinese
638 EXPECT_TRUE(manager_->EnableInputMethods(ids));
639 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
640 EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
642 InputMethodPropertyList current_property_list;
643 current_property_list.push_back(InputMethodProperty("key-mozc",
644 "label",
645 false,
646 false));
647 manager_->SetCurrentInputMethodProperties(current_property_list);
649 ASSERT_EQ(1U, manager_->GetCurrentInputMethodProperties().size());
650 EXPECT_EQ("key-mozc", manager_->GetCurrentInputMethodProperties().at(0).key);
652 manager_->ChangeInputMethod(kExt2Engine1Id);
653 // Since the IME is changed, the property for mozc Japanese should be hidden.
654 EXPECT_TRUE(manager_->GetCurrentInputMethodProperties().empty());
656 // Asynchronous property update signal from mozc-chewing.
657 current_property_list.clear();
658 current_property_list.push_back(InputMethodProperty("key-chewing",
659 "label",
660 false,
661 false));
662 manager_->SetCurrentInputMethodProperties(current_property_list);
663 ASSERT_EQ(1U, manager_->GetCurrentInputMethodProperties().size());
664 EXPECT_EQ("key-chewing",
665 manager_->GetCurrentInputMethodProperties().at(0).key);
668 TEST_F(InputMethodManagerImplTest, TestNextInputMethod) {
669 TestObserver observer;
670 manager_->AddObserver(&observer);
671 InitComponentExtension();
672 // For http://crbug.com/19655#c11 - (1)
673 manager_->EnableLayouts("en-US", "xkb:us::eng");
674 EXPECT_EQ(5U, manager_->GetNumActiveInputMethods());
675 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
676 EXPECT_EQ("us", xkeyboard_->last_layout_);
677 manager_->SwitchToNextInputMethod();
678 EXPECT_TRUE(observer.last_show_message_);
679 EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
680 EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
681 manager_->SwitchToNextInputMethod();
682 EXPECT_TRUE(observer.last_show_message_);
683 EXPECT_EQ("xkb:us:altgr-intl:eng", manager_->GetCurrentInputMethod().id());
684 EXPECT_EQ("us(altgr-intl)", xkeyboard_->last_layout_);
685 manager_->SwitchToNextInputMethod();
686 EXPECT_TRUE(observer.last_show_message_);
687 EXPECT_EQ("xkb:us:dvorak:eng", manager_->GetCurrentInputMethod().id());
688 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
689 manager_->SwitchToNextInputMethod();
690 EXPECT_TRUE(observer.last_show_message_);
691 EXPECT_EQ("xkb:us:colemak:eng", manager_->GetCurrentInputMethod().id());
692 EXPECT_EQ("us(colemak)", xkeyboard_->last_layout_);
693 manager_->SwitchToNextInputMethod();
694 EXPECT_TRUE(observer.last_show_message_);
695 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
696 EXPECT_EQ("us", xkeyboard_->last_layout_);
698 manager_->RemoveObserver(&observer);
701 TEST_F(InputMethodManagerImplTest, TestPreviousInputMethod) {
702 TestObserver observer;
703 manager_->AddObserver(&observer);
704 InitComponentExtension();
706 ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
707 keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
708 ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
709 keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
711 manager_->EnableLayouts("en-US", "xkb:us::eng");
712 EXPECT_EQ(5U, manager_->GetNumActiveInputMethods());
713 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
714 EXPECT_EQ("us", xkeyboard_->last_layout_);
715 EXPECT_TRUE(manager_->SwitchToNextInputMethod());
716 EXPECT_TRUE(observer.last_show_message_);
717 EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
718 EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
719 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
720 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
721 EXPECT_TRUE(observer.last_show_message_);
722 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
723 EXPECT_EQ("us", xkeyboard_->last_layout_);
724 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
725 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
726 EXPECT_TRUE(observer.last_show_message_);
727 EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
728 EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
729 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
730 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
731 EXPECT_TRUE(observer.last_show_message_);
732 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
733 EXPECT_EQ("us", xkeyboard_->last_layout_);
734 EXPECT_TRUE(manager_->SwitchToNextInputMethod());
735 EXPECT_TRUE(observer.last_show_message_);
736 EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
737 EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
738 EXPECT_TRUE(manager_->SwitchToNextInputMethod());
739 EXPECT_TRUE(observer.last_show_message_);
740 EXPECT_EQ("xkb:us:altgr-intl:eng", manager_->GetCurrentInputMethod().id());
741 EXPECT_EQ("us(altgr-intl)", xkeyboard_->last_layout_);
742 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
743 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
744 EXPECT_TRUE(observer.last_show_message_);
745 EXPECT_EQ("xkb:us:intl:eng", manager_->GetCurrentInputMethod().id());
746 EXPECT_EQ("us(intl)", xkeyboard_->last_layout_);
747 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
748 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
749 EXPECT_TRUE(observer.last_show_message_);
750 EXPECT_EQ("xkb:us:altgr-intl:eng", manager_->GetCurrentInputMethod().id());
751 EXPECT_EQ("us(altgr-intl)", xkeyboard_->last_layout_);
753 manager_->RemoveObserver(&observer);
756 TEST_F(InputMethodManagerImplTest,
757 TestSwitchToPreviousInputMethodForOneActiveInputMethod) {
758 TestObserver observer;
759 manager_->AddObserver(&observer);
760 InitComponentExtension();
762 ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
763 keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
764 ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
765 keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
767 std::vector<std::string> ids;
768 ids.push_back("xkb:us:dvorak:eng");
769 EXPECT_TRUE(manager_->EnableInputMethods(ids));
770 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
772 // Ctrl+Space accelerator should not be consumed if there is only one active
773 // input method.
774 EXPECT_FALSE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
775 EXPECT_FALSE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
777 manager_->RemoveObserver(&observer);
780 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithUsLayouts) {
781 TestObserver observer;
782 manager_->AddObserver(&observer);
783 InitComponentExtension();
784 manager_->EnableLayouts("en-US", "xkb:us::eng");
785 EXPECT_EQ(5U, manager_->GetNumActiveInputMethods());
786 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
787 EXPECT_EQ("us", xkeyboard_->last_layout_);
789 // Henkan, Muhenkan, ZenkakuHankaku should be ignored when no Japanese IMEs
790 // and keyboards are enabled.
791 EXPECT_FALSE(manager_->SwitchInputMethod(
792 ui::Accelerator(ui::VKEY_CONVERT, ui::EF_NONE)));
793 EXPECT_FALSE(observer.last_show_message_);
794 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
795 EXPECT_EQ("us", xkeyboard_->last_layout_);
796 EXPECT_FALSE(manager_->SwitchInputMethod(
797 ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
798 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
799 EXPECT_EQ("us", xkeyboard_->last_layout_);
800 EXPECT_FALSE(manager_->SwitchInputMethod(
801 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
802 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
803 EXPECT_EQ("us", xkeyboard_->last_layout_);
804 EXPECT_FALSE(manager_->SwitchInputMethod(
805 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
806 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
807 EXPECT_EQ("us", xkeyboard_->last_layout_);
809 manager_->RemoveObserver(&observer);
812 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpLayout) {
813 // Enable "xkb:jp::jpn" and press Muhenkan/ZenkakuHankaku.
814 InitComponentExtension();
816 ui::Accelerator keydown_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
817 keydown_accelerator.set_type(ui::ET_KEY_PRESSED);
818 ui::Accelerator keyup_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN);
819 keyup_accelerator.set_type(ui::ET_KEY_RELEASED);
821 manager_->EnableLayouts("ja", "xkb:us::eng");
822 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
823 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
824 EXPECT_EQ("us", xkeyboard_->last_layout_);
825 EXPECT_TRUE(manager_->SwitchInputMethod(
826 ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
827 EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
828 EXPECT_EQ("jp", xkeyboard_->last_layout_);
829 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
830 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
831 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
832 EXPECT_EQ("us", xkeyboard_->last_layout_);
833 EXPECT_TRUE(manager_->SwitchInputMethod(
834 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
835 EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
836 EXPECT_EQ("jp", xkeyboard_->last_layout_);
837 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keydown_accelerator));
838 EXPECT_TRUE(manager_->SwitchToPreviousInputMethod(keyup_accelerator));
839 EXPECT_EQ("xkb:us::eng", manager_->GetCurrentInputMethod().id());
840 EXPECT_EQ("us", xkeyboard_->last_layout_);
841 EXPECT_TRUE(manager_->SwitchInputMethod(
842 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
843 EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
844 EXPECT_EQ("jp", xkeyboard_->last_layout_);
847 TEST_F(InputMethodManagerImplTest, TestSwitchInputMethodWithJpIme) {
848 InitComponentExtension();
849 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
850 std::vector<std::string> ids;
851 ids.push_back("xkb:jp::jpn");
852 ids.push_back(kNaclMozcJpId);
853 EXPECT_TRUE(manager_->EnableInputMethods(ids));
854 EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
855 EXPECT_EQ("jp", xkeyboard_->last_layout_);
856 EXPECT_TRUE(manager_->SwitchInputMethod(
857 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
858 EXPECT_EQ(kNaclMozcJpId, manager_->GetCurrentInputMethod().id());
859 EXPECT_EQ("jp", xkeyboard_->last_layout_);
860 EXPECT_TRUE(manager_->SwitchInputMethod(
861 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR, ui::EF_NONE)));
862 EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
863 EXPECT_EQ("jp", xkeyboard_->last_layout_);
864 EXPECT_TRUE(manager_->SwitchInputMethod(
865 ui::Accelerator(ui::VKEY_CONVERT, ui::EF_NONE)));
866 EXPECT_EQ(kNaclMozcJpId, manager_->GetCurrentInputMethod().id());
867 EXPECT_EQ("jp", xkeyboard_->last_layout_);
868 EXPECT_TRUE(manager_->SwitchInputMethod(
869 ui::Accelerator(ui::VKEY_CONVERT, ui::EF_NONE)));
870 EXPECT_EQ(kNaclMozcJpId, manager_->GetCurrentInputMethod().id());
871 EXPECT_EQ("jp", xkeyboard_->last_layout_);
872 EXPECT_TRUE(manager_->SwitchInputMethod(
873 ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
874 EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
875 EXPECT_EQ("jp", xkeyboard_->last_layout_);
876 EXPECT_TRUE(manager_->SwitchInputMethod(
877 ui::Accelerator(ui::VKEY_NONCONVERT, ui::EF_NONE)));
878 EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
879 EXPECT_EQ("jp", xkeyboard_->last_layout_);
881 // Add Dvorak.
882 ids.push_back("xkb:us:dvorak:eng");
883 EXPECT_TRUE(manager_->EnableInputMethods(ids));
884 EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
885 EXPECT_EQ("jp", xkeyboard_->last_layout_);
886 EXPECT_TRUE(manager_->SwitchInputMethod(
887 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
888 EXPECT_EQ(kNaclMozcJpId, manager_->GetCurrentInputMethod().id());
889 EXPECT_EQ("jp", xkeyboard_->last_layout_);
890 EXPECT_TRUE(manager_->SwitchInputMethod(
891 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR, ui::EF_NONE)));
892 EXPECT_EQ("xkb:jp::jpn", manager_->GetCurrentInputMethod().id());
893 EXPECT_EQ("jp", xkeyboard_->last_layout_);
896 TEST_F(InputMethodManagerImplTest, TestAddRemoveExtensionInputMethods) {
897 TestObserver observer;
898 manager_->AddObserver(&observer);
899 InitComponentExtension();
900 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
901 std::vector<std::string> ids;
902 ids.push_back("xkb:us:dvorak:eng");
903 EXPECT_TRUE(manager_->EnableInputMethods(ids));
904 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
905 EXPECT_EQ(1, observer.input_method_changed_count_);
906 EXPECT_EQ(ids[0],
907 manager_->GetCurrentInputMethod().id());
908 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
910 // Add two Extension IMEs.
911 std::vector<std::string> layouts;
912 layouts.push_back("us");
913 std::vector<std::string> languages;
914 languages.push_back("en-US");
916 const std::string ext1_id =
917 extension_ime_util::GetInputMethodID("deadbeef", "engine_id");
918 const InputMethodDescriptor descriptor1(ext1_id,
919 "deadbeef input method",
920 layouts,
921 languages,
922 false, // is_login_keyboard
923 GURL(),
924 GURL());
925 MockInputMethodEngine engine(descriptor1);
926 manager_->AddInputMethodExtension(ext1_id, &engine);
928 // Extension IMEs are not enabled by default.
929 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
931 std::vector<std::string> extension_ime_ids;
932 extension_ime_ids.push_back(ext1_id);
933 manager_->SetEnabledExtensionImes(&extension_ime_ids);
934 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
937 scoped_ptr<InputMethodDescriptors> methods(
938 manager_->GetActiveInputMethods());
939 ASSERT_EQ(2U, methods->size());
940 // Ext IMEs should be at the end of the list.
941 EXPECT_EQ(ext1_id, methods->at(1).id());
944 const std::string ext2_id =
945 extension_ime_util::GetInputMethodID("cafebabe", "engine_id");
946 const InputMethodDescriptor descriptor2(ext2_id,
947 "cafebabe input method",
948 layouts,
949 languages,
950 false, // is_login_keyboard
951 GURL(),
952 GURL());
953 MockInputMethodEngine engine2(descriptor2);
954 manager_->AddInputMethodExtension(ext2_id, &engine2);
955 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
957 extension_ime_ids.push_back(ext2_id);
958 manager_->SetEnabledExtensionImes(&extension_ime_ids);
959 EXPECT_EQ(3U, manager_->GetNumActiveInputMethods());
961 scoped_ptr<InputMethodDescriptors> methods(
962 manager_->GetActiveInputMethods());
963 ASSERT_EQ(3U, methods->size());
964 // Ext IMEs should be at the end of the list.
965 EXPECT_EQ(ext1_id, methods->at(1).id());
966 EXPECT_EQ(ext2_id, methods->at(2).id());
969 // Remove them.
970 manager_->RemoveInputMethodExtension(ext1_id);
971 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
972 manager_->RemoveInputMethodExtension(ext2_id);
973 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
976 TEST_F(InputMethodManagerImplTest, TestAddExtensionInputThenLockScreen) {
977 TestObserver observer;
978 InitComponentExtension();
979 manager_->AddObserver(&observer);
980 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
981 std::vector<std::string> ids;
982 ids.push_back("xkb:us::eng");
983 EXPECT_TRUE(manager_->EnableInputMethods(ids));
984 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
985 EXPECT_EQ(1, observer.input_method_changed_count_);
986 EXPECT_EQ(ids[0], manager_->GetCurrentInputMethod().id());
987 EXPECT_EQ("us", xkeyboard_->last_layout_);
989 // Add an Extension IME.
990 std::vector<std::string> layouts;
991 layouts.push_back("us(dvorak)");
992 std::vector<std::string> languages;
993 languages.push_back("en-US");
995 const std::string ext_id =
996 extension_ime_util::GetInputMethodID("deadbeef", "engine_id");
997 const InputMethodDescriptor descriptor(ext_id,
998 "deadbeef input method",
999 layouts,
1000 languages,
1001 false, // is_login_keyboard
1002 GURL(),
1003 GURL());
1004 MockInputMethodEngine engine(descriptor);
1005 manager_->AddInputMethodExtension(ext_id, &engine);
1007 // Extension IME is not enabled by default.
1008 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
1009 EXPECT_EQ(1, observer.input_method_changed_count_);
1011 std::vector<std::string> extension_ime_ids;
1012 extension_ime_ids.push_back(ext_id);
1013 manager_->SetEnabledExtensionImes(&extension_ime_ids);
1014 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
1016 // Switch to the IME.
1017 manager_->SwitchToNextInputMethod();
1018 EXPECT_EQ(3, observer.input_method_changed_count_);
1019 EXPECT_EQ(ext_id, manager_->GetCurrentInputMethod().id());
1020 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
1022 // Lock the screen. This is for crosbug.com/27049.
1023 manager_->SetState(InputMethodManager::STATE_LOCK_SCREEN);
1024 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods()); // Qwerty. No Ext. IME
1025 EXPECT_EQ("xkb:us::eng",
1026 manager_->GetCurrentInputMethod().id());
1027 EXPECT_EQ("us", xkeyboard_->last_layout_);
1029 // Unlock the screen.
1030 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
1031 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
1032 EXPECT_EQ(ext_id, manager_->GetCurrentInputMethod().id());
1033 EXPECT_EQ("us(dvorak)", xkeyboard_->last_layout_);
1035 // This is for crosbug.com/27052.
1036 scoped_ptr<InputMethodDescriptors> methods(
1037 manager_->GetActiveInputMethods());
1038 ASSERT_EQ(2U, methods->size());
1039 // Ext. IMEs should be at the end of the list.
1040 EXPECT_EQ(ext_id, methods->at(1).id());
1042 manager_->RemoveObserver(&observer);
1045 TEST_F(InputMethodManagerImplTest,
1046 ChangeInputMethodBeforeComponentExtensionInitialization_OneIME) {
1047 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
1048 std::vector<std::string> ids;
1049 ids.push_back(kNaclMozcUsId);
1050 EXPECT_TRUE(manager_->EnableInputMethods(ids));
1051 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
1052 manager_->ChangeInputMethod(kNaclMozcUsId);
1054 InitComponentExtension();
1055 EXPECT_EQ(kNaclMozcUsId, manager_->GetCurrentInputMethod().id());
1058 TEST_F(InputMethodManagerImplTest,
1059 ChangeInputMethodBeforeComponentExtensionInitialization_TwoIME) {
1060 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
1061 std::vector<std::string> ids;
1062 ids.push_back(kNaclMozcUsId);
1063 ids.push_back(kNaclMozcJpId);
1064 EXPECT_TRUE(manager_->EnableInputMethods(ids));
1065 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
1066 manager_->ChangeInputMethod(kNaclMozcUsId);
1067 manager_->ChangeInputMethod(kNaclMozcJpId);
1069 InitComponentExtension();
1070 EXPECT_EQ(kNaclMozcJpId, manager_->GetCurrentInputMethod().id());
1073 TEST_F(InputMethodManagerImplTest,
1074 ChangeInputMethodBeforeComponentExtensionInitialization_CompOneIME) {
1075 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
1076 const std::string ext_id = extension_ime_util::GetComponentInputMethodID(
1077 ime_list_[0].id,
1078 ime_list_[0].engines[0].engine_id);
1079 std::vector<std::string> ids;
1080 ids.push_back(ext_id);
1081 EXPECT_TRUE(manager_->EnableInputMethods(ids));
1082 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
1083 manager_->ChangeInputMethod(ext_id);
1085 InitComponentExtension();
1086 EXPECT_EQ(ext_id, manager_->GetCurrentInputMethod().id());
1089 TEST_F(InputMethodManagerImplTest,
1090 ChangeInputMethodBeforeComponentExtensionInitialization_CompTwoIME) {
1091 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
1092 const std::string ext_id1 = extension_ime_util::GetComponentInputMethodID(
1093 ime_list_[0].id,
1094 ime_list_[0].engines[0].engine_id);
1095 const std::string ext_id2 = extension_ime_util::GetComponentInputMethodID(
1096 ime_list_[1].id,
1097 ime_list_[1].engines[0].engine_id);
1098 std::vector<std::string> ids;
1099 ids.push_back(ext_id1);
1100 ids.push_back(ext_id2);
1101 EXPECT_TRUE(manager_->EnableInputMethods(ids));
1102 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
1103 manager_->ChangeInputMethod(ext_id1);
1104 manager_->ChangeInputMethod(ext_id2);
1106 InitComponentExtension();
1107 EXPECT_EQ(ext_id2, manager_->GetCurrentInputMethod().id());
1110 TEST_F(InputMethodManagerImplTest,
1111 ChangeInputMethod_ComponenteExtensionOneIME) {
1112 InitComponentExtension();
1113 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
1114 const std::string ext_id = extension_ime_util::GetComponentInputMethodID(
1115 ime_list_[0].id,
1116 ime_list_[0].engines[0].engine_id);
1117 std::vector<std::string> ids;
1118 ids.push_back(ext_id);
1119 EXPECT_TRUE(manager_->EnableInputMethods(ids));
1120 EXPECT_EQ(1U, manager_->GetNumActiveInputMethods());
1121 EXPECT_EQ(ext_id, manager_->GetCurrentInputMethod().id());
1124 TEST_F(InputMethodManagerImplTest,
1125 ChangeInputMethod_ComponenteExtensionTwoIME) {
1126 InitComponentExtension();
1127 manager_->SetState(InputMethodManager::STATE_BROWSER_SCREEN);
1128 const std::string ext_id1 = extension_ime_util::GetComponentInputMethodID(
1129 ime_list_[0].id,
1130 ime_list_[0].engines[0].engine_id);
1131 const std::string ext_id2 = extension_ime_util::GetComponentInputMethodID(
1132 ime_list_[1].id,
1133 ime_list_[1].engines[0].engine_id);
1134 std::vector<std::string> ids;
1135 ids.push_back(ext_id1);
1136 ids.push_back(ext_id2);
1137 EXPECT_TRUE(manager_->EnableInputMethods(ids));
1138 EXPECT_EQ(2U, manager_->GetNumActiveInputMethods());
1139 EXPECT_EQ(ext_id1, manager_->GetCurrentInputMethod().id());
1140 manager_->ChangeInputMethod(ext_id2);
1141 EXPECT_EQ(ext_id2, manager_->GetCurrentInputMethod().id());
1144 } // namespace input_method
1145 } // namespace chromeos