Fix for bug 371594 - expose groupPosition for Gecko. r=aaronlev
authorsurkov.alexander@gmail.com
Tue, 27 Mar 2007 05:17:11 -0700
changeset 144 e18f1a1049c14dc0bb735305b3f15de1f6417cdc
parent 143 6b5f78b57c59072d0dacf8e9c6614d84d76cbb89
child 145 8c47343c89eb98edc60117bfd618e86e4e85184c
push idunknown
push userunknown
push dateunknown
reviewersaaronlev
bugs371594
milestone1.9a4pre
Fix for bug 371594 - expose groupPosition for Gecko. r=aaronlev
accessible/public/nsIAccessible.idl
accessible/src/atk/Makefile.in
accessible/src/atk/nsAccessibleWrap.cpp
accessible/src/atk/nsAccessibleWrap.h
accessible/src/atk/nsHTMLFormControlAccessibleWrap.h
accessible/src/base/Makefile.in
accessible/src/base/nsAccessibilityService.cpp
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/nsHTMLTextAccessible.cpp
accessible/src/html/nsHyperTextAccessible.cpp
accessible/src/mac/Makefile.in
accessible/src/mac/nsHTMLFormControlAccessibleWrap.h
accessible/src/msaa/Makefile.in
accessible/src/msaa/nsAccessibleWrap.cpp
accessible/src/msaa/nsAccessibleWrap.h
accessible/src/msaa/nsHTMLFormControlAccessibleWrap.cpp
accessible/src/msaa/nsHTMLFormControlAccessibleWrap.h
accessible/src/msaa/nsXULTreeAccessibleWrap.cpp
accessible/src/msaa/nsXULTreeAccessibleWrap.h
accessible/src/other/Makefile.in
accessible/src/other/nsHTMLFormControlAccessibleWrap.h
accessible/src/xforms/nsXFormsAccessible.cpp
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/public/nsIAccessible.idl
+++ b/accessible/public/nsIAccessible.idl
@@ -52,17 +52,17 @@ interface nsIDOMDOMStringList;
  * Can also be used by in-process accessibility clients to get information
  * about objects in the accessible tree. The accessible tree is a subset of 
  * nodes in the DOM tree -- such as documents, focusable elements and text.
  * Mozilla creates the implementations of nsIAccessible on demand.
  * See http://www.mozilla.org/projects/ui/accessibility for more information.
  *
  * @status UNDER_REVIEW
  */
-[scriptable, uuid(6ff04a18-a66c-4e50-9099-8e46eca181f6)]
+[scriptable, uuid(1f4ab23c-2878-4b26-9679-855f839d4542)]
 interface nsIAccessible : nsISupports
 {
   /**
    * Parent node in accessible tree.
    */
   readonly attribute nsIAccessible parent;
 
   /**
@@ -182,16 +182,27 @@ interface nsIAccessible : nsISupports
   readonly attribute nsIAccessible focusedChild;
 
   /**
    * Attributes of accessible
    */
   readonly attribute nsIPersistentProperties attributes;
 
   /**
+   * Returns grouping information. Used for tree items, list items, tab panel
+   * labels, radio buttons, etc. Also used for collectons of non-text objects.
+   *
+   * @param groupLevel - 0-based, similar to ARIA 'level' property
+   * @param similarItemsInGroup - 1-based, similar to ARIA 'setsize' property
+   * @param positionInGroup - 0-based, similar to ARIA 'posinset' property
+   */
+  void groupPosition(out long aGroupLevel, out long aSimilarItemsInGroup,
+                     out long aPositionInGroup);
+
+  /**
    * Accessible child which contains the coordinate at (x, y) in screen pixels.
    */
   nsIAccessible getChildAtPoint(in long x, in long y);
 
   /**
    * Nth accessible child using zero-based index or last child if index less than zero
    */
   nsIAccessible getChildAt(in long aChildIndex);
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -87,17 +87,16 @@ CPPSRCS += \
   nsXULTreeAccessibleWrap.cpp \
   $(NULL)
 endif
 
 EXPORTS = \
   nsAccessNodeWrap.h \
   nsAccessibleWrap.h \
   nsDocAccessibleWrap.h \
-  nsHTMLFormControlAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsTextAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   $(NULL)
 
 # we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -53,17 +53,16 @@
 #include "nsMaiInterfaceEditableText.h"
 #include "nsMaiInterfaceSelection.h"
 #include "nsMaiInterfaceValue.h"
 #include "nsMaiInterfaceHypertext.h"
 #include "nsMaiInterfaceHyperlinkImpl.h"
 #include "nsMaiInterfaceTable.h"
 #include "nsXPCOMStrings.h"
 #include "nsComponentManagerUtils.h"
-#include "nsIPersistentProperties2.h"
 #include "nsMaiInterfaceDocument.h"
 #include "nsMaiInterfaceImage.h"
 
 extern "C" GType g_atk_hyperlink_impl_type; //defined in nsAppRootAccessible.cpp
 
 /* MaiAtkObject */
 
 enum {
--- a/accessible/src/atk/nsAccessibleWrap.h
+++ b/accessible/src/atk/nsAccessibleWrap.h
@@ -85,11 +85,9 @@ public:
     
 protected:
     AtkObject *mAtkObject;
 
 private:
     PRUint16 CreateMaiInterfaces(void);
 };
 
-typedef class nsHTMLRadioButtonAccessible nsHTMLRadioButtonAccessibleWrap;
-
 #endif /* __NS_ACCESSIBLE_WRAP_H__ */
deleted file mode 100644
--- a/accessible/src/atk/nsHTMLFormControlAccessibleWrap.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Sun Microsystems, Inc.
- * Portions created by the Initial Developer are Copyright (C) 2002
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Kyle Yuan (kyle.yuan@sun.com)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef __nsHTMLFormControlAccessibleWrap_h__
-#define __nsHTMLFormControlAccessibleWrap_h__
-
-#include "nsHTMLFormControlAccessible.h"
-
-typedef class nsHTMLRadioButtonAccessible nsHTMLRadioButtonAccessibleWrap;
-
-#endif
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -72,16 +72,17 @@ REQUIRES	= appshell \
 		  $(NULL)
 
 CPPSRCS = \
   nsAccessNode.cpp \
   nsAccessibleEventData.cpp \
   nsDocAccessible.cpp \
   nsOuterDocAccessible.cpp \
   nsAccessibilityAtoms.cpp \
+  nsAccessibilityUtils.cpp \
   nsAccessibilityService.cpp \
   nsAccessible.cpp \
   nsAccessibleTreeWalker.cpp \
   nsBaseWidgetAccessible.cpp \
   nsFormControlAccessible.cpp \
   nsRootAccessible.cpp \
   nsCaretAccessible.cpp \
   nsTextAccessible.cpp \
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -37,17 +37,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 // NOTE: alphabetically ordered
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibilityService.h"
 #include "nsCURILoader.h"
 #include "nsDocAccessible.h"
 #include "nsHTMLAreaAccessible.h"
-#include "nsHTMLFormControlAccessibleWrap.h"
 #include "nsHTMLImageAccessible.h"
 #include "nsHTMLLinkAccessible.h"
 #include "nsHTMLSelectAccessible.h"
 #include "nsHTMLTableAccessible.h"
 #include "nsHTMLTextAccessible.h"
 #include "nsHyperTextAccessible.h"
 #include "nsIAccessibilityService.h"
 #include "nsIAccessibleProvider.h"
@@ -710,17 +709,17 @@ nsAccessibilityService::CreateHTMLRadioB
 {
   nsIFrame* frame;
   nsCOMPtr<nsIDOMNode> node;
   nsCOMPtr<nsIWeakReference> weakShell;
   nsresult rv = GetInfo(aFrame, &frame, getter_AddRefs(weakShell), getter_AddRefs(node));
   if (NS_FAILED(rv))
     return rv;
 
-  *_retval = new nsHTMLRadioButtonAccessibleWrap(node, weakShell);
+  *_retval = new nsHTMLRadioButtonAccessible(node, weakShell);
   if (! *_retval) 
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP 
new file mode 100755
--- /dev/null
+++ b/accessible/src/base/nsAccessibilityUtils.cpp
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAccessibilityUtils.h"
+#include "nsIDOMXULSelectCntrlEl.h"
+#include "nsIDOMXULSelectCntrlItemEl.h"
+
+void
+nsAccessibilityUtils::GetAccAttr(nsIPersistentProperties *aAttributes,
+                                 nsIAtom *aAttrName,
+                                 nsAString& aAttrValue)
+{
+  nsCAutoString attrName;
+  aAttrName->ToUTF8String(attrName);
+  aAttributes->GetStringProperty(attrName, aAttrValue);
+}
+
+void
+nsAccessibilityUtils::SetAccAttr(nsIPersistentProperties *aAttributes,
+                                 nsIAtom *aAttrName,
+                                 const nsAString& aAttrValue)
+{
+  nsAutoString oldValue;
+  nsCAutoString attrName;
+
+  aAttrName->ToUTF8String(attrName);
+  aAttributes->SetStringProperty(attrName, aAttrValue, oldValue);
+}
+
+void
+nsAccessibilityUtils::GetAccGroupAttrs(nsIPersistentProperties *aAttributes,
+                                       PRInt32 *aLevel,
+                                       PRInt32 *aPosInSet,
+                                       PRInt32 *aSizeSet)
+{
+  *aLevel = 0;
+  *aPosInSet = 0;
+  *aSizeSet = 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);
+  if (!value.IsEmpty()) {
+    PRInt32 posInSet = value.ToInteger(&error);
+    if (NS_SUCCEEDED(error))
+      *aPosInSet = posInSet;
+  }
+
+  GetAccAttr(aAttributes, nsAccessibilityAtoms::posinset, value);
+  if (!value.IsEmpty()) {
+    PRInt32 sizeSet = value.ToInteger(&error);
+    if (NS_SUCCEEDED(error))
+      *aSizeSet = sizeSet;
+  }
+}
+
+void
+nsAccessibilityUtils::SetAccGroupAttrs(nsIPersistentProperties *aAttributes,
+                                       PRInt32 aLevel,
+                                       PRInt32 aPosInSet,
+                                       PRInt32 aSizeSet)
+{
+  nsAutoString value;
+
+  if (aLevel) {
+    value.AppendInt(aLevel);
+    SetAccAttr(aAttributes, nsAccessibilityAtoms::level, value);
+  }
+
+  if (aSizeSet && aPosInSet) {
+    value.Truncate();
+    value.AppendInt(aPosInSet);
+    SetAccAttr(aAttributes, nsAccessibilityAtoms::posinset, value);
+
+    value.Truncate();
+    value.AppendInt(aSizeSet);
+    SetAccAttr(aAttributes, nsAccessibilityAtoms::setsize, value);
+  }
+}
+
+void
+nsAccessibilityUtils::SetAccAttrsForXULSelectControlItem(nsIDOMNode *aNode,
+                                                         nsIPersistentProperties *aAttributes)
+{
+  nsCOMPtr<nsIDOMXULSelectControlItemElement> item(do_QueryInterface(aNode));
+  if (!item)
+    return;
+
+  nsCOMPtr<nsIDOMXULSelectControlElement> control;
+  item->GetControl(getter_AddRefs(control));
+  if (!control)
+    return;
+
+  PRUint32 itemsCount;
+  control->GetItemCount(&itemsCount);
+  PRInt32 indexOf;
+  control->GetIndexOfItem(item, &indexOf);
+
+  SetAccGroupAttrs(aAttributes, 0, indexOf + 1, itemsCount);
+}
new file mode 100755
--- /dev/null
+++ b/accessible/src/base/nsAccessibilityUtils.h
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsAccessibilityUtils_h_
+#define nsAccessibilityUtils_h_
+
+#include "nsAccessibilityAtoms.h"
+
+#include "nsIDOMNode.h"
+#include "nsIPersistentProperties2.h"
+
+class nsAccessibilityUtils
+{
+public:
+  /**
+   * Returns value of attribute from the given attributes container.
+   *
+   * @param aAttributes - attributes container
+   * @param aAttrName - the name of requested attribute
+   * @param aAttrValue - value of attribute
+   */
+  static void GetAccAttr(nsIPersistentProperties *aAttributes,
+                         nsIAtom *aAttrName,
+                         nsAString& aAttrValue);
+
+  /**
+   * Set value of attribute for the given attributes container.
+   *
+   * @param aAttributes - attributes container
+   * @param aAttrName - the name of requested attribute
+   * @param aAttrValue - new value of attribute
+   */
+  static void SetAccAttr(nsIPersistentProperties *aAttributes,
+                         nsIAtom *aAttrName,
+                         const nsAString& aAttrValue);
+
+  /**
+   * Return values of group attributes ('level', 'setsize', 'posinset')
+   */
+  static void GetAccGroupAttrs(nsIPersistentProperties *aAttributes,
+                               PRInt32 *aLevel,
+                               PRInt32 *aPosInSet,
+                               PRInt32 *aSizeSet);
+
+  /**
+   * Set group attributes ('level', 'setsize', 'posinset').
+   */
+  static void SetAccGroupAttrs(nsIPersistentProperties *aAttributes,
+                               PRInt32 aLevel,
+                               PRInt32 aPosInSet,
+                               PRInt32 aSizeSet);
+
+  /**
+   * Set group attributes - 'level', 'setsize', 'posinset'.
+   *
+   * @param aNode - XUL element that implements
+   *                nsIDOMXULSelectControlItemElement interface
+   * @param aAttributes - attributes container
+   */
+  static void SetAccAttrsForXULSelectControlItem(nsIDOMNode *aNode,
+                                                 nsIPersistentProperties *aAttributes);
+};
+
+#endif
\ No newline at end of file
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -86,17 +86,16 @@
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIFocusController.h"
 #include "nsAccessibleTreeWalker.h"
 #include "nsIURI.h"
 #include "nsIImageLoadingContent.h"
 #include "nsITimer.h"
 #include "nsIMutableArray.h"
-#include "nsIPersistentProperties2.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMDocumentTraversal.h"
 #include "nsIDOMNodeFilter.h"
 
 #ifdef NS_DEBUG
 #include "nsIFrameDebug.h"
 #include "nsIDOMCharacterData.h"
 #endif
@@ -2118,16 +2117,56 @@ NS_IMETHODIMP nsAccessible::GetAttribute
     }
   }
 
   attributes.swap(*aAttributes);
 
   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
+  // via IAccessible::attributes and groupLevel of groupPosition method is 0.
+  // Elements that expose 'level' attribute only (like html headings elements)
+  // don't support this method and all arguements are equealed 0.
+
+  NS_ENSURE_ARG_POINTER(aGroupLevel);
+  NS_ENSURE_ARG_POINTER(aSimilarItemsInGroup);
+  NS_ENSURE_ARG_POINTER(aPositionInGroup);
+
+  *aGroupLevel = 0;
+  *aSimilarItemsInGroup = 0;
+  *aPositionInGroup = 0;
+
+  nsCOMPtr<nsIPersistentProperties> attributes;
+  nsresult rv = GetAttributes(getter_AddRefs(attributes));
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(attributes, NS_ERROR_FAILURE);
+
+  PRInt32 level, posInSet, setSize;
+  nsAccessibilityUtils::GetAccGroupAttrs(attributes,
+                                         &level, &posInSet, &setSize);
+
+  if (!posInSet && !setSize)
+    return NS_OK;
+
+  *aGroupLevel = level;
+
+  *aPositionInGroup = posInSet - 1;
+  *aSimilarItemsInGroup = setSize - 1;
+
+  return NS_OK;
+}
+
 PRBool nsAccessible::MappedAttrState(nsIContent *aContent, PRUint32 *aStateInOut,
                                      nsStateMapEntry *aStateMapEntry)
 {
   // Return true if we should continue
   if (!aStateMapEntry->attributeName) {
     return PR_FALSE;  // Stop looking -- no more states
   }
 
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -37,17 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsAccessible_H_
 #define _nsAccessible_H_
 
 #include "nsIAccessibleRole.h"
 #include "nsIAccessibleStates.h"
 #include "nsAccessNodeWrap.h"
-#include "nsAccessibilityAtoms.h"
+#include "nsAccessibilityUtils.h"
 #include "nsIAccessible.h"
 #include "nsPIAccessible.h"
 #include "nsIAccessibleHyperLink.h"
 #include "nsIAccessibleSelectable.h"
 #include "nsIAccessibleValue.h"
 #include "nsIDOMNodeList.h"
 #include "nsINameSpaceManager.h"
 #include "nsWeakReference.h"
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -127,16 +127,60 @@ NS_IMETHODIMP nsHTMLRadioButtonAccessibl
     htmlRadioElement->GetChecked(&checked);
 
   if (checked) 
     *_retval |= nsIAccessibleStates::STATE_CHECKED;
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsHTMLRadioButtonAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+  NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
+
+  nsresult rv = nsRadioButtonAccessible::GetAttributes(aAttributes);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoString nsURI;
+  mDOMNode->GetNamespaceURI(nsURI);
+  nsAutoString tagName;
+  mDOMNode->GetLocalName(tagName);
+
+  nsCOMPtr<nsIDOMHTMLInputElement> radio(do_QueryInterface(mDOMNode));
+  nsCOMPtr<nsIDOMHTMLFormElement> form;
+  radio->GetForm(getter_AddRefs(form));
+  NS_ENSURE_TRUE(form, NS_OK);
+
+  nsCOMPtr<nsIDOMNodeList> radios;
+  form->GetElementsByTagNameNS(nsURI, tagName, getter_AddRefs(radios));
+  NS_ENSURE_TRUE(radios, NS_OK);
+
+  // setsize
+  PRUint32 radiosCount = 0;
+  radios->GetLength(&radiosCount);
+
+  // posinset
+  PRInt32 indexOf = 0;
+  for (PRUint32 index = 0; index < radiosCount; index++) {
+    nsCOMPtr<nsIDOMNode> item;
+    radios->Item(index, getter_AddRefs(item));
+    if (item == mDOMNode) {
+      indexOf = index;
+      break;
+    }
+  }
+
+  nsAccessibilityUtils::
+    SetAccGroupAttrs(*aAttributes, 0, indexOf + 1, radiosCount);
+
+  return  NS_OK;
+}
+
 // ----- Button -----
 
 nsHTMLButtonAccessible::nsHTMLButtonAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
 nsHyperTextAccessible(aNode, aShell)
 { 
 }
 
 NS_IMETHODIMP nsHTMLButtonAccessible::GetNumActions(PRUint8 *_retval)
--- a/accessible/src/html/nsHTMLFormControlAccessible.h
+++ b/accessible/src/html/nsHTMLFormControlAccessible.h
@@ -56,17 +56,19 @@ public:
   NS_IMETHOD GetState(PRUint32 *aState); 
 };
 
 class nsHTMLRadioButtonAccessible : public nsRadioButtonAccessible
 {
 
 public:
   nsHTMLRadioButtonAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
-  NS_IMETHOD GetState(PRUint32 *_retval); 
+
+  NS_IMETHOD GetState(PRUint32 *_retval);
+  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
 };
 
 class nsHTMLButtonAccessible : public nsHyperTextAccessible
 {
 
 public:
   enum { eAction_Click = 0 };
 
--- a/accessible/src/html/nsHTMLSelectAccessible.cpp
+++ b/accessible/src/html/nsHTMLSelectAccessible.cpp
@@ -516,16 +516,41 @@ NS_IMETHODIMP nsHTMLSelectOptionAccessib
         return NS_OK;
       }
     }
   }
   
   return NS_ERROR_FAILURE;
 }
 
+NS_IMETHODIMP
+nsHTMLSelectOptionAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+  NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
+
+  nsresult rv = nsHyperTextAccessible::GetAttributes(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);
+  return  NS_OK;
+}
+
 nsIFrame* nsHTMLSelectOptionAccessible::GetBoundsFrame()
 {
   nsCOMPtr<nsIContent> selectContent(do_QueryInterface(mDOMNode));
 
   while (selectContent && selectContent->Tag() != nsAccessibilityAtoms::select) {
     selectContent = selectContent->GetParent();
   }
 
--- a/accessible/src/html/nsHTMLSelectAccessible.h
+++ b/accessible/src/html/nsHTMLSelectAccessible.h
@@ -159,16 +159,18 @@ public:
 
   /* ----- nsIAccessible ----- */
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetState(PRUint32 *_retval);
   NS_IMETHOD GetRole(PRUint32 *aRole);
   NS_IMETHOD GetName(nsAString& aName);
+  NS_IMETHOD GetAttributes(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
@@ -46,17 +46,16 @@
 #include "nsIDOMHTMLCollection.h"
 #include "nsIDOMHTMLTableCaptionElem.h"
 #include "nsIDOMHTMLTableCellElement.h"
 #include "nsIDOMHTMLTableElement.h"
 #include "nsIDOMHTMLTableRowElement.h"
 #include "nsIDOMHTMLTableSectionElem.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
-#include "nsIPersistentProperties2.h"
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsITableLayout.h"
 
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLTableCellAccessible, nsHyperTextAccessible)
 
 nsHTMLTableCellAccessible::nsHTMLTableCellAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell):
--- a/accessible/src/html/nsHTMLTextAccessible.cpp
+++ b/accessible/src/html/nsHTMLTextAccessible.cpp
@@ -42,17 +42,16 @@
 #include "nsBulletFrame.h"
 #include "nsIAccessibleDocument.h"
 #include "nsIAccessibleEvent.h"
 #include "nsIFrame.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsISelection.h"
 #include "nsISelectionController.h"
-#include "nsIPersistentProperties2.h"
 #include "nsComponentManagerUtils.h"
 
 nsHTMLTextAccessible::nsHTMLTextAccessible(nsIDOMNode* aDomNode, nsIWeakReference* aShell, nsIFrame *aFrame):
 nsTextAccessibleWrap(aDomNode, aShell), mFrame(aFrame)
 { 
 }
 
 NS_IMETHODIMP nsHTMLTextAccessible::GetName(nsAString& aName)
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -51,17 +51,16 @@
 #include "nsIDOMRange.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIFontMetrics.h"
 #include "nsIFrame.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIServiceManager.h"
 #include "nsTextFragment.h"
-#include "nsIPersistentProperties2.h"
 
 static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
 
 // ------------
 // nsHyperTextAccessible
 // ------------
 
 NS_IMPL_ADDREF_INHERITED(nsHyperTextAccessible, nsAccessible)
@@ -818,40 +817,34 @@ NS_IMETHODIMP nsHyperTextAccessible::Get
 
   nsresult rv = nsAccessibleWrap::GetAttributes(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
   NS_ENSURE_TRUE(content, NS_ERROR_UNEXPECTED);
   nsIAtom *tag = content->Tag();
 
-  PRInt32 headLevel = 0;
-  if (tag == nsAccessibilityAtoms::h1) {
-    headLevel = 1;
-  }
-  else if (tag == nsAccessibilityAtoms::h2) {
-    headLevel = 2;
-  }
-  else if (tag == nsAccessibilityAtoms::h3) {
-    headLevel = 3;
-  }
-  else if (tag == nsAccessibilityAtoms::h4) {
-    headLevel = 4;
-  }
-  else if (tag == nsAccessibilityAtoms::h5) {
-    headLevel = 5;
-  }
-  else if (tag == nsAccessibilityAtoms::h6) {
-    headLevel = 6;
-  }
-  if (headLevel) {
-    nsAutoString valueString;
-    valueString.AppendInt(headLevel);
-    nsAutoString oldValueUnused;
-    (*aAttributes)->SetStringProperty(NS_LITERAL_CSTRING("level"), valueString, oldValueUnused);
+  nsAutoString headLevel;
+  if (tag == nsAccessibilityAtoms::h1)
+    headLevel.AssignLiteral("1");
+  else if (tag == nsAccessibilityAtoms::h2)
+    headLevel.AssignLiteral("2");
+  else if (tag == nsAccessibilityAtoms::h3)
+    headLevel.AssignLiteral("3");
+  else if (tag == nsAccessibilityAtoms::h4)
+    headLevel.AssignLiteral("4");
+  else if (tag == nsAccessibilityAtoms::h5)
+    headLevel.AssignLiteral("5");
+  else if (tag == nsAccessibilityAtoms::h6)
+    headLevel.AssignLiteral("6");
+
+  if (!headLevel.IsEmpty()) {
+    nsAccessibilityUtils::SetAccAttr(*aAttributes,
+                                     nsAccessibilityAtoms::level,
+                                     headLevel);
   }
 
   return  NS_OK;
 }
 
 /*
  * Given an offset, the x, y, width, and height values are filled appropriately.
  */
--- a/accessible/src/mac/Makefile.in
+++ b/accessible/src/mac/Makefile.in
@@ -74,17 +74,16 @@ CMMSRCS = nsAccessNodeWrap.mm \
           
 
 EXPORTS = \
   nsAccessNodeWrap.h \
   nsTextAccessibleWrap.h \
   nsAccessibleWrap.h \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
-  nsHTMLFormControlAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   mozDocAccessible.h \
   mozAccessible.h \
   mozAccessibleWrapper.h \
   mozAccessibleProtocol.h \
   mozActionElements.h \
   mozTextAccessible.h \
deleted file mode 100644
--- a/accessible/src/mac/nsHTMLFormControlAccessibleWrap.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is IBM Corporation
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Author: Aaron Leventhal (aleventh@us.ibm.com)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef __nsHTMLFormControlAccessibleWrap_h__
-#define __nsHTMLFormControlAccessibleWrap_h__
-
-#include "nsHTMLFormControlAccessible.h"
-
-typedef class nsHTMLRadioButtonAccessible nsHTMLRadioButtonAccessibleWrap;
-
-#endif
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -67,29 +67,27 @@ REQUIRES	= content \
 		  $(NULL)
 
 CPPSRCS = \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsTextAccessibleWrap.cpp \
   nsDocAccessibleWrap.cpp \
   nsRootAccessibleWrap.cpp \
-  nsHTMLFormControlAccessibleWrap.cpp \
   nsHTMLWin32ObjectAccessible.cpp \
   nsXULMenuAccessibleWrap.cpp \
   nsXULTreeAccessibleWrap.cpp \
   $(NULL)
 
 EXPORTS = \
   nsAccessNodeWrap.h \
   nsAccessibleWrap.h \
   nsTextAccessibleWrap.h \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
-  nsHTMLFormControlAccessibleWrap.h \
   nsHTMLWin32ObjectAccessible.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -297,123 +297,134 @@ STDMETHODIMP nsAccessibleWrap::get_accVa
       return S_FALSE;
 
     *pszValue = ::SysAllocString(value.get());
   }
 
   return S_OK;
 }
 
-NS_IMETHODIMP nsAccessibleWrap::GetDescription(nsAString& aDescription)
+STDMETHODIMP
+nsAccessibleWrap::get_accDescription(VARIANT varChild,
+                                     BSTR __RPC_FAR *pszDescription)
 {
-  // For items that are a choice in a list of choices,
-  // use MSAA description field to shoehorn positional info, it's becoming
-  // a defacto standard use for the field.
-  // Tree items override this, because they provide the current level as well
+  *pszDescription = NULL;
+  nsCOMPtr<nsIAccessible> xpAccessible;
+  GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
+  if (!xpAccessible)
+    return E_FAIL;
 
-  aDescription.Truncate();
+  // For items that are a choice in a list of choices, use MSAA description
+  // field to shoehorn positional info, it's becoming a defacto standard use for
+  // the field.
+
+  nsAutoString description;
+
+  // Try nsIAccessible::groupPosition to make a positional description string.
+  PRInt32 groupLevel;
+  PRInt32 similarItemsInGroup;
+  PRInt32 positionInGroup;
 
-  // Try ARIA properties first:
-  // If they exist then map them to positional description string
-  nsIContent *content = GetRoleContent(mDOMNode);
-  nsAutoString posInSet, setSize;
-  if (content->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::posinset, posInSet) &&
-      content->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::setsize, setSize)) {
-    PRInt32 errPosInSet, errSetSize;
-    PRInt32 intPosInSet = posInSet.ToInteger(&errPosInSet);
-    PRInt32 intSetSize = setSize.ToInteger(&errSetSize);
-    if (NS_SUCCEEDED(errPosInSet) && intPosInSet >=1 && NS_SUCCEEDED(errSetSize) && intSetSize >= 1) {
-      nsAutoString level;
-      if (content->GetAttr(kNameSpaceID_WAIProperties, nsAccessibilityAtoms::level,  level)) {
-        // Position has a level
-        PRInt32 errLevel;
-        PRInt32 intLevel = level.ToInteger(&errLevel);
-        if (NS_SUCCEEDED(errLevel) && intLevel >= 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(aDescription,
-                                    NS_LITERAL_STRING("L%d, %d of %d").get(), intLevel, intPosInSet, intSetSize);
-        }
+  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);
+      } else { // Position has no level
+        nsTextFormatter::ssprintf(description,
+                                  NS_LITERAL_STRING("%d of %d").get(),
+                                  positionInGroup + 1, similarItemsInGroup + 1);
       }
-      else { // Position has no level
-        nsTextFormatter::ssprintf(aDescription,
-                                  NS_LITERAL_STRING("%d of %d").get(), intPosInSet, intSetSize);
-      }
-      return NS_OK;
+
+      *pszDescription = ::SysAllocString(description.get());
+      return S_OK;
     }
   }
 
   PRUint32 currentRole;
-  nsresult rv = GetFinalRole(&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)) {
-    nsAutoString description;
-    nsAccessible::GetDescription(description);
+    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.
-      aDescription = NS_LITERAL_STRING("Description: ") + description;
+      description = NS_LITERAL_STRING("Description: ") + description;
     }
-    return NS_OK;
+
+    *pszDescription = ::SysAllocString(description.get());
+    return S_OK;
   }
 
-  nsCOMPtr<nsIAccessible> parent(GetParent());
-  if (!parent) {
-    return NS_ERROR_FAILURE;
-  }
+  // 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.
 
-  PRInt32 indexInParent = 0, numSiblings = 0;
+  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));
-  NS_ENSURE_TRUE(sibling, NS_ERROR_FAILURE);
+  if (!sibling)
+    return E_FAIL;
 
   PRBool foundCurrent = PR_FALSE;
   PRUint32 siblingRole;
   while (sibling) {
     sibling->GetFinalRole(&siblingRole);
     if (siblingRole == currentRole) {
-      ++ numSiblings;
+      ++ similarItemsInGroup;
       if (!foundCurrent) {
-        ++ indexInParent;
-        if (sibling == this) {
+        ++ 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) {
-    PRUint32 level = 1;
+    groupLevel = 1;
     nsCOMPtr<nsIAccessible> nextParent;
     while (parent) {
       parent->GetFinalRole(&currentRole);
-      if (currentRole != nsIAccessibleRole::ROLE_GROUPING) {
+      if (currentRole != nsIAccessibleRole::ROLE_GROUPING)
         break;
-      }
-      ++level;
+
+      ++ groupLevel;
       parent->GetParent(getter_AddRefs(nextParent));
       parent.swap(nextParent);
     }
 
     // Count the number of tree item children
     PRInt32 numChildren = 0;
     nsCOMPtr<nsIAccessible> groupSibling;
-    GetNextSibling(getter_AddRefs(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);
@@ -421,42 +432,26 @@ NS_IMETHODIMP nsAccessibleWrap::GetDescr
           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(aDescription,
+    nsTextFormatter::ssprintf(description,
                               NS_LITERAL_STRING("L%d, %d of %d with %d").get(),
-                              level, indexInParent, numSiblings, numChildren);
-  }
-  else {
-    nsTextFormatter::ssprintf(aDescription, NS_LITERAL_STRING("%d of %d").get(),
-                              indexInParent, numSiblings);
-  }
-  return NS_OK;
-}
-
-STDMETHODIMP nsAccessibleWrap::get_accDescription(
-      /* [optional][in] */ VARIANT varChild,
-      /* [retval][out] */ BSTR __RPC_FAR *pszDescription)
-{
-  *pszDescription = NULL;
-  nsCOMPtr<nsIAccessible> xpAccessible;
-  GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
-  if (xpAccessible) {
-     nsAutoString description;
-     if (NS_FAILED(xpAccessible->GetDescription(description)))
-       return S_FALSE;
-
-     *pszDescription = ::SysAllocString(description.get());
+                              groupLevel, positionInGroup,
+                              similarItemsInGroup, numChildren);
+  } else {
+    nsTextFormatter::ssprintf(description, NS_LITERAL_STRING("%d of %d").get(),
+                              positionInGroup, similarItemsInGroup);
   }
 
+ *pszDescription = ::SysAllocString(description.get());
   return S_OK;
 }
 
 STDMETHODIMP nsAccessibleWrap::get_accRole(
       /* [optional][in] */ VARIANT varChild,
       /* [retval][out] */ VARIANT __RPC_FAR *pvarRole)
 {
   VariantInit(pvarRole);
@@ -1144,21 +1139,34 @@ STDMETHODIMP
 nsAccessibleWrap::scrollTo(boolean topLeft)
 {
   if (NS_SUCCEEDED(ScrollTo(topLeft)))
     return S_OK;
   return E_FAIL;
 }
 
 STDMETHODIMP
-nsAccessibleWrap::get_groupPosition(long *groupLevel,
-                                    long *similarItemsInGroup,
-                                    long *positionInGroup)
+nsAccessibleWrap::get_groupPosition(long *aGroupLevel,
+                                    long *aSimilarItemsInGroup,
+                                    long *aPositionInGroup)
 {
-  return E_NOTIMPL;
+  PRInt32 groupLevel = 0;
+  PRInt32 similarItemsInGroup = 0;
+  PRInt32 positionInGroup = 0;
+  nsresult rv = GroupPosition(&groupLevel, &similarItemsInGroup,
+                              &positionInGroup);
+
+  if (NS_SUCCEEDED(rv)) {
+   *aGroupLevel = groupLevel;
+   *aSimilarItemsInGroup = similarItemsInGroup;
+   *aPositionInGroup = positionInGroup;
+    return S_OK;
+  }
+
+  return E_FAIL;
 }
 
 STDMETHODIMP
 nsAccessibleWrap::get_localizedRoleName(BSTR *localizedRoleName)
 {
   return E_NOTIMPL;
 }
 
--- a/accessible/src/msaa/nsAccessibleWrap.h
+++ b/accessible/src/msaa/nsAccessibleWrap.h
@@ -271,17 +271,16 @@ class nsAccessibleWrap : public nsAccess
   STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames,
                                UINT cNames, LCID lcid, DISPID *rgDispId);
   STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid,
         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
         VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
 
   virtual void GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible);
   NS_IMETHOD GetNativeInterface(void **aOutAccessible);
-  NS_IMETHOD GetDescription(nsAString& aDescription);
 
   // NT4 does not have the oleacc that defines these methods. So we define copies here that automatically
   // load the library only if needed.
   static STDMETHODIMP AccessibleObjectFromWindow(HWND hwnd,DWORD dwObjectID,REFIID riid,void **ppvObject);
   static STDMETHODIMP NotifyWinEvent(DWORD event,HWND hwnd,LONG idObjectType,LONG idObject);
 
   static IDispatch *NativeAccessible(nsIAccessible *aXPAccessible);
 
deleted file mode 100644
--- a/accessible/src/msaa/nsHTMLFormControlAccessibleWrap.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is IBM Corporation
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Author: Aaron Leventhal (aleventh@us.ibm.com)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsHTMLFormControlAccessibleWrap.h"
-#include "nsIDOMHTMLInputElement.h"
-#include "nsIRadioControlElement.h"
-#include "nsIRadioGroupContainer.H"
-#include "nsTextFormatter.h"
-
-// --------------------------------------------------------
-// nsXULMenuAccessibleWrap Accessible
-// --------------------------------------------------------
-
-nsHTMLRadioButtonAccessibleWrap::nsHTMLRadioButtonAccessibleWrap(nsIDOMNode *aDOMNode, 
-                                                         nsIWeakReference *aShell):
-nsHTMLRadioButtonAccessible(aDOMNode, aShell)
-{
-}
-
-NS_IMETHODIMP nsHTMLRadioButtonAccessibleWrap::GetDescription(nsAString& aDescription)
-{
-  aDescription.Truncate();
-
-  nsCOMPtr<nsIRadioControlElement> radio(do_QueryInterface(mDOMNode));
-  if (!radio) {
-    return NS_ERROR_FAILURE;
-  }
-
-  NS_ASSERTION(radio, "We should only have HTML radio buttons here");
-  nsCOMPtr<nsIRadioGroupContainer> radioGroupContainer =
-    radio->GetRadioGroupContainer();
-
-  if (radioGroupContainer) {
-    nsCOMPtr<nsIDOMHTMLInputElement> input(do_QueryInterface(mDOMNode));
-    PRInt32 radioIndex, radioItemsInGroup;
-    if (NS_SUCCEEDED(radioGroupContainer->GetPositionInGroup(input, &radioIndex, 
-                                                             &radioItemsInGroup))) {
-      // 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.
-      nsTextFormatter::ssprintf(aDescription, NS_LITERAL_STRING("%d of %d").get(),
-                                radioIndex + 1, radioItemsInGroup);
-      return NS_OK;
-    }
-  }
-  return nsAccessibleWrap::GetDescription(aDescription);
-}
deleted file mode 100644
--- a/accessible/src/msaa/nsHTMLFormControlAccessibleWrap.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is IBM Corporation
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Author: Aaron Leventhal (aleventh@us.ibm.com)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef __nsHTMLFormControlAccessibleWrap_h__
-#define __nsHTMLFormControlAccessibleWrap_h__
-
-#include "nsHTMLFormControlAccessible.h"
-
-class nsHTMLRadioButtonAccessibleWrap : public nsHTMLRadioButtonAccessible
-{
-public:
-  nsHTMLRadioButtonAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell);
-  virtual ~nsHTMLRadioButtonAccessibleWrap() {}
-  NS_IMETHOD GetDescription(nsAString& aName);
-};
-
-#endif
--- a/accessible/src/msaa/nsXULTreeAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsXULTreeAccessibleWrap.cpp
@@ -125,74 +125,8 @@ NS_IMETHODIMP nsXULTreeitemAccessibleWra
     aName += colText + NS_LITERAL_STRING("  ");
     nsCOMPtr<nsITreeColumn> nextColumn;
     column->GetNext(getter_AddRefs(nextColumn));
     column = nextColumn;
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP nsXULTreeitemAccessibleWrap::GetDescription(nsAString& aDescription)
-{
-  if (!mParent || !mWeakShell || !mTreeView) {
-    return NS_ERROR_FAILURE;
-  }
-
-  PRUint32 itemRole;
-  GetRole(&itemRole);
-  if (itemRole == nsIAccessibleRole::ROLE_LISTITEM) {
-    return nsAccessibleWrap::GetDescription(aDescription);
-  }
-
-  aDescription.Truncate();
-
-  PRInt32 level;
-  if (NS_FAILED(mTreeView->GetLevel(mRow, &level))) {
-    return NS_OK;
-  }
-
-  PRInt32 testRow = -1;
-  if (level > 0) {
-    mTreeView->GetParentIndex(mRow, &testRow);
-  }
-
-  PRInt32 numRows;
-  mTreeView->GetRowCount(&numRows);
-
-  PRInt32 indexInParent = 0, numSiblings = 0;
-
-  // Get the index in parent and number of siblings
-  while (++ testRow < numRows) {
-    PRInt32 testLevel = 0;
-    mTreeView->GetLevel(testRow, &testLevel);
-    if (testLevel == level) {
-      if (testRow <= mRow) {
-        ++indexInParent;
-      }
-      ++numSiblings;
-    }
-    else if (testLevel < level) {
-      break;
-    }
-  }
-
-  // Count the number of children
-  testRow = mRow;
-  PRInt32 numChildren = 0;
-  while (++ testRow < numRows) {
-    PRInt32 testLevel = 0;
-    mTreeView->GetLevel(testRow, &testLevel);
-    if (testLevel <= level) {
-      break;
-    }
-    else if (testLevel == level + 1) {
-      ++ numChildren;
-    }
-  }
-
-  // Don't localize "of" or "with" -- that is just the format of
-  // the string, and are parsed out by the AT
-  nsTextFormatter::ssprintf(aDescription, NS_LITERAL_STRING("L%d, %d of %d with %d").get(),
-                            level + 1, indexInParent, numSiblings, numChildren);
-
-  return NS_OK;
-}
-
--- a/accessible/src/msaa/nsXULTreeAccessibleWrap.h
+++ b/accessible/src/msaa/nsXULTreeAccessibleWrap.h
@@ -52,15 +52,15 @@ public:
 };
 
 class nsXULTreeitemAccessibleWrap : public nsXULTreeitemAccessible
 {
 public:
   nsXULTreeitemAccessibleWrap(nsIAccessible *aParent, nsIDOMNode *aDOMNode, nsIWeakReference *aShell, 
     PRInt32 aRow, nsITreeColumn* aColumn);
   virtual ~nsXULTreeitemAccessibleWrap() {}
+
   NS_IMETHOD GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height);
   NS_IMETHOD GetRole(PRUint32 *aRole);
   NS_IMETHOD GetName(nsAString &aName);
-  NS_IMETHOD GetDescription(nsAString &aDescription);
 };
 
 #endif
--- a/accessible/src/other/Makefile.in
+++ b/accessible/src/other/Makefile.in
@@ -76,17 +76,16 @@ CPPSRCS = \
 EXPORTS = \
   nsAccessNodeWrap.h \
   nsTextAccessibleWrap.h \
   nsAccessibleWrap.h \
   nsDocAccessibleWrap.h \
   nsRootAccessibleWrap.h \
   nsXULMenuAccessibleWrap.h \
   nsXULTreeAccessibleWrap.h \
-  nsHTMLFormControlAccessibleWrap.h \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
deleted file mode 100644
--- a/accessible/src/other/nsHTMLFormControlAccessibleWrap.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is IBM Corporation
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Author: Aaron Leventhal (aleventh@us.ibm.com)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef __nsHTMLFormControlAccessibleWrap_h__
-#define __nsHTMLFormControlAccessibleWrap_h__
-
-#include "nsHTMLFormControlAccessible.h"
-
-typedef class nsHTMLRadioButtonAccessible nsHTMLRadioButtonAccessibleWrap;
-
-#endif
--- a/accessible/src/xforms/nsXFormsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsAccessible.cpp
@@ -40,17 +40,16 @@
 
 #include "nscore.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNodeList.h"
 #include "nsIMutableArray.h"
 #include "nsIXFormsUtilityService.h"
 #include "nsIPlaintextEditor.h"
-#include "nsIPersistentProperties2.h"
 
 // nsXFormsAccessibleBase
 
 nsIXFormsUtilityService *nsXFormsAccessibleBase::sXFormsService = nsnull;
 
 nsXFormsAccessibleBase::nsXFormsAccessibleBase()
 {
   if (!sXFormsService) {
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -523,16 +523,31 @@ NS_IMETHODIMP nsXULRadioButtonAccessible
     if (selected) {
       *_retval |= nsIAccessibleStates::STATE_CHECKED;
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsXULRadioButtonAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+  NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
+
+  nsresult rv = nsFormControlAccessible::GetAttributes(aAttributes);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAccessibilityUtils::
+    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
   *   this for the purpose of getting the proper RadioButton. Need this here to 
   *   avoid circular reference problems when navigating the accessible tree and
   *   for getting to the radiobuttons.
   */
--- a/accessible/src/xul/nsXULFormControlAccessible.h
+++ b/accessible/src/xul/nsXULFormControlAccessible.h
@@ -108,17 +108,18 @@ public:
   NS_IMETHOD GetValue(nsAString &aValue);
 };
 
 class nsXULRadioButtonAccessible : public nsRadioButtonAccessible
 {
 
 public:
   nsXULRadioButtonAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
-  NS_IMETHOD GetState(PRUint32 *_retval);
+  NS_IMETHOD GetState(PRUint32 *aState);
+  NS_IMETHOD GetAttributes(nsIPersistentProperties **aAttributes);
 };
 
 class nsXULRadioGroupAccessible : public nsXULSelectableAccessible
 {
 public:
   nsXULRadioGroupAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
   NS_IMETHOD GetRole(PRUint32 *_retval); 
   NS_IMETHOD GetState(PRUint32 *_retval); 
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -430,16 +430,34 @@ NS_IMETHODIMP nsXULMenuitemAccessible::G
       *aRole = nsIAccessibleRole::ROLE_PARENT_MENUITEM;
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsXULMenuitemAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+  NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
+
+  nsresult rv = nsAccessible::GetAttributes(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);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsXULMenuitemAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
 {
   // That indicates we don't walk anonymous children for menuitems
   *aAllowsAnonChildren = PR_FALSE;
   return NS_OK;
 }
 
 NS_IMETHODIMP nsXULMenuitemAccessible::DoAction(PRUint8 index)
--- a/accessible/src/xul/nsXULMenuAccessible.h
+++ b/accessible/src/xul/nsXULMenuAccessible.h
@@ -81,16 +81,17 @@ public:
   NS_IMETHOD GetDescription(nsAString& aDescription);
   NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
   NS_IMETHOD GetDefaultKeyBinding(nsAString& aKeyBinding);
   NS_IMETHOD GetState(PRUint32 *_retval); 
   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);
   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
@@ -122,16 +122,31 @@ NS_IMETHODIMP nsXULTabAccessible::GetSta
   if (tab) {
     PRBool selected = PR_FALSE;
     if (NS_SUCCEEDED(tab->GetSelected(&selected)) && selected)
       *_retval |= nsIAccessibleStates::STATE_SELECTED;
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsXULTabAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+  NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
+
+  nsresult rv = nsLeafAccessible::GetAttributes(aAttributes);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAccessibilityUtils::
+    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.
   */
 
 /** Constructor */
 nsXULTabBoxAccessible::nsXULTabBoxAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
--- a/accessible/src/xul/nsXULTabAccessible.h
+++ b/accessible/src/xul/nsXULTabAccessible.h
@@ -50,16 +50,17 @@ public:
   enum { eAction_Switch = 0 };
 
   nsXULTabAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
   NS_IMETHOD GetRole(PRUint32 *_retval); 
   NS_IMETHOD GetState(PRUint32 *_retval);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
+  NS_IMETHOD GetAttributes(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
@@ -34,18 +34,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIBoxObject.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULMultSelectCntrlEl.h"
+#include "nsIDOMXULTreeElement.h"
 #include "nsITreeSelection.h"
-#include "nsITreeColumns.h"
 #include "nsXULTreeAccessibleWrap.h"
 #include "nsIMutableArray.h"
 #include "nsComponentManagerUtils.h"
 
 #ifdef MOZ_ACCESSIBILITY_ATK
 #include "nsIAccessibleTable.h"
 #endif
 
@@ -667,16 +667,57 @@ NS_IMETHODIMP nsXULTreeitemAccessible::G
     }
 
     return NS_OK;
   }
 
   return NS_ERROR_INVALID_ARG;
 }
 
+NS_IMETHODIMP
+nsXULTreeitemAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
+{
+  NS_ENSURE_ARG_POINTER(aAttributes);
+  NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
+
+  nsresult rv = nsLeafAccessible::GetAttributes(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);
+
+  PRInt32 level;
+  rv = view->GetLevel(mRow, &level);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  PRInt32 lvl = -1;
+  PRInt32 startIndex = mRow;
+  for (;startIndex - 1 > 0 &&
+        NS_SUCCEEDED(view->GetLevel(startIndex - 1, &lvl)) && lvl != level;
+        startIndex--);
+
+  lvl = -1;
+  PRInt32 endIndex = mRow;
+  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);
+
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsXULTreeitemAccessible::GetParent(nsIAccessible **aParent)
 {
   *aParent = nsnull;
 
   if (mParent) {
     *aParent = mParent;
     NS_ADDREF(*aParent);
   }
--- a/accessible/src/xul/nsXULTreeAccessible.h
+++ b/accessible/src/xul/nsXULTreeAccessible.h
@@ -105,16 +105,17 @@ public:
   NS_IMETHOD Shutdown();
 
   /* ----- nsIAccessible ----- */
   NS_IMETHOD GetName(nsAString& _retval);
   NS_IMETHOD GetRole(PRUint32 *_retval);
   NS_IMETHOD GetState(PRUint32 *_retval);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
+  NS_IMETHOD GetAttributes(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);