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 "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"
30 namespace input_method
{
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())
52 class InputMethodManagerImplTest
: public testing::Test
{
54 InputMethodManagerImplTest()
56 candidate_window_controller_(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());
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
{
121 candidate_window_controller_
= NULL
;
124 IBusBridge::Get()->SetCurrentEngineHandler(NULL
);
125 IBusBridge::Shutdown();
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_
;
158 DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImplTest
);
161 class TestObserver
: public InputMethodManager::Observer
{
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_
;
185 DISALLOW_COPY_AND_ASSIGN(TestObserver
);
188 class TestCandidateWindowObserver
189 : public InputMethodManager::CandidateWindowObserver
{
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_
;
208 DISALLOW_COPY_AND_ASSIGN(TestCandidateWindowObserver
);
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
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
269 const InputMethodDescriptor
* id_to_find
=
270 manager_
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
272 id_to_find
= manager_
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
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(
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(
327 EXPECT_TRUE(Contain(*methods
.get(), *id_to_find
));
328 id_to_find
= manager_
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
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
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_
);
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_
);
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_
);
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_
);
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_
);
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_
);
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
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_
);
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_
);
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_
);
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_
);
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_
);
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",
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",
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",
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
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_
);
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_
);
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",
922 false, // is_login_keyboard
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",
950 false, // is_login_keyboard
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());
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",
1001 false, // is_login_keyboard
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(
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(
1094 ime_list_
[0].engines
[0].engine_id
);
1095 const std::string ext_id2
= extension_ime_util::GetComponentInputMethodID(
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(
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(
1130 ime_list_
[0].engines
[0].engine_id
);
1131 const std::string ext_id2
= extension_ime_util::GetComponentInputMethodID(
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