Final polish of WebView accessibility support for no JavaScript case.

1. Added tests for the new code added by change:I5a796aef

2. WebCore thread now calls the UI thread to set the cursor to
   the current position enabling the user to interact with
   the content that is being selected on the page.

3. Removed the code that changes the selection on movement of the
   cursor ring. We are dropping the "default web view behavior"
   as granularity of reading the document since with this change
   a user can freely access inputs/buttons/links.

Change-Id: I7a3f6677eff0bc95e8127973d07cec78e3465c7b
This commit is contained in:
Svetoslav Ganov
2011-01-14 11:38:17 -08:00
parent c45ec3440b
commit 9504f5753d
4 changed files with 592 additions and 53 deletions

View File

@@ -113,6 +113,11 @@ class AccessibilityInjector {
* @return True if the event was processed.
*/
public boolean onKeyEvent(KeyEvent event) {
// We do not handle ENTER in any circumstances.
if (isEnterActionKey(event.getKeyCode())) {
return false;
}
if (event.getAction() == KeyEvent.ACTION_UP) {
return mLastDownEventHandled;
}
@@ -367,6 +372,12 @@ class AccessibilityInjector {
}
}
private boolean isEnterActionKey(int keyCode) {
return keyCode == KeyEvent.KEYCODE_DPAD_CENTER
|| keyCode == KeyEvent.KEYCODE_ENTER
|| keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER;
}
/**
* Represents a web content key-binding.
*/

View File

@@ -16,9 +16,6 @@
package android.webkit;
import android.view.HardwareCanvas;
import com.android.internal.R;
import android.annotation.Widget;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
@@ -31,7 +28,6 @@ import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -57,7 +53,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.provider.Settings;
import android.speech.tts.TextToSpeech;
import android.text.Selection;
@@ -66,6 +61,7 @@ import android.util.AttributeSet;
import android.util.EventLog;
import android.util.Log;
import android.view.Gravity;
import android.view.HardwareCanvas;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -92,7 +88,6 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.EdgeGlow;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.OverScroller;
@@ -677,6 +672,8 @@ public class WebView extends AbsoluteLayout
static final int SET_AUTOFILLABLE = 133;
static final int AUTOFILL_COMPLETE = 134;
static final int SELECT_AT = 135;
private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
private static final int LAST_PACKAGE_MSG_ID = SET_TOUCH_HIGHLIGHT_RECTS;
@@ -728,7 +725,8 @@ public class WebView extends AbsoluteLayout
"SET_TOUCH_HIGHLIGHT_RECTS", // = 131;
"SAVE_WEBARCHIVE_FINISHED", // = 132;
"SET_AUTOFILLABLE", // = 133;
"AUTOFILL_COMPLETE" // = 134;
"AUTOFILL_COMPLETE", // = 134;
"SELECT_AT" // = 135;
};
// If the site doesn't use the viewport meta tag to specify the viewport,
@@ -7600,6 +7598,10 @@ public class WebView extends AbsoluteLayout
}
break;
case SELECT_AT:
nativeSelectAt(msg.arg1, msg.arg2);
break;
default:
super.handleMessage(msg);
break;
@@ -7957,24 +7959,6 @@ public class WebView extends AbsoluteLayout
cursorData());
}
/*
* Called from JNI when the cursor has moved. This method
* sends a message to the WebCore requesting the given
* nodePtr in the given framePrt to be selected which will
* result in firing an accessibility event announing its
* content.
*
* Note: Accessibility support.
*/
@SuppressWarnings("unused")
// called from JNI
private void sendMoveSelection(int framePtr, int nodePtr) {
if (AccessibilityManager.getInstance(mContext).isEnabled()
&& mAccessibilityInjector != null) {
mWebViewCore.sendMessage(EventHub.MOVE_SELECTION, framePtr, nodePtr);
}
}
/**
* Called by JNI to send a message to the webcore thread that the user
* touched the webpage.
@@ -8283,6 +8267,7 @@ public class WebView extends AbsoluteLayout
private native Point nativeSelectableText();
private native void nativeSelectAll();
private native void nativeSelectBestAt(Rect rect);
private native void nativeSelectAt(int x, int y);
private native int nativeSelectionX();
private native int nativeSelectionY();
private native int nativeFindIndex();

View File

@@ -641,18 +641,6 @@ final class WebViewCore {
*/
private native String nativeModifySelection(int direction, int granularity);
/**
* Moves the selection to given node i.e. selects that node.
*
* Note: Accessibility support.
*
* @param framePtr Pointer to the frame containing the node to be selected.
* @param nodePtr Pointer to the node to be selected.
*
* @return The selection string.
*/
private native String nativeMoveSelection(int framePtr, int nodePtr);
// EventHub for processing messages
private final EventHub mEventHub;
// WebCore thread handler
@@ -1018,9 +1006,6 @@ final class WebViewCore {
static final int PROXY_CHANGED = 193;
// accessibility support
static final int MOVE_SELECTION = 194;
// private message ids
private static final int DESTROY = 200;
@@ -1439,12 +1424,6 @@ final class WebViewCore {
modifiedSelectionString).sendToTarget();
break;
case MOVE_SELECTION:
String movedSelectionString = nativeMoveSelection(msg.arg1, msg.arg2);
mWebView.mPrivateHandler.obtainMessage(WebView.SELECTION_STRING_CHANGED,
movedSelectionString).sendToTarget();
break;
case LISTBOX_CHOICES:
SparseBooleanArray choices = (SparseBooleanArray)
msg.obj;
@@ -2714,6 +2693,14 @@ final class WebViewCore {
hMode, vMode).sendToTarget();
}
// called by JNI
@SuppressWarnings("unused")
private void selectAt(int x, int y) {
if (mWebView != null) {
mWebView.mPrivateHandler.obtainMessage(WebView.SELECT_AT, x, y).sendToTarget();
}
}
private void useMockDeviceOrientation() {
mDeviceMotionAndOrientationManager.useMock();
}

View File

@@ -51,7 +51,7 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
private static final long TIMEOUT_ENABLE_ACCESSIBILITY_AND_MOCK_SERVICE = 1000;
/** The count of tests to detect when to shut down the service. */
private static final int TEST_CASE_COUNT = 8;
private static final int TEST_CASE_COUNT = 16;
/** The meta state for pressed left ALT. */
private static final int META_STATE_ALT_LEFT_ON = KeyEvent.META_ALT_ON
@@ -140,7 +140,8 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
"</p>" +
"<p>" +
"d" +
"<input>e</input>" +
"<p/>" +
"e" +
"</p>" +
"</body>" +
"</html>";
@@ -179,6 +180,10 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the fifth character (reverse)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("e");
// go to the fourth character (reverse)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("d");
@@ -199,6 +204,10 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first character
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("a");
// go to the second character (reverse again)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<b>b</b>");
@@ -223,11 +232,11 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
"</p>" +
"<p>" +
" scattered " +
"<input>all</input>" +
" over " +
"<p/>" +
" all over " +
"</p>" +
"<div>" +
"<button>the place.</button>" +
"<p>the place.</p>" +
"</div>" +
"</body>" +
"</html>";
@@ -284,7 +293,7 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
// go to the last word (reverse)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("place");
assertSelectionString("place.");
// go to the eight word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
@@ -322,6 +331,10 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("This");
// go to the second word (reverse again)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("is");
@@ -384,6 +397,10 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the fifth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("This is the second sentence of the second paragraph.");
// go to the fourth sentence (reverse)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("This is the first sentence of the second paragraph.");
@@ -405,6 +422,11 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("This is the first sentence of the first paragraph and has an "
+ "<b>inline bold tag</b>.");
// go to the second sentence (reverse again)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("This is the second sentence of the first paragraph.");
@@ -746,6 +768,539 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
assertSelectionString("Third");
}
/**
* Tests that the selection does not cross anchor boundaries. This is a
* workaround for the asymmetric and inconsistent handling of text with
* links by WebKit while traversing by sentence.
*/
@LargeTest
public void testEnforceSelectionDoesNotCrossAnchorBoundary1() throws Exception {
// a bit ugly but helps detect beginning and end of all tests so accessibility
// and the mock service are not toggled on every test (expensive)
sExecutedTestCount++;
String html =
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
"</head>" +
"<body>" +
"<div>First</div>" +
"<p>" +
"<a href=\"\">Second</a> Third" +
"</p>" +
"</body>" +
"</html>";
WebView webView = createWebVewWithHtml(html);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<a href=\"\">Second</a>");
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("Third");
// go to past the last sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("Third");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<a href=\"\">Second</a>");
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("First");
// go to before the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
}
/**
* Tests that the selection does not cross anchor boundaries. This is a
* workaround for the asymmetric and inconsistent handling of text with
* links by WebKit while traversing by sentence.
*/
@LargeTest
public void testEnforceSelectionDoesNotCrossAnchorBoundary2() throws Exception {
// a bit ugly but helps detect beginning and end of all tests so accessibility
// and the mock service are not toggled on every test (expensive)
sExecutedTestCount++;
String html =
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
"</head>" +
"<body>" +
"<div>First</div>" +
"<a href=\"#\">Second</a>" +
"&nbsp;" +
"<a href=\"#\">Third</a>" +
"</body>" +
"</html>";
WebView webView = createWebVewWithHtml(html);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<a href=\"#\">Second</a>");
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("&nbsp;");
// go to the fourth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<a href=\"#\">Third</a>");
// go to past the last sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the fourth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<a href=\"#\">Third</a>");
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("&nbsp;");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<a href=\"#\">Second</a>");
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("First");
// go to before the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
}
/**
* Tests that the selection does not cross anchor boundaries. This is a
* workaround for the asymmetric and inconsistent handling of text with
* links by WebKit while traversing by sentence.
*/
@LargeTest
public void testEnforceSelectionDoesNotCrossAnchorBoundary3() throws Exception {
// a bit ugly but helps detect beginning and end of all tests so accessibility
// and the mock service are not toggled on every test (expensive)
sExecutedTestCount++;
String html =
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
"</head>" +
"<body>" +
"<div>" +
"First" +
"<div>" +
"<div>" +
"<a href=\"#\">Second</a>" +
"</div>" +
"<div>" +
"Third" +
"</div>" +
"</body>" +
"</html>";
WebView webView = createWebVewWithHtml(html);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<a href=\"#\">Second</a>");
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("Third");
// go to past the last sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("Third");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<a href=\"#\">Second</a>");
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("First");
// go to before the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
}
/**
* Tests skipping of content with hidden visibility.
*/
@LargeTest
public void testSkipVisibilityHidden() throws Exception {
// a bit ugly but helps detect beginning and end of all tests so accessibility
// and the mock service are not toggled on every test (expensive)
sExecutedTestCount++;
String html =
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
"</head>" +
"<body>" +
"<div>First </div>" +
"<div style=\"visibility:hidden;\">Second</div>" +
"<div> Third</div>" +
"</body>" +
"</html>";
WebView webView = createWebVewWithHtml(html);
// change navigation axis to word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, META_STATE_ALT_LEFT_ON);
assertSelectionString("1"); // expect the word navigation axis
// go to the first word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
// go to the third word (the second is invisible)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("Third");
// go to past the last sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the third word (the second is invisible)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("Third");
// go to the first word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("First");
// go to before the first word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
}
/**
* Tests skipping of content with display none.
*/
@LargeTest
public void testSkipDisplayNone() throws Exception {
// a bit ugly but helps detect beginning and end of all tests so accessibility
// and the mock service are not toggled on every test (expensive)
sExecutedTestCount++;
String html =
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
"</head>" +
"<body>" +
"<div>First</div>" +
"<div style=\"display: none;\">Second</div>" +
"<div>Third</div>" +
"</body>" +
"</html>";
WebView webView = createWebVewWithHtml(html);
// change navigation axis to word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, META_STATE_ALT_LEFT_ON);
assertSelectionString("1"); // expect the word navigation axis
// go to the first word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
// go to the third word (the second is invisible)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("Third");
// go to past the last sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the third word (the second is invisible)
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("Third");
// go to the first word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("First");
// go to before the first word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first word
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
}
/**
* Tests for the selection not getting stuck.
*
* Note: The selection always proceeds but if it can
* be selecting the same content i.e. between the start
* and end are contained the same text nodes.
*/
@LargeTest
public void testSelectionTextProceed() throws Exception {
// a bit ugly but helps detect beginning and end of all tests so accessibility
// and the mock service are not toggled on every test (expensive)
sExecutedTestCount++;
String html =
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
"</head>" +
"<body>" +
"<a href=\"#\">First</a>" +
"<span><a href=\"#\"><span>Second</span>&nbsp;<small>a</small></a>" +
"</span>&nbsp;<a href=\"#\">Third</a>" +
"</body>" +
"</html>";
WebView webView = createWebVewWithHtml(html);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<a href=\"#\">First</a>");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<a href=\"#\"><span>Second&nbsp;<small>a</small></a>");
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("&nbsp;");
// go to the fourth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<a href=\"#\">Third</a>");
// go to past the last sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<a href=\"#\">Third</a>");
// NOTE: Here we are a bit asymmetric around whitespace but we can live with it
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("&nbsp;");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<a href=\"#\"><span>Second&nbsp;<small>a</small></a>");
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<a href=\"#\">First</a>");
// go to before the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<a href=\"#\">First</a>");
}
/**
* Tests if input elements are selected rather skipped.
*/
@LargeTest
public void testSelectionOfInputElements() throws Exception {
// a bit ugly but helps detect beginning and end of all tests so accessibility
// and the mock service are not toggled on every test (expensive)
sExecutedTestCount++;
String html =
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
"</head>" +
"<body>" +
"<p>" +
"First" +
"</p>" +
"<input type=\"text\"/>" +
"<p>" +
"Second" +
"</p>" +
"</body>" +
"</html>";
WebView webView = createWebVewWithHtml(html);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<input type=\"text\">");
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("Second");
// go to past the last sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("Second");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<input type=\"text\">");
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("First");
// go to before the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString(null);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
}
/**
* Tests traversing of input controls.
*/
@LargeTest
public void testSelectionOfInputElements2() throws Exception {
// a bit ugly but helps detect beginning and end of all tests so accessibility
// and the mock service are not toggled on every test (expensive)
sExecutedTestCount++;
String html =
"<!DOCTYPE html>" +
"<html>" +
"<head>" +
"</head>" +
"<body>" +
"<div>" +
"First" +
"<input type=\"text\"/>" +
"<span>" +
"<input type=\"text\"/>" +
"</span>" +
"<button type=\"button\">Click Me!</button>" +
"<div>" +
"<input type=\"submit\"/>" +
"</div>" +
"<p>" +
"Second" +
"</p>" +
"</div>" +
"</body>" +
"</html>";
WebView webView = createWebVewWithHtml(html);
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("First");
// go to the second sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<input type=\"text\">");
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<input type=\"text\">");
// go to the fourth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<button type=\"button\">Click Me!</button>");
// go to the fifth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("<input type=\"submit\">");
// go to the sixth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString("Second");
// go to past the last sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_DOWN, 0);
assertSelectionString(null);
// go to the sixth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("Second");
// go to the fifth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<input type=\"submit\">");
// go to the fourth sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<button type=\"button\">Click Me!</button>");
// go to the third sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("<input type=\"text\">");
// go to the first sentence
sendKeyEvent(webView, KeyEvent.KEYCODE_DPAD_UP, 0);
assertSelectionString("First");
}
/**
* Enable accessibility and the mock accessibility service.
*/
@@ -887,7 +1442,8 @@ public class AccessibilityInjectorTest extends AndroidTestCase {
*/
private void restoreDefaultWebContentKeyBindings() {
Settings.Secure.putString(getContext().getContentResolver(),
Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS, mDefaultKeyBindings);
Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
mDefaultKeyBindings);
}
/**