Bug 382321. Alphabetize ARIA role table and move to a separate file. r=surkov, sr=neil
authoraaronleventhal@moonset.net
Tue, 05 Jun 2007 08:41:07 -0700
changeset 2136 6e5f6fde2dafc56e9a72e734694cd284c33cd438
parent 2135 2e366350e783426843c5878fafdc5c50e070c38b
child 2137 1d4aa2c3b51079d0ee725aaecfedcd167830eec4
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)
reviewerssurkov, neil
bugs382321
milestone1.9a6pre
Bug 382321. Alphabetize ARIA role table and move to a separate file. r=surkov, sr=neil
accessible/src/base/Makefile.in
accessible/src/base/nsARIAMap.cpp
accessible/src/base/nsARIAMap.h
accessible/src/base/nsAccessible.cpp
accessible/src/base/nsAccessible.h
accessible/src/msaa/nsAccessibleWrap.cpp
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -69,16 +69,17 @@ REQUIRES	= appshell \
 		  xpcom \
 		  xuldoc \
 		  imglib2 \
 		  $(NULL)
 
 CPPSRCS = \
   nsAccessNode.cpp \
   nsAccessibleEventData.cpp \
+  nsARIAMap.cpp \
   nsDocAccessible.cpp \
   nsOuterDocAccessible.cpp \
   nsAccessibilityAtoms.cpp \
   nsAccessibilityUtils.cpp \
   nsAccessibilityService.cpp \
   nsAccessible.cpp \
   nsAccessibleRelation.cpp \
   nsAccessibleTreeWalker.cpp \
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=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) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Aaron Leventhal <aleventh@us.ibm.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 ***** */
+
+#include "nsARIAMap.h"
+#include "nsIAccessibleRole.h"
+#include "nsIAccessibleStates.h"
+
+/**
+ *  This list of WAI-defined roles are currently hardcoded.
+ *  Eventually we will most likely be loading an RDF resource that contains this information
+ *  Using RDF will also allow for role extensibility. See bug 280138.
+ *
+ *  XXX Should we store attribute names in this table as atoms instead of strings?
+ *  Definition of nsRoleMapEntry and nsStateMapEntry contains comments explaining this table.
+ *
+ *  When no nsIAccessibleRole neum mapping exists for an ARIA role, the
+ *  role will be exposed via the object attribute "xml-roles".
+ *  In addition, in MSAA, the unmapped role will also be exposed as a BSTR string role.
+ *
+ *  There are no nsIAccessibleRole enums for the following landmark roles:
+ *    banner, contentinfo, main, navigation, note, search, secondary, seealso, breadcrumbs
+ */ 
+
+static const nsStateMapEntry kEndEntry = {0, 0, 0};  // To fill in array of state mappings
+
+nsRoleMapEntry nsARIAMap::gWAIRoleMap[] = 
+{
+  {"alert", nsIAccessibleRole::ROLE_ALERT, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
+  {"alertdialog", nsIAccessibleRole::ROLE_ALERT, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
+  {"application", nsIAccessibleRole::ROLE_APPLICATION, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"button", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates,
+            {"pressed", kBoolState, nsIAccessibleStates::STATE_PRESSED},
+            {"haspopup", kBoolState, nsIAccessibleStates::STATE_HASPOPUP}, kEndEntry},
+  {"buttonsubmit", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_DEFAULT, kEndEntry},
+  {"buttoncancel", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
+  {"checkbox", nsIAccessibleRole::ROLE_CHECKBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED},
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
+  {"checkboxtristate", nsIAccessibleRole::ROLE_CHECKBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED},
+            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED},
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
+  {"columnheader", nsIAccessibleRole::ROLE_COLUMNHEADER, eNameOkFromChildren, eNoValue, kNoReqStates,
+            {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
+            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
+  {"combobox", nsIAccessibleRole::ROLE_COMBOBOX, eNameLabelOrTitle, eHasValueMinMax, kNoReqStates,
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY},
+            {"expanded", kBoolState, nsIAccessibleStates::STATE_EXPANDED},
+            {"multiselectable", kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
+  {"description", nsIAccessibleRole::ROLE_TEXT_CONTAINER, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
+  {"dialog", nsIAccessibleRole::ROLE_DIALOG, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"document", nsIAccessibleRole::ROLE_DOCUMENT, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"grid", nsIAccessibleRole::ROLE_TABLE, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_FOCUSABLE,
+            {"multiselectable", kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
+  {"gridcell", nsIAccessibleRole::ROLE_CELL, eNameOkFromChildren, eNoValue, kNoReqStates,
+            {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
+            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
+  {"group", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"label", nsIAccessibleRole::ROLE_LABEL, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
+  {"link", nsIAccessibleRole::ROLE_LINK, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_LINKED, kEndEntry},
+  {"list", nsIAccessibleRole::ROLE_LIST, eNameLabelOrTitle, eNoValue, kNoReqStates,
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY},
+            {"multiselectable", kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
+  {"listbox", nsIAccessibleRole::ROLE_LIST, eNameLabelOrTitle, eNoValue, kNoReqStates,
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY},
+            {"multiselectable", kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
+  {"listitem", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
+            {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
+            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
+            {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
+  {"menu", nsIAccessibleRole::ROLE_MENUPOPUP, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"menubar", nsIAccessibleRole::ROLE_MENUBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"menuitem", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
+            {"haspopup", kBoolState, nsIAccessibleStates::STATE_HASPOPUP},
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
+            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED},
+            {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
+  {"menuitemcheckbox", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED }, kEndEntry},
+  {"menuitemradio", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED }, kEndEntry},
+  {"option", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
+            {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
+            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
+            {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE}, kEndEntry},
+  {"progressbar", nsIAccessibleRole::ROLE_PROGRESSBAR, eNameLabelOrTitle, eHasValueMinMax, nsIAccessibleStates::STATE_READONLY,
+            {"valuenow", "unknown", nsIAccessibleStates::STATE_MIXED}, kEndEntry},
+  {"radio", nsIAccessibleRole::ROLE_RADIOBUTTON, eNameOkFromChildren, eNoValue, kNoReqStates,
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED}, kEndEntry},
+  {"radiogroup", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"rowheader", nsIAccessibleRole::ROLE_ROWHEADER, eNameOkFromChildren, eNoValue, kNoReqStates,
+            {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
+            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
+  {"secret", nsIAccessibleRole::ROLE_PASSWORD_TEXT, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_PROTECTED,
+             kEndEntry},  // nsIAccessibleStates::EXT_STATE_SINGLE_LINE manually supported in code
+  {"separator", nsIAccessibleRole::ROLE_SEPARATOR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"slider", nsIAccessibleRole::ROLE_SLIDER, eNameLabelOrTitle, eHasValueMinMax, kNoReqStates,
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
+  {"spinbutton", nsIAccessibleRole::ROLE_SPINBUTTON, eNameLabelOrTitle, eHasValueMinMax, kNoReqStates,
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry},
+  {"spreadsheet", nsIAccessibleRole::ROLE_TABLE, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE | nsIAccessibleStates::STATE_FOCUSABLE,
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry}, // Still supported, but deprecated in favor of grid
+  {"status", nsIAccessibleRole::ROLE_STATUSBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"tab", nsIAccessibleRole::ROLE_PAGETAB, eNameOkFromChildren, eNoValue, kNoReqStates, kEndEntry},
+  {"table", nsIAccessibleRole::ROLE_TABLE, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"td", nsIAccessibleRole::ROLE_CELL, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"th", nsIAccessibleRole::ROLE_CELL, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"tablist", nsIAccessibleRole::ROLE_PAGETABLIST, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"tabpanel", nsIAccessibleRole::ROLE_PROPERTYPAGE, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"textarea", nsIAccessibleRole::ROLE_ENTRY, eNameLabelOrTitle, eHasValueMinMax, kNoReqStates,
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, kEndEntry}, // XXX nsIAccessibleStates::EXT_STATE_MULTI_LINE supported in code
+  {"textfield", nsIAccessibleRole::ROLE_ENTRY, eNameLabelOrTitle, eHasValueMinMax, kNoReqStates,
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY}, 
+            {"haspopup", kBoolState, nsIAccessibleStates::STATE_HASPOPUP}, kEndEntry}, // XXX nsIAccessibleStates::EXT_STATE_SINGLE_LINE supported in code
+  {"toolbar", nsIAccessibleRole::ROLE_TOOLBAR, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {"tree", nsIAccessibleRole::ROLE_OUTLINE, eNameLabelOrTitle, eNoValue, kNoReqStates,
+            {"readonly", kBoolState, nsIAccessibleStates::STATE_READONLY},
+            {"multiselectable", kBoolState, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, kEndEntry},
+  {"treeitem", nsIAccessibleRole::ROLE_OUTLINEITEM, eNameOkFromChildren, eNoValue, kNoReqStates,
+            {"selected", kBoolState, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
+            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
+            {"expanded", kBoolState, nsIAccessibleStates::STATE_EXPANDED},
+            {"expanded", "false", nsIAccessibleStates::STATE_COLLAPSED},
+            {"checked", kBoolState, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
+            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED},
+            {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE},},
+  {"treegroup", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry},
+  {nsnull, nsIAccessibleRole::ROLE_NOTHING, eNameLabelOrTitle, eNoValue, kNoReqStates, kEndEntry} // Last item
+};
+
+/**
+ * Universal states:
+ * The following state rules are applied to any accessible element,
+ * whether there is an ARIA role or not:
+ */
+nsStateMapEntry nsARIAMap::gWAIUnivStateMap[] = {
+  {"disabled", kBoolState, nsIAccessibleStates::STATE_UNAVAILABLE},
+  {"required", kBoolState, nsIAccessibleStates::STATE_REQUIRED},
+  {"invalid", kBoolState, nsIAccessibleStates::STATE_INVALID},
+  kEndEntry
+};
+
new file mode 100644
--- /dev/null
+++ b/accessible/src/base/nsARIAMap.h
@@ -0,0 +1,130 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:expandtab:shiftwidth=2:tabstop=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) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Aaron Leventhal <aleventh@us.ibm.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 _nsARIAMap_H_
+#define _nsARIAMap_H_
+
+#include "prtypes.h"
+
+// Name mapping rule: can the name be computed from descendants?
+enum ENameRule
+{
+  // eNameLabelOrTitle:
+  // Collect name from:
+  //   1) The content subtrees pointed to by labelledby
+  //      which contains the IDs for the label content, or if unspecified
+  //   2) The title attribute if specified
+  eNameLabelOrTitle,
+  
+  // eNameOkFromChildren
+  // Collect name from:
+  //   1) The content subtrees pointed to by labelledby
+  //      which contains the IDs for the label content, or if un specified
+  //   2) The text and text equivalents from descendents,
+  //      as well as the value of controls, collected in depth-first order, or if empty
+  //   3) The title attribute if specified
+  eNameOkFromChildren
+};
+
+// Is nsIAccessible value supported for this role or not?
+enum EValueRule
+{
+  eNoValue,
+  eHasValueMinMax    // Supports value, min and max from aaa:valuenow, valuemin and valuemax
+};
+
+// Used for an nsStateMapEntry if a given state attribute supports "true" and "false"
+static const char *kBoolState = 0;
+
+// Used in nsRoleMapEntry.state if no nsIAccessibleStates are automatic for a given role
+static const PRUint32 kNoReqStates = 0;
+
+// For this name and value pair, what is the nsIAccessibleStates mapping.
+// nsStateMapEntry.state
+struct nsStateMapEntry
+{
+  const char* attributeName;  // magic value of nsnull means last entry in map
+  const char* attributeValue; // magic value of kBoolState (0) means supports "true" and "false"
+  PRUint32 state;             // If match, this is the nsIAccessibleStates to map to
+};
+
+// For each ARIA role, this maps the nsIAccessible information
+struct nsRoleMapEntry
+{
+  // ARIA role: string representation such as "button"
+  const char *roleString;
+  
+  // Role mapping rule: maps to this nsIAccessibleRole
+  PRUint32 role;
+  
+  // Name mapping rule: how to compute nsIAccessible name
+  ENameRule nameRule;
+  
+  // Value mapping rule: how to compute nsIAccessible value
+  EValueRule valueRule;
+  
+  // Automatic state mapping rule: always include in nsIAccessibleStates
+  PRUint32 state;   // or kNoReqStates if no nsIAccessibleStates are automatic for this role.
+  
+  // ARIA properties supported for this role
+  // (in other words, the aaa:foo attribute to nsIAccessibleStates mapping rules)
+  // Currently you cannot have unlimited mappings, because
+  // a variable sized array would not allow the use of
+  // C++'s struct initialization feature.
+  nsStateMapEntry attributeMap1;
+  nsStateMapEntry attributeMap2;
+  nsStateMapEntry attributeMap3;
+  nsStateMapEntry attributeMap4;
+  nsStateMapEntry attributeMap5;
+  nsStateMapEntry attributeMap6;
+  nsStateMapEntry attributeMap7;
+};
+
+/**
+ *  These are currently initialized (hardcoded) in nsARIAMap.cpp, 
+ *  and provide the mappings for WAI-ARIA roles and properties using the 
+ *  structs defined in this file.
+ */
+struct nsARIAMap
+{
+  static nsRoleMapEntry gWAIRoleMap[];
+  static nsStateMapEntry gWAIUnivStateMap[];
+};
+
+#endif
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -507,24 +507,24 @@ NS_IMETHODIMP nsAccessible::Init()
       }
       prefix += ':';
       PRUint32 length = prefix.Length();
       if (length > 1 && StringBeginsWith(roleString, prefix)) {
         roleString.Cut(0, length);
         nsCString utf8Role = NS_ConvertUTF16toUTF8(roleString); // For easy comparison
         ToLowerCase(utf8Role);
         PRUint32 index;
-        for (index = 0; gWAIRoleMap[index].roleString; index ++) {
-          if (utf8Role.Equals(gWAIRoleMap[index].roleString)) {
+        for (index = 0; nsARIAMap::gWAIRoleMap[index].roleString; index ++) {
+          if (utf8Role.Equals(nsARIAMap::gWAIRoleMap[index].roleString)) {
             break; // The dynamic role attribute maps to an entry in our table
           }
         }
         // Always use some entry if there is a role string
         // If no match, we use the last entry which maps to ROLE_NOTHING
-        mRoleMapEntry = &gWAIRoleMap[index];
+        mRoleMapEntry = &nsARIAMap::gWAIRoleMap[index];
       }
     }
   }
 
   return nsAccessNodeWrap::Init();
 }
 
 nsIContent *nsAccessible::GetRoleContent(nsIDOMNode *aDOMNode)
@@ -2032,142 +2032,16 @@ nsAccessible::FireAccessibleEvent(nsIAcc
 
   nsCOMPtr<nsIObserverService> obsService =
     do_GetService("@mozilla.org/observer-service;1");
   NS_ENSURE_TRUE(obsService, NS_ERROR_FAILURE);
 
   return obsService->NotifyObservers(aEvent, NS_ACCESSIBLE_EVENT_TOPIC, nsnull);
 }
 
-nsRoleMapEntry nsAccessible::gWAIRoleMap[] = 
-{
-  // This list of WAI-defined roles are currently hardcoded.
-  // Eventually we will most likely be loading an RDF resource that contains this information
-  // Using RDF will also allow for role extensibility. See bug 280138.
-  // XXX Should we store attribute names in this table as atoms instead of strings?
-  // Definition of nsRoleMapEntry and nsStateMapEntry contains comments explaining this table.
-  {"alert", nsIAccessibleRole::ROLE_ALERT, eNameOkFromChildren, eNoValue, eNoReqStates, END_ENTRY},
-  {"alertdialog", nsIAccessibleRole::ROLE_ALERT, eNameOkFromChildren, eNoValue, eNoReqStates, END_ENTRY},
-  {"application", nsIAccessibleRole::ROLE_APPLICATION, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"button", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, eNoReqStates,
-            {"pressed", BOOL_STATE, nsIAccessibleStates::STATE_PRESSED},
-            {"haspopup", BOOL_STATE, nsIAccessibleStates::STATE_HASPOPUP}, END_ENTRY},
-  {"buttonsubmit", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_DEFAULT, END_ENTRY},
-  {"buttoncancel", nsIAccessibleRole::ROLE_PUSHBUTTON, eNameOkFromChildren, eNoValue, eNoReqStates, END_ENTRY},
-  {"checkbox", nsIAccessibleRole::ROLE_CHECKBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
-            {"checked", BOOL_STATE, nsIAccessibleStates::STATE_CHECKED},
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY},
-  {"checkboxtristate", nsIAccessibleRole::ROLE_CHECKBUTTON, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
-            {"checked", BOOL_STATE, nsIAccessibleStates::STATE_CHECKED},
-            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED},
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY},
-  {"columnheader", nsIAccessibleRole::ROLE_COLUMNHEADER, eNameOkFromChildren, eNoValue, eNoReqStates,
-            {"selected", BOOL_STATE, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
-            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY},
-  {"combobox", nsIAccessibleRole::ROLE_COMBOBOX, eNameLabelOrTitle, eHasValueMinMax, eNoReqStates,
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY},
-            {"expanded", BOOL_STATE, nsIAccessibleStates::STATE_EXPANDED},
-            {"multiselectable", BOOL_STATE, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, END_ENTRY},
-  {"description", nsIAccessibleRole::ROLE_TEXT_CONTAINER, eNameOkFromChildren, eNoValue, eNoReqStates, END_ENTRY},
-  {"dialog", nsIAccessibleRole::ROLE_DIALOG, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"document", nsIAccessibleRole::ROLE_DOCUMENT, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"label", nsIAccessibleRole::ROLE_LABEL, eNameOkFromChildren, eNoValue, eNoReqStates, END_ENTRY},
-  {"list", nsIAccessibleRole::ROLE_LIST, eNameLabelOrTitle, eNoValue, eNoReqStates,
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY},
-            {"multiselectable", BOOL_STATE, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, END_ENTRY},
-  {"listbox", nsIAccessibleRole::ROLE_LIST, eNameLabelOrTitle, eNoValue, eNoReqStates,
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY},
-            {"multiselectable", BOOL_STATE, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, END_ENTRY},
-  {"listitem", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, eNoReqStates,
-            {"selected", BOOL_STATE, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
-            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
-            {"checked", BOOL_STATE, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
-            {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE}, END_ENTRY},
-  {"menu", nsIAccessibleRole::ROLE_MENUPOPUP, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"menubar", nsIAccessibleRole::ROLE_MENUBAR, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"menuitem", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, eNoReqStates,
-            {"haspopup", BOOL_STATE, nsIAccessibleStates::STATE_HASPOPUP},
-            {"checked", BOOL_STATE, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
-            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED},
-            {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE}, END_ENTRY},
-  {"menuitemcheckbox", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
-            {"checked", BOOL_STATE, nsIAccessibleStates::STATE_CHECKED }, END_ENTRY},
-  {"menuitemradio", nsIAccessibleRole::ROLE_MENUITEM, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_CHECKABLE,
-            {"checked", BOOL_STATE, nsIAccessibleStates::STATE_CHECKED }, END_ENTRY},
-  {"grid", nsIAccessibleRole::ROLE_TABLE, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_FOCUSABLE,
-            {"multiselectable", BOOL_STATE, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE},
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY},
-  {"gridcell", nsIAccessibleRole::ROLE_CELL, eNameOkFromChildren, eNoValue, eNoReqStates,
-            {"selected", BOOL_STATE, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
-            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY},
-  {"group", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"link", nsIAccessibleRole::ROLE_LINK, eNameOkFromChildren, eNoValue, nsIAccessibleStates::STATE_LINKED, END_ENTRY},
-  {"option", nsIAccessibleRole::ROLE_LISTITEM, eNameOkFromChildren, eNoValue, eNoReqStates,
-            {"selected", BOOL_STATE, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
-            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
-            {"checked", BOOL_STATE, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
-            {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE}, END_ENTRY},
-  {"progressbar", nsIAccessibleRole::ROLE_PROGRESSBAR, eNameLabelOrTitle, eHasValueMinMax, nsIAccessibleStates::STATE_READONLY,
-            {"valuenow", "unknown", nsIAccessibleStates::STATE_MIXED}, END_ENTRY},
-  {"radio", nsIAccessibleRole::ROLE_RADIOBUTTON, eNameOkFromChildren, eNoValue, eNoReqStates,
-            {"checked", BOOL_STATE, nsIAccessibleStates::STATE_CHECKED}, END_ENTRY},
-  {"radiogroup", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"rowheader", nsIAccessibleRole::ROLE_ROWHEADER, eNameOkFromChildren, eNoValue, eNoReqStates,
-            {"selected", BOOL_STATE, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
-            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY},
-  {"secret", nsIAccessibleRole::ROLE_PASSWORD_TEXT, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_PROTECTED,
-             END_ENTRY},  // nsIAccessibleStates::EXT_STATE_SINGLE_LINE manually supported in code
-  {"separator", nsIAccessibleRole::ROLE_SEPARATOR, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"slider", nsIAccessibleRole::ROLE_SLIDER, eNameLabelOrTitle, eHasValueMinMax, eNoReqStates,
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY},
-  {"spinbutton", nsIAccessibleRole::ROLE_SPINBUTTON, eNameLabelOrTitle, eHasValueMinMax, eNoReqStates,
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY},
-  {"spreadsheet", nsIAccessibleRole::ROLE_TABLE, eNameLabelOrTitle, eNoValue, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE | nsIAccessibleStates::STATE_FOCUSABLE,
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY}, // Still supported, but deprecated in favor of grid
-  {"status", nsIAccessibleRole::ROLE_STATUSBAR, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"tab", nsIAccessibleRole::ROLE_PAGETAB, eNameOkFromChildren, eNoValue, eNoReqStates, END_ENTRY},
-  {"table", nsIAccessibleRole::ROLE_TABLE, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"td", nsIAccessibleRole::ROLE_CELL, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"th", nsIAccessibleRole::ROLE_CELL, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"tablist", nsIAccessibleRole::ROLE_PAGETABLIST, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"tabpanel", nsIAccessibleRole::ROLE_PROPERTYPAGE, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"textarea", nsIAccessibleRole::ROLE_ENTRY, eNameLabelOrTitle, eHasValueMinMax, eNoReqStates,
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, END_ENTRY}, // XXX nsIAccessibleStates::EXT_STATE_MULTI_LINE supported in code
-  {"textfield", nsIAccessibleRole::ROLE_ENTRY, eNameLabelOrTitle, eHasValueMinMax, eNoReqStates,
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY}, 
-            {"haspopup", BOOL_STATE, nsIAccessibleStates::STATE_HASPOPUP}, END_ENTRY}, // XXX nsIAccessibleStates::EXT_STATE_SINGLE_LINE supported in code
-  {"toolbar", nsIAccessibleRole::ROLE_TOOLBAR, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {"tree", nsIAccessibleRole::ROLE_OUTLINE, eNameLabelOrTitle, eNoValue, eNoReqStates,
-            {"readonly", BOOL_STATE, nsIAccessibleStates::STATE_READONLY},
-            {"multiselectable", BOOL_STATE, nsIAccessibleStates::STATE_MULTISELECTABLE | nsIAccessibleStates::STATE_EXTSELECTABLE}, END_ENTRY},
-  {"treeitem", nsIAccessibleRole::ROLE_OUTLINEITEM, eNameOkFromChildren, eNoValue, eNoReqStates,
-            {"selected", BOOL_STATE, nsIAccessibleStates::STATE_SELECTED | nsIAccessibleStates::STATE_SELECTABLE},
-            {"selected", "false", nsIAccessibleStates::STATE_SELECTABLE},
-            {"expanded", BOOL_STATE, nsIAccessibleStates::STATE_EXPANDED},
-            {"expanded", "false", nsIAccessibleStates::STATE_COLLAPSED},
-            {"checked", BOOL_STATE, nsIAccessibleStates::STATE_CHECKED | nsIAccessibleStates::STATE_CHECKABLE},
-            {"checked", "mixed", nsIAccessibleStates::STATE_MIXED},
-            {"checked", "false", nsIAccessibleStates::STATE_CHECKABLE},},
-  {"treegroup", nsIAccessibleRole::ROLE_GROUPING, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY},
-  {nsnull, nsIAccessibleRole::ROLE_NOTHING, eNameLabelOrTitle, eNoValue, eNoReqStates, END_ENTRY} // Last item
-};
-
-// XHTML 2 roles
-// These don't need a mapping - they are exposed either through DOM or via MSAA role string
-// banner, contentinfo, main, navigation, note, search, secondary, seealso
-
-nsStateMapEntry nsAccessible::gUnivStateMap[] = {
-  {"disabled", BOOL_STATE, nsIAccessibleStates::STATE_UNAVAILABLE},
-  {"required", BOOL_STATE, nsIAccessibleStates::STATE_REQUIRED},
-  {"invalid", BOOL_STATE, nsIAccessibleStates::STATE_INVALID}
-};
-
 NS_IMETHODIMP nsAccessible::GetFinalRole(PRUint32 *aRole)
 {
   if (mRoleMapEntry) {
     *aRole = mRoleMapEntry->role;
     if (*aRole != nsIAccessibleRole::ROLE_NOTHING) {
       return NS_OK;
     }
   }
@@ -2352,17 +2226,17 @@ PRBool nsAccessible::MappedAttrState(nsI
   // Return true if we should continue
   if (!aStateMapEntry->attributeName) {
     return PR_FALSE;  // Stop looking -- no more states
   }
 
   nsAutoString attribValue;
   nsCOMPtr<nsIAtom> attribAtom = do_GetAtom(aStateMapEntry->attributeName); // XXX put atoms directly in entry
   if (aContent->GetAttr(kNameSpaceID_WAIProperties, attribAtom, attribValue)) {
-    if (aStateMapEntry->attributeValue == BOOL_STATE) {
+    if (aStateMapEntry->attributeValue == kBoolState) {
       // No attribute value map specified in state map entry indicates state cleared
       if (attribValue.EqualsLiteral("false")) {
         return *aStateInOut &= ~aStateMapEntry->state;
       }
       return *aStateInOut |= aStateMapEntry->state;
     }
     if (NS_ConvertUTF16toUTF8(attribValue).Equals(aStateMapEntry->attributeValue)) {
       return *aStateInOut |= aStateMapEntry->state;
@@ -2390,19 +2264,20 @@ nsAccessible::GetARIAState(PRUint32 *aSt
   if (!mDOMNode) {
     return NS_ERROR_FAILURE; // Node already shut down
   }
 
   // Test for universal states first
   nsIContent *content = GetRoleContent(mDOMNode);
   NS_ENSURE_TRUE(content, NS_ERROR_FAILURE); // Node already shut down
 
-  PRUint32 length = NS_ARRAY_LENGTH(nsAccessible::gUnivStateMap);
-  for (PRUint32 index = 0; index < length; index++) {
-    MappedAttrState(content, aState, &nsAccessible::gUnivStateMap[index]);
+  PRUint32 index = 0;
+  while (nsARIAMap::gWAIUnivStateMap[index].attributeName != nsnull) {
+    MappedAttrState(content, aState, &nsARIAMap::gWAIUnivStateMap[index]);
+    ++ index;
   }
 
   if (!mRoleMapEntry)
     return NS_OK;
 
   // Once DHTML role is used, we're only readonly if DHTML readonly used
   (*aState) &= ~nsIAccessibleStates::STATE_READONLY;
 
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -52,81 +52,33 @@
 #include "nsAccessibleRelationWrap.h"
 #include "nsIAccessibleEvent.h"
 
 #include "nsIDOMNodeList.h"
 #include "nsINameSpaceManager.h"
 #include "nsWeakReference.h"
 #include "nsString.h"
 #include "nsIDOMDOMStringList.h"
+#include "nsARIAMap.h"
 
 struct nsRect;
 class nsIContent;
 class nsIFrame;
 class nsIPresShell;
 class nsIDOMNode;
 class nsIAtom;
 class nsIView;
 
 // When mNextSibling is set to this, it indicates there ar eno more siblings
 #define DEAD_END_ACCESSIBLE NS_STATIC_CAST(nsIAccessible*, (void*)1)
 
 // Saves a data member -- if child count equals this value we haven't
 // cached children or child count yet
 enum { eChildCountUninitialized = -1 };
 
-struct nsStateMapEntry
-{
-  const char* attributeName;  // magic value of nsnull means last entry in map
-  const char* attributeValue; // magic value of nsnull means any value
-  PRUint32 state;       // OR state with this
-};
-
-enum ENameRule {
-  eNameLabelOrTitle,     // Collect name if explicitly specified from 
-                         // 1) content subtree pointed to by labelledby
-                         //    which contains the ID for the label content, or
-                         // 2) title attribute if specified
-  eNameOkFromChildren    // Collect name from
-                         // 1) labelledby attribute if specified, or
-                         // 2) text & img descendents, or
-                         // 3) title attribute if specified
-};
-
-enum EValueRule {
-  eNoValue,
-  eHasValueMinMax    // Supports value, min and max from waistate:valuenow, valuemin and valuemax
-};
-
-#define eNoReqStates 0
-#define END_ENTRY {0, 0, 0}  // To fill in array of state mappings
-#define BOOL_STATE 0
-
-struct nsRoleMapEntry
-{
-  const char *roleString; // such as "button"
-  PRUint32 role;   // use this role
-  ENameRule nameRule;  // how to compute name
-  EValueRule valueRule;  // how to compute name
-  PRUint32 state;  // always OR state with this
-  // For this role with a DOM attribute/value match definined in
-  // nsStateMapEntry.attributeName && .attributeValue, OR accessible state with
-  // nsStateMapEntry.state
-  // Currently you can have up to 3 DOM attributes with accessible state mappings.
-  // A variable sized array would not allow use of C++'s struct initialization feature.
-  nsStateMapEntry attributeMap1;
-  nsStateMapEntry attributeMap2;
-  nsStateMapEntry attributeMap3;
-  nsStateMapEntry attributeMap4;
-  nsStateMapEntry attributeMap5;
-  nsStateMapEntry attributeMap6;
-  nsStateMapEntry attributeMap7;
-};
-
-
 class nsAccessibleDOMStringList : public nsIDOMDOMStringList
 {
 public:
   nsAccessibleDOMStringList();
   virtual ~nsAccessibleDOMStringList();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMDOMSTRINGLIST
@@ -306,16 +258,13 @@ protected:
   // Check the visibility across both parent content and chrome
   PRBool CheckVisibilityInParentChain(nsIDocument* aDocument, nsIView* aView);
 
   // Data Members
   nsCOMPtr<nsIAccessible> mParent;
   nsIAccessible *mFirstChild, *mNextSibling;
   nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well
   PRInt32 mAccChildCount;
-
-  static nsRoleMapEntry gWAIRoleMap[];
-  static nsStateMapEntry gUnivStateMap[];
 };
 
 
 #endif  
 
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -758,16 +758,17 @@ STDMETHODIMP nsAccessibleWrap::get_accDe
 
 STDMETHODIMP nsAccessibleWrap::accSelect(
       /* [in] */ long flagsSelect,
       /* [optional][in] */ VARIANT varChild)
 {
   // currently only handle focus and selection
   nsCOMPtr<nsIAccessible> xpAccessible;
   GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
+  NS_ENSURE_TRUE(xpAccessible, E_FAIL);
 
   if (flagsSelect & (SELFLAG_TAKEFOCUS|SELFLAG_TAKESELECTION|SELFLAG_REMOVESELECTION))
   {
     if (flagsSelect & SELFLAG_TAKEFOCUS)
       xpAccessible->TakeFocus();
 
     if (flagsSelect & SELFLAG_TAKESELECTION)
       xpAccessible->TakeSelection();