Index: test/keystrokes/firefox/dojo_button.py
===================================================================
--- test/keystrokes/firefox/dojo_button.py	(revision 4483)
+++ test/keystrokes/firefox/dojo_button.py	(working copy)
@@ -89,7 +89,7 @@
 sequence.append(PauseAction(3000))
 sequence.append(utils.AssertPresentationAction(
     "Tab to Create",
-    ["BRAILLE LINE:  'Create Button View Button Create Button   Button $l Edit! $l   $l $l Color $l   $lSave Button   Button Disabled Button'",
+    ["BRAILLE LINE:  'Create Button View Button Create Button   Menu $l Edit! $l   $l $l Color $l   $lSave Button   Menu Disabled Button'",
      "     VISIBLE:  'Create Button View Button Create', cursor=1",
      "SPEECH OUTPUT: ''",
      "SPEECH OUTPUT: 'Create button'",
@@ -103,7 +103,7 @@
 sequence.append(PauseAction(3000))
 sequence.append(utils.AssertPresentationAction(
     "Basic Where Am I on Create", 
-    ["BRAILLE LINE:  'Create Button View Button Create Button   Button $l Edit! $l   $l $l Color $l   $lSave Button   Button Disabled Button'",
+    ["BRAILLE LINE:  'Create Button View Button Create Button   Menu $l Edit! $l   $l $l Color $l   $lSave Button   Menu Disabled Button'",
      "     VISIBLE:  'Create Button View Button Create', cursor=1",
      "SPEECH OUTPUT: 'Create'",
      "SPEECH OUTPUT: 'button'",
@@ -125,10 +125,10 @@
 sequence.append(WaitForFocus("", acc_role=pyatspi.ROLE_MENU))
 sequence.append(utils.AssertPresentationAction(
     "Tab to drop down menu on Create", 
-    ["BRAILLE LINE:  'Create Button   Button $l Edit! $l   $l $l Color $l   $lSave Button   Button Disabled Button'",
-     "     VISIBLE:  '  Button $l Edit! $l   $l $l Col', cursor=1",
+    ["BRAILLE LINE:  'Create Button   Menu $l Edit! $l   $l $l Color $l   $lSave Button   Menu Disabled Button'",
+     "     VISIBLE:  '  Menu $l Edit! $l   $l $l Color', cursor=1",
      "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: '  button'"]))
+     "SPEECH OUTPUT: '  menu'"]))
 
 ########################################################################
 # Do a basic "Where Am I" via KP_Enter.  
@@ -138,10 +138,10 @@
 sequence.append(PauseAction(3000))
 sequence.append(utils.AssertPresentationAction(
     "Basic Where Am I on drop down menu on Create", 
-    ["BRAILLE LINE:  'Create Button   Button $l Edit! $l   $l $l Color $l   $lSave Button   Button Disabled Button'",
-     "     VISIBLE:  '  Button $l Edit! $l   $l $l Col', cursor=1",
+    ["BRAILLE LINE:  'Create Button   Menu $l Edit! $l   $l $l Color $l   $lSave Button   Menu Disabled Button'",
+     "     VISIBLE:  '  Menu $l Edit! $l   $l $l Color', cursor=1",
      "SPEECH OUTPUT: ' '",
-     "SPEECH OUTPUT: 'button'",
+     "SPEECH OUTPUT: 'menu'",
      "SPEECH OUTPUT: ''",
      "SPEECH OUTPUT: 'save options'"]))
 
@@ -201,10 +201,10 @@
 sequence.append(WaitForFocus("Edit!", acc_role=pyatspi.ROLE_PUSH_BUTTON))
 sequence.append(utils.AssertPresentationAction(
     "Go to Edit!", 
-    ["BRAILLE LINE:  ' $l Edit! $l   $l $l Color $l   $lSave Button   Button Disabled Button'",
+    ["BRAILLE LINE:  ' $l Edit! $l   $l $l Color $l   $lSave Button   Menu Disabled Button'",
      "     VISIBLE:  ' $l Edit! $l   $l $l Color $l   ', cursor=0",
      "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: 'Edit! button'"]))
+     "SPEECH OUTPUT: 'Edit! menu'"]))
 
 ########################################################################
 # Open the Edit! menu and navigate through it.
@@ -349,12 +349,12 @@
     "Close the Edit! menu", 
     ["BRAILLE LINE:  'tooltip on buttonMenu Menu Menu Menu'",
      "     VISIBLE:  'Menu', cursor=1",
-     "BRAILLE LINE:  ' $l Edit! $l   $l $l Color $l   $lSave Button   Button Disabled Button'",
+     "BRAILLE LINE:  ' $l Edit! $l   $l $l Color $l   $lSave Button   Menu Disabled Button'",
      "     VISIBLE:  ' $l Edit! $l   $l $l Color $l   ', cursor=0",
      "SPEECH OUTPUT: ''",
      "SPEECH OUTPUT: 'menu'",
      "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: 'Edit! button'"]))
+     "SPEECH OUTPUT: 'Edit! menu'"]))
 
 ########################################################################
 # Open the Color menu and navigate through it.
@@ -364,10 +364,10 @@
 sequence.append(WaitForFocus("Color", acc_role=pyatspi.ROLE_PUSH_BUTTON))
 sequence.append(utils.AssertPresentationAction(
     "Tab to the Color button", 
-    ["BRAILLE LINE:  ' $l Color $l   $lSave Button   Button Disabled Button'",
-     "     VISIBLE:  ' $l Color $l   $lSave Button   B', cursor=0",
+    ["BRAILLE LINE:  ' $l Color $l   $lSave Button   Menu Disabled Button'",
+     "     VISIBLE:  ' $l Color $l   $lSave Button   M', cursor=0",
      "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: 'Color button'"]))
+     "SPEECH OUTPUT: 'Color menu'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Down"))
@@ -458,7 +458,7 @@
     "Close the Color menu", 
     ["BRAILLE LINE:  '<button> <input type='button'> Button       Create    $l Edit!    $l Color   Save     '",
      "     VISIBLE:  ' $l Color   Save     ', cursor=1",
-     "SPEECH OUTPUT: '<button> button <input type='button'> button Create button   button Edit!   Color   Save button   button'"]))
+     "SPEECH OUTPUT: '<button> button <input type='button'> button Create button   menu Edit!   Color   Save button   menu'"]))
 
 ########################################################################
 # Go to the unlabelled buttons
@@ -473,7 +473,7 @@
 sequence.append(WaitForFocus("Rich Text Test!", acc_role=pyatspi.ROLE_PUSH_BUTTON))
 sequence.append(utils.AssertPresentationAction(
     "Tab to the first unlabelled button ('+')", 
-    ["BRAILLE LINE:  'Rich Text Test! Button $l   $lSave Button   Button'",
+    ["BRAILLE LINE:  'Rich Text Test! Button $l   $lSave Button   Menu'",
      "     VISIBLE:  'Rich Text Test! Button $l   $lSa', cursor=1",
      "SPEECH OUTPUT: ''",
      "SPEECH OUTPUT: 'Rich Text Test! button'"]))
@@ -483,18 +483,18 @@
 sequence.append(WaitForFocus("Color", acc_role=pyatspi.ROLE_PUSH_BUTTON))
 sequence.append(utils.AssertPresentationAction(
     "Tab to the second unlabelled button ('Color')", 
-    ["BRAILLE LINE:  ' $l   $lSave Button   Button'",
-     "     VISIBLE:  ' $l   $lSave Button   Button', cursor=0",
+    ["BRAILLE LINE:  ' $l   $lSave Button   Menu'",
+     "     VISIBLE:  ' $l   $lSave Button   Menu', cursor=0",
      "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: 'Color button'"]))
+     "SPEECH OUTPUT: 'Color menu'"]))
 
 sequence.append(utils.StartRecordingAction())
 sequence.append(KeyComboAction("Tab"))
 sequence.append(WaitForFocus("Save", acc_role=pyatspi.ROLE_PUSH_BUTTON))
 sequence.append(utils.AssertPresentationAction(
     "Tab to the third unlabelled button ('Save')", 
-    ["BRAILLE LINE:  ' $l   $lSave Button   Button'",
-     "     VISIBLE:  ' $l   $lSave Button   Button', cursor=9",
+    ["BRAILLE LINE:  ' $l   $lSave Button   Menu'",
+     "     VISIBLE:  ' $l   $lSave Button   Menu', cursor=9",
      "SPEECH OUTPUT: ''",
      "SPEECH OUTPUT: 'Save button'"]))
 
@@ -503,10 +503,10 @@
 sequence.append(WaitForFocus("  ▼", acc_role=pyatspi.ROLE_PUSH_BUTTON))
 sequence.append(utils.AssertPresentationAction(
     "Tab to the down arrow button", 
-    ["BRAILLE LINE:  ' $l   $lSave Button   Button'",
-     "     VISIBLE:  ' $l   $lSave Button   Button', cursor=21",
+    ["BRAILLE LINE:  ' $l   $lSave Button   Menu'",
+     "     VISIBLE:  ' $l   $lSave Button   Menu', cursor=21",
      "SPEECH OUTPUT: ''",
-     "SPEECH OUTPUT: '  button'"]))
+     "SPEECH OUTPUT: '  menu'"]))
 
 ########################################################################
 # Tab to the 1st "Toggle me" toggle button.
Index: src/orca/rolenames.py
===================================================================
--- src/orca/rolenames.py	(revision 4483)
+++ src/orca/rolenames.py	(working copy)
@@ -1179,6 +1179,28 @@
                 pyatspi_role = getattr(pyatspi, sym)
                 rolenames[pyatspi_role] = rolenames[key]
 
+def _adjustRole(obj, role):
+    """Adjust the role to what the role really is.
+    """
+
+    # Return fake "menu" role names.
+    #
+    if (role == pyatspi.ROLE_MENU_ITEM) \
+          and (obj.childCount > 0):
+        role = ROLE_MENU
+
+    # If this is an ARIA button with the "haspopup:true" attribute, then
+    # it's really a menu.
+    #
+    if role in [pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_MENU_ITEM]:
+        attributes = obj.getAttributes()
+        for attribute in attributes:
+            if attribute.startswith("haspopup:true"):
+                role = ROLE_MENU
+                break
+
+    return role
+
 def getSpeechForRoleName(obj, role=None):
     """Returns the localized name of the given Accessible object; the name is
     suitable to be spoken.  If a localized name cannot be discovered, this
@@ -1190,13 +1212,8 @@
     Returns a string containing the localized name of the object suitable
     to be spoken.
     """
-    role = role or obj.getRole()
 
-    # Return fake "menu" role names.
-    #[[[TODO: eitani - Discontinue ]]
-    if (role == pyatspi.ROLE_MENU_ITEM) \
-          and (obj.childCount > 0):
-        role = ROLE_MENU
+    role = _adjustRole(obj, role or obj.getRole())
 
     # If the enum is not in the dictionary, check by name.
     role_entry = \
@@ -1222,13 +1239,8 @@
     Returns a short string containing the localized name of the object
     suitable for a Braille display.
     """
-    role = role or obj.getRole()
 
-    # Return fake "menu" role names.
-    #[[[TODO: eitani - Discontinue ]]
-    if (role == pyatspi.ROLE_MENU_ITEM) \
-          and (obj.childCount > 0):
-        role = ROLE_MENU
+    role = _adjustRole(obj, role or obj.getRole())
 
     # If the enum is not in the dictionary, check by name.
     role_entry = \
@@ -1254,13 +1266,8 @@
     Returns a string containing the localized name of the object suitable for
     a Braille display.
     """
-    role = role or obj.getRole()
 
-    # Return fake "menu" role names.
-    #[[[TODO: eitani - Discontinue ]]
-    if (role == pyatspi.ROLE_MENU_ITEM) \
-          and (obj.childCount > 0):
-        role = ROLE_MENU
+    role = _adjustRole(obj, role or obj.getRole())
 
     # If the enum is not in the dictionary, check by name.
     role_entry = \
@@ -1275,9 +1282,6 @@
         else:
             return repr(role)
 
-
-
-
 def getBrailleForRoleName(obj, role=None):
     """Returns the localized name of the given Accessible object; the name is
     a string suitable for a Braille display.  If a localized name cannot
