Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / chromeos / input_method / input_method_engine_browsertests.cc
blob548a45f7e0e956900a3351f99a10f45dd73a7729
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.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/dom3/dom_code.h"
26 #include "ui/events/keycodes/dom4/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 ASSERT_TRUE(surrounding_text_listener.WaitUntilSatisfied());
200 ASSERT_TRUE(surrounding_text_listener.was_satisfied());
202 // onMenuItemActivated should be fired if PropertyActivate is called.
203 ExtensionTestMessageListener property_listener("onMenuItemActivated", false);
204 engine_handler->PropertyActivate("property_name");
205 ASSERT_TRUE(property_listener.WaitUntilSatisfied());
206 ASSERT_TRUE(property_listener.was_satisfied());
208 // onReset should be fired if Reset is called.
209 ExtensionTestMessageListener reset_listener("onReset", false);
210 engine_handler->Reset();
211 ASSERT_TRUE(reset_listener.WaitUntilSatisfied());
212 ASSERT_TRUE(reset_listener.was_satisfied());
214 // onBlur should be fired if FocusOut is called.
215 ExtensionTestMessageListener blur_listener("onBlur", false);
216 engine_handler->FocusOut();
217 ASSERT_TRUE(blur_listener.WaitUntilSatisfied());
218 ASSERT_TRUE(blur_listener.was_satisfied());
220 // onDeactivated should be fired if Disable is called.
221 ExtensionTestMessageListener disabled_listener("onDeactivated", false);
222 engine_handler->Disable();
223 ASSERT_TRUE(disabled_listener.WaitUntilSatisfied());
224 ASSERT_TRUE(disabled_listener.was_satisfied());
226 IMEBridge::Get()->SetInputContextHandler(NULL);
227 IMEBridge::Get()->SetCandidateWindowHandler(NULL);
230 IN_PROC_BROWSER_TEST_P(InputMethodEngineBrowserTest,
231 APIArgumentTest) {
232 LoadTestInputMethod();
234 InputMethodManager::Get()->GetActiveIMEState()->ChangeInputMethod(
235 kAPIArgumentIMEID, false /* show_message */);
237 scoped_ptr<MockIMEInputContextHandler> mock_input_context(
238 new MockIMEInputContextHandler());
239 scoped_ptr<MockIMECandidateWindowHandler> mock_candidate_window(
240 new MockIMECandidateWindowHandler());
242 IMEBridge::Get()->SetInputContextHandler(mock_input_context.get());
243 IMEBridge::Get()->SetCandidateWindowHandler(mock_candidate_window.get());
245 IMEEngineHandlerInterface* engine_handler =
246 IMEBridge::Get()->GetCurrentEngineHandler();
247 ASSERT_TRUE(engine_handler);
249 extensions::ExtensionHost* host =
250 extensions::ProcessManager::Get(profile())
251 ->GetBackgroundHostForExtension(extension_->id());
252 ASSERT_TRUE(host);
254 engine_handler->Enable("APIArgumentIME");
255 IMEEngineHandlerInterface::InputContext context(ui::TEXT_INPUT_TYPE_TEXT,
256 ui::TEXT_INPUT_MODE_DEFAULT,
257 ui::TEXT_INPUT_FLAG_NONE);
258 engine_handler->FocusIn(context);
261 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:No, Caps:No");
262 KeyEventDoneCallback callback(false);
263 const std::string expected_value =
264 "onKeyEvent::keydown:a:KeyA:false:false:false:false";
265 ExtensionTestMessageListener keyevent_listener(expected_value, false);
267 ui::KeyEvent key_event(
268 ui::ET_KEY_PRESSED, ui::VKEY_A, ui::DomCode::KEY_A, ui::EF_NONE);
269 engine_handler->ProcessKeyEvent(key_event,
270 base::Bind(&KeyEventDoneCallback::Run,
271 base::Unretained(&callback)));
272 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
273 EXPECT_TRUE(keyevent_listener.was_satisfied());
274 callback.WaitUntilCalled();
277 SCOPED_TRACE("KeyDown, Ctrl:Yes, alt:No, Shift:No, Caps:No");
278 KeyEventDoneCallback callback(false);
279 const std::string expected_value =
280 "onKeyEvent::keydown:a:KeyA:true:false:false:false";
281 ExtensionTestMessageListener keyevent_listener(expected_value, false);
283 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
284 ui::VKEY_A,
285 ui::DomCode::KEY_A,
286 ui::EF_CONTROL_DOWN);
287 engine_handler->ProcessKeyEvent(key_event,
288 base::Bind(&KeyEventDoneCallback::Run,
289 base::Unretained(&callback)));
290 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
291 EXPECT_TRUE(keyevent_listener.was_satisfied());
292 callback.WaitUntilCalled();
295 SCOPED_TRACE("KeyDown, Ctrl:No, alt:Yes, Shift:No, Caps:No");
296 KeyEventDoneCallback callback(false);
297 const std::string expected_value =
298 "onKeyEvent::keydown:a:KeyA:false:true:false:false";
299 ExtensionTestMessageListener keyevent_listener(expected_value, false);
301 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
302 ui::VKEY_A,
303 ui::DomCode::KEY_A,
304 ui::EF_ALT_DOWN);
305 engine_handler->ProcessKeyEvent(key_event,
306 base::Bind(&KeyEventDoneCallback::Run,
307 base::Unretained(&callback)));
308 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
309 EXPECT_TRUE(keyevent_listener.was_satisfied());
310 callback.WaitUntilCalled();
313 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:Yes, Caps:No");
314 KeyEventDoneCallback callback(false);
315 const std::string expected_value =
316 "onKeyEvent::keydown:A:KeyA:false:false:true:false";
317 ExtensionTestMessageListener keyevent_listener(expected_value, false);
319 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
320 ui::VKEY_A,
321 ui::DomCode::KEY_A,
322 ui::EF_SHIFT_DOWN);
323 engine_handler->ProcessKeyEvent(key_event,
324 base::Bind(&KeyEventDoneCallback::Run,
325 base::Unretained(&callback)));
326 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
327 EXPECT_TRUE(keyevent_listener.was_satisfied());
328 callback.WaitUntilCalled();
331 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:No, Caps:Yes");
332 KeyEventDoneCallback callback(false);
333 const std::string expected_value =
334 "onKeyEvent::keydown:A:KeyA:false:false:false:true";
335 ExtensionTestMessageListener keyevent_listener(expected_value, false);
337 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
338 ui::VKEY_A,
339 ui::DomCode::KEY_A,
340 ui::EF_CAPS_LOCK_DOWN);
341 engine_handler->ProcessKeyEvent(key_event,
342 base::Bind(&KeyEventDoneCallback::Run,
343 base::Unretained(&callback)));
344 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
345 EXPECT_TRUE(keyevent_listener.was_satisfied());
346 callback.WaitUntilCalled();
349 SCOPED_TRACE("KeyDown, Ctrl:Yes, alt:Yes, Shift:No, Caps:No");
350 KeyEventDoneCallback callback(false);
351 const std::string expected_value =
352 "onKeyEvent::keydown:a:KeyA:true:true:false:false";
353 ExtensionTestMessageListener keyevent_listener(expected_value, false);
355 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
356 ui::VKEY_A,
357 ui::DomCode::KEY_A,
358 ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN);
359 engine_handler->ProcessKeyEvent(key_event,
360 base::Bind(&KeyEventDoneCallback::Run,
361 base::Unretained(&callback)));
362 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
363 EXPECT_TRUE(keyevent_listener.was_satisfied());
364 callback.WaitUntilCalled();
367 SCOPED_TRACE("KeyDown, Ctrl:No, alt:No, Shift:Yes, Caps:Yes");
368 KeyEventDoneCallback callback(false);
369 const std::string expected_value =
370 "onKeyEvent::keydown:a:KeyA:false:false:true:true";
371 ExtensionTestMessageListener keyevent_listener(expected_value, false);
373 ui::KeyEvent key_event(ui::ET_KEY_PRESSED,
374 ui::VKEY_A,
375 ui::DomCode::KEY_A,
376 ui::EF_SHIFT_DOWN | ui::EF_CAPS_LOCK_DOWN);
377 engine_handler->ProcessKeyEvent(key_event,
378 base::Bind(&KeyEventDoneCallback::Run,
379 base::Unretained(&callback)));
380 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
381 EXPECT_TRUE(keyevent_listener.was_satisfied());
382 callback.WaitUntilCalled();
384 // Media keys cases.
385 const struct {
386 ui::KeyboardCode keycode;
387 const char* code;
388 const char* key;
389 } kMediaKeyCases[] = {
390 { ui::VKEY_BROWSER_BACK, "BrowserBack", "HistoryBack" },
391 { ui::VKEY_BROWSER_FORWARD, "BrowserForward", "HistoryForward" },
392 { ui::VKEY_BROWSER_REFRESH, "BrowserRefresh", "BrowserRefresh" },
393 { ui::VKEY_MEDIA_LAUNCH_APP2, "ChromeOSFullscreen", "ChromeOSFullscreen" },
394 { ui::VKEY_MEDIA_LAUNCH_APP1,
395 "ChromeOSSwitchWindow", "ChromeOSSwitchWindow" },
396 { ui::VKEY_BRIGHTNESS_DOWN, "BrightnessDown", "BrightnessDown" },
397 { ui::VKEY_BRIGHTNESS_UP, "BrightnessUp", "BrightnessUp" },
398 { ui::VKEY_VOLUME_MUTE, "VolumeMute", "AudioVolumeMute" },
399 { ui::VKEY_VOLUME_DOWN, "VolumeDown", "AudioVolumeDown" },
400 { ui::VKEY_VOLUME_UP, "VolumeUp", "AudioVolumeUp" },
401 { ui::VKEY_F1, "F1", "HistoryBack" },
402 { ui::VKEY_F2, "F2", "HistoryForward" },
403 { ui::VKEY_F3, "F3", "BrowserRefresh" },
404 { ui::VKEY_F4, "F4", "ChromeOSFullscreen" },
405 { ui::VKEY_F5, "F5", "ChromeOSSwitchWindow" },
406 { ui::VKEY_F6, "F6", "BrightnessDown" },
407 { ui::VKEY_F7, "F7", "BrightnessUp" },
408 { ui::VKEY_F8, "F8", "AudioVolumeMute" },
409 { ui::VKEY_F9, "F9", "AudioVolumeDown" },
410 { ui::VKEY_F10, "F10", "AudioVolumeUp" },
412 for (size_t i = 0; i < arraysize(kMediaKeyCases); ++i) {
413 SCOPED_TRACE(std::string("KeyDown, ") + kMediaKeyCases[i].code);
414 KeyEventDoneCallback callback(false);
415 const std::string expected_value =
416 base::StringPrintf("onKeyEvent::keydown:%s:%s:false:false:false:false",
417 kMediaKeyCases[i].key, kMediaKeyCases[i].code);
418 ExtensionTestMessageListener keyevent_listener(expected_value, false);
420 ui::KeyEvent key_event(
421 ui::ET_KEY_PRESSED,
422 kMediaKeyCases[i].keycode,
423 ui::KeycodeConverter::CodeStringToDomCode(kMediaKeyCases[i].code),
424 ui::EF_NONE);
425 engine_handler->ProcessKeyEvent(key_event,
426 base::Bind(&KeyEventDoneCallback::Run,
427 base::Unretained(&callback)));
428 ASSERT_TRUE(keyevent_listener.WaitUntilSatisfied());
429 EXPECT_TRUE(keyevent_listener.was_satisfied());
430 callback.WaitUntilCalled();
432 // TODO(nona): Add browser tests for other API as well.
434 SCOPED_TRACE("commitText test");
435 mock_input_context->Reset();
436 mock_candidate_window->Reset();
438 const char commit_text_test_script[] =
439 "chrome.input.ime.commitText({"
440 " contextID: engineBridge.getFocusedContextID().contextID,"
441 " text:'COMMIT_TEXT'"
442 "});";
444 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
445 commit_text_test_script));
446 EXPECT_EQ(1, mock_input_context->commit_text_call_count());
447 EXPECT_EQ("COMMIT_TEXT", mock_input_context->last_commit_text());
450 SCOPED_TRACE("sendKeyEvents test");
451 mock_input_context->Reset();
452 mock_candidate_window->Reset();
454 const char send_key_events_test_script[] =
455 "chrome.input.ime.sendKeyEvents({"
456 " contextID: engineBridge.getFocusedContextID().contextID,"
457 " keyData : [{"
458 " type : 'keydown',"
459 " requestId : '0',"
460 " key : 'z',"
461 " code : 'KeyZ',"
462 " },{"
463 " type : 'keyup',"
464 " requestId : '1',"
465 " key : 'z',"
466 " code : 'KeyZ',"
467 " }]"
468 "});";
470 ExtensionTestMessageListener keyevent_listener_down(
471 std::string("onKeyEvent:") + kExtensionID +
472 ":keydown:z:KeyZ:false:false:false:false",
473 false);
474 ExtensionTestMessageListener keyevent_listener_up(
475 std::string("onKeyEvent:") + kExtensionID +
476 ":keyup:z:KeyZ:false:false:false:false",
477 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("sendKeyEvents test with keyCode");
489 mock_input_context->Reset();
490 mock_candidate_window->Reset();
492 const char send_key_events_test_script[] =
493 "chrome.input.ime.sendKeyEvents({"
494 " contextID: engineBridge.getFocusedContextID().contextID,"
495 " keyData : [{"
496 " type : 'keydown',"
497 " requestId : '2',"
498 " key : 'a',"
499 " code : 'KeyQ',"
500 " keyCode : 0x41,"
501 " },{"
502 " type : 'keyup',"
503 " requestId : '3',"
504 " key : 'a',"
505 " code : 'KeyQ',"
506 " keyCode : 0x41,"
507 " }]"
508 "});";
510 ExtensionTestMessageListener keyevent_listener_down(
511 std::string("onKeyEvent:") + kExtensionID +
512 ":keydown:a:KeyQ:false:false:false:false",
513 false);
514 ExtensionTestMessageListener keyevent_listener_up(
515 std::string("onKeyEvent:") + kExtensionID +
516 ":keyup:a:KeyQ:false:false:false:false",
517 false);
519 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
520 send_key_events_test_script));
522 ASSERT_TRUE(keyevent_listener_down.WaitUntilSatisfied());
523 EXPECT_TRUE(keyevent_listener_down.was_satisfied());
524 ASSERT_TRUE(keyevent_listener_up.WaitUntilSatisfied());
525 EXPECT_TRUE(keyevent_listener_up.was_satisfied());
528 SCOPED_TRACE("setComposition test");
529 mock_input_context->Reset();
530 mock_candidate_window->Reset();
532 const char set_composition_test_script[] =
533 "chrome.input.ime.setComposition({"
534 " contextID: engineBridge.getFocusedContextID().contextID,"
535 " text:'COMPOSITION_TEXT',"
536 " cursor:4,"
537 " segments : [{"
538 " start: 0,"
539 " end: 5,"
540 " style: 'underline'"
541 " },{"
542 " start: 6,"
543 " end: 10,"
544 " style: 'doubleUnderline'"
545 " }]"
546 "});";
548 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
549 set_composition_test_script));
550 EXPECT_EQ(1, mock_input_context->update_preedit_text_call_count());
552 EXPECT_EQ(4U,
553 mock_input_context->last_update_composition_arg().cursor_pos);
554 EXPECT_TRUE(mock_input_context->last_update_composition_arg().is_visible);
556 const CompositionText& composition_text =
557 mock_input_context->last_update_composition_arg().composition_text;
558 EXPECT_EQ(base::UTF8ToUTF16("COMPOSITION_TEXT"), composition_text.text());
559 const std::vector<CompositionText::UnderlineAttribute>& underlines =
560 composition_text.underline_attributes();
562 ASSERT_EQ(2U, underlines.size());
563 EXPECT_EQ(CompositionText::COMPOSITION_TEXT_UNDERLINE_SINGLE,
564 underlines[0].type);
565 EXPECT_EQ(0U, underlines[0].start_index);
566 EXPECT_EQ(5U, underlines[0].end_index);
568 EXPECT_EQ(CompositionText::COMPOSITION_TEXT_UNDERLINE_DOUBLE,
569 underlines[1].type);
570 EXPECT_EQ(6U, underlines[1].start_index);
571 EXPECT_EQ(10U, underlines[1].end_index);
574 SCOPED_TRACE("clearComposition test");
575 mock_input_context->Reset();
576 mock_candidate_window->Reset();
578 const char commite_text_test_script[] =
579 "chrome.input.ime.clearComposition({"
580 " contextID: engineBridge.getFocusedContextID().contextID,"
581 "});";
583 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
584 commite_text_test_script));
585 EXPECT_EQ(1, mock_input_context->update_preedit_text_call_count());
586 EXPECT_FALSE(
587 mock_input_context->last_update_composition_arg().is_visible);
588 const CompositionText& composition_text =
589 mock_input_context->last_update_composition_arg().composition_text;
590 EXPECT_TRUE(composition_text.text().empty());
593 SCOPED_TRACE("setCandidateWindowProperties:visibility test");
594 mock_input_context->Reset();
595 mock_candidate_window->Reset();
597 const char set_candidate_window_properties_test_script[] =
598 "chrome.input.ime.setCandidateWindowProperties({"
599 " engineID: engineBridge.getActiveEngineID(),"
600 " properties: {"
601 " visible: true,"
602 " }"
603 "});";
604 ASSERT_TRUE(content::ExecuteScript(
605 host->host_contents(),
606 set_candidate_window_properties_test_script));
607 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
608 EXPECT_TRUE(
609 mock_candidate_window->last_update_lookup_table_arg().is_visible);
612 SCOPED_TRACE("setCandidateWindowProperties:cursor_visibility test");
613 mock_input_context->Reset();
614 mock_candidate_window->Reset();
616 const char set_candidate_window_properties_test_script[] =
617 "chrome.input.ime.setCandidateWindowProperties({"
618 " engineID: engineBridge.getActiveEngineID(),"
619 " properties: {"
620 " cursorVisible: true,"
621 " }"
622 "});";
623 ASSERT_TRUE(content::ExecuteScript(
624 host->host_contents(),
625 set_candidate_window_properties_test_script));
626 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
628 // window visibility is kept as before.
629 EXPECT_TRUE(
630 mock_candidate_window->last_update_lookup_table_arg().is_visible);
632 const ui::CandidateWindow& table =
633 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
634 EXPECT_TRUE(table.is_cursor_visible());
637 SCOPED_TRACE("setCandidateWindowProperties:vertical test");
638 mock_input_context->Reset();
639 mock_candidate_window->Reset();
641 const char set_candidate_window_properties_test_script[] =
642 "chrome.input.ime.setCandidateWindowProperties({"
643 " engineID: engineBridge.getActiveEngineID(),"
644 " properties: {"
645 " vertical: true,"
646 " }"
647 "});";
648 ASSERT_TRUE(content::ExecuteScript(
649 host->host_contents(),
650 set_candidate_window_properties_test_script));
651 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
653 // window visibility is kept as before.
654 EXPECT_TRUE(
655 mock_candidate_window->last_update_lookup_table_arg().is_visible);
657 const ui::CandidateWindow& table =
658 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
660 // cursor visibility is kept as before.
661 EXPECT_TRUE(table.is_cursor_visible());
663 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
666 SCOPED_TRACE("setCandidateWindowProperties:pageSize test");
667 mock_input_context->Reset();
668 mock_candidate_window->Reset();
670 const char set_candidate_window_properties_test_script[] =
671 "chrome.input.ime.setCandidateWindowProperties({"
672 " engineID: engineBridge.getActiveEngineID(),"
673 " properties: {"
674 " pageSize: 7,"
675 " }"
676 "});";
677 ASSERT_TRUE(content::ExecuteScript(
678 host->host_contents(),
679 set_candidate_window_properties_test_script));
680 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
682 // window visibility is kept as before.
683 EXPECT_TRUE(
684 mock_candidate_window->last_update_lookup_table_arg().is_visible);
686 const ui::CandidateWindow& table =
687 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
689 // cursor visibility is kept as before.
690 EXPECT_TRUE(table.is_cursor_visible());
692 // oritantation is kept as before.
693 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
695 EXPECT_EQ(7U, table.page_size());
698 SCOPED_TRACE("setCandidateWindowProperties:auxTextVisibility test");
699 mock_input_context->Reset();
700 mock_candidate_window->Reset();
702 const char set_candidate_window_properties_test_script[] =
703 "chrome.input.ime.setCandidateWindowProperties({"
704 " engineID: engineBridge.getActiveEngineID(),"
705 " properties: {"
706 " auxiliaryTextVisible: true"
707 " }"
708 "});";
709 ASSERT_TRUE(content::ExecuteScript(
710 host->host_contents(),
711 set_candidate_window_properties_test_script));
712 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
714 const ui::CandidateWindow& table =
715 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
716 EXPECT_TRUE(table.is_auxiliary_text_visible());
719 SCOPED_TRACE("setCandidateWindowProperties:auxText test");
720 mock_input_context->Reset();
721 mock_candidate_window->Reset();
723 const char set_candidate_window_properties_test_script[] =
724 "chrome.input.ime.setCandidateWindowProperties({"
725 " engineID: engineBridge.getActiveEngineID(),"
726 " properties: {"
727 " auxiliaryText: 'AUXILIARY_TEXT'"
728 " }"
729 "});";
730 ASSERT_TRUE(content::ExecuteScript(
731 host->host_contents(),
732 set_candidate_window_properties_test_script));
733 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
735 // aux text visibility is kept as before.
736 const ui::CandidateWindow& table =
737 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
738 EXPECT_TRUE(table.is_auxiliary_text_visible());
739 EXPECT_EQ("AUXILIARY_TEXT", table.auxiliary_text());
742 SCOPED_TRACE("setCandidates test");
743 mock_input_context->Reset();
744 mock_candidate_window->Reset();
746 const char set_candidates_test_script[] =
747 "chrome.input.ime.setCandidates({"
748 " contextID: engineBridge.getFocusedContextID().contextID,"
749 " candidates: [{"
750 " candidate: 'CANDIDATE_1',"
751 " id: 1,"
752 " },{"
753 " candidate: 'CANDIDATE_2',"
754 " id: 2,"
755 " label: 'LABEL_2',"
756 " },{"
757 " candidate: 'CANDIDATE_3',"
758 " id: 3,"
759 " label: 'LABEL_3',"
760 " annotation: 'ANNOTACTION_3'"
761 " },{"
762 " candidate: 'CANDIDATE_4',"
763 " id: 4,"
764 " label: 'LABEL_4',"
765 " annotation: 'ANNOTACTION_4',"
766 " usage: {"
767 " title: 'TITLE_4',"
768 " body: 'BODY_4'"
769 " }"
770 " }]"
771 "});";
772 ASSERT_TRUE(content::ExecuteScript(host->host_contents(),
773 set_candidates_test_script));
775 // window visibility is kept as before.
776 EXPECT_TRUE(
777 mock_candidate_window->last_update_lookup_table_arg().is_visible);
779 const ui::CandidateWindow& table =
780 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
782 // cursor visibility is kept as before.
783 EXPECT_TRUE(table.is_cursor_visible());
785 // oritantation is kept as before.
786 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
788 // page size is kept as before.
789 EXPECT_EQ(7U, table.page_size());
791 ASSERT_EQ(4U, table.candidates().size());
793 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_1"),
794 table.candidates().at(0).value);
796 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_2"),
797 table.candidates().at(1).value);
798 EXPECT_EQ(base::UTF8ToUTF16("LABEL_2"), table.candidates().at(1).label);
800 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_3"),
801 table.candidates().at(2).value);
802 EXPECT_EQ(base::UTF8ToUTF16("LABEL_3"), table.candidates().at(2).label);
803 EXPECT_EQ(base::UTF8ToUTF16("ANNOTACTION_3"),
804 table.candidates().at(2).annotation);
806 EXPECT_EQ(base::UTF8ToUTF16("CANDIDATE_4"),
807 table.candidates().at(3).value);
808 EXPECT_EQ(base::UTF8ToUTF16("LABEL_4"), table.candidates().at(3).label);
809 EXPECT_EQ(base::UTF8ToUTF16("ANNOTACTION_4"),
810 table.candidates().at(3).annotation);
811 EXPECT_EQ(base::UTF8ToUTF16("TITLE_4"),
812 table.candidates().at(3).description_title);
813 EXPECT_EQ(base::UTF8ToUTF16("BODY_4"),
814 table.candidates().at(3).description_body);
817 SCOPED_TRACE("setCursorPosition test");
818 mock_input_context->Reset();
819 mock_candidate_window->Reset();
821 const char set_cursor_position_test_script[] =
822 "chrome.input.ime.setCursorPosition({"
823 " contextID: engineBridge.getFocusedContextID().contextID,"
824 " candidateID: 2"
825 "});";
826 ASSERT_TRUE(content::ExecuteScript(
827 host->host_contents(), set_cursor_position_test_script));
828 EXPECT_EQ(1, mock_candidate_window->update_lookup_table_call_count());
830 // window visibility is kept as before.
831 EXPECT_TRUE(
832 mock_candidate_window->last_update_lookup_table_arg().is_visible);
834 const ui::CandidateWindow& table =
835 mock_candidate_window->last_update_lookup_table_arg().lookup_table;
837 // cursor visibility is kept as before.
838 EXPECT_TRUE(table.is_cursor_visible());
840 // oritantation is kept as before.
841 EXPECT_EQ(ui::CandidateWindow::VERTICAL, table.orientation());
843 // page size is kept as before.
844 EXPECT_EQ(7U, table.page_size());
846 // candidates are same as before.
847 ASSERT_EQ(4U, table.candidates().size());
849 // Candidate ID == 2 is 1 in index.
850 EXPECT_EQ(1U, table.cursor_position());
853 SCOPED_TRACE("setMenuItem test");
854 mock_input_context->Reset();
855 mock_candidate_window->Reset();
857 const char set_menu_item_test_script[] =
858 "chrome.input.ime.setMenuItems({"
859 " engineID: engineBridge.getActiveEngineID(),"
860 " items: [{"
861 " id: 'ID0',"
862 " },{"
863 " id: 'ID1',"
864 " label: 'LABEL1',"
865 " },{"
866 " id: 'ID2',"
867 " label: 'LABEL2',"
868 " style: 'radio',"
869 " },{"
870 " id: 'ID3',"
871 " label: 'LABEL3',"
872 " style: 'check',"
873 " visible: true,"
874 " },{"
875 " id: 'ID4',"
876 " label: 'LABEL4',"
877 " style: 'separator',"
878 " visible: true,"
879 " checked: true"
880 " }]"
881 "});";
882 ASSERT_TRUE(content::ExecuteScript(
883 host->host_contents(), set_menu_item_test_script));
885 const ui::ime::InputMethodMenuItemList& props =
886 ui::ime::InputMethodMenuManager::GetInstance()->
887 GetCurrentInputMethodMenuItemList();
888 ASSERT_EQ(5U, props.size());
890 EXPECT_EQ("ID0", props[0].key);
891 EXPECT_EQ("ID1", props[1].key);
892 EXPECT_EQ("ID2", props[2].key);
893 EXPECT_EQ("ID3", props[3].key);
894 EXPECT_EQ("ID4", props[4].key);
896 EXPECT_EQ("LABEL1", props[1].label);
897 EXPECT_EQ("LABEL2", props[2].label);
898 EXPECT_EQ("LABEL3", props[3].label);
899 EXPECT_EQ("LABEL4", props[4].label);
901 EXPECT_TRUE(props[2].is_selection_item);
902 // TODO(nona): Add tests for style: ["toggle" and "separator"]
903 // and visible:, when implement them.
905 EXPECT_TRUE(props[4].is_selection_item_checked);
908 SCOPED_TRACE("deleteSurroundingText test");
909 mock_input_context->Reset();
910 mock_candidate_window->Reset();
912 const char delete_surrounding_text_test_script[] =
913 "chrome.input.ime.deleteSurroundingText({"
914 " engineID: engineBridge.getActiveEngineID(),"
915 " contextID: engineBridge.getFocusedContextID().contextID,"
916 " offset: 5,"
917 " length: 3"
918 "});";
919 ASSERT_TRUE(content::ExecuteScript(
920 host->host_contents(), delete_surrounding_text_test_script));
922 EXPECT_EQ(1, mock_input_context->delete_surrounding_text_call_count());
923 EXPECT_EQ(5, mock_input_context->last_delete_surrounding_text_arg().offset);
924 EXPECT_EQ(3U,
925 mock_input_context->last_delete_surrounding_text_arg().length);
928 SCOPED_TRACE("onFocus test");
929 mock_input_context->Reset();
930 mock_candidate_window->Reset();
933 ExtensionTestMessageListener focus_listener("onFocus:text", false);
934 IMEEngineHandlerInterface::InputContext context(
935 ui::TEXT_INPUT_TYPE_TEXT, ui::TEXT_INPUT_MODE_DEFAULT,
936 ui::TEXT_INPUT_FLAG_NONE);
937 engine_handler->FocusIn(context);
938 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
939 ASSERT_TRUE(focus_listener.was_satisfied());
942 ExtensionTestMessageListener focus_listener("onFocus:search", false);
943 IMEEngineHandlerInterface::InputContext context(
944 ui::TEXT_INPUT_TYPE_SEARCH, ui::TEXT_INPUT_MODE_DEFAULT,
945 ui::TEXT_INPUT_FLAG_NONE);
946 engine_handler->FocusIn(context);
947 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
948 ASSERT_TRUE(focus_listener.was_satisfied());
951 ExtensionTestMessageListener focus_listener("onFocus:tel", false);
952 IMEEngineHandlerInterface::InputContext context(
953 ui::TEXT_INPUT_TYPE_TELEPHONE, ui::TEXT_INPUT_MODE_DEFAULT,
954 ui::TEXT_INPUT_FLAG_NONE);
955 engine_handler->FocusIn(context);
956 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
957 ASSERT_TRUE(focus_listener.was_satisfied());
960 ExtensionTestMessageListener focus_listener("onFocus:url", false);
961 IMEEngineHandlerInterface::InputContext context(
962 ui::TEXT_INPUT_TYPE_URL, ui::TEXT_INPUT_MODE_DEFAULT,
963 ui::TEXT_INPUT_FLAG_NONE);
964 engine_handler->FocusIn(context);
965 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
966 ASSERT_TRUE(focus_listener.was_satisfied());
969 ExtensionTestMessageListener focus_listener("onFocus:email", false);
970 IMEEngineHandlerInterface::InputContext context(
971 ui::TEXT_INPUT_TYPE_EMAIL, ui::TEXT_INPUT_MODE_DEFAULT,
972 ui::TEXT_INPUT_FLAG_NONE);
973 engine_handler->FocusIn(context);
974 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
975 ASSERT_TRUE(focus_listener.was_satisfied());
978 ExtensionTestMessageListener focus_listener("onFocus:number", false);
979 IMEEngineHandlerInterface::InputContext context(
980 ui::TEXT_INPUT_TYPE_NUMBER, ui::TEXT_INPUT_MODE_DEFAULT,
981 ui::TEXT_INPUT_FLAG_NONE);
982 engine_handler->FocusIn(context);
983 ASSERT_TRUE(focus_listener.WaitUntilSatisfied());
984 ASSERT_TRUE(focus_listener.was_satisfied());
988 IMEBridge::Get()->SetInputContextHandler(NULL);
989 IMEBridge::Get()->SetCandidateWindowHandler(NULL);
992 } // namespace
993 } // namespace input_method
994 } // namespace chromeos