diff options
author | Charles Chen <clchen@google.com> | 2012-05-17 16:55:40 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-05-17 16:55:40 -0700 |
commit | c6015df128811a52faf918bd34d0d7296c8a6834 (patch) | |
tree | 3f2c8f6f6e072bd1f7072df6930a8284f87931e0 | |
parent | 9a9a041cb75a803856b22191db7e6bde7f1412e8 (diff) | |
parent | 6a62b77dfb95364e863b44662c13d6deec47f7d2 (diff) | |
download | frameworks_base-c6015df128811a52faf918bd34d0d7296c8a6834.zip frameworks_base-c6015df128811a52faf918bd34d0d7296c8a6834.tar.gz frameworks_base-c6015df128811a52faf918bd34d0d7296c8a6834.tar.bz2 |
Merge "Add actions to non-JavaScript accessibility handler." into jb-dev
-rw-r--r-- | core/java/android/webkit/AccessibilityInjector.java | 23 | ||||
-rw-r--r-- | core/java/android/webkit/AccessibilityInjectorFallback.java | 100 |
2 files changed, 99 insertions, 24 deletions
diff --git a/core/java/android/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java index bea97c5..cc490bd 100644 --- a/core/java/android/webkit/AccessibilityInjector.java +++ b/core/java/android/webkit/AccessibilityInjector.java @@ -63,7 +63,7 @@ class AccessibilityInjector { // Lazily loaded helper objects. private AccessibilityManager mAccessibilityManager; - private AccessibilityInjectorFallback mAccessibilityInjector; + private AccessibilityInjectorFallback mAccessibilityInjectorFallback; private JSONObject mAccessibilityJSONObject; // Whether the accessibility script has been injected into the current page. @@ -200,10 +200,9 @@ class AccessibilityInjector { if (mAccessibilityScriptInjected) { return sendActionToAndroidVox(action, arguments); } - - if (mAccessibilityInjector != null) { - // TODO: Implement actions for non-JS handler. - return false; + + if (mAccessibilityInjectorFallback != null) { + return mAccessibilityInjectorFallback.performAccessibilityAction(action, arguments); } return false; @@ -238,11 +237,11 @@ class AccessibilityInjector { return true; } - if (mAccessibilityInjector != null) { + if (mAccessibilityInjectorFallback != null) { // if an accessibility injector is present (no JavaScript enabled or // the site opts out injecting our JavaScript screen reader) we let // it decide whether to act on and consume the event. - return mAccessibilityInjector.onKeyEvent(event); + return mAccessibilityInjectorFallback.onKeyEvent(event); } return false; @@ -255,8 +254,8 @@ class AccessibilityInjector { * @param selectionString The selection string. */ public void handleSelectionChangedIfNecessary(String selectionString) { - if (mAccessibilityInjector != null) { - mAccessibilityInjector.onSelectionStringChange(selectionString); + if (mAccessibilityInjectorFallback != null) { + mAccessibilityInjectorFallback.onSelectionStringChange(selectionString); } } @@ -304,10 +303,10 @@ class AccessibilityInjector { * {@code false} to disable it. */ private void toggleFallbackAccessibilityInjector(boolean enabled) { - if (enabled && (mAccessibilityInjector == null)) { - mAccessibilityInjector = new AccessibilityInjectorFallback(mWebViewClassic); + if (enabled && (mAccessibilityInjectorFallback == null)) { + mAccessibilityInjectorFallback = new AccessibilityInjectorFallback(mWebViewClassic); } else { - mAccessibilityInjector = null; + mAccessibilityInjectorFallback = null; } } diff --git a/core/java/android/webkit/AccessibilityInjectorFallback.java b/core/java/android/webkit/AccessibilityInjectorFallback.java index 9bf52ca..4d9c26c 100644 --- a/core/java/android/webkit/AccessibilityInjectorFallback.java +++ b/core/java/android/webkit/AccessibilityInjectorFallback.java @@ -16,6 +16,7 @@ package android.webkit; +import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; @@ -23,6 +24,7 @@ import android.util.Log; import android.view.KeyEvent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.webkit.WebViewCore.EventHub; import java.util.ArrayList; @@ -48,7 +50,7 @@ import java.util.Stack; * {@link #setCurrentAxis(int, boolean, String)}, or * {@link #traverseCurrentAxis(int, boolean, String)} * {@link #traverseGivenAxis(int, int, boolean, String)} - * {@link #prefromAxisTransition(int, int, boolean, String)} + * {@link #performAxisTransition(int, int, boolean, String)} * referred via the values of: * {@link #ACTION_SET_CURRENT_AXIS}, * {@link #ACTION_TRAVERSE_CURRENT_AXIS}, @@ -72,15 +74,30 @@ class AccessibilityInjectorFallback { private static final int ACTION_PERFORM_AXIS_TRANSITION = 3; private static final int ACTION_TRAVERSE_DEFAULT_WEB_VIEW_BEHAVIOR_AXIS = 4; - // the default WebView behavior abstracted as a navigation axis + // WebView navigation axes from WebViewCore.h, plus an additional axis for + // the default behavior. + private static final int NAVIGATION_AXIS_CHARACTER = 0; + private static final int NAVIGATION_AXIS_WORD = 1; + private static final int NAVIGATION_AXIS_SENTENCE = 2; + @SuppressWarnings("unused") + private static final int NAVIGATION_AXIS_HEADING = 3; + private static final int NAVIGATION_AXIS_SIBLING = 5; + @SuppressWarnings("unused") + private static final int NAVIGATION_AXIS_PARENT_FIRST_CHILD = 5; + private static final int NAVIGATION_AXIS_DOCUMENT = 6; private static final int NAVIGATION_AXIS_DEFAULT_WEB_VIEW_BEHAVIOR = 7; + // WebView navigation directions from WebViewCore.h. + private static final int NAVIGATION_DIRECTION_BACKWARD = 0; + private static final int NAVIGATION_DIRECTION_FORWARD = 1; + // these are the same for all instances so make them process wide private static ArrayList<AccessibilityWebContentKeyBinding> sBindings = new ArrayList<AccessibilityWebContentKeyBinding>(); // handle to the WebViewClassic this injector is associated with. private final WebViewClassic mWebView; + private final WebView mWebViewInternal; // events scheduled for sending as soon as we receive the selected text private final Stack<AccessibilityEvent> mScheduledEventStack = new Stack<AccessibilityEvent>(); @@ -104,6 +121,7 @@ class AccessibilityInjectorFallback { */ public AccessibilityInjectorFallback(WebViewClassic webView) { mWebView = webView; + mWebViewInternal = mWebView.getWebView(); ensureWebContentKeyBindings(); } @@ -176,7 +194,7 @@ class AccessibilityInjectorFallback { int fromAxis = binding.getFirstArgument(i); int toAxis = binding.getSecondArgument(i); sendEvent = (binding.getThirdArgument(i) == 1); - prefromAxisTransition(fromAxis, toAxis, sendEvent, contentDescription); + performAxisTransition(fromAxis, toAxis, sendEvent, contentDescription); mLastDownEventHandled = true; break; case ACTION_TRAVERSE_DEFAULT_WEB_VIEW_BEHAVIOR_AXIS: @@ -214,7 +232,8 @@ class AccessibilityInjectorFallback { private void setCurrentAxis(int axis, boolean sendEvent, String contentDescription) { mCurrentAxis = axis; if (sendEvent) { - AccessibilityEvent event = getPartialyPopulatedAccessibilityEvent(); + final AccessibilityEvent event = getPartialyPopulatedAccessibilityEvent( + AccessibilityEvent.TYPE_ANNOUNCEMENT); event.getText().add(String.valueOf(axis)); event.setContentDescription(contentDescription); sendAccessibilityEvent(event); @@ -229,7 +248,7 @@ class AccessibilityInjectorFallback { * @param sendEvent Flag if to send an event to announce successful transition. * @param contentDescription A description of the performed action. */ - private void prefromAxisTransition(int fromAxis, int toAxis, boolean sendEvent, + private void performAxisTransition(int fromAxis, int toAxis, boolean sendEvent, String contentDescription) { if (mCurrentAxis == fromAxis) { setCurrentAxis(toAxis, sendEvent, contentDescription); @@ -249,6 +268,62 @@ class AccessibilityInjectorFallback { String contentDescription) { return traverseGivenAxis(direction, mCurrentAxis, sendEvent, contentDescription); } + + boolean performAccessibilityAction(int action, Bundle arguments) { + switch (action) { + case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: + case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: + final int direction = getDirectionForAction(action); + final int axis = getAxisForGranularity(arguments.getInt( + AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT)); + return traverseGivenAxis(direction, axis, true, null); + default: + return false; + } + } + + /** + * Returns the {@link WebView}-defined direction for the given + * {@link AccessibilityNodeInfo}-defined action. + * + * @param action An accessibility action identifier. + * @return A web view navigation direction. + */ + private static int getDirectionForAction(int action) { + switch (action) { + case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: + return NAVIGATION_DIRECTION_FORWARD; + case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: + return NAVIGATION_DIRECTION_BACKWARD; + default: + return -1; + } + } + + /** + * Returns the {@link WebView}-defined axis for the given + * {@link AccessibilityNodeInfo}-defined granularity. + * + * @param granularity An accessibility granularity identifier. + * @return A web view navigation axis. + */ + private static int getAxisForGranularity(int granularity) { + switch (granularity) { + case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: + return NAVIGATION_AXIS_CHARACTER; + case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: + return NAVIGATION_AXIS_WORD; + case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE: + return NAVIGATION_AXIS_SENTENCE; + case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: + // TODO: Figure out what nextSibling() actually means. + return NAVIGATION_AXIS_SIBLING; + case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE: + return NAVIGATION_AXIS_DOCUMENT; + default: + return -1; + } + } /** * Traverse the document along the given navigation axis. @@ -268,7 +343,8 @@ class AccessibilityInjectorFallback { AccessibilityEvent event = null; if (sendEvent) { - event = getPartialyPopulatedAccessibilityEvent(); + event = getPartialyPopulatedAccessibilityEvent( + AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY); // the text will be set upon receiving the selection string event.setContentDescription(contentDescription); } @@ -296,8 +372,10 @@ class AccessibilityInjectorFallback { return; } AccessibilityEvent event = mScheduledEventStack.pop(); - if (event != null) { + if ((event != null) && (selectionString != null)) { event.getText().add(selectionString); + event.setFromIndex(0); + event.setToIndex(selectionString.length()); sendAccessibilityEvent(event); } } @@ -323,11 +401,9 @@ class AccessibilityInjectorFallback { * @return An accessibility event whose members are populated except its * text and content description. */ - private AccessibilityEvent getPartialyPopulatedAccessibilityEvent() { - AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SELECTED); - event.setClassName(mWebView.getClass().getName()); - event.setPackageName(mWebView.getContext().getPackageName()); - event.setEnabled(mWebView.getWebView().isEnabled()); + private AccessibilityEvent getPartialyPopulatedAccessibilityEvent(int eventType) { + AccessibilityEvent event = AccessibilityEvent.obtain(eventType); + mWebViewInternal.onInitializeAccessibilityEvent(event); return event; } |