Bug 615180 - introduce ARIARole() method, r=fer, a=davidb
authorAlexander Surkov <surkov.alexander@gmail.com>
Wed, 01 Dec 2010 16:53:17 +0800
changeset 58433 e6a435a52576c79a8459470940a5c5a1ed488852
parent 58432 f7e893ed421ab5ff38805c8238ff221218fd8898
child 58434 90cbd8bf83e20f2a1b6e8f3b26ca1c11271266d1
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersfer, davidb
bugs615180
milestone2.0b8pre
Bug 615180 - introduce ARIARole() method, r=fer, a=davidb
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/base/nsApplicationAccessible.cpp
accessible/src/base/nsApplicationAccessible.h
accessible/src/base/nsDocAccessible.cpp
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -77,16 +77,17 @@ CPPSRCS = \
   nsTextEquivUtils.cpp \
   nsTextAttrs.cpp \
   $(NULL)
 
 EXPORTS = \
   a11yGeneric.h \
   nsAccessible.h \
   nsAccessNode.h \
+  nsARIAMap.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 += \
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -33,19 +33,23 @@
  * 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"
 
+#include "nsAccessibilityAtoms.h"
+#include "nsIContent.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.
  *
  *  Definition of nsRoleMapEntry and nsStateMapEntry contains comments explaining this table.
  *
  *  When no nsIAccessibleRole enum mapping exists for an ARIA role, the
--- a/accessible/src/base/nsARIAMap.h
+++ b/accessible/src/base/nsARIAMap.h
@@ -36,19 +36,19 @@
  * 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"
-#include "nsAccessibilityAtoms.h"
 
-#include "nsIContent.h"
+class nsIAtom;
+class nsIContent;
 
 ////////////////////////////////////////////////////////////////////////////////
 // Value constants
 
 /**
  * Used to define if role requires to expose nsIAccessibleValue.
  */
 enum EValueRule
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -39,17 +39,16 @@
 
 #include "nsAccessible.h"
 
 #include "nsIXBLAccessible.h"
 
 #include "AccGroupInfo.h"
 #include "AccIterator.h"
 #include "nsAccUtils.h"
-#include "nsARIAMap.h"
 #include "nsDocAccessible.h"
 #include "nsEventShell.h"
 
 #include "nsAccEvent.h"
 #include "nsAccessibilityService.h"
 #include "nsAccTreeWalker.h"
 #include "nsRelUtils.h"
 #include "nsTextEquivUtils.h"
@@ -1819,21 +1818,20 @@ nsAccessible::GetKeyBindings(PRUint8 aAc
   if (!defaultKey.IsEmpty())
     keyBindings->Add(defaultKey);
 
   NS_ADDREF(*aKeyBindings = keyBindings);
   return NS_OK;
 }
 
 PRUint32
-nsAccessible::Role()
+nsAccessible::ARIARoleInternal()
 {
-  // No ARIA role or it doesn't suppress role from native markup.
-  if (!mRoleMapEntry || mRoleMapEntry->roleRule != kUseMapRole)
-    return NativeRole();
+  NS_PRECONDITION(mRoleMapEntry && mRoleMapEntry->roleRule == kUseMapRole,
+                  "ARIARoleInternal should only be called when ARIA role overrides!");
 
   // XXX: these unfortunate exceptions don't fit into the ARIA table. This is
   // where the accessible role depends on both the role and ARIA state.
   if (mRoleMapEntry->role == nsIAccessibleRole::ROLE_PUSHBUTTON) {
     if (nsAccUtils::HasDefinedARIAToken(mContent,
                                         nsAccessibilityAtoms::aria_pressed)) {
       // For simplicity, any existing pressed attribute except "" or "undefined"
       // indicates a toggle.
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -43,16 +43,17 @@
 
 #include "nsIAccessible.h"
 #include "nsIAccessibleHyperLink.h"
 #include "nsIAccessibleSelectable.h"
 #include "nsIAccessibleValue.h"
 #include "nsIAccessibleRole.h"
 #include "nsIAccessibleStates.h"
 
+#include "nsARIAMap.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "nsRefPtrHashtable.h"
 
 class AccGroupInfo;
 class EmbeddedObjCollector;
 class nsAccessible;
 class AccEvent;
@@ -140,17 +141,35 @@ public:
    *                           explicitly (see nsIAccessible::name attribute for
    *                           details)
    */
   virtual nsresult GetNameInternal(nsAString& aName);
 
   /**
    * Return enumerated accessible role (see constants in nsIAccessibleRole).
    */
-  virtual PRUint32 Role();
+  inline PRUint32 Role()
+  {
+    if (!mRoleMapEntry || mRoleMapEntry->roleRule != kUseMapRole)
+      return NativeRole();
+
+    return ARIARoleInternal();
+  }
+
+  /**
+   * Return accessible role specified by ARIA (see constants in
+   * nsIAccessibleRole).
+   */
+  inline PRUint32 ARIARole()
+  {
+    if (!mRoleMapEntry || mRoleMapEntry->roleRule != kUseMapRole)
+      return nsIAccessibleRole::ROLE_NOTHING;
+
+    return ARIARoleInternal();
+  }
 
   /**
    * Returns enumerated accessible role from native markup (see constants in
    * nsIAccessibleRole). Doesn't take into account ARIA roles.
    */
   virtual PRUint32 NativeRole();
 
   /**
@@ -200,17 +219,16 @@ 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);
-  const nsRoleMapEntry* GetRoleMapEntry() const { return mRoleMapEntry; }
 
   /**
    * Cache children if necessary. Return true if the accessible is defunct.
    */
   PRBool EnsureChildren();
 
   /**
    * Set the child count to -1 (unknown) and null out cached child pointers.
@@ -437,16 +455,21 @@ protected:
    * Return sibling accessible at the given offset.
    */
   virtual nsAccessible* GetSiblingAtOffset(PRInt32 aOffset,
                                            nsresult *aError = nsnull);
 
   //////////////////////////////////////////////////////////////////////////////
   // Miscellaneous helpers
 
+  /**
+   * Return ARIA role (helper method).
+   */
+  PRUint32 ARIARoleInternal();
+
   virtual nsIFrame* GetBoundsFrame();
   virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
   PRBool IsVisible(PRBool *aIsOffscreen); 
 
   //////////////////////////////////////////////////////////////////////////////
   // Name helpers
 
   /**
--- a/accessible/src/base/nsApplicationAccessible.cpp
+++ b/accessible/src/base/nsApplicationAccessible.cpp
@@ -374,22 +374,16 @@ nsApplicationAccessible::IsPrimaryForNod
 
 nsresult
 nsApplicationAccessible::GetARIAState(PRUint32 *aState, PRUint32 *aExtraState)
 {
   return NS_OK;
 }
 
 PRUint32
-nsApplicationAccessible::Role()
-{
-  return NativeRole();
-}
-
-PRUint32
 nsApplicationAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_APP_ROOT;
 }
 
 nsresult
 nsApplicationAccessible::GetStateInternal(PRUint32 *aState,
                                           PRUint32 *aExtraState)
--- a/accessible/src/base/nsApplicationAccessible.h
+++ b/accessible/src/base/nsApplicationAccessible.h
@@ -121,17 +121,16 @@ public:
   // nsAccessNode
   virtual PRBool IsDefunct();
   virtual PRBool Init();
   virtual void Shutdown();
   virtual bool IsPrimaryForNode() const;
 
   // nsAccessible
   virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState);
-  virtual PRUint32 Role();
   virtual PRUint32 NativeRole();
   virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
 
   virtual void InvalidateChildren();
 
 protected:
 
   // nsAccessible
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1492,18 +1492,17 @@ nsDocAccessible::UpdateTree(nsIContent* 
 
   // Check to see if change occurred inside an alert, and fire an EVENT_ALERT
   // if it did.
   if (aIsInsert && !(updateFlags & eAlertAccessible)) {
     // XXX: tree traversal is perf issue, accessible should know if they are
     // children of alert accessible to avoid this.
     nsAccessible* ancestor = container;
     while (ancestor) {
-      const nsRoleMapEntry* roleMapEntry = ancestor->GetRoleMapEntry();
-      if (roleMapEntry && roleMapEntry->role == nsIAccessibleRole::ROLE_ALERT) {
+      if (ancestor->ARIARole() == nsIAccessibleRole::ROLE_ALERT) {
         FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT,
                                    ancestor->GetNode(), AccEvent::eRemoveDupes,
                                    fromUserInput);
         break;
       }
 
       // Don't climb above this document.
       if (ancestor == this)
@@ -1928,18 +1927,17 @@ nsDocAccessible::UpdateTreeInternal(nsAc
 
       // XXX: We don't look into children of hidden subtree to find hiding
       // menupopup (as we did prior bug 570275) because we don't do that when
       // menu is showing (and that's impossible until bug 606924 is fixed).
       // Nevertheless we should do this at least because layout coalesces
       // the changes before our processing and we may miss some menupopup
       // events. Now we just want to be consistent in content insertion/removal
       // handling.
-      const nsRoleMapEntry* roleMapEntry = accessible->GetRoleMapEntry();
-      if (roleMapEntry && roleMapEntry->role == nsIAccessibleRole::ROLE_MENUPOPUP) {
+      if (accessible->ARIARole() == nsIAccessibleRole::ROLE_MENUPOPUP) {
         nsRefPtr<AccEvent> event =
           new AccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END, accessible);
 
         if (event)
           FireDelayedAccessibleEvent(event);
       }
     }
 
@@ -1951,29 +1949,27 @@ nsDocAccessible::UpdateTreeInternal(nsAc
       else
         event = new AccHideEvent(accessible, node, aFromUserInput);
 
       if (event)
         FireDelayedAccessibleEvent(event);
     }
 
     if (aIsInsert) {
-      const nsRoleMapEntry* roleMapEntry = accessible->GetRoleMapEntry();
-      if (roleMapEntry) {
-        if (roleMapEntry->role == nsIAccessibleRole::ROLE_MENUPOPUP) {
-          // Fire EVENT_MENUPOPUP_START if ARIA menu appears.
-          FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
-                                     node, AccEvent::eRemoveDupes, aFromUserInput);
+      PRUint32 ariaRole = accessible->ARIARole();
+      if (ariaRole == nsIAccessibleRole::ROLE_MENUPOPUP) {
+        // Fire EVENT_MENUPOPUP_START if ARIA menu appears.
+        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START,
+                                   node, AccEvent::eRemoveDupes, aFromUserInput);
 
-        } else if (roleMapEntry->role == nsIAccessibleRole::ROLE_ALERT) {
-          // Fire EVENT_ALERT if ARIA alert appears.
-          updateFlags = eAlertAccessible;
-          FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT, node,
-                                     AccEvent::eRemoveDupes, aFromUserInput);
-        }
+      } else if (ariaRole == nsIAccessibleRole::ROLE_ALERT) {
+        // Fire EVENT_ALERT if ARIA alert appears.
+        updateFlags = eAlertAccessible;
+        FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_ALERT, node,
+                                   AccEvent::eRemoveDupes, aFromUserInput);
       }
 
       // If focused node has been shown then it means its frame was recreated
       // while it's focused. Fire focus event on new focused accessible. If
       // the queue contains focus event for this node then it's suppressed by
       // this one.
       if (node == gLastFocusedNode) {
         FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_FOCUS,