Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Side by Side Diff: content/public/android/javatests/src/org/chromium/content/browser/input/ImeTest.java

Issue 373523002: Send correct key-codes when doing composition events instead of always 0. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address review comments Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.content.browser.input; 5 package org.chromium.content.browser.input;
6 6
7 import android.app.Activity; 7 import android.app.Activity;
8 import android.content.ClipData; 8 import android.content.ClipData;
9 import android.content.ClipboardManager; 9 import android.content.ClipboardManager;
10 import android.content.Context; 10 import android.content.Context;
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 257
258 finishComposingText(mConnection); 258 finishComposingText(mConnection);
259 waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 5, "hllo ", 1 , 1, -1, -1); 259 waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 5, "hllo ", 1 , 1, -1, -1);
260 260
261 commitText(mConnection, "\n", 1); 261 commitText(mConnection, "\n", 1);
262 waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 6, "h\nllo ", 2, 2, -1, -1); 262 waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 6, "h\nllo ", 2, 2, -1, -1);
263 } 263 }
264 264
265 @SmallTest 265 @SmallTest
266 @Feature({"TextInput", "Main"}) 266 @Feature({"TextInput", "Main"})
267 public void testGuessedKeycodeFromTyping() throws Throwable {
268 assertEquals(0, ImeAdapter.getTypedKeycodeGuess(null, ""));
269 assertEquals(KeyEvent.KEYCODE_X, ImeAdapter.getTypedKeycodeGuess(null, " x"));
270 assertEquals(0, ImeAdapter.getTypedKeycodeGuess(null, "xyz"));
271
272 assertEquals(0, ImeAdapter.getTypedKeycodeGuess("abc", "abc"));
273 assertEquals(KeyEvent.KEYCODE_DEL, ImeAdapter.getTypedKeycodeGuess("abc" , ""));
274
275 assertEquals(KeyEvent.KEYCODE_H, ImeAdapter.getTypedKeycodeGuess("", "h" ));
276 assertEquals(KeyEvent.KEYCODE_DEL, ImeAdapter.getTypedKeycodeGuess("h", ""));
277 assertEquals(KeyEvent.KEYCODE_E, ImeAdapter.getTypedKeycodeGuess("h", "h e"));
278 assertEquals(KeyEvent.KEYCODE_L, ImeAdapter.getTypedKeycodeGuess("he", " hel"));
279 assertEquals(KeyEvent.KEYCODE_O, ImeAdapter.getTypedKeycodeGuess("hel", "helo"));
280 assertEquals(KeyEvent.KEYCODE_DEL, ImeAdapter.getTypedKeycodeGuess("helo ", "hel"));
281 assertEquals(KeyEvent.KEYCODE_L, ImeAdapter.getTypedKeycodeGuess("hel", "hell"));
282 assertEquals(KeyEvent.KEYCODE_L, ImeAdapter.getTypedKeycodeGuess("hell", "helll"));
283 assertEquals(KeyEvent.KEYCODE_DEL, ImeAdapter.getTypedKeycodeGuess("hell l", "hell"));
284 assertEquals(KeyEvent.KEYCODE_O, ImeAdapter.getTypedKeycodeGuess("hell", "hello"));
285
286 assertEquals(KeyEvent.KEYCODE_X, ImeAdapter.getTypedKeycodeGuess("xxx", "xxxx"));
287 assertEquals(KeyEvent.KEYCODE_X, ImeAdapter.getTypedKeycodeGuess("xxx", "xxxxx"));
288 assertEquals(KeyEvent.KEYCODE_DEL, ImeAdapter.getTypedKeycodeGuess("xxx" , "xx"));
289 assertEquals(KeyEvent.KEYCODE_DEL, ImeAdapter.getTypedKeycodeGuess("xxx" , "x"));
290
291 assertEquals(KeyEvent.KEYCODE_Y, ImeAdapter.getTypedKeycodeGuess("xxx", "xxxy"));
292 assertEquals(KeyEvent.KEYCODE_Y, ImeAdapter.getTypedKeycodeGuess("xxx", "xxxxy"));
293 assertEquals(0, ImeAdapter.getTypedKeycodeGuess("xxx", "xy"));
294 assertEquals(0, ImeAdapter.getTypedKeycodeGuess("xxx", "y"));
295
296 assertEquals(0, ImeAdapter.getTypedKeycodeGuess("foo", "bar"));
297 assertEquals(0, ImeAdapter.getTypedKeycodeGuess("foo", "bars"));
298 assertEquals(0, ImeAdapter.getTypedKeycodeGuess("foo", "ba"));
299 }
300
301 @SmallTest
302 @Feature({"TextInput", "Main"})
303 public void testKeyCodesWhileComposingText() throws Throwable {
304 DOMUtils.focusNode(mContentViewCore, "textarea");
305 assertWaitForKeyboardStatus(true);
306
307 // The calls below are a reflection of what the stock Google Keyboard (A ndroid 4.4) sends
308 // when the noted key is touched on screen. Exercise care when altering to make sure
309 // that the test reflects reality. If this test breaks, it's possible t hat code has
310 // changed and different calls need to be made instead.
311 mConnection = (TestAdapterInputConnection) getAdapterInputConnection();
312 waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 0, "", 0, 0, -1, -1);
313
314 // H
315 expectUpdateStateCall(mConnection);
316 setComposingText(mConnection, "h", 1);
317 assertEquals(KeyEvent.KEYCODE_H, mImeAdapter.mLastSyntheticKeyCode);
318 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
319 assertUpdateStateCall(mConnection, 1000);
320 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
321
322 // O
323 expectUpdateStateCall(mConnection);
324 setComposingText(mConnection, "ho", 1);
325 assertEquals(KeyEvent.KEYCODE_O, mImeAdapter.mLastSyntheticKeyCode);
326 assertEquals("ho", mConnection.getTextBeforeCursor(9, 0));
327 assertUpdateStateCall(mConnection, 1000);
328 assertEquals("ho", mConnection.getTextBeforeCursor(9, 0));
329
330 // DEL
331 expectUpdateStateCall(mConnection);
332 setComposingText(mConnection, "h", 1);
333 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
334 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
335 assertUpdateStateCall(mConnection, 1000);
336 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
337 setComposingRegion(mConnection, 0, 1); // DEL calls cancelComposition() then restarts
338
339 // I
340 setComposingText(mConnection, "hi", 1);
341 assertEquals(KeyEvent.KEYCODE_I, mImeAdapter.mLastSyntheticKeyCode);
342 assertEquals("hi", mConnection.getTextBeforeCursor(9, 0));
343
344 // SPACE
345 commitText(mConnection, "hi", 1);
346 assertEquals(0, mImeAdapter.mLastSyntheticKeyCode);
347 commitText(mConnection, " ", 1);
348 assertEquals(KeyEvent.KEYCODE_SPACE, mImeAdapter.mLastSyntheticKeyCode);
349 assertEquals("hi ", mConnection.getTextBeforeCursor(9, 0));
350
351 // DEL
352 deleteSurroundingText(mConnection, 1, 0);
353 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
354 setComposingRegion(mConnection, 0, 2);
355 assertEquals("hi", mConnection.getTextBeforeCursor(9, 0));
356
357 // DEL
358 setComposingText(mConnection, "h", 1);
359 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
360 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
361
362 // DEL
363 commitText(mConnection, "", 1);
364 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
365 assertEquals("", mConnection.getTextBeforeCursor(9, 0));
366
367 // DEL (on empty input)
368 deleteSurroundingText(mConnection, 1, 0); // BS on empty still sends 1, 0
369 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
370 assertEquals("", mConnection.getTextBeforeCursor(9, 0));
371 }
372
373 @SmallTest
374 @Feature({"TextInput", "Main"})
375 public void testKeyCodesWhileTypingText() throws Throwable {
376 DOMUtils.focusNode(mContentViewCore, "textarea");
377 assertWaitForKeyboardStatus(true);
378
379 // The calls below are a reflection of what the Hacker's Keyboard sends when the noted
380 // key is touched on screen. Exercise care when altering to make sure t hat the test
381 // reflects reality.
382 mConnection = (TestAdapterInputConnection) getAdapterInputConnection();
383 waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 0, "", 0, 0, -1, -1);
384
385 // H
386 expectUpdateStateCall(mConnection);
387 commitText(mConnection, "h", 1);
388 assertEquals(KeyEvent.KEYCODE_H, mImeAdapter.mLastSyntheticKeyCode);
389 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
390 assertUpdateStateCall(mConnection, 1000);
391 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
392
393 // O
394 expectUpdateStateCall(mConnection);
395 commitText(mConnection, "o", 1);
396 assertEquals(KeyEvent.KEYCODE_O, mImeAdapter.mLastSyntheticKeyCode);
397 assertEquals("ho", mConnection.getTextBeforeCursor(9, 0));
398 assertUpdateStateCall(mConnection, 1000);
399 assertEquals("ho", mConnection.getTextBeforeCursor(9, 0));
400
401 // DEL
402 expectUpdateStateCall(mConnection);
403 deleteSurroundingText(mConnection, 1, 0);
404 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
405 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
406 assertUpdateStateCall(mConnection, 1000);
407 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
408
409 // I
410 expectUpdateStateCall(mConnection);
411 commitText(mConnection, "i", 1);
412 assertEquals(KeyEvent.KEYCODE_I, mImeAdapter.mLastSyntheticKeyCode);
413 assertEquals("hi", mConnection.getTextBeforeCursor(9, 0));
414 assertUpdateStateCall(mConnection, 1000);
415 assertEquals("hi", mConnection.getTextBeforeCursor(9, 0));
416
417 // SPACE
418 expectUpdateStateCall(mConnection);
419 commitText(mConnection, " ", 1);
420 assertEquals(KeyEvent.KEYCODE_SPACE, mImeAdapter.mLastSyntheticKeyCode);
421 assertEquals("hi ", mConnection.getTextBeforeCursor(9, 0));
422 assertUpdateStateCall(mConnection, 1000);
423 assertEquals("hi ", mConnection.getTextBeforeCursor(9, 0));
424
425 // DEL
426 expectUpdateStateCall(mConnection);
427 deleteSurroundingText(mConnection, 1, 0);
428 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
429 assertEquals("hi", mConnection.getTextBeforeCursor(9, 0));
430 assertUpdateStateCall(mConnection, 1000);
431 assertEquals("hi", mConnection.getTextBeforeCursor(9, 0));
432
433 // DEL
434 expectUpdateStateCall(mConnection);
435 deleteSurroundingText(mConnection, 1, 0);
436 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
437 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
438 assertUpdateStateCall(mConnection, 1000);
439 assertEquals("h", mConnection.getTextBeforeCursor(9, 0));
440
441 // DEL
442 expectUpdateStateCall(mConnection);
443 deleteSurroundingText(mConnection, 1, 0);
444 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
445 assertEquals("", mConnection.getTextBeforeCursor(9, 0));
446 assertUpdateStateCall(mConnection, 1000);
447 assertEquals("", mConnection.getTextBeforeCursor(9, 0));
448
449 // DEL (on empty input)
450 deleteSurroundingText(mConnection, 1, 0); // BS on empty still sends 1, 0
451 assertEquals(KeyEvent.KEYCODE_DEL, mImeAdapter.mLastSyntheticKeyCode);
452 assertEquals("", mConnection.getTextBeforeCursor(9, 0));
453 }
454
455 @SmallTest
456 @Feature({"TextInput", "Main"})
267 public void testEnterKeyEventWhileComposingText() throws Throwable { 457 public void testEnterKeyEventWhileComposingText() throws Throwable {
268 DOMUtils.focusNode(mContentViewCore, "input_radio"); 458 DOMUtils.focusNode(mContentViewCore, "input_radio");
269 assertWaitForKeyboardStatus(false); 459 assertWaitForKeyboardStatus(false);
270 DOMUtils.focusNode(mContentViewCore, "textarea"); 460 DOMUtils.focusNode(mContentViewCore, "textarea");
271 assertWaitForKeyboardStatus(true); 461 assertWaitForKeyboardStatus(true);
272 462
273 mConnection = (TestAdapterInputConnection) getAdapterInputConnection(); 463 mConnection = (TestAdapterInputConnection) getAdapterInputConnection();
274 waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 0, "", 0, 0, -1, -1); 464 waitAndVerifyEditableCallback(mConnection.mImeUpdateQueue, 0, "", 0, 0, -1, -1);
275 465
276 setComposingText(mConnection, "hello", 1); 466 setComposingText(mConnection, "hello", 1);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 510 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
321 @Override 511 @Override
322 public boolean isSatisfied() { 512 public boolean isSatisfied() {
323 return states.size() > index; 513 return states.size() > index;
324 } 514 }
325 })); 515 }));
326 states.get(index).assertEqualState( 516 states.get(index).assertEqualState(
327 text, selectionStart, selectionEnd, compositionStart, compositio nEnd); 517 text, selectionStart, selectionEnd, compositionStart, compositio nEnd);
328 } 518 }
329 519
520 private void expectUpdateStateCall(final TestAdapterInputConnection connecti on) {
521 connection.mUpdateStateCalls = 0;
522 }
523
524 private void assertUpdateStateCall(final TestAdapterInputConnection connecti on, int maxms)
525 throws Exception {
526 while (connection.mUpdateStateCalls == 0 && maxms > 0) {
527 try {
528 Thread.sleep(50);
529 } catch (Exception e) {
530 // Not really a problem since we're just going to sleep again.
531 }
532 maxms -= 50;
533 }
534 assertTrue(connection.mUpdateStateCalls > 0);
535 }
536
330 private void assertClipboardContents(final Activity activity, final String e xpectedContents) 537 private void assertClipboardContents(final Activity activity, final String e xpectedContents)
331 throws InterruptedException { 538 throws InterruptedException {
332 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 539 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
333 @Override 540 @Override
334 public boolean isSatisfied() { 541 public boolean isSatisfied() {
335 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable <Boolean>() { 542 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable <Boolean>() {
336 @Override 543 @Override
337 public Boolean call() throws Exception { 544 public Boolean call() throws Exception {
338 ClipboardManager clipboardManager = 545 ClipboardManager clipboardManager =
339 (ClipboardManager) activity.getSystemService( 546 (ClipboardManager) activity.getSystemService(
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 649
443 private void finishComposingText(final AdapterInputConnection connection) { 650 private void finishComposingText(final AdapterInputConnection connection) {
444 ThreadUtils.runOnUiThreadBlocking(new Runnable() { 651 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
445 @Override 652 @Override
446 public void run() { 653 public void run() {
447 connection.finishComposingText(); 654 connection.finishComposingText();
448 } 655 }
449 }); 656 });
450 } 657 }
451 658
659 private void deleteSurroundingText(final AdapterInputConnection connection, final int before,
660 final int after) {
661 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
662 @Override
663 public void run() {
664 connection.deleteSurroundingText(before, after);
665 }
666 });
667 }
668
452 private static class TestAdapterInputConnectionFactory extends 669 private static class TestAdapterInputConnectionFactory extends
453 ImeAdapter.AdapterInputConnectionFactory { 670 ImeAdapter.AdapterInputConnectionFactory {
454 @Override 671 @Override
455 public AdapterInputConnection get(View view, ImeAdapter imeAdapter, 672 public AdapterInputConnection get(View view, ImeAdapter imeAdapter,
456 Editable editable, EditorInfo outAttrs) { 673 Editable editable, EditorInfo outAttrs) {
457 return new TestAdapterInputConnection(view, imeAdapter, editable, ou tAttrs); 674 return new TestAdapterInputConnection(view, imeAdapter, editable, ou tAttrs);
458 } 675 }
459 } 676 }
460 677
461 private static class TestAdapterInputConnection extends AdapterInputConnecti on { 678 private static class TestAdapterInputConnection extends AdapterInputConnecti on {
462 private final ArrayList<TestImeState> mImeUpdateQueue = new ArrayList<Te stImeState>(); 679 private final ArrayList<TestImeState> mImeUpdateQueue = new ArrayList<Te stImeState>();
aurimas (slooooooooow) 2014/07/22 16:25:43 Can you simply use mImeUpdateQueue.size() instead
bcwhite 2014/07/22 17:28:33 Done.
680 public int mUpdateStateCalls = 0;
463 681
464 public TestAdapterInputConnection(View view, ImeAdapter imeAdapter, 682 public TestAdapterInputConnection(View view, ImeAdapter imeAdapter,
465 Editable editable, EditorInfo outAttrs) { 683 Editable editable, EditorInfo outAttrs) {
466 super(view, imeAdapter, editable, outAttrs); 684 super(view, imeAdapter, editable, outAttrs);
467 } 685 }
468 686
469 @Override 687 @Override
470 public void updateState(String text, int selectionStart, int selectionEn d, 688 public void updateState(String text, int selectionStart, int selectionEn d,
471 int compositionStart, int compositionEnd, boolean requiredAck) { 689 int compositionStart, int compositionEnd, boolean requiredAck) {
690 mUpdateStateCalls++;
472 mImeUpdateQueue.add(new TestImeState(text, selectionStart, selection End, 691 mImeUpdateQueue.add(new TestImeState(text, selectionStart, selection End,
473 compositionStart, compositionEnd)); 692 compositionStart, compositionEnd));
474 super.updateState(text, selectionStart, selectionEnd, compositionSta rt, 693 super.updateState(text, selectionStart, selectionEnd, compositionSta rt,
475 compositionEnd, requiredAck); 694 compositionEnd, requiredAck);
476 } 695 }
477 } 696 }
478 697
479 private static class TestImeState { 698 private static class TestImeState {
480 private final String mText; 699 private final String mText;
481 private final int mSelectionStart; 700 private final int mSelectionStart;
(...skipping 13 matching lines...) Expand all
495 public void assertEqualState(String text, int selectionStart, int select ionEnd, 714 public void assertEqualState(String text, int selectionStart, int select ionEnd,
496 int compositionStart, int compositionEnd) { 715 int compositionStart, int compositionEnd) {
497 assertEquals("Text did not match", text, mText); 716 assertEquals("Text did not match", text, mText);
498 assertEquals("Selection start did not match", selectionStart, mSelec tionStart); 717 assertEquals("Selection start did not match", selectionStart, mSelec tionStart);
499 assertEquals("Selection end did not match", selectionEnd, mSelection End); 718 assertEquals("Selection end did not match", selectionEnd, mSelection End);
500 assertEquals("Composition start did not match", compositionStart, mC ompositionStart); 719 assertEquals("Composition start did not match", compositionStart, mC ompositionStart);
501 assertEquals("Composition end did not match", compositionEnd, mCompo sitionEnd); 720 assertEquals("Composition end did not match", compositionEnd, mCompo sitionEnd);
502 } 721 }
503 } 722 }
504 } 723 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698