BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / chrome / browser / chromeos / input_method / input_method_engine_browsertests.cc
blob677025ff47a72331ac1b8b91d1aa035b99e7f2f1
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 "base/bind_helpers.h"
6 #include "base/strings/stringprintf.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/extensions/extension_browsertest.h"
9 #include "content/public/test/browser_test_utils.h"
10 #include "content/public/test/test_utils.h"
11 #include "extensions/browser/process_manager.h"
12 #include "extensions/common/manifest_handlers/background_info.h"
13 #include "extensions/test/extension_test_message_listener.h"
14 #include "ui/base/ime/chromeos/component_extension_ime_manager.h"
15 #include "ui/base/ime/chromeos/composition_text_chromeos.h"
16 #include "ui/base/ime/chromeos/ime_bridge.h"
17 #include "ui/base/ime/chromeos/input_method_descriptor.h"
18 #include "ui/base/ime/chromeos/input_method_manager.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/base/ime/text_input_flags.h"
22 #include "ui/chromeos/ime/input_method_menu_item.h"
23 #include "ui/chromeos/ime/input_method_menu_manager.h"
24 #include "ui/events/event.h"
25 #include "ui/events/keycodes/dom/dom_code.h"
26 #include "ui/events/keycodes/dom/keycode_converter.h"
28 namespace chromeos {
29 namespace input_method {
30 namespace {
32 const char kIdentityIMEID[] =
33 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpIdentityIME";
34 const char kToUpperIMEID[] =
35 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpToUpperIME";
36 const char kAPIArgumentIMEID[] =
37 "_ext_ime_iafoklpfplgfnoimmaejoeondnjnlcfpAPIArgumentIME";
38 const char kExtensionID[] = "iafoklpfplgfnoimmaejoeondnjnlcfp";
40 // InputMethod extension should work on 1)normal extension, 2)normal extension
41 // in incognito mode 3)component extension.
42 enum TestType {
43 kTestTypeNormal = 0,
44 kTestTypeIncognito = 1,
45 kTestTypeComponent = 2,
48 class InputMethodEngineBrowserTest
49 : public ExtensionBrowserTest,
50 public ::testing::WithParamInterface<TestType> {
51 public:
52 InputMethodEngineBrowserTest()
53 : ExtensionBrowserTest() {}
54 virtual ~InputMethodEngineBrowserTest() {}
56 void SetUpInProcessBrowserTestFixture() override {
57 ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
60 void TearDownInProcessBrowserTestFixture() override { extension_ = NULL; }
62 protected:
63 void LoadTestInputMethod() {
64 // This will load "chrome/test/data/extensions/input_ime"
65 ExtensionTestMessageListener ime_ready_listener("ReadyToUseImeEvent",
66 false);
67 extension_ = LoadExtensionWithType("input_ime", GetParam());
68 ASSERT_TRUE(extension_);
69 ASSERT_TRUE(ime_ready_listener.WaitUntilSatisfied());
71 // Extension IMEs are not enabled by default.
72 std::vector<std::string> extension_ime_ids;
73 extension_ime_ids.push_back(kIdentityIMEID);
74 extension_ime_ids.push_back(kToUpperIMEID);
75 extension_ime_ids.push_back(kAPIArgumentIMEID);
76 InputMethodManager::Get()->GetActiveIMEState()->SetEnabledExtensionImes(
77 &extension_ime_ids);
79 InputMethodDescriptors extension_imes;
80 InputMethodManager::Get()->GetActiveIMEState()->GetInputMethodExtensions(
81 &extension_imes);
83 // Test IME has two input methods, thus InputMethodManager should have two
84 // extension IME.
85 // Note: Even extension is loaded by LoadExtensionAsComponent as above, the
86 // IME does not managed by ComponentExtensionIMEManager or it's id won't
87 // start with __comp__. The component extension IME is whitelisted and
88 // managed by ComponentExtensionIMEManager, but its framework is same as
89 // normal extension IME.
90 EXPECT_EQ(3U, extension_imes.size());
93 const extensions::Extension* LoadExtensionWithType(
94 const std::string& extension_name, TestType type) {
95 switch (type) {
96 case kTestTypeNormal:
97 return LoadExtension(test_data_dir_.AppendASCII(extension_name));
98 case kTestTypeIncognito:
99 return LoadExtensionIncognito(
100 test_data_dir_.AppendASCII(extension_name));
101 case kTestTypeComponent:
102 return LoadExtensionAsComponent(
103 test_data_dir_.AppendASCII(extension_name));
105 NOTREACHED();
106 return NULL;
109 const extensions::Extension* extension_;
112 class KeyEventDoneCallback {
113 public:
114 explicit KeyEventDoneCallback(bool expected_argument)
115 : expected_argument_(expected_argument),
116 is_called_(false) {}
117 ~KeyEventDoneCallback() {}
119 void Run(bool consumed) {
120 if (consumed == expected_argument_) {
121 base::MessageLoop::current()->Quit();
122 is_called_ = true;
126 void WaitUntilCalled() {
127 while (!is_called_)
128 content::RunMessageLoop();
131 private:
132 bool expected_argument_;
133 bool is_called_;
135 DISALLOW_COPY_AND_ASSIGN(KeyEventDoneCallback);
138 INSTANTIATE_TEST_CASE_P(InputMethodEngineBrowserTest,
139 InputMethodEngineBrowserTest,
140 ::testing::Values(kTestTypeNormal));
141 INSTANTIATE_TEST_CASE_P(InputMethodEngineIncognitoBrowserTest,
142 InputMethodEngineBrowserTest,
143 ::testing::Values(kTestTypeIncognito));
144 INSTANTIATE_TEST_CASE_P(InputMethodEngineComponentExtensionBrowserTest,
145 InputMethodEngineBrowserTest,
146 ::testing::Values(kTestTypeComponent));
148 IN_PROC_BROWSER_TEST_P(InputMethodEngineBrowserTest,
149 BasicScenarioTest) {
150 LoadTestInputMethod();
152 InputMethodManager::Get()->GetActiveIMEState()->ChangeInputMethod(
153 kIdentityIMEID, false /* show_message */);
155 scoped_ptr<MockIMEInputContextHandler> mock_input_context(
156 new MockIMEInputContextHandler());
157 scoped_ptr<MockIMECandidateWindowHandler> mock_candidate_window(
158 new MockIMECandidateWindowHandler());
160 IMEBridge::Get()->SetInputContextHandler(mock_input_context.get());
161 IMEBridge::Get()->SetCandidateWindowHandler(mock_candidate_window.get());
163 IMEEngineHandlerInterface* engine_handler =
164 IMEBridge::Get()->GetCurrentEngineHandler();
165 ASSERT_TRUE(engine_handler);
167 // onActivate event should be fired if Enable function is called.
168 ExtensionTestMessageListener activated_listener("onActivate", false);
169 engine_handler->Enable("IdentityIME");
170 ASSERT_TRUE(activated_listener.WaitUntilSatisfied());
171 ASSERT_TRUE(activated_listener.was_satisfied());
173 // onFocus event should be fired if FocusIn function is called.
174 ExtensionTestMessageListener focus_listener("onFocus:text", false);
175 IMEEngineHandlerInterface::InputContext context(ui::TEXT_INPUT_TYPE_TEXT,
176 ui::TEXT_INPUT_MODE_DEFAULT,
177 ui::TEXT_INPUT_FLAG_NONE);
178 engine_handler->FocusIn(context);
179 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
180 ASSERT_TRUE(focus_listener.was_satisfied());
182 // onKeyEvent should be fired if ProcessKeyEvent is called.
183 KeyEventDoneCallback callback(false); // EchoBackIME doesn't consume keys.
184 ExtensionTestMessageListener keyevent_listener("onKeyEvent", false);
185 ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
186 engine_handler->ProcessKeyEvent(key_event,
187 base::Bind(&KeyEventDoneCallback::Run,
188 base::Unretained(&callback)));
189 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
190 ASSERT_TRUE(keyevent_listener.was_satisfied());
191 callback.WaitUntilCalled();
193 // onSurroundingTextChange should be fired if SetSurroundingText is called.
194 ExtensionTestMessageListener surrounding_text_listener(
195 "onSurroundingTextChanged", false);
196 engine_handler->SetSurroundingText("text", // Surrounding text.
197 0, // focused position.
198 1, // anchor position.
199 0); // offset position.
200 ASSERT_TRUE(surrounding_text_listener.WaitUntilSatisfied());
201 ASSERT_TRUE(surrounding_text_listener.was_satisfied());
203 // onMenuItemActivated should be fired if PropertyActivate is called.
204 ExtensionTestMessageListener property_listener("onMenuItemActivated", false);
205 engine_handler->PropertyActivate("property_name");
206 ASSERT_TRUE(property_listener.WaitUntilSatisfied());
207 ASSERT_TRUE(property_listener.was_satisfied());
209 // onReset should be fired if Reset is called.
210 ExtensionTestMessageListener reset_listener("onReset", false);
211 engine_handler->Reset();
212 ASSERT_TRUE(reset_listener.WaitUntilSatisfied());
213 ASSERT_TRUE(reset_listener.was_satisfied());
215 // onBlur should be fired if FocusOut is called.
216 ExtensionTestMessageListener blur_listener("onBlur", false);
217 engine_handler->FocusOut();
218 ASSERT_TRUE(blur_listener.WaitUntilSatisfied());
219 ASSERT_TRUE(blur_listener.was_satisfied());
221 // onDeactivated should be fired if Disable is called.
222 ExtensionTestMessageListener disabled_listener("onDeactivated", false);
223 engine_handler->Disable();
224 ASSERT_TRUE(disabled_listener.WaitUntilSatisfied());
225 ASSERT_TRUE(disabled_listener.was_satisfied());
227 IMEBridge::Get()->SetInputContextHandler(NULL);
228 IMEBridge::Get()->SetCandidateWindowHandler(NULL);
231 IN_PROC_BROWSER_TEST_P(InputMethodEngineBrowserTest,
232 APIArgumentTest) {
233 LoadTestInputMethod();
235 InputMethodManager::Get()->GetActiveIMEState()->ChangeInputMethod(
236 kAPIArgumentIMEID, false /* show_message */);
238 scoped_ptr<MockIMEInputContextHandler> mock_input_context(
239 new MockIMEInputContextHandler());
240 scoped_ptr<MockIMECandidateWindowHandler> mock_candidate_window(
241 new MockIMECandidateWindowHandler());
243 IMEBridge::Get()->SetInputContextHandler(mock_input_context.get());
244 IMEBridge::Get()->SetCandidateWindowHandler(mock_candidate_window.get());
246 IMEEngineHandlerInterface* engine_handler =
247 IMEBridge::Get()->GetCurrentEngineHandler();
248 ASSERT_TRUE(engine_handler);
250 extensions::ExtensionHost* host =
251 extensions::ProcessManager::Get(profile())
252 ->GetBackgroundHostForExtension(extension_->id());
253 ASSERT_TRUE(host);
255 engine_handler->Enable("APIArgumentIME");
256 IMEEngineHandlerInterface::InputContext context(ui::TEXT_INPUT_TYPE_TEXT,
257 ui::TEXT_INPUT_MODE_DEFAULT,
258 ui::TEXT_INPUT_FLAG_NONE);
259 engine_handler->FocusIn(context);
262 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:No, Caps:No");
263 KeyEventDoneCallback callback(false);
264 const std::string expected_value =
265 "onKeyEvent::keydown:a:KeyA:false:false:false:false";
266 ExtensionTestMessageListener keyevent_listener(expected_value, false);
268 ui::KeyEvent key_event(
269 ui::ET_KEY_PRESSED, ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_NONE);
270 engine_handler->ProcessKeyEvent(key_event,
271 base::Bind(&KeyEventDoneCallback::Run,
272 base::Unretained(&callback)));
273 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
274 EXPECT_TRUE(keyevent_listener.was_satisfied());
275 callback.WaitUntilCalled();
278 SCOPED_TRACE("KeyDown, Ctrl:Yes, alt:No, Shift:No, Caps:No");
279 KeyEventDoneCallback callback(false);
280 const std::string expected_value =
281 "onKeyEvent::keydown:a:KeyA:true:false:false:false";
282 ExtensionTestMessageListener keyevent_listener(expected_value, false);
284 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
285 ui::VKEY_A,
286 ui::DomCode::KEY_A,
287 ui::EF_CONTROL_DOWN);
288 engine_handler->ProcessKeyEvent(key_event,
289 base::Bind(&KeyEventDoneCallback::Run,
290 base::Unretained(&callback)));
291 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
292 EXPECT_TRUE(keyevent_listener.was_satisfied());
293 callback.WaitUntilCalled();
296 SCOPED_TRACE("KeyDown, Ctrl:No, alt:Yes, Shift:No, Caps:No");
297 KeyEventDoneCallback callback(false);
298 const std::string expected_value =
299 "onKeyEvent::keydown:a:KeyA:false:true:false:false";
300 ExtensionTestMessageListener keyevent_listener(expected_value, false);
302 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
303 ui::VKEY_A,
304 ui::DomCode::KEY_A,
305 ui::EF_ALT_DOWN);
306 engine_handler->ProcessKeyEvent(key_event,
307 base::Bind(&KeyEventDoneCallback::Run,
308 base::Unretained(&callback)));
309 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
310 EXPECT_TRUE(keyevent_listener.was_satisfied());
311 callback.WaitUntilCalled();
314 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:Yes, Caps:No");
315 KeyEventDoneCallback callback(false);
316 const std::string expected_value =
317 "onKeyEvent::keydown:A:KeyA:false:false:true:false";
318 ExtensionTestMessageListener keyevent_listener(expected_value, false);
320 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
321 ui::VKEY_A,
322 ui::DomCode::KEY_A,
323 ui::EF_SHIFT_DOWN);
324 engine_handler->ProcessKeyEvent(key_event,
325 base::Bind(&KeyEventDoneCallback::Run,
326 base::Unretained(&callback)));
327 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
328 EXPECT_TRUE(keyevent_listener.was_satisfied());
329 callback.WaitUntilCalled();
332 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:No, Caps:Yes");
333 KeyEventDoneCallback callback(false);
334 const std::string expected_value =
335 "onKeyEvent::keydown:A:KeyA:false:false:false:true";
336 ExtensionTestMessageListener keyevent_listener(expected_value, false);
338 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
339 ui::VKEY_A,
340 ui::DomCode::KEY_A,
341 ui::EF_CAPS_LOCK_DOWN);
342 engine_handler->ProcessKeyEvent(key_event,
343 base::Bind(&KeyEventDoneCallback::Run,
344 base::Unretained(&callback)));
345 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
346 EXPECT_TRUE(keyevent_listener.was_satisfied());
347 callback.WaitUntilCalled();
350 SCOPED_TRACE("KeyDown, Ctrl:Yes, alt:Yes, Shift:No, Caps:No");
351 KeyEventDoneCallback callback(false);
352 const std::string expected_value =
353 "onKeyEvent::keydown:a:KeyA:true:true:false:false";
354 ExtensionTestMessageListener keyevent_listener(expected_value, false);
356 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
357 ui::VKEY_A,
358 ui::DomCode::KEY_A,
359 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN);
360 engine_handler->ProcessKeyEvent(key_event,
361 base::Bind(&KeyEventDoneCallback::Run,
362 base::Unretained(&callback)));
363 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
364 EXPECT_TRUE(keyevent_listener.was_satisfied());
365 callback.WaitUntilCalled();
368 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:Yes, Caps:Yes");
369 KeyEventDoneCallback callback(false);
370 const std::string expected_value =
371 "onKeyEvent::keydown:a:KeyA:false:false:true:true";
372 ExtensionTestMessageListener keyevent_listener(expected_value, false);
374 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
375 ui::VKEY_A,
376 ui::DomCode::KEY_A,
377 ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN);
378 engine_handler->ProcessKeyEvent(key_event,
379 base::Bind(&KeyEventDoneCallback::Run,
380 base::Unretained(&callback)));
381 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
382 EXPECT_TRUE(keyevent_listener.was_satisfied());
383 callback.WaitUntilCalled();
385 // Media keys cases.
386 const struct {
387 ui::KeyboardCode keycode;
388 const char* code;
389 const char* key;
390 } kMediaKeyCases[] = {
391 { ui::VKEY_BROWSER_BACK, "BrowserBack", "HistoryBack" },
392 { ui::VKEY_BROWSER_FORWARD, "BrowserForward", "HistoryForward" },
393 { ui::VKEY_BROWSER_REFRESH, "BrowserRefresh", "BrowserRefresh" },
394 { ui::VKEY_MEDIA_LAUNCH_APP2, "ChromeOSFullscreen", "ChromeOSFullscreen" },
395 { ui::VKEY_MEDIA_LAUNCH_APP1,
396 "ChromeOSSwitchWindow", "ChromeOSSwitchWindow" },
397 { ui::VKEY_BRIGHTNESS_DOWN, "BrightnessDown", "BrightnessDown" },
398 { ui::VKEY_BRIGHTNESS_UP, "BrightnessUp", "BrightnessUp" },
399 { ui::VKEY_VOLUME_MUTE, "VolumeMute", "AudioVolumeMute" },
400 { ui::VKEY_VOLUME_DOWN, "VolumeDown", "AudioVolumeDown" },
401 { ui::VKEY_VOLUME_UP, "VolumeUp", "AudioVolumeUp" },
402 { ui::VKEY_F1, "F1", "HistoryBack" },
403 { ui::VKEY_F2, "F2", "HistoryForward" },
404 { ui::VKEY_F3, "F3", "BrowserRefresh" },
405 { ui::VKEY_F4, "F4", "ChromeOSFullscreen" },
406 { ui::VKEY_F5, "F5", "ChromeOSSwitchWindow" },
407 { ui::VKEY_F6, "F6", "BrightnessDown" },
408 { ui::VKEY_F7, "F7", "BrightnessUp" },
409 { ui::VKEY_F8, "F8", "AudioVolumeMute" },
410 { ui::VKEY_F9, "F9", "AudioVolumeDown" },
411 { ui::VKEY_F10, "F10", "AudioVolumeUp" },
413 for (size_t i = 0; i < arraysize(kMediaKeyCases); ++i) {
414 SCOPED_TRACE(std::string("KeyDown, ") + kMediaKeyCases[i].code);
415 KeyEventDoneCallback callback(false);
416 const std::string expected_value =
417 base::StringPrintf("onKeyEvent::keydown:%s:%s:false:false:false:false",
418 kMediaKeyCases[i].key, kMediaKeyCases[i].code);
419 ExtensionTestMessageListener keyevent_listener(expected_value, false);
421 ui::KeyEvent key_event(
422 ui::ET_KEY_PRESSED,
423 kMediaKeyCases[i].keycode,
424 ui::KeycodeConverter::CodeStringToDomCode(kMediaKeyCases[i].code),
425 ui::EF_NONE);
426 engine_handler->ProcessKeyEvent(key_event,
427 base::Bind(&KeyEventDoneCallback::Run,
428 base::Unretained(&callback)));
429 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
430 EXPECT_TRUE(keyevent_listener.was_satisfied());
431 callback.WaitUntilCalled();
433 // TODO(nona): Add browser tests for other API as well.
435 SCOPED_TRACE("commitText test");
436 mock_input_context->Reset();
437 mock_candidate_window->Reset();
439 const char commit_text_test_script[] =
440 "chrome.input.ime.commitText({"
441 " contextID: engineBridge.getFocusedContextID().contextID,"
442 " text:'COMMIT_TEXT'"
443 "});";
445 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
446 commit_text_test_script));
447 EXPECT_EQ(1, mock_input_context->commit_text_call_count());
448 EXPECT_EQ("COMMIT_TEXT", mock_input_context->last_commit_text());
451 SCOPED_TRACE("sendKeyEvents test");
452 mock_input_context->Reset();
453 mock_candidate_window->Reset();
455 const char send_key_events_test_script[] =
456 "chrome.input.ime.sendKeyEvents({"
457 " contextID: engineBridge.getFocusedContextID().contextID,"
458 " keyData : [{"
459 " type : 'keydown',"
460 " requestId : '0',"
461 " key : 'z',"
462 " code : 'KeyZ',"
463 " },{"
464 " type : 'keyup',"
465 " requestId : '1',"
466 " key : 'z',"
467 " code : 'KeyZ',"
468 " }]"
469 "});";
471 ExtensionTestMessageListener keyevent_listener_down(
472 std::string("onKeyEvent:") + kExtensionID +
473 ":keydown:z:KeyZ:false:false:false:false",
474 false);
475 ExtensionTestMessageListener keyevent_listener_up(
476 std::string("onKeyEvent:") + kExtensionID +
477 ":keyup:z:KeyZ:false:false:false:false",
478 false);
480 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
481 send_key_events_test_script));
483 ASSERT_TRUE(keyevent_listener_down.WaitUntilSatisfied());
484 EXPECT_TRUE(keyevent_listener_down.was_satisfied());
485 ASSERT_TRUE(keyevent_listener_up.WaitUntilSatisfied());
486 EXPECT_TRUE(keyevent_listener_up.was_satisfied());
489 SCOPED_TRACE("sendKeyEvents test with keyCode");
490 mock_input_context->Reset();
491 mock_candidate_window->Reset();
493 const char send_key_events_test_script[] =
494 "chrome.input.ime.sendKeyEvents({"
495 " contextID: engineBridge.getFocusedContextID().contextID,"
496 " keyData : [{"
497 " type : 'keydown',"
498 " requestId : '2',"
499 " key : 'a',"
500 " code : 'KeyQ',"
501 " keyCode : 0x41,"
502 " },{"
503 " type : 'keyup',"
504 " requestId : '3',"
505 " key : 'a',"
506 " code : 'KeyQ',"
507 " keyCode : 0x41,"
508 " }]"
509 "});";
511 ExtensionTestMessageListener keyevent_listener_down(
512 std::string("onKeyEvent:") + kExtensionID +
513 ":keydown:a:KeyQ:false:false:false:false",
514 false);
515 ExtensionTestMessageListener keyevent_listener_up(
516 std::string("onKeyEvent:") + kExtensionID +
517 ":keyup:a:KeyQ:false:false:false:false",
518 false);
520 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
521 send_key_events_test_script));
523 ASSERT_TRUE(keyevent_listener_down.WaitUntilSatisfied());
524 EXPECT_TRUE(keyevent_listener_down.was_satisfied());
525 ASSERT_TRUE(keyevent_listener_up.WaitUntilSatisfied());
526 EXPECT_TRUE(keyevent_listener_up.was_satisfied());
529 SCOPED_TRACE("setComposition test");
530 mock_input_context->Reset();
531 mock_candidate_window->Reset();
533 const char set_composition_test_script[] =
534 "chrome.input.ime.setComposition({"
535 " contextID: engineBridge.getFocusedContextID().contextID,"
536 " text:'COMPOSITION_TEXT',"
537 " cursor:4,"
538 " segments : [{"
539 " start: 0,"
540 " end: 5,"
541 " style: 'underline'"
542 " },{"
543 " start: 6,"
544 " end: 10,"
545 " style: 'doubleUnderline'"
546 " }]"
547 "});";
549 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
550 set_composition_test_script));
551 EXPECT_EQ(1, mock_input_context->update_preedit_text_call_count());
553 EXPECT_EQ(4U,
554 mock_input_context->last_update_composition_arg().cursor_pos);
555 EXPECT_TRUE(mock_input_context->last_update_composition_arg().is_visible);
557 const CompositionText& composition_text =
558 mock_input_context->last_update_composition_arg().composition_text;
559 EXPECT_EQ(base::UTF8ToUTF16("COMPOSITION_TEXT"), composition_text.text());
560 const std::vector<CompositionText::UnderlineAttribute>& underlines =
561 composition_text.underline_attributes();
563 ASSERT_EQ(2U, underlines.size());
564 EXPECT_EQ(CompositionText::COMPOSITION_TEXT_UNDERLINE_SINGLE,
565 underlines[0].type);
566 EXPECT_EQ(0U, underlines[0].start_index);
567 EXPECT_EQ(5U, underlines[0].end_index);
569 EXPECT_EQ(CompositionText::COMPOSITION_TEXT_UNDERLINE_DOUBLE,
570 underlines[1].type);
571 EXPECT_EQ(6U, underlines[1].start_index);
572 EXPECT_EQ(10U, underlines[1].end_index);
575 SCOPED_TRACE("clearComposition test");
576 mock_input_context->Reset();
577 mock_candidate_window->Reset();
579 const char commite_text_test_script[] =
580 "chrome.input.ime.clearComposition({"
581 " contextID: engineBridge.getFocusedContextID().contextID,"
582 "});";
584 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
585 commite_text_test_script));
586 EXPECT_EQ(1, mock_input_context->update_preedit_text_call_count());
587 EXPECT_FALSE(
588 mock_input_context->last_update_composition_arg().is_visible);
589 const CompositionText& composition_text =
590 mock_input_context->last_update_composition_arg().composition_text;
591 EXPECT_TRUE(composition_text.text().empty());
594 SCOPED_TRACE("setCandidateWindowProperties:visibility test");
595 mock_input_context->Reset();
596 mock_candidate_window->Reset();
598 const char set_candidate_window_properties_test_script[] =
599 "chrome.input.ime.setCandidateWindowProperties({"
600 " engineID: engineBridge.getActiveEngineID(),"
601 " properties: {"
602 " visible: true,"
603 " }"
604 "});";
605 ASSERT_TRUE(content::ExecuteScript(
606 host->host_contents(),
607 set_candidate_window_properties_test_script));
608 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
609 EXPECT_TRUE(
610 mock_candidate_window->last_update_lookup_table_arg().is_visible);
613 SCOPED_TRACE("setCandidateWindowProperties:cursor_visibility test");
614 mock_input_context->Reset();
615 mock_candidate_window->Reset();
617 const char set_candidate_window_properties_test_script[] =
618 "chrome.input.ime.setCandidateWindowProperties({"
619 " engineID: engineBridge.getActiveEngineID(),"
620 " properties: {"
621 " cursorVisible: true,"
622 " }"
623 "});";
624 ASSERT_TRUE(content::ExecuteScript(
625 host->host_contents(),
626 set_candidate_window_properties_test_script));
627 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
629 // window visibility is kept as before.
630 EXPECT_TRUE(
631 mock_candidate_window->last_update_lookup_table_arg().is_visible);
633 const ui::CandidateWindow& table =
634 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
635 EXPECT_TRUE(table.is_cursor_visible());
638 SCOPED_TRACE("setCandidateWindowProperties:vertical test");
639 mock_input_context->Reset();
640 mock_candidate_window->Reset();
642 const char set_candidate_window_properties_test_script[] =
643 "chrome.input.ime.setCandidateWindowProperties({"
644 " engineID: engineBridge.getActiveEngineID(),"
645 " properties: {"
646 " vertical: true,"
647 " }"
648 "});";
649 ASSERT_TRUE(content::ExecuteScript(
650 host->host_contents(),
651 set_candidate_window_properties_test_script));
652 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
654 // window visibility is kept as before.
655 EXPECT_TRUE(
656 mock_candidate_window->last_update_lookup_table_arg().is_visible);
658 const ui::CandidateWindow& table =
659 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
661 // cursor visibility is kept as before.
662 EXPECT_TRUE(table.is_cursor_visible());
664 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
667 SCOPED_TRACE("setCandidateWindowProperties:pageSize test");
668 mock_input_context->Reset();
669 mock_candidate_window->Reset();
671 const char set_candidate_window_properties_test_script[] =
672 "chrome.input.ime.setCandidateWindowProperties({"
673 " engineID: engineBridge.getActiveEngineID(),"
674 " properties: {"
675 " pageSize: 7,"
676 " }"
677 "});";
678 ASSERT_TRUE(content::ExecuteScript(
679 host->host_contents(),
680 set_candidate_window_properties_test_script));
681 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
683 // window visibility is kept as before.
684 EXPECT_TRUE(
685 mock_candidate_window->last_update_lookup_table_arg().is_visible);
687 const ui::CandidateWindow& table =
688 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
690 // cursor visibility is kept as before.
691 EXPECT_TRUE(table.is_cursor_visible());
693 // oritantation is kept as before.
694 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
696 EXPECT_EQ(7U, table.page_size());
699 SCOPED_TRACE("setCandidateWindowProperties:auxTextVisibility test");
700 mock_input_context->Reset();
701 mock_candidate_window->Reset();
703 const char set_candidate_window_properties_test_script[] =
704 "chrome.input.ime.setCandidateWindowProperties({"
705 " engineID: engineBridge.getActiveEngineID(),"
706 " properties: {"
707 " auxiliaryTextVisible: true"
708 " }"
709 "});";
710 ASSERT_TRUE(content::ExecuteScript(
711 host->host_contents(),
712 set_candidate_window_properties_test_script));
713 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
715 const ui::CandidateWindow& table =
716 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
717 EXPECT_TRUE(table.is_auxiliary_text_visible());
720 SCOPED_TRACE("setCandidateWindowProperties:auxText test");
721 mock_input_context->Reset();
722 mock_candidate_window->Reset();
724 const char set_candidate_window_properties_test_script[] =
725 "chrome.input.ime.setCandidateWindowProperties({"
726 " engineID: engineBridge.getActiveEngineID(),"
727 " properties: {"
728 " auxiliaryText: 'AUXILIARY_TEXT'"
729 " }"
730 "});";
731 ASSERT_TRUE(content::ExecuteScript(
732 host->host_contents(),
733 set_candidate_window_properties_test_script));
734 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
736 // aux text visibility is kept as before.
737 const ui::CandidateWindow& table =
738 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
739 EXPECT_TRUE(table.is_auxiliary_text_visible());
740 EXPECT_EQ("AUXILIARY_TEXT", table.auxiliary_text());
743 SCOPED_TRACE("setCandidates test");
744 mock_input_context->Reset();
745 mock_candidate_window->Reset();
747 const char set_candidates_test_script[] =
748 "chrome.input.ime.setCandidates({"
749 " contextID: engineBridge.getFocusedContextID().contextID,"
750 " candidates: [{"
751 " candidate: 'CANDIDATE_1',"
752 " id: 1,"
753 " },{"
754 " candidate: 'CANDIDATE_2',"
755 " id: 2,"
756 " label: 'LABEL_2',"
757 " },{"
758 " candidate: 'CANDIDATE_3',"
759 " id: 3,"
760 " label: 'LABEL_3',"
761 " annotation: 'ANNOTACTION_3'"
762 " },{"
763 " candidate: 'CANDIDATE_4',"
764 " id: 4,"
765 " label: 'LABEL_4',"
766 " annotation: 'ANNOTACTION_4',"
767 " usage: {"
768 " title: 'TITLE_4',"
769 " body: 'BODY_4'"
770 " }"
771 " }]"
772 "});";
773 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
774 set_candidates_test_script));
776 // window visibility is kept as before.
777 EXPECT_TRUE(
778 mock_candidate_window->last_update_lookup_table_arg().is_visible);
780 const ui::CandidateWindow& table =
781 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
783 // cursor visibility is kept as before.
784 EXPECT_TRUE(table.is_cursor_visible());
786 // oritantation is kept as before.
787 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
789 // page size is kept as before.
790 EXPECT_EQ(7U, table.page_size());
792 ASSERT_EQ(4U, table.candidates().size());
794 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_1"),
795 table.candidates().at(0).value);
797 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_2"),
798 table.candidates().at(1).value);
799 EXPECT_EQ(base::UTF8ToUTF16("LABEL_2"), table.candidates().at(1).label);
801 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_3"),
802 table.candidates().at(2).value);
803 EXPECT_EQ(base::UTF8ToUTF16("LABEL_3"), table.candidates().at(2).label);
804 EXPECT_EQ(base::UTF8ToUTF16("ANNOTACTION_3"),
805 table.candidates().at(2).annotation);
807 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_4"),
808 table.candidates().at(3).value);
809 EXPECT_EQ(base::UTF8ToUTF16("LABEL_4"), table.candidates().at(3).label);
810 EXPECT_EQ(base::UTF8ToUTF16("ANNOTACTION_4"),
811 table.candidates().at(3).annotation);
812 EXPECT_EQ(base::UTF8ToUTF16("TITLE_4"),
813 table.candidates().at(3).description_title);
814 EXPECT_EQ(base::UTF8ToUTF16("BODY_4"),
815 table.candidates().at(3).description_body);
818 SCOPED_TRACE("setCursorPosition test");
819 mock_input_context->Reset();
820 mock_candidate_window->Reset();
822 const char set_cursor_position_test_script[] =
823 "chrome.input.ime.setCursorPosition({"
824 " contextID: engineBridge.getFocusedContextID().contextID,"
825 " candidateID: 2"
826 "});";
827 ASSERT_TRUE(content::ExecuteScript(
828 host->host_contents(), set_cursor_position_test_script));
829 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
831 // window visibility is kept as before.
832 EXPECT_TRUE(
833 mock_candidate_window->last_update_lookup_table_arg().is_visible);
835 const ui::CandidateWindow& table =
836 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
838 // cursor visibility is kept as before.
839 EXPECT_TRUE(table.is_cursor_visible());
841 // oritantation is kept as before.
842 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
844 // page size is kept as before.
845 EXPECT_EQ(7U, table.page_size());
847 // candidates are same as before.
848 ASSERT_EQ(4U, table.candidates().size());
850 // Candidate ID == 2 is 1 in index.
851 EXPECT_EQ(1U, table.cursor_position());
854 SCOPED_TRACE("setMenuItem test");
855 mock_input_context->Reset();
856 mock_candidate_window->Reset();
858 const char set_menu_item_test_script[] =
859 "chrome.input.ime.setMenuItems({"
860 " engineID: engineBridge.getActiveEngineID(),"
861 " items: [{"
862 " id: 'ID0',"
863 " },{"
864 " id: 'ID1',"
865 " label: 'LABEL1',"
866 " },{"
867 " id: 'ID2',"
868 " label: 'LABEL2',"
869 " style: 'radio',"
870 " },{"
871 " id: 'ID3',"
872 " label: 'LABEL3',"
873 " style: 'check',"
874 " visible: true,"
875 " },{"
876 " id: 'ID4',"
877 " label: 'LABEL4',"
878 " style: 'separator',"
879 " visible: true,"
880 " checked: true"
881 " }]"
882 "});";
883 ASSERT_TRUE(content::ExecuteScript(
884 host->host_contents(), set_menu_item_test_script));
886 const ui::ime::InputMethodMenuItemList& props =
887 ui::ime::InputMethodMenuManager::GetInstance()->
888 GetCurrentInputMethodMenuItemList();
889 ASSERT_EQ(5U, props.size());
891 EXPECT_EQ("ID0", props[0].key);
892 EXPECT_EQ("ID1", props[1].key);
893 EXPECT_EQ("ID2", props[2].key);
894 EXPECT_EQ("ID3", props[3].key);
895 EXPECT_EQ("ID4", props[4].key);
897 EXPECT_EQ("LABEL1", props[1].label);
898 EXPECT_EQ("LABEL2", props[2].label);
899 EXPECT_EQ("LABEL3", props[3].label);
900 EXPECT_EQ("LABEL4", props[4].label);
902 EXPECT_TRUE(props[2].is_selection_item);
903 // TODO(nona): Add tests for style: ["toggle" and "separator"]
904 // and visible:, when implement them.
906 EXPECT_TRUE(props[4].is_selection_item_checked);
909 SCOPED_TRACE("deleteSurroundingText test");
910 mock_input_context->Reset();
911 mock_candidate_window->Reset();
913 const char delete_surrounding_text_test_script[] =
914 "chrome.input.ime.deleteSurroundingText({"
915 " engineID: engineBridge.getActiveEngineID(),"
916 " contextID: engineBridge.getFocusedContextID().contextID,"
917 " offset: 5,"
918 " length: 3"
919 "});";
920 ASSERT_TRUE(content::ExecuteScript(
921 host->host_contents(), delete_surrounding_text_test_script));
923 EXPECT_EQ(1, mock_input_context->delete_surrounding_text_call_count());
924 EXPECT_EQ(5, mock_input_context->last_delete_surrounding_text_arg().offset);
925 EXPECT_EQ(3U,
926 mock_input_context->last_delete_surrounding_text_arg().length);
929 SCOPED_TRACE("onFocus test");
930 mock_input_context->Reset();
931 mock_candidate_window->Reset();
934 ExtensionTestMessageListener focus_listener("onFocus:text", false);
935 IMEEngineHandlerInterface::InputContext context(
936 ui::TEXT_INPUT_TYPE_TEXT, ui::TEXT_INPUT_MODE_DEFAULT,
937 ui::TEXT_INPUT_FLAG_NONE);
938 engine_handler->FocusIn(context);
939 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
940 ASSERT_TRUE(focus_listener.was_satisfied());
943 ExtensionTestMessageListener focus_listener("onFocus:search", false);
944 IMEEngineHandlerInterface::InputContext context(
945 ui::TEXT_INPUT_TYPE_SEARCH, ui::TEXT_INPUT_MODE_DEFAULT,
946 ui::TEXT_INPUT_FLAG_NONE);
947 engine_handler->FocusIn(context);
948 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
949 ASSERT_TRUE(focus_listener.was_satisfied());
952 ExtensionTestMessageListener focus_listener("onFocus:tel", false);
953 IMEEngineHandlerInterface::InputContext context(
954 ui::TEXT_INPUT_TYPE_TELEPHONE, ui::TEXT_INPUT_MODE_DEFAULT,
955 ui::TEXT_INPUT_FLAG_NONE);
956 engine_handler->FocusIn(context);
957 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
958 ASSERT_TRUE(focus_listener.was_satisfied());
961 ExtensionTestMessageListener focus_listener("onFocus:url", false);
962 IMEEngineHandlerInterface::InputContext context(
963 ui::TEXT_INPUT_TYPE_URL, ui::TEXT_INPUT_MODE_DEFAULT,
964 ui::TEXT_INPUT_FLAG_NONE);
965 engine_handler->FocusIn(context);
966 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
967 ASSERT_TRUE(focus_listener.was_satisfied());
970 ExtensionTestMessageListener focus_listener("onFocus:email", false);
971 IMEEngineHandlerInterface::InputContext context(
972 ui::TEXT_INPUT_TYPE_EMAIL, ui::TEXT_INPUT_MODE_DEFAULT,
973 ui::TEXT_INPUT_FLAG_NONE);
974 engine_handler->FocusIn(context);
975 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
976 ASSERT_TRUE(focus_listener.was_satisfied());
979 ExtensionTestMessageListener focus_listener("onFocus:number", false);
980 IMEEngineHandlerInterface::InputContext context(
981 ui::TEXT_INPUT_TYPE_NUMBER, ui::TEXT_INPUT_MODE_DEFAULT,
982 ui::TEXT_INPUT_FLAG_NONE);
983 engine_handler->FocusIn(context);
984 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
985 ASSERT_TRUE(focus_listener.was_satisfied());
989 IMEBridge::Get()->SetInputContextHandler(NULL);
990 IMEBridge::Get()->SetCandidateWindowHandler(NULL);
993 } // namespace
994 } // namespace input_method
995 } // namespace chromeos