mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Backed out changeset ae9049c5ac63 (bug 1473998) for gv-junit failures on test.AccessibilityTest.testTextEntryNode. a=backout
This commit is contained in:
parent
26e792fe42
commit
1519cc7aac
@ -9,7 +9,6 @@ const AndroidEvents = {
|
||||
WINDOW_STATE_CHANGED: 0x20,
|
||||
VIEW_HOVER_ENTER: 0x80,
|
||||
VIEW_HOVER_EXIT: 0x100,
|
||||
WINDOW_CONTENT_CHANGED: 0x800,
|
||||
VIEW_SCROLLED: 0x1000,
|
||||
VIEW_TEXT_SELECTION_CHANGED: 0x2000,
|
||||
ANNOUNCEMENT: 0x4000,
|
||||
|
@ -13,17 +13,11 @@ ChromeUtils.defineModuleGetter(this, "UtteranceGenerator", // jshint ignore:line
|
||||
"resource://gre/modules/accessibility/OutputGenerator.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "States", // jshint ignore:line
|
||||
"resource://gre/modules/accessibility/Constants.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "Roles", // jshint ignore:line
|
||||
"resource://gre/modules/accessibility/Constants.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "AndroidEvents", // jshint ignore:line
|
||||
"resource://gre/modules/accessibility/Constants.jsm");
|
||||
|
||||
var EXPORTED_SYMBOLS = ["Presentation"]; // jshint ignore:line
|
||||
|
||||
const EDIT_TEXT_ROLES = new Set([
|
||||
Roles.SPINBUTTON, Roles.PASSWORD_TEXT,
|
||||
Roles.AUTOCOMPLETE, Roles.ENTRY, Roles.EDITCOMBOBOX]);
|
||||
|
||||
class AndroidPresentor {
|
||||
constructor() {
|
||||
this.type = "Android";
|
||||
@ -47,7 +41,11 @@ class AndroidPresentor {
|
||||
|
||||
let androidEvents = [];
|
||||
|
||||
const isExploreByTouch = aReason == Ci.nsIAccessiblePivot.REASON_POINT;
|
||||
let isExploreByTouch = (aReason == Ci.nsIAccessiblePivot.REASON_POINT &&
|
||||
Utils.AndroidSdkVersion >= 14);
|
||||
let focusEventType = (Utils.AndroidSdkVersion >= 16) ?
|
||||
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED :
|
||||
AndroidEvents.VIEW_FOCUSED;
|
||||
|
||||
if (isExploreByTouch) {
|
||||
// This isn't really used by TalkBack so this is a half-hearted attempt
|
||||
@ -56,19 +54,20 @@ class AndroidPresentor {
|
||||
}
|
||||
|
||||
if (aReason === Ci.nsIAccessiblePivot.REASON_TEXT) {
|
||||
const adjustedText = context.textAndAdjustedOffsets;
|
||||
if (Utils.AndroidSdkVersion >= 16) {
|
||||
let adjustedText = context.textAndAdjustedOffsets;
|
||||
|
||||
androidEvents.push({
|
||||
eventType: AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
text: [adjustedText.text],
|
||||
fromIndex: adjustedText.startOffset,
|
||||
toIndex: adjustedText.endOffset
|
||||
});
|
||||
androidEvents.push({
|
||||
eventType: AndroidEvents.VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
|
||||
text: [adjustedText.text],
|
||||
fromIndex: adjustedText.startOffset,
|
||||
toIndex: adjustedText.endOffset
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let info = this._infoFromContext(context);
|
||||
let eventType = isExploreByTouch ?
|
||||
AndroidEvents.VIEW_HOVER_ENTER :
|
||||
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED;
|
||||
AndroidEvents.VIEW_HOVER_ENTER : focusEventType;
|
||||
androidEvents.push({...info, eventType});
|
||||
}
|
||||
|
||||
@ -144,7 +143,17 @@ class AndroidPresentor {
|
||||
textSelectionChanged(aText, aStart, aEnd, aOldStart, aOldEnd, aIsFromUserInput) {
|
||||
let androidEvents = [];
|
||||
|
||||
if (aIsFromUserInput) {
|
||||
if (Utils.AndroidSdkVersion >= 14 && !aIsFromUserInput) {
|
||||
androidEvents.push({
|
||||
eventType: AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
|
||||
text: [aText],
|
||||
fromIndex: aStart,
|
||||
toIndex: aEnd,
|
||||
itemCount: aText.length
|
||||
});
|
||||
}
|
||||
|
||||
if (Utils.AndroidSdkVersion >= 16 && aIsFromUserInput) {
|
||||
let [from, to] = aOldStart < aStart ?
|
||||
[aOldStart, aStart] : [aStart, aOldStart];
|
||||
androidEvents.push({
|
||||
@ -153,14 +162,6 @@ class AndroidPresentor {
|
||||
fromIndex: from,
|
||||
toIndex: to
|
||||
});
|
||||
} else {
|
||||
androidEvents.push({
|
||||
eventType: AndroidEvents.VIEW_TEXT_SELECTION_CHANGED,
|
||||
text: [aText],
|
||||
fromIndex: aStart,
|
||||
toIndex: aEnd,
|
||||
itemCount: aText.length
|
||||
});
|
||||
}
|
||||
|
||||
return androidEvents;
|
||||
@ -224,19 +225,24 @@ class AndroidPresentor {
|
||||
viewportChanged(aWindow) {
|
||||
let currentContext = this.displayedAccessibles.get(aWindow);
|
||||
|
||||
if (Utils.AndroidSdkVersion < 14) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let events = [{
|
||||
eventType: AndroidEvents.VIEW_SCROLLED,
|
||||
text: [],
|
||||
scrollX: aWindow.scrollX,
|
||||
scrollY: aWindow.scrollY,
|
||||
maxScrollX: aWindow.scrollMaxX,
|
||||
maxScrollY: aWindow.scrollMaxY,
|
||||
maxScrollY: aWindow.scrollMaxY
|
||||
}];
|
||||
|
||||
if (currentContext) {
|
||||
if (Utils.AndroidSdkVersion >= 16 && currentContext) {
|
||||
let currentAcc = currentContext.accessibleForBounds;
|
||||
if (Utils.isAliveAndVisible(currentAcc)) {
|
||||
events.push({
|
||||
eventType: AndroidEvents.WINDOW_CONTENT_CHANGED,
|
||||
eventType: AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED,
|
||||
bounds: Utils.getBounds(currentAcc)
|
||||
});
|
||||
}
|
||||
@ -251,7 +257,9 @@ class AndroidPresentor {
|
||||
announce(aAnnouncement) {
|
||||
let localizedAnnouncement = Utils.localize(aAnnouncement).join(" ");
|
||||
return [{
|
||||
eventType: AndroidEvents.ANNOUNCEMENT,
|
||||
eventType: (Utils.AndroidSdkVersion >= 16) ?
|
||||
AndroidEvents.ANNOUNCEMENT :
|
||||
AndroidEvents.VIEW_TEXT_CHANGED,
|
||||
text: [localizedAnnouncement],
|
||||
addedCount: localizedAnnouncement.length,
|
||||
removedCount: 0,
|
||||
@ -287,8 +295,9 @@ class AndroidPresentor {
|
||||
}
|
||||
|
||||
_infoFromContext(aContext) {
|
||||
const state = Utils.getState(aContext.accessible);
|
||||
const info = {
|
||||
let state = Utils.getState(aContext.accessible);
|
||||
return {
|
||||
text: Utils.localize(UtteranceGenerator.genForContext(aContext)),
|
||||
bounds: aContext.bounds,
|
||||
focusable: state.contains(States.FOCUSABLE),
|
||||
focused: state.contains(States.FOCUSED),
|
||||
@ -297,22 +306,6 @@ class AndroidPresentor {
|
||||
checked: state.contains(States.CHECKED),
|
||||
editable: state.contains(States.EDITABLE),
|
||||
};
|
||||
|
||||
if (EDIT_TEXT_ROLES.has(aContext.accessible.role)) {
|
||||
let textAcc = aContext.accessible.QueryInterface(Ci.nsIAccessibleText);
|
||||
return {
|
||||
...info,
|
||||
className: "android.widget.EditText",
|
||||
hint: aContext.accessible.name,
|
||||
text: [textAcc.getText(0, -1)]
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...info,
|
||||
className: "android.view.View",
|
||||
text: Utils.localize(UtteranceGenerator.genForContext(aContext)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,9 @@
|
||||
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
|
||||
is(evt[0].editable, true, "focused item is editable");
|
||||
runner.eventTextMatches(evt[1],
|
||||
["Please refrain from Mayoneggs during this salmonella scare."]);
|
||||
is(evt[1].className, "android.widget.EditText", "editable class");
|
||||
["Text content test document",
|
||||
"Please refrain from Mayoneggs during this salmonella scare.",
|
||||
"text area"]);
|
||||
is(evt[1].focused, true, "a11y focused item is focused");
|
||||
is(evt[2].fromIndex, 0, "Correct fromIndex");
|
||||
is(evt[2].toIndex, 0, "Correct toIndex");
|
||||
|
@ -41,7 +41,7 @@
|
||||
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED,
|
||||
AndroidEvents.VIEW_TEXT_SELECTION_CHANGED);
|
||||
is(evt[0].editable, true, "focused item is editable");
|
||||
is(evt[1].className, "android.widget.EditText", "editable class");
|
||||
runner.eventTextMatches(evt[1], ["Text content test document", "entry"]);
|
||||
is(evt[1].focused, true, "a11y focused item is focused");
|
||||
is(evt[2].fromIndex, 0, "Caret at start (fromIndex)");
|
||||
is(evt[2].toIndex, 0, "Caret at start (toIndex)");
|
||||
|
@ -32,9 +32,10 @@
|
||||
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
|
||||
is(evt[0].editable, true, "focused item is editable");
|
||||
is(evt[1].focused, true, "a11y focused item is focused");
|
||||
is(evt[1].className, "android.widget.EditText", "editable class");
|
||||
runner.eventTextMatches(evt[1],
|
||||
["Please refrain from Mayoneggs during this salmonella scare."]);
|
||||
["Text content test document",
|
||||
"Please refrain from Mayoneggs during this salmonella scare.",
|
||||
"text area"]);
|
||||
|
||||
evt = await runner.moveNext("Simple",
|
||||
AndroidEvents.VIEW_FOCUSED,
|
||||
@ -45,7 +46,7 @@
|
||||
|
||||
evt = await runner.moveNext("Simple",
|
||||
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
|
||||
is(evt.className, "android.widget.EditText", "editable class");
|
||||
runner.eventTextMatches(evt, ["entry"]);
|
||||
runner.isFocused("html");
|
||||
|
||||
evt = await runner.activateCurrent(0,
|
||||
@ -65,7 +66,7 @@
|
||||
|
||||
evt = await runner.moveNext("Simple",
|
||||
AndroidEvents.VIEW_ACCESSIBILITY_FOCUSED);
|
||||
is(evt.className, "android.widget.EditText", "editable class");
|
||||
runner.eventTextMatches(evt, ["entry"]);
|
||||
runner.isFocused("html");
|
||||
|
||||
// XXX: TEXT_SELECTION_CHANGED should be fired here
|
||||
|
@ -33,12 +33,12 @@ import org.junit.runner.RunWith
|
||||
@WithDevToolsAPI
|
||||
class AccessibilityTest : BaseSessionTest() {
|
||||
lateinit var view: View
|
||||
val provider: AccessibilityNodeProvider get() = view.accessibilityNodeProvider
|
||||
val provider: AccessibilityNodeProvider get() = view.getAccessibilityNodeProvider()
|
||||
|
||||
// Given a child ID, return the virtual descendent ID.
|
||||
private fun getVirtualDescendantId(childId: Long): Int {
|
||||
try {
|
||||
val getVirtualDescendantIdMethod =
|
||||
var getVirtualDescendantIdMethod =
|
||||
AccessibilityNodeInfo::class.java.getMethod("getVirtualDescendantId", Long::class.java)
|
||||
return getVirtualDescendantIdMethod.invoke(null, childId) as Int
|
||||
} catch (ex: Exception) {
|
||||
@ -49,7 +49,7 @@ class AccessibilityTest : BaseSessionTest() {
|
||||
// Retrieve the virtual descendent ID of the event's source.
|
||||
private fun getSourceId(event: AccessibilityEvent): Int {
|
||||
try {
|
||||
val getSourceIdMethod =
|
||||
var getSourceIdMethod =
|
||||
AccessibilityRecord::class.java.getMethod("getSourceNodeId")
|
||||
return getVirtualDescendantId(getSourceIdMethod.invoke(event) as Long)
|
||||
} catch (ex: Exception) {
|
||||
@ -60,13 +60,11 @@ class AccessibilityTest : BaseSessionTest() {
|
||||
private interface EventDelegate {
|
||||
fun onAccessibilityFocused(event: AccessibilityEvent) { }
|
||||
fun onFocused(event: AccessibilityEvent) { }
|
||||
fun onTextSelectionChanged(event: AccessibilityEvent) { }
|
||||
fun onTextChanged(event: AccessibilityEvent) { }
|
||||
}
|
||||
|
||||
@Before fun setup() {
|
||||
// We initialize a view with a parent and grandparent so that the
|
||||
// accessibility events propagate up at least to the parent.
|
||||
// accessibility events propogate up at least to the parent.
|
||||
view = FrameLayout(InstrumentationRegistry.getTargetContext())
|
||||
FrameLayout(InstrumentationRegistry.getTargetContext()).addView(view)
|
||||
FrameLayout(InstrumentationRegistry.getTargetContext()).addView(view.parent as View)
|
||||
@ -81,11 +79,9 @@ class AccessibilityTest : BaseSessionTest() {
|
||||
EventDelegate::class,
|
||||
{ newDelegate -> (view.parent as View).setAccessibilityDelegate(object : View.AccessibilityDelegate() {
|
||||
override fun onRequestSendAccessibilityEvent(host: ViewGroup, child: View, event: AccessibilityEvent): Boolean {
|
||||
when (event.eventType) {
|
||||
when (event.getEventType()) {
|
||||
AccessibilityEvent.TYPE_VIEW_FOCUSED -> newDelegate.onFocused(event)
|
||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED -> newDelegate.onAccessibilityFocused(event)
|
||||
AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED -> newDelegate.onTextSelectionChanged(event)
|
||||
AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED -> newDelegate.onTextChanged(event)
|
||||
else -> {}
|
||||
}
|
||||
return false
|
||||
@ -101,9 +97,9 @@ class AccessibilityTest : BaseSessionTest() {
|
||||
|
||||
@Test fun testRootNode() {
|
||||
assertThat("provider is not null", provider, notNullValue())
|
||||
val node = provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID)
|
||||
var node = provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID)
|
||||
assertThat("Root node should have WebView class name",
|
||||
node.className.toString(), equalTo("android.webkit.WebView"))
|
||||
node.getClassName().toString(), equalTo("android.webkit.WebView"))
|
||||
}
|
||||
|
||||
@Test fun testPageLoad() {
|
||||
@ -127,8 +123,8 @@ class AccessibilityTest : BaseSessionTest() {
|
||||
@AssertCalled(count = 1)
|
||||
override fun onAccessibilityFocused(event: AccessibilityEvent) {
|
||||
nodeId = getSourceId(event)
|
||||
val node = provider.createAccessibilityNodeInfo(nodeId)
|
||||
assertThat("Text node should not be focusable", node.isFocusable, equalTo(false))
|
||||
var node = provider.createAccessibilityNodeInfo(nodeId)
|
||||
assertThat("Text node should not be focusable", node.isFocusable(), equalTo(false))
|
||||
}
|
||||
})
|
||||
|
||||
@ -139,29 +135,9 @@ class AccessibilityTest : BaseSessionTest() {
|
||||
@AssertCalled(count = 1)
|
||||
override fun onAccessibilityFocused(event: AccessibilityEvent) {
|
||||
nodeId = getSourceId(event)
|
||||
val node = provider.createAccessibilityNodeInfo(nodeId)
|
||||
assertThat("Entry node should be focusable", node.isFocusable, equalTo(true))
|
||||
var node = provider.createAccessibilityNodeInfo(nodeId)
|
||||
assertThat("Entry node should be focusable", node.isFocusable(), equalTo(true))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@Test fun testTextEntryNode() {
|
||||
sessionRule.session.loadString("<input aria-label='Name' value='Tobias'>", "text/html")
|
||||
sessionRule.waitForPageStop()
|
||||
|
||||
mainSession.evaluateJS("$('input').focus()")
|
||||
|
||||
sessionRule.waitUntilCalled(object : EventDelegate {
|
||||
@AssertCalled(count = 1)
|
||||
override fun onAccessibilityFocused(event: AccessibilityEvent) {
|
||||
val nodeId = getSourceId(event)
|
||||
val node = provider.createAccessibilityNodeInfo(nodeId)
|
||||
assertThat("Focused EditBox", node.className.toString(),
|
||||
equalTo("android.widget.EditText"))
|
||||
assertThat("Hint has field name",
|
||||
node.extras.getString("AccessibilityNodeInfo.hint"),
|
||||
equalTo("Name"))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,9 @@ import org.mozilla.gecko.PrefsHelper;
|
||||
import org.mozilla.gecko.util.BundleEventListener;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoBundle;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
@ -131,6 +133,7 @@ public class SessionAccessibility {
|
||||
info.setSource(mView, virtualDescendantId);
|
||||
info.setVisibleToUser(mView.isShown());
|
||||
info.setPackageName(GeckoAppShell.getApplicationContext().getPackageName());
|
||||
info.setClassName(mView.getClass().getName());
|
||||
info.setEnabled(true);
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
|
||||
@ -321,6 +324,7 @@ public class SessionAccessibility {
|
||||
private AccessibilityEvent obtainEvent(final int eventType, final int sourceId) {
|
||||
AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
|
||||
event.setPackageName(GeckoAppShell.getApplicationContext().getPackageName());
|
||||
event.setClassName(SessionAccessibility.class.getName());
|
||||
event.setSource(mView, sourceId);
|
||||
|
||||
return event;
|
||||
@ -333,8 +337,6 @@ public class SessionAccessibility {
|
||||
event.getText().add(textArray[i] != null ? textArray[i] : "");
|
||||
}
|
||||
|
||||
if (message.containsKey("className"))
|
||||
event.setClassName(message.getString("className"));
|
||||
event.setContentDescription(message.getString("description", ""));
|
||||
event.setEnabled(message.getBoolean("enabled", true));
|
||||
event.setChecked(message.getBoolean("checked"));
|
||||
@ -361,11 +363,9 @@ public class SessionAccessibility {
|
||||
node.setFocusable(message.getBoolean("focusable"));
|
||||
node.setFocused(message.getBoolean("focused"));
|
||||
if (Build.VERSION.SDK_INT >= 18) {
|
||||
node.setEditable(message.getBoolean("editable"));
|
||||
node.setEditable(message.getBoolean("editable"));
|
||||
}
|
||||
|
||||
node.setClassName(message.getString("className", "android.view.View"));
|
||||
|
||||
final String[] textArray = message.getStringArray("text");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (textArray != null && textArray.length > 0) {
|
||||
@ -382,29 +382,21 @@ public class SessionAccessibility {
|
||||
node.addAction(AccessibilityNodeInfo.ACTION_CLICK);
|
||||
}
|
||||
|
||||
if (message.containsKey("hint")) {
|
||||
Bundle bundle = node.getExtras();
|
||||
bundle.putCharSequence("AccessibilityNodeInfo.hint", message.getString("hint"));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBounds(final AccessibilityNodeInfo node, final GeckoBundle message) {
|
||||
final GeckoBundle bounds = message.getBundle("bounds");
|
||||
if (bounds == null) {
|
||||
return;
|
||||
if (bounds != null) {
|
||||
Rect screenBounds = new Rect(bounds.getInt("left"), bounds.getInt("top"),
|
||||
bounds.getInt("right"), bounds.getInt("bottom"));
|
||||
node.setBoundsInScreen(screenBounds);
|
||||
|
||||
final Matrix matrix = new Matrix();
|
||||
final float[] origin = new float[2];
|
||||
mSession.getClientToScreenMatrix(matrix);
|
||||
matrix.mapPoints(origin);
|
||||
|
||||
screenBounds.offset((int) -origin[0], (int) -origin[1]);
|
||||
node.setBoundsInParent(screenBounds);
|
||||
}
|
||||
|
||||
Rect screenBounds = new Rect(bounds.getInt("left"), bounds.getInt("top"),
|
||||
bounds.getInt("right"), bounds.getInt("bottom"));
|
||||
node.setBoundsInScreen(screenBounds);
|
||||
|
||||
final Matrix matrix = new Matrix();
|
||||
final float[] origin = new float[2];
|
||||
mSession.getClientToScreenMatrix(matrix);
|
||||
matrix.mapPoints(origin);
|
||||
|
||||
screenBounds.offset((int) -origin[0], (int) -origin[1]);
|
||||
node.setBoundsInParent(screenBounds);
|
||||
}
|
||||
|
||||
private void sendAccessibilityEvent(final GeckoBundle message) {
|
||||
@ -445,11 +437,6 @@ public class SessionAccessibility {
|
||||
populateNodeInfoFromJSON(mVirtualContentNode, message);
|
||||
}
|
||||
|
||||
if (mVirtualContentNode != null) {
|
||||
// Bounds for the virtual content can be updated from any event.
|
||||
updateBounds(mVirtualContentNode, message);
|
||||
}
|
||||
|
||||
final AccessibilityEvent accessibilityEvent = obtainEvent(eventType, eventSource);
|
||||
populateEventFromJSON(accessibilityEvent, message);
|
||||
((ViewParent) mView).requestSendAccessibilityEvent(mView, accessibilityEvent);
|
||||
|
Loading…
Reference in New Issue
Block a user