Bug 742657 - move nsAccUtils::GetRoleMapEntry(nsINode *aNode) into nsARIAMap, r=tbsaunde, f=surkov
authorpcheng@gmx.com <pcheng@gmx.com>
Mon, 16 Apr 2012 18:24:23 +0900
changeset 95061 5972e57175a560315683a098c0e57563027db456
parent 95060 01fd11649cc8f93cc9d4df770884019938794361
child 95062 61088f8aa842fb7042453ce2b2565492b32322d8
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstbsaunde
bugs742657
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 742657 - move nsAccUtils::GetRoleMapEntry(nsINode *aNode) into nsARIAMap, r=tbsaunde, f=surkov
accessible/src/base/nsARIAMap.cpp
accessible/src/base/nsARIAMap.h
accessible/src/base/nsAccDocManager.cpp
accessible/src/base/nsAccUtils.cpp
accessible/src/base/nsAccUtils.h
accessible/src/base/nsAccessibilityService.cpp
accessible/src/base/nsAccessible.h
accessible/src/base/nsDocAccessible.cpp
accessible/src/html/nsHTMLImageMapAccessible.cpp
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -34,21 +34,24 @@
  * 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 "nsCoreUtils.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsIContent.h"
+#include "nsWhitespaceTokenizer.h"
 
+using namespace mozilla;
 using namespace mozilla::a11y;
 using namespace mozilla::a11y::aria;
 
 /**
  *  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.
  *
@@ -57,17 +60,17 @@ using namespace mozilla::a11y::aria;
  *  When no nsIAccessibleRole enum 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
  */
 
-nsRoleMapEntry nsARIAMap::gWAIRoleMap[] = 
+static nsRoleMapEntry sWAIRoleMaps[] =
 {
   {
     "alert",
     roles::ALERT,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
@@ -581,19 +584,17 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
                      // on states
     eNoLiveAttr,
     kNoReqStates,
     eARIASelectable,
     eARIACheckedMixed
   }
 };
 
-PRUint32 nsARIAMap::gWAIRoleMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIRoleMap);
-
-nsRoleMapEntry nsARIAMap::gLandmarkRoleMap = {
+static nsRoleMapEntry sLandmarkRoleMap = {
   "",
   roles::NOTHING,
   kUseNativeRole,
   eNoValue,
   eNoAction,
   eNoLiveAttr,
   kNoReqStates
 };
@@ -662,8 +663,44 @@ nsAttributeCharacteristics nsARIAMap::gW
   {&nsGkAtoms::aria_sort,                               ATTR_VALTOKEN },
   {&nsGkAtoms::aria_valuenow,          ATTR_BYPASSOBJ                 },
   {&nsGkAtoms::aria_valuemin,          ATTR_BYPASSOBJ                 },
   {&nsGkAtoms::aria_valuemax,          ATTR_BYPASSOBJ                 },
   {&nsGkAtoms::aria_valuetext,         ATTR_BYPASSOBJ                 }
 };
 
 PRUint32 nsARIAMap::gWAIUnivAttrMapLength = NS_ARRAY_LENGTH(nsARIAMap::gWAIUnivAttrMap);
+
+nsRoleMapEntry*
+aria::GetRoleMap(nsINode* aNode)
+{
+  nsIContent* content = nsCoreUtils::GetRoleContent(aNode);
+  nsAutoString roleString;
+  if (!content ||
+      !content->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roleString) ||
+      roleString.IsEmpty()) {
+    // We treat role="" as if the role attribute is absent (per aria spec:8.1.1)
+    return nsnull;
+  }
+
+  nsWhitespaceTokenizer tokenizer(roleString);
+  while (tokenizer.hasMoreTokens()) {
+    // Do a binary search through table for the next role in role list
+    NS_LossyConvertUTF16toASCII role(tokenizer.nextToken());
+    PRUint32 low = 0;
+    PRUint32 high = ArrayLength(sWAIRoleMaps);
+    while (low < high) {
+      PRUint32 idx = (low + high) / 2;
+      PRInt32 compare = strcmp(role.get(), sWAIRoleMaps[idx].roleString);
+      if (compare == 0) 
+        return sWAIRoleMaps + idx;
+
+      if (compare < 0)
+        high = idx;
+      else
+        low = idx + 1;
+    }
+  }
+
+  // Always use some entry if there is a non-empty role string
+  // To ensure an accessible object is created
+  return &sLandmarkRoleMap;
+}
--- a/accessible/src/base/nsARIAMap.h
+++ b/accessible/src/base/nsARIAMap.h
@@ -40,16 +40,17 @@
 #ifndef _nsARIAMap_H_
 #define _nsARIAMap_H_
 
 #include "ARIAStateMap.h"
 #include "mozilla/a11y/Role.h"
 
 class nsIAtom;
 class nsIContent;
+class nsINode;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Value constants
 
 /**
  * Used to define if role requires to expose nsIAccessibleValue.
  */
 enum EValueRule
@@ -206,28 +207,16 @@ struct nsRoleMapEntry
 /**
  *  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
 {
   /**
-   * Array of supported ARIA role map entries and its length.
-   */
-  static nsRoleMapEntry gWAIRoleMap[];
-  static PRUint32 gWAIRoleMapLength;
-
-  /**
-   * Landmark role map entry. Used when specified ARIA role isn't mapped to
-   * accessibility API.
-   */
-  static nsRoleMapEntry gLandmarkRoleMap;
-
-  /**
    * Empty role map entry. Used by accessibility service to create an accessible
    * if the accessible can't use role of used accessible class. For example,
    * it is used for table cells that aren't contained by table.
    */
   static nsRoleMapEntry gEmptyRoleMap;
 
   /**
    * State map of ARIA states applied to any accessible not depending on
@@ -252,9 +241,27 @@ struct nsARIAMap
     while (mozilla::a11y::aria::MapToState(gWAIUnivStateMap[index],
                                            aElement, &state))
       index++;
 
     return state;
   }
 };
 
+namespace mozilla {
+namespace a11y {
+namespace aria {
+
+/**
+ * Get the role map entry for a given DOM node. This will use the first
+ * ARIA role if the role attribute provides a space delimited list of roles.
+ *
+ * @param aNode  [in] the DOM node to get the role map entry for
+ * @return        a pointer to the role map entry for the ARIA role, or nsnull
+ *                if none
+ */
+nsRoleMapEntry* GetRoleMap(nsINode* aNode);
+
+} // namespace aria
+} // namespace a11y
+} // namespace mozilla
+
 #endif
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsAccDocManager.h"
 
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsApplicationAccessible.h"
+#include "nsARIAMap.h"
 #include "nsRootAccessibleWrap.h"
 #include "States.h"
 
 #include "nsCURILoader.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsIChannel.h"
 #include "nsIContentViewer.h"
 #include "nsIDOMDocument.h"
@@ -397,17 +398,17 @@ nsAccDocManager::CreateDocOrRootAccessib
   if (!docAcc || !mDocAccessibleCache.Put(aDocument, docAcc))
     return nsnull;
 
   // Initialize the document accessible.
   if (!docAcc->Init()) {
     docAcc->Shutdown();
     return nsnull;
   }
-  docAcc->SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(aDocument));
+  docAcc->SetRoleMapEntry(aria::GetRoleMap(aDocument));
 
   // Bind the document to the tree.
   if (isRootDoc) {
     nsAccessible* appAcc = nsAccessNode::GetApplicationAccessible();
     if (!appAcc->AppendChild(docAcc)) {
       docAcc->Shutdown();
       return nsnull;
     }
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -169,17 +169,17 @@ nsAccUtils::SetLiveContainerAttributes(n
     // container-relevant attribute
     if (relevant.IsEmpty() &&
         nsAccUtils::HasDefinedARIAToken(ancestor, nsGkAtoms::aria_relevant) &&
         ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_relevant, relevant))
       SetAccAttr(aAttributes, nsGkAtoms::containerRelevant, relevant);
 
     // container-live, and container-live-role attributes
     if (live.IsEmpty()) {
-      nsRoleMapEntry *role = GetRoleMapEntry(ancestor);
+      nsRoleMapEntry* role = aria::GetRoleMap(ancestor);
       if (nsAccUtils::HasDefinedARIAToken(ancestor,
                                           nsGkAtoms::aria_live)) {
         ancestor->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_live,
                           live);
       } else if (role) {
         GetLiveAttrValue(role->liveAttRule, live);
       }
       if (!live.IsEmpty()) {
@@ -413,55 +413,16 @@ nsAccUtils::GetScreenCoordsForParent(nsA
   nsIFrame *parentFrame = parent->GetFrame();
   if (!parentFrame)
     return nsIntPoint(0, 0);
 
   nsIntRect parentRect = parentFrame->GetScreenRectExternal();
   return nsIntPoint(parentRect.x, parentRect.y);
 }
 
-nsRoleMapEntry*
-nsAccUtils::GetRoleMapEntry(nsINode *aNode)
-{
-  nsIContent *content = nsCoreUtils::GetRoleContent(aNode);
-  nsAutoString roleString;
-  if (!content ||
-      !content->GetAttr(kNameSpaceID_None, nsGkAtoms::role, roleString) ||
-      roleString.IsEmpty()) {
-    // We treat role="" as if the role attribute is absent (per aria spec:8.1.1)
-    return nsnull;
-  }
-
-  nsWhitespaceTokenizer tokenizer(roleString);
-  while (tokenizer.hasMoreTokens()) {
-    // Do a binary search through table for the next role in role list
-    NS_LossyConvertUTF16toASCII role(tokenizer.nextToken());
-    PRUint32 low = 0;
-    PRUint32 high = nsARIAMap::gWAIRoleMapLength;
-    while (low < high) {
-      PRUint32 index = (low + high) / 2;
-      PRInt32 compare = PL_strcmp(role.get(), nsARIAMap::gWAIRoleMap[index].roleString);
-      if (compare == 0) {
-        // The  role attribute maps to an entry in the role table
-        return &nsARIAMap::gWAIRoleMap[index];
-      }
-      if (compare < 0) {
-        high = index;
-      }
-      else {
-        low = index + 1;
-      }
-    }
-  }
-
-  // Always use some entry if there is a non-empty role string
-  // To ensure an accessible object is created
-  return &nsARIAMap::gLandmarkRoleMap;
-}
-
 PRUint8
 nsAccUtils::GetAttributeCharacteristics(nsIAtom* aAtom)
 {
     for (PRUint32 i = 0; i < nsARIAMap::gWAIUnivAttrMapLength; i++)
       if (*nsARIAMap::gWAIUnivAttrMap[i].attributeName == aAtom)
         return nsARIAMap::gWAIUnivAttrMap[i].characteristics;
 
     return 0;
--- a/accessible/src/base/nsAccUtils.h
+++ b/accessible/src/base/nsAccUtils.h
@@ -245,26 +245,16 @@ public:
   /**
    * Returns coordinates relative screen for the parent of the given accessible.
    *
    * @param aAccessNode  the accessible
    */
   static nsIntPoint GetScreenCoordsForParent(nsAccessNode *aAccessNode);
 
   /**
-   * Get the role map entry for a given DOM node. This will use the first
-   * ARIA role if the role attribute provides a space delimited list of roles.
-   *
-   * @param aNode  [in] the DOM node to get the role map entry for
-   * @return        a pointer to the role map entry for the ARIA role, or nsnull
-   *                if none
-   */
-  static nsRoleMapEntry *GetRoleMapEntry(nsINode *aNode);
-
-  /**
    * Return the role of the given accessible.
    */
   static PRUint32 Role(nsIAccessible *aAcc)
   {
     PRUint32 role = nsIAccessibleRole::ROLE_NOTHING;
     if (aAcc)
       aAcc->GetRole(&role);
 
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -1070,22 +1070,22 @@ nsAccessibilityService::GetOrCreateAcces
                                               weakFrame->GetParent()).IsEmpty()) {
       if (aIsSubtreeHidden)
         *aIsSubtreeHidden = true;
 
       return nsnull;
     }
 
     newAcc = new nsHyperTextAccessibleWrap(content, docAcc);
-    if (docAcc->BindToDocument(newAcc, nsAccUtils::GetRoleMapEntry(aNode)))
+    if (docAcc->BindToDocument(newAcc, aria::GetRoleMap(aNode)))
       return newAcc;
     return nsnull;
   }
 
-  nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode);
+  nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aNode);
   if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation")) {
     // Ignore presentation role if element is focusable (focus event shouldn't
     // be ever lost and should be sensible).
     if (content->IsFocusable())
       roleMapEntry = nsnull;
     else
       return nsnull;
   }
@@ -1122,18 +1122,17 @@ nsAccessibilityService::GetOrCreateAcces
               if (role != roles::TABLE && role != roles::TREE_TABLE)
                 roleMapEntry = &nsARIAMap::gEmptyRoleMap;
             }
 
             break;
           }
 
 #ifdef DEBUG
-          nsRoleMapEntry *tableRoleMapEntry =
-            nsAccUtils::GetRoleMapEntry(tableContent);
+          nsRoleMapEntry* tableRoleMapEntry = aria::GetRoleMap(tableContent);
           NS_ASSERTION(tableRoleMapEntry &&
                        !nsCRT::strcmp(tableRoleMapEntry->roleString, "presentation"),
                        "No accessible for parent table and it didn't have role of presentation");
 #endif
 
           if (!roleMapEntry && !content->IsFocusable()) {
             // Table-related descendants of presentation table are also
             // presentation if they aren't focusable and have not explicit ARIA
@@ -1662,17 +1661,17 @@ nsAccessibilityService::CreateHTMLAccess
     nsAccessible* accessible = new nsHTMLListAccessible(aContent, aDoc);
     NS_IF_ADDREF(accessible);
     return accessible;
   }
 
   if (tag == nsGkAtoms::a) {
     // Only some roles truly enjoy life as nsHTMLLinkAccessibles, for details
     // see closed bug 494807.
-    nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aContent);
+    nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent);
     if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
         roleMapEntry->role != roles::LINK) {
       nsAccessible* accessible = new nsHyperTextAccessibleWrap(aContent, aDoc);
       NS_IF_ADDREF(accessible);
       return accessible;
     }
 
     nsAccessible* accessible = new nsHTMLLinkAccessible(aContent, aDoc);
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -271,17 +271,17 @@ public:
 
   /**
    * Set the ARIA role map entry for a new accessible.
    * For a newly created accessible, specify which role map entry should be used.
    *
    * @param aRoleMapEntry The ARIA nsRoleMapEntry* for the accessible, or 
    *                      nsnull if none.
    */
-  virtual void SetRoleMapEntry(nsRoleMapEntry *aRoleMapEntry);
+  virtual void SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry);
 
   /**
    * Update the children cache.
    */
   inline bool UpdateChildren()
   {
     InvalidateChildren();
     return EnsureChildren();
@@ -831,18 +831,21 @@ protected:
   PRUint32 mFlags;
 
   nsAutoPtr<EmbeddedObjCollector> mEmbeddedObjCollector;
   PRInt32 mIndexOfEmbeddedChild;
   friend class EmbeddedObjCollector;
 
   nsAutoPtr<AccGroupInfo> mGroupInfo;
   friend class AccGroupInfo;
-
-  nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well
+  
+  /**
+   * Non-null indicates author-supplied role; possibly state & value as well
+   */
+  nsRoleMapEntry* mRoleMapEntry;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsAccessible,
                               NS_ACCESSIBLE_IMPL_IID)
 
 
 /**
  * Represent key binding associated with accessible (such as access key and
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -280,17 +280,17 @@ nsDocAccessible::SetRoleMapEntry(nsRoleM
 
   nsIDocument *parentDoc = mDocument->GetParentDocument();
   if (!parentDoc)
     return; // No parent document for the root document
 
   // Allow use of ARIA role from outer to override
   nsIContent *ownerContent = parentDoc->FindContentForSubDocument(mDocument);
   if (ownerContent) {
-    nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(ownerContent);
+    nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(ownerContent);
     if (roleMapEntry)
       mRoleMapEntry = roleMapEntry; // Override
   }
 }
 
 void
 nsDocAccessible::Description(nsString& aDescription)
 {
@@ -1693,17 +1693,17 @@ nsDocAccessible::RemoveDependentIDsFor(n
 bool
 nsDocAccessible::UpdateAccessibleOnAttrChange(dom::Element* aElement,
                                               nsIAtom* aAttribute)
 {
   if (aAttribute == nsGkAtoms::role) {
     // It is common for js libraries to set the role on the body element after
     // the document has loaded. In this case we just update the role map entry.
     if (mContent == aElement) {
-      SetRoleMapEntry(nsAccUtils::GetRoleMapEntry(aElement));
+      SetRoleMapEntry(aria::GetRoleMap(aElement));
       return true;
     }
 
     // Recreate the accessible when role is changed because we might require a
     // different accessible class for the new role or the accessible may expose
     // a different sets of interfaces (COM restriction).
     RecreateAccessible(aElement);
 
--- a/accessible/src/html/nsHTMLImageMapAccessible.cpp
+++ b/accessible/src/html/nsHTMLImageMapAccessible.cpp
@@ -138,17 +138,17 @@ nsHTMLImageMapAccessible::UpdateChildAre
   // Insert new areas into the tree.
   PRUint32 areaElmCount = imageMapObj->AreaCount();
   for (PRUint32 idx = 0; idx < areaElmCount; idx++) {
     nsIContent* areaContent = imageMapObj->GetAreaAt(idx);
 
     nsAccessible* area = mChildren.SafeElementAt(idx);
     if (!area || area->GetContent() != areaContent) {
       nsRefPtr<nsAccessible> area = new nsHTMLAreaAccessible(areaContent, mDoc);
-      if (!mDoc->BindToDocument(area, nsAccUtils::GetRoleMapEntry(areaContent)))
+      if (!mDoc->BindToDocument(area, aria::GetRoleMap(areaContent)))
         break;
 
       if (!InsertChildAt(idx, area)) {
         mDoc->UnbindFromDocument(area);
         break;
       }
 
       if (aDoFireEvents) {