Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java

Issue 2609313002: Revert of Android accessibility: automatically focus links (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/accessibility/browser_accessibility_manager_android.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.content.browser.accessibility; 5 package org.chromium.content.browser.accessibility;
6 6
7 import android.annotation.SuppressLint; 7 import android.annotation.SuppressLint;
8 import android.content.Context; 8 import android.content.Context;
9 import android.graphics.Rect; 9 import android.graphics.Rect;
10 import android.os.Build; 10 import android.os.Build;
(...skipping 19 matching lines...) Expand all
30 import java.util.List; 30 import java.util.List;
31 import java.util.Locale; 31 import java.util.Locale;
32 32
33 /** 33 /**
34 * Native accessibility for a {@link ContentViewCore}. 34 * Native accessibility for a {@link ContentViewCore}.
35 */ 35 */
36 @JNINamespace("content") 36 @JNINamespace("content")
37 public class BrowserAccessibilityManager { 37 public class BrowserAccessibilityManager {
38 private static final String TAG = "BrowserAccessibilityManager"; 38 private static final String TAG = "BrowserAccessibilityManager";
39 39
40 private static final int WINDOW_CONTENT_CHANGED_DELAY_MS = 500;
41 private static final int ACCESSIBILITY_FOCUS_LOCATION_CHANGED_DELAY_MS = 100 ;
42
43 // Constants from AccessibilityNodeInfo defined in the K SDK. 40 // Constants from AccessibilityNodeInfo defined in the K SDK.
44 private static final int ACTION_COLLAPSE = 0x00080000; 41 private static final int ACTION_COLLAPSE = 0x00080000;
45 private static final int ACTION_EXPAND = 0x00040000; 42 private static final int ACTION_EXPAND = 0x00040000;
46 43
47 // Constants from AccessibilityNodeInfo defined in the L SDK. 44 // Constants from AccessibilityNodeInfo defined in the L SDK.
48 private static final int ACTION_SET_TEXT = 0x200000; 45 private static final int ACTION_SET_TEXT = 0x200000;
49 private static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE = 46 private static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
50 "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE"; 47 "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
48 private static final int WINDOW_CONTENT_CHANGED_DELAY_MS = 500;
51 49
52 // Constants from AccessibilityNodeInfo defined in the M SDK. 50 // Constants from AccessibilityNodeInfo defined in the M SDK.
53 // Source: https://developer.android.com/reference/android/R.id.html 51 // Source: https://developer.android.com/reference/android/R.id.html
54 protected static final int ACTION_CONTEXT_CLICK = 0x0102003c; 52 protected static final int ACTION_CONTEXT_CLICK = 0x0102003c;
55 protected static final int ACTION_SHOW_ON_SCREEN = 0x01020036; 53 protected static final int ACTION_SHOW_ON_SCREEN = 0x01020036;
56 protected static final int ACTION_SCROLL_UP = 0x01020038; 54 protected static final int ACTION_SCROLL_UP = 0x01020038;
57 protected static final int ACTION_SCROLL_DOWN = 0x0102003a; 55 protected static final int ACTION_SCROLL_DOWN = 0x0102003a;
58 protected static final int ACTION_SCROLL_LEFT = 0x01020039; 56 protected static final int ACTION_SCROLL_LEFT = 0x01020039;
59 protected static final int ACTION_SCROLL_RIGHT = 0x0102003b; 57 protected static final int ACTION_SCROLL_RIGHT = 0x0102003b;
60 58
61 private final AccessibilityNodeProvider mAccessibilityNodeProvider; 59 private final AccessibilityNodeProvider mAccessibilityNodeProvider;
62 private ContentViewCore mContentViewCore; 60 private ContentViewCore mContentViewCore;
63 private final AccessibilityManager mAccessibilityManager; 61 private final AccessibilityManager mAccessibilityManager;
64 private final RenderCoordinates mRenderCoordinates; 62 private final RenderCoordinates mRenderCoordinates;
65 private long mNativeObj; 63 private long mNativeObj;
66 private Rect mAccessibilityFocusRect; 64 private Rect mAccessibilityFocusRect;
67 private boolean mIsHovering; 65 private boolean mIsHovering;
68 private int mLastHoverId = View.NO_ID; 66 private int mLastHoverId = View.NO_ID;
69 protected int mCurrentRootId; 67 protected int mCurrentRootId;
70 private final int[] mTempLocation = new int[2]; 68 private final int[] mTempLocation = new int[2];
71 private final ViewGroup mView; 69 private final ViewGroup mView;
72 private boolean mUserHasTouchExplored; 70 private boolean mUserHasTouchExplored;
73 private boolean mPendingScrollToMakeNodeVisible; 71 private boolean mPendingScrollToMakeNodeVisible;
74 private boolean mNotifyFrameInfoInitializedCalled; 72 private boolean mNotifyFrameInfoInitializedCalled;
75 private int mSelectionGranularity; 73 private int mSelectionGranularity;
76 private int mSelectionStartIndex; 74 private int mSelectionStartIndex;
77 private int mSelectionEndIndex; 75 private int mSelectionEndIndex;
78 protected int mAccessibilityFocusId; 76 protected int mAccessibilityFocusId;
79 private Runnable mSendWindowContentChangedRunnable; 77 private Runnable mSendWindowContentChangedRunnable;
80 private Runnable mAccessibilityFocusLocationChangedRunnable;
81 78
82 /** 79 /**
83 * Create a BrowserAccessibilityManager object, which is owned by the C++ 80 * Create a BrowserAccessibilityManager object, which is owned by the C++
84 * BrowserAccessibilityManagerAndroid instance, and connects to the content view. 81 * BrowserAccessibilityManagerAndroid instance, and connects to the content view.
85 * @param nativeBrowserAccessibilityManagerAndroid A pointer to the counterp art native 82 * @param nativeBrowserAccessibilityManagerAndroid A pointer to the counterp art native
86 * C++ object that owns this object. 83 * C++ object that owns this object.
87 * @param contentViewCore The content view that this object provides accessi bility for. 84 * @param contentViewCore The content view that this object provides accessi bility for.
88 */ 85 */
89 @CalledByNative 86 @CalledByNative
90 private static BrowserAccessibilityManager create(long nativeBrowserAccessib ilityManagerAndroid, 87 private static BrowserAccessibilityManager create(long nativeBrowserAccessib ilityManagerAndroid,
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 } 230 }
234 return true; 231 return true;
235 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: 232 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
236 // ALWAYS respond with TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED whe ther we thought 233 // ALWAYS respond with TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED whe ther we thought
237 // it had focus or not, so that the Android framework cache is c orrect. 234 // it had focus or not, so that the Android framework cache is c orrect.
238 sendAccessibilityEvent(virtualViewId, 235 sendAccessibilityEvent(virtualViewId,
239 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED ); 236 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED );
240 if (mAccessibilityFocusId == virtualViewId) { 237 if (mAccessibilityFocusId == virtualViewId) {
241 mAccessibilityFocusId = View.NO_ID; 238 mAccessibilityFocusId = View.NO_ID;
242 mAccessibilityFocusRect = null; 239 mAccessibilityFocusRect = null;
243 // If we had a pending callback to update the location of th e previous object
244 // with accessibility focus, remove it.
245 if (mAccessibilityFocusLocationChangedRunnable != null) {
246 mView.removeCallbacks(mAccessibilityFocusLocationChanged Runnable);
247 mAccessibilityFocusLocationChangedRunnable = null;
248 }
249 } 240 }
250 return true; 241 return true;
251 case AccessibilityNodeInfo.ACTION_CLICK: 242 case AccessibilityNodeInfo.ACTION_CLICK:
252 nativeClick(mNativeObj, virtualViewId); 243 nativeClick(mNativeObj, virtualViewId);
253 return true; 244 return true;
254 case AccessibilityNodeInfo.ACTION_FOCUS: 245 case AccessibilityNodeInfo.ACTION_FOCUS:
255 nativeFocus(mNativeObj, virtualViewId); 246 nativeFocus(mNativeObj, virtualViewId);
256 return true; 247 return true;
257 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: 248 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS:
258 nativeBlur(mNativeObj); 249 nativeBlur(mNativeObj);
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 530
540 private boolean moveAccessibilityFocusToId(int newAccessibilityFocusId) { 531 private boolean moveAccessibilityFocusToId(int newAccessibilityFocusId) {
541 if (newAccessibilityFocusId == mAccessibilityFocusId) return false; 532 if (newAccessibilityFocusId == mAccessibilityFocusId) return false;
542 533
543 mAccessibilityFocusId = newAccessibilityFocusId; 534 mAccessibilityFocusId = newAccessibilityFocusId;
544 mAccessibilityFocusRect = null; 535 mAccessibilityFocusRect = null;
545 mSelectionGranularity = 0; 536 mSelectionGranularity = 0;
546 mSelectionStartIndex = 0; 537 mSelectionStartIndex = 0;
547 mSelectionEndIndex = 0; 538 mSelectionEndIndex = 0;
548 539
549 // If we had a pending callback to update the location of the previous o bject with
550 // accessibility focus, remove it.
551 if (mAccessibilityFocusLocationChangedRunnable != null) {
552 mView.removeCallbacks(mAccessibilityFocusLocationChangedRunnable);
553 mAccessibilityFocusLocationChangedRunnable = null;
554 }
555
556 // Call nativeSetAccessibilityFocus. For the most part Chrome doesn't ha ve a
557 // concept of accessibility focus, but we do two things: (1) auto-focus certain
558 // roles like links when they get accessibility focus and (2) load inlin e text boxes
559 // for nodes when they get accessibility focus since inline text boxes a re expensive
560 // to load and on Android they're only needed for nodes that have input focus or
561 // accessibility focus.
562 //
563 // Calling nativeSetAccessibilityFocus will asynchronously load inline t ext boxes for 540 // Calling nativeSetAccessibilityFocus will asynchronously load inline t ext boxes for
564 // this node and its subtree. If accessibility focus is on anything othe r than 541 // this node and its subtree. If accessibility focus is on anything othe r than
565 // the root, do it - otherwise set it to -1 so we don't load inline text boxes 542 // the root, do it - otherwise set it to -1 so we don't load inline text boxes
566 // for the whole subtree of the root. 543 // for the whole subtree of the root.
567 if (mAccessibilityFocusId == mCurrentRootId) { 544 if (mAccessibilityFocusId == mCurrentRootId) {
568 nativeSetAccessibilityFocus(mNativeObj, -1); 545 nativeSetAccessibilityFocus(mNativeObj, -1);
569 } else { 546 } else {
570 nativeSetAccessibilityFocus(mNativeObj, mAccessibilityFocusId); 547 nativeSetAccessibilityFocus(mNativeObj, mAccessibilityFocusId);
571 } 548 }
572 549
573 sendAccessibilityEvent(mAccessibilityFocusId, 550 sendAccessibilityEvent(mAccessibilityFocusId,
574 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); 551 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
575 return true; 552 return true;
576 } 553 }
577 554
578 private void moveAccessibilityFocusToIdAndRefocusIfNeeded(int newAccessibili tyFocusId) { 555 private void moveAccessibilityFocusToIdAndRefocusIfNeeded(int newAccessibili tyFocusId) {
579 // Work around a bug in the Android framework where it doesn't fully upd ate the object 556 // Work around a bug in the Android framework where it doesn't fully upd ate the object
580 // with accessibility focus even if you send it a WINDOW_CONTENT_CHANGED . To work around 557 // with accessibility focus even if you send it a WINDOW_CONTENT_CHANGED . To work around
581 // this, clear focus and then set focus again. 558 // this, clear focus and then set focus again.
582 if (newAccessibilityFocusId == mAccessibilityFocusId) { 559 if (newAccessibilityFocusId == mAccessibilityFocusId) {
583 sendAccessibilityEvent(newAccessibilityFocusId, 560 sendAccessibilityEvent(newAccessibilityFocusId,
584 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); 561 AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
585 mAccessibilityFocusId = View.NO_ID; 562 mAccessibilityFocusId = View.NO_ID;
586 } 563 }
587 564
588 moveAccessibilityFocusToId(newAccessibilityFocusId); 565 moveAccessibilityFocusToId(newAccessibilityFocusId);
589 } 566 }
590 567
591 /** 568 /**
592 * Work around a bug in the Android framework where if the object with acces sibility
593 * focus moves, the accessibility focus rect is not updated - both the visu al highlight,
594 * and the location on the screen that's clicked if you double-tap. To work around this,
595 * when we know the object with accessibility focus moved, move focus away a nd then
596 * move focus right back to it, which tricks Android into updating its bound s.
597 *
598 * Do this after a short delay because sometimes the change to the object wi th accessibility
599 * focus happens just before navigating somewhere else.
600 */
601 private void updateAccessibilityFocusLocationAfterDelay() {
602 if (mNativeObj == 0) return;
603
604 if (mAccessibilityFocusLocationChangedRunnable != null) return;
605
606 mAccessibilityFocusLocationChangedRunnable = new Runnable() {
607 @Override
608 public void run() {
609 updateAccessibilityFocusLocation();
610 }
611 };
612
613 mView.postDelayed(mAccessibilityFocusLocationChangedRunnable,
614 ACCESSIBILITY_FOCUS_LOCATION_CHANGED_DELAY_MS);
615 }
616
617 /**
618 * See updateAccessibilityFocusLocationAfterDelay for details.
619 */
620 private void updateAccessibilityFocusLocation() {
621 // This can be called from a timeout, so we need to make sure we're stil l valid.
622 if (mNativeObj == 0 || mContentViewCore == null || mView == null) return ;
623
624 if (mAccessibilityFocusLocationChangedRunnable != null) {
625 mView.removeCallbacks(mAccessibilityFocusLocationChangedRunnable);
626 mAccessibilityFocusLocationChangedRunnable = null;
627 }
628
629 moveAccessibilityFocusToIdAndRefocusIfNeeded(mAccessibilityFocusId);
630 }
631
632 /**
633 * Send a WINDOW_CONTENT_CHANGED event after a short delay. This helps throt tle such 569 * Send a WINDOW_CONTENT_CHANGED event after a short delay. This helps throt tle such
634 * events from firing too quickly during animations, for example. 570 * events from firing too quickly during animations, for example.
635 */ 571 */
636 @CalledByNative 572 @CalledByNative
637 private void sendDelayedWindowContentChangedEvent() { 573 private void sendDelayedWindowContentChangedEvent() {
638 if (mNativeObj == 0) return; 574 if (mNativeObj == 0) return;
639 575
640 if (mSendWindowContentChangedRunnable != null) return; 576 if (mSendWindowContentChangedRunnable != null) return;
641 577
642 mSendWindowContentChangedRunnable = new Runnable() { 578 mSendWindowContentChangedRunnable = new Runnable() {
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after
1058 rect.offset(viewLocation[0], viewLocation[1]); 994 rect.offset(viewLocation[0], viewLocation[1]);
1059 995
1060 // Clip the node's bounding rect to the viewport bounds. 996 // Clip the node's bounding rect to the viewport bounds.
1061 int viewportRectTop = viewLocation[1] + (int) mRenderCoordinates.getCont entOffsetYPix(); 997 int viewportRectTop = viewLocation[1] + (int) mRenderCoordinates.getCont entOffsetYPix();
1062 int viewportRectBottom = viewportRectTop + mContentViewCore.getViewportH eightPix(); 998 int viewportRectBottom = viewportRectTop + mContentViewCore.getViewportH eightPix();
1063 if (rect.top < viewportRectTop) rect.top = viewportRectTop; 999 if (rect.top < viewportRectTop) rect.top = viewportRectTop;
1064 if (rect.bottom > viewportRectBottom) rect.bottom = viewportRectBottom; 1000 if (rect.bottom > viewportRectBottom) rect.bottom = viewportRectBottom;
1065 1001
1066 node.setBoundsInScreen(rect); 1002 node.setBoundsInScreen(rect);
1067 1003
1068 // If this is the node with accessibility focus, ensure that its locatio n on-screen 1004 // Work around a bug in the Android framework where if the object with a ccessibility
1069 // is up-to-date. 1005 // focus moves, the accessibility focus rect is not updated - both the v isual highlight,
1006 // and the location on the screen that's clicked if you double-tap. To w ork around this,
1007 // when we know the object with accessibility focus moved, move focus aw ay and then
1008 // move focus right back to it, which tricks Android into updating its b ounds.
1070 if (virtualViewId == mAccessibilityFocusId && virtualViewId != mCurrentR ootId) { 1009 if (virtualViewId == mAccessibilityFocusId && virtualViewId != mCurrentR ootId) {
1071 if (mAccessibilityFocusRect == null) { 1010 if (mAccessibilityFocusRect == null) {
1072 mAccessibilityFocusRect = rect; 1011 mAccessibilityFocusRect = rect;
1073 } else if (!mAccessibilityFocusRect.equals(rect)) { 1012 } else if (!mAccessibilityFocusRect.equals(rect)) {
1074 mAccessibilityFocusRect = rect; 1013 mAccessibilityFocusRect = rect;
1075 updateAccessibilityFocusLocationAfterDelay(); 1014 moveAccessibilityFocusToIdAndRefocusIfNeeded(virtualViewId);
1076 } 1015 }
1077 } 1016 }
1078 } 1017 }
1079 1018
1080 @CalledByNative 1019 @CalledByNative
1081 protected void setAccessibilityNodeInfoKitKatAttributes(AccessibilityNodeInf o node, 1020 protected void setAccessibilityNodeInfoKitKatAttributes(AccessibilityNodeInf o node,
1082 boolean isRoot, boolean isEditableText, String roleDescription) { 1021 boolean isRoot, boolean isEditableText, String roleDescription) {
1083 // Requires KitKat or higher. 1022 // Requires KitKat or higher.
1084 } 1023 }
1085 1024
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 long nativeBrowserAccessibilityManagerAndroid, int id); 1209 long nativeBrowserAccessibilityManagerAndroid, int id);
1271 private native boolean nativeIsSlider( 1210 private native boolean nativeIsSlider(
1272 long nativeBrowserAccessibilityManagerAndroid, int id); 1211 long nativeBrowserAccessibilityManagerAndroid, int id);
1273 private native boolean nativeScroll( 1212 private native boolean nativeScroll(
1274 long nativeBrowserAccessibilityManagerAndroid, int id, int direction ); 1213 long nativeBrowserAccessibilityManagerAndroid, int id, int direction );
1275 protected native String nativeGetSupportedHtmlElementTypes( 1214 protected native String nativeGetSupportedHtmlElementTypes(
1276 long nativeBrowserAccessibilityManagerAndroid); 1215 long nativeBrowserAccessibilityManagerAndroid);
1277 private native void nativeShowContextMenu( 1216 private native void nativeShowContextMenu(
1278 long nativeBrowserAccessibilityManagerAndroid, int id); 1217 long nativeBrowserAccessibilityManagerAndroid, int id);
1279 } 1218 }
OLDNEW
« no previous file with comments | « content/browser/accessibility/browser_accessibility_manager_android.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698