Bug 1256461 - merge MoveChild and SeizeChild methods, r=yzen
authorAlexander Surkov <surkov.alexander@gmail.com>
Thu, 31 Mar 2016 21:22:13 -0400
changeset 291168 dbb5c40ec3a2ef633a55187f2f260ec098f18932
parent 291167 c710d0da3ac166eab902071388e89c68c5fba4ea
child 291169 d32bcd5bd2cf9a0e504d6ad78583c7f95bc1ccf3
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyzen
bugs1256461
milestone48.0a1
Bug 1256461 - merge MoveChild and SeizeChild methods, r=yzen
accessible/generic/DocAccessible.cpp
accessible/generic/DocAccessible.h
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -2058,21 +2058,30 @@ DocAccessible::ValidateARIAOwned()
 void
 DocAccessible::DoARIAOwnsRelocation(Accessible* aOwner)
 {
   nsTArray<RefPtr<Accessible> >* children = mARIAOwnsHash.LookupOrAdd(aOwner);
 
   MOZ_ASSERT(aOwner, "aOwner must be a valid pointer");
   MOZ_ASSERT(aOwner->Elm(), "aOwner->Elm() must be a valid pointer");
 
+#ifdef A11Y_LOG
+  logging::TreeInfo("aria owns relocation", logging::eVerbose, aOwner);
+#endif
+
   IDRefsIterator iter(this, aOwner->Elm(), nsGkAtoms::aria_owns);
   Accessible* child = nullptr;
 
   uint32_t arrayIdx = 0, insertIdx = aOwner->ChildCount() - children->Length();
   while ((child = iter.Next())) {
+#ifdef A11Y_LOG
+  logging::TreeInfo("aria owns traversal", logging::eVerbose,
+                    "candidate", child, nullptr);
+#endif
+
     // Same child on same position, no change.
     if (child->Parent() == aOwner &&
         child->IndexInParent() == static_cast<int32_t>(insertIdx)) {
       NS_ASSERTION(child == children->ElementAt(arrayIdx), "Not in sync!");
       insertIdx++; arrayIdx++;
       continue;
     }
 
@@ -2090,138 +2099,31 @@ DocAccessible::DoARIAOwnsRelocation(Acce
         parent = parent->Parent();
       }
       // A referred child cannot be a parent of the owner.
       if (parent == child) {
         continue;
       }
     }
 
-    if (child->Parent() == aOwner) {
-      if (child->IsRelocated()) {
-        children->RemoveElement(child);
-      }
-      MoveChild(child, insertIdx);
+    if (MoveChild(child, aOwner, insertIdx)) {
+      child->SetRelocated(true);
       children->InsertElementAt(arrayIdx, child);
       arrayIdx++;
       insertIdx = child->IndexInParent() + 1;
-
-    } else if (SeizeChild(aOwner, child, insertIdx)) {
-      children->InsertElementAt(arrayIdx, child);
-      insertIdx++; arrayIdx++;
     }
   }
 
   // Put back children that are not seized anymore.
   PutChildrenBack(children, arrayIdx);
   if (children->Length() == 0) {
     mARIAOwnsHash.Remove(aOwner);
   }
 }
 
-bool
-DocAccessible::SeizeChild(Accessible* aNewParent, Accessible* aChild,
-                          int32_t aIdxInParent)
-{
-  Accessible* oldParent = aChild->Parent();
-  if (!oldParent) {
-    NS_ERROR("No parent? The tree is broken!");
-    return false;
-  }
-
-  int32_t oldIdxInParent = aChild->IndexInParent();
-
-#ifdef A11Y_LOG
-  logging::TreeInfo("aria owns seize child", 0,
-                    "old parent", oldParent, "new parent", aNewParent,
-                    "child", aChild, nullptr);
-#endif
-
-  RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(oldParent);
-  RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(aChild, false);
-  reorderEvent->AddSubMutationEvent(hideEvent);
-
-  {
-    AutoTreeMutation mut(oldParent);
-    oldParent->RemoveChild(aChild);
-  }
-
-  bool isReinserted = false;
-  {
-    AutoTreeMutation mut(aNewParent);
-    isReinserted = aNewParent->InsertChildAt(aIdxInParent, aChild);
-  }
-
-#ifdef A11Y_LOG
-    logging::TreeInfo("aria owns seize child: new parent tree after",
-                      logging::eVerbose, aNewParent);
-#endif
-
-  if (!isReinserted) {
-    AutoTreeMutation mut(oldParent);
-    oldParent->InsertChildAt(oldIdxInParent, aChild);
-    return false;
-  }
-
-  // The child may be stolen from other ARIA owns element.
-  if (aChild->IsRelocated()) {
-    nsTArray<RefPtr<Accessible> >* children = mARIAOwnsHash.Get(oldParent);
-    children->RemoveElement(aChild);
-  }
-
-  FireDelayedEvent(hideEvent);
-  MaybeNotifyOfValueChange(oldParent);
-  FireDelayedEvent(reorderEvent);
-
-  reorderEvent = new AccReorderEvent(aNewParent);
-  RefPtr<AccMutationEvent> showEvent = new AccShowEvent(aChild);
-  reorderEvent->AddSubMutationEvent(showEvent);
-
-  FireDelayedEvent(showEvent);
-  MaybeNotifyOfValueChange(aNewParent);
-  FireDelayedEvent(reorderEvent);
-
-  aChild->SetRelocated(true);
-  return true;
-}
-
-void
-DocAccessible::MoveChild(Accessible* aChild, int32_t aIdxInParent)
-{
-  NS_PRECONDITION(aChild->Parent(), "No parent?");
-
-  Accessible* parent = aChild->Parent();
-  RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(parent);
-  RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(aChild, false);
-  reorderEvent->AddSubMutationEvent(hideEvent);
-
-#ifdef A11Y_LOG
-  logging::TreeInfo("aria owns move child", 0,
-                    "parent", parent, "child", aChild, nullptr);
-#endif
-
-  AutoTreeMutation mut(parent);
-  parent->MoveChild(aIdxInParent, aChild);
-  aChild->SetRelocated(true);
-
-#ifdef A11Y_LOG
-  logging::TreeInfo("aria owns move child: parent tree after",
-                    logging::eVerbose, parent);
-#endif
-
-  FireDelayedEvent(hideEvent);
-
-  RefPtr<AccMutationEvent> showEvent = new AccShowEvent(aChild);
-  reorderEvent->AddSubMutationEvent(showEvent);
-  FireDelayedEvent(showEvent);
-
-  MaybeNotifyOfValueChange(parent);
-  FireDelayedEvent(reorderEvent);
-}
-
 void
 DocAccessible::PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
                                uint32_t aStartIdx)
 {
   nsTArray<RefPtr<Accessible> > containers;
   for (auto idx = aStartIdx; idx < aChildren->Length(); idx++) {
     Accessible* child = aChildren->ElementAt(idx);
     if (!child->IsInDocument()) {
@@ -2235,64 +2137,126 @@ DocAccessible::PutChildrenBack(nsTArray<
       continue;
     }
 
 #ifdef A11Y_LOG
     logging::TreeInfo("aria owns put child back", 0,
                       "old parent", owner, "child", child, nullptr);
 #endif
 
-    RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(owner);
-    RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(child, false);
-    reorderEvent->AddSubMutationEvent(hideEvent);
-    FireDelayedEvent(hideEvent);
+    // Unset relocated flag to find an insertion point for the child.
+    child->SetRelocated(false);
 
-    {
-      AutoTreeMutation mut(owner);
-      owner->RemoveChild(child);
-      child->SetRelocated(false);
-    }
-
-    MaybeNotifyOfValueChange(owner);
-    FireDelayedEvent(reorderEvent);
-
-#ifdef A11Y_LOG
-    logging::TreeInfo("aria owns put child back: old parent tree after",
-                      logging::eVerbose, owner);
-#endif
-
-    // and put it back where it belongs to.
+    int32_t idxInParent = -1;
     Accessible* origContainer = GetContainerAccessible(child->GetContent());
     if (origContainer) {
       TreeWalker walker(origContainer);
       if (walker.Seek(child->GetContent())) {
         Accessible* prevChild = walker.Prev();
-        {
-          AutoTreeMutation mut(origContainer);
-          origContainer->InsertAfter(child, prevChild);
-        }
-
-        RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(origContainer);
-        RefPtr<AccMutationEvent> showEvent = new AccShowEvent(child);
-        reorderEvent->AddSubMutationEvent(showEvent);
-        FireDelayedEvent(showEvent);
-        MaybeNotifyOfValueChange(origContainer);
-        FireDelayedEvent(reorderEvent);
-
-#ifdef A11Y_LOG
-        logging::TreeInfo("aria owns put child back: new parent tree after",
-                          logging::eVerbose, origContainer);
-#endif
+        idxInParent = prevChild ? prevChild->IndexInParent() + 1 : 0;
       }
     }
+    MoveChild(child, origContainer, idxInParent);
   }
 
   aChildren->RemoveElementsAt(aStartIdx, aChildren->Length() - aStartIdx);
 }
 
+bool
+DocAccessible::MoveChild(Accessible* aChild, Accessible* aNewParent,
+                         int32_t aIdxInParent)
+{
+  MOZ_ASSERT(aChild, "No child");
+  MOZ_ASSERT(aChild->Parent(), "No parent");
+
+  Accessible* curParent = aChild->Parent();
+
+#ifdef A11Y_LOG
+  logging::TreeInfo("move child", 0,
+                    "old parent", curParent, "new parent", aNewParent,
+                    "child", aChild, nullptr);
+#endif
+
+  // If the child was taken from from an ARIA owns element.
+  if (aChild->IsRelocated()) {
+    nsTArray<RefPtr<Accessible> >* children = mARIAOwnsHash.Get(curParent);
+    children->RemoveElement(aChild);
+  }
+
+  if (curParent == aNewParent) {
+    MOZ_ASSERT(aChild->IndexInParent() != aIdxInParent, "No move case");
+
+    RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(curParent);
+    RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(aChild, false);
+    reorderEvent->AddSubMutationEvent(hideEvent);
+    FireDelayedEvent(hideEvent);
+
+    AutoTreeMutation mut(curParent);
+    curParent->MoveChild(aIdxInParent, aChild);
+
+    RefPtr<AccMutationEvent> showEvent = new AccShowEvent(aChild);
+    reorderEvent->AddSubMutationEvent(showEvent);
+    FireDelayedEvent(showEvent);
+
+    MaybeNotifyOfValueChange(curParent);
+    FireDelayedEvent(reorderEvent);
+
+#ifdef A11Y_LOG
+    logging::TreeInfo("move child: parent tree after",
+                      logging::eVerbose, curParent);
+#endif
+    return true;
+  }
+
+  if (!aNewParent->IsAcceptableChild(aChild->GetContent())) {
+    return false;
+  }
+
+  RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(curParent);
+  RefPtr<AccMutationEvent> hideEvent = new AccHideEvent(aChild, false);
+  reorderEvent->AddSubMutationEvent(hideEvent);
+  FireDelayedEvent(hideEvent);
+
+  {
+    AutoTreeMutation mut(curParent);
+    curParent->RemoveChild(aChild);
+  }
+
+  MaybeNotifyOfValueChange(curParent);
+  FireDelayedEvent(reorderEvent);
+
+  // No insertion point for the child.
+  if (aIdxInParent == -1) {
+    return true;
+  }
+
+  {
+    AutoTreeMutation mut(aNewParent);
+    aNewParent->InsertChildAt(aIdxInParent, aChild);
+  }
+
+  reorderEvent = new AccReorderEvent(aNewParent);
+  RefPtr<AccMutationEvent> showEvent = new AccShowEvent(aChild);
+  reorderEvent->AddSubMutationEvent(showEvent);
+  FireDelayedEvent(showEvent);
+
+  MaybeNotifyOfValueChange(aNewParent);
+  FireDelayedEvent(reorderEvent);
+
+#ifdef A11Y_LOG
+  logging::TreeInfo("move child: old parent tree after",
+                    logging::eVerbose, curParent);
+  logging::TreeInfo("move child: new parent tree after",
+                    logging::eVerbose, aNewParent);
+#endif
+
+  return true;
+}
+
+
 void
 DocAccessible::CacheChildrenInSubtree(Accessible* aRoot,
                                       Accessible** aFocusedAcc)
 {
   // If the accessible is focused then report a focus event after all related
   // mutation events.
   if (aFocusedAcc && !*aFocusedAcc &&
       FocusMgr()->HasDOMFocus(aRoot->GetContent()))
--- a/accessible/generic/DocAccessible.h
+++ b/accessible/generic/DocAccessible.h
@@ -525,32 +525,24 @@ protected:
   void ValidateARIAOwned();
 
   /**
    * Steals or puts back accessible subtrees.
    */
   void DoARIAOwnsRelocation(Accessible* aOwner);
 
   /**
-   * Moves the child from old parent under new one.
-   */
-  bool SeizeChild(Accessible* aNewParent, Accessible* aChild,
-                  int32_t aIdxInParent);
-
-  /**
-   * Move the child under same parent.
-   */
-  void MoveChild(Accessible* aChild, int32_t aIdxInParent);
-
-  /**
    * Moves children back under their original parents.
    */
   void PutChildrenBack(nsTArray<RefPtr<Accessible> >* aChildren,
                        uint32_t aStartIdx);
 
+  bool MoveChild(Accessible* aChild, Accessible* aNewParent,
+                 int32_t aIdxInParent);
+
   /**
    * Create accessible tree.
    *
    * @param aRoot       [in] a root of subtree to create
    * @param aFocusedAcc [in, optional] a focused accessible under created
    *                      subtree if any
    */
   void CacheChildrenInSubtree(Accessible* aRoot,