Bug 1396951 - 4. Pass in GeckoView instance when sending a11y event; r?snorp draft
authorJim Chen <nchen@mozilla.com>
Fri, 22 Sep 2017 14:35:23 -0400
changeset 669225 f11aa972a55795d021c0229089b900ad2c660bc3
parent 669224 27aa264d8a3493f6a2df6a38a5394991825ad995
child 669226 8fbfeb2d7d6de268e39d5caa0b4906add6a8964c
push id81260
push userbmo:nchen@mozilla.com
push dateFri, 22 Sep 2017 18:35:47 +0000
reviewerssnorp
bugs1396951
milestone58.0a1
Bug 1396951 - 4. Pass in GeckoView instance when sending a11y event; r?snorp Pass in a `GeckoView` instance when sending a11y events so we're not dependent on `GeckoAppShell.getLayerView()`. However, there's likely more work to be done to make a11y work for any GeckoView. MozReview-Commit-ID: DBeDOX5c3qY
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAccessibility.java
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -668,17 +668,17 @@ public abstract class GeckoApp extends G
                     getSharedPreferences().edit().putInt(PREFS_CRASHED_COUNT, 0).apply();
                 }
             }, STARTUP_PHASE_DURATION_MS);
 
         } else if ("Accessibility:Ready".equals(event)) {
             GeckoAccessibility.updateAccessibilitySettings(this);
 
         } else if ("Accessibility:Event".equals(event)) {
-            GeckoAccessibility.sendAccessibilityEvent(message);
+            GeckoAccessibility.sendAccessibilityEvent(mLayerView, message);
 
         } else if ("Bookmark:Insert".equals(event)) {
             final BrowserDB db = BrowserDB.from(getProfile());
             final boolean bookmarkAdded = db.addBookmark(
                     getContentResolver(), message.getString("title"), message.getString("url"));
             final int resId = bookmarkAdded ? R.string.bookmark_added
                                             : R.string.bookmark_already_added;
             ThreadUtils.postToUiThread(new Runnable() {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAccessibility.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAccessibility.java
@@ -2,18 +2,16 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import org.json.JSONException;
 import org.json.JSONObject;
-import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.gfx.LayerView;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
 import android.util.Log;
@@ -105,30 +103,32 @@ public class GeckoAccessibility {
             // Accessibility is off.
         }
     }
 
     public static boolean isEnabled() {
         return sEnabled;
     }
 
-    public static void sendAccessibilityEvent(final GeckoBundle message) {
+    public static void sendAccessibilityEvent(final GeckoView view,
+                                              final GeckoBundle message) {
         if (!sEnabled)
             return;
 
         final int eventType = message.getInt("eventType", -1);
         if (eventType < 0) {
             Log.e(LOGTAG, "No accessibility event type provided");
             return;
         }
 
-        sendAccessibilityEvent(message, eventType);
+        sendAccessibilityEvent(view, message, eventType);
     }
 
-    public static void sendAccessibilityEvent(final GeckoBundle message, final int eventType) {
+    public static void sendAccessibilityEvent(final GeckoView view, final GeckoBundle message,
+                                              final int eventType) {
         if (!sEnabled)
             return;
 
         final String exitView = message.getString("exitView", "");
         if (exitView.equals("moveNext")) {
             sCurrentNode = VIRTUAL_ENTRY_POINT_AFTER;
         } else if (exitView.equals("movePrevious")) {
             sCurrentNode = VIRTUAL_ENTRY_POINT_BEFORE;
@@ -143,20 +143,16 @@ public class GeckoAccessibility {
                     @Override
                     public void run() {
                         sendDirectAccessibilityEvent(eventType, message);
                 }
             });
         } else {
             // In Jelly Bean we populate an AccessibilityNodeInfo with the minimal amount of data to have
             // it work with TalkBack.
-            final LayerView view = GeckoAppShell.getLayerView();
-            if (view == null)
-                return;
-
             if (sVirtualCursorNode == null) {
                 sVirtualCursorNode = AccessibilityNodeInfo.obtain(view, VIRTUAL_CURSOR_POSITION);
             }
             sVirtualCursorNode.setEnabled(message.getBoolean("enabled", true));
             sVirtualCursorNode.setClickable(message.getBoolean("clickable"));
             sVirtualCursorNode.setCheckable(message.getBoolean("checkable"));
             sVirtualCursorNode.setChecked(message.getBoolean("checked"));
             sVirtualCursorNode.setPassword(message.getBoolean("password"));
@@ -261,17 +257,22 @@ public class GeckoAccessibility {
             EventDispatcher.getInstance().dispatch("Accessibility:Focus", data);
         }
     }
 
     public static class GeckoAccessibilityDelegate extends View.AccessibilityDelegate {
         AccessibilityNodeProvider mAccessibilityNodeProvider;
 
         @Override
-        public AccessibilityNodeProvider getAccessibilityNodeProvider(final View host) {
+        public AccessibilityNodeProvider getAccessibilityNodeProvider(final View hostView) {
+            if (!(hostView instanceof GeckoView)) {
+                return super.getAccessibilityNodeProvider(hostView);
+            }
+            final GeckoView host = (GeckoView) hostView;
+
             if (mAccessibilityNodeProvider == null)
                 // The accessibility node structure for web content consists of 3 LayerView child nodes:
                 // 1. VIRTUAL_ENTRY_POINT_BEFORE: Represents the entry point before the LayerView.
                 // 2. VIRTUAL_CURSOR_POSITION: Represents the current position of the virtual cursor.
                 // 3. VIRTUAL_ENTRY_POINT_AFTER: Represents the entry point after the LayerView.
                 mAccessibilityNodeProvider = new AccessibilityNodeProvider() {
                         @Override
                         public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualDescendantId) {
@@ -314,17 +315,17 @@ public class GeckoAccessibility {
                         }
 
                         @Override
                         public boolean performAction (int virtualViewId, int action, Bundle arguments) {
                             if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
                                 // The accessibility focus is permanently on the middle node, VIRTUAL_CURSOR_POSITION.
                                 // When we enter the view forward or backward we just ask Gecko to get focus, keeping the current position.
                                 if (virtualViewId == VIRTUAL_CURSOR_POSITION && sHoverEnter != null) {
-                                    GeckoAccessibility.sendAccessibilityEvent(sHoverEnter, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
+                                    GeckoAccessibility.sendAccessibilityEvent(host, sHoverEnter, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
                                 } else {
                                     final GeckoBundle data = new GeckoBundle(1);
                                     data.putBoolean("gainFocus", true);
                                     EventDispatcher.getInstance().dispatch("Accessibility:Focus", data);
                                 }
                                 return true;
                             } else if (action == AccessibilityNodeInfo.ACTION_CLICK && virtualViewId == VIRTUAL_CURSOR_POSITION) {
                                 EventDispatcher.getInstance().dispatch("Accessibility:ActivateObject", null);