Backed out 2 changesets (bug 1499209) for Accessibility crashes [@ mozilla::a11y::Accessible::Proxy() const] on a CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Sat, 20 Oct 2018 04:22:52 +0300
changeset 500728 e1daa7729f92b1b5597f7d41d76c823296f2939d
parent 500727 22c6202bd0d80505778ded5365f709e573f831ff
child 500729 ebf726d7d48ddc01f847a43baf3a606ce6ad2429
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)
bugs1499209
milestone64.0a1
backs outc8d88737a20ef4975399bd8825f5519ac378d6c9
6a22bf58801fe225e7477e089817d84df2e736ec
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 2 changesets (bug 1499209) for Accessibility crashes [@ mozilla::a11y::Accessible::Proxy() const] on a CLOSED TREE Backed out changeset c8d88737a20e (bug 1499209) Backed out changeset 6a22bf58801f (bug 1499209)
accessible/android/AccessibleWrap.cpp
accessible/android/AccessibleWrap.h
accessible/android/ProxyAccessibleWrap.cpp
accessible/android/ProxyAccessibleWrap.h
accessible/android/SessionAccessibility.cpp
--- a/accessible/android/AccessibleWrap.cpp
+++ b/accessible/android/AccessibleWrap.cpp
@@ -201,16 +201,164 @@ bool
 AccessibleWrap::GetSelectionBounds(int32_t* aStartOffset, int32_t* aEndOffset) {
   if (IsHyperText()) {
     return AsHyperText()->SelectionBoundsAt(0, aStartOffset, aEndOffset);
   }
 
   return false;
 }
 
+mozilla::java::GeckoBundle::LocalRef
+AccessibleWrap::CreateBundle(int32_t aParentID,
+                             role aRole,
+                             uint64_t aState,
+                             const nsString& aName,
+                             const nsString& aTextValue,
+                             const nsString& aDOMNodeID,
+                             const nsIntRect& aBounds,
+                             double aCurVal,
+                             double aMinVal,
+                             double aMaxVal,
+                             double aStep,
+                             nsIPersistentProperties* aAttributes,
+                             const nsTArray<int32_t>& aChildren) const
+{
+  GECKOBUNDLE_START(nodeInfo);
+  GECKOBUNDLE_PUT(nodeInfo, "id", java::sdk::Integer::ValueOf(VirtualViewID()));
+  GECKOBUNDLE_PUT(nodeInfo, "parentId", java::sdk::Integer::ValueOf(aParentID));
+  uint64_t flags = GetFlags(aRole, aState);
+  GECKOBUNDLE_PUT(nodeInfo, "flags", java::sdk::Integer::ValueOf(flags));
+
+  nsAutoString geckoRole;
+  nsAutoString roleDescription;
+  int32_t androidClass = java::SessionAccessibility::CLASSNAME_VIEW;
+  if (VirtualViewID() == kNoID) {
+    androidClass = java::SessionAccessibility::CLASSNAME_WEBVIEW;
+  } else {
+    GetRoleDescription(aRole, geckoRole, roleDescription);
+    androidClass = GetAndroidClass(aRole);
+  }
+
+  GECKOBUNDLE_PUT(
+    nodeInfo, "roleDescription", jni::StringParam(roleDescription));
+  GECKOBUNDLE_PUT(nodeInfo, "geckoRole", jni::StringParam(geckoRole));
+  GECKOBUNDLE_PUT(nodeInfo, "className", java::sdk::Integer::ValueOf(androidClass));
+
+  if (!aTextValue.IsEmpty() &&
+      (flags & java::SessionAccessibility::FLAG_EDITABLE)) {
+    GECKOBUNDLE_PUT(nodeInfo, "hint", jni::StringParam(aName));
+    GECKOBUNDLE_PUT(nodeInfo, "text", jni::StringParam(aTextValue));
+  } else {
+    GECKOBUNDLE_PUT(nodeInfo, "text", jni::StringParam(aName));
+  }
+
+  if (!aDOMNodeID.IsEmpty()) {
+    GECKOBUNDLE_PUT(
+      nodeInfo, "viewIdResourceName", jni::StringParam(aDOMNodeID));
+  }
+
+  const int32_t data[4] = {
+    aBounds.x, aBounds.y, aBounds.x + aBounds.width, aBounds.y + aBounds.height
+  };
+  GECKOBUNDLE_PUT(nodeInfo, "bounds", jni::IntArray::New(data, 4));
+
+  if (HasNumericValue()) {
+    GECKOBUNDLE_START(rangeInfo);
+    if (aMaxVal == 1 && aMinVal == 0) {
+      GECKOBUNDLE_PUT(
+        rangeInfo, "type", java::sdk::Integer::ValueOf(2)); // percent
+    } else if (std::round(aStep) != aStep) {
+      GECKOBUNDLE_PUT(
+        rangeInfo, "type", java::sdk::Integer::ValueOf(1)); // float
+    } else {
+      GECKOBUNDLE_PUT(
+        rangeInfo, "type", java::sdk::Integer::ValueOf(0)); // integer
+    }
+
+    if (!IsNaN(aCurVal)) {
+      GECKOBUNDLE_PUT(rangeInfo, "current", java::sdk::Double::New(aCurVal));
+    }
+    if (!IsNaN(aMinVal)) {
+      GECKOBUNDLE_PUT(rangeInfo, "min", java::sdk::Double::New(aMinVal));
+    }
+    if (!IsNaN(aMaxVal)) {
+      GECKOBUNDLE_PUT(rangeInfo, "max", java::sdk::Double::New(aMaxVal));
+    }
+
+    GECKOBUNDLE_FINISH(rangeInfo);
+    GECKOBUNDLE_PUT(nodeInfo, "rangeInfo", rangeInfo);
+  }
+
+  nsString inputTypeAttr;
+  nsAccUtils::GetAccAttr(aAttributes, nsGkAtoms::textInputType, inputTypeAttr);
+  int32_t inputType = GetInputType(inputTypeAttr);
+  if (inputType) {
+    GECKOBUNDLE_PUT(nodeInfo, "inputType", java::sdk::Integer::ValueOf(inputType));
+  }
+
+  nsString posinset;
+  nsresult rv = aAttributes->GetStringProperty(NS_LITERAL_CSTRING("posinset"), posinset);
+  if (NS_SUCCEEDED(rv)) {
+    int32_t rowIndex;
+    if (sscanf(NS_ConvertUTF16toUTF8(posinset).get(), "%d", &rowIndex) > 0) {
+      GECKOBUNDLE_START(collectionItemInfo);
+      GECKOBUNDLE_PUT(
+        collectionItemInfo, "rowIndex", java::sdk::Integer::ValueOf(rowIndex));
+      GECKOBUNDLE_PUT(
+        collectionItemInfo, "columnIndex", java::sdk::Integer::ValueOf(0));
+      GECKOBUNDLE_PUT(
+        collectionItemInfo, "rowSpan", java::sdk::Integer::ValueOf(1));
+      GECKOBUNDLE_PUT(
+        collectionItemInfo, "columnSpan", java::sdk::Integer::ValueOf(1));
+      GECKOBUNDLE_FINISH(collectionItemInfo);
+
+      GECKOBUNDLE_PUT(nodeInfo, "collectionItemInfo", collectionItemInfo);
+    }
+  }
+
+  nsString colSize;
+  rv = aAttributes->GetStringProperty(NS_LITERAL_CSTRING("child-item-count"),
+                                      colSize);
+  if (NS_SUCCEEDED(rv)) {
+    int32_t rowCount;
+    if (sscanf(NS_ConvertUTF16toUTF8(colSize).get(), "%d", &rowCount) > 0) {
+      GECKOBUNDLE_START(collectionInfo);
+      GECKOBUNDLE_PUT(
+        collectionInfo, "rowCount", java::sdk::Integer::ValueOf(rowCount));
+      GECKOBUNDLE_PUT(
+        collectionInfo, "columnCount", java::sdk::Integer::ValueOf(1));
+
+      nsString unused;
+      rv = aAttributes->GetStringProperty(NS_LITERAL_CSTRING("hierarchical"),
+                                          unused);
+      if (NS_SUCCEEDED(rv)) {
+        GECKOBUNDLE_PUT(
+          collectionInfo, "isHierarchical", java::sdk::Boolean::TRUE());
+      }
+
+      if (IsSelect()) {
+        int32_t selectionMode = (aState & states::MULTISELECTABLE) ? 2 : 1;
+        GECKOBUNDLE_PUT(collectionInfo,
+                        "selectionMode",
+                        java::sdk::Integer::ValueOf(selectionMode));
+      }
+      GECKOBUNDLE_FINISH(collectionInfo);
+
+      GECKOBUNDLE_PUT(nodeInfo, "collectionInfo", collectionInfo);
+    }
+  }
+
+  GECKOBUNDLE_PUT(nodeInfo,
+                  "children",
+                  jni::IntArray::New(aChildren.Elements(), aChildren.Length()));
+  GECKOBUNDLE_FINISH(nodeInfo);
+
+  return nodeInfo;
+}
+
 uint64_t
 AccessibleWrap::GetFlags(role aRole, uint64_t aState)
 {
   uint64_t flags = 0;
   if (aState & states::CHECKABLE) {
     flags |= java::SessionAccessibility::FLAG_CHECKABLE;
   }
 
@@ -342,205 +490,58 @@ AccessibleWrap::GetInputType(const nsStr
   if (aInputTypeAttr.EqualsIgnoreCase("url")) {
     return java::sdk::InputType::TYPE_CLASS_TEXT | java::sdk::InputType::TYPE_TEXT_VARIATION_URI;
   }
 
   return 0;
 }
 
 void
-AccessibleWrap::WrapperDOMNodeID(nsString& aDOMNodeID)
+AccessibleWrap::DOMNodeID(nsString& aDOMNodeID)
 {
   if (mContent) {
     nsAtom* id = mContent->GetID();
     if (id) {
       id->ToString(aDOMNodeID);
     }
   }
 }
 
-bool
-AccessibleWrap::WrapperRangeInfo(double* aCurVal, double* aMinVal,
-                             double* aMaxVal, double* aStep)
+mozilla::java::GeckoBundle::LocalRef
+AccessibleWrap::ToBundle()
 {
-  if (HasNumericValue()) {
-    *aCurVal = CurValue();
-    *aMinVal = MinValue();
-    *aMaxVal = MaxValue();
-    *aStep = Step();
-    return true;
-  }
-
-  return false;
-}
-
-mozilla::java::GeckoBundle::LocalRef
-AccessibleWrap::ToBundle(bool aMinimal)
-{
-  if (!Proxy() && IsDefunct()) {
+  if (IsDefunct()) {
     return nullptr;
   }
 
-  GECKOBUNDLE_START(nodeInfo);
-  GECKOBUNDLE_PUT(nodeInfo, "id", java::sdk::Integer::ValueOf(VirtualViewID()));
-
-  AccessibleWrap* parent = WrapperParent();
-  GECKOBUNDLE_PUT(nodeInfo, "parentId",
-    java::sdk::Integer::ValueOf(parent ? parent->VirtualViewID() : 0));
-
-  role role = WrapperRole();
-  uint64_t state = State();
-  uint64_t flags = GetFlags(role, state);
-  GECKOBUNDLE_PUT(nodeInfo, "flags", java::sdk::Integer::ValueOf(flags));
-  GECKOBUNDLE_PUT(nodeInfo, "className", java::sdk::Integer::ValueOf(AndroidClass()));
-
-  nsAutoString text;
-  if (state & states::EDITABLE) {
-    Value(text);
-  }
+  AccessibleWrap* parent = static_cast<AccessibleWrap*>(Parent());
+  nsAutoString name;
+  Name(name);
 
-  if (!text.IsEmpty()) {
-    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));
-  GECKOBUNDLE_PUT(nodeInfo, "geckoRole", jni::StringParam(geckoRole));
-
-  GECKOBUNDLE_PUT(
-    nodeInfo, "roleDescription", jni::StringParam(roleDescription));
-  GECKOBUNDLE_PUT(nodeInfo, "geckoRole", jni::StringParam(geckoRole));
+  nsAutoString value;
+  Value(value);
 
   nsAutoString viewIdResourceName;
-  WrapperDOMNodeID(viewIdResourceName);
-  if (!viewIdResourceName.IsEmpty()) {
-    GECKOBUNDLE_PUT(
-      nodeInfo, "viewIdResourceName", jni::StringParam(viewIdResourceName));
-  }
-
-  nsIntRect bounds = Bounds();
-  const int32_t data[4] = {
-    bounds.x, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height
-  };
-  GECKOBUNDLE_PUT(nodeInfo, "bounds", jni::IntArray::New(data, 4));
-
-  double curValue = 0;
-  double minValue = 0;
-  double maxValue = 0;
-  double step = 0;
-  if (WrapperRangeInfo(&curValue, &minValue, &maxValue, &step)) {
-    GECKOBUNDLE_START(rangeInfo);
-    if (maxValue == 1 && minValue == 0) {
-      GECKOBUNDLE_PUT(
-        rangeInfo, "type", java::sdk::Integer::ValueOf(2)); // percent
-    } else if (std::round(step) != step) {
-      GECKOBUNDLE_PUT(
-        rangeInfo, "type", java::sdk::Integer::ValueOf(1)); // float
-    } else {
-      GECKOBUNDLE_PUT(
-        rangeInfo, "type", java::sdk::Integer::ValueOf(0)); // integer
-    }
-
-    if (!IsNaN(curValue)) {
-      GECKOBUNDLE_PUT(rangeInfo, "current", java::sdk::Double::New(curValue));
-    }
-    if (!IsNaN(minValue)) {
-      GECKOBUNDLE_PUT(rangeInfo, "min", java::sdk::Double::New(minValue));
-    }
-    if (!IsNaN(maxValue)) {
-      GECKOBUNDLE_PUT(rangeInfo, "max", java::sdk::Double::New(maxValue));
-    }
-
-    GECKOBUNDLE_FINISH(rangeInfo);
-    GECKOBUNDLE_PUT(nodeInfo, "rangeInfo", rangeInfo);
-  }
+  DOMNodeID(viewIdResourceName);
 
   nsCOMPtr<nsIPersistentProperties> attributes = Attributes();
 
-  nsString inputTypeAttr;
-  nsAccUtils::GetAccAttr(attributes, nsGkAtoms::textInputType, inputTypeAttr);
-  int32_t inputType = GetInputType(inputTypeAttr);
-  if (inputType) {
-    GECKOBUNDLE_PUT(nodeInfo, "inputType", java::sdk::Integer::ValueOf(inputType));
-  }
-
-  nsString posinset;
-  nsresult rv = attributes->GetStringProperty(NS_LITERAL_CSTRING("posinset"), posinset);
-  if (NS_SUCCEEDED(rv)) {
-    int32_t rowIndex;
-    if (sscanf(NS_ConvertUTF16toUTF8(posinset).get(), "%d", &rowIndex) > 0) {
-      GECKOBUNDLE_START(collectionItemInfo);
-      GECKOBUNDLE_PUT(
-        collectionItemInfo, "rowIndex", java::sdk::Integer::ValueOf(rowIndex));
-      GECKOBUNDLE_PUT(
-        collectionItemInfo, "columnIndex", java::sdk::Integer::ValueOf(0));
-      GECKOBUNDLE_PUT(
-        collectionItemInfo, "rowSpan", java::sdk::Integer::ValueOf(1));
-      GECKOBUNDLE_PUT(
-        collectionItemInfo, "columnSpan", java::sdk::Integer::ValueOf(1));
-      GECKOBUNDLE_FINISH(collectionItemInfo);
-
-      GECKOBUNDLE_PUT(nodeInfo, "collectionItemInfo", collectionItemInfo);
-    }
-  }
-
-  nsString colSize;
-  rv = attributes->GetStringProperty(NS_LITERAL_CSTRING("child-item-count"),
-                                      colSize);
-  if (NS_SUCCEEDED(rv)) {
-    int32_t rowCount;
-    if (sscanf(NS_ConvertUTF16toUTF8(colSize).get(), "%d", &rowCount) > 0) {
-      GECKOBUNDLE_START(collectionInfo);
-      GECKOBUNDLE_PUT(
-        collectionInfo, "rowCount", java::sdk::Integer::ValueOf(rowCount));
-      GECKOBUNDLE_PUT(
-        collectionInfo, "columnCount", java::sdk::Integer::ValueOf(1));
-
-      nsString unused;
-      rv = attributes->GetStringProperty(NS_LITERAL_CSTRING("hierarchical"),
-                                          unused);
-      if (NS_SUCCEEDED(rv)) {
-        GECKOBUNDLE_PUT(
-          collectionInfo, "isHierarchical", java::sdk::Boolean::TRUE());
-      }
-
-      if (IsSelect()) {
-        int32_t selectionMode = (state & states::MULTISELECTABLE) ? 2 : 1;
-        GECKOBUNDLE_PUT(collectionInfo,
-                        "selectionMode",
-                        java::sdk::Integer::ValueOf(selectionMode));
-      }
-      GECKOBUNDLE_FINISH(collectionInfo);
-
-      GECKOBUNDLE_PUT(nodeInfo, "collectionInfo", collectionInfo);
-    }
-  }
-
   auto childCount = ChildCount();
   nsTArray<int32_t> children(childCount);
   for (uint32_t i = 0; i < childCount; i++) {
     auto child = static_cast<AccessibleWrap*>(GetChildAt(i));
     children.AppendElement(child->VirtualViewID());
   }
 
-  GECKOBUNDLE_PUT(nodeInfo,
-                  "children",
-                  jni::IntArray::New(children.Elements(), children.Length()));
-  GECKOBUNDLE_FINISH(nodeInfo);
-
-  return nodeInfo;
+  return CreateBundle(parent ? parent->VirtualViewID() : 0,
+                      Role(),
+                      State(),
+                      name,
+                      value,
+                      viewIdResourceName,
+                      Bounds(),
+                      CurValue(),
+                      MinValue(),
+                      MaxValue(),
+                      Step(),
+                      attributes,
+                      children);
 }
--- a/accessible/android/AccessibleWrap.h
+++ b/accessible/android/AccessibleWrap.h
@@ -26,46 +26,48 @@ 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);
-
-  int32_t AndroidClass()
-  {
-    return mID == kNoID ? java::SessionAccessibility::CLASSNAME_WEBVIEW
-                        : GetAndroidClass(WrapperRole());
-  }
+  virtual mozilla::java::GeckoBundle::LocalRef ToBundle();
 
   static const int32_t kNoID = -1;
 
 protected:
+  mozilla::java::GeckoBundle::LocalRef CreateBundle(
+    int32_t aParentID,
+    role aRole,
+    uint64_t aState,
+    const nsString& aName,
+    const nsString& aTextValue,
+    const nsString& aDOMNodeID,
+    const nsIntRect& aBounds,
+    double aCurVal,
+    double aMinVal,
+    double aMaxVal,
+    double aStep,
+    nsIPersistentProperties* aAttributes,
+    const nsTArray<int32_t>& aChildren) const;
 
   // IDs should be a positive 32bit integer.
   static int32_t AcquireID();
   static void ReleaseID(int32_t aID);
 
   static int32_t GetAndroidClass(role aRole);
 
   static int32_t GetInputType(const nsString& aInputTypeAttr);
 
   int32_t mID;
 
 private:
-  virtual AccessibleWrap* WrapperParent() { return static_cast<AccessibleWrap*>(Parent()); }
-
-  virtual bool WrapperRangeInfo(double* aCurVal, double* aMinVal, double* aMaxVal, double* aStep);
-
-  virtual role WrapperRole() { return Role(); }
-
-  virtual void WrapperDOMNodeID(nsString& aDOMNodeID);
+  void DOMNodeID(nsString& aDOMNodeID);
 
   static void GetRoleDescription(role aRole,
                                  nsAString& aGeckoRole,
                                  nsAString& aRoleDescription);
 
   static uint64_t GetFlags(role aRole, uint64_t aState);
 };
 
--- a/accessible/android/ProxyAccessibleWrap.cpp
+++ b/accessible/android/ProxyAccessibleWrap.cpp
@@ -67,48 +67,16 @@ ProxyAccessibleWrap::Attributes()
 }
 
 uint32_t
 ProxyAccessibleWrap::ChildCount() const
 {
   return Proxy()->ChildrenCount();
 }
 
-Accessible*
-ProxyAccessibleWrap::GetChildAt(uint32_t aIndex) const
-{
-  ProxyAccessible* child = Proxy()->ChildAt(aIndex);
-  return child ? WrapperFor(child) : nullptr;
-}
-
-ENameValueFlag
-ProxyAccessibleWrap::Name(nsString& aName) const
-{
-  Proxy()->Name(aName);
-  return eNameOK;
-}
-
-void
-ProxyAccessibleWrap::Value(nsString& aValue) const
-{
-  Proxy()->Value(aValue);
-}
-
-uint64_t
-ProxyAccessibleWrap::State()
-{ 
-  return Proxy()->State();
-}
-
-nsIntRect
-ProxyAccessibleWrap::Bounds() const
-{
-  return Proxy()->Bounds();
-}
-
 void
 ProxyAccessibleWrap::ScrollTo(uint32_t aHow) const
 {
   Proxy()->ScrollTo(aHow);
 }
 
 // Other
 
@@ -129,43 +97,51 @@ ProxyAccessibleWrap::GetTextContents(nsA
 bool
 ProxyAccessibleWrap::GetSelectionBounds(int32_t* aStartOffset,
                                         int32_t* aEndOffset)
 {
   nsAutoString unused;
   return Proxy()->SelectionBoundsAt(0, unused, aStartOffset, aEndOffset);
 }
 
-role
-ProxyAccessibleWrap::WrapperRole()
-{
-  return Proxy()->Role();
-}
-
-AccessibleWrap*
-ProxyAccessibleWrap::WrapperParent()
+mozilla::java::GeckoBundle::LocalRef
+ProxyAccessibleWrap::ToBundle()
 {
-  return Proxy()->Parent() ? WrapperFor(Proxy()->Parent()) : nullptr;
-}
-
-bool
-ProxyAccessibleWrap::WrapperRangeInfo(double* aCurVal,
-                                      double* aMinVal,
-                                      double* aMaxVal,
-                                      double* aStep)
-{
-  if (HasNumericValue()) {
-    ProxyAccessible* proxy = Proxy();
-    *aCurVal = proxy->CurValue();
-    *aMinVal = proxy->MinValue();
-    *aMaxVal = proxy->MaxValue();
-    *aStep = proxy->Step();
-    return true;
+  ProxyAccessible* proxy = Proxy();
+  if (!proxy) {
+    return nullptr;
   }
 
-  return false;
-}
+  int32_t parentID = proxy->Parent() ?
+    WrapperFor(proxy->Parent())->VirtualViewID() : 0;
+
+  nsAutoString name;
+  proxy->Name(name);
+
+  nsAutoString value;
+  proxy->Value(value);
+
+  nsAutoString viewIdResourceName;
+  proxy->DOMNodeID(viewIdResourceName);
+
+  nsCOMPtr<nsIPersistentProperties> attributes = Attributes();
 
-void
-ProxyAccessibleWrap::WrapperDOMNodeID(nsString& aDOMNodeID)
-{
-  Proxy()->DOMNodeID(aDOMNodeID);
+  auto childCount = proxy->ChildrenCount();
+  nsTArray<int32_t> children(childCount);
+  for (uint32_t i = 0; i < childCount; i++) {
+    auto child = WrapperFor(proxy->ChildAt(i));
+    children.AppendElement(child->VirtualViewID());
+  }
+
+  return CreateBundle(parentID,
+                      proxy->Role(),
+                      proxy->State(),
+                      name,
+                      value,
+                      viewIdResourceName,
+                      proxy->Bounds(),
+                      proxy->CurValue(),
+                      proxy->MinValue(),
+                      proxy->MaxValue(),
+                      proxy->Step(),
+                      attributes,
+                      children);
 }
--- a/accessible/android/ProxyAccessibleWrap.h
+++ b/accessible/android/ProxyAccessibleWrap.h
@@ -29,45 +29,27 @@ public:
   virtual void Shutdown() override;
 
   // Accessible
 
   virtual already_AddRefed<nsIPersistentProperties> Attributes() override;
 
   virtual uint32_t ChildCount() const override;
 
-  virtual Accessible* GetChildAt(uint32_t aIndex) const override;
-
-  virtual ENameValueFlag Name(nsString& aName) const override;
-
-  virtual void Value(nsString& aValue) const override;
-
-  virtual uint64_t State() override;
-
-  virtual nsIntRect Bounds() const override;
-
   virtual void ScrollTo(uint32_t aHow) const override;
 
   // AccessibleWrap
 
   virtual void SetTextContents(const nsAString& aText) override;
 
   virtual void GetTextContents(nsAString& aText) override;
 
   virtual bool GetSelectionBounds(int32_t* aStartOffset, int32_t* aEndOffset) override;
 
-private:
-  virtual role WrapperRole() override;
-
-  virtual AccessibleWrap* WrapperParent() override;
-
-  virtual bool WrapperRangeInfo(double* aCurVal, double* aMinVal, double* aMaxVal, double* aStep) override;
-
-  virtual void WrapperDOMNodeID(nsString& aDOMNodeID) override;
-
+  virtual mozilla::java::GeckoBundle::LocalRef ToBundle() override;
 };
 
 class DocProxyAccessibleWrap : public ProxyAccessibleWrap
 {
 public:
   explicit DocProxyAccessibleWrap(DocAccessibleParent* aProxy)
     : ProxyAccessibleWrap(aProxy)
   {
--- 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(), nullptr, aAccessible->ToBundle());
   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(), nullptr, aAccessible->ToBundle());
 }
 
 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(), nullptr, aAccessible->ToBundle());
 }
 
 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,
+    eventInfo, aAccessible->ToBundle());
 
   SendWindowContentChangedEvent(aAccessible);
 }
 
 void
 SessionAccessibility::SendWindowContentChangedEvent(AccessibleWrap* aAccessible)
 {
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_WINDOW_CONTENT_CHANGED,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle());
 }
 
 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(), nullptr, aAccessible->ToBundle());
 }
 
 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(), eventInfo, aAccessible->ToBundle());
 }
 
 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(), eventInfo, aAccessible->ToBundle());
 }
 
 void
 SessionAccessibility::SendTextTraversedEvent(AccessibleWrap* aAccessible,
                                              int32_t aStartOffset,
                                              int32_t aEndOffset)
 {
   nsAutoString text;
@@ -294,26 +294,26 @@ 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(), eventInfo, aAccessible->ToBundle());
 }
 
 void
 SessionAccessibility::SendClickedEvent(AccessibleWrap* aAccessible)
 {
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_VIEW_CLICKED,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle());
 }
 
 void
 SessionAccessibility::SendSelectedEvent(AccessibleWrap* aAccessible)
 {
   mSessionAccessibility->SendEvent(
     java::sdk::AccessibilityEvent::TYPE_VIEW_SELECTED,
-    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle(true));
+    aAccessible->VirtualViewID(), nullptr, aAccessible->ToBundle());
 }