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("sendKeyEvents test with keyCode");
449 mock_input_context->Reset();
450 mock_candidate_window->Reset();
452 const char send_key_events_test_script[] =
453 "chrome.input.ime.sendKeyEvents({"
454 " contextID: engineBridge.getFocusedContextID().contextID,"
470 ExtensionTestMessageListener keyevent_listener_down(
471 std::string("onKeyEvent:") + kExtensionID +
472 ":keydown:a:KeyQ:false:false:false:false",
474 ExtensionTestMessageListener keyevent_listener_up(
475 std::string("onKeyEvent:") + kExtensionID +
476 ":keyup:a:KeyQ:false:false:false:false",
479 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
480 send_key_events_test_script));
482 ASSERT_TRUE(keyevent_listener_down.WaitUntilSatisfied());
483 EXPECT_TRUE(keyevent_listener_down.was_satisfied());
484 ASSERT_TRUE(keyevent_listener_up.WaitUntilSatisfied());
485 EXPECT_TRUE(keyevent_listener_up.was_satisfied());
488 SCOPED_TRACE("setComposition test");
489 mock_input_context->Reset();
490 mock_candidate_window->Reset();
492 const char set_composition_test_script[] =
493 "chrome.input.ime.setComposition({"
494 " contextID: engineBridge.getFocusedContextID().contextID,"
495 " text:'COMPOSITION_TEXT',"
500 " style: 'underline'"
504 " style: 'doubleUnderline'"
508 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
509 set_composition_test_script));
510 EXPECT_EQ(1, mock_input_context->update_preedit_text_call_count());
513 mock_input_context->last_update_composition_arg().cursor_pos);
514 EXPECT_TRUE(mock_input_context->last_update_composition_arg().is_visible);
516 const CompositionText& composition_text =
517 mock_input_context->last_update_composition_arg().composition_text;
518 EXPECT_EQ(base::UTF8ToUTF16("COMPOSITION_TEXT"), composition_text.text());
519 const std::vector<CompositionText::UnderlineAttribute>& underlines =
520 composition_text.underline_attributes();
522 ASSERT_EQ(2U, underlines.size());
523 EXPECT_EQ(CompositionText::COMPOSITION_TEXT_UNDERLINE_SINGLE,
525 EXPECT_EQ(0U, underlines[0].start_index);
526 EXPECT_EQ(5U, underlines[0].end_index);
528 EXPECT_EQ(CompositionText::COMPOSITION_TEXT_UNDERLINE_DOUBLE,
530 EXPECT_EQ(6U, underlines[1].start_index);
531 EXPECT_EQ(10U, underlines[1].end_index);
534 SCOPED_TRACE("clearComposition test");
535 mock_input_context->Reset();
536 mock_candidate_window->Reset();
538 const char commite_text_test_script[] =
539 "chrome.input.ime.clearComposition({"
540 " contextID: engineBridge.getFocusedContextID().contextID,"
543 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
544 commite_text_test_script));
545 EXPECT_EQ(1, mock_input_context->update_preedit_text_call_count());
547 mock_input_context->last_update_composition_arg().is_visible);
548 const CompositionText& composition_text =
549 mock_input_context->last_update_composition_arg().composition_text;
550 EXPECT_TRUE(composition_text.text().empty());
553 SCOPED_TRACE("setCandidateWindowProperties:visibility test");
554 mock_input_context->Reset();
555 mock_candidate_window->Reset();
557 const char set_candidate_window_properties_test_script[] =
558 "chrome.input.ime.setCandidateWindowProperties({"
559 " engineID: engineBridge.getActiveEngineID(),"
564 ASSERT_TRUE(content::ExecuteScript(
565 host->host_contents(),
566 set_candidate_window_properties_test_script));
567 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
569 mock_candidate_window->last_update_lookup_table_arg().is_visible);
572 SCOPED_TRACE("setCandidateWindowProperties:cursor_visibility test");
573 mock_input_context->Reset();
574 mock_candidate_window->Reset();
576 const char set_candidate_window_properties_test_script[] =
577 "chrome.input.ime.setCandidateWindowProperties({"
578 " engineID: engineBridge.getActiveEngineID(),"
580 " cursorVisible: true,"
583 ASSERT_TRUE(content::ExecuteScript(
584 host->host_contents(),
585 set_candidate_window_properties_test_script));
586 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
588 // window visibility is kept as before.
590 mock_candidate_window->last_update_lookup_table_arg().is_visible);
592 const ui::CandidateWindow& table =
593 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
594 EXPECT_TRUE(table.is_cursor_visible());
597 SCOPED_TRACE("setCandidateWindowProperties:vertical test");
598 mock_input_context->Reset();
599 mock_candidate_window->Reset();
601 const char set_candidate_window_properties_test_script[] =
602 "chrome.input.ime.setCandidateWindowProperties({"
603 " engineID: engineBridge.getActiveEngineID(),"
608 ASSERT_TRUE(content::ExecuteScript(
609 host->host_contents(),
610 set_candidate_window_properties_test_script));
611 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
613 // window visibility is kept as before.
615 mock_candidate_window->last_update_lookup_table_arg().is_visible);
617 const ui::CandidateWindow& table =
618 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
620 // cursor visibility is kept as before.
621 EXPECT_TRUE(table.is_cursor_visible());
623 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
626 SCOPED_TRACE("setCandidateWindowProperties:pageSize test");
627 mock_input_context->Reset();
628 mock_candidate_window->Reset();
630 const char set_candidate_window_properties_test_script[] =
631 "chrome.input.ime.setCandidateWindowProperties({"
632 " engineID: engineBridge.getActiveEngineID(),"
637 ASSERT_TRUE(content::ExecuteScript(
638 host->host_contents(),
639 set_candidate_window_properties_test_script));
640 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
642 // window visibility is kept as before.
644 mock_candidate_window->last_update_lookup_table_arg().is_visible);
646 const ui::CandidateWindow& table =
647 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
649 // cursor visibility is kept as before.
650 EXPECT_TRUE(table.is_cursor_visible());
652 // oritantation is kept as before.
653 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
655 EXPECT_EQ(7U, table.page_size());
658 SCOPED_TRACE("setCandidateWindowProperties:auxTextVisibility test");
659 mock_input_context->Reset();
660 mock_candidate_window->Reset();
662 const char set_candidate_window_properties_test_script[] =
663 "chrome.input.ime.setCandidateWindowProperties({"
664 " engineID: engineBridge.getActiveEngineID(),"
666 " auxiliaryTextVisible: true"
669 ASSERT_TRUE(content::ExecuteScript(
670 host->host_contents(),
671 set_candidate_window_properties_test_script));
672 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
674 const ui::CandidateWindow& table =
675 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
676 EXPECT_TRUE(table.is_auxiliary_text_visible());
679 SCOPED_TRACE("setCandidateWindowProperties:auxText test");
680 mock_input_context->Reset();
681 mock_candidate_window->Reset();
683 const char set_candidate_window_properties_test_script[] =
684 "chrome.input.ime.setCandidateWindowProperties({"
685 " engineID: engineBridge.getActiveEngineID(),"
687 " auxiliaryText: 'AUXILIARY_TEXT'"
690 ASSERT_TRUE(content::ExecuteScript(
691 host->host_contents(),
692 set_candidate_window_properties_test_script));
693 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
695 // aux text visibility is kept as before.
696 const ui::CandidateWindow& table =
697 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
698 EXPECT_TRUE(table.is_auxiliary_text_visible());
699 EXPECT_EQ("AUXILIARY_TEXT", table.auxiliary_text());
702 SCOPED_TRACE("setCandidates test");
703 mock_input_context->Reset();
704 mock_candidate_window->Reset();
706 const char set_candidates_test_script[] =
707 "chrome.input.ime.setCandidates({"
708 " contextID: engineBridge.getFocusedContextID().contextID,"
710 " candidate: 'CANDIDATE_1',"
713 " candidate: 'CANDIDATE_2',"
717 " candidate: 'CANDIDATE_3',"
720 " annotation: 'ANNOTACTION_3'"
722 " candidate: 'CANDIDATE_4',"
725 " annotation: 'ANNOTACTION_4',"
732 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
733 set_candidates_test_script));
735 // window visibility is kept as before.
737 mock_candidate_window->last_update_lookup_table_arg().is_visible);
739 const ui::CandidateWindow& table =
740 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
742 // cursor visibility is kept as before.
743 EXPECT_TRUE(table.is_cursor_visible());
745 // oritantation is kept as before.
746 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
748 // page size is kept as before.
749 EXPECT_EQ(7U, table.page_size());
751 ASSERT_EQ(4U, table.candidates().size());
753 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_1"),
754 table.candidates().at(0).value);
756 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_2"),
757 table.candidates().at(1).value);
758 EXPECT_EQ(base::UTF8ToUTF16("LABEL_2"), table.candidates().at(1).label);
760 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_3"),
761 table.candidates().at(2).value);
762 EXPECT_EQ(base::UTF8ToUTF16("LABEL_3"), table.candidates().at(2).label);
763 EXPECT_EQ(base::UTF8ToUTF16("ANNOTACTION_3"),
764 table.candidates().at(2).annotation);
766 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_4"),
767 table.candidates().at(3).value);
768 EXPECT_EQ(base::UTF8ToUTF16("LABEL_4"), table.candidates().at(3).label);
769 EXPECT_EQ(base::UTF8ToUTF16("ANNOTACTION_4"),
770 table.candidates().at(3).annotation);
771 EXPECT_EQ(base::UTF8ToUTF16("TITLE_4"),
772 table.candidates().at(3).description_title);
773 EXPECT_EQ(base::UTF8ToUTF16("BODY_4"),
774 table.candidates().at(3).description_body);
777 SCOPED_TRACE("setCursorPosition test");
778 mock_input_context->Reset();
779 mock_candidate_window->Reset();
781 const char set_cursor_position_test_script[] =
782 "chrome.input.ime.setCursorPosition({"
783 " contextID: engineBridge.getFocusedContextID().contextID,"
786 ASSERT_TRUE(content::ExecuteScript(
787 host->host_contents(), set_cursor_position_test_script));
788 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
790 // window visibility is kept as before.
792 mock_candidate_window->last_update_lookup_table_arg().is_visible);
794 const ui::CandidateWindow& table =
795 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
797 // cursor visibility is kept as before.
798 EXPECT_TRUE(table.is_cursor_visible());
800 // oritantation is kept as before.
801 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
803 // page size is kept as before.
804 EXPECT_EQ(7U, table.page_size());
806 // candidates are same as before.
807 ASSERT_EQ(4U, table.candidates().size());
809 // Candidate ID == 2 is 1 in index.
810 EXPECT_EQ(1U, table.cursor_position());
813 SCOPED_TRACE("setMenuItem test");
814 mock_input_context->Reset();
815 mock_candidate_window->Reset();
817 const char set_menu_item_test_script[] =
818 "chrome.input.ime.setMenuItems({"
819 " engineID: engineBridge.getActiveEngineID(),"
837 " style: 'separator',"
842 ASSERT_TRUE(content::ExecuteScript(
843 host->host_contents(), set_menu_item_test_script));
845 const ash::ime::InputMethodMenuItemList& props =
846 ash::ime::InputMethodMenuManager::GetInstance()->
847 GetCurrentInputMethodMenuItemList();
848 ASSERT_EQ(5U, props.size());
850 EXPECT_EQ("ID0", props[0].key);
851 EXPECT_EQ("ID1", props[1].key);
852 EXPECT_EQ("ID2", props[2].key);
853 EXPECT_EQ("ID3", props[3].key);
854 EXPECT_EQ("ID4", props[4].key);
856 EXPECT_EQ("LABEL1", props[1].label);
857 EXPECT_EQ("LABEL2", props[2].label);
858 EXPECT_EQ("LABEL3", props[3].label);
859 EXPECT_EQ("LABEL4", props[4].label);
861 EXPECT_TRUE(props[2].is_selection_item);
862 // TODO(nona): Add tests for style: ["toggle" and "separator"]
863 // and visible:, when implement them.
865 EXPECT_TRUE(props[4].is_selection_item_checked);
868 SCOPED_TRACE("deleteSurroundingText test");
869 mock_input_context->Reset();
870 mock_candidate_window->Reset();
872 const char delete_surrounding_text_test_script[] =
873 "chrome.input.ime.deleteSurroundingText({"
874 " engineID: engineBridge.getActiveEngineID(),"
875 " contextID: engineBridge.getFocusedContextID().contextID,"
879 ASSERT_TRUE(content::ExecuteScript(
880 host->host_contents(), delete_surrounding_text_test_script));
882 EXPECT_EQ(1, mock_input_context->delete_surrounding_text_call_count());
883 EXPECT_EQ(5, mock_input_context->last_delete_surrounding_text_arg().offset);
885 mock_input_context->last_delete_surrounding_text_arg().length);
888 SCOPED_TRACE("onFocus test");
889 mock_input_context->Reset();
890 mock_candidate_window->Reset();
893 ExtensionTestMessageListener focus_listener("onFocus:text", false);
894 IMEEngineHandlerInterface::InputContext context(
895 ui::TEXT_INPUT_TYPE_TEXT, ui::TEXT_INPUT_MODE_DEFAULT);
896 engine_handler->FocusIn(context);
897 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
898 ASSERT_TRUE(focus_listener.was_satisfied());
901 ExtensionTestMessageListener focus_listener("onFocus:search", false);
902 IMEEngineHandlerInterface::InputContext context(
903 ui::TEXT_INPUT_TYPE_SEARCH, ui::TEXT_INPUT_MODE_DEFAULT);
904 engine_handler->FocusIn(context);
905 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
906 ASSERT_TRUE(focus_listener.was_satisfied());
909 ExtensionTestMessageListener focus_listener("onFocus:tel", false);
910 IMEEngineHandlerInterface::InputContext context(
911 ui::TEXT_INPUT_TYPE_TELEPHONE, ui::TEXT_INPUT_MODE_DEFAULT);
912 engine_handler->FocusIn(context);
913 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
914 ASSERT_TRUE(focus_listener.was_satisfied());
917 ExtensionTestMessageListener focus_listener("onFocus:url", false);
918 IMEEngineHandlerInterface::InputContext context(
919 ui::TEXT_INPUT_TYPE_URL, ui::TEXT_INPUT_MODE_DEFAULT);
920 engine_handler->FocusIn(context);
921 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
922 ASSERT_TRUE(focus_listener.was_satisfied());
925 ExtensionTestMessageListener focus_listener("onFocus:email", false);
926 IMEEngineHandlerInterface::InputContext context(
927 ui::TEXT_INPUT_TYPE_EMAIL, ui::TEXT_INPUT_MODE_DEFAULT);
928 engine_handler->FocusIn(context);
929 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
930 ASSERT_TRUE(focus_listener.was_satisfied());
933 ExtensionTestMessageListener focus_listener("onFocus:number", false);
934 IMEEngineHandlerInterface::InputContext context(
935 ui::TEXT_INPUT_TYPE_NUMBER, ui::TEXT_INPUT_MODE_DEFAULT);
936 engine_handler->FocusIn(context);
937 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
938 ASSERT_TRUE(focus_listener.was_satisfied());
942 IMEBridge::Get()->SetInputContextHandler(NULL);
943 IMEBridge::Get()->SetCandidateWindowHandler(NULL);
947 } // namespace input_method
948 } // namespace chromeos