OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |