Commit 490ccaf2 authored by aurimas@chromium.org's avatar aurimas@chromium.org

Adding IME test changes to make it easier to test.

NOTRY=true


Review URL: https://chromiumcodereview.appspot.com/12262016

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182344 0039d316-1c4b-4281-b951-d872f2087c98
parent 8838f983
...@@ -44,6 +44,7 @@ import org.chromium.base.JNINamespace; ...@@ -44,6 +44,7 @@ import org.chromium.base.JNINamespace;
import org.chromium.base.WeakContext; import org.chromium.base.WeakContext;
import org.chromium.content.R; import org.chromium.content.R;
import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate; 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.browser.accessibility.AccessibilityInjector;
import org.chromium.content.common.ProcessInitException; import org.chromium.content.common.ProcessInitException;
import org.chromium.content.common.TraceEvent; import org.chromium.content.common.TraceEvent;
...@@ -211,6 +212,7 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { ...@@ -211,6 +212,7 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient {
// Only valid when focused on a text / password field. // Only valid when focused on a text / password field.
private ImeAdapter mImeAdapter; private ImeAdapter mImeAdapter;
private ImeAdapter.AdapterInputConnectionFactory mAdapterInputConnectionFactory;
private ImeAdapter.AdapterInputConnection mInputConnection; private ImeAdapter.AdapterInputConnection mInputConnection;
private SelectionHandleController mSelectionHandleController; private SelectionHandleController mSelectionHandleController;
...@@ -285,6 +287,7 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { ...@@ -285,6 +287,7 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient {
WeakContext.initializeWeakContext(context); WeakContext.initializeWeakContext(context);
mPersonality = personality; mPersonality = personality;
HeapStatsLogger.init(mContext.getApplicationContext()); HeapStatsLogger.init(mContext.getApplicationContext());
mAdapterInputConnectionFactory = new AdapterInputConnectionFactory();
} }
/** /**
...@@ -332,6 +335,11 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { ...@@ -332,6 +335,11 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient {
return mImeAdapter; return mImeAdapter;
} }
@VisibleForTesting
protected void setAdapterInputConnectionFactory(AdapterInputConnectionFactory factory) {
mAdapterInputConnectionFactory = factory;
}
@VisibleForTesting @VisibleForTesting
protected ImeAdapter.AdapterInputConnection getInputConnectionForTest() { protected ImeAdapter.AdapterInputConnection getInputConnectionForTest() {
return mInputConnection; return mInputConnection;
...@@ -1227,8 +1235,8 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient { ...@@ -1227,8 +1235,8 @@ public class ContentViewCore implements MotionEventDelegate, NavigationClient {
// enter fullscreen mode. // enter fullscreen mode.
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN; outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
} }
mInputConnection = ImeAdapter.AdapterInputConnection.getInstance( mInputConnection =
mContainerView, mImeAdapter, outAttrs); mAdapterInputConnectionFactory.get(mContainerView, mImeAdapter, outAttrs);
return mInputConnection; return mInputConnection;
} }
......
...@@ -280,7 +280,8 @@ class ImeAdapter { ...@@ -280,7 +280,8 @@ class ImeAdapter {
} }
} }
private boolean checkCompositionQueueAndCallNative(String text, int newCursorPosition, @VisibleForTesting
boolean checkCompositionQueueAndCallNative(String text, int newCursorPosition,
boolean isCommit) { boolean isCommit) {
if (mNativeImeAdapterAndroid == 0) { if (mNativeImeAdapterAndroid == 0) {
return false; return false;
...@@ -461,20 +462,21 @@ class ImeAdapter { ...@@ -461,20 +462,21 @@ class ImeAdapter {
return true; 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. // This InputConnection is created by ContentView.onCreateInputConnection.
// It then adapts android's IME to chrome's RenderWidgetHostView using the // It then adapts android's IME to chrome's RenderWidgetHostView using the
// native ImeAdapterAndroid via the outer class ImeAdapter. // native ImeAdapterAndroid via the outer class ImeAdapter.
static public class AdapterInputConnection extends BaseInputConnection { public static class AdapterInputConnection extends BaseInputConnection {
private View mInternalView; private View mInternalView;
private ImeAdapter mImeAdapter; private ImeAdapter mImeAdapter;
private boolean mSingleLine; 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 * Updates the AdapterInputConnection's internal representation of the text
* being edited and its selection and composition properties. The resulting * being edited and its selection and composition properties. The resulting
...@@ -522,7 +524,6 @@ class ImeAdapter { ...@@ -522,7 +524,6 @@ class ImeAdapter {
} }
Selection.setSelection(editable, selectionStart, selectionEnd); Selection.setSelection(editable, selectionStart, selectionEnd);
super.setComposingRegion(compositionStart, compositionEnd); super.setComposingRegion(compositionStart, compositionEnd);
if (textUnchanged || prevText.equals("")) { if (textUnchanged || prevText.equals("")) {
// updateSelection should be called when a manual selection change occurs. // updateSelection should be called when a manual selection change occurs.
// Should not be called if text is being entered else issues can occur // Should not be called if text is being entered else issues can occur
...@@ -685,7 +686,8 @@ class ImeAdapter { ...@@ -685,7 +686,8 @@ class ImeAdapter {
.getSystemService(Context.INPUT_METHOD_SERVICE); .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); super(view, true);
mInternalView = view; mInternalView = view;
mImeAdapter = imeAdapter; mImeAdapter = imeAdapter;
......
...@@ -5,9 +5,15 @@ ...@@ -5,9 +5,15 @@
package org.chromium.content.browser; package org.chromium.content.browser;
import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.View;
import android.view.inputmethod.EditorInfo; 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.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.Criteria;
import org.chromium.content.browser.test.util.CriteriaHelper; import org.chromium.content.browser.test.util.CriteriaHelper;
import org.chromium.content.browser.test.util.DOMUtils; import org.chromium.content.browser.test.util.DOMUtils;
...@@ -17,31 +23,132 @@ import org.chromium.content_shell.ContentShellTestBase; ...@@ -17,31 +23,132 @@ import org.chromium.content_shell.ContentShellTestBase;
public class ImeTest extends ContentShellTestBase { public class ImeTest extends ContentShellTestBase {
private static final String DATA_URL = private static final String DATA_URL = UrlUtils.encodeHtmlDataUri(
"data:text/html;utf-8,<html><body>" + "<html><body>" +
"<form action=\"about:blank\">" +
"<input id=\"input_text\" type=\"text\" />" + "<input id=\"input_text\" type=\"text\" />" +
"</body></html>"; "</form></body></html>");
/*
@MediumTest @MediumTest
@Feature({"TextInput", "Main"}) @Feature({"TextInput", "Main"})
*/
@DisabledTest
public void testKeyboardDismissedAfterClickingGo() throws Throwable { public void testKeyboardDismissedAfterClickingGo() throws Throwable {
launchContentShellWithUrl(DATA_URL); launchContentShellWithUrl(DATA_URL);
assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading()); assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading());
getContentViewCore().setAdapterInputConnectionFactory(
new TestAdapterInputConnectionFactory());
final ContentView view = getActivity().getActiveContentView(); final ContentView view = getActivity().getActiveContentView();
final TestCallbackHelperContainer viewClient = final TestCallbackHelperContainer viewClient =
new TestCallbackHelperContainer(view); new TestCallbackHelperContainer(view);
DOMUtils.clickNode(this, view, viewClient, "input_text"); DOMUtils.clickNode(this, view, viewClient, "input_text");
assertWaitForKeyboardStatus(true); assertWaitForKeyboardStatus(true);
getAdapterInputConnection().setComposingText("hello", 5); TestAdapterInputConnection connection =
getAdapterInputConnection().performEditorAction(EditorInfo.IME_ACTION_GO); (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);
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("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);
// Since hiding the keyboard is an asynchronous task, it might take an arbitrary amount adapter.checkCompositionQueueAndCallNative("hel", 1, true);
// of time. settleDownUI will wait for one second and hopefully allowing the keyboard to assertWaitForSetEditableCallback(5, connection);
// get to it's final state. assertEquals("hel", connection.mText);
UiUtils.settleDownUI(getInstrumentation()); assertEquals(3, connection.mSelectionStart);
assertWaitForKeyboardStatus(false); 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 { private void assertWaitForKeyboardStatus(final boolean show) throws Throwable {
...@@ -53,6 +160,16 @@ public class ImeTest extends ContentShellTestBase { ...@@ -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() { private ImeAdapter getImeAdapter() {
return getContentViewCore().getImeAdapterForTest(); return getContentViewCore().getImeAdapterForTest();
} }
...@@ -60,4 +177,38 @@ public class ImeTest extends ContentShellTestBase { ...@@ -60,4 +177,38 @@ public class ImeTest extends ContentShellTestBase {
private ImeAdapter.AdapterInputConnection getAdapterInputConnection() { private ImeAdapter.AdapterInputConnection getAdapterInputConnection() {
return getContentViewCore().getInputConnectionForTest(); 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++;
}
}
} }
...@@ -146,6 +146,9 @@ public class Shell extends LinearLayout { ...@@ -146,6 +146,9 @@ public class Shell extends LinearLayout {
mContentView.loadUrl(new LoadUrlParams(sanitizeUrl(url))); mContentView.loadUrl(new LoadUrlParams(sanitizeUrl(url)));
} }
mUrlTextView.clearFocus(); mUrlTextView.clearFocus();
// TODO(aurimas): Remove this when crbug.com/174541 is fixed.
mContentView.clearFocus();
mContentView.requestFocus();
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment