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 "base/run_loop.h"
17 #include "chrome/browser/chromeos/input_method/input_method_engine_interface.h"
18 #include "chrome/browser/chromeos/input_method/mock_candidate_window_controller.h"
19 #include "chrome/browser/chromeos/input_method/mock_input_method_engine.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/test/base/browser_with_test_window_test.h"
22 #include "chrome/test/base/testing_browser_process.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "chrome/test/base/testing_profile_manager.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "ui/base/accelerators/accelerator.h"
27 #include "ui/base/ime/chromeos/extension_ime_util.h"
28 #include "ui/base/ime/chromeos/fake_ime_keyboard.h"
29 #include "ui/base/ime/chromeos/fake_input_method_delegate.h"
30 #include "ui/base/ime/chromeos/mock_component_extension_ime_manager_delegate.h"
31 #include "ui/base/ime/chromeos/mock_ime_engine_handler.h"
32 #include "ui/base/ime/input_method_initializer.h"
33 #include "ui/chromeos/ime/input_method_menu_item.h"
34 #include "ui/chromeos/ime/input_method_menu_manager.h"
35 #include "ui/events/keycodes/keyboard_codes.h"
39 namespace input_method
{
42 const char kNaclMozcUsId
[] = "nacl_mozc_us";
43 const char kNaclMozcJpId
[] = "nacl_mozc_jp";
44 const char kExt2Engine1Id
[] = "ext2_engine1-t-i0-engine_id";
45 const char kExt2Engine2Id
[] = "ext2_engine2-t-i0-engine_id";
46 const char kPinyinImeId
[] = "zh-t-i0-pinyin";
47 const char kExtensionId1
[] = "00000000000000000000000000000000";
48 const char kExtensionId2
[] = "11111111111111111111111111111111";
50 // Returns true if |descriptors| contain |target|.
51 bool Contain(const InputMethodDescriptors
& descriptors
,
52 const InputMethodDescriptor
& target
) {
53 for (size_t i
= 0; i
< descriptors
.size(); ++i
) {
54 if (descriptors
[i
].id() == target
.id())
60 std::string
ImeIdFromEngineId(const std::string
& id
) {
61 return extension_ime_util::GetInputMethodIDByEngineID(id
);
64 class TestObserver
: public InputMethodManager::Observer
,
65 public ui::ime::InputMethodMenuManager::Observer
{
68 : input_method_changed_count_(0),
69 input_method_menu_item_changed_count_(0),
70 last_show_message_(false) {
72 ~TestObserver() override
{}
74 void InputMethodChanged(InputMethodManager
* manager
,
75 Profile
* /* profile */,
76 bool show_message
) override
{
77 ++input_method_changed_count_
;
78 last_show_message_
= show_message
;
80 void InputMethodMenuItemChanged(
81 ui::ime::InputMethodMenuManager
* manager
) override
{
82 ++input_method_menu_item_changed_count_
;
85 int input_method_changed_count_
;
86 int input_method_menu_item_changed_count_
;
87 bool last_show_message_
;
90 DISALLOW_COPY_AND_ASSIGN(TestObserver
);
93 class TestCandidateWindowObserver
94 : public InputMethodManager::CandidateWindowObserver
{
96 TestCandidateWindowObserver()
97 : candidate_window_opened_count_(0),
98 candidate_window_closed_count_(0) {
101 ~TestCandidateWindowObserver() override
{}
103 void CandidateWindowOpened(InputMethodManager
* manager
) override
{
104 ++candidate_window_opened_count_
;
106 void CandidateWindowClosed(InputMethodManager
* manager
) override
{
107 ++candidate_window_closed_count_
;
110 int candidate_window_opened_count_
;
111 int candidate_window_closed_count_
;
114 DISALLOW_COPY_AND_ASSIGN(TestCandidateWindowObserver
);
118 class InputMethodManagerImplTest
: public BrowserWithTestWindowTest
{
120 InputMethodManagerImplTest()
122 candidate_window_controller_(NULL
),
125 ~InputMethodManagerImplTest() override
{}
127 void SetUp() override
{
128 profile_manager_
.reset(new TestingProfileManager(GetBrowserProcess()));
129 ASSERT_TRUE(profile_manager_
->SetUp());
131 ui::InitializeInputMethodForTesting();
133 delegate_
= new FakeInputMethodDelegate();
134 manager_
.reset(new InputMethodManagerImpl(
135 scoped_ptr
<InputMethodDelegate
>(delegate_
), false));
136 manager_
->GetInputMethodUtil()->UpdateHardwareLayoutCache();
137 candidate_window_controller_
= new MockCandidateWindowController
;
138 manager_
->SetCandidateWindowControllerForTesting(
139 candidate_window_controller_
);
140 keyboard_
= new FakeImeKeyboard
;
141 manager_
->SetImeKeyboardForTesting(keyboard_
);
142 mock_engine_handler_
.reset(new MockInputMethodEngine());
143 IMEBridge::Initialize();
144 IMEBridge::Get()->SetCurrentEngineHandler(mock_engine_handler_
.get());
146 menu_manager_
= ui::ime::InputMethodMenuManager::GetInstance();
150 BrowserWithTestWindowTest::SetUp();
153 void TearDown() override
{
154 BrowserWithTestWindowTest::TearDown();
156 ui::ShutdownInputMethodForTesting();
159 candidate_window_controller_
= NULL
;
163 profile_manager_
.reset();
167 // Helper function to initialize component extension stuff for testing.
168 void InitComponentExtension() {
169 mock_delegate_
= new MockComponentExtIMEManagerDelegate();
170 mock_delegate_
->set_ime_list(ime_list_
);
171 scoped_ptr
<ComponentExtensionIMEManagerDelegate
> delegate(mock_delegate_
);
173 // CreateNewState(NULL) returns state with non-empty current_input_method.
174 // So SetState() triggers ChangeInputMethod().
176 manager_
->CreateNewState(ProfileManager::GetActiveUserProfile()));
178 std::vector
<std::string
> layouts
;
179 layouts
.push_back("us");
180 std::vector
<std::string
> languages
;
181 languages
.push_back("en-US");
183 // Note, for production, these SetEngineHandler are called when
184 // IMEEngineHandlerInterface is initialized via
185 // InitializeComponentextension.
186 InputMethodDescriptors descriptors
;
187 manager_
->GetActiveIMEState()->AddInputMethodExtension(
188 ImeIdFromEngineId(kNaclMozcUsId
),
190 mock_engine_handler_
.get());
191 manager_
->GetActiveIMEState()->AddInputMethodExtension(
192 ImeIdFromEngineId(kExt2Engine1Id
),
194 mock_engine_handler_
.get());
195 manager_
->InitializeComponentExtensionForTesting(delegate
.Pass());
201 ComponentExtensionIME ext_xkb
;
202 ext_xkb
.id
= extension_ime_util::kXkbExtensionId
;
203 ext_xkb
.description
= "ext_xkb_description";
204 ext_xkb
.path
= base::FilePath("ext_xkb_file_path");
206 ComponentExtensionEngine ext_xkb_engine_us
;
207 ext_xkb_engine_us
.engine_id
= "xkb:us::eng";
208 ext_xkb_engine_us
.display_name
= "xkb:us::eng";
209 ext_xkb_engine_us
.language_codes
.push_back("en-US");
210 ext_xkb_engine_us
.layouts
.push_back("us");
211 ext_xkb
.engines
.push_back(ext_xkb_engine_us
);
213 ComponentExtensionEngine ext_xkb_engine_intl
;
214 ext_xkb_engine_intl
.engine_id
= "xkb:us:intl:eng";
215 ext_xkb_engine_intl
.display_name
= "xkb:us:intl:eng";
216 ext_xkb_engine_intl
.language_codes
.push_back("en-US");
217 ext_xkb_engine_intl
.layouts
.push_back("us(intl)");
218 ext_xkb
.engines
.push_back(ext_xkb_engine_intl
);
220 ComponentExtensionEngine ext_xkb_engine_altgr_intl
;
221 ext_xkb_engine_altgr_intl
.engine_id
= "xkb:us:altgr-intl:eng";
222 ext_xkb_engine_altgr_intl
.display_name
= "xkb:us:altgr-intl:eng";
223 ext_xkb_engine_altgr_intl
.language_codes
.push_back("en-US");
224 ext_xkb_engine_altgr_intl
.layouts
.push_back("us(altgr-intl)");
225 ext_xkb
.engines
.push_back(ext_xkb_engine_altgr_intl
);
227 ComponentExtensionEngine ext_xkb_engine_dvorak
;
228 ext_xkb_engine_dvorak
.engine_id
= "xkb:us:dvorak:eng";
229 ext_xkb_engine_dvorak
.display_name
= "xkb:us:dvorak:eng";
230 ext_xkb_engine_dvorak
.language_codes
.push_back("en-US");
231 ext_xkb_engine_dvorak
.layouts
.push_back("us(dvorak)");
232 ext_xkb
.engines
.push_back(ext_xkb_engine_dvorak
);
234 ComponentExtensionEngine ext_xkb_engine_dvp
;
235 ext_xkb_engine_dvp
.engine_id
= "xkb:us:dvp:eng";
236 ext_xkb_engine_dvp
.display_name
= "xkb:us:dvp:eng";
237 ext_xkb_engine_dvp
.language_codes
.push_back("en-US");
238 ext_xkb_engine_dvp
.layouts
.push_back("us(dvp)");
239 ext_xkb
.engines
.push_back(ext_xkb_engine_dvp
);
241 ComponentExtensionEngine ext_xkb_engine_colemak
;
242 ext_xkb_engine_colemak
.engine_id
= "xkb:us:colemak:eng";
243 ext_xkb_engine_colemak
.display_name
= "xkb:us:colemak:eng";
244 ext_xkb_engine_colemak
.language_codes
.push_back("en-US");
245 ext_xkb_engine_colemak
.layouts
.push_back("us(colemak)");
246 ext_xkb
.engines
.push_back(ext_xkb_engine_colemak
);
248 ComponentExtensionEngine ext_xkb_engine_fr
;
249 ext_xkb_engine_fr
.engine_id
= "xkb:fr::fra";
250 ext_xkb_engine_fr
.display_name
= "xkb:fr::fra";
251 ext_xkb_engine_fr
.language_codes
.push_back("fr");
252 ext_xkb_engine_fr
.layouts
.push_back("fr");
253 ext_xkb
.engines
.push_back(ext_xkb_engine_fr
);
255 ComponentExtensionEngine ext_xkb_engine_se
;
256 ext_xkb_engine_se
.engine_id
= "xkb:se::swe";
257 ext_xkb_engine_se
.display_name
= "xkb:se::swe";
258 ext_xkb_engine_se
.language_codes
.push_back("sv");
259 ext_xkb_engine_se
.layouts
.push_back("se");
260 ext_xkb
.engines
.push_back(ext_xkb_engine_se
);
262 ComponentExtensionEngine ext_xkb_engine_jp
;
263 ext_xkb_engine_jp
.engine_id
= "xkb:jp::jpn";
264 ext_xkb_engine_jp
.display_name
= "xkb:jp::jpn";
265 ext_xkb_engine_jp
.language_codes
.push_back("ja");
266 ext_xkb_engine_jp
.layouts
.push_back("jp");
267 ext_xkb
.engines
.push_back(ext_xkb_engine_jp
);
269 ComponentExtensionEngine ext_xkb_engine_ru
;
270 ext_xkb_engine_ru
.engine_id
= "xkb:ru::rus";
271 ext_xkb_engine_ru
.display_name
= "xkb:ru::rus";
272 ext_xkb_engine_ru
.language_codes
.push_back("ru");
273 ext_xkb_engine_ru
.layouts
.push_back("ru");
274 ext_xkb
.engines
.push_back(ext_xkb_engine_ru
);
276 ComponentExtensionEngine ext_xkb_engine_hu
;
277 ext_xkb_engine_hu
.engine_id
= "xkb:hu::hun";
278 ext_xkb_engine_hu
.display_name
= "xkb:hu::hun";
279 ext_xkb_engine_hu
.language_codes
.push_back("hu");
280 ext_xkb_engine_hu
.layouts
.push_back("hu");
281 ext_xkb
.engines
.push_back(ext_xkb_engine_hu
);
283 ime_list_
.push_back(ext_xkb
);
285 ComponentExtensionIME ext1
;
286 ext1
.id
= extension_ime_util::kMozcExtensionId
;
287 ext1
.description
= "ext1_description";
288 ext1
.path
= base::FilePath("ext1_file_path");
290 ComponentExtensionEngine ext1_engine1
;
291 ext1_engine1
.engine_id
= "nacl_mozc_us";
292 ext1_engine1
.display_name
= "ext1_engine_1_display_name";
293 ext1_engine1
.language_codes
.push_back("ja");
294 ext1_engine1
.layouts
.push_back("us");
295 ext1
.engines
.push_back(ext1_engine1
);
297 ComponentExtensionEngine ext1_engine2
;
298 ext1_engine2
.engine_id
= "nacl_mozc_jp";
299 ext1_engine2
.display_name
= "ext1_engine_1_display_name";
300 ext1_engine2
.language_codes
.push_back("ja");
301 ext1_engine2
.layouts
.push_back("jp");
302 ext1
.engines
.push_back(ext1_engine2
);
304 ime_list_
.push_back(ext1
);
306 ComponentExtensionIME ext2
;
307 ext2
.id
= extension_ime_util::kT13nExtensionId
;
308 ext2
.description
= "ext2_description";
309 ext2
.path
= base::FilePath("ext2_file_path");
311 ComponentExtensionEngine ext2_engine1
;
312 ext2_engine1
.engine_id
= kExt2Engine1Id
;
313 ext2_engine1
.display_name
= "ext2_engine_1_display_name";
314 ext2_engine1
.language_codes
.push_back("en");
315 ext2_engine1
.layouts
.push_back("us");
316 ext2
.engines
.push_back(ext2_engine1
);
318 ComponentExtensionEngine ext2_engine2
;
319 ext2_engine2
.engine_id
= kExt2Engine2Id
;
320 ext2_engine2
.display_name
= "ext2_engine_2_display_name";
321 ext2_engine2
.language_codes
.push_back("en");
322 ext2_engine2
.layouts
.push_back("us(dvorak)");
323 ext2
.engines
.push_back(ext2_engine2
);
325 ime_list_
.push_back(ext2
);
328 TestingBrowserProcess
* GetBrowserProcess() {
329 return TestingBrowserProcess::GetGlobal();
332 scoped_ptr
<TestingProfileManager
> profile_manager_
;
333 scoped_ptr
<InputMethodManagerImpl
> manager_
;
334 FakeInputMethodDelegate
* delegate_
;
335 MockCandidateWindowController
* candidate_window_controller_
;
336 scoped_ptr
<MockInputMethodEngine
> mock_engine_handler_
;
337 FakeImeKeyboard
* keyboard_
;
338 MockComponentExtIMEManagerDelegate
* mock_delegate_
;
339 std::vector
<ComponentExtensionIME
> ime_list_
;
340 ui::ime::InputMethodMenuManager
* menu_manager_
;
343 DISALLOW_COPY_AND_ASSIGN(InputMethodManagerImplTest
);
346 TEST_F(InputMethodManagerImplTest
, TestGetImeKeyboard
) {
347 EXPECT_TRUE(manager_
->GetImeKeyboard());
348 EXPECT_EQ(keyboard_
, manager_
->GetImeKeyboard());
351 TEST_F(InputMethodManagerImplTest
, TestCandidateWindowObserver
) {
352 TestCandidateWindowObserver observer
;
353 candidate_window_controller_
->NotifyCandidateWindowOpened(); // nop
354 candidate_window_controller_
->NotifyCandidateWindowClosed(); // nop
355 manager_
->AddCandidateWindowObserver(&observer
);
356 candidate_window_controller_
->NotifyCandidateWindowOpened();
357 EXPECT_EQ(1, observer
.candidate_window_opened_count_
);
358 candidate_window_controller_
->NotifyCandidateWindowClosed();
359 EXPECT_EQ(1, observer
.candidate_window_closed_count_
);
360 candidate_window_controller_
->NotifyCandidateWindowOpened();
361 EXPECT_EQ(2, observer
.candidate_window_opened_count_
);
362 candidate_window_controller_
->NotifyCandidateWindowClosed();
363 EXPECT_EQ(2, observer
.candidate_window_closed_count_
);
364 manager_
->RemoveCandidateWindowObserver(&observer
);
367 TEST_F(InputMethodManagerImplTest
, TestObserver
) {
368 // For http://crbug.com/19655#c11 - (3). browser_state_monitor_unittest.cc is
369 // also for the scenario.
370 std::vector
<std::string
> keyboard_layouts
;
371 keyboard_layouts
.push_back("xkb:us::eng");
373 TestObserver observer
;
374 InitComponentExtension();
375 manager_
->AddObserver(&observer
);
376 menu_manager_
->AddObserver(&observer
);
377 EXPECT_EQ(0, observer
.input_method_changed_count_
);
378 manager_
->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts
);
379 EXPECT_EQ(6U, manager_
->GetActiveIMEState()->GetActiveInputMethods()->size());
380 EXPECT_EQ(1, observer
.input_method_changed_count_
);
381 // Menu change is triggered only if current input method was actually changed.
382 EXPECT_EQ(0, observer
.input_method_menu_item_changed_count_
);
383 manager_
->GetActiveIMEState()->ChangeInputMethod(
384 ImeIdFromEngineId("xkb:us:dvorak:eng"), false /* show_message */);
385 EXPECT_FALSE(observer
.last_show_message_
);
386 EXPECT_EQ(2, observer
.input_method_changed_count_
);
387 EXPECT_EQ(1, observer
.input_method_menu_item_changed_count_
);
388 manager_
->GetActiveIMEState()->ChangeInputMethod(
389 ImeIdFromEngineId("xkb:us:dvorak:eng"), false /* show_message */);
390 EXPECT_FALSE(observer
.last_show_message_
);
392 // The observer is always notified even when the same input method ID is
393 // passed to ChangeInputMethod() more than twice.
394 // TODO(komatsu): Revisit if this is neccessary.
395 EXPECT_EQ(3, observer
.input_method_changed_count_
);
397 // If the same input method ID is passed, PropertyChanged() is not
399 EXPECT_EQ(1, observer
.input_method_menu_item_changed_count_
);
401 manager_
->RemoveObserver(&observer
);
402 menu_manager_
->RemoveObserver(&observer
);
405 TEST_F(InputMethodManagerImplTest
, TestGetSupportedInputMethods
) {
406 InitComponentExtension();
407 InputMethodDescriptors methods
;
408 methods
= manager_
->GetComponentExtensionIMEManager()
409 ->GetXkbIMEAsInputMethodDescriptor();
410 // Try to find random 4-5 layuts and IMEs to make sure the returned list is
412 const InputMethodDescriptor
* id_to_find
=
413 manager_
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
414 ImeIdFromEngineId(kNaclMozcUsId
));
415 id_to_find
= manager_
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
416 ImeIdFromEngineId("xkb:us::eng"));
417 EXPECT_TRUE(Contain(methods
, *id_to_find
));
418 id_to_find
= manager_
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
419 ImeIdFromEngineId("xkb:us:dvorak:eng"));
420 EXPECT_TRUE(Contain(methods
, *id_to_find
));
421 id_to_find
= manager_
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
422 ImeIdFromEngineId("xkb:fr::fra"));
423 EXPECT_TRUE(Contain(methods
, *id_to_find
));
426 TEST_F(InputMethodManagerImplTest
, TestEnableLayouts
) {
427 // Currently 6 keyboard layouts are supported for en-US, and 1 for ja. See
428 // ibus_input_method.txt.
429 std::vector
<std::string
> keyboard_layouts
;
431 InitComponentExtension();
432 manager_
->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts
);
433 EXPECT_EQ(6U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
435 // For http://crbug.com/19655#c11 - (5)
436 // The hardware keyboard layout "xkb:us::eng" is always active, hence 2U.
437 manager_
->GetActiveIMEState()->EnableLoginLayouts(
438 "ja", keyboard_layouts
); // Japanese
439 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
442 TEST_F(InputMethodManagerImplTest
, TestEnableLayoutsAndCurrentInputMethod
) {
443 // For http://crbug.com/329061
444 std::vector
<std::string
> keyboard_layouts
;
445 keyboard_layouts
.push_back(ImeIdFromEngineId("xkb:se::swe"));
447 InitComponentExtension();
448 manager_
->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts
);
449 const std::string im_id
=
450 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id();
451 EXPECT_EQ(ImeIdFromEngineId("xkb:se::swe"), im_id
);
454 TEST_F(InputMethodManagerImplTest
, TestEnableLayoutsNonUsHardwareKeyboard
) {
455 InitComponentExtension();
456 // The physical layout is French.
457 manager_
->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
459 manager_
->GetActiveIMEState()->EnableLoginLayouts(
461 manager_
->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
464 manager_
->GetActiveIMEState()->GetNumActiveInputMethods()); // 6 + French
465 // The physical layout is Japanese.
466 manager_
->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
468 manager_
->GetActiveIMEState()->EnableLoginLayouts(
469 "ja", manager_
->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
470 // "xkb:us::eng" is not needed, hence 1.
471 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
473 // The physical layout is Russian.
474 manager_
->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
476 manager_
->GetActiveIMEState()->EnableLoginLayouts(
477 "ru", manager_
->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
478 // "xkb:us::eng" only.
479 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
480 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
481 manager_
->GetActiveIMEState()->GetActiveInputMethodIds().front());
484 TEST_F(InputMethodManagerImplTest
, TestEnableMultipleHardwareKeyboardLayout
) {
485 InitComponentExtension();
486 // The physical layouts are French and Hungarian.
487 manager_
->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
488 "xkb:fr::fra,xkb:hu::hun");
489 manager_
->GetActiveIMEState()->EnableLoginLayouts(
491 manager_
->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
492 // 6 + French + Hungarian
493 EXPECT_EQ(8U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
496 TEST_F(InputMethodManagerImplTest
,
497 TestEnableMultipleHardwareKeyboardLayout_NoLoginKeyboard
) {
498 InitComponentExtension();
499 // The physical layouts are English (US) and Russian.
500 manager_
->GetInputMethodUtil()->SetHardwareKeyboardLayoutForTesting(
501 "xkb:us::eng,xkb:ru::rus");
502 manager_
->GetActiveIMEState()->EnableLoginLayouts(
503 "ru", manager_
->GetInputMethodUtil()->GetHardwareLoginInputMethodIds());
505 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
508 TEST_F(InputMethodManagerImplTest
, TestActiveInputMethods
) {
509 InitComponentExtension();
510 std::vector
<std::string
> keyboard_layouts
;
511 manager_
->GetActiveIMEState()->EnableLoginLayouts(
512 "ja", keyboard_layouts
); // Japanese
513 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
514 scoped_ptr
<InputMethodDescriptors
> methods(
515 manager_
->GetActiveIMEState()->GetActiveInputMethods());
516 ASSERT_TRUE(methods
.get());
517 EXPECT_EQ(2U, methods
->size());
518 const InputMethodDescriptor
* id_to_find
=
519 manager_
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
520 ImeIdFromEngineId("xkb:us::eng"));
521 EXPECT_TRUE(id_to_find
&& Contain(*methods
.get(), *id_to_find
));
522 id_to_find
= manager_
->GetInputMethodUtil()->GetInputMethodDescriptorFromId(
523 ImeIdFromEngineId("xkb:jp::jpn"));
524 EXPECT_TRUE(id_to_find
&& Contain(*methods
.get(), *id_to_find
));
527 TEST_F(InputMethodManagerImplTest
, TestEnableTwoLayouts
) {
528 // For http://crbug.com/19655#c11 - (8), step 6.
529 TestObserver observer
;
530 InitComponentExtension();
531 manager_
->AddObserver(&observer
);
532 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
533 std::vector
<std::string
> ids
;
534 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
535 ids
.push_back(ImeIdFromEngineId("xkb:us:colemak:eng"));
536 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
537 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
538 // Since all the IDs added avobe are keyboard layouts, Start() should not be
540 EXPECT_EQ(1, observer
.input_method_changed_count_
);
541 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
542 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
543 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
545 ids
.erase(ids
.begin());
546 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
547 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
548 EXPECT_EQ(2, observer
.input_method_changed_count_
);
549 EXPECT_EQ(ImeIdFromEngineId(ids
[0]), // colemak
550 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
551 EXPECT_EQ("us(colemak)", keyboard_
->last_layout_
);
552 manager_
->RemoveObserver(&observer
);
555 TEST_F(InputMethodManagerImplTest
, TestEnableThreeLayouts
) {
556 // For http://crbug.com/19655#c11 - (9).
557 TestObserver observer
;
558 InitComponentExtension();
559 manager_
->AddObserver(&observer
);
560 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
561 std::vector
<std::string
> ids
;
562 ids
.push_back(ImeIdFromEngineId("xkb:us::eng"));
563 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
564 ids
.push_back(ImeIdFromEngineId("xkb:us:colemak:eng"));
565 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
566 EXPECT_EQ(3U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
567 EXPECT_EQ(1, observer
.input_method_changed_count_
);
568 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
569 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
570 EXPECT_EQ("us", keyboard_
->last_layout_
);
572 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
573 EXPECT_EQ(2, observer
.input_method_changed_count_
);
574 EXPECT_EQ(ImeIdFromEngineId(ids
[1]),
575 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
576 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
578 ids
.erase(ids
.begin() + 1);
579 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
580 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
581 EXPECT_EQ(3, observer
.input_method_changed_count_
);
582 EXPECT_EQ(ImeIdFromEngineId(ids
[0]), // US Qwerty
583 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
584 EXPECT_EQ("us", keyboard_
->last_layout_
);
585 manager_
->RemoveObserver(&observer
);
588 TEST_F(InputMethodManagerImplTest
, TestEnableLayoutAndIme
) {
589 // For http://crbug.com/19655#c11 - (10).
590 TestObserver observer
;
591 InitComponentExtension();
592 manager_
->AddObserver(&observer
);
593 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
594 std::vector
<std::string
> ids
;
595 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
596 ids
.push_back(ImeIdFromEngineId(kNaclMozcUsId
));
597 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
598 EXPECT_EQ(1, observer
.input_method_changed_count_
);
599 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
600 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
601 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
603 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
604 EXPECT_EQ(2, observer
.input_method_changed_count_
);
605 EXPECT_EQ(ImeIdFromEngineId(ids
[1]),
606 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
607 EXPECT_EQ("us", keyboard_
->last_layout_
);
609 ids
.erase(ids
.begin() + 1);
610 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
611 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
612 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
613 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
614 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
617 TEST_F(InputMethodManagerImplTest
, TestEnableLayoutAndIme2
) {
618 // For http://crbug.com/19655#c11 - (11).
619 TestObserver observer
;
620 InitComponentExtension();
621 manager_
->AddObserver(&observer
);
622 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
623 std::vector
<std::string
> ids
;
624 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
625 ids
.push_back(ImeIdFromEngineId(kNaclMozcUsId
));
626 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
627 EXPECT_EQ(1, observer
.input_method_changed_count_
);
628 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
629 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
630 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
633 ids
.erase(ids
.begin());
634 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
635 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
636 EXPECT_EQ(ImeIdFromEngineId(ids
[0]), // Mozc
637 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
638 EXPECT_EQ("us", keyboard_
->last_layout_
);
639 manager_
->RemoveObserver(&observer
);
642 TEST_F(InputMethodManagerImplTest
, TestEnableImes
) {
643 TestObserver observer
;
644 InitComponentExtension();
645 manager_
->AddObserver(&observer
);
646 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
647 std::vector
<std::string
> ids
;
648 ids
.push_back(ImeIdFromEngineId(kExt2Engine1Id
));
649 ids
.push_back("mozc-dv");
650 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
651 EXPECT_EQ(1, observer
.input_method_changed_count_
);
652 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
653 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
654 EXPECT_EQ("us", keyboard_
->last_layout_
);
655 manager_
->RemoveObserver(&observer
);
658 TEST_F(InputMethodManagerImplTest
, TestEnableUnknownIds
) {
659 TestObserver observer
;
660 InitComponentExtension();
661 manager_
->AddObserver(&observer
);
662 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
663 std::vector
<std::string
> ids
;
664 ids
.push_back("xkb:tl::tlh"); // Klingon, which is not supported.
665 ids
.push_back("unknown-super-cool-ime");
666 EXPECT_FALSE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
668 // TODO(yusukes): Should we fall back to the hardware keyboard layout in this
670 EXPECT_EQ(0, observer
.input_method_changed_count_
);
672 manager_
->RemoveObserver(&observer
);
675 TEST_F(InputMethodManagerImplTest
, TestEnableLayoutsThenLock
) {
676 // For http://crbug.com/19655#c11 - (14).
677 TestObserver observer
;
678 InitComponentExtension();
679 manager_
->AddObserver(&observer
);
680 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
681 std::vector
<std::string
> ids
;
682 ids
.push_back(ImeIdFromEngineId("xkb:us::eng"));
683 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
684 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
685 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
686 EXPECT_EQ(1, observer
.input_method_changed_count_
);
687 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
688 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
689 EXPECT_EQ("us", keyboard_
->last_layout_
);
692 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
693 EXPECT_EQ(2, observer
.input_method_changed_count_
);
694 EXPECT_EQ(ImeIdFromEngineId(ids
[1]),
695 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
696 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
699 scoped_refptr
<input_method::InputMethodManager::State
> saved_ime_state
=
700 manager_
->GetActiveIMEState();
701 manager_
->SetState(saved_ime_state
->Clone());
702 manager_
->GetActiveIMEState()->EnableLockScreenLayouts();
703 manager_
->SetUISessionState(InputMethodManager::STATE_LOCK_SCREEN
);
704 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
705 EXPECT_EQ(ImeIdFromEngineId(ids
[1]), // still Dvorak
706 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
707 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
708 // Switch back to Qwerty.
709 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
710 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
711 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
712 EXPECT_EQ("us", keyboard_
->last_layout_
);
714 // Unlock screen. The original state, Dvorak, is restored.
715 manager_
->SetState(saved_ime_state
);
716 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
717 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
718 EXPECT_EQ(ImeIdFromEngineId(ids
[1]),
719 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
720 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
722 manager_
->RemoveObserver(&observer
);
725 TEST_F(InputMethodManagerImplTest
, SwitchInputMethodTest
) {
726 // For http://crbug.com/19655#c11 - (15).
727 TestObserver observer
;
728 InitComponentExtension();
729 manager_
->AddObserver(&observer
);
730 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
731 std::vector
<std::string
> ids
;
732 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
733 ids
.push_back(ImeIdFromEngineId(kExt2Engine2Id
));
734 ids
.push_back(ImeIdFromEngineId(kExt2Engine1Id
));
735 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
736 EXPECT_EQ(3U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
737 EXPECT_EQ(1, observer
.input_method_changed_count_
);
738 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
739 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
740 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
743 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
744 EXPECT_EQ(2, observer
.input_method_changed_count_
);
745 EXPECT_EQ(ImeIdFromEngineId(ids
[1]),
746 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
747 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
750 scoped_refptr
<input_method::InputMethodManager::State
> saved_ime_state
=
751 manager_
->GetActiveIMEState();
752 manager_
->SetState(saved_ime_state
->Clone());
753 manager_
->GetActiveIMEState()->EnableLockScreenLayouts();
754 manager_
->SetUISessionState(InputMethodManager::STATE_LOCK_SCREEN
);
756 manager_
->GetActiveIMEState()
757 ->GetNumActiveInputMethods()); // Qwerty+Dvorak.
758 EXPECT_EQ(ImeIdFromEngineId("xkb:us:dvorak:eng"),
759 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
760 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
761 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
762 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), // The hardware keyboard layout.
763 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
764 EXPECT_EQ("us", keyboard_
->last_layout_
);
766 // Unlock screen. The original state, pinyin-dv, is restored.
767 manager_
->SetState(saved_ime_state
);
768 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
770 manager_
->GetActiveIMEState()
771 ->GetNumActiveInputMethods()); // Dvorak and 2 IMEs.
772 EXPECT_EQ(ImeIdFromEngineId(ids
[1]),
773 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
774 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
776 manager_
->RemoveObserver(&observer
);
779 TEST_F(InputMethodManagerImplTest
, TestXkbSetting
) {
780 EXPECT_EQ(0, keyboard_
->set_current_keyboard_layout_by_name_count_
);
781 // For http://crbug.com/19655#c11 - (8), step 7-11.
782 InitComponentExtension();
783 EXPECT_EQ(1, keyboard_
->set_current_keyboard_layout_by_name_count_
);
784 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
785 std::vector
<std::string
> ids
;
786 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
787 ids
.push_back(ImeIdFromEngineId("xkb:us:colemak:eng"));
788 ids
.push_back(ImeIdFromEngineId(kNaclMozcJpId
));
789 ids
.push_back(ImeIdFromEngineId(kNaclMozcUsId
));
790 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
791 EXPECT_EQ(4U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
792 EXPECT_EQ(2, keyboard_
->set_current_keyboard_layout_by_name_count_
);
793 // See input_methods.txt for an expected XKB layout name.
794 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
795 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
796 EXPECT_EQ(3, keyboard_
->set_current_keyboard_layout_by_name_count_
);
797 EXPECT_EQ("us(colemak)", keyboard_
->last_layout_
);
798 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
799 EXPECT_EQ(4, keyboard_
->set_current_keyboard_layout_by_name_count_
);
800 EXPECT_EQ("jp", keyboard_
->last_layout_
);
801 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
802 EXPECT_EQ(5, keyboard_
->set_current_keyboard_layout_by_name_count_
);
803 EXPECT_EQ("us", keyboard_
->last_layout_
);
804 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
805 EXPECT_EQ(6, keyboard_
->set_current_keyboard_layout_by_name_count_
);
806 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
808 ids
.erase(ids
.begin());
809 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
810 EXPECT_EQ(3U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
811 EXPECT_EQ(7, keyboard_
->set_current_keyboard_layout_by_name_count_
);
812 EXPECT_EQ("us(colemak)", keyboard_
->last_layout_
);
815 TEST_F(InputMethodManagerImplTest
, TestActivateInputMethodMenuItem
) {
816 const std::string kKey
= "key";
817 ui::ime::InputMethodMenuItemList menu_list
;
818 menu_list
.push_back(ui::ime::InputMethodMenuItem(
819 kKey
, "label", false, false));
820 menu_manager_
->SetCurrentInputMethodMenuItemList(menu_list
);
822 manager_
->ActivateInputMethodMenuItem(kKey
);
823 EXPECT_EQ(kKey
, mock_engine_handler_
->last_activated_property());
825 // Key2 is not registered, so activated property should not be changed.
826 manager_
->ActivateInputMethodMenuItem("key2");
827 EXPECT_EQ(kKey
, mock_engine_handler_
->last_activated_property());
830 TEST_F(InputMethodManagerImplTest
, TestGetCurrentInputMethodProperties
) {
831 InitComponentExtension();
832 EXPECT_TRUE(menu_manager_
->GetCurrentInputMethodMenuItemList().empty());
834 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
835 std::vector
<std::string
> ids
;
836 ids
.push_back(ImeIdFromEngineId("xkb:us::eng"));
837 ids
.push_back(ImeIdFromEngineId(kNaclMozcUsId
));
838 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
839 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
840 EXPECT_TRUE(menu_manager_
->GetCurrentInputMethodMenuItemList().empty());
841 manager_
->GetActiveIMEState()->ChangeInputMethod(
842 ImeIdFromEngineId(kNaclMozcUsId
), false /* show_message */);
844 ui::ime::InputMethodMenuItemList current_property_list
;
845 current_property_list
.push_back(ui::ime::InputMethodMenuItem(
846 "key", "label", false, false));
847 menu_manager_
->SetCurrentInputMethodMenuItemList(current_property_list
);
849 ASSERT_EQ(1U, menu_manager_
->GetCurrentInputMethodMenuItemList().size());
851 menu_manager_
->GetCurrentInputMethodMenuItemList().at(0).key
);
853 manager_
->GetActiveIMEState()->ChangeInputMethod("xkb:us::eng",
854 false /* show_message */);
855 EXPECT_TRUE(menu_manager_
->GetCurrentInputMethodMenuItemList().empty());
858 TEST_F(InputMethodManagerImplTest
, TestGetCurrentInputMethodPropertiesTwoImes
) {
859 InitComponentExtension();
860 EXPECT_TRUE(menu_manager_
->GetCurrentInputMethodMenuItemList().empty());
862 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
863 std::vector
<std::string
> ids
;
864 ids
.push_back(ImeIdFromEngineId(kNaclMozcUsId
)); // Japanese
865 ids
.push_back(ImeIdFromEngineId(kExt2Engine1Id
)); // T-Chinese
866 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
867 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
868 EXPECT_TRUE(menu_manager_
->GetCurrentInputMethodMenuItemList().empty());
870 ui::ime::InputMethodMenuItemList current_property_list
;
871 current_property_list
.push_back(ui::ime::InputMethodMenuItem("key-mozc",
875 menu_manager_
->SetCurrentInputMethodMenuItemList(current_property_list
);
877 ASSERT_EQ(1U, menu_manager_
->GetCurrentInputMethodMenuItemList().size());
878 EXPECT_EQ("key-mozc",
879 menu_manager_
->GetCurrentInputMethodMenuItemList().at(0).key
);
881 manager_
->GetActiveIMEState()->ChangeInputMethod(
882 ImeIdFromEngineId(kExt2Engine1Id
), false /* show_message */);
883 // Since the IME is changed, the property for mozc Japanese should be hidden.
884 EXPECT_TRUE(menu_manager_
->GetCurrentInputMethodMenuItemList().empty());
886 // Asynchronous property update signal from mozc-chewing.
887 current_property_list
.clear();
888 current_property_list
.push_back(ui::ime::InputMethodMenuItem(
889 "key-chewing", "label", false, false));
890 menu_manager_
->SetCurrentInputMethodMenuItemList(current_property_list
);
891 ASSERT_EQ(1U, menu_manager_
->GetCurrentInputMethodMenuItemList().size());
892 EXPECT_EQ("key-chewing",
893 menu_manager_
->GetCurrentInputMethodMenuItemList().at(0).key
);
896 TEST_F(InputMethodManagerImplTest
, TestNextInputMethod
) {
897 TestObserver observer
;
898 InitComponentExtension();
899 manager_
->AddObserver(&observer
);
900 std::vector
<std::string
> keyboard_layouts
;
901 keyboard_layouts
.push_back(ImeIdFromEngineId("xkb:us::eng"));
902 // For http://crbug.com/19655#c11 - (1)
903 manager_
->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts
);
904 EXPECT_EQ(6U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
905 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
906 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
907 EXPECT_EQ("us", keyboard_
->last_layout_
);
908 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
909 EXPECT_TRUE(observer
.last_show_message_
);
910 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
911 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
912 EXPECT_EQ("us(intl)", keyboard_
->last_layout_
);
913 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
914 EXPECT_TRUE(observer
.last_show_message_
);
915 EXPECT_EQ(ImeIdFromEngineId("xkb:us:altgr-intl:eng"),
916 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
917 EXPECT_EQ("us(altgr-intl)", keyboard_
->last_layout_
);
918 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
919 EXPECT_TRUE(observer
.last_show_message_
);
920 EXPECT_EQ(ImeIdFromEngineId("xkb:us:dvorak:eng"),
921 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
922 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
923 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
924 EXPECT_TRUE(observer
.last_show_message_
);
925 EXPECT_EQ(ImeIdFromEngineId("xkb:us:dvp:eng"),
926 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
927 EXPECT_EQ("us(dvp)", keyboard_
->last_layout_
);
928 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
929 EXPECT_TRUE(observer
.last_show_message_
);
930 EXPECT_EQ(ImeIdFromEngineId("xkb:us:colemak:eng"),
931 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
932 EXPECT_EQ("us(colemak)", keyboard_
->last_layout_
);
933 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
934 EXPECT_TRUE(observer
.last_show_message_
);
935 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
936 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
937 EXPECT_EQ("us", keyboard_
->last_layout_
);
939 manager_
->RemoveObserver(&observer
);
942 TEST_F(InputMethodManagerImplTest
, TestPreviousInputMethod
) {
943 TestObserver observer
;
944 InitComponentExtension();
945 manager_
->AddObserver(&observer
);
947 std::vector
<std::string
> keyboard_layouts
;
948 keyboard_layouts
.push_back(ImeIdFromEngineId("xkb:us::eng"));
949 manager_
->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts
);
950 EXPECT_EQ(6U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
951 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanCycleInputMethod());
952 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
953 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
954 EXPECT_EQ("us", keyboard_
->last_layout_
);
955 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
956 EXPECT_TRUE(observer
.last_show_message_
);
957 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
958 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
959 EXPECT_EQ("us(intl)", keyboard_
->last_layout_
);
960 manager_
->GetActiveIMEState()->SwitchToPreviousInputMethod();
961 EXPECT_TRUE(observer
.last_show_message_
);
962 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
963 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
964 EXPECT_EQ("us", keyboard_
->last_layout_
);
965 manager_
->GetActiveIMEState()->SwitchToPreviousInputMethod();
966 EXPECT_TRUE(observer
.last_show_message_
);
967 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
968 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
969 EXPECT_EQ("us(intl)", keyboard_
->last_layout_
);
970 manager_
->GetActiveIMEState()->SwitchToPreviousInputMethod();
971 EXPECT_TRUE(observer
.last_show_message_
);
972 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
973 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
974 EXPECT_EQ("us", keyboard_
->last_layout_
);
975 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
976 EXPECT_TRUE(observer
.last_show_message_
);
977 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
978 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
979 EXPECT_EQ("us(intl)", keyboard_
->last_layout_
);
980 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
981 EXPECT_TRUE(observer
.last_show_message_
);
982 EXPECT_EQ(ImeIdFromEngineId("xkb:us:altgr-intl:eng"),
983 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
984 EXPECT_EQ("us(altgr-intl)", keyboard_
->last_layout_
);
985 manager_
->GetActiveIMEState()->SwitchToPreviousInputMethod();
986 EXPECT_TRUE(observer
.last_show_message_
);
987 EXPECT_EQ(ImeIdFromEngineId("xkb:us:intl:eng"),
988 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
989 EXPECT_EQ("us(intl)", keyboard_
->last_layout_
);
990 manager_
->GetActiveIMEState()->SwitchToPreviousInputMethod();
991 EXPECT_TRUE(observer
.last_show_message_
);
992 EXPECT_EQ(ImeIdFromEngineId("xkb:us:altgr-intl:eng"),
993 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
994 EXPECT_EQ("us(altgr-intl)", keyboard_
->last_layout_
);
996 manager_
->RemoveObserver(&observer
);
999 TEST_F(InputMethodManagerImplTest
,
1000 TestCanCycleInputMethodForOneActiveInputMethod
) {
1001 TestObserver observer
;
1002 InitComponentExtension();
1003 manager_
->AddObserver(&observer
);
1005 std::vector
<std::string
> ids
;
1006 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
1007 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
1008 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1010 // CanCycleInputMethod() should return false if there is only one active input
1012 EXPECT_FALSE(manager_
->GetActiveIMEState()->CanCycleInputMethod());
1014 manager_
->RemoveObserver(&observer
);
1017 TEST_F(InputMethodManagerImplTest
, TestSwitchInputMethodWithUsLayouts
) {
1018 InitComponentExtension();
1019 std::vector
<std::string
> keyboard_layouts
;
1020 keyboard_layouts
.push_back(ImeIdFromEngineId("xkb:us::eng"));
1021 manager_
->GetActiveIMEState()->EnableLoginLayouts("en-US", keyboard_layouts
);
1022 EXPECT_EQ(6U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1024 // Henkan, Muhenkan, ZenkakuHankaku should be ignored when no Japanese IMEs
1025 // and keyboards are enabled.
1026 EXPECT_FALSE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1027 ui::Accelerator(ui::VKEY_CONVERT
, ui::EF_NONE
)));
1028 EXPECT_FALSE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1029 ui::Accelerator(ui::VKEY_NONCONVERT
, ui::EF_NONE
)));
1030 EXPECT_FALSE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1031 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR
, ui::EF_NONE
)));
1032 EXPECT_FALSE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1033 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR
, ui::EF_NONE
)));
1036 TEST_F(InputMethodManagerImplTest
, TestSwitchInputMethodWithJpLayout
) {
1037 // Enable "xkb:jp::jpn" and press Muhenkan/ZenkakuHankaku.
1038 InitComponentExtension();
1040 std::vector
<std::string
> keyboard_layouts
;
1041 keyboard_layouts
.push_back(ImeIdFromEngineId("xkb:us::eng"));
1042 manager_
->GetActiveIMEState()->EnableLoginLayouts("ja", keyboard_layouts
);
1043 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1044 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
1045 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1046 EXPECT_EQ("us", keyboard_
->last_layout_
);
1047 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1048 ui::Accelerator(ui::VKEY_NONCONVERT
, ui::EF_NONE
)));
1049 manager_
->GetActiveIMEState()->SwitchInputMethod(
1050 ui::Accelerator(ui::VKEY_NONCONVERT
, ui::EF_NONE
));
1051 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1052 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1053 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1054 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanCycleInputMethod());
1055 manager_
->GetActiveIMEState()->SwitchToPreviousInputMethod();
1056 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
1057 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1058 EXPECT_EQ("us", keyboard_
->last_layout_
);
1059 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1060 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR
, ui::EF_NONE
)));
1061 manager_
->GetActiveIMEState()->SwitchInputMethod(
1062 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR
, ui::EF_NONE
));
1063 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1064 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1065 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1066 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanCycleInputMethod());
1067 manager_
->GetActiveIMEState()->SwitchToPreviousInputMethod();
1068 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
1069 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1070 EXPECT_EQ("us", keyboard_
->last_layout_
);
1071 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1072 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR
, ui::EF_NONE
)));
1073 manager_
->GetActiveIMEState()->SwitchInputMethod(
1074 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR
, ui::EF_NONE
));
1075 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1076 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1077 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1080 TEST_F(InputMethodManagerImplTest
, TestSwitchInputMethodWithJpIme
) {
1081 InitComponentExtension();
1082 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
1083 std::vector
<std::string
> ids
;
1084 ids
.push_back(ImeIdFromEngineId("xkb:jp::jpn"));
1085 ids
.push_back(ImeIdFromEngineId(kNaclMozcJpId
));
1086 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
1087 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1088 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1089 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1090 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1091 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR
, ui::EF_NONE
)));
1092 manager_
->GetActiveIMEState()->SwitchInputMethod(
1093 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR
, ui::EF_NONE
));
1094 EXPECT_EQ(ImeIdFromEngineId(kNaclMozcJpId
),
1095 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1096 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1097 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1098 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR
, ui::EF_NONE
)));
1099 manager_
->GetActiveIMEState()->SwitchInputMethod(
1100 ui::Accelerator(ui::VKEY_DBE_DBCSCHAR
, ui::EF_NONE
));
1101 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1102 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1103 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1104 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1105 ui::Accelerator(ui::VKEY_CONVERT
, ui::EF_NONE
)));
1106 manager_
->GetActiveIMEState()->SwitchInputMethod(
1107 ui::Accelerator(ui::VKEY_CONVERT
, ui::EF_NONE
));
1108 EXPECT_EQ(ImeIdFromEngineId(kNaclMozcJpId
),
1109 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1110 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1111 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1112 ui::Accelerator(ui::VKEY_CONVERT
, ui::EF_NONE
)));
1113 manager_
->GetActiveIMEState()->SwitchInputMethod(
1114 ui::Accelerator(ui::VKEY_CONVERT
, ui::EF_NONE
));
1115 EXPECT_EQ(ImeIdFromEngineId(kNaclMozcJpId
),
1116 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1117 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1118 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1119 ui::Accelerator(ui::VKEY_NONCONVERT
, ui::EF_NONE
)));
1120 manager_
->GetActiveIMEState()->SwitchInputMethod(
1121 ui::Accelerator(ui::VKEY_NONCONVERT
, ui::EF_NONE
));
1122 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1123 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1124 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1125 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1126 ui::Accelerator(ui::VKEY_NONCONVERT
, ui::EF_NONE
)));
1127 manager_
->GetActiveIMEState()->SwitchInputMethod(
1128 ui::Accelerator(ui::VKEY_NONCONVERT
, ui::EF_NONE
));
1129 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1130 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1131 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1134 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
1135 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
1136 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1137 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1138 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1139 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1140 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR
, ui::EF_NONE
)));
1141 manager_
->GetActiveIMEState()->SwitchInputMethod(
1142 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR
, ui::EF_NONE
));
1143 EXPECT_EQ(ImeIdFromEngineId(kNaclMozcJpId
),
1144 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1145 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1146 EXPECT_TRUE(manager_
->GetActiveIMEState()->CanSwitchInputMethod(
1147 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR
, ui::EF_NONE
)));
1148 manager_
->GetActiveIMEState()->SwitchInputMethod(
1149 ui::Accelerator(ui::VKEY_DBE_SBCSCHAR
, ui::EF_NONE
));
1150 EXPECT_EQ(ImeIdFromEngineId("xkb:jp::jpn"),
1151 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1152 EXPECT_EQ("jp", keyboard_
->last_layout_
);
1155 TEST_F(InputMethodManagerImplTest
, TestAddRemoveExtensionInputMethods
) {
1156 TestObserver observer
;
1157 InitComponentExtension();
1158 manager_
->AddObserver(&observer
);
1159 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
1160 std::vector
<std::string
> ids
;
1161 ids
.push_back(ImeIdFromEngineId("xkb:us:dvorak:eng"));
1162 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
1163 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1164 EXPECT_EQ(1, observer
.input_method_changed_count_
);
1165 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
1166 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1167 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
1169 // Add two Extension IMEs.
1170 std::vector
<std::string
> layouts
;
1171 layouts
.push_back("us");
1172 std::vector
<std::string
> languages
;
1173 languages
.push_back("en-US");
1175 const std::string ext1_id
=
1176 extension_ime_util::GetInputMethodID(kExtensionId1
, "engine_id");
1177 const InputMethodDescriptor
descriptor1(ext1_id
,
1178 "deadbeef input method",
1182 false, // is_login_keyboard
1185 MockInputMethodEngine engine
;
1186 InputMethodDescriptors descriptors
;
1187 descriptors
.push_back(descriptor1
);
1188 manager_
->GetActiveIMEState()->AddInputMethodExtension(
1189 kExtensionId1
, descriptors
, &engine
);
1191 // Extension IMEs are not enabled by default.
1192 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1194 std::vector
<std::string
> extension_ime_ids
;
1195 extension_ime_ids
.push_back(ext1_id
);
1196 manager_
->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids
);
1197 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1200 scoped_ptr
<InputMethodDescriptors
> methods(
1201 manager_
->GetActiveIMEState()->GetActiveInputMethods());
1202 ASSERT_EQ(2U, methods
->size());
1203 // Ext IMEs should be at the end of the list.
1204 EXPECT_EQ(ext1_id
, methods
->at(1).id());
1207 const std::string ext2_id
=
1208 extension_ime_util::GetInputMethodID(kExtensionId2
, "engine_id");
1209 const InputMethodDescriptor
descriptor2(ext2_id
,
1210 "cafebabe input method",
1214 false, // is_login_keyboard
1217 descriptors
.clear();
1218 descriptors
.push_back(descriptor2
);
1219 MockInputMethodEngine engine2
;
1220 manager_
->GetActiveIMEState()->AddInputMethodExtension(
1221 kExtensionId2
, descriptors
, &engine2
);
1222 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1224 extension_ime_ids
.push_back(ext2_id
);
1225 manager_
->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids
);
1226 EXPECT_EQ(3U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1228 scoped_ptr
<InputMethodDescriptors
> methods(
1229 manager_
->GetActiveIMEState()->GetActiveInputMethods());
1230 ASSERT_EQ(3U, methods
->size());
1231 // Ext IMEs should be at the end of the list.
1232 EXPECT_EQ(ext1_id
, methods
->at(1).id());
1233 EXPECT_EQ(ext2_id
, methods
->at(2).id());
1237 manager_
->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId1
);
1238 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1239 manager_
->GetActiveIMEState()->RemoveInputMethodExtension(kExtensionId2
);
1240 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1243 TEST_F(InputMethodManagerImplTest
, TestAddExtensionInputThenLockScreen
) {
1244 TestObserver observer
;
1245 InitComponentExtension();
1246 manager_
->AddObserver(&observer
);
1247 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
1248 std::vector
<std::string
> ids
;
1249 ids
.push_back(ImeIdFromEngineId("xkb:us::eng"));
1250 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
1251 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1252 EXPECT_EQ(1, observer
.input_method_changed_count_
);
1253 EXPECT_EQ(ImeIdFromEngineId(ids
[0]),
1254 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1255 EXPECT_EQ("us", keyboard_
->last_layout_
);
1257 // Add an Extension IME.
1258 std::vector
<std::string
> layouts
;
1259 layouts
.push_back("us(dvorak)");
1260 std::vector
<std::string
> languages
;
1261 languages
.push_back("en-US");
1263 const std::string ext_id
=
1264 extension_ime_util::GetInputMethodID(kExtensionId1
, "engine_id");
1265 const InputMethodDescriptor
descriptor(ext_id
,
1266 "deadbeef input method",
1270 false, // is_login_keyboard
1273 MockInputMethodEngine engine
;
1274 InputMethodDescriptors descriptors
;
1275 descriptors
.push_back(descriptor
);
1276 manager_
->GetActiveIMEState()->AddInputMethodExtension(
1277 kExtensionId1
, descriptors
, &engine
);
1279 // Extension IME is not enabled by default.
1280 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1281 EXPECT_EQ(1, observer
.input_method_changed_count_
);
1283 std::vector
<std::string
> extension_ime_ids
;
1284 extension_ime_ids
.push_back(ext_id
);
1285 manager_
->GetActiveIMEState()->SetEnabledExtensionImes(&extension_ime_ids
);
1286 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1288 // Switch to the IME.
1289 manager_
->GetActiveIMEState()->SwitchToNextInputMethod();
1290 EXPECT_EQ(3, observer
.input_method_changed_count_
);
1292 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1293 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
1295 // Lock the screen. This is for crosbug.com/27049.
1296 scoped_refptr
<input_method::InputMethodManager::State
> saved_ime_state
=
1297 manager_
->GetActiveIMEState();
1298 manager_
->SetState(saved_ime_state
->Clone());
1299 manager_
->GetActiveIMEState()->EnableLockScreenLayouts();
1300 manager_
->SetUISessionState(InputMethodManager::STATE_LOCK_SCREEN
);
1302 manager_
->GetActiveIMEState()
1303 ->GetNumActiveInputMethods()); // Qwerty. No Ext. IME
1304 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"),
1305 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1306 EXPECT_EQ("us", keyboard_
->last_layout_
);
1308 // Unlock the screen.
1309 manager_
->SetState(saved_ime_state
);
1310 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
1311 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1313 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1314 EXPECT_EQ("us(dvorak)", keyboard_
->last_layout_
);
1316 // This is for crosbug.com/27052.
1317 scoped_ptr
<InputMethodDescriptors
> methods(
1318 manager_
->GetActiveIMEState()->GetActiveInputMethods());
1319 ASSERT_EQ(2U, methods
->size());
1320 // Ext. IMEs should be at the end of the list.
1321 EXPECT_EQ(ext_id
, methods
->at(1).id());
1323 manager_
->RemoveObserver(&observer
);
1326 TEST_F(InputMethodManagerImplTest
,
1327 ChangeInputMethod_ComponenteExtensionOneIME
) {
1328 InitComponentExtension();
1329 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
1330 const std::string ext_id
= extension_ime_util::GetComponentInputMethodID(
1332 ime_list_
[1].engines
[0].engine_id
);
1333 std::vector
<std::string
> ids
;
1334 ids
.push_back(ext_id
);
1335 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
1336 EXPECT_EQ(1U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1338 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1341 TEST_F(InputMethodManagerImplTest
,
1342 ChangeInputMethod_ComponenteExtensionTwoIME
) {
1343 InitComponentExtension();
1344 manager_
->SetUISessionState(InputMethodManager::STATE_BROWSER_SCREEN
);
1345 const std::string ext_id1
= extension_ime_util::GetComponentInputMethodID(
1347 ime_list_
[1].engines
[0].engine_id
);
1348 const std::string ext_id2
= extension_ime_util::GetComponentInputMethodID(
1350 ime_list_
[2].engines
[0].engine_id
);
1351 std::vector
<std::string
> ids
;
1352 ids
.push_back(ext_id1
);
1353 ids
.push_back(ext_id2
);
1354 EXPECT_TRUE(manager_
->GetActiveIMEState()->ReplaceEnabledInputMethods(ids
));
1355 EXPECT_EQ(2U, manager_
->GetActiveIMEState()->GetNumActiveInputMethods());
1357 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1358 manager_
->GetActiveIMEState()->ChangeInputMethod(ext_id2
,
1359 false /* show_message */);
1361 manager_
->GetActiveIMEState()->GetCurrentInputMethod().id());
1364 TEST_F(InputMethodManagerImplTest
, MigrateInputMethodTest
) {
1365 std::vector
<std::string
> input_method_ids
;
1366 input_method_ids
.push_back("xkb:us::eng");
1367 input_method_ids
.push_back("xkb:fr::fra");
1368 input_method_ids
.push_back(ImeIdFromEngineId("xkb:us::eng"));
1369 input_method_ids
.push_back("xkb:fr::fra");
1370 input_method_ids
.push_back(ImeIdFromEngineId("xkb:us::eng"));
1371 input_method_ids
.push_back("_comp_ime_asdf_pinyin");
1372 input_method_ids
.push_back(ImeIdFromEngineId(kPinyinImeId
));
1374 manager_
->MigrateInputMethods(&input_method_ids
);
1376 ASSERT_EQ(4U, input_method_ids
.size());
1378 EXPECT_EQ(ImeIdFromEngineId("xkb:us::eng"), input_method_ids
[0]);
1379 EXPECT_EQ(ImeIdFromEngineId("xkb:fr::fra"), input_method_ids
[1]);
1380 EXPECT_EQ("_comp_ime_asdf_pinyin", input_method_ids
[2]);
1381 EXPECT_EQ(ImeIdFromEngineId("zh-t-i0-pinyin"), input_method_ids
[3]);
1384 } // namespace input_method
1385 } // namespace chromeos