1 // Copyright 2013 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 "ash/ime/input_method_menu_item.h"
6 #include "ash/ime/input_method_menu_manager.h"
7 #include "base/bind_helpers.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/extension_browsertest.h"
10 #include "chrome/browser/extensions/extension_test_message_listener.h"
11 #include "chromeos/ime/component_extension_ime_manager.h"
12 #include "chromeos/ime/composition_text.h"
13 #include "chromeos/ime/input_method_descriptor.h"
14 #include "chromeos/ime/input_method_manager.h"
15 #include "content/public/test/browser_test_utils.h"
16 #include "content/public/test/test_utils.h"
17 #include "extensions/common/manifest_handlers/background_info.h"
18 #include "ui/base/ime/chromeos/ime_bridge.h"
19 #include "ui/base/ime/chromeos/mock_ime_candidate_window_handler.h"
20 #include "ui/base/ime/chromeos/mock_ime_input_context_handler.h"
21 #include "ui/events/event.h"
24 namespace input_method
{
27 const char kIdentityIMEID
[] =
28 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpIdentityIME";
29 const char kToUpperIMEID
[] =
30 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpToUpperIME";
31 const char kAPIArgumentIMEID
[] =
32 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpAPIArgumentIME";
33 const char kExtensionID
[] = "iafoklpfplgfnoimmaejoeondnjnlcfp";
35 // InputMethod extension should work on 1)normal extension, 2)normal extension
36 // in incognito mode 3)component extension.
39 kTestTypeIncognito
= 1,
40 kTestTypeComponent
= 2,
43 class InputMethodEngineBrowserTest
44 : public ExtensionBrowserTest
,
45 public ::testing::WithParamInterface
<TestType
> {
47 InputMethodEngineBrowserTest()
48 : ExtensionBrowserTest() {}
49 virtual ~InputMethodEngineBrowserTest() {}
51 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE
{
52 ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
55 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE
{
60 void LoadTestInputMethod() {
61 // This will load "chrome/test/data/extensions/input_ime"
62 ExtensionTestMessageListener
ime_ready_listener("ReadyToUseImeEvent",
64 extension_
= LoadExtensionWithType("input_ime", GetParam());
65 ASSERT_TRUE(extension_
);
66 ASSERT_TRUE(ime_ready_listener
.WaitUntilSatisfied());
68 // Make sure ComponentExtensionIMEManager is initialized.
69 // ComponentExtensionIMEManagerImpl::InitializeAsync posts
70 // ReadComponentExtensionsInfo to the FILE thread for the
71 // initialization. If it is never initialized for some reasons,
72 // the test is timed out and failed.
73 ComponentExtensionIMEManager
* ceimm
=
74 InputMethodManager::Get()->GetComponentExtensionIMEManager();
75 while (!ceimm
->IsInitialized()) {
76 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
79 // Extension IMEs are not enabled by default.
80 std::vector
<std::string
> extension_ime_ids
;
81 extension_ime_ids
.push_back(kIdentityIMEID
);
82 extension_ime_ids
.push_back(kToUpperIMEID
);
83 extension_ime_ids
.push_back(kAPIArgumentIMEID
);
84 InputMethodManager::Get()->SetEnabledExtensionImes(&extension_ime_ids
);
86 InputMethodDescriptors extension_imes
;
87 InputMethodManager::Get()->GetInputMethodExtensions(&extension_imes
);
89 // Test IME has two input methods, thus InputMethodManager should have two
91 // Note: Even extension is loaded by LoadExtensionAsComponent as above, the
92 // IME does not managed by ComponentExtensionIMEManager or it's id won't
93 // start with __comp__. The component extension IME is whitelisted and
94 // managed by ComponentExtensionIMEManager, but its framework is same as
95 // normal extension IME.
96 EXPECT_EQ(3U, extension_imes
.size());
99 const extensions::Extension
* LoadExtensionWithType(
100 const std::string
& extension_name
, TestType type
) {
102 case kTestTypeNormal
:
103 return LoadExtension(test_data_dir_
.AppendASCII(extension_name
));
104 case kTestTypeIncognito
:
105 return LoadExtensionIncognito(
106 test_data_dir_
.AppendASCII(extension_name
));
107 case kTestTypeComponent
:
108 return LoadExtensionAsComponent(
109 test_data_dir_
.AppendASCII(extension_name
));
115 const extensions::Extension
* extension_
;
118 class KeyEventDoneCallback
{
120 explicit KeyEventDoneCallback(bool expected_argument
)
121 : expected_argument_(expected_argument
),
123 ~KeyEventDoneCallback() {}
125 void Run(bool consumed
) {
126 if (consumed
== expected_argument_
) {
127 base::MessageLoop::current()->Quit();
132 void WaitUntilCalled() {
134 content::RunMessageLoop();
138 bool expected_argument_
;
141 DISALLOW_COPY_AND_ASSIGN(KeyEventDoneCallback
);
144 INSTANTIATE_TEST_CASE_P(InputMethodEngineBrowserTest
,
145 InputMethodEngineBrowserTest
,
146 ::testing::Values(kTestTypeNormal
));
147 INSTANTIATE_TEST_CASE_P(InputMethodEngineIncognitoBrowserTest
,
148 InputMethodEngineBrowserTest
,
149 ::testing::Values(kTestTypeIncognito
));
150 INSTANTIATE_TEST_CASE_P(InputMethodEngineComponentExtensionBrowserTest
,
151 InputMethodEngineBrowserTest
,
152 ::testing::Values(kTestTypeComponent
));
154 IN_PROC_BROWSER_TEST_P(InputMethodEngineBrowserTest
,
156 LoadTestInputMethod();
158 InputMethodManager::Get()->ChangeInputMethod(kIdentityIMEID
);
160 scoped_ptr
<MockIMEInputContextHandler
> mock_input_context(
161 new MockIMEInputContextHandler());
162 scoped_ptr
<MockIMECandidateWindowHandler
> mock_candidate_window(
163 new MockIMECandidateWindowHandler());
165 IMEBridge::Get()->SetInputContextHandler(mock_input_context
.get());
166 IMEBridge::Get()->SetCandidateWindowHandler(mock_candidate_window
.get());
168 IMEEngineHandlerInterface
* engine_handler
=
169 IMEBridge::Get()->GetCurrentEngineHandler();
170 ASSERT_TRUE(engine_handler
);
172 // onActivate event should be fired if Enable function is called.
173 ExtensionTestMessageListener
activated_listener("onActivate", false);
174 engine_handler
->Enable();
175 ASSERT_TRUE(activated_listener
.WaitUntilSatisfied());
176 ASSERT_TRUE(activated_listener
.was_satisfied());
178 // onFocus event should be fired if FocusIn function is called.
179 ExtensionTestMessageListener
focus_listener("onFocus:text", false);
180 IMEEngineHandlerInterface::InputContext
context(ui::TEXT_INPUT_TYPE_TEXT
,
181 ui::TEXT_INPUT_MODE_DEFAULT
);
182 engine_handler
->FocusIn(context
);
183 ASSERT_TRUE(focus_listener
.WaitUntilSatisfied());
184 ASSERT_TRUE(focus_listener
.was_satisfied());
186 // onKeyEvent should be fired if ProcessKeyEvent is called.
187 KeyEventDoneCallback
callback(false); // EchoBackIME doesn't consume keys.
188 ExtensionTestMessageListener
keyevent_listener("onKeyEvent", false);
189 ui::KeyEvent
key_event(ui::ET_KEY_PRESSED
, ui::VKEY_A
, ui::EF_NONE
, false);
190 engine_handler
->ProcessKeyEvent(key_event
,
191 base::Bind(&KeyEventDoneCallback::Run
,
192 base::Unretained(&callback
)));
193 ASSERT_TRUE(keyevent_listener
.WaitUntilSatisfied());
194 ASSERT_TRUE(keyevent_listener
.was_satisfied());
195 callback
.WaitUntilCalled();
197 // onSurroundingTextChange should be fired if SetSurroundingText is called.
198 ExtensionTestMessageListener
surrounding_text_listener(
199 "onSurroundingTextChanged", false);
200 engine_handler
->SetSurroundingText("text", // Surrounding text.
201 0, // focused position.
202 1); // anchor position.
203 ASSERT_TRUE(surrounding_text_listener
.WaitUntilSatisfied());
204 ASSERT_TRUE(surrounding_text_listener
.was_satisfied());
206 // onMenuItemActivated should be fired if PropertyActivate is called.
207 ExtensionTestMessageListener
property_listener("onMenuItemActivated", false);
208 engine_handler
->PropertyActivate("property_name");
209 ASSERT_TRUE(property_listener
.WaitUntilSatisfied());
210 ASSERT_TRUE(property_listener
.was_satisfied());
212 // onReset should be fired if Reset is called.
213 ExtensionTestMessageListener
reset_listener("onReset", false);
214 engine_handler
->Reset();
215 ASSERT_TRUE(reset_listener
.WaitUntilSatisfied());
216 ASSERT_TRUE(reset_listener
.was_satisfied());
218 // onBlur should be fired if FocusOut is called.
219 ExtensionTestMessageListener
blur_listener("onBlur", false);
220 engine_handler
->FocusOut();
221 ASSERT_TRUE(blur_listener
.WaitUntilSatisfied());
222 ASSERT_TRUE(blur_listener
.was_satisfied());
224 // onDeactivated should be fired if Disable is called.
225 ExtensionTestMessageListener
disabled_listener("onDeactivated", false);
226 engine_handler
->Disable();
227 ASSERT_TRUE(disabled_listener
.WaitUntilSatisfied());
228 ASSERT_TRUE(disabled_listener
.was_satisfied());
230 IMEBridge::Get()->SetInputContextHandler(NULL
);
231 IMEBridge::Get()->SetCandidateWindowHandler(NULL
);
234 IN_PROC_BROWSER_TEST_P(InputMethodEngineBrowserTest
,
236 LoadTestInputMethod();
238 InputMethodManager::Get()->ChangeInputMethod(kAPIArgumentIMEID
);
240 scoped_ptr
<MockIMEInputContextHandler
> mock_input_context(
241 new MockIMEInputContextHandler());
242 scoped_ptr
<MockIMECandidateWindowHandler
> mock_candidate_window(
243 new MockIMECandidateWindowHandler());
245 IMEBridge::Get()->SetInputContextHandler(mock_input_context
.get());
246 IMEBridge::Get()->SetCandidateWindowHandler(mock_candidate_window
.get());
248 IMEEngineHandlerInterface
* engine_handler
=
249 IMEBridge::Get()->GetCurrentEngineHandler();
250 ASSERT_TRUE(engine_handler
);
252 extensions::ExtensionHost
* host
= FindHostWithPath(
253 extensions::ExtensionSystem::Get(profile())->process_manager(),
254 extensions::BackgroundInfo::GetBackgroundURL(extension_
).path(),
257 engine_handler
->Enable();
258 IMEEngineHandlerInterface::InputContext
context(ui::TEXT_INPUT_TYPE_TEXT
,
259 ui::TEXT_INPUT_MODE_DEFAULT
);
260 engine_handler
->FocusIn(context
);
263 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:No, Caps:No");
264 KeyEventDoneCallback
callback(false);
265 const std::string expected_value
=
266 "onKeyEvent::keydown:a:KeyA:false:false:false:false";
267 ExtensionTestMessageListener
keyevent_listener(expected_value
, false);
269 ui::KeyEvent
key_event(
270 ui::ET_KEY_PRESSED
, ui::VKEY_A
, "KeyA", ui::EF_NONE
, false);
271 engine_handler
->ProcessKeyEvent(key_event
,
272 base::Bind(&KeyEventDoneCallback::Run
,
273 base::Unretained(&callback
)));
274 ASSERT_TRUE(keyevent_listener
.WaitUntilSatisfied());
275 EXPECT_TRUE(keyevent_listener
.was_satisfied());
276 callback
.WaitUntilCalled();
279 SCOPED_TRACE("KeyDown, Ctrl:Yes, alt:No, Shift:No, Caps:No");
280 KeyEventDoneCallback
callback(false);
281 const std::string expected_value
=
282 "onKeyEvent::keydown:a:KeyA:true:false:false:false";
283 ExtensionTestMessageListener
keyevent_listener(expected_value
, false);
285 ui::KeyEvent
key_event(ui::ET_KEY_PRESSED
,
290 engine_handler
->ProcessKeyEvent(key_event
,
291 base::Bind(&KeyEventDoneCallback::Run
,
292 base::Unretained(&callback
)));
293 ASSERT_TRUE(keyevent_listener
.WaitUntilSatisfied());
294 EXPECT_TRUE(keyevent_listener
.was_satisfied());
295 callback
.WaitUntilCalled();
298 SCOPED_TRACE("KeyDown, Ctrl:No, alt:Yes, Shift:No, Caps:No");
299 KeyEventDoneCallback
callback(false);
300 const std::string expected_value
=
301 "onKeyEvent::keydown:a:KeyA:false:true:false:false";
302 ExtensionTestMessageListener
keyevent_listener(expected_value
, false);
304 ui::KeyEvent
key_event(ui::ET_KEY_PRESSED
,
309 engine_handler
->ProcessKeyEvent(key_event
,
310 base::Bind(&KeyEventDoneCallback::Run
,
311 base::Unretained(&callback
)));
312 ASSERT_TRUE(keyevent_listener
.WaitUntilSatisfied());
313 EXPECT_TRUE(keyevent_listener
.was_satisfied());
314 callback
.WaitUntilCalled();
317 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:Yes, Caps:No");
318 KeyEventDoneCallback
callback(false);
319 const std::string expected_value
=
320 "onKeyEvent::keydown:A:KeyA:false:false:true:false";
321 ExtensionTestMessageListener
keyevent_listener(expected_value
, false);
323 ui::KeyEvent
key_event(ui::ET_KEY_PRESSED
,
328 engine_handler
->ProcessKeyEvent(key_event
,
329 base::Bind(&KeyEventDoneCallback::Run
,
330 base::Unretained(&callback
)));
331 ASSERT_TRUE(keyevent_listener
.WaitUntilSatisfied());
332 EXPECT_TRUE(keyevent_listener
.was_satisfied());
333 callback
.WaitUntilCalled();
336 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:No, Caps:Yes");
337 KeyEventDoneCallback
callback(false);
338 const std::string expected_value
=
339 "onKeyEvent::keydown:a:KeyA:false:false:false:true";
340 ExtensionTestMessageListener
keyevent_listener(expected_value
, false);
342 ui::KeyEvent
key_event(ui::ET_KEY_PRESSED
,
345 ui::EF_CAPS_LOCK_DOWN
,
347 engine_handler
->ProcessKeyEvent(key_event
,
348 base::Bind(&KeyEventDoneCallback::Run
,
349 base::Unretained(&callback
)));
350 ASSERT_TRUE(keyevent_listener
.WaitUntilSatisfied());
351 EXPECT_TRUE(keyevent_listener
.was_satisfied());
352 callback
.WaitUntilCalled();
355 SCOPED_TRACE("KeyDown, Ctrl:Yes, alt:Yes, Shift:No, Caps:No");
356 KeyEventDoneCallback
callback(false);
357 const std::string expected_value
=
358 "onKeyEvent::keydown:a:KeyA:true:true:false:false";
359 ExtensionTestMessageListener
keyevent_listener(expected_value
, false);
361 ui::KeyEvent
key_event(ui::ET_KEY_PRESSED
,
364 ui::EF_ALT_DOWN
| ui::EF_CONTROL_DOWN
,
366 engine_handler
->ProcessKeyEvent(key_event
,
367 base::Bind(&KeyEventDoneCallback::Run
,
368 base::Unretained(&callback
)));
369 ASSERT_TRUE(keyevent_listener
.WaitUntilSatisfied());
370 EXPECT_TRUE(keyevent_listener
.was_satisfied());
371 callback
.WaitUntilCalled();
374 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:Yes, Caps:Yes");
375 KeyEventDoneCallback
callback(false);
376 const std::string expected_value
=
377 "onKeyEvent::keydown:A:KeyA:false:false:true:true";
378 ExtensionTestMessageListener
keyevent_listener(expected_value
, false);
380 ui::KeyEvent
key_event(ui::ET_KEY_PRESSED
,
383 ui::EF_SHIFT_DOWN
| ui::EF_CAPS_LOCK_DOWN
,
385 engine_handler
->ProcessKeyEvent(key_event
,
386 base::Bind(&KeyEventDoneCallback::Run
,
387 base::Unretained(&callback
)));
388 ASSERT_TRUE(keyevent_listener
.WaitUntilSatisfied());
389 EXPECT_TRUE(keyevent_listener
.was_satisfied());
390 callback
.WaitUntilCalled();
392 // TODO(nona): Add browser tests for other API as well.
394 SCOPED_TRACE("commitText test");
395 mock_input_context
->Reset();
396 mock_candidate_window
->Reset();
398 const char commit_text_test_script
[] =
399 "chrome.input.ime.commitText({"
400 " contextID: engineBridge.getFocusedContextID().contextID,"
401 " text:'COMMIT_TEXT'"
404 ASSERT_TRUE(content::ExecuteScript(host
->host_contents(),
405 commit_text_test_script
));
406 EXPECT_EQ(1, mock_input_context
->commit_text_call_count());
407 EXPECT_EQ("COMMIT_TEXT", mock_input_context
->last_commit_text());
410 SCOPED_TRACE("sendKeyEvents test");
411 mock_input_context
->Reset();
412 mock_candidate_window
->Reset();
414 const char send_key_events_test_script
[] =
415 "chrome.input.ime.sendKeyEvents({"
416 " contextID: engineBridge.getFocusedContextID().contextID,"
430 ExtensionTestMessageListener
keyevent_listener_down(
431 std::string("onKeyEvent:") + kExtensionID
+
432 ":keydown:z:KeyZ:false:false:false:false",
434 ExtensionTestMessageListener
keyevent_listener_up(
435 std::string("onKeyEvent:") + kExtensionID
+
436 ":keyup:z:KeyZ:false:false:false:false",
439 ASSERT_TRUE(content::ExecuteScript(host
->host_contents(),
440 send_key_events_test_script
));
442 ASSERT_TRUE(keyevent_listener_down
.WaitUntilSatisfied());
443 EXPECT_TRUE(keyevent_listener_down
.was_satisfied());
444 ASSERT_TRUE(keyevent_listener_up
.WaitUntilSatisfied());
445 EXPECT_TRUE(keyevent_listener_up
.was_satisfied());
448 SCOPED_TRACE("setComposition test");
449 mock_input_context
->Reset();
450 mock_candidate_window
->Reset();
452 const char set_composition_test_script
[] =
453 "chrome.input.ime.setComposition({"
454 " contextID: engineBridge.getFocusedContextID().contextID,"
455 " text:'COMPOSITION_TEXT',"
460 " style: 'underline'"
464 " style: 'doubleUnderline'"
468 ASSERT_TRUE(content::ExecuteScript(host
->host_contents(),
469 set_composition_test_script
));
470 EXPECT_EQ(1, mock_input_context
->update_preedit_text_call_count());
473 mock_input_context
->last_update_composition_arg().cursor_pos
);
474 EXPECT_TRUE(mock_input_context
->last_update_composition_arg().is_visible
);
476 const CompositionText
& composition_text
=
477 mock_input_context
->last_update_composition_arg().composition_text
;
478 EXPECT_EQ(base::UTF8ToUTF16("COMPOSITION_TEXT"), composition_text
.text());
479 const std::vector
<CompositionText::UnderlineAttribute
>& underlines
=
480 composition_text
.underline_attributes();
482 ASSERT_EQ(2U, underlines
.size());
483 EXPECT_EQ(CompositionText::COMPOSITION_TEXT_UNDERLINE_SINGLE
,
485 EXPECT_EQ(0U, underlines
[0].start_index
);
486 EXPECT_EQ(5U, underlines
[0].end_index
);
488 EXPECT_EQ(CompositionText::COMPOSITION_TEXT_UNDERLINE_DOUBLE
,
490 EXPECT_EQ(6U, underlines
[1].start_index
);
491 EXPECT_EQ(10U, underlines
[1].end_index
);
494 SCOPED_TRACE("clearComposition test");
495 mock_input_context
->Reset();
496 mock_candidate_window
->Reset();
498 const char commite_text_test_script
[] =
499 "chrome.input.ime.clearComposition({"
500 " contextID: engineBridge.getFocusedContextID().contextID,"
503 ASSERT_TRUE(content::ExecuteScript(host
->host_contents(),
504 commite_text_test_script
));
505 EXPECT_EQ(1, mock_input_context
->update_preedit_text_call_count());
507 mock_input_context
->last_update_composition_arg().is_visible
);
508 const CompositionText
& composition_text
=
509 mock_input_context
->last_update_composition_arg().composition_text
;
510 EXPECT_TRUE(composition_text
.text().empty());
513 SCOPED_TRACE("setCandidateWindowProperties:visibility test");
514 mock_input_context
->Reset();
515 mock_candidate_window
->Reset();
517 const char set_candidate_window_properties_test_script
[] =
518 "chrome.input.ime.setCandidateWindowProperties({"
519 " engineID: engineBridge.getActiveEngineID(),"
524 ASSERT_TRUE(content::ExecuteScript(
525 host
->host_contents(),
526 set_candidate_window_properties_test_script
));
527 EXPECT_EQ(1, mock_candidate_window
->update_lookup_table_call_count());
529 mock_candidate_window
->last_update_lookup_table_arg().is_visible
);
532 SCOPED_TRACE("setCandidateWindowProperties:cursor_visibility test");
533 mock_input_context
->Reset();
534 mock_candidate_window
->Reset();
536 const char set_candidate_window_properties_test_script
[] =
537 "chrome.input.ime.setCandidateWindowProperties({"
538 " engineID: engineBridge.getActiveEngineID(),"
540 " cursorVisible: true,"
543 ASSERT_TRUE(content::ExecuteScript(
544 host
->host_contents(),
545 set_candidate_window_properties_test_script
));
546 EXPECT_EQ(1, mock_candidate_window
->update_lookup_table_call_count());
548 // window visibility is kept as before.
550 mock_candidate_window
->last_update_lookup_table_arg().is_visible
);
552 const ui::CandidateWindow
& table
=
553 mock_candidate_window
->last_update_lookup_table_arg().lookup_table
;
554 EXPECT_TRUE(table
.is_cursor_visible());
557 SCOPED_TRACE("setCandidateWindowProperties:vertical test");
558 mock_input_context
->Reset();
559 mock_candidate_window
->Reset();
561 const char set_candidate_window_properties_test_script
[] =
562 "chrome.input.ime.setCandidateWindowProperties({"
563 " engineID: engineBridge.getActiveEngineID(),"
568 ASSERT_TRUE(content::ExecuteScript(
569 host
->host_contents(),
570 set_candidate_window_properties_test_script
));
571 EXPECT_EQ(1, mock_candidate_window
->update_lookup_table_call_count());
573 // window visibility is kept as before.
575 mock_candidate_window
->last_update_lookup_table_arg().is_visible
);
577 const ui::CandidateWindow
& table
=
578 mock_candidate_window
->last_update_lookup_table_arg().lookup_table
;
580 // cursor visibility is kept as before.
581 EXPECT_TRUE(table
.is_cursor_visible());
583 EXPECT_EQ(ui::CandidateWindow::VERTICAL
, table
.orientation());
586 SCOPED_TRACE("setCandidateWindowProperties:pageSize test");
587 mock_input_context
->Reset();
588 mock_candidate_window
->Reset();
590 const char set_candidate_window_properties_test_script
[] =
591 "chrome.input.ime.setCandidateWindowProperties({"
592 " engineID: engineBridge.getActiveEngineID(),"
597 ASSERT_TRUE(content::ExecuteScript(
598 host
->host_contents(),
599 set_candidate_window_properties_test_script
));
600 EXPECT_EQ(1, mock_candidate_window
->update_lookup_table_call_count());
602 // window visibility is kept as before.
604 mock_candidate_window
->last_update_lookup_table_arg().is_visible
);
606 const ui::CandidateWindow
& table
=
607 mock_candidate_window
->last_update_lookup_table_arg().lookup_table
;
609 // cursor visibility is kept as before.
610 EXPECT_TRUE(table
.is_cursor_visible());
612 // oritantation is kept as before.
613 EXPECT_EQ(ui::CandidateWindow::VERTICAL
, table
.orientation());
615 EXPECT_EQ(7U, table
.page_size());
618 SCOPED_TRACE("setCandidateWindowProperties:auxTextVisibility test");
619 mock_input_context
->Reset();
620 mock_candidate_window
->Reset();
622 const char set_candidate_window_properties_test_script
[] =
623 "chrome.input.ime.setCandidateWindowProperties({"
624 " engineID: engineBridge.getActiveEngineID(),"
626 " auxiliaryTextVisible: true"
629 ASSERT_TRUE(content::ExecuteScript(
630 host
->host_contents(),
631 set_candidate_window_properties_test_script
));
632 EXPECT_EQ(1, mock_candidate_window
->update_lookup_table_call_count());
634 const ui::CandidateWindow
& table
=
635 mock_candidate_window
->last_update_lookup_table_arg().lookup_table
;
636 EXPECT_TRUE(table
.is_auxiliary_text_visible());
639 SCOPED_TRACE("setCandidateWindowProperties:auxText test");
640 mock_input_context
->Reset();
641 mock_candidate_window
->Reset();
643 const char set_candidate_window_properties_test_script
[] =
644 "chrome.input.ime.setCandidateWindowProperties({"
645 " engineID: engineBridge.getActiveEngineID(),"
647 " auxiliaryText: 'AUXILIARY_TEXT'"
650 ASSERT_TRUE(content::ExecuteScript(
651 host
->host_contents(),
652 set_candidate_window_properties_test_script
));
653 EXPECT_EQ(1, mock_candidate_window
->update_lookup_table_call_count());
655 // aux text visibility is kept as before.
656 const ui::CandidateWindow
& table
=
657 mock_candidate_window
->last_update_lookup_table_arg().lookup_table
;
658 EXPECT_TRUE(table
.is_auxiliary_text_visible());
659 EXPECT_EQ("AUXILIARY_TEXT", table
.auxiliary_text());
662 SCOPED_TRACE("setCandidates test");
663 mock_input_context
->Reset();
664 mock_candidate_window
->Reset();
666 const char set_candidates_test_script
[] =
667 "chrome.input.ime.setCandidates({"
668 " contextID: engineBridge.getFocusedContextID().contextID,"
670 " candidate: 'CANDIDATE_1',"
673 " candidate: 'CANDIDATE_2',"
677 " candidate: 'CANDIDATE_3',"
680 " annotation: 'ANNOTACTION_3'"
682 " candidate: 'CANDIDATE_4',"
685 " annotation: 'ANNOTACTION_4',"
692 ASSERT_TRUE(content::ExecuteScript(host
->host_contents(),
693 set_candidates_test_script
));
695 // window visibility is kept as before.
697 mock_candidate_window
->last_update_lookup_table_arg().is_visible
);
699 const ui::CandidateWindow
& table
=
700 mock_candidate_window
->last_update_lookup_table_arg().lookup_table
;
702 // cursor visibility is kept as before.
703 EXPECT_TRUE(table
.is_cursor_visible());
705 // oritantation is kept as before.
706 EXPECT_EQ(ui::CandidateWindow::VERTICAL
, table
.orientation());
708 // page size is kept as before.
709 EXPECT_EQ(7U, table
.page_size());
711 ASSERT_EQ(4U, table
.candidates().size());
713 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_1"),
714 table
.candidates().at(0).value
);
716 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_2"),
717 table
.candidates().at(1).value
);
718 EXPECT_EQ(base::UTF8ToUTF16("LABEL_2"), table
.candidates().at(1).label
);
720 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_3"),
721 table
.candidates().at(2).value
);
722 EXPECT_EQ(base::UTF8ToUTF16("LABEL_3"), table
.candidates().at(2).label
);
723 EXPECT_EQ(base::UTF8ToUTF16("ANNOTACTION_3"),
724 table
.candidates().at(2).annotation
);
726 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_4"),
727 table
.candidates().at(3).value
);
728 EXPECT_EQ(base::UTF8ToUTF16("LABEL_4"), table
.candidates().at(3).label
);
729 EXPECT_EQ(base::UTF8ToUTF16("ANNOTACTION_4"),
730 table
.candidates().at(3).annotation
);
731 EXPECT_EQ(base::UTF8ToUTF16("TITLE_4"),
732 table
.candidates().at(3).description_title
);
733 EXPECT_EQ(base::UTF8ToUTF16("BODY_4"),
734 table
.candidates().at(3).description_body
);
737 SCOPED_TRACE("setCursorPosition test");
738 mock_input_context
->Reset();
739 mock_candidate_window
->Reset();
741 const char set_cursor_position_test_script
[] =
742 "chrome.input.ime.setCursorPosition({"
743 " contextID: engineBridge.getFocusedContextID().contextID,"
746 ASSERT_TRUE(content::ExecuteScript(
747 host
->host_contents(), set_cursor_position_test_script
));
748 EXPECT_EQ(1, mock_candidate_window
->update_lookup_table_call_count());
750 // window visibility is kept as before.
752 mock_candidate_window
->last_update_lookup_table_arg().is_visible
);
754 const ui::CandidateWindow
& table
=
755 mock_candidate_window
->last_update_lookup_table_arg().lookup_table
;
757 // cursor visibility is kept as before.
758 EXPECT_TRUE(table
.is_cursor_visible());
760 // oritantation is kept as before.
761 EXPECT_EQ(ui::CandidateWindow::VERTICAL
, table
.orientation());
763 // page size is kept as before.
764 EXPECT_EQ(7U, table
.page_size());
766 // candidates are same as before.
767 ASSERT_EQ(4U, table
.candidates().size());
769 // Candidate ID == 2 is 1 in index.
770 EXPECT_EQ(1U, table
.cursor_position());
773 SCOPED_TRACE("setMenuItem test");
774 mock_input_context
->Reset();
775 mock_candidate_window
->Reset();
777 const char set_menu_item_test_script
[] =
778 "chrome.input.ime.setMenuItems({"
779 " engineID: engineBridge.getActiveEngineID(),"
797 " style: 'separator',"
802 ASSERT_TRUE(content::ExecuteScript(
803 host
->host_contents(), set_menu_item_test_script
));
805 const ash::ime::InputMethodMenuItemList
& props
=
806 ash::ime::InputMethodMenuManager::GetInstance()->
807 GetCurrentInputMethodMenuItemList();
808 ASSERT_EQ(5U, props
.size());
810 EXPECT_EQ("ID0", props
[0].key
);
811 EXPECT_EQ("ID1", props
[1].key
);
812 EXPECT_EQ("ID2", props
[2].key
);
813 EXPECT_EQ("ID3", props
[3].key
);
814 EXPECT_EQ("ID4", props
[4].key
);
816 EXPECT_EQ("LABEL1", props
[1].label
);
817 EXPECT_EQ("LABEL2", props
[2].label
);
818 EXPECT_EQ("LABEL3", props
[3].label
);
819 EXPECT_EQ("LABEL4", props
[4].label
);
821 EXPECT_TRUE(props
[2].is_selection_item
);
822 // TODO(nona): Add tests for style: ["toggle" and "separator"]
823 // and visible:, when implement them.
825 EXPECT_TRUE(props
[4].is_selection_item_checked
);
828 SCOPED_TRACE("deleteSurroundingText test");
829 mock_input_context
->Reset();
830 mock_candidate_window
->Reset();
832 const char delete_surrounding_text_test_script
[] =
833 "chrome.input.ime.deleteSurroundingText({"
834 " engineID: engineBridge.getActiveEngineID(),"
835 " contextID: engineBridge.getFocusedContextID().contextID,"
839 ASSERT_TRUE(content::ExecuteScript(
840 host
->host_contents(), delete_surrounding_text_test_script
));
842 EXPECT_EQ(1, mock_input_context
->delete_surrounding_text_call_count());
843 EXPECT_EQ(5, mock_input_context
->last_delete_surrounding_text_arg().offset
);
845 mock_input_context
->last_delete_surrounding_text_arg().length
);
848 SCOPED_TRACE("onFocus test");
849 mock_input_context
->Reset();
850 mock_candidate_window
->Reset();
853 ExtensionTestMessageListener
focus_listener("onFocus:text", false);
854 IMEEngineHandlerInterface::InputContext
context(
855 ui::TEXT_INPUT_TYPE_TEXT
, ui::TEXT_INPUT_MODE_DEFAULT
);
856 engine_handler
->FocusIn(context
);
857 ASSERT_TRUE(focus_listener
.WaitUntilSatisfied());
858 ASSERT_TRUE(focus_listener
.was_satisfied());
861 ExtensionTestMessageListener
focus_listener("onFocus:search", false);
862 IMEEngineHandlerInterface::InputContext
context(
863 ui::TEXT_INPUT_TYPE_SEARCH
, ui::TEXT_INPUT_MODE_DEFAULT
);
864 engine_handler
->FocusIn(context
);
865 ASSERT_TRUE(focus_listener
.WaitUntilSatisfied());
866 ASSERT_TRUE(focus_listener
.was_satisfied());
869 ExtensionTestMessageListener
focus_listener("onFocus:tel", false);
870 IMEEngineHandlerInterface::InputContext
context(
871 ui::TEXT_INPUT_TYPE_TELEPHONE
, ui::TEXT_INPUT_MODE_DEFAULT
);
872 engine_handler
->FocusIn(context
);
873 ASSERT_TRUE(focus_listener
.WaitUntilSatisfied());
874 ASSERT_TRUE(focus_listener
.was_satisfied());
877 ExtensionTestMessageListener
focus_listener("onFocus:url", false);
878 IMEEngineHandlerInterface::InputContext
context(
879 ui::TEXT_INPUT_TYPE_URL
, ui::TEXT_INPUT_MODE_DEFAULT
);
880 engine_handler
->FocusIn(context
);
881 ASSERT_TRUE(focus_listener
.WaitUntilSatisfied());
882 ASSERT_TRUE(focus_listener
.was_satisfied());
885 ExtensionTestMessageListener
focus_listener("onFocus:email", false);
886 IMEEngineHandlerInterface::InputContext
context(
887 ui::TEXT_INPUT_TYPE_EMAIL
, ui::TEXT_INPUT_MODE_DEFAULT
);
888 engine_handler
->FocusIn(context
);
889 ASSERT_TRUE(focus_listener
.WaitUntilSatisfied());
890 ASSERT_TRUE(focus_listener
.was_satisfied());
893 ExtensionTestMessageListener
focus_listener("onFocus:number", false);
894 IMEEngineHandlerInterface::InputContext
context(
895 ui::TEXT_INPUT_TYPE_NUMBER
, ui::TEXT_INPUT_MODE_DEFAULT
);
896 engine_handler
->FocusIn(context
);
897 ASSERT_TRUE(focus_listener
.WaitUntilSatisfied());
898 ASSERT_TRUE(focus_listener
.was_satisfied());
902 IMEBridge::Get()->SetInputContextHandler(NULL
);
903 IMEBridge::Get()->SetCandidateWindowHandler(NULL
);
907 } // namespace input_method
908 } // namespace chromeos