Fix for bug 375534 - groupPosition problems, r=aaronlev
authorsurkov.alexander@gmail.com
Sat, 07 Apr 2007 02:07:24 -0700
changeset 401 f49652f9ca3d3ef7bdf8193f182c54b0e5ce29da
parent 400 608ab081e718f226e3fa006e17fcd19567f78cc0
child 402 dac84c43fdd3aa4f00b015381d611861688590e5
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaaronlev
bugs375534
milestone1.9a4pre
Fix for bug 375534 - groupPosition problems, r=aaronlev
accessible/src/base/nsAccessibilityUtils.cpp
accessible/src/base/nsAccessibilityUtils.h
accessible/src/base/nsAccessible.cpp
accessible/src/base/nsAccessible.h
accessible/src/html/nsHTMLFormControlAccessible.cpp
accessible/src/html/nsHTMLFormControlAccessible.h
accessible/src/html/nsHTMLSelectAccessible.cpp
accessible/src/html/nsHTMLSelectAccessible.h
accessible/src/html/nsHTMLTableAccessible.cpp
accessible/src/html/nsHTMLTableAccessible.h
accessible/src/html/nsHTMLTextAccessible.cpp
accessible/src/html/nsHTMLTextAccessible.h
accessible/src/html/nsHyperTextAccessible.cpp
accessible/src/html/nsHyperTextAccessible.h
accessible/src/msaa/nsAccessibleWrap.cpp
accessible/src/xforms/nsXFormsAccessible.cpp
accessible/src/xforms/nsXFormsAccessible.h
accessible/src/xul/nsXULFormControlAccessible.cpp
accessible/src/xul/nsXULFormControlAccessible.h
accessible/src/xul/nsXULMenuAccessible.cpp
accessible/src/xul/nsXULMenuAccessible.h
accessible/src/xul/nsXULTabAccessible.cpp
accessible/src/xul/nsXULTabAccessible.h
accessible/src/xul/nsXULTreeAccessible.cpp
accessible/src/xul/nsXULTreeAccessible.h
--- a/accessible/src/base/nsAccessibilityUtils.cpp
+++ b/accessible/src/base/nsAccessibilityUtils.cpp
@@ -61,67 +61,81 @@ nsAccessibilityUtils::SetAccAttr(nsIPers
   aAttrName->ToUTF8String(attrName);
   aAttributes->SetStringProperty(attrName, aAttrValue, oldValue);
 }
 
 void
 nsAccessibilityUtils::GetAccGroupAttrs(nsIPersistentProperties *aAttributes,
                                        PRInt32 *aLevel,
                                        PRInt32 *aPosInSet,
-                                       PRInt32 *aSizeSet)
+                                       PRInt32 *aSetSize)
 {
   *aLevel = 0;
   *aPosInSet = 0;
-  *aSizeSet = 0;
+  *aSetSize = 0;
 
   nsAutoString value;
   PRInt32 error = NS_OK;
 
   GetAccAttr(aAttributes, nsAccessibilityAtoms::level, value);
   if (!value.IsEmpty()) {
     PRInt32 level = value.ToInteger(&error);
     if (NS_SUCCEEDED(error))
       *aLevel = level;
   }
 
-  GetAccAttr(aAttributes, nsAccessibilityAtoms::setsize, value);
+  GetAccAttr(aAttributes, nsAccessibilityAtoms::posinset, value);
   if (!value.IsEmpty()) {
     PRInt32 posInSet = value.ToInteger(&error);
     if (NS_SUCCEEDED(error))
       *aPosInSet = posInSet;
   }
 
-  GetAccAttr(aAttributes, nsAccessibilityAtoms::posinset, value);
+  GetAccAttr(aAttributes, nsAccessibilityAtoms::setsize, value);
   if (!value.IsEmpty()) {
     PRInt32 sizeSet = value.ToInteger(&error);
     if (NS_SUCCEEDED(error))
-      *aSizeSet = sizeSet;
+      *aSetSize = sizeSet;
   }
 }
 
+PRBool
+nsAccessibilityUtils::HasAccGroupAttrs(nsIPersistentProperties *aAttributes)
+{
+  nsAutoString value;
+
+  GetAccAttr(aAttributes, nsAccessibilityAtoms::setsize, value);
+  if (!value.IsEmpty()) {
+    GetAccAttr(aAttributes, nsAccessibilityAtoms::posinset, value);
+    return !value.IsEmpty();
+  }
+
+  return PR_FALSE;
+}
+
 void
 nsAccessibilityUtils::SetAccGroupAttrs(nsIPersistentProperties *aAttributes,
                                        PRInt32 aLevel,
                                        PRInt32 aPosInSet,
-                                       PRInt32 aSizeSet)
+                                       PRInt32 aSetSize)
 {
   nsAutoString value;
 
   if (aLevel) {
     value.AppendInt(aLevel);
     SetAccAttr(aAttributes, nsAccessibilityAtoms::level, value);
   }
 
-  if (aSizeSet && aPosInSet) {
+  if (aSetSize && aPosInSet) {
     value.Truncate();
     value.AppendInt(aPosInSet);
     SetAccAttr(aAttributes, nsAccessibilityAtoms::posinset, value);
 
     value.Truncate();
-    value.AppendInt(aSizeSet);
+    value.AppendInt(aSetSize);
     SetAccAttr(aAttributes, nsAccessibilityAtoms::setsize, value);
   }
 }
 
 void
 nsAccessibilityUtils::SetAccAttrsForXULSelectControlItem(nsIDOMNode *aNode,
                                                          nsIPersistentProperties *aAttributes)
 {
--- a/accessible/src/base/nsAccessibilityUtils.h
+++ b/accessible/src/base/nsAccessibilityUtils.h
@@ -70,25 +70,30 @@ public:
                          const nsAString& aAttrValue);
 
   /**
    * Return values of group attributes ('level', 'setsize', 'posinset')
    */
   static void GetAccGroupAttrs(nsIPersistentProperties *aAttributes,
                                PRInt32 *aLevel,
                                PRInt32 *aPosInSet,
-                               PRInt32 *aSizeSet);
+                               PRInt32 *aSetSize);
+
+  /**
+   * Returns true if there are level, posinset and sizeset attributes.
+   */
+  static PRBool HasAccGroupAttrs(nsIPersistentProperties *aAttributes);
 
   /**
    * Set group attributes ('level', 'setsize', 'posinset').
    */
   static void SetAccGroupAttrs(nsIPersistentProperties *aAttributes,
                                PRInt32 aLevel,
                                PRInt32 aPosInSet,
-                               PRInt32 aSizeSet);
+                               PRInt32 aSetSize);
 
   /**
    * Set group attributes - 'level', 'setsize', 'posinset'.
    *
    * @param aNode - XUL element that implements
    *                nsIDOMXULSelectControlItemElement interface
    * @param aAttributes - attributes container
    */
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -2111,41 +2111,32 @@ NS_IMETHODIMP nsAccessible::GetFinalRole
     *aRole = mRoleMapEntry->role;
     if (*aRole != nsIAccessibleRole::ROLE_NOTHING) {
       return NS_OK;
     }
   }
   return mDOMNode ? GetRole(aRole) : NS_ERROR_FAILURE;  // Node already shut down
 }
 
-NS_IMETHODIMP nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+NS_IMETHODIMP
+nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
 {
-  *aAttributes = nsnull;
-
-  if (!mDOMNode) {
-    return NS_ERROR_FAILURE;  // Node already shut down
-  }
-
-  nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
-  NS_ENSURE_TRUE(element, NS_ERROR_UNEXPECTED);
+  NS_ENSURE_ARG_POINTER(aAttributes);
 
   nsCOMPtr<nsIPersistentProperties> attributes =
      do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
   NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
 
-  nsAutoString tagName;
-  nsAutoString oldValueUnused; 
-  element->GetTagName(tagName);
-  if (!tagName.IsEmpty()) {
-    attributes->SetStringProperty(NS_LITERAL_CSTRING("tag"), tagName, oldValueUnused);
-  }
-  
+  nsresult rv = GetAttributesInternal(attributes);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   nsCOMPtr<nsIContent> content = GetRoleContent(mDOMNode);
   if (content) {
     nsAutoString id;
+    nsAutoString oldValueUnused;
     if (content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::id, id)) {
       attributes->SetStringProperty(NS_LITERAL_CSTRING("id"), id, oldValueUnused);    
     }
     // XXX In the future we may need to expose the dynamic content role inheritance chain
     // through this attribute
     nsAutoString xmlRole;
     if (GetRoleAttribute(content, xmlRole)) {
       attributes->SetStringProperty(NS_LITERAL_CSTRING("xml-roles"), xmlRole, oldValueUnused);          
@@ -2158,21 +2149,99 @@ NS_IMETHODIMP nsAccessible::GetAttribute
       nsCOMPtr<nsIAtom> attr = do_GetAtom(ariaProperties[index]);
       if (content->GetAttr(kNameSpaceID_WAIProperties, attr, value)) {
         ToLowerCase(value);
         attributes->SetStringProperty(nsDependentCString(ariaProperties[index]), value, oldValueUnused);    
       }
     }
   }
 
+  if (!nsAccessibilityUtils::HasAccGroupAttrs(attributes)) {
+    // The role of an accessible can be pointed by ARIA attribute but ARIA
+    // posinset, level, setsize may be skipped. Therefore we calculate here
+    // these properties to map them into description.
+
+    PRUint32 role = Role(this);
+    if (role == nsIAccessibleRole::ROLE_LISTITEM ||
+        role == nsIAccessibleRole::ROLE_MENUITEM ||
+        role == nsIAccessibleRole::ROLE_RADIOBUTTON ||
+        role == nsIAccessibleRole::ROLE_PAGETAB ||
+        role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
+
+      nsCOMPtr<nsIAccessible> parent = GetParent();
+      NS_ENSURE_TRUE(parent, NS_ERROR_FAILURE);
+
+      PRInt32 positionInGroup = 0;
+      PRInt32 setSize = 0;
+
+      nsCOMPtr<nsIAccessible> sibling, nextSibling;
+      parent->GetFirstChild(getter_AddRefs(sibling));
+      NS_ENSURE_TRUE(sibling, NS_ERROR_FAILURE);
+
+      PRBool foundCurrent = PR_FALSE;
+      PRUint32 siblingRole;
+      while (sibling) {
+        sibling->GetFinalRole(&siblingRole);
+        if (siblingRole == role) {
+          ++ setSize;
+          if (!foundCurrent) {
+            ++ positionInGroup;
+            if (sibling == this)
+              foundCurrent = PR_TRUE;
+          }
+        }
+        sibling->GetNextSibling(getter_AddRefs(nextSibling));
+        sibling = nextSibling;
+      }
+
+      PRInt32 groupLevel = 0;
+      if (role == nsIAccessibleRole::ROLE_OUTLINEITEM) {
+        groupLevel = 1;
+        nsCOMPtr<nsIAccessible> nextParent;
+        while (parent) {
+          parent->GetFinalRole(&role);
+
+          if (role == nsIAccessibleRole::ROLE_OUTLINE)
+            break;
+          if (role == nsIAccessibleRole::ROLE_OUTLINEITEM)
+            ++ groupLevel;
+
+          parent->GetParent(getter_AddRefs(nextParent));
+          parent.swap(nextParent);
+        }
+      }
+
+      nsAccessibilityUtils::SetAccGroupAttrs(attributes, groupLevel,
+                                             positionInGroup,
+                                             setSize);
+    }
+  }
+
   attributes.swap(*aAttributes);
 
   return NS_OK;
 }
 
+nsresult
+nsAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
+{
+  nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mDOMNode));
+  NS_ENSURE_TRUE(element, NS_ERROR_UNEXPECTED);
+
+  nsAutoString tagName;
+  element->GetTagName(tagName);
+  if (!tagName.IsEmpty()) {
+    nsAutoString oldValueUnused;
+    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("tag"), tagName,
+                                   oldValueUnused);
+  }
+
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsAccessible::GroupPosition(PRInt32 *aGroupLevel,
                             PRInt32 *aSimilarItemsInGroup,
                             PRInt32 *aPositionInGroup)
 {
   // Every element exposes level/posinset/sizeset for IAccessdible::attributes
   // if they make sense for it. These attributes are mapped into groupPosition.
   // If 'level' attribute doesn't make sense element then it isn't represented
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -162,16 +162,22 @@ public:
    * Return the state of accessible that doesn't take into account ARIA states.
    * Use nsIAccessible::finalState() to get all states for accessible. If
    * second argument is omitted then second bit field of accessible state won't
    * be calculated.
    */
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
 
   /**
+   * Returns attributes for accessible without explicitly setted ARIA
+   * attributes.
+   */
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
+
+  /**
    * Maps ARIA state attributes to state of accessible. Note the given state
    * argument should hold states for accessible before you pass it into this
    * method.
    */
   nsresult GetARIAState(PRUint32 *aState);
 
 #ifdef MOZ_ACCESSIBILITY_ATK
   static PRBool FindTextFrame(PRInt32 &index, nsPresContext *aPresContext, nsIFrame *aCurFrame, 
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -134,23 +134,23 @@ nsHTMLRadioButtonAccessible::GetState(PR
     htmlRadioElement->GetChecked(&checked);
 
   if (checked)
     *aState |= nsIAccessibleStates::STATE_CHECKED;
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsHTMLRadioButtonAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsHTMLRadioButtonAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
   NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
 
-  nsresult rv = nsRadioButtonAccessible::GetAttributes(aAttributes);
+  nsresult rv = nsRadioButtonAccessible::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString nsURI;
   mDOMNode->GetNamespaceURI(nsURI);
   nsAutoString tagName;
   mDOMNode->GetLocalName(tagName);
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
@@ -198,17 +198,17 @@ nsHTMLRadioButtonAccessible::GetAttribut
       count++;
 
       if (itemNode == mDOMNode)
         indexOf = count;
     }
   }
 
   nsAccessibilityUtils::
-    SetAccGroupAttrs(*aAttributes, 0, indexOf, count);
+    SetAccGroupAttrs(aAttributes, 0, indexOf, count);
 
   return  NS_OK;
 }
 
 // ----- Button -----
 
 nsHTMLButtonAccessible::nsHTMLButtonAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
 nsHyperTextAccessible(aNode, aShell)
--- a/accessible/src/html/nsHTMLFormControlAccessible.h
+++ b/accessible/src/html/nsHTMLFormControlAccessible.h
@@ -58,17 +58,17 @@ public:
 
 class nsHTMLRadioButtonAccessible : public nsRadioButtonAccessible
 {
 
 public:
   nsHTMLRadioButtonAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
 
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 };
 
 class nsHTMLButtonAccessible : public nsHyperTextAccessible
 {
 
 public:
   enum { eAction_Click = 0 };
 
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -519,38 +519,38 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessib
         return NS_OK;
       }
     }
   }
   
   return NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP
-nsHTMLSelectOptionAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsHTMLSelectOptionAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
   NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
 
-  nsresult rv = nsHyperTextAccessible::GetAttributes(aAttributes);
+  nsresult rv = nsHyperTextAccessible::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
   NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIContent> parentContent = content->GetParent();
   NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE);
 
   PRUint32 level =
     parentContent->NodeInfo()->Equals(nsAccessibilityAtoms::optgroup) ? 2 : 1;
   PRUint32 childCount = parentContent->GetChildCount();
   PRUint32 indexOf = parentContent->IndexOf(content);
 
   nsAccessibilityUtils::
-    SetAccGroupAttrs(*aAttributes, level, indexOf + 1, childCount);
+    SetAccGroupAttrs(aAttributes, level, indexOf + 1, childCount);
   return  NS_OK;
 }
 
 nsIFrame* nsHTMLSelectOptionAccessible::GetBoundsFrame()
 {
   nsCOMPtr<nsIContent> selectContent(do_QueryInterface(mDOMNode));
 
   while (selectContent && selectContent->Tag() != nsAccessibilityAtoms::select) {
--- a/accessible/src/html/nsHTMLSelectAccessible.h
+++ b/accessible/src/html/nsHTMLSelectAccessible.h
@@ -159,17 +159,17 @@ public:
 
   /* ----- nsIAccessible ----- */
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
   NS_IMETHOD GetRole(PRUint32 *aRole);
   NS_IMETHOD GetName(nsAString& aName);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 
   nsIFrame*  GetBoundsFrame();
   static nsresult GetFocusedOptionNode(nsIDOMNode *aListNode, nsIDOMNode **aFocusedOptionNode);
   static void SelectionChangedIfOption(nsIContent *aPossibleOption);
 };
 
 /*
  * Opt Groups inside the select, contained within the list
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -194,30 +194,32 @@ NS_IMETHODIMP nsHTMLTableAccessible::Get
       nsCOMPtr<nsIContent> content(do_QueryInterface(element));
       NS_ASSERTION(content, "No content for DOM element");
       content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::summary, aName);
     }
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP nsHTMLTableAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   if (!mDOMNode) {
     return NS_ERROR_FAILURE;  // Node already shut down
   }
 
-  nsresult rv = nsAccessibleWrap::GetAttributes(aAttributes);
+  nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
   
   PRBool isProbablyForLayout;
   IsProbablyForLayout(&isProbablyForLayout);
   if (isProbablyForLayout) {
     nsAutoString oldValueUnused;
-    (*aAttributes)->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"), NS_LITERAL_STRING("true"), oldValueUnused);
+    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
+                                   NS_LITERAL_STRING("true"), oldValueUnused);
   }
   
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
 {
--- a/accessible/src/html/nsHTMLTableAccessible.h
+++ b/accessible/src/html/nsHTMLTableAccessible.h
@@ -65,17 +65,17 @@ class nsHTMLTableAccessible : public nsA
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLETABLE
 
   nsHTMLTableAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
   NS_IMETHOD GetRole(PRUint32 *aResult); 
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
   NS_IMETHOD GetName(nsAString& aResult);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 #ifdef SHOW_LAYOUT_HEURISTIC
   NS_IMETHOD GetDescription(nsAString& aDescription);
 #endif
 
 protected:
   virtual void CacheChildren();
   nsresult GetTableNode(nsIDOMNode **_retval);
   nsresult GetTableLayout(nsITableLayout **aLayoutObject);
--- a/accessible/src/html/nsHTMLTextAccessible.cpp
+++ b/accessible/src/html/nsHTMLTextAccessible.cpp
@@ -125,34 +125,29 @@ nsHTMLTextAccessible::GetState(PRUint32 
      if (0 == (extState & nsIAccessibleStates::EXT_STATE_EDITABLE)) {
        *aState |= nsIAccessibleStates::STATE_READONLY; // Links not focusable in editor
      }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP nsHTMLTextAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsHTMLTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
-  *aAttributes = nsnull;
-
   if (!mDOMNode) {
     return NS_ERROR_FAILURE;  // Node already shut down
   }
 
   PRUint32 role;
   GetRole(&role);
   if (role == nsIAccessibleRole::ROLE_STATICTEXT) {
-    nsCOMPtr<nsIPersistentProperties> attributes =
-        do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
-    NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
     nsAutoString oldValueUnused;
-    attributes->SetStringProperty(NS_LITERAL_CSTRING("static"),
+    aAttributes->SetStringProperty(NS_LITERAL_CSTRING("static"),
                                   NS_LITERAL_STRING("true"), oldValueUnused);
-    attributes.swap(*aAttributes);
   }
 
   return NS_OK;
 }
 
 nsHTMLHRAccessible::nsHTMLHRAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
 nsLeafAccessible(aDomNode, aShell)
 { 
--- a/accessible/src/html/nsHTMLTextAccessible.h
+++ b/accessible/src/html/nsHTMLTextAccessible.h
@@ -49,17 +49,17 @@ class nsHTMLTextAccessible : public nsTe
 {
 public:
   nsHTMLTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell, nsIFrame *aFrame);
   
   // nsIAccessible
   NS_IMETHOD GetName(nsAString& _retval);
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
   NS_IMETHOD GetRole(PRUint32 *aRole);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   NS_IMETHOD Shutdown() { mFrame = nsnull; return nsTextAccessibleWrap::Shutdown(); }
   
   // nsPIAccessNode
   NS_IMETHOD_(nsIFrame *) GetFrame(void);
 
   // nsPIAccessible
   NS_IMETHOD FireToolkitEvent(PRUint32 aEvent, nsIAccessible *aTarget,
                               void *aData);
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -806,47 +806,50 @@ NS_IMETHODIMP nsHyperTextAccessible::Get
       return NS_OK;
     }
     *aRangeStartOffset += length;
   }
 
   return NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP nsHyperTextAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   if (!mDOMNode) {
     return NS_ERROR_FAILURE;  // Node already shut down
   }
 
-  nsresult rv = nsAccessibleWrap::GetAttributes(aAttributes);
+  nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
   NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED);
   nsIAtom *tag = content->Tag();
 
-  nsAutoString headLevel;
+  PRInt32 headLevel = 0;
   if (tag == nsAccessibilityAtoms::h1)
-    headLevel.AssignLiteral("1");
+    headLevel = 1;
   else if (tag == nsAccessibilityAtoms::h2)
-    headLevel.AssignLiteral("2");
+    headLevel = 2;
   else if (tag == nsAccessibilityAtoms::h3)
-    headLevel.AssignLiteral("3");
+    headLevel = 3;
   else if (tag == nsAccessibilityAtoms::h4)
-    headLevel.AssignLiteral("4");
+    headLevel = 4;
   else if (tag == nsAccessibilityAtoms::h5)
-    headLevel.AssignLiteral("5");
+    headLevel = 5;
   else if (tag == nsAccessibilityAtoms::h6)
-    headLevel.AssignLiteral("6");
+    headLevel = 6;
 
-  if (!headLevel.IsEmpty()) {
-    nsAccessibilityUtils::SetAccAttr(*aAttributes,
+  if (headLevel) {
+    nsAutoString strHeadLevel;
+    strHeadLevel.AppendInt(headLevel);
+    nsAccessibilityUtils::SetAccAttr(aAttributes,
                                      nsAccessibilityAtoms::level,
-                                     headLevel);
+                                     strHeadLevel);
   }
 
   return  NS_OK;
 }
 
 /*
  * Given an offset, the x, y, width, and height values are filled appropriately.
  */
--- a/accessible/src/html/nsHyperTextAccessible.h
+++ b/accessible/src/html/nsHyperTextAccessible.h
@@ -71,17 +71,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLETEXT
   NS_DECL_NSIACCESSIBLEHYPERTEXT
   NS_DECL_NSIACCESSIBLEEDITABLETEXT
   NS_DECL_NSIEDITACTIONLISTENER
 
   NS_IMETHOD GetRole(PRUint32 *aRole);
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   void CacheChildren();
 
 protected:
   PRBool IsHyperText();
 
   /*
    * This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
    * @param aType, eGetBefore, eGetAt, eGetAfter
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -323,135 +323,80 @@ nsAccessibleWrap::get_accDescription(VAR
   PRInt32 similarItemsInGroup;
   PRInt32 positionInGroup;
 
   nsresult rv = xpAccessible->GroupPosition(&groupLevel, &similarItemsInGroup,
                                             &positionInGroup);
   if (NS_SUCCEEDED(rv)) {
     if (positionInGroup != -1 && similarItemsInGroup != -1) {
       if (groupLevel != -1) {
-        // XXX: How do we calculate the number of children?
-        // Normally we would append " with [numChildren]c" if we had that
-        // information. In the future we may need to use the ARIA owns property
-        // to calculate that if it's present.
-        nsTextFormatter::ssprintf(description,
-                                  NS_LITERAL_STRING("L%d, %d of %d").get(),
-                                  groupLevel, positionInGroup + 1,
-                                  similarItemsInGroup + 1);
+        // XXX: How do we calculate the number of children? Now we append
+        // " with [numChildren]c" for tree item. In the future we may need to
+        // use the ARIA owns property to calculate that if it's present.
+        PRInt32 numChildren = 0;
+
+        PRUint32 currentRole = 0;
+        rv = xpAccessible->GetFinalRole(&currentRole);
+        if (NS_SUCCEEDED(rv) &&
+            currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM) {
+          nsCOMPtr<nsIAccessible> child;
+          xpAccessible->GetFirstChild(getter_AddRefs(child));
+          while (child) {
+            child->GetFinalRole(&currentRole);
+            if (currentRole == nsIAccessibleRole::ROLE_GROUPING) {
+              nsCOMPtr<nsIAccessible> groupChild;
+              child->GetFirstChild(getter_AddRefs(groupChild));
+              while (groupChild) {
+                groupChild->GetFinalRole(&currentRole);
+                numChildren +=
+                  (currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM);
+                nsCOMPtr<nsIAccessible> nextGroupChild;
+                groupChild->GetNextSibling(getter_AddRefs(nextGroupChild));
+                groupChild.swap(nextGroupChild);
+              }
+              break;
+            }
+            nsCOMPtr<nsIAccessible> nextChild;
+            child->GetNextSibling(getter_AddRefs(nextChild));
+            child.swap(nextChild);
+          }
+        }
+
+        if (numChildren) {
+          nsTextFormatter::ssprintf(description,
+                                    NS_LITERAL_STRING("L%d, %d of %d with %d").get(),
+                                    groupLevel, positionInGroup + 1,
+                                    similarItemsInGroup + 1, numChildren);
+        } else {
+          nsTextFormatter::ssprintf(description,
+                                    NS_LITERAL_STRING("L%d, %d of %d").get(),
+                                    groupLevel, positionInGroup + 1,
+                                    similarItemsInGroup + 1);
+        }
       } else { // Position has no level
         nsTextFormatter::ssprintf(description,
                                   NS_LITERAL_STRING("%d of %d").get(),
                                   positionInGroup + 1, similarItemsInGroup + 1);
       }
 
       *pszDescription = ::SysAllocString(description.get());
       return S_OK;
     }
   }
 
-  PRUint32 currentRole;
-  rv = xpAccessible->GetFinalRole(&currentRole);
-  if (NS_FAILED(rv) ||
-      (currentRole != nsIAccessibleRole::ROLE_LISTITEM &&
-       currentRole != nsIAccessibleRole::ROLE_MENUITEM &&
-       currentRole != nsIAccessibleRole::ROLE_RADIOBUTTON &&
-       currentRole != nsIAccessibleRole::ROLE_PAGETAB &&
-       currentRole != nsIAccessibleRole::ROLE_OUTLINEITEM)) {
-    xpAccessible->GetDescription(description);
-    if (!description.IsEmpty()) {
-      // Signal to screen readers that this description is speakable
-      // and is not a formatted positional information description
-      // Don't localize the "Description: " part of this string, it will be
-      // parsed out by assistive technologies.
-      description = NS_LITERAL_STRING("Description: ") + description;
-    }
-
-    *pszDescription = ::SysAllocString(description.get());
-    return S_OK;
+  xpAccessible->GetDescription(description);
+  if (!description.IsEmpty()) {
+    // Signal to screen readers that this description is speakable
+    // and is not a formatted positional information description
+    // Don't localize the "Description: " part of this string, it will be
+    // parsed out by assistive technologies.
+    description = NS_LITERAL_STRING("Description: ") + description;
   }
 
-  // XXX: The role of an accessible can be pointed by ARIA attribute but
-  // ARIA posinset, level, setsize may be skipped. Therefore we calculate
-  // here these properties to map them into description. This should be
-  // handled in cross-platform code.
-
-  nsCOMPtr<nsIAccessible> parent;
-  xpAccessible->GetParent(getter_AddRefs(parent));
-  NS_ENSURE_TRUE(parent, NS_ERROR_FAILURE);
-
-  positionInGroup = 0;
-  similarItemsInGroup = 0;
-
-  nsCOMPtr<nsIAccessible> sibling, nextSibling;
-  parent->GetFirstChild(getter_AddRefs(sibling));
-  if (!sibling)
-    return E_FAIL;
-
-  PRBool foundCurrent = PR_FALSE;
-  PRUint32 siblingRole;
-  while (sibling) {
-    sibling->GetFinalRole(&siblingRole);
-    if (siblingRole == currentRole) {
-      ++ similarItemsInGroup;
-      if (!foundCurrent) {
-        ++ positionInGroup;
-        if (sibling == this)
-          foundCurrent = PR_TRUE;
-      }
-    }
-    sibling->GetNextSibling(getter_AddRefs(nextSibling));
-    sibling = nextSibling;
-  }
-
-  // Don't localize the string "of" -- that's just the format of this string.
-  // The AT will parse the relevant numbers out and add its own localization.
-  if (currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM) {
-    groupLevel = 1;
-    nsCOMPtr<nsIAccessible> nextParent;
-    while (parent) {
-      parent->GetFinalRole(&currentRole);
-      if (currentRole != nsIAccessibleRole::ROLE_GROUPING)
-        break;
-
-      ++ groupLevel;
-      parent->GetParent(getter_AddRefs(nextParent));
-      parent.swap(nextParent);
-    }
-
-    // Count the number of tree item children
-    PRInt32 numChildren = 0;
-    nsCOMPtr<nsIAccessible> groupSibling;
-    xpAccessible->GetNextSibling(getter_AddRefs(groupSibling));
-    if (groupSibling) {
-      groupSibling->GetFinalRole(&currentRole);
-      if (currentRole == nsIAccessibleRole::ROLE_GROUPING) {
-        // Accessible that groups child tree items
-        nsCOMPtr<nsIAccessible> child;
-        groupSibling->GetFirstChild(getter_AddRefs(child));
-        while (child) {
-          child->GetFinalRole(&currentRole);
-          numChildren += (currentRole == nsIAccessibleRole::ROLE_OUTLINEITEM);
-          nsCOMPtr<nsIAccessible> nextChild;
-          child->GetNextSibling(getter_AddRefs(nextChild));
-          child.swap(nextChild);
-        }
-      }
-    }
-
-    // This must be a DHTML tree item -- XUL tree items impl GetDescription()
-    nsTextFormatter::ssprintf(description,
-                              NS_LITERAL_STRING("L%d, %d of %d with %d").get(),
-                              groupLevel, positionInGroup,
-                              similarItemsInGroup, numChildren);
-  } else {
-    nsTextFormatter::ssprintf(description, NS_LITERAL_STRING("%d of %d").get(),
-                              positionInGroup, similarItemsInGroup);
-  }
-
- *pszDescription = ::SysAllocString(description.get());
+  *pszDescription = ::SysAllocString(description.get());
   return S_OK;
 }
 
 STDMETHODIMP nsAccessibleWrap::get_accRole(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarRole)
 {
   VariantInit(pvarRole);
--- a/accessible/src/xforms/nsXFormsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsAccessible.cpp
@@ -236,31 +236,31 @@ nsXFormsAccessible::GetDescription(nsASt
     aDescription = description;
     return NS_OK;
   }
 
   // search the xforms:hint element
   return GetBoundChildElementValue(NS_LITERAL_STRING("hint"), aDescription);
 }
 
-NS_IMETHODIMP
-nsXFormsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsXFormsAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
 
-  nsresult rv = nsHyperTextAccessible::GetAttributes(aAttributes);
+  nsresult rv = nsHyperTextAccessible::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString name;
   rv = sXFormsService->GetBuiltinTypeName(mDOMNode, name);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoString unused;
-  return (*aAttributes)->SetStringProperty(NS_LITERAL_CSTRING("datatype"),
-                                           name, unused);
+  return aAttributes->SetStringProperty(NS_LITERAL_CSTRING("datatype"),
+                                        name, unused);
 }
 
 NS_IMETHODIMP
 nsXFormsAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
 {
   NS_ENSURE_ARG_POINTER(aAllowsAnonChildren);
 
   *aAllowsAnonChildren = PR_FALSE;
--- a/accessible/src/xforms/nsXFormsAccessible.h
+++ b/accessible/src/xforms/nsXFormsAccessible.h
@@ -82,17 +82,17 @@ public:
   // Returns value of child xforms 'label' element.
   NS_IMETHOD GetName(nsAString& aName);
 
   // Returns value of child xforms 'hint' element.
   NS_IMETHOD GetDescription(nsAString& aDescription);
 
   // Appends ARIA 'datatype' property based on datatype of instance node that
   // element is bound to.
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 
   // Denies accessible nodes in anonymous content of xforms element by
   // always returning PR_FALSE value.
   NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
 
 protected:
   // Returns value of first child xforms element by tagname that is bound to
   // instance node.
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -539,27 +539,27 @@ nsXULRadioButtonAccessible::GetState(PRU
     if (selected) {
       *aState |= nsIAccessibleStates::STATE_CHECKED;
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULRadioButtonAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsXULRadioButtonAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
   NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
 
-  nsresult rv = nsFormControlAccessible::GetAttributes(aAttributes);
+  nsresult rv = nsFormControlAccessible::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAccessibilityUtils::
-    SetAccAttrsForXULSelectControlItem(mDOMNode, *aAttributes);
+    SetAccAttrsForXULSelectControlItem(mDOMNode, aAttributes);
 
   return NS_OK;
 }
 
 /**
   * XUL Radio Group
   *   The Radio Group proxies for the Radio Buttons themselves. The Group gets
   *   focus whereas the Buttons do not. So we only have an accessible object for
--- a/accessible/src/xul/nsXULFormControlAccessible.h
+++ b/accessible/src/xul/nsXULFormControlAccessible.h
@@ -109,17 +109,17 @@ public:
 };
 
 class nsXULRadioButtonAccessible : public nsRadioButtonAccessible
 {
 
 public:
   nsXULRadioButtonAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 };
 
 class nsXULRadioGroupAccessible : public nsXULSelectableAccessible
 {
 public:
   nsXULRadioGroupAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
   NS_IMETHOD GetRole(PRUint32 *_retval); 
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -433,30 +433,30 @@ NS_IMETHODIMP nsXULMenuitemAccessible::G
     if (childCount > 0) {
       *aRole = nsIAccessibleRole::ROLE_PARENT_MENUITEM;
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULMenuitemAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsXULMenuitemAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
   NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
 
-  nsresult rv = nsAccessible::GetAttributes(aAttributes);
+  nsresult rv = nsAccessible::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // XXX: we don't support xul:menuitem inside xul:menu element now until
   // bug 372552 is fixed.
 
   nsAccessibilityUtils::
-    SetAccAttrsForXULSelectControlItem(mDOMNode, *aAttributes);
+    SetAccAttrsForXULSelectControlItem(mDOMNode, aAttributes);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULMenuitemAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
 {
   // That indicates we don't walk anonymous children for menuitems
--- a/accessible/src/xul/nsXULMenuAccessible.h
+++ b/accessible/src/xul/nsXULMenuAccessible.h
@@ -81,17 +81,17 @@ public:
   NS_IMETHOD GetDescription(nsAString& aDescription);
   NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
   NS_IMETHOD GetDefaultKeyBinding(nsAString& aKeyBinding);
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
   NS_IMETHOD GetRole(PRUint32 *_retval); 
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
 };
 
 class nsXULMenuSeparatorAccessible : public nsXULMenuitemAccessible
 {
 public:
   nsXULMenuSeparatorAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell);
   NS_IMETHOD GetName(nsAString& _retval); 
--- a/accessible/src/xul/nsXULTabAccessible.cpp
+++ b/accessible/src/xul/nsXULTabAccessible.cpp
@@ -124,27 +124,27 @@ nsXULTabAccessible::GetState(PRUint32 *a
   if (tab) {
     PRBool selected = PR_FALSE;
     if (NS_SUCCEEDED(tab->GetSelected(&selected)) && selected)
       *aState |= nsIAccessibleStates::STATE_SELECTED;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULTabAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsXULTabAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
   NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
 
-  nsresult rv = nsLeafAccessible::GetAttributes(aAttributes);
+  nsresult rv = nsLeafAccessible::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAccessibilityUtils::
-    SetAccAttrsForXULSelectControlItem(mDOMNode, *aAttributes);
+    SetAccAttrsForXULSelectControlItem(mDOMNode, aAttributes);
 
   return NS_OK;
 }
 
 /**
   * XUL TabBox
   *  to facilitate naming of the tabPanels object we will give this the name
   *   of the selected tab in the tabs object.
--- a/accessible/src/xul/nsXULTabAccessible.h
+++ b/accessible/src/xul/nsXULTabAccessible.h
@@ -50,17 +50,17 @@ public:
   enum { eAction_Switch = 0 };
 
   nsXULTabAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
   NS_IMETHOD GetRole(PRUint32 *_retval); 
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 };
 
 /** 
   * Contains a tabs object and a tabPanels object. A complete
   *    entity with relationships between tabs and content to
   *    be displayed in the tabpanels object
   */
 class nsXULTabBoxAccessible : public nsAccessibleWrap
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -676,23 +676,23 @@ NS_IMETHODIMP nsXULTreeitemAccessible::G
     }
 
     return NS_OK;
   }
 
   return NS_ERROR_INVALID_ARG;
 }
 
-NS_IMETHODIMP
-nsXULTreeitemAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+nsresult
+nsXULTreeitemAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
   NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
 
-  nsresult rv = nsLeafAccessible::GetAttributes(aAttributes);
+  nsresult rv = nsLeafAccessible::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMXULTreeElement> tree(do_QueryInterface(mDOMNode));
   NS_ENSURE_TRUE(tree, NS_OK);
 
   nsCOMPtr<nsITreeView> view;
   tree->GetView(getter_AddRefs(view));
   NS_ENSURE_TRUE(view, NS_OK);
@@ -712,17 +712,17 @@ nsXULTreeitemAccessible::GetAttributes(n
   for (;endIndex - 1 > 0 &&
         NS_SUCCEEDED(view->GetLevel(endIndex - 1, &lvl)) && lvl != level;
         endIndex--);
 
   PRInt32 setSize = endIndex - startIndex + 1;
   PRInt32 posInSet = mRow - startIndex + 1;
 
   nsAccessibilityUtils::
-    SetAccGroupAttrs(*aAttributes, level + 1, posInSet, setSize);
+    SetAccGroupAttrs(aAttributes, level + 1, posInSet, setSize);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsXULTreeitemAccessible::GetParent(nsIAccessible **aParent)
 {
   *aParent = nsnull;
 
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -105,17 +105,17 @@ public:
   NS_IMETHOD Shutdown();
 
   /* ----- nsIAccessible ----- */
   NS_IMETHOD GetName(nsAString& _retval);
   NS_IMETHOD GetRole(PRUint32 *_retval);
   NS_IMETHOD GetState(PRUint32 *aState, PRUint32 *aExtraState);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
-  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
+  virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
 
   NS_IMETHOD GetParent(nsIAccessible **_retval);
   NS_IMETHOD GetNextSibling(nsIAccessible **_retval);
   NS_IMETHOD GetPreviousSibling(nsIAccessible **_retval);
 
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
   NS_IMETHOD SetSelected(PRBool aSelect);