Bug 412878. Fix our accessible subtree invalidation (removing nodes from cache etc.), to hopefully fix cache-related crashes in InvalidateChildren(). r=ginn, r=surkov, a=blocking1.9
authoraaronleventhal@moonset.net
Tue, 22 Jan 2008 06:43:18 -0800
changeset 10530 9efea6583783417592385d55849bdacc4947ea2f
parent 10529 d019b7edf576a8d958592ac6239cb25462575560
child 10531 e6b565dd5d3ba98721b3687c6ec686754a89ea2e
push idunknown
push userunknown
push dateunknown
reviewersginn, surkov, blocking1.9
bugs412878
milestone1.9b3pre
Bug 412878. Fix our accessible subtree invalidation (removing nodes from cache etc.), to hopefully fix cache-related crashes in InvalidateChildren(). r=ginn, r=surkov, a=blocking1.9
accessible/src/base/nsDocAccessible.cpp
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1657,50 +1657,56 @@ void nsDocAccessible::RefreshNodes(nsIDO
                             iterContent->GetBindingParent())) {
           // GetBindingParent() check is a perf win -- make sure we don't
           // shut down the same subtree twice since we'll reach non-anon content via
           // DOM traversal later in this method
           RefreshNodes(iterNode);
         }
       }
     }
-
-    // Shutdown ordinary content subtree as well -- there may be
-    // access node children which are not full accessible objects
-    aStartNode->GetFirstChild(getter_AddRefs(nextNode));
-    while (nextNode) {
-      nextNode.swap(iterNode);
-      RefreshNodes(iterNode);
-      iterNode->GetNextSibling(getter_AddRefs(nextNode));
-    }
-
-    // Don't shutdown our doc object!
-    if (accessNode && accessNode != static_cast<nsIAccessNode*>(this)) {
-      // Fire menupopup end if a menu goes away
-      PRUint32 role = Role(accessible);
-      if (role == nsIAccessibleRole::ROLE_MENUPOPUP) {
-        nsCOMPtr<nsIDOMNode> domNode;
-        accessNode->GetDOMNode(getter_AddRefs(domNode));
-        nsCOMPtr<nsIDOMXULPopupElement> popup(do_QueryInterface(domNode));
-        if (!popup) {
-          // Popup elements already fire these via DOMMenuInactive
-          // handling in nsRootAccessible::HandleEvent
-          nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
-                                   accessible);
-        }
+    // Fire menupopup end if a menu goes away
+    PRUint32 role = Role(accessible);
+    if (role == nsIAccessibleRole::ROLE_MENUPOPUP) {
+      nsCOMPtr<nsIDOMNode> domNode;
+      accessNode->GetDOMNode(getter_AddRefs(domNode));
+      nsCOMPtr<nsIDOMXULPopupElement> popup(do_QueryInterface(domNode));
+      if (!popup) {
+        // Popup elements already fire these via DOMMenuInactive
+        // handling in nsRootAccessible::HandleEvent
+        nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
+                                 accessible);
       }
-      // Shut down the actual accessible or access node
-      void *uniqueID;
-      accessNode->GetUniqueID(&uniqueID);
-      nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(accessNode));
-      privateAccessNode->Shutdown();
-      // Remove from hash table as well
-      mAccessNodeCache.Remove(uniqueID);
     }
   }
+
+  // Shutdown ordinary content subtree as well -- there may be
+  // access node children which are not full accessible objects
+  aStartNode->GetFirstChild(getter_AddRefs(nextNode));
+  while (nextNode) {
+    nextNode.swap(iterNode);
+    RefreshNodes(iterNode);
+    iterNode->GetNextSibling(getter_AddRefs(nextNode));
+  }
+
+  if (!accessNode) {
+    return;
+  }
+  if (accessNode == this) {
+    // Is this nsDocAccessible. It won't get shut down until pagehide
+    InvalidateChildren();
+    return;
+  }
+  
+  // Shut down the actual accessible or access node
+  nsCOMPtr<nsPIAccessNode> privateAccessNode(do_QueryInterface(accessNode));
+  privateAccessNode->Shutdown();
+  // Remove from hash table as well
+  void *uniqueID;
+  accessNode->GetUniqueID(&uniqueID);
+  mAccessNodeCache.Remove(uniqueID);
 }
 
 NS_IMETHODIMP nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
                                                       PRUint32 aChangeEventType)
 {
   PRBool isHiding = 
     aChangeEventType == nsIAccessibleEvent::EVENT_ASYNCH_HIDE ||
     aChangeEventType == nsIAccessibleEvent::EVENT_DOM_DESTROY;