diff options
author | aurimas@google.com <aurimas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-19 19:32:39 +0000 |
---|---|---|
committer | aurimas@google.com <aurimas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-19 19:32:39 +0000 |
commit | 990f7296cff83d131217ce6e985e6f614519236e (patch) | |
tree | 10565f23b64750a66c1d606b6730d80569d13999 /content/public | |
parent | f9ca2dcd42c17c00f181a1b924dd3906fdfb6a86 (diff) | |
download | chromium_src-990f7296cff83d131217ce6e985e6f614519236e.zip chromium_src-990f7296cff83d131217ce6e985e6f614519236e.tar.gz chromium_src-990f7296cff83d131217ce6e985e6f614519236e.tar.bz2 |
Merge 182344
> Adding IME test changes to make it easier to test.
>
> NOTRY=true
> BUG=177005
>
> Review URL: https://chromiumcodereview.appspot.com/12262016
TBR=aurimas@chromium.org
Review URL: https://codereview.chromium.org/12295035
git-svn-id: svn://svn.chromium.org/chrome/branches/1410/src@183265 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/public')
3 files changed, 183 insertions, 22 deletions
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index 6234564..ace7a1d 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java @@ -44,6 +44,7 @@ import org.chromium.base.JNINamespace; import org.chromium.base.WeakContext; import org.chromium.content.R; import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate; +import org.chromium.content.browser.ImeAdapter.AdapterInputConnectionFactory; import org.chromium.content.browser.accessibility.AccessibilityInjector; import org.chromium.content.common.ProcessInitException; import org.chromium.content.common.TraceEvent; @@ -211,6 +212,7 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { // Only valid when focused on a text / password field. private ImeAdapter mImeAdapter; + private ImeAdapter.AdapterInputConnectionFactory mAdapterInputConnectionFactory; private ImeAdapter.AdapterInputConnection mInputConnection; private SelectionHandleController mSelectionHandleController; @@ -293,6 +295,7 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { WeakContext.initializeWeakContext(context); mPersonality = personality; HeapStatsLogger.init(mContext.getApplicationContext()); + mAdapterInputConnectionFactory = new AdapterInputConnectionFactory(); } /** @@ -341,6 +344,11 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { } @VisibleForTesting + protected void setAdapterInputConnectionFactory(AdapterInputConnectionFactory factory) { + mAdapterInputConnectionFactory = factory; + } + + @VisibleForTesting protected ImeAdapter.AdapterInputConnection getInputConnectionForTest() { return mInputConnection; } @@ -1235,8 +1243,8 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { // enter fullscreen mode. outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN; } - mInputConnection = ImeAdapter.AdapterInputConnection.getInstance( - mContainerView, mImeAdapter, outAttrs); + mInputConnection = + mAdapterInputConnectionFactory.get(mContainerView, mImeAdapter, outAttrs); return mInputConnection; } diff --git a/content/public/android/java/src/org/chromium/content/browser/ImeAdapter.java b/content/public/android/java/src/org/chromium/content/browser/ImeAdapter.java index e5ddc298..aa2a218 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ImeAdapter.java +++ b/content/public/android/java/src/org/chromium/content/browser/ImeAdapter.java @@ -280,7 +280,8 @@ class ImeAdapter { } } - private boolean checkCompositionQueueAndCallNative(String text, int newCursorPosition, + @VisibleForTesting + boolean checkCompositionQueueAndCallNative(String text, int newCursorPosition, boolean isCommit) { if (mNativeImeAdapterAndroid == 0) { return false; @@ -461,20 +462,21 @@ class ImeAdapter { return true; } + public static class AdapterInputConnectionFactory { + public AdapterInputConnection get(View view, ImeAdapter imeAdapter, + EditorInfo outAttrs) { + return new AdapterInputConnection(view, imeAdapter, outAttrs); + } + } + // This InputConnection is created by ContentView.onCreateInputConnection. // It then adapts android's IME to chrome's RenderWidgetHostView using the // native ImeAdapterAndroid via the outer class ImeAdapter. - static public class AdapterInputConnection extends BaseInputConnection { + public static class AdapterInputConnection extends BaseInputConnection { private View mInternalView; private ImeAdapter mImeAdapter; private boolean mSingleLine; - // Factory function. - static public AdapterInputConnection getInstance(View view, ImeAdapter imeAdapter, - EditorInfo outAttrs) { - return new AdapterInputConnection(view, imeAdapter, outAttrs); - } - /** * Updates the AdapterInputConnection's internal representation of the text * being edited and its selection and composition properties. The resulting @@ -522,7 +524,6 @@ class ImeAdapter { } Selection.setSelection(editable, selectionStart, selectionEnd); super.setComposingRegion(compositionStart, compositionEnd); - if (textUnchanged || prevText.equals("")) { // updateSelection should be called when a manual selection change occurs. // Should not be called if text is being entered else issues can occur @@ -685,7 +686,8 @@ class ImeAdapter { .getSystemService(Context.INPUT_METHOD_SERVICE); } - private AdapterInputConnection(View view, ImeAdapter imeAdapter, EditorInfo outAttrs) { + @VisibleForTesting + protected AdapterInputConnection(View view, ImeAdapter imeAdapter, EditorInfo outAttrs) { super(view, true); mInternalView = view; mImeAdapter = imeAdapter; diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ImeTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ImeTest.java index 2b0cf27..5071f1b 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ImeTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ImeTest.java @@ -5,9 +5,15 @@ package org.chromium.content.browser; import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.view.View; import android.view.inputmethod.EditorInfo; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.UrlUtils; +import org.chromium.content.browser.ImeAdapter.AdapterInputConnection; +import org.chromium.content.browser.ImeAdapter.AdapterInputConnectionFactory; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.content.browser.test.util.DOMUtils; @@ -17,31 +23,132 @@ import org.chromium.content_shell.ContentShellTestBase; public class ImeTest extends ContentShellTestBase { - private static final String DATA_URL = - "data:text/html;utf-8,<html><body>" + + private static final String DATA_URL = UrlUtils.encodeHtmlDataUri( + "<html><body>" + + "<form action=\"about:blank\">" + "<input id=\"input_text\" type=\"text\" />" + - "</body></html>"; + "</form></body></html>"); + /* @MediumTest @Feature({"TextInput", "Main"}) + */ + @DisabledTest public void testKeyboardDismissedAfterClickingGo() throws Throwable { launchContentShellWithUrl(DATA_URL); assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading()); + getContentViewCore().setAdapterInputConnectionFactory( + new TestAdapterInputConnectionFactory()); + + final ContentView view = getActivity().getActiveContentView(); + final TestCallbackHelperContainer viewClient = + new TestCallbackHelperContainer(view); + DOMUtils.clickNode(this, view, viewClient, "input_text"); + assertWaitForKeyboardStatus(true); + + TestAdapterInputConnection connection = + (TestAdapterInputConnection) getAdapterInputConnection(); + ImeAdapter adapter = getImeAdapter(); + + assertWaitForSetEditableCallback(1, connection); + assertEquals("", connection.mText); + assertEquals(0, connection.mSelectionStart); + assertEquals(0, connection.mSelectionEnd); + assertEquals(-1, connection.mCompositionStart); + assertEquals(-1, connection.mCompositionEnd); + + adapter.checkCompositionQueueAndCallNative("hello", 1, false); + assertWaitForSetEditableCallback(2, connection); + assertEquals("hello", connection.mText); + assertEquals(5, connection.mSelectionStart); + assertEquals(5, connection.mSelectionEnd); + assertEquals(0, connection.mCompositionStart); + assertEquals(5, connection.mCompositionEnd); + + performGo(getAdapterInputConnection(), viewClient); + + assertWaitForSetEditableCallback(3, connection); + assertEquals("", connection.mText); + assertEquals(0, connection.mSelectionStart); + assertEquals(0, connection.mSelectionEnd); + assertEquals(-1, connection.mCompositionStart); + assertEquals(-1, connection.mCompositionEnd); + assertWaitForKeyboardStatus(true); + } + + /* + @SmallTest + @Feature({"TextInput", "Main"}) + */ + @DisabledTest + public void testGetTextUpdatesAfterEnteringText() throws Throwable { + launchContentShellWithUrl(DATA_URL); + assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading()); + + getContentViewCore().setAdapterInputConnectionFactory( + new TestAdapterInputConnectionFactory()); + final ContentView view = getActivity().getActiveContentView(); final TestCallbackHelperContainer viewClient = new TestCallbackHelperContainer(view); DOMUtils.clickNode(this, view, viewClient, "input_text"); assertWaitForKeyboardStatus(true); - getAdapterInputConnection().setComposingText("hello", 5); - getAdapterInputConnection().performEditorAction(EditorInfo.IME_ACTION_GO); + TestAdapterInputConnection connection = + (TestAdapterInputConnection) getAdapterInputConnection(); + ImeAdapter adapter = getImeAdapter(); - // Since hiding the keyboard is an asynchronous task, it might take an arbitrary amount - // of time. settleDownUI will wait for one second and hopefully allowing the keyboard to - // get to it's final state. - UiUtils.settleDownUI(getInstrumentation()); - assertWaitForKeyboardStatus(false); + assertWaitForSetEditableCallback(1, connection); + assertEquals("", connection.mText); + assertEquals(0, connection.mSelectionStart); + assertEquals(0, connection.mSelectionEnd); + assertEquals(-1, connection.mCompositionStart); + assertEquals(-1, connection.mCompositionEnd); + + adapter.checkCompositionQueueAndCallNative("h", 1, false); + assertWaitForSetEditableCallback(2, connection); + assertEquals("h", connection.mText); + assertEquals(1, connection.mSelectionStart); + assertEquals(1, connection.mSelectionEnd); + assertEquals(0, connection.mCompositionStart); + assertEquals(1, connection.mCompositionEnd); + + adapter.checkCompositionQueueAndCallNative("he", 1, false); + assertWaitForSetEditableCallback(3, connection); + assertEquals("he", connection.mText); + assertEquals(2, connection.mSelectionStart); + assertEquals(2, connection.mSelectionEnd); + assertEquals(0, connection.mCompositionStart); + assertEquals(2, connection.mCompositionEnd); + + adapter.checkCompositionQueueAndCallNative("hel", 1, false); + assertWaitForSetEditableCallback(4, connection); + assertEquals("hel", connection.mText); + assertEquals(3, connection.mSelectionStart); + assertEquals(3, connection.mSelectionEnd); + assertEquals(0, connection.mCompositionStart); + assertEquals(3, connection.mCompositionEnd); + + adapter.checkCompositionQueueAndCallNative("hel", 1, true); + assertWaitForSetEditableCallback(5, connection); + assertEquals("hel", connection.mText); + assertEquals(3, connection.mSelectionStart); + assertEquals(3, connection.mSelectionEnd); + assertEquals(-1, connection.mCompositionStart); + assertEquals(-1, connection.mCompositionEnd); + } + + private void performGo(final AdapterInputConnection inputConnection, + TestCallbackHelperContainer testCallbackHelperContainer) throws Throwable { + handleBlockingCallbackAction( + testCallbackHelperContainer.getOnPageFinishedHelper(), + new Runnable() { + @Override + public void run() { + inputConnection.performEditorAction(EditorInfo.IME_ACTION_GO); + } + }); } private void assertWaitForKeyboardStatus(final boolean show) throws Throwable { @@ -53,6 +160,16 @@ public class ImeTest extends ContentShellTestBase { })); } + private void assertWaitForSetEditableCallback(final int callbackNumber, + final TestAdapterInputConnection connection) throws Throwable { + assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { + @Override + public boolean isSatisfied() { + return callbackNumber == connection.mSetEditableTextCallCounter; + } + })); + } + private ImeAdapter getImeAdapter() { return getContentViewCore().getImeAdapterForTest(); } @@ -60,4 +177,38 @@ public class ImeTest extends ContentShellTestBase { private ImeAdapter.AdapterInputConnection getAdapterInputConnection() { return getContentViewCore().getInputConnectionForTest(); } + + private static class TestAdapterInputConnectionFactory extends + ImeAdapter.AdapterInputConnectionFactory { + @Override + public AdapterInputConnection get(View view, ImeAdapter imeAdapter, + EditorInfo outAttrs) { + return new TestAdapterInputConnection(view, imeAdapter, outAttrs); + } + } + + private static class TestAdapterInputConnection extends ImeAdapter.AdapterInputConnection { + private int mSetEditableTextCallCounter; + private String mText; + private int mSelectionStart; + private int mSelectionEnd; + private int mCompositionStart; + private int mCompositionEnd; + + public TestAdapterInputConnection(View view, ImeAdapter imeAdapter, EditorInfo outAttrs) { + super(view, imeAdapter, outAttrs); + mSetEditableTextCallCounter = 0; + } + + @Override + public void setEditableText(String text, int selectionStart, int selectionEnd, + int compositionStart, int compositionEnd) { + mText = text; + mSelectionStart = selectionStart; + mSelectionEnd = selectionEnd; + mCompositionStart = compositionStart; + mCompositionEnd = compositionEnd; + mSetEditableTextCallCounter++; + } + } } |