Bug 1501496 - Don't send accessible GeckoBundle in sendEvent, class names is enough. r=Jamie a=jcristau
authorEitan Isaacson <eitan@monotonous.org>
Thu, 25 Oct 2018 21:49:28 +0000
changeset 501341 d901616bfe1a7e9a45bc404e4d586586c4d2eeee
parent 501340 59b5d9b0fe7eb87cbf8d4556d2efcd690f2dfb12
child 501342 f96dbab7b6a3cdf977e1b92a8f76f77d2e79b330
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersJamie, jcristau
bugs1501496
milestone64.0
Bug 1501496 - Don't send accessible GeckoBundle in sendEvent, class names is enough. r=Jamie a=jcristau Differential Revision: https://phabricator.services.mozilla.com/D9689
accessible/android/AccessibleWrap.cpp
accessible/android/AccessibleWrap.h
accessible/android/Platform.cpp
accessible/android/SessionAccessibility.cpp
accessible/android/SessionAccessibility.h
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
--- a/accessible/android/AccessibleWrap.cpp
+++ b/accessible/android/AccessibleWrap.cpp
@@ -113,17 +113,17 @@ AccessibleWrap::HandleAccEvent(AccEvent*
                                        event->IsTextInserted(),
                                        event->IsFromUserInput());
       break;
     }
     case nsIAccessibleEvent::EVENT_STATE_CHANGE: {
       AccStateChangeEvent* event = downcast_accEvent(aEvent);
       auto state = event->GetState();
       if (state & states::CHECKED) {
-        sessionAcc->SendClickedEvent(accessible);
+        sessionAcc->SendClickedEvent(accessible, event->IsStateEnabled());
       }
 
       if (state & states::SELECTED) {
         sessionAcc->SendSelectedEvent(accessible);
       }
 
       if (state & states::BUSY) {
         sessionAcc->SendWindowStateChangedEvent(accessible);
@@ -368,17 +368,17 @@ AccessibleWrap::WrapperRangeInfo(double*
     *aStep = Step();
     return true;
   }
 
   return false;
 }
 
 mozilla::java::GeckoBundle::LocalRef
-AccessibleWrap::ToBundle(bool aMinimal)
+AccessibleWrap::ToBundle()
 {
   if (!IsProxy() && IsDefunct()) {
     return nullptr;
   }
 
   GECKOBUNDLE_START(nodeInfo);
   GECKOBUNDLE_PUT(nodeInfo, "id", java::sdk::Integer::ValueOf(VirtualViewID()));
 
@@ -401,21 +401,16 @@ AccessibleWrap::ToBundle(bool aMinimal)
     nsAutoString hint;
     Name(hint);
     GECKOBUNDLE_PUT(nodeInfo, "hint", jni::StringParam(hint));
   } else {
     Name(text);
   }
   GECKOBUNDLE_PUT(nodeInfo, "text", jni::StringParam(text));
 
-  if (aMinimal) {
-    GECKOBUNDLE_FINISH(nodeInfo);
-    return nodeInfo;
-  }
-
   nsAutoString geckoRole;
   nsAutoString roleDescription;
   if (VirtualViewID() != kNoID) {
     GetRoleDescription(role, geckoRole, roleDescription);
   }
 
   GECKOBUNDLE_PUT(
     nodeInfo, "roleDescription", jni::StringParam(roleDescription));
--- a/accessible/android/AccessibleWrap.h
+++ b/accessible/android/AccessibleWrap.h
@@ -26,17 +26,17 @@ public:
   int32_t VirtualViewID() const { return mID; }
 
   virtual void SetTextContents(const nsAString& aText);
 
   virtual void GetTextContents(nsAString& aText);
 
   virtual bool GetSelectionBounds(int32_t* aStartOffset, int32_t* aEndOffset);
 
-  mozilla::java::GeckoBundle::LocalRef ToBundle(bool aMinimal = false);
+  mozilla::java::GeckoBundle::LocalRef ToBundle();
 
   int32_t AndroidClass()
   {
     return mID == kNoID ? java::SessionAccessibility::CLASSNAME_WEBVIEW
                         : GetAndroidClass(WrapperRole());
   }
 
   static const int32_t kNoID = -1;
--- a/accessible/android/Platform.cpp
+++ b/accessible/android/Platform.cpp
@@ -80,17 +80,17 @@ a11y::ProxyStateChangeEvent(ProxyAccessi
   SessionAccessibility* sessionAcc =
     SessionAccessibility::GetInstanceFor(aTarget);
 
   if (!sessionAcc) {
     return;
   }
 
   if (aState & states::CHECKED) {
-    sessionAcc->SendClickedEvent(WrapperFor(aTarget));
+    sessionAcc->SendClickedEvent(WrapperFor(aTarget), aEnabled);
   }
 
   if (aState & states::SELECTED) {
     sessionAcc->SendSelectedEvent(WrapperFor(aTarget));
   }
 
   if (aState & states::BUSY) {
     sessionAcc->SendWindowStateChangedEvent(WrapperFor(aTarget));
--- a/accessible/android/SessionAccessibility.cpp
+++ b/accessible/android/SessionAccessibility.cpp
@@ -146,40 +146,40 @@ SessionAccessibility::GetInstanceFor(Acc
   return nullptr;
 }
 
 void
 SessionAccessibility::SendAccessibilityFocusedEvent(AccessibleWrap* aAccessible)
 {
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_VIEW_ACCESSIBILITY_FOCUSED,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), nullptr);
   aAccessible->ScrollTo(nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE);
 }
 
 void
 SessionAccessibility::SendHoverEnterEvent(AccessibleWrap* aAccessible)
 {
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_VIEW_HOVER_ENTER,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), nullptr);
 }
 
 void
 SessionAccessibility::SendFocusEvent(AccessibleWrap* aAccessible)
 {
   // Suppress focus events from about:blank pages.
   // This is important for tests.
   if (aAccessible->IsDoc() && aAccessible->ChildCount() == 0) {
     return;
   }
 
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_VIEW_FOCUSED,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), nullptr);
 }
 
 void
 SessionAccessibility::SendScrollingEvent(AccessibleWrap* aAccessible,
                                          int32_t aScrollX,
                                          int32_t aScrollY,
                                          int32_t aMaxScrollX,
                                          int32_t aMaxScrollY)
@@ -194,42 +194,42 @@ SessionAccessibility::SendScrollingEvent
   GECKOBUNDLE_START(eventInfo);
   GECKOBUNDLE_PUT(eventInfo, "scrollX", java::sdk::Integer::ValueOf(aScrollX));
   GECKOBUNDLE_PUT(eventInfo, "scrollY", java::sdk::Integer::ValueOf(aScrollY));
   GECKOBUNDLE_PUT(eventInfo, "maxScrollX", java::sdk::Integer::ValueOf(aMaxScrollX));
   GECKOBUNDLE_PUT(eventInfo, "maxScrollY", java::sdk::Integer::ValueOf(aMaxScrollY));
   GECKOBUNDLE_FINISH(eventInfo);
 
   mSessionAccessibility->SendEvent(
-    java::sdk::AccessibilityEvent::TYPE_VIEW_SCROLLED, virtualViewId, eventInfo,
-    aAccessible->ToBundle(true));
+    java::sdk::AccessibilityEvent::TYPE_VIEW_SCROLLED, virtualViewId,
+    aAccessible->AndroidClass(), eventInfo);
 
   SendWindowContentChangedEvent(aAccessible);
 }
 
 void
 SessionAccessibility::SendWindowContentChangedEvent(AccessibleWrap* aAccessible)
 {
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_WINDOW_CONTENT_CHANGED,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), nullptr);
 }
 
 void
 SessionAccessibility::SendWindowStateChangedEvent(AccessibleWrap* aAccessible)
 {
   // Suppress window state changed events from about:blank pages.
   // This is important for tests.
   if (aAccessible->IsDoc() && aAccessible->ChildCount() == 0) {
     return;
   }
 
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_WINDOW_STATE_CHANGED,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), nullptr);
 }
 
 void
 SessionAccessibility::SendTextSelectionChangedEvent(AccessibleWrap* aAccessible,
                                                     int32_t aCaretOffset)
 {
   int32_t fromIndex = aCaretOffset;
   int32_t startSel = -1;
@@ -240,17 +240,17 @@ SessionAccessibility::SendTextSelectionC
 
   GECKOBUNDLE_START(eventInfo);
   GECKOBUNDLE_PUT(eventInfo, "fromIndex", java::sdk::Integer::ValueOf(fromIndex));
   GECKOBUNDLE_PUT(eventInfo, "toIndex", java::sdk::Integer::ValueOf(aCaretOffset));
   GECKOBUNDLE_FINISH(eventInfo);
 
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_VIEW_TEXT_SELECTION_CHANGED,
-    aAccessible->VirtualViewID(), eventInfo, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), eventInfo);
 }
 
 void
 SessionAccessibility::SendTextChangedEvent(AccessibleWrap* aAccessible,
                                            const nsString& aStr,
                                            int32_t aStart,
                                            uint32_t aLen,
                                            bool aIsInsert,
@@ -274,17 +274,17 @@ SessionAccessibility::SendTextChangedEve
   GECKOBUNDLE_PUT(eventInfo, "text", jni::StringParam(text));
   GECKOBUNDLE_PUT(eventInfo, "beforeText", jni::StringParam(beforeText));
   GECKOBUNDLE_PUT(eventInfo, "addedCount", java::sdk::Integer::ValueOf(aIsInsert ? aLen : 0));
   GECKOBUNDLE_PUT(eventInfo, "removedCount", java::sdk::Integer::ValueOf(aIsInsert ? 0 : aLen));
   GECKOBUNDLE_FINISH(eventInfo);
 
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_VIEW_TEXT_CHANGED,
-    aAccessible->VirtualViewID(), eventInfo, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), eventInfo);
 }
 
 void
 SessionAccessibility::SendTextTraversedEvent(AccessibleWrap* aAccessible,
                                              int32_t aStartOffset,
                                              int32_t aEndOffset)
 {
   nsAutoString text;
@@ -294,26 +294,31 @@ SessionAccessibility::SendTextTraversedE
   GECKOBUNDLE_PUT(eventInfo, "text", jni::StringParam(text));
   GECKOBUNDLE_PUT(eventInfo, "fromIndex", java::sdk::Integer::ValueOf(aStartOffset));
   GECKOBUNDLE_PUT(eventInfo, "toIndex", java::sdk::Integer::ValueOf(aEndOffset));
   GECKOBUNDLE_FINISH(eventInfo);
 
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::
       TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
-    aAccessible->VirtualViewID(), eventInfo, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), eventInfo);
 }
 
 void
-SessionAccessibility::SendClickedEvent(AccessibleWrap* aAccessible)
+SessionAccessibility::SendClickedEvent(AccessibleWrap* aAccessible, bool aChecked)
 {
+  GECKOBUNDLE_START(eventInfo);
+  // Boolean::FALSE/TRUE gets clobbered by a macro, so ugh.
+  GECKOBUNDLE_PUT(eventInfo, "checked", java::sdk::Integer::ValueOf(aChecked ? 1 : 0));
+  GECKOBUNDLE_FINISH(eventInfo);
+
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_VIEW_CLICKED,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), eventInfo);
 }
 
 void
 SessionAccessibility::SendSelectedEvent(AccessibleWrap* aAccessible)
 {
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_VIEW_SELECTED,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), aAccessible->AndroidClass(), nullptr);
 }
--- a/accessible/android/SessionAccessibility.h
+++ b/accessible/android/SessionAccessibility.h
@@ -95,17 +95,17 @@ public:
                               int32_t aEndOffset);
   void SendTextChangedEvent(AccessibleWrap* aAccessible,
                             const nsString& aStr,
                             int32_t aStart,
                             uint32_t aLen,
                             bool aIsInsert,
                             bool aFromUser);
   void SendSelectedEvent(AccessibleWrap* aAccessible);
-  void SendClickedEvent(AccessibleWrap* aAccessible);
+  void SendClickedEvent(AccessibleWrap* aAccessible, bool aChecked);
   void SendWindowContentChangedEvent(AccessibleWrap* aAccessible);
   void SendWindowStateChangedEvent(AccessibleWrap* aAccessible);
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SessionAccessibility)
 
 private:
   ~SessionAccessibility() {}
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
@@ -124,33 +124,33 @@ public class SessionAccessibility {
 
         @Override
         public boolean performAction(final int virtualViewId, int action, Bundle arguments) {
             final GeckoBundle data;
 
             switch (action) {
             case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
                     if (virtualViewId == View.NO_ID) {
-                        sendEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, View.NO_ID, null, null);
+                        sendEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, View.NO_ID, CLASSNAME_WEBVIEW, null);
                     } else {
                         final GeckoBundle nodeInfo = nativeProvider.getNodeInfo(virtualViewId);
                         final int flags = nodeInfo != null ? nodeInfo.getInt("flags") : 0;
                         if ((flags & FLAG_FOCUSED) != 0) {
                             mSession.getEventDispatcher().dispatch("GeckoView:AccessibilityCursorToFocused", null);
                         } else {
-                            sendEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, virtualViewId, null, nodeInfo);
+                            sendEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED, virtualViewId, nodeInfo.getInt("className"), null);
                         }
                     }
                 return true;
             case AccessibilityNodeInfo.ACTION_CLICK:
                 mSession.getEventDispatcher().dispatch("GeckoView:AccessibilityActivate", null);
                 GeckoBundle nodeInfo = nativeProvider.getNodeInfo(virtualViewId);
                 final int flags = nodeInfo != null ? nodeInfo.getInt("flags") : 0;
                 if ((flags & (FLAG_SELECTABLE | FLAG_CHECKABLE)) == 0) {
-                    sendEvent(AccessibilityEvent.TYPE_VIEW_CLICKED, virtualViewId, null, nodeInfo);
+                    sendEvent(AccessibilityEvent.TYPE_VIEW_CLICKED, virtualViewId, nodeInfo.getInt("className"), null);
                 }
                 return true;
             case AccessibilityNodeInfo.ACTION_LONG_CLICK:
                 mSession.getEventDispatcher().dispatch("GeckoView:AccessibilityLongPress", null);
                 return true;
             case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
                 mSession.getEventDispatcher().dispatch("GeckoView:AccessibilityScrollForward", null);
                 return true;
@@ -564,17 +564,17 @@ public class SessionAccessibility {
         }
 
         final GeckoBundle data = new GeckoBundle(2);
         data.putDoubleArray("coordinates", new double[] {event.getRawX(), event.getRawY()});
         mSession.getEventDispatcher().dispatch("GeckoView:AccessibilityExploreByTouch", data);
         return true;
     }
 
-    /* package */ void sendEvent(final int eventType, final int sourceId, final GeckoBundle eventData, final GeckoBundle sourceInfo) {
+    /* package */ void sendEvent(final int eventType, final int sourceId, final int className, final GeckoBundle eventData) {
         ThreadUtils.assertOnUiThread();
         if (mView == null) {
             return;
         }
 
         if (!Settings.isPlatformEnabled() && (Build.VERSION.SDK_INT < 17 || mView.getDisplay() != null)) {
             // Accessibility could be activated in Gecko via xpcom, for example when using a11y
             // devtools. Here we assure that either Android a11y is *really* enabled, or no
@@ -583,41 +583,36 @@ public class SessionAccessibility {
         }
         if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
             mAccessibilityFocusedNode = sourceId;
         }
 
         final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
         event.setPackageName(GeckoAppShell.getApplicationContext().getPackageName());
         event.setSource(mView, sourceId);
+        event.setClassName(getClassName(className));
         event.setEnabled(true);
 
-        if (sourceInfo != null) {
-            final int flags = sourceInfo.getInt("flags");
-            event.setClassName(getClassName(sourceInfo.getInt("className")));
-            event.setChecked((flags & FLAG_CHECKED) != 0);
-            event.getText().add(sourceInfo.getString("text", ""));
-        }
-
         if (eventData != null) {
             if (eventData.containsKey("text")) {
                 event.getText().add(eventData.getString("text"));
             }
             event.setContentDescription(eventData.getString("description", ""));
             event.setAddedCount(eventData.getInt("addedCount", -1));
             event.setRemovedCount(eventData.getInt("removedCount", -1));
             event.setFromIndex(eventData.getInt("fromIndex", -1));
             event.setItemCount(eventData.getInt("itemCount", -1));
             event.setCurrentItemIndex(eventData.getInt("currentItemIndex", -1));
             event.setBeforeText(eventData.getString("beforeText", ""));
             event.setToIndex(eventData.getInt("toIndex", -1));
             event.setScrollX(eventData.getInt("scrollX", -1));
             event.setScrollY(eventData.getInt("scrollY", -1));
             event.setMaxScrollX(eventData.getInt("maxScrollX", -1));
             event.setMaxScrollY(eventData.getInt("maxScrollY", -1));
+            event.setChecked(eventData.getInt("checked") != 0);
         }
 
         ((ViewParent) mView).requestSendAccessibilityEvent(mView, event);
     }
 
     /* package */ final class NativeProvider extends JNIObject {
         @WrapForJNI(calledFrom = "ui")
         private void setAttached(final boolean attached) {
@@ -632,18 +627,18 @@ public class SessionAccessibility {
 
         @WrapForJNI(dispatchTo = "current")
         public native GeckoBundle getNodeInfo(int id);
 
         @WrapForJNI(dispatchTo = "gecko")
         public native void setText(int id, String text);
 
         @WrapForJNI(calledFrom = "gecko", stubName = "SendEvent")
-        private void sendEventNative(final int eventType, final int sourceId, final GeckoBundle eventData, final GeckoBundle sourceInfo) {
+        private void sendEventNative(final int eventType, final int sourceId, final int className, final GeckoBundle eventData) {
             ThreadUtils.postToUiThread(new Runnable() {
                 @Override
                 public void run() {
-                    sendEvent(eventType, sourceId, eventData, sourceInfo);
+                    sendEvent(eventType, sourceId, className, eventData);
                 }
             });
         }
     }
 }