Bug 630486 - ASSERTION 'Want to fire mutation events, but it's not safe' in nsContentUtils::HasMutationListeners triggered by a11y, r=marcoz, gavin, bz, f=davidb
authorAlexander Surkov <surkov.alexander@gmail.com>
Fri, 15 Apr 2011 11:11:39 +0900
changeset 68152 29ea31633ac69c8d7219bb7a741bb8ae182da4d6
parent 68151 24505fa656f3cd03fc599a11bf0ab30a7409aa80
child 68153 3a38a70b0e1258a7a389dd813c67d4de6d4b5ea8
child 68155 15b8b01a965e01526b25f989a73a642f1922e50d
push id19525
push usersurkov.alexander@gmail.com
push dateFri, 15 Apr 2011 02:12:21 +0000
treeherdermozilla-central@29ea31633ac6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmarcoz, gavin, bz
bugs630486
milestone6.0a1
first release with
nightly linux32
29ea31633ac6 / 6.0a1 / 20110415030523 / files
nightly linux64
29ea31633ac6 / 6.0a1 / 20110415030523 / files
nightly mac
29ea31633ac6 / 6.0a1 / 20110415030523 / files
nightly win32
29ea31633ac6 / 6.0a1 / 20110415030523 / files
nightly win64
29ea31633ac6 / 6.0a1 / 20110415030205 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 630486 - ASSERTION 'Want to fire mutation events, but it's not safe' in nsContentUtils::HasMutationListeners triggered by a11y, r=marcoz, gavin, bz, f=davidb
accessible/src/base/nsAccessibilityAtomList.h
accessible/src/base/nsCoreUtils.cpp
accessible/src/base/nsCoreUtils.h
accessible/src/xul/nsXULColorPickerAccessible.cpp
accessible/src/xul/nsXULColorPickerAccessible.h
accessible/src/xul/nsXULComboboxAccessible.cpp
accessible/src/xul/nsXULComboboxAccessible.h
accessible/src/xul/nsXULFormControlAccessible.cpp
accessible/src/xul/nsXULFormControlAccessible.h
accessible/src/xul/nsXULMenuAccessible.cpp
accessible/src/xul/nsXULMenuAccessible.h
accessible/tests/mochitest/actions/test_general.xul
accessible/tests/mochitest/tree/Makefile.in
accessible/tests/mochitest/tree/test_button.xul
accessible/tests/mochitest/tree/test_colorpicker.xul
accessible/tests/mochitest/tree/test_menu.xul
accessible/tests/mochitest/treeupdate/Makefile.in
accessible/tests/mochitest/treeupdate/test_colorpicker.xul
accessible/tests/mochitest/treeupdate/test_contextmenu.xul
accessible/tests/mochitest/treeupdate/test_menu.xul
accessible/tests/mochitest/treeupdate/test_menubutton.xul
browser/components/feeds/content/subscribe.xml
content/base/src/nsGkAtomList.h
layout/xul/base/src/nsMenuPopupFrame.cpp
--- a/accessible/src/base/nsAccessibilityAtomList.h
+++ b/accessible/src/base/nsAccessibilityAtomList.h
@@ -59,17 +59,16 @@
 ACCESSIBILITY_ATOM(button, "button")
 ACCESSIBILITY_ATOM(checkbox, "checkbox")
 ACCESSIBILITY_ATOM(col, "col")
 ACCESSIBILITY_ATOM(_empty, "")
 ACCESSIBILITY_ATOM(_false, "false")
 ACCESSIBILITY_ATOM(image, "image")
 ACCESSIBILITY_ATOM(menu, "menu")
 ACCESSIBILITY_ATOM(menuButton, "menu-button")
-ACCESSIBILITY_ATOM(menugenerated, "menugenerated")
 ACCESSIBILITY_ATOM(multiple, "multiple")
 ACCESSIBILITY_ATOM(open, "open")
 ACCESSIBILITY_ATOM(password, "password")
 ACCESSIBILITY_ATOM(radio, "radio")
 ACCESSIBILITY_ATOM(reset, "reset")
 ACCESSIBILITY_ATOM(row, "row")
 ACCESSIBILITY_ATOM(submit, "submit")
 ACCESSIBILITY_ATOM(_true, "true")
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -756,57 +756,16 @@ nsCoreUtils::IsColumnHidden(nsITreeColum
 {
   nsCOMPtr<nsIDOMElement> element;
   aColumn->GetElement(getter_AddRefs(element));
   nsCOMPtr<nsIContent> content = do_QueryInterface(element);
   return content->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::hidden,
                               nsAccessibilityAtoms::_true, eCaseMatters);
 }
 
-void
-nsCoreUtils::GeneratePopupTree(nsIContent *aContent, PRBool aIsAnon)
-{
-  // Set menugenerated="true" on the menupopup node to generate the sub-menu
-  // items if they have not been generated.
-
-  nsCOMPtr<nsIDOMNodeList> list;
-  if (aIsAnon) {    
-    nsIDocument* document = aContent->GetCurrentDoc();
-    if (document)
-      document->GetXBLChildNodesFor(aContent, getter_AddRefs(list));
-
-  } else {
-    list = aContent->GetChildNodesList();
-  }
-
-  PRUint32 length = 0;
-  if (!list || NS_FAILED(list->GetLength(&length)))
-    return;
-
-  for (PRUint32 idx = 0; idx < length; idx++) {
-    nsCOMPtr<nsIDOMNode> childNode;
-    list->Item(idx, getter_AddRefs(childNode));
-    nsCOMPtr<nsIContent> child(do_QueryInterface(childNode));
-
-    PRBool isPopup = child->NodeInfo()->Equals(nsAccessibilityAtoms::menupopup,
-                                               kNameSpaceID_XUL) ||
-                     child->NodeInfo()->Equals(nsAccessibilityAtoms::panel,
-                                               kNameSpaceID_XUL);
-    if (isPopup && !child->AttrValueIs(kNameSpaceID_None,
-                                       nsAccessibilityAtoms::menugenerated,
-                                       nsAccessibilityAtoms::_true,
-                                       eCaseMatters)) {
-
-      child->SetAttr(kNameSpaceID_None, nsAccessibilityAtoms::menugenerated,
-                     NS_LITERAL_STRING("true"), PR_TRUE);
-      return;
-    }
-  }
-}
-
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessibleDOMStringList
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMPL_ISUPPORTS1(nsAccessibleDOMStringList, nsIDOMDOMStringList)
 
 NS_IMETHODIMP
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -362,26 +362,16 @@ public:
   /**
    * Return true if the given node is table header element.
    */
   static PRBool IsHTMLTableHeader(nsIContent *aContent)
   {
     return aContent->NodeInfo()->Equals(nsAccessibilityAtoms::th) ||
       aContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::scope);
   }
-
-  /**
-   * Generates frames for popup subtree.
-   *
-   * @param aContent [in] DOM node containing the menupopup element as a child
-   * @param aIsAnon  [in] specifies whether popup should be searched inside of
-   *                  anonymous or explicit content
-   */
-  static void GeneratePopupTree(nsIContent *aContent,
-                                PRBool aIsAnon = PR_FALSE);
 };
 
 
 /**
  * nsIDOMDOMStringList implementation.
  */
 class nsAccessibleDOMStringList : public nsIDOMDOMStringList
 {
--- a/accessible/src/xul/nsXULColorPickerAccessible.cpp
+++ b/accessible/src/xul/nsXULColorPickerAccessible.cpp
@@ -112,29 +112,16 @@ nsXULColorPickerTileAccessible::NativeSt
 
 nsXULColorPickerAccessible::
   nsXULColorPickerAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsXULColorPickerTileAccessible(aContent, aShell)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULColorPickerAccessible: nsAccessNode
-
-PRBool
-nsXULColorPickerAccessible::Init()
-{
-  if (!nsXULColorPickerTileAccessible::Init())
-    return PR_FALSE;
-
-  nsCoreUtils::GeneratePopupTree(mContent, PR_TRUE);
-  return PR_TRUE;
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // nsXULColorPickerAccessible: nsAccessible
 
 PRUint64
 nsXULColorPickerAccessible::NativeState()
 {
   // Possible states: focused, focusable, unavailable(disabled).
 
   // get focus and disable status from base class
--- a/accessible/src/xul/nsXULColorPickerAccessible.h
+++ b/accessible/src/xul/nsXULColorPickerAccessible.h
@@ -63,19 +63,16 @@ public:
 /**
  * Used for colorpicker button (xul:colorpicker@type="button").
  */
 class nsXULColorPickerAccessible : public nsXULColorPickerTileAccessible
 {
 public:
   nsXULColorPickerAccessible(nsIContent *aContent, nsIWeakReference *aShell);
 
-  // nsAccessNode
-  virtual PRBool Init();
-
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
 
 protected:
 
   // nsAccessible
   virtual void CacheChildren();
--- a/accessible/src/xul/nsXULComboboxAccessible.cpp
+++ b/accessible/src/xul/nsXULComboboxAccessible.cpp
@@ -52,26 +52,16 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULComboboxAccessible::
   nsXULComboboxAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsAccessibleWrap(aContent, aShell)
 {
 }
 
-PRBool
-nsXULComboboxAccessible::Init()
-{
-  if (!nsAccessibleWrap::Init())
-    return PR_FALSE;
-
-  nsCoreUtils::GeneratePopupTree(mContent);
-  return PR_TRUE;
-}
-
 PRUint32
 nsXULComboboxAccessible::NativeRole()
 {
   if (mContent->AttrValueIs(kNameSpaceID_None, nsAccessibilityAtoms::type,
                             nsAccessibilityAtoms::autocomplete, eIgnoreCase))
     return nsIAccessibleRole::ROLE_AUTOCOMPLETE;
   return nsIAccessibleRole::ROLE_COMBOBOX;
 }
--- a/accessible/src/xul/nsXULComboboxAccessible.h
+++ b/accessible/src/xul/nsXULComboboxAccessible.h
@@ -55,18 +55,15 @@ public:
 
   // nsIAccessible
   NS_IMETHOD GetValue(nsAString& aValue);
   NS_IMETHOD GetDescription(nsAString& aDescription);
   NS_IMETHOD DoAction(PRUint8 aIndex);
   NS_IMETHOD GetNumActions(PRUint8 *aNumActions);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
 
-  // nsAccessNode
-  virtual PRBool Init();
-
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
   virtual PRBool GetAllowsAnonChildAccessibles();
 };
 
 #endif
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -105,31 +105,16 @@ nsXULButtonAccessible::DoAction(PRUint8 
   if (aIndex != 0)
     return NS_ERROR_INVALID_ARG;
 
   DoCommand();
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsXULButtonAccessible: nsAccessNode
-
-PRBool
-nsXULButtonAccessible::Init()
-{
-  if (!nsAccessibleWrap::Init())
-    return PR_FALSE;
-
-  if (ContainsMenu())
-    nsCoreUtils::GeneratePopupTree(mContent);
-
-  return PR_TRUE;
-}
-
-////////////////////////////////////////////////////////////////////////////////
 // nsXULButtonAccessible: nsAccessible
 
 PRUint32
 nsXULButtonAccessible::NativeRole()
 {
   return nsIAccessibleRole::ROLE_PUSHBUTTON;
 }
 
--- a/accessible/src/xul/nsXULFormControlAccessible.h
+++ b/accessible/src/xul/nsXULFormControlAccessible.h
@@ -61,19 +61,16 @@ public:
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessible
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD DoAction(PRUint8 index);
 
-  // nsAccessNode
-  virtual PRBool Init();
-
   // nsAccessible
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
 
 protected:
 
   // nsAccessible
   virtual void CacheChildren();
--- a/accessible/src/xul/nsXULMenuAccessible.cpp
+++ b/accessible/src/xul/nsXULMenuAccessible.cpp
@@ -275,26 +275,16 @@ nsXULSelectableAccessible::SelectAll()
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULMenuitemAccessible::
   nsXULMenuitemAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
   nsAccessibleWrap(aContent, aShell)
 {
 }
 
-PRBool
-nsXULMenuitemAccessible::Init()
-{
-  if (!nsAccessibleWrap::Init())
-    return PR_FALSE;
-
-  nsCoreUtils::GeneratePopupTree(mContent);
-  return PR_TRUE;
-}
-
 PRUint64
 nsXULMenuitemAccessible::NativeState()
 {
   PRUint64 state = nsAccessible::NativeState();
 
   // Focused?
   if (mContent->HasAttr(kNameSpaceID_None,
                         nsAccessibilityAtoms::_moz_menuactive))
--- a/accessible/src/xul/nsXULMenuAccessible.h
+++ b/accessible/src/xul/nsXULMenuAccessible.h
@@ -84,19 +84,16 @@ public:
   // nsIAccessible
   NS_IMETHOD GetDescription(nsAString& aDescription);
   NS_IMETHOD GetKeyboardShortcut(nsAString& _retval);
   NS_IMETHOD GetDefaultKeyBinding(nsAString& aKeyBinding);
   NS_IMETHOD DoAction(PRUint8 index);
   NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
   NS_IMETHOD GetNumActions(PRUint8 *_retval);
 
-  // nsAccessNode
-  virtual PRBool Init();
-
   // nsAccessible
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual PRUint32 NativeRole();
   virtual PRUint64 NativeState();
   virtual PRInt32 GetLevelInternal();
   virtual void GetPositionAndSizeInternal(PRInt32 *aPosInSet,
                                           PRInt32 *aSetSize);
 
--- a/accessible/tests/mochitest/actions/test_general.xul
+++ b/accessible/tests/mochitest/actions/test_general.xul
@@ -24,17 +24,22 @@
   <script type="application/javascript">
   <![CDATA[
     function doTest()
     {
       var actionsArray = [
         {
           ID: "menu",
           actionName: "click",
-          events: CLICK_EVENTS
+          events: CLICK_EVENTS,
+          // Wait for focus event, it guarantees us the submenu tree is created,
+          // that's necessary for next test.
+          eventSeq: [
+            new invokerChecker(EVENT_FOCUS, getNode("menu"))
+          ]
         },
         {
           ID: "submenu",
           actionName: "click",
           events: CLICK_EVENTS
         },
         {
           ID: "menuitem",
--- a/accessible/tests/mochitest/tree/Makefile.in
+++ b/accessible/tests/mochitest/tree/Makefile.in
@@ -46,31 +46,29 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		dockids.html \
 	$(warning test_applicationacc.xul temporarily disabled, see bug 561508) \
 		test_aria_globals.html \
 		test_aria_imgmap.html \
 		test_button.xul \
-		test_colorpicker.xul \
 		test_combobox.xul \
 		test_cssoverflow.html \
 		test_dochierarchy.html \
 		test_dockids.html \
 		test_filectrl.html \
 		test_formctrl.html \
 		test_formctrl.xul \
 		test_gencontent.html \
 		test_groupbox.xul \
 		test_iframe.html \
 		test_img.html \
 		test_list.html \
 		test_media.html \
-		test_menu.xul \
 		test_select.html \
 		test_tabbox.xul \
 		test_tabbrowser.xul \
 		test_table.html \
 		test_tree.xul \
 		test_txtcntr.html \
 		test_txtctrl.html \
 		test_txtctrl.xul \
--- a/accessible/tests/mochitest/tree/test_button.xul
+++ b/accessible/tests/mochitest/tree/test_button.xul
@@ -19,132 +19,34 @@
   <script type="application/javascript">
   <![CDATA[
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
     function doTest()
     {
       //////////////////////////////////////////////////////////////////////////
-      // button1
+      // button
 
       var accTree = {
         role: ROLE_PUSHBUTTON,
         name: "hello",
         children: [ ]
       };
       testAccessibleTree("button1", accTree);
 
       //////////////////////////////////////////////////////////////////////////
-      // button2
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button2", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button3
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          },
-          {
-            role: ROLE_PUSHBUTTON,
-            children: [
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button3", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button4
+      // toolbarbutton
 
       var accTree = {
         role: ROLE_PUSHBUTTON,
         name: "hello",
         children: [ ]
       };
-      testAccessibleTree("button4", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button5
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button5", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button6
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          },
-          {
-            role: ROLE_PUSHBUTTON,
-            children: [
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button6", accTree);
+      testAccessibleTree("button2", accTree);
 
       SimpleTest.finish()
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
@@ -160,39 +62,14 @@
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
       <button id="button1" label="hello"/>
-      <button id="button2" type="menu" label="hello">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </button>
-      <button id="button3" type="menu-button" label="hello">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </button>
-
-      <toolbarbutton id="button4" label="hello"/>
-      <toolbarbutton id="button5" type="menu" label="hello">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </toolbarbutton>
-      <toolbarbutton id="button6" type="menu-button" label="hello">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </toolbarbutton>
+      <toolbarbutton id="button2" label="hello"/>
     </vbox>
   </hbox>
 
 </window>
 
deleted file mode 100644
--- a/accessible/tests/mochitest/tree/test_menu.xul
+++ /dev/null
@@ -1,86 +0,0 @@
-<?xml version="1.0"?>
-<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
-<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
-                 type="text/css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="Accessible XUL menu hierarchy tests">
-
-  <script type="application/javascript" 
-          src="chrome://mochikit/content/MochiKit/packed.js" />
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-
-  <script type="application/javascript"
-          src="../common.js" />
-  <script type="application/javascript"
-          src="../role.js" />
-
-  <script type="application/javascript">
-  <![CDATA[
-    ////////////////////////////////////////////////////////////////////////////
-    // Test
-
-    function doTest()
-    {
-      if (LINUX || SOLARIS) {
-        // XXX: bug 527646
-
-        todo(false, "Failure on Linux and Solaris.");
-        SimpleTest.finish();
-        return;
-      }
-
-      var accTree = {
-        role: ROLE_PARENT_MENUITEM,
-        name: "menu",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("menu", accTree);
-
-      SimpleTest.finish();
-    }
-
-    SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTest);
-  ]]>
-  </script>
-
-  <hbox flex="1" style="overflow: auto;">
-    <body xmlns="http://www.w3.org/1999/xhtml">
-      <a target="_blank"
-         href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
-         title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
-        Mozilla Bug 249292
-      </a><br/>
-      <p id="display"></p>
-      <div id="content" style="display: none">
-      </div>
-      <pre id="test">
-      </pre>
-    </body>
-
-    <vbox flex="1">
-      <menu id="menu" label="menu">
-        <menupopup>
-          <menuitem label="menuitem"/>
-          <menuitem label="menuitem"/>
-        </menupopup>
-      </menu>
-    </vbox>
-  </hbox>
-
-</window>
-
--- a/accessible/tests/mochitest/treeupdate/Makefile.in
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -42,21 +42,24 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible/treeupdate
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =\
 		test_ariadialog.html \
+		test_colorpicker.xul \
+		test_contextmenu.xul \
 		test_doc.html \
 		test_gencontent.html \
 		test_list_editabledoc.html \
 		test_list.html \
 		test_menu.xul \
+		test_menubutton.xul \
 		test_recreation.html \
 		test_select.html \
 		test_textleaf.html \
 		test_visibility.html \
 		test_whitespace.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
rename from accessible/tests/mochitest/tree/test_colorpicker.xul
rename to accessible/tests/mochitest/treeupdate/test_colorpicker.xul
--- a/accessible/tests/mochitest/tree/test_colorpicker.xul
+++ b/accessible/tests/mochitest/treeupdate/test_colorpicker.xul
@@ -10,60 +10,137 @@
           src="chrome://mochikit/content/MochiKit/packed.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
           src="../role.js" />
+  <script type="application/javascript"
+          src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
+    function openColorpicker(aColorpickerID)
+    {
+      this.node = getNode(aColorpickerID);
+
+      this.eventSeq = [];
+
+      var it = new colorButtonIterator(this.node);
+      for (var btnNode = it.next(); btnNode = it.next(); btnNode)
+        this.eventSeq.push(new invokerChecker(EVENT_SHOW, btnNode));
+
+      var popupNode = getPopupNode(this.node);
+      this.eventSeq.push(new invokerChecker(EVENT_REORDER, popupNode));
+
+      this.invoke = function openColorpicker_invoke()
+      {
+        var tree =
+          { BUTTONDROPDOWNGRID: [
+            { ALERT: [ ] }
+          ] };
+        testAccessibleTree(this.node, tree);
+
+        this.node.showPopup();
+      }
+
+      this.finalCheck = function openColorpicker_finalCheck()
+      {
+        var tree =
+          { BUTTONDROPDOWNGRID: [
+            { ALERT: [ ] }
+          ] };
+
+        var colorButtons = tree.BUTTONDROPDOWNGRID[0].ALERT;
+        var it = new colorButtonIterator(this.node);
+        while (it.next()) {
+          var obj = { PUSHBUTTON: [ ] };
+          colorButtons.push(obj);
+        }
+
+        testAccessibleTree(this.node, tree);
+      }
+
+      this.getID = function openColorpicker_getID()
+      {
+        return "open colorpicker " + prettyName(aColorpickerID);
+      }
+    }
+
+    function getPopupNode(aColorpickerNode)
+    {
+      return aColorpickerNode.mPicker.parentNode;
+    }
+
+    function colorButtonIterator(aColorpickerNode)
+    {
+      this.container = aColorpickerNode.mPicker.mBox;
+      this.group = this.container.firstChild;
+      this.item = null;
+
+      this.next = function colorButtonIterator_next()
+      {
+        if (!this.group)
+          return null;
+
+        if (!this.item) {
+          this.item = this.group.firstChild;
+          return this.item;
+        }
+
+        if (this.item.nextSibling) {
+          this.item = this.item.nextSibling;
+          return this.item;
+        }
+
+        if (this.group.nextSibling) {
+          this.group = this.group.nextSibling;
+          this.item = this.group.firstChild;
+          return this.item;
+        }
+
+        this.group = null;
+        this.item = null;
+        return null;
+      }
+    }
+
+    //gA11yEventDumpToConsole = true; // debug stuff
+
+    var gQueue = null;
     function doTest()
     {
-      //////////////////////////////////////////////////////////////////////////
-      // button1
-
-      var accTree = {
-        role: ROLE_BUTTONDROPDOWNGRID,
-        children: [
-          {
-            role: ROLE_ALERT,
-            children: [ ]
-          }
-        ]
-      };
-
-      var colorButtons = accTree.children[0].children;
-      for (var idx = 0; idx < 70; idx++) {
-        var obj = { role: ROLE_PUSHBUTTON };
-        colorButtons.push(obj);
-      }
-
-      testAccessibleTree("colorpicker", accTree);
-
-      SimpleTest.finish()
+      gQueue = new eventQueue();
+      gQueue.push(new openColorpicker("colorpicker"));
+      gQueue.invoke(); // Will call SimpleTest.finish()
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
     <body xmlns="http://www.w3.org/1999/xhtml">
       <a target="_blank"
          href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
          title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
         Mozilla Bug 249292
-      </a><br/>
+      </a>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=630486"
+         title="Don't force accessible creation for popup children.">
+        Mozilla Bug 630486
+      </a>
+      <br/>
       <p id="display"></p>
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_contextmenu.xul
@@ -0,0 +1,321 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="menu tree and events">
+
+  <script type="application/javascript" 
+          src="chrome://mochikit/content/MochiKit/packed.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+  <script type="application/javascript"
+          src="../role.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+
+    function openMenu(aID, aTree)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_MENUPOPUP_START, getNode(aID))
+      ];
+
+      this.invoke = function openMenu_invoke()
+      {
+        var button = getNode("button");
+        getNode(aID).openPopup(button, "after_start", 0, 0, true, false);
+      }
+
+      this.finalCheck = function openMenu_finalCheck(aEvent)
+      {
+        testAccessibleTree(aID, aTree);
+      }
+
+      this.getID = function openMenu_getID()
+      {
+        return "open menu " + prettyName(aID);
+      }
+    }
+
+    function selectNextMenuItem(aID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, getNode(aID))
+      ];
+
+      this.invoke = function selectMenuItem_invoke()
+      {
+        synthesizeKey("VK_DOWN", { });
+      }
+
+      this.getID = function selectMenuItem_getID()
+      {
+        return "select menuitem " + prettyName(aID);
+      }
+    }
+    
+    function openSubMenu(aSubMenuID, aItemID, aMenuID, aTree)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, getNode(aItemID)),
+      ];
+
+      this.invoke = function openSubMenu_invoke()
+      {
+        synthesizeKey("VK_ENTER", { });
+      }
+
+      this.finalCheck = function openSubMenu_finalCheck(aEvent)
+      {
+        testAccessibleTree(aMenuID, aTree);
+      }
+
+      this.getID = function openSubMenu_getID()
+      {
+        return "open submenu " + prettyName(aSubMenuID) + " focusing item " + prettyName(aItemID);
+      }
+    }
+
+    function closeSubMenu(aSubMenuID, aItemID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_FOCUS, getNode(aItemID)),
+      ];
+
+      this.invoke = function closeSubMenu_invoke()
+      {
+        synthesizeKey("VK_ESCAPE", { });
+      }
+
+      this.getID = function closeSubMenu_getID()
+      {
+        return "close submenu " + prettyName(aSubMenuID) + " focusing item " + prettyName(aItemID);
+      }
+    }
+
+    function closeMenu(aID)
+    {
+      this.eventSeq = [
+        new invokerChecker(EVENT_MENUPOPUP_END, getNode(aID))
+      ];
+
+      this.invoke = function closeMenu_invoke()
+      {
+        synthesizeKey("VK_ESCAPE", { });
+      }
+
+      this.getID = function closeMenu_getID()
+      {
+        return "close menu " + prettyName(aID);
+      }
+    }
+
+    //gA11yEventDumpID = "eventdump";
+    //gA11yEventDumpToConsole = true;
+
+    var gQueue = null;
+    var gContextTree = {};
+
+    // Linux and Windows menu trees discrepancy: bug 527646.
+
+    /**
+     * Return the context menu tree before submenus were open.
+     */
+    function getMenuTree1()
+    {
+      if (LINUX || SOLARIS) {
+        var tree = {
+          role: ROLE_MENUPOPUP,
+          children: [
+            {
+              name: "item0",
+              role: ROLE_MENUITEM,
+              children: []
+            },
+            {
+              name: "item1",
+              role: ROLE_MENUITEM,
+              children: []
+            },
+            {
+              name: "item2",
+              role: ROLE_PARENT_MENUITEM,
+              children: [ ]
+            }
+          ]
+        };
+        return tree;
+      }
+
+      // Windows
+      var tree = {
+        role: ROLE_MENUPOPUP,
+        children: [
+          {
+            name: "item0",
+            role: ROLE_MENUITEM,
+            children: []
+          },
+          {
+            name: "item1",
+            role: ROLE_MENUITEM,
+            children: []
+          },
+          {
+            name: "item2",
+            role: ROLE_PARENT_MENUITEM,
+            children: [
+              {
+                name: "item2",
+                role: ROLE_MENUPOPUP,
+                children: [ ]
+              }
+            ]
+          }
+        ]
+      };
+      return tree;
+    }
+
+    /**
+     * Return context menu tree when submenu was open.
+     */
+    function getMenuTree2()
+    {
+      var tree = getMenuTree1();
+      if (LINUX || SOLARIS) {
+        var submenuTree =
+        {
+          name: "item2.0",
+          role: ROLE_PARENT_MENUITEM,
+          children: [ ]
+        };
+        tree.children[2].children.push(submenuTree);
+        return tree;
+      }
+
+      // Windows
+      var submenuTree =
+      {
+        name: "item2.0",
+        role: ROLE_PARENT_MENUITEM,
+        children: [
+          {
+            name: "item2.0",
+            role: ROLE_MENUPOPUP,
+            children: [ ]
+          }
+        ]
+      };
+
+      tree.children[2].children[0].children.push(submenuTree);
+      return tree;
+    }
+
+    /**
+     * Return context menu tree when subsub menu was open.
+     */
+    function getMenuTree3()
+    {
+      var tree = getMenuTree2();
+      var subsubmenuTree =
+      {
+        name: "item2.0.0",
+        role: ROLE_MENUITEM,
+        children: []
+      };
+
+      if (LINUX || SOLARIS)
+        tree.children[2].children[0].\(subsubmenuTree);
+      else
+        tree.children[2].children[0].children[0].children[0].children.push(subsubmenuTree);
+
+      return tree;
+    }
+
+
+    function doTests()
+    {
+      gQueue = new eventQueue();
+
+      // Check initial empty tree
+      testAccessibleTree("context", { MENUPOPUP: [] });
+
+      // Open context menu and check that menu item accesibles are created.
+      gQueue.push(new openMenu("context", getMenuTree1()));
+
+      // Select items and check focus event on them.
+      gQueue.push(new selectNextMenuItem("item0"));
+      gQueue.push(new selectNextMenuItem("item1"));
+      gQueue.push(new selectNextMenuItem("item2"));
+
+      // Open sub menu and check menu accessible tree and focus event.
+      gQueue.push(new openSubMenu("submenu2", "item2.0",
+                                  "context", getMenuTree2()));
+      gQueue.push(new openSubMenu("submenu2.0", "item2.0.0",
+                                  "context", getMenuTree3()));
+
+      // Close submenus and check that focus goes to parent.
+      gQueue.push(new closeSubMenu("submenu2.0", "item2.0"));
+      gQueue.push(new closeSubMenu("submenu2", "item2"));
+
+      gQueue.push(new closeMenu("context"));
+
+      gQueue.invoke(); // Will call SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTests);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=630194"
+       title="Update accessible tree when opening the menu popup">
+      Mozilla Bug 630194
+    </a>
+    <a target="_blank"
+       href="https://bugzilla.mozilla.org/show_bug.cgi?id=630486"
+       title="Don't force accessible creation for popup children.">
+      Mozilla Bug 630486
+    </a>
+  <p id="display"></p>
+    <div id="content" style="display: none">
+    </div>
+    <pre id="test">
+    </pre>
+  </body>
+
+    <vbox flex="1">
+
+      <menupopup id="context">
+        <menuitem id="item0" label="item0"/>
+        <menuitem id="item1" label="item1"/>
+        <menu id="item2" label="item2">
+          <menupopup id="submenu2">
+            <menu id="item2.0" label="item2.0">
+              <menupopup id="submenu2.0">
+                <menuitem id="item2.0.0" label="item2.0.0"/>
+              </menupopup>
+            </menu>
+          </menupopup>
+        </menu>
+      </menupopup>
+
+      <button context="context" id="button">btn</button>
+
+      <vbox id="eventdump" role="log"/>
+    </vbox>
+  </hbox>
+</window>
--- a/accessible/tests/mochitest/treeupdate/test_menu.xul
+++ b/accessible/tests/mochitest/treeupdate/test_menu.xul
@@ -1,277 +1,130 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
                  type="text/css"?>
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="menu tree and events">
+        title="Accessible XUL menu hierarchy tests">
 
   <script type="application/javascript" 
           src="chrome://mochikit/content/MochiKit/packed.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
-  <script type="application/javascript"
-          src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
-          src="../events.js" />
+          src="../role.js" />
   <script type="application/javascript"
-          src="../role.js" />
+          src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
-    function openMenu(aID, aTree)
+    ////////////////////////////////////////////////////////////////////////////
+    // Invokers
+
+    function openMenu(aID)
     {
+      this.menuNode = getNode(aID),
+
       this.eventSeq = [
-        new invokerChecker(EVENT_MENUPOPUP_START, getNode(aID))
+        new invokerChecker(EVENT_FOCUS, this.menuNode)
       ];
 
       this.invoke = function openMenu_invoke()
       {
-        var button = getNode("button");
-        getNode(aID).openPopup(button, "after_start", 0, 0, true, false);
+        var tree;
+        if (LINUX || SOLARIS) {
+          tree =
+            { PARENT_MENUITEM: [ ] };
+
+        } else {
+          tree =
+            { PARENT_MENUITEM: [
+              { MENUPOPUP: [ ] }
+            ] };
+        }
+        testAccessibleTree(aID, tree);
+
+        // Show menu.
+        this.menuNode.open = true;
       }
 
-      this.finalCheck = function openMenu_finalCheck(aEvent)
+      this.finalCheck = function openMenu_finalCheck()
       {
-        testAccessibleTree(aID, aTree);
+        var tree;
+        if (LINUX || SOLARIS) {
+          tree =
+            { PARENT_MENUITEM: [
+              { MENUITEM: [ ] },
+              { MENUITEM: [ ] }
+            ] };
+
+        } else {
+          tree =
+            { PARENT_MENUITEM: [
+              { MENUPOPUP: [
+                { MENUITEM: [ ] },
+                { MENUITEM: [ ] }
+              ] }
+            ] };
+        }
+        testAccessibleTree(aID, tree);
       }
 
       this.getID = function openMenu_getID()
       {
         return "open menu " + prettyName(aID);
       }
     }
 
-    function selectNextMenuItem(aID)
-    {
-      this.eventSeq = [
-        new invokerChecker(EVENT_FOCUS, getNode(aID))
-      ];
-
-      this.invoke = function selectMenuItem_invoke()
-      {
-        synthesizeKey("VK_DOWN", { });
-      }
-
-      this.getID = function selectMenuItem_getID()
-      {
-        return "select menuitem " + prettyName(aID);
-      }
-    }
-    
-    function openSubMenu(aSubMenuID, aItemID)
-    {
-      this.eventSeq = [
-        new invokerChecker(EVENT_FOCUS, getNode(aItemID)),
-      ];
-
-      this.invoke = function openSubMenu_invoke()
-      {
-        synthesizeKey("VK_ENTER", { });
-      }
-
-      this.finalCheck = function openSubMenu_finalCheck(aEvent)
-      {
-        getAccessible(aItemID);
-      }
-
-      this.getID = function openSubMenu_getID()
-      {
-        return "open submenu " + prettyName(aSubMenuID) + " focusing item " + prettyName(aItemID);
-      }
-    }
-
-    function closeSubMenu(aSubMenuID, aItemID)
-    {
-      this.eventSeq = [
-        new invokerChecker(EVENT_FOCUS, getNode(aItemID)),
-      ];
-
-      this.invoke = function closeSubMenu_invoke()
-      {
-        synthesizeKey("VK_ESCAPE", { });
-      }
-
-      this.getID = function closeSubMenu_getID()
-      {
-        return "close submenu " + prettyName(aSubMenuID) + " focusing item " + prettyName(aItemID);
-      }
-    }
-
-    function closeMenu(aID)
-    {
-      this.eventSeq = [
-        new invokerChecker(EVENT_MENUPOPUP_END, getNode(aID))
-      ];
-
-      this.invoke = function closeMenu_invoke()
-      {
-        synthesizeKey("VK_ESCAPE", { });
-      }
-
-      this.getID = function closeMenu_getID()
-      {
-        return "close menu " + prettyName(aID);
-      }
-    }
-
-    //gA11yEventDumpID = "eventdump";
-    //gA11yEventDumpToConsole = true;
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
 
     var gQueue = null;
-    var gContextTree = {};
-
-    // bug 527646
-    if (LINUX || SOLARIS) {
-      gContextTree = {
-        role: ROLE_MENUPOPUP,
-        children: [
-          {
-            name: "item0",
-            role: ROLE_MENUITEM,
-            children: []
-          },
-          {
-            name: "item1",
-            role: ROLE_MENUITEM,
-            children: []
-          },
-          {
-            name: "item2",
-            role: ROLE_PARENT_MENUITEM,
-            children: [
-              {
-                name: "item2.0",
-                role: ROLE_PARENT_MENUITEM,
-                children: [
-                  { 
-                    name: "item2.0.0",
-                    role: ROLE_MENUITEM,
-                    children: []
-                  }
-                ]
-              }
-            ]
-          }
-        ]
-      };
-    } else {
-      gContextTree = {
-        role: ROLE_MENUPOPUP,
-        children: [
-          {
-            name: "item0",
-            role: ROLE_MENUITEM,
-            children: []
-          },
-          {
-            name: "item1",
-            role: ROLE_MENUITEM,
-            children: []
-          },
-          {
-            name: "item2",
-            role: ROLE_PARENT_MENUITEM,
-            children: [
-              {
-                name: "item2",
-                role: ROLE_MENUPOPUP,
-                children: [
-                  {
-                    name: "item2.0",
-                    role: ROLE_PARENT_MENUITEM,
-                    children: [
-                      { 
-                        name: "item2.0",
-                        role: ROLE_MENUPOPUP,
-                        children: [
-                          { 
-                            name: "item2.0.0",
-                            role: ROLE_MENUITEM,
-                            children: []
-                          }
-                        ]
-                      }
-                    ]
-                  }
-                ]
-              }
-            ]
-          }
-        ]
-      };
-    }
-
-
-    function doTests()
+    function doTest()
     {
       gQueue = new eventQueue();
-
-      // Check initial empty tree
-      testAccessibleTree("context", { MENUPOPUP: [] });
-
-      // Open context menu and check that menu item accesibles are created.
-      gQueue.push(new openMenu("context", gContextTree));
-
-      // Select items and check focus event on them.
-      gQueue.push(new selectNextMenuItem("item0"));
-      gQueue.push(new selectNextMenuItem("item1"));
-      gQueue.push(new selectNextMenuItem("item2"));
-
-      // Open sub menu and check menu item accessibles and focus event.
-      gQueue.push(new openSubMenu("submenu2", "item2.0"));
-      gQueue.push(new openSubMenu("submenu2.0", "item2.0.0"));
-
-      // Close submenus and check that focus goes to parent.
-      gQueue.push(new closeSubMenu("submenu2.0", "item2.0"));
-      gQueue.push(new closeSubMenu("submenu2", "item2"));
-
-      gQueue.push(new closeMenu("context"));
-
+      gQueue.push(new openMenu("menu"));
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
-    addA11yLoadEvent(doTests);
+    addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
-  <body xmlns="http://www.w3.org/1999/xhtml">
-    <a target="_blank"
-       href="https://bugzilla.mozilla.org/show_bug.cgi?id=630194"
-       title="Update accessible tree when opening the menu popup">
-      Mozilla Bug 630194
-    </a>
-  <p id="display"></p>
-    <div id="content" style="display: none">
-    </div>
-    <pre id="test">
-    </pre>
-  </body>
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
+         title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
+        Mozilla Bug 249292
+      </a>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=630486"
+         title="Don't force accessible creation for popup children.">
+        Mozilla Bug 630486
+      </a>
+      <br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
 
     <vbox flex="1">
-
-      <menupopup id="context">
-        <menuitem id="item0" label="item0"/>
-        <menuitem id="item1" label="item1"/>
-        <menu id="item2" label="item2">
-          <menupopup id="submenu2">
-            <menu id="item2.0" label="item2.0">
-              <menupopup id="submenu2.0">
-                <menuitem id="item2.0.0" label="item2.0.0"/>
-              </menupopup>
-            </menu>
+      <menubar>
+        <menu id="menu" label="menu">
+          <menupopup>
+            <menuitem label="menuitem"/>
+            <menuitem label="menuitem"/>
           </menupopup>
         </menu>
-      </menupopup>
-
-      <button context="context" id="button">btn</button>
-
-      <vbox id="eventdump" role="log"/>
+      </menubar>
     </vbox>
   </hbox>
+
 </window>
+
copy from accessible/tests/mochitest/tree/test_button.xul
copy to accessible/tests/mochitest/treeupdate/test_menubutton.xul
--- a/accessible/tests/mochitest/tree/test_button.xul
+++ b/accessible/tests/mochitest/treeupdate/test_menubutton.xul
@@ -10,187 +10,168 @@
           src="chrome://mochikit/content/MochiKit/packed.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
           src="../role.js" />
+  <script type="application/javascript"
+          src="../events.js" />
 
   <script type="application/javascript">
   <![CDATA[
+
     ////////////////////////////////////////////////////////////////////////////
-    // Test
+    // Invokers
+
+    function openMenu(aButtonID)
+    {
+      this.buttonNode = getNode(aButtonID);
+      this.menupoupNode = this.buttonNode.firstChild;
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, this.menupoupNode)
+      ];
+
+      this.invoke = function openMenu_invoke()
+      {
+        var tree =
+          { PUSHBUTTON: [
+            { MENUPOPUP: [ ] }
+          ] };
+        testAccessibleTree(this.buttonNode, tree);
+
+        this.buttonNode.open = true;
+      }
+
+      this.finalCheck = function openMenu_finalCheck()
+      {
+        var tree =
+          { PUSHBUTTON: [
+            { MENUPOPUP: [
+              { MENUITEM: [ ] },
+              { MENUITEM: [ ] }
+            ] }
+          ] };
+        testAccessibleTree(this.buttonNode, tree);
+      }
+
+      this.getID = function openMenu_getID()
+      {
+        return "open menu for button " + prettyName(aButtonID);
+      }
+    }
+
+    function openMenuButton(aButtonID)
+    {
+      this.buttonNode = getNode(aButtonID);
+      this.menupoupNode = this.buttonNode.firstChild;
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_REORDER, this.menupoupNode)
+      ];
+
+      this.invoke = function openMenu_invoke()
+      {
+        var tree =
+          { PUSHBUTTON: [
+            { MENUPOPUP: [ ] },
+            { PUSHBUTTON: [ ] }
+          ] };
+        testAccessibleTree(this.buttonNode, tree);
+
+        this.buttonNode.open = true;
+      }
+
+      this.finalCheck = function openMenu_finalCheck()
+      {
+        var tree =
+          { PUSHBUTTON: [
+            { MENUPOPUP: [
+              { MENUITEM: [ ] },
+              { MENUITEM: [ ] }
+            ] },
+            { PUSHBUTTON: [ ] }
+          ] };
+        testAccessibleTree(this.buttonNode, tree);
+      }
+
+      this.getID = function openMenu_getID()
+      {
+        return "open menu for menu button " + prettyName(aButtonID);
+      }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // Do test
+
+    gA11yEventDumpToConsole = true; // debug stuff
+
+    var gQueue = null;
 
     function doTest()
     {
-      //////////////////////////////////////////////////////////////////////////
-      // button1
-
-      var accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [ ]
-      };
-      testAccessibleTree("button1", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button2
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button2", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button3
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          },
-          {
-            role: ROLE_PUSHBUTTON,
-            children: [
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button3", accTree);
+      gQueue = new eventQueue();
 
-      //////////////////////////////////////////////////////////////////////////
-      // button4
-
-      var accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [ ]
-      };
-      testAccessibleTree("button4", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button5
+      gQueue.push(new openMenu("button1"));
+      gQueue.push(new openMenuButton("button2"));
+      gQueue.push(new openMenu("button3"));
+      gQueue.push(new openMenuButton("button4"));
 
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button5", accTree);
-
-      //////////////////////////////////////////////////////////////////////////
-      // button6
-
-      accTree = {
-        role: ROLE_PUSHBUTTON,
-        name: "hello",
-        children: [
-          {
-            role: ROLE_MENUPOPUP,
-            children: [
-              {
-                role: ROLE_MENUITEM
-              },
-              {
-                role: ROLE_MENUITEM
-              }
-            ]
-          },
-          {
-            role: ROLE_PUSHBUTTON,
-            children: [
-            ]
-          }
-        ]
-      };
-      testAccessibleTree("button6", accTree);
-
-      SimpleTest.finish()
+      gQueue.invoke(); // SimpleTest.finish()
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
     <body xmlns="http://www.w3.org/1999/xhtml">
       <a target="_blank"
          href="https://bugzilla.mozilla.org/show_bug.cgi?id=249292"
          title="Ensure accessible children for toolbarbutton types 'menu' and 'menu-button'">
         Mozilla Bug 249292
-      </a><br/>
+      </a>
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=630486"
+         title="Don't force accessible creation for popup children.">
+        Mozilla Bug 630486
+      </a>
+      <br/>
       <p id="display"></p>
       <div id="content" style="display: none">
       </div>
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
-      <button id="button1" label="hello"/>
-      <button id="button2" type="menu" label="hello">
+      <button id="button1" type="menu" label="hello">
         <menupopup>
           <menuitem label="menuitem"/>
           <menuitem label="menuitem"/>
         </menupopup>
       </button>
-      <button id="button3" type="menu-button" label="hello">
+      <button id="button2" type="menu-button" label="hello">
         <menupopup>
           <menuitem label="menuitem"/>
           <menuitem label="menuitem"/>
         </menupopup>
       </button>
 
-      <toolbarbutton id="button4" label="hello"/>
-      <toolbarbutton id="button5" type="menu" label="hello">
+      <toolbarbutton id="button3" type="menu" label="hello">
         <menupopup>
           <menuitem label="menuitem"/>
           <menuitem label="menuitem"/>
         </menupopup>
       </toolbarbutton>
-      <toolbarbutton id="button6" type="menu-button" label="hello">
+      <toolbarbutton id="button4" type="menu-button" label="hello">
         <menupopup>
           <menuitem label="menuitem"/>
           <menuitem label="menuitem"/>
         </menupopup>
       </toolbarbutton>
     </vbox>
   </hbox>
 
--- a/browser/components/feeds/content/subscribe.xml
+++ b/browser/components/feeds/content/subscribe.xml
@@ -44,17 +44,17 @@
           xmlns="http://www.mozilla.org/xbl"
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <binding id="feedreaderUI">
     <content>
       <xul:vbox>
         <xul:hbox align="center">
           <xul:description anonid="subscribeUsingDescription" class="subscribeUsingDescription"/>
           <xul:menulist anonid="handlersMenuList" class="handlersMenuList" aria-labelledby="subscribeUsingDescription">
-            <xul:menupopup menugenerated="true" anonid="handlersMenuPopup" class="handlersMenuPopup">
+            <xul:menupopup anonid="handlersMenuPopup" class="handlersMenuPopup">
               <xul:menuitem anonid="liveBookmarksMenuItem" label="&feedLiveBookmarks;" class="menuitem-iconic liveBookmarksMenuItem" image="chrome://browser/skin/page-livemarks.png" selected="true"/>
               <xul:menuseparator/>
             </xul:menupopup>
           </xul:menulist>
         </xul:hbox>
         <xul:hbox>
           <xul:checkbox anonid="alwaysUse" class="alwaysUse" checked="false"/>
         </xul:hbox>
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -556,17 +556,16 @@ GK_ATOM(maxwidth, "maxwidth")
 GK_ATOM(mayscript, "mayscript")
 GK_ATOM(media, "media")
 GK_ATOM(mediaType, "media-type")
 GK_ATOM(member, "member")
 GK_ATOM(menu, "menu")
 GK_ATOM(menubar, "menubar")
 GK_ATOM(menubutton, "menubutton")
 GK_ATOM(menuButton, "menu-button")
-GK_ATOM(menugenerated, "menugenerated")
 GK_ATOM(menuitem, "menuitem")
 GK_ATOM(menulist, "menulist")
 GK_ATOM(menupopup, "menupopup")
 GK_ATOM(message, "message")
 GK_ATOM(meta, "meta")
 GK_ATOM(meter, "meter")
 GK_ATOM(method, "method")
 GK_ATOM(middle, "middle")
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -1776,27 +1776,16 @@ nsMenuPopupFrame::AttributeChanged(PRInt
         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, title);
         if (!title.IsEmpty()) {
           widget->SetTitle(title);
         }
       }
     }
   }
 
-  // accessibility needs this to ensure the frames get constructed when the
-  // menugenerated attribute is set, see bug 279703 comment 42 for discussion
-  if (aAttribute == nsGkAtoms::menugenerated &&
-      mFrames.IsEmpty() && !mGeneratedChildren) {
-    EnsureWidget();
-
-    // indicate that the children have been generated and then generate them
-    mGeneratedChildren = PR_TRUE;
-    PresContext()->PresShell()->FrameConstructor()->GenerateChildFrames(this);
-  }
-
   return rv;
 }
 
 void
 nsMenuPopupFrame::MoveToAttributePosition()
 {
   // Move the widget around when the user sets the |left| and |top| attributes. 
   // Note that this is not the best way to move the widget, as it results in lots