Bug 582719, use nsQueryFrame for menus and popups rather than GetType, r=neil
authorNeil Deakin <neil@mozilla.com>
Mon, 30 Jul 2012 20:43:28 -0400
changeset 100926 1ca7e8b00fbbea1b33ff8e5a515833faeb28044e
parent 100925 df1d8e3c45cb1e76ea97438e48128683aec01075
child 100927 de293780ba8aab62cfa995b1254b4e5601e85461
push id12750
push userneil@mozilla.com
push dateTue, 31 Jul 2012 02:45:47 +0000
treeherdermozilla-inbound@6d9745a02c2d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersneil
bugs582719
milestone17.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 582719, use nsQueryFrame for menus and popups rather than GetType, r=neil
accessible/src/xul/XULMenuAccessible.cpp
content/base/src/nsGkAtomList.h
content/xul/content/src/Makefile.in
content/xul/content/src/nsXULPopupListener.cpp
layout/base/nsPresShell.cpp
layout/xul/base/public/nsXULPopupManager.h
layout/xul/base/src/nsMenuBarFrame.cpp
layout/xul/base/src/nsMenuBarFrame.h
layout/xul/base/src/nsMenuBoxObject.cpp
layout/xul/base/src/nsMenuFrame.cpp
layout/xul/base/src/nsMenuPopupFrame.cpp
layout/xul/base/src/nsPopupBoxObject.cpp
layout/xul/base/src/nsResizerFrame.cpp
layout/xul/base/src/nsTitleBarFrame.cpp
layout/xul/base/src/nsXULPopupManager.cpp
layout/xul/base/src/nsXULTooltipListener.cpp
--- a/accessible/src/xul/XULMenuAccessible.cpp
+++ b/accessible/src/xul/XULMenuAccessible.cpp
@@ -533,17 +533,17 @@ XULMenupopupAccessible::ContainerWidget(
 
   nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(GetFrame());
   while (menuPopupFrame) {
     Accessible* menuPopup =
       document->GetAccessible(menuPopupFrame->GetContent());
     if (!menuPopup) // shouldn't be a real case
       return nullptr;
 
-    nsMenuFrame* menuFrame = menuPopupFrame->GetParentMenu();
+    nsMenuFrame* menuFrame = do_QueryFrame(menuPopupFrame->GetParent());
     if (!menuFrame) // context menu or popups
       return nullptr;
 
     nsMenuParent* menuParent = menuFrame->GetMenuParent();
     if (!menuParent) // menulist or menubutton
       return menuPopup->Parent();
 
     if (menuParent->IsMenuBar()) { // menubar menu
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1699,17 +1699,16 @@ GK_ATOM(imageBoxFrame, "ImageBoxFrame")
 GK_ATOM(imageFrame, "ImageFrame")
 GK_ATOM(imageControlFrame, "ImageControlFrame")
 GK_ATOM(inlineFrame, "InlineFrame")
 GK_ATOM(leafBoxFrame, "LeafBoxFrame")
 GK_ATOM(legendFrame, "LegendFrame")
 GK_ATOM(letterFrame, "LetterFrame")
 GK_ATOM(lineFrame, "LineFrame")
 GK_ATOM(listControlFrame,"ListControlFrame")
-GK_ATOM(menuBarFrame,"MenuBarFrame")
 GK_ATOM(menuFrame,"MenuFrame")
 GK_ATOM(menuPopupFrame,"MenuPopupFrame")
 GK_ATOM(objectFrame, "ObjectFrame")
 GK_ATOM(pageFrame, "PageFrame")
 GK_ATOM(pageBreakFrame, "PageBreakFrame")
 GK_ATOM(pageContentFrame, "PageContentFrame")
 GK_ATOM(placeholderFrame, "PlaceholderFrame")
 GK_ATOM(popupSetFrame, "PopupSetFrame")
--- a/content/xul/content/src/Makefile.in
+++ b/content/xul/content/src/Makefile.in
@@ -33,16 +33,18 @@ FORCE_STATIC_LIB = 1
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES	= \
 	-I$(srcdir)/../../document/src \
 	-I$(srcdir)/../../templates/src \
 	-I$(srcdir)/../../../xml/content/src \
 	-I$(srcdir)/../../../base/src \
 	-I$(srcdir)/../../../xml/document/src \
+	-I$(srcdir)/../../../../layout/generic \
 	-I$(srcdir)/../../../../layout/style \
+	-I$(srcdir)/../../../../layout/xul/base/src \
 	-I$(srcdir)/../../../html/content/src \
 	-I$(srcdir)/../../../events/src \
 	-I$(srcdir)/../../../xbl/src \
 	-I$(topsrcdir)/xpcom/ds \
 	$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/xul/content/src/nsXULPopupListener.cpp
+++ b/content/xul/content/src/nsXULPopupListener.cpp
@@ -38,16 +38,17 @@
 
 // for event firing in context menus
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsFocusManager.h"
 #include "nsPIDOMWindow.h"
 #include "nsIViewManager.h"
 #include "nsDOMError.h"
+#include "nsMenuFrame.h"
 
 using namespace mozilla;
 
 // on win32 and os/2, context menus come up on mouse up. On other platforms,
 // they appear on mouse down. Certain bits of code care about this difference.
 #if defined(XP_WIN) || defined(XP_OS2)
 #define NS_CONTEXT_MENU_IS_MOUSEUP 1
 #endif
@@ -382,18 +383,18 @@ nsXULPopupListener::LaunchPopup(nsIDOMEv
   if ( !popupElement || popupElement == mElement)
     return NS_OK;
 
   // Submenus can't be used as context menus or popups, bug 288763.
   // Similar code also in nsXULTooltipListener::GetTooltipFor.
   nsCOMPtr<nsIContent> popup = do_QueryInterface(popupElement);
   nsIContent* parent = popup->GetParent();
   if (parent) {
-    nsIFrame* frame = parent->GetPrimaryFrame();
-    if (frame && frame->GetType() == nsGkAtoms::menuFrame)
+    nsMenuFrame* menu = do_QueryFrame(parent->GetPrimaryFrame());
+    if (menu)
       return NS_OK;
   }
 
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (!pm)
     return NS_OK;
 
   // For left-clicks, if the popup has an position attribute, or both the
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -7687,18 +7687,19 @@ ReResolveMenusAndTrees(nsIFrame *aFrame,
   nsTreeBodyFrame *treeBody = do_QueryFrame(aFrame);
   if (treeBody)
     treeBody->ClearStyleAndImageCaches();
 
   // We deliberately don't re-resolve style on a menu's popup
   // sub-content, since doing so slows menus to a crawl.  That means we
   // have to special-case them on a skin switch, and ensure that the
   // popup frames just get destroyed completely.
-  if (aFrame && aFrame->GetType() == nsGkAtoms::menuFrame)
-    (static_cast<nsMenuFrame *>(aFrame))->CloseMenu(true);
+  nsMenuFrame* menu = do_QueryFrame(aFrame);
+  if (menu)
+    menu->CloseMenu(true);
   return true;
 }
 
 static bool
 ReframeImageBoxes(nsIFrame *aFrame, void *aClosure)
 {
   nsStyleChangeList *list = static_cast<nsStyleChangeList*>(aClosure);
   if (aFrame->GetType() == nsGkAtoms::imageBoxFrame) {
--- a/layout/xul/base/public/nsXULPopupManager.h
+++ b/layout/xul/base/public/nsXULPopupManager.h
@@ -299,23 +299,16 @@ public:
   static void Shutdown();
 
   // returns a weak reference to the popup manager instance, could return null
   // if a popup manager could not be allocated
   static nsXULPopupManager* GetInstance();
 
   void AdjustPopupsOnWindowChange(nsPIDOMWindow* aWindow);
 
-  // get the frame for a content node aContent if the frame's type
-  // matches aFrameType. Otherwise, return null. If aShouldFlush is true,
-  // then the frames are flushed before retrieving the frame.
-  nsIFrame* GetFrameOfTypeForContent(nsIContent* aContent,
-                                     nsIAtom* aFrameType,
-                                     bool aShouldFlush);
-
   // given a menu frame, find the prevous or next menu frame. If aPopup is
   // true then navigate a menupopup, from one item on the menu to the previous
   // or next one. This is used for cursor navigation between items in a popup
   // menu. If aIsPopup is false, the navigation is on a menubar, so navigate
   // between menus on the menubar. This is used for left/right cursor navigation.
   //
   // Items that are not valid, such as non-menu or non-menuitem elements are
   // skipped, and the next or previous item after that is checked.
@@ -600,19 +593,16 @@ public:
   nsresult KeyUp(nsIDOMKeyEvent* aKeyEvent);
   nsresult KeyDown(nsIDOMKeyEvent* aKeyEvent);
   nsresult KeyPress(nsIDOMKeyEvent* aKeyEvent);
 
 protected:
   nsXULPopupManager();
   ~nsXULPopupManager();
 
-  // get the nsMenuFrame, if any, for the given content node
-  nsMenuFrame* GetMenuFrameForContent(nsIContent* aContent);
-
   // get the nsMenuPopupFrame, if any, for the given content node
   nsMenuPopupFrame* GetPopupFrameForContent(nsIContent* aContent, bool aShouldFlush);
 
   // return the topmost menu, skipping over invisible popups
   nsMenuChainItem* GetTopVisibleMenu();
 
   // Hide all of the visible popups from the given list. aDeselectMenu
   // indicates whether to deselect the menu of popups when hiding; this
--- a/layout/xul/base/src/nsMenuBarFrame.cpp
+++ b/layout/xul/base/src/nsMenuBarFrame.cpp
@@ -228,18 +228,17 @@ nsMenuBarFrame::FindMenuWithShortcut(nsI
           foundMenu = currFrame;
           foundIndex = index;
         }
       }
     }
     currFrame = currFrame->GetNextSibling();
   }
   if (foundMenu) {
-    return (foundMenu->GetType() == nsGkAtoms::menuFrame) ?
-           static_cast<nsMenuFrame *>(foundMenu) : nullptr;
+    return do_QueryFrame(foundMenu);
   }
 
   // didn't find a matching menu item
 #ifdef XP_WIN
   // behavior on Windows - this item is on the menu bar, beep and deactivate the menu bar
   if (mIsActive) {
     nsCOMPtr<nsISound> soundInterface = do_CreateInstance("@mozilla.org/sound;1");
     if (soundInterface)
@@ -308,18 +307,17 @@ public:
     nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
     if (!pm)
       return NS_ERROR_UNEXPECTED;
 
     // if switching from one menu to another, set a flag so that the call to
     // HidePopup doesn't deactivate the menubar when the first menu closes.
     nsMenuBarFrame* menubar = nullptr;
     if (mOldMenu && mNewMenu) {
-      menubar = static_cast<nsMenuBarFrame *>
-        (pm->GetFrameOfTypeForContent(mMenuBar, nsGkAtoms::menuBarFrame, false));
+      menubar = do_QueryFrame(mMenuBar->GetPrimaryFrame());
       if (menubar)
         menubar->SetStayActive(true);
     }
 
     if (mOldMenu) {
       nsWeakFrame weakMenuBar(menubar);
       pm->HidePopup(mOldMenu, false, false, false);
       // clear the flag again
--- a/layout/xul/base/src/nsMenuBarFrame.h
+++ b/layout/xul/base/src/nsMenuBarFrame.h
@@ -51,18 +51,16 @@ public:
   void RemoveKeyboardNavigator();
 
   NS_IMETHOD Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
                   nsIFrame*        aPrevInFlow);
 
   virtual void DestroyFrom(nsIFrame* aDestructRoot);
 
-  virtual nsIAtom* GetType() const { return nsGkAtoms::menuBarFrame; }
-
   virtual void LockMenuUntilClosed(bool aLock) {}
   virtual bool IsMenuLocked() { return false; }
 
 // Non-interface helpers
 
   void
   SetStayActive(bool aStayActive) { mStayActive = aStayActive; }
 
--- a/layout/xul/base/src/nsMenuBoxObject.cpp
+++ b/layout/xul/base/src/nsMenuBoxObject.cpp
@@ -41,42 +41,43 @@ NS_IMETHODIMP nsMenuBoxObject::OpenMenu(
   if (pm) {
     nsIFrame* frame = GetFrame(false);
     if (frame) {
       if (aOpenFlag) {
         nsCOMPtr<nsIContent> content = mContent;
         pm->ShowMenu(content, false, false);
       }
       else {
-        if (frame->GetType() == nsGkAtoms::menuFrame) {
-          nsMenuPopupFrame* popupFrame = (static_cast<nsMenuFrame *>(frame))->GetPopup();
+        nsMenuFrame* menu = do_QueryFrame(frame);
+        if (menu) {
+          nsMenuPopupFrame* popupFrame = menu->GetPopup();
           if (popupFrame)
             pm->HidePopup(popupFrame->GetContent(), false, true, false);
         }
       }
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP nsMenuBoxObject::GetActiveChild(nsIDOMElement** aResult)
 {
   *aResult = nullptr;
-  nsIFrame* frame = GetFrame(false);
-  if (frame && frame->GetType() == nsGkAtoms::menuFrame)
-    return static_cast<nsMenuFrame *>(frame)->GetActiveChild(aResult);
+  nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
+  if (menu)
+    return menu->GetActiveChild(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsMenuBoxObject::SetActiveChild(nsIDOMElement* aResult)
 {
-  nsIFrame* frame = GetFrame(false);
-  if (frame && frame->GetType() == nsGkAtoms::menuFrame)
-    return static_cast<nsMenuFrame *>(frame)->SetActiveChild(aResult);
+  nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
+  if (menu)
+    return menu->SetActiveChild(aResult);
   return NS_OK;
 }
 
 /* boolean handleKeyPress (in nsIDOMKeyEvent keyEvent); */
 NS_IMETHODIMP nsMenuBoxObject::HandleKeyPress(nsIDOMKeyEvent* aKeyEvent, bool* aHandledFlag)
 {
   *aHandledFlag = false;
   NS_ENSURE_ARG(aKeyEvent);
@@ -93,21 +94,21 @@ NS_IMETHODIMP nsMenuBoxObject::HandleKey
   bool eventHandled = false;
   domNSEvent->GetPreventDefault(&eventHandled);
   if (eventHandled)
     return NS_OK;
 
   if (nsMenuBarListener::IsAccessKeyPressed(aKeyEvent))
     return NS_OK;
 
-  nsIFrame* frame = GetFrame(false);
-  if (!frame || frame->GetType() != nsGkAtoms::menuFrame)
+  nsMenuFrame* menu = do_QueryFrame(GetFrame(false));
+  if (!menu)
     return NS_OK;
 
-  nsMenuPopupFrame* popupFrame = static_cast<nsMenuFrame *>(frame)->GetPopup();
+  nsMenuPopupFrame* popupFrame = menu->GetPopup();
   if (!popupFrame)
     return NS_OK;
 
   PRUint32 keyCode;
   aKeyEvent->GetKeyCode(&keyCode);
   switch (keyCode) {
     case NS_VK_UP:
     case NS_VK_DOWN:
@@ -126,24 +127,25 @@ NS_IMETHODIMP nsMenuBoxObject::HandleKey
   }
 }
 
 NS_IMETHODIMP
 nsMenuBoxObject::GetOpenedWithKey(bool* aOpenedWithKey)
 {
   *aOpenedWithKey = false;
 
-  nsIFrame* frame = GetFrame(false);
-  if (!frame || frame->GetType() != nsGkAtoms::menuFrame)
+  nsMenuFrame* menuframe = do_QueryFrame(GetFrame(false));
+  if (!menuframe)
     return NS_OK;
 
-  frame = frame->GetParent();
+  nsIFrame* frame = menuframe->GetParent();
   while (frame) {
-    if (frame->GetType() == nsGkAtoms::menuBarFrame) {
-      *aOpenedWithKey = (static_cast<nsMenuBarFrame *>(frame))->IsActiveByKeyboard();
+    nsMenuBarFrame* menubar = do_QueryFrame(frame);
+    if (menubar) {
+      *aOpenedWithKey = menubar->IsActiveByKeyboard();
       return NS_OK;
     }
     frame = frame->GetParent();
   }
 
   return NS_OK;
 }
 
--- a/layout/xul/base/src/nsMenuFrame.cpp
+++ b/layout/xul/base/src/nsMenuFrame.cpp
@@ -194,46 +194,47 @@ nsMenuFrame::SetParent(nsIFrame* aParent
   nsBoxFrame::SetParent(aParent);
   InitMenuParent(aParent);
 }
 
 void
 nsMenuFrame::InitMenuParent(nsIFrame* aParent)
 {
   while (aParent) {
-    nsIAtom* type = aParent->GetType();
-    if (type == nsGkAtoms::menuPopupFrame) {
-      mMenuParent = static_cast<nsMenuPopupFrame *>(aParent);
+    nsMenuPopupFrame* popup = do_QueryFrame(aParent);
+    if (popup) {
+      mMenuParent = popup;
       break;
     }
-    else if (type == nsGkAtoms::menuBarFrame) {
-      mMenuParent = static_cast<nsMenuBarFrame *>(aParent);
+
+    nsMenuBarFrame* menubar = do_QueryFrame(aParent);
+    if (menubar) {
+      mMenuParent = menubar;
       break;
     }
+
     aParent = aParent->GetParent();
   }
 }
 
 class nsASyncMenuInitialization MOZ_FINAL : public nsIReflowCallback
 {
 public:
   nsASyncMenuInitialization(nsIFrame* aFrame)
     : mWeakFrame(aFrame)
   {
   }
 
   virtual bool ReflowFinished()
   {
     bool shouldFlush = false;
-    if (mWeakFrame.IsAlive()) {
-      if (mWeakFrame.GetFrame()->GetType() == nsGkAtoms::menuFrame) {
-        nsMenuFrame* menu = static_cast<nsMenuFrame*>(mWeakFrame.GetFrame());
-        menu->UpdateMenuType(menu->PresContext());
-        shouldFlush = true;
-      }
+    nsMenuFrame* menu = do_QueryFrame(mWeakFrame.GetFrame());
+    if (menu) {
+      menu->UpdateMenuType(menu->PresContext());
+      shouldFlush = true;
     }
     delete this;
     return shouldFlush;
   }
 
   virtual void ReflowCallbackCanceled()
   {
     delete this;
@@ -316,19 +317,19 @@ nsMenuFrame::DestroyPopupList()
   RemoveStateBits(NS_STATE_MENU_HAS_POPUP_LIST);
   delete prop;
 }
 
 void
 nsMenuFrame::SetPopupFrame(nsFrameList& aFrameList)
 {
   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
-    if (e.get()->GetType() == nsGkAtoms::menuPopupFrame) {
+    nsMenuPopupFrame* popupFrame = do_QueryFrame(e.get());
+    if (popupFrame) {
       // Remove the frame from the list and store it in a nsFrameList* property.
-      nsIFrame* popupFrame = e.get();
       aFrameList.RemoveFrame(popupFrame);
       nsFrameList* popupList = new nsFrameList(popupFrame, popupFrame);
       Properties().Set(PopupListProperty(), popupList);
       AddStateBits(NS_STATE_MENU_HAS_POPUP_LIST);
       break;
     }
   }
 }
@@ -598,26 +599,27 @@ nsMenuFrame::SelectMenu(bool aActivateFl
     // When a menu opens a submenu, the mouse will often be moved onto a
     // sibling before moving onto an item within the submenu, causing the
     // parent to become deselected. We need to ensure that the parent menu
     // is reselected when an item in the submenu is selected, so navigate up
     // from the item to its popup, and then to the popup above that.
     if (aActivateFlag) {
       nsIFrame* parent = GetParent();
       while (parent) {
-        if (parent->GetType() == nsGkAtoms::menuPopupFrame) {
+        nsMenuPopupFrame* menupopup = do_QueryFrame(parent);
+        if (menupopup) {
           // a menu is always the direct parent of a menupopup
-          parent = parent->GetParent();
-          if (parent && parent->GetType() == nsGkAtoms::menuFrame) {
+          nsMenuFrame* menu = do_QueryFrame(menupopup->GetParent());
+          if (menu) {
             // a popup however is not necessarily the direct parent of a menu
-            nsIFrame* popupParent = parent->GetParent();
+            nsIFrame* popupParent = menu->GetParent();
             while (popupParent) {
-              if (popupParent->GetType() == nsGkAtoms::menuPopupFrame) {
-                nsMenuPopupFrame* popup = static_cast<nsMenuPopupFrame *>(popupParent);
-                popup->SetCurrentMenuItem(static_cast<nsMenuFrame *>(parent));
+              menupopup = do_QueryFrame(popupParent);
+              if (menupopup) {
+                menupopup->SetCurrentMenuItem(menu);
                 break;
               }
               popupParent = popupParent->GetParent();
             }
           }
           break;
         }
         parent = parent->GetParent();
@@ -961,21 +963,20 @@ nsMenuFrame::UpdateMenuSpecialState(nsPr
 
   /* walk siblings, looking for the other checked item with the same name */
   // get the first sibling in this menu popup. This frame may be it, and if we're
   // being called at creation time, this frame isn't yet in the parent's child list.
   // All I'm saying is that this may fail, but it's most likely alright.
   nsIFrame* sib = GetParent()->GetFirstPrincipalChild();
 
   while (sib) {
-    if (sib != this && sib->GetType() == nsGkAtoms::menuFrame) {
-      nsMenuFrame* menu = static_cast<nsMenuFrame*>(sib);
-      if (menu->GetMenuType() == eMenuType_Radio &&
-          menu->IsChecked() &&
-          (menu->GetRadioGroupName() == mGroupName)) {      
+    if (sib != this) {
+      nsMenuFrame* menu = do_QueryFrame(sib);
+      if (menu && menu->GetMenuType() == eMenuType_Radio &&
+          menu->IsChecked() && menu->GetRadioGroupName() == mGroupName) {
         /* uncheck the old item */
         sib->GetContent()->UnsetAttr(kNameSpaceID_None, nsGkAtoms::checked,
                                      true);
         /* XXX in DEBUG, check to make sure that there aren't two checked items */
         return;
       }
     }
 
@@ -1421,19 +1422,19 @@ nsMenuFrame::SetActiveChild(nsIDOMElemen
   if (!aChild) {
     // Remove the current selection
     popupFrame->ChangeMenuItem(nullptr, false);
     return NS_OK;
   }
 
   nsCOMPtr<nsIContent> child(do_QueryInterface(aChild));
 
-  nsIFrame* kid = child->GetPrimaryFrame();
-  if (kid && kid->GetType() == nsGkAtoms::menuFrame)
-    popupFrame->ChangeMenuItem(static_cast<nsMenuFrame *>(kid), false);
+  nsMenuFrame* menu = do_QueryFrame(child->GetPrimaryFrame());
+  if (menu)
+    popupFrame->ChangeMenuItem(menu, false);
   return NS_OK;
 }
 
 nsIScrollableFrame* nsMenuFrame::GetScrollTargetFrame()
 {
   nsMenuPopupFrame* popupFrame = GetPopup();
   if (!popupFrame)
     return nullptr;
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -468,17 +468,17 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayou
 nsIContent*
 nsMenuPopupFrame::GetTriggerContent(nsMenuPopupFrame* aMenuPopupFrame)
 {
   while (aMenuPopupFrame) {
     if (aMenuPopupFrame->mTriggerContent)
       return aMenuPopupFrame->mTriggerContent;
 
     // check up the menu hierarchy until a popup with a trigger node is found
-    nsMenuFrame* menuFrame = aMenuPopupFrame->GetParentMenu();
+    nsMenuFrame* menuFrame = do_QueryFrame(aMenuPopupFrame->GetParent());
     if (!menuFrame)
       break;
 
     nsMenuParent* parentPopup = menuFrame->GetMenuParent();
     if (!parentPopup || !parentPopup->IsMenu())
       break;
 
     aMenuPopupFrame = static_cast<nsMenuPopupFrame *>(parentPopup);
@@ -700,17 +700,17 @@ void
 nsMenuPopupFrame::ShowPopup(bool aIsContextMenu, bool aSelectFirstItem)
 {
   mIsContextMenu = aIsContextMenu;
 
   if (mPopupState == ePopupShowing) {
     mPopupState = ePopupOpen;
     mIsOpenChanged = true;
 
-    nsMenuFrame* menuFrame = GetParentMenu();
+    nsMenuFrame* menuFrame = do_QueryFrame(GetParent());
     if (menuFrame) {
       nsWeakFrame weakFrame(this);
       menuFrame->PopupOpened();
       if (!weakFrame.IsAlive())
         return;
     }
 
     // do we need an actual reflow here?
@@ -794,17 +794,17 @@ nsMenuPopupFrame::HidePopup(bool aDesele
   NS_ASSERTION(mContent->IsElement(), "How do we have a non-element?");
   nsEventStates state = mContent->AsElement()->State();
 
   if (state.HasState(NS_EVENT_STATE_HOVER)) {
     nsEventStateManager *esm = PresContext()->EventStateManager();
     esm->SetContentState(nullptr, NS_EVENT_STATE_HOVER);
   }
 
-  nsMenuFrame* menuFrame = GetParentMenu();
+  nsMenuFrame* menuFrame = do_QueryFrame(GetParent());
   if (menuFrame) {
     menuFrame->PopupClosed(aDeselectMenu);
   }
 }
 
 void
 nsMenuPopupFrame::InvalidateInternal(const nsRect& aDamageRect,
                                      nscoord aX, nscoord aY, nsIFrame* aForChild,
@@ -1635,34 +1635,35 @@ nsMenuPopupFrame::FindMenuWithShortcut(n
           current->GetAttr(kNameSpaceID_None, nsGkAtoms::value, textKey);
       }
       else
         isShortcut = true;
 
       if (StringBeginsWith(textKey, incrementalString,
                            nsCaseInsensitiveStringComparator())) {
         // mIncrementalString is a prefix of textKey
-        if (currFrame->GetType() == nsGkAtoms::menuFrame) {
+        nsMenuFrame* menu = do_QueryFrame(currFrame);
+        if (menu) {
           // There is one match
           matchCount++;
           if (isShortcut) {
             // There is one shortcut-key match
             matchShortcutCount++;
             // Record the matched item. If there is only one matched shortcut item, do it
-            frameShortcut = static_cast<nsMenuFrame *>(currFrame);
+            frameShortcut = menu;
           }
           if (!foundActive) {
             // It's a first candidate item located before/on the current item
             if (!frameBefore)
-              frameBefore = static_cast<nsMenuFrame *>(currFrame);
+              frameBefore = menu;
           }
           else {
             // It's a first candidate item located after the current item
             if (!frameAfter)
-              frameAfter = static_cast<nsMenuFrame *>(currFrame);
+              frameAfter = menu;
           }
         }
         else
           return nullptr;
       }
 
       // Get the active status
       if (current->AttrValueIs(kNameSpaceID_None, nsGkAtoms::menuactive,
@@ -1706,19 +1707,19 @@ nsMenuPopupFrame::FindMenuWithShortcut(n
 }
 
 void
 nsMenuPopupFrame::LockMenuUntilClosed(bool aLock)
 {
   mIsMenuLocked = aLock;
 
   // Lock / unlock the parent, too.
-  nsIFrame* parent = GetParent();
-  if (parent && parent->GetType() == nsGkAtoms::menuFrame) {
-    nsMenuParent* parentParent = static_cast<nsMenuFrame*>(parent)->GetMenuParent();
+  nsMenuFrame* menu = do_QueryFrame(GetParent());
+  if (menu) {
+    nsMenuParent* parentParent = menu->GetMenuParent();
     if (parentParent) {
       parentParent->LockMenuUntilClosed(aLock);
     }
   }
 }
 
 nsIWidget*
 nsMenuPopupFrame::GetWidget()
@@ -1797,21 +1798,21 @@ nsMenuPopupFrame::MoveToAttributePositio
 
   if (NS_SUCCEEDED(err1) && NS_SUCCEEDED(err2))
     MoveTo(xpos, ypos, false);
 }
 
 void
 nsMenuPopupFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  nsIFrame* parent = GetParent();
-  if (parent && parent->GetType() == nsGkAtoms::menuFrame) {
+  nsMenuFrame* menu = do_QueryFrame(GetParent());
+  if (menu) {
     // clear the open attribute on the parent menu
     nsContentUtils::AddScriptRunner(
-      new nsUnsetAttrRunnable(parent->GetContent(), nsGkAtoms::open));
+      new nsUnsetAttrRunnable(menu->GetContent(), nsGkAtoms::open));
   }
 
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm)
     pm->PopupDestroyed(this);
 
   nsIRootBox* rootBox =
     nsIRootBox::GetRootBox(PresContext()->GetPresShell());
--- a/layout/xul/base/src/nsPopupBoxObject.cpp
+++ b/layout/xul/base/src/nsPopupBoxObject.cpp
@@ -23,23 +23,16 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIPOPUPBOXOBJECT
 
   nsPopupBoxObject() {}
 protected:
   virtual ~nsPopupBoxObject() {}
 
   nsPopupSetFrame* GetPopupSetFrame();
-  nsMenuPopupFrame* GetMenuPopupFrame()
-  {
-    nsIFrame* frame = GetFrame(false);
-    if (frame && frame->GetType() == nsGkAtoms::menuPopupFrame)
-      return static_cast<nsMenuPopupFrame*>(frame);
-    return nullptr;
-  }
 };
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsPopupBoxObject, nsBoxObject, nsIPopupBoxObject)
 
 nsPopupSetFrame*
 nsPopupBoxObject::GetPopupSetFrame()
 {
   nsIRootBox* rootBox = nsIRootBox::GetRootBox(GetPresShell(false));
@@ -110,17 +103,17 @@ nsPopupBoxObject::OpenPopupAtScreen(PRIn
   if (pm && mContent)
     pm->ShowPopupAtScreen(mContent, aXPos, aYPos, aIsContextMenu, aTriggerEvent);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPopupBoxObject::MoveTo(PRInt32 aLeft, PRInt32 aTop)
 {
-  nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
+  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (menuPopupFrame) {
     menuPopupFrame->MoveTo(aLeft, aTop, true);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -138,28 +131,28 @@ nsPopupBoxObject::SizeTo(PRInt32 aWidth,
   content->SetAttr(kNameSpaceID_None, nsGkAtoms::height, height, true);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPopupBoxObject::GetAutoPosition(bool* aShouldAutoPosition)
 {
-  nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
+  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (menuPopupFrame) {
     *aShouldAutoPosition = menuPopupFrame->GetAutoPosition();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPopupBoxObject::SetAutoPosition(bool aShouldAutoPosition)
 {
-  nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
+  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (menuPopupFrame) {
     menuPopupFrame->SetAutoPosition(aShouldAutoPosition);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -167,17 +160,17 @@ nsPopupBoxObject::EnableRollup(bool aSho
 {
   // this does nothing now
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPopupBoxObject::SetConsumeRollupEvent(PRUint32 aConsume)
 {
-  nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
+  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (menuPopupFrame) {
     menuPopupFrame->SetConsumeRollupEvent(aConsume);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -197,17 +190,17 @@ nsPopupBoxObject::EnableKeyboardNavigato
 }
 
 NS_IMETHODIMP
 nsPopupBoxObject::GetPopupState(nsAString& aState)
 {
   // set this here in case there's no frame for the popup
   aState.AssignLiteral("closed");
 
-  nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
+  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (menuPopupFrame) {
     switch (menuPopupFrame->PopupState()) {
       case ePopupShowing:
       case ePopupOpen:
         aState.AssignLiteral("showing");
         break;
       case ePopupOpenAndVisible:
         aState.AssignLiteral("open");
@@ -227,29 +220,30 @@ nsPopupBoxObject::GetPopupState(nsAStrin
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPopupBoxObject::GetTriggerNode(nsIDOMNode** aTriggerNode)
 {
   *aTriggerNode = nullptr;
 
-  nsIContent* triggerContent = nsMenuPopupFrame::GetTriggerContent(GetMenuPopupFrame());
+  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
+  nsIContent* triggerContent = nsMenuPopupFrame::GetTriggerContent(menuPopupFrame);
   if (triggerContent)
     CallQueryInterface(triggerContent, aTriggerNode);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPopupBoxObject::GetAnchorNode(nsIDOMElement** aAnchor)
 {
   *aAnchor = nullptr;
 
-  nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
+  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (!menuPopupFrame)
     return NS_OK;
 
   nsIContent* anchor = menuPopupFrame->GetAnchor();
   if (anchor)
     CallQueryInterface(anchor, aAnchor);
 
   return NS_OK;
@@ -259,17 +253,17 @@ NS_IMETHODIMP
 nsPopupBoxObject::GetOuterScreenRect(nsIDOMClientRect** aRect)
 {
   nsClientRect* rect = new nsClientRect();
   if (!rect)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aRect = rect);
 
-  nsMenuPopupFrame *menuPopupFrame = GetMenuPopupFrame();
+  nsMenuPopupFrame *menuPopupFrame = do_QueryFrame(GetFrame(false));
   if (!menuPopupFrame)
     return NS_OK;
 
   // Return an empty rectangle if the popup is not open.
   nsPopupState state = menuPopupFrame->PopupState();
   if (state != ePopupOpen && state != ePopupOpenAndVisible)
     return NS_OK;
 
--- a/layout/xul/base/src/nsResizerFrame.cpp
+++ b/layout/xul/base/src/nsResizerFrame.cpp
@@ -152,20 +152,17 @@ nsResizerFrame::HandleEvent(nsPresContex
       nsCOMPtr<nsIBaseWindow> window;
       nsIPresShell* presShell = aPresContext->GetPresShell();
       nsCOMPtr<nsIContent> contentToResize =
         GetContentToResize(presShell, getter_AddRefs(window));
 
       // check if the returned content really is a menupopup
       nsMenuPopupFrame* menuPopupFrame = nullptr;
       if (contentToResize) {
-        nsIFrame* frameToResize = contentToResize->GetPrimaryFrame();
-        if (frameToResize && frameToResize->GetType() == nsGkAtoms::menuPopupFrame) {
-          menuPopupFrame = static_cast<nsMenuPopupFrame *>(frameToResize);
-        }
+        menuPopupFrame = do_QueryFrame(contentToResize->GetPrimaryFrame());
       }
 
       // both MouseMove and direction are negative when pointing to the
       // top and left, and positive when pointing to the bottom and right
 
       // retrieve the offset of the mousemove event relative to the mousedown.
       // The difference is how much the resize needs to be
       nsIntPoint refPoint;
@@ -279,18 +276,18 @@ nsResizerFrame::HandleEvent(nsPresContex
     if (aEvent->eventStructType == NS_MOUSE_EVENT &&
         static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton)
     {
       nsCOMPtr<nsIBaseWindow> window;
       nsIPresShell* presShell = aPresContext->GetPresShell();
       nsIContent* contentToResize =
         GetContentToResize(presShell, getter_AddRefs(window));
       if (contentToResize) {
-        nsIFrame* frameToResize = contentToResize->GetPrimaryFrame();
-        if (frameToResize && frameToResize->GetType() == nsGkAtoms::menuPopupFrame)
+        nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(contentToResize->GetPrimaryFrame());
+        if (menuPopupFrame)
           break; // Don't restore original sizing for menupopup frames until
                  // we handle screen constraints here. (Bug 357725)
 
         RestoreOriginalSize(contentToResize);
       }
     }
     break;
   }
@@ -311,18 +308,19 @@ nsResizerFrame::GetContentToResize(nsIPr
 
   nsAutoString elementid;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::element, elementid);
   if (elementid.IsEmpty()) {
     // If the resizer is in a popup, resize the popup's widget, otherwise
     // resize the widget associated with the window.
     nsIFrame* popup = GetParent();
     while (popup) {
-      if (popup->GetType() == nsGkAtoms::menuPopupFrame) {
-        return popup->GetContent();
+      nsMenuPopupFrame* popupFrame = do_QueryFrame(popup);
+      if (popupFrame) {
+        return popupFrame->GetContent();
       }
       popup = popup->GetParent();
     }
 
     // don't allow resizing windows in content shells
     bool isChromeShell = false;
     nsCOMPtr<nsISupports> cont = aPresShell->GetPresContext()->GetContainer();
     nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(cont);
--- a/layout/xul/base/src/nsTitleBarFrame.cpp
+++ b/layout/xul/base/src/nsTitleBarFrame.cpp
@@ -115,18 +115,22 @@ nsTitleBarFrame::HandleEvent(nsPresConte
      break;
 
    case NS_MOUSE_MOVE: {
        if(mTrackingMouseMove)
        {
          nsIntPoint nsMoveBy = aEvent->refPoint - mLastPoint;
 
          nsIFrame* parent = GetParent();
-         while (parent && parent->GetType() != nsGkAtoms::menuPopupFrame)
+         while (parent) {
+           nsMenuPopupFrame* popupFrame = do_QueryFrame(parent);
+           if (popupFrame)
+             break;
            parent = parent->GetParent();
+         }
 
          // if the titlebar is in a popup, move the popup frame, otherwise
          // move the widget associated with the window
          if (parent) {
            nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame*>(parent);
            nsCOMPtr<nsIWidget> widget = menuPopupFrame->GetWidget();
            nsIntRect bounds;
            widget->GetScreenBounds(bounds);
--- a/layout/xul/base/src/nsXULPopupManager.cpp
+++ b/layout/xul/base/src/nsXULPopupManager.cpp
@@ -293,21 +293,21 @@ nsXULPopupManager::AdjustPopupsOnWindowC
 
     item = item->GetParent();
   }
 }
 
 static
 nsMenuPopupFrame* GetPopupToMoveOrResize(nsIFrame* aFrame)
 {
-  if (!aFrame || aFrame->GetType() != nsGkAtoms::menuPopupFrame)
+  nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(aFrame);
+  if (!menuPopupFrame)
     return nullptr;
 
   // no point moving or resizing hidden popups
-  nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame *>(aFrame);
   if (menuPopupFrame->PopupState() != ePopupOpenAndVisible)
     return nullptr;
 
   return menuPopupFrame;
 }
 
 void
 nsXULPopupManager::PopupMoved(nsIFrame* aFrame, nsIntPoint aPnt)
@@ -353,47 +353,29 @@ nsXULPopupManager::PopupResized(nsIFrame
     nsAutoString width, height;
     width.AppendInt(aSize.width);
     height.AppendInt(aSize.height);
     popup->SetAttr(kNameSpaceID_None, nsGkAtoms::width, width, false);
     popup->SetAttr(kNameSpaceID_None, nsGkAtoms::height, height, true);
   }
 }
 
-nsIFrame*
-nsXULPopupManager::GetFrameOfTypeForContent(nsIContent* aContent,
-                                            nsIAtom* aFrameType,
-                                            bool aShouldFlush)
+nsMenuPopupFrame*
+nsXULPopupManager::GetPopupFrameForContent(nsIContent* aContent, bool aShouldFlush)
 {
   if (aShouldFlush) {
     nsIDocument *document = aContent->GetCurrentDoc();
     if (document) {
       nsCOMPtr<nsIPresShell> presShell = document->GetShell();
       if (presShell)
         presShell->FlushPendingNotifications(Flush_Layout);
     }
   }
 
-  nsIFrame* frame = aContent->GetPrimaryFrame();
-  return (frame && frame->GetType() == aFrameType) ? frame : nullptr;
-}
-
-nsMenuFrame*
-nsXULPopupManager::GetMenuFrameForContent(nsIContent* aContent)
-{
-  // as ShowMenu is called from frames, don't flush to be safe.
-  return static_cast<nsMenuFrame *>
-                    (GetFrameOfTypeForContent(aContent, nsGkAtoms::menuFrame, false));
-}
-
-nsMenuPopupFrame*
-nsXULPopupManager::GetPopupFrameForContent(nsIContent* aContent, bool aShouldFlush)
-{
-  return static_cast<nsMenuPopupFrame *>
-                    (GetFrameOfTypeForContent(aContent, nsGkAtoms::menuPopupFrame, aShouldFlush));
+  return do_QueryFrame(aContent->GetPrimaryFrame());
 }
 
 nsMenuChainItem*
 nsXULPopupManager::GetTopVisibleMenu()
 {
   nsMenuChainItem* item = mPopups;
   while (item && item->Frame()->PopupState() == ePopupInvisible)
     item = item->GetParent();
@@ -516,17 +498,17 @@ nsXULPopupManager::ShowMenu(nsIContent *
           builder->CreateContents(aMenu, true);
           break;
         }
       }
       element = element->GetParent();
     } while (element);
   }
 
-  nsMenuFrame* menuFrame = GetMenuFrameForContent(aMenu);
+  nsMenuFrame* menuFrame = do_QueryFrame(aMenu->GetPrimaryFrame());
   if (!menuFrame || !menuFrame->IsMenu())
     return;
 
   nsMenuPopupFrame* popupFrame =  menuFrame->GetPopup();
   if (!popupFrame || !MayShowPopup(popupFrame))
     return;
 
   // inherit whether or not we're a context menu from the parent
@@ -697,17 +679,17 @@ nsXULPopupManager::ShowPopupCallback(nsI
   // attribute may be used to disable adding these event listeners for popups
   // that want to handle their own keyboard events.
   if (aPopup->AttrValueIs(kNameSpaceID_None, nsGkAtoms::ignorekeys,
                            nsGkAtoms::_true, eCaseMatters))
     item->SetIgnoreKeys(true);
 
   if (ismenu) {
     // if the menu is on a menubar, use the menubar's listener instead
-    nsMenuFrame* menuFrame = aPopupFrame->GetParentMenu();
+    nsMenuFrame* menuFrame = do_QueryFrame(aPopupFrame->GetParent());
     if (menuFrame) {
       item->SetOnMenuBar(menuFrame->IsOnMenuBar());
     }
   }
 
   // use a weak frame as the popup will set an open attribute if it is a menu
   nsWeakFrame weakFrame(aPopupFrame);
   aPopupFrame->ShowPopup(aIsContextMenu, aSelectFirstItem);
@@ -940,17 +922,18 @@ nsXULPopupManager::HidePopupCallback(nsI
                            foundMenu->PopupType(), aDeselectMenu);
     }
   }
 }
 
 void
 nsXULPopupManager::HidePopup(nsIFrame* aFrame)
 {
-  if (aFrame && aFrame->GetType() == nsGkAtoms::menuPopupFrame)
+  nsMenuPopupFrame* popup = do_QueryFrame(aFrame);
+  if (popup)
     HidePopup(aFrame->GetContent(), false, true, false);
 }
 
 void
 nsXULPopupManager::HidePopupAfterDelay(nsMenuPopupFrame* aPopup)
 {
   // Don't close up immediately.
   // Kick off a close timer.
@@ -1099,33 +1082,32 @@ nsXULPopupManager::ExecuteMenu(nsIConten
 
 void
 nsXULPopupManager::FirePopupShowingEvent(nsIContent* aPopup,
                                          bool aIsContextMenu,
                                          bool aSelectFirstItem)
 {
   nsCOMPtr<nsIContent> popup = aPopup; // keep a strong reference to the popup
 
-  nsIFrame* frame = aPopup->GetPrimaryFrame();
-  if (!frame || frame->GetType() != nsGkAtoms::menuPopupFrame)
+  nsMenuPopupFrame* popupFrame = do_QueryFrame(aPopup->GetPrimaryFrame());
+  if (!popupFrame)
     return;
 
-  nsMenuPopupFrame* popupFrame = static_cast<nsMenuPopupFrame *>(frame);
   nsPresContext *presContext = popupFrame->PresContext();
   nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
   nsPopupType popupType = popupFrame->PopupType();
 
   // generate the child frames if they have not already been generated
   if (!popupFrame->HasGeneratedChildren()) {
     popupFrame->SetGeneratedChildren();
     presShell->FrameConstructor()->GenerateChildFrames(popupFrame);
   }
 
   // get the frame again
-  frame = aPopup->GetPrimaryFrame();
+  nsIFrame* frame = aPopup->GetPrimaryFrame();
   if (!frame)
     return;
 
   presShell->FrameNeedsReflow(frame, nsIPresShell::eTreeChange,
                               NS_FRAME_HAS_DIRTY_CHILDREN);
 
   // cache the popup so that document.popupNode can retrieve the trigger node
   // during the popupshowing event. It will be cleared below after the event
@@ -1181,20 +1163,18 @@ nsXULPopupManager::FirePopupShowingEvent
     }
   }
 
   // clear these as they are no longer valid
   mRangeParent = nullptr;
   mRangeOffset = 0;
 
   // get the frame again in case it went away
-  frame = aPopup->GetPrimaryFrame();
-  if (frame && frame->GetType() == nsGkAtoms::menuPopupFrame) {
-    nsMenuPopupFrame* popupFrame = static_cast<nsMenuPopupFrame *>(frame);
-
+  popupFrame = do_QueryFrame(aPopup->GetPrimaryFrame());
+  if (popupFrame) {
     // if the event was cancelled, don't open the popup, reset its state back
     // to closed and clear its trigger content.
     if (status == nsEventStatus_eConsumeNoDefault) {
       popupFrame->SetPopupState(ePopupClosed);
       popupFrame->ClearTriggerContent();
     }
     else {
       ShowPopupCallback(aPopup, popupFrame, aIsContextMenu, aSelectFirstItem);
@@ -1231,20 +1211,18 @@ nsXULPopupManager::FirePopupHidingEvent(
       if (doc && currentFocus &&
           nsContentUtils::ContentIsCrossDocDescendantOf(currentFocus, aPopup)) {
         fm->ClearFocus(doc->GetWindow());
       }
     }
   }
 
   // get frame again in case it went away
-  nsIFrame* frame = aPopup->GetPrimaryFrame();
-  if (frame && frame->GetType() == nsGkAtoms::menuPopupFrame) {
-    nsMenuPopupFrame* popupFrame = static_cast<nsMenuPopupFrame *>(frame);
-
+  nsMenuPopupFrame* popupFrame = do_QueryFrame(aPopup->GetPrimaryFrame());
+  if (popupFrame) {
     // if the event was cancelled, don't hide the popup, and reset its
     // state back to open. Only popups in chrome shells can prevent a popup
     // from hiding.
     if (status == nsEventStatus_eConsumeNoDefault &&
         !popupFrame->IsInContentShell()) {
       popupFrame->SetPopupState(ePopupOpenAndVisible);
     }
     else {
@@ -1289,17 +1267,17 @@ nsXULPopupManager::IsPopupOpen(nsIConten
 
 bool
 nsXULPopupManager::IsPopupOpenForMenuParent(nsMenuParent* aMenuParent)
 {
   nsMenuChainItem* item = GetTopVisibleMenu();
   while (item) {
     nsMenuPopupFrame* popup = item->Frame();
     if (popup && popup->IsOpen()) {
-      nsMenuFrame* menuFrame = popup->GetParentMenu();
+      nsMenuFrame* menuFrame = do_QueryFrame(popup->GetParent());
       if (menuFrame && menuFrame->GetMenuParent() == aMenuParent) {
         return true;
       }
     }
     item = item->GetParent();
   }
 
   return false;
@@ -1450,17 +1428,17 @@ nsXULPopupManager::MayShowPopup(nsMenuPo
   if (mainWidget) {
     PRInt32 sizeMode;
     mainWidget->GetSizeMode(&sizeMode);
     if (sizeMode == nsSizeMode_Minimized)
       return false;
   }
 
   // cannot open a popup that is a submenu of a menupopup that isn't open.
-  nsMenuFrame* menuFrame = aPopup->GetParentMenu();
+  nsMenuFrame* menuFrame = do_QueryFrame(aPopup->GetParent());
   if (menuFrame) {
     nsMenuParent* parentPopup = menuFrame->GetMenuParent();
     if (parentPopup && !parentPopup->IsOpen())
       return false;
   }
 
   return true;
 }
@@ -1785,17 +1763,17 @@ nsXULPopupManager::HandleKeyboardNavigat
       // stop if the parent isn't a menu
       if (!nextitem->IsMenu())
         break;
 
       // check to make sure that the parent is actually the parent menu. It won't
       // be if the parent is in a different frame hierarchy, for example, for a
       // context menu opened on another menu.
       nsMenuParent* expectedParent = static_cast<nsMenuParent *>(nextitem->Frame());
-      nsMenuFrame* menuFrame = item->Frame()->GetParentMenu();
+      nsMenuFrame* menuFrame = do_QueryFrame(item->Frame()->GetParent());
       if (!menuFrame || menuFrame->GetMenuParent() != expectedParent) {
         break;
       }
     }
   }
 
   nsIFrame* itemFrame;
   if (item)
@@ -1932,30 +1910,28 @@ nsXULPopupManager::GetNextMenuItem(nsIFr
   if (aStart)
     currFrame = aStart->GetNextSibling();
   else 
     currFrame = immediateParent->GetFirstPrincipalChild();
   
   while (currFrame) {
     // See if it's a menu item.
     if (IsValidMenuItem(presContext, currFrame->GetContent(), aIsPopup)) {
-      return (currFrame->GetType() == nsGkAtoms::menuFrame) ?
-             static_cast<nsMenuFrame *>(currFrame) : nullptr;
+      return do_QueryFrame(currFrame);
     }
     currFrame = currFrame->GetNextSibling();
   }
 
   currFrame = immediateParent->GetFirstPrincipalChild();
 
   // Still don't have anything. Try cycling from the beginning.
   while (currFrame && currFrame != aStart) {
     // See if it's a menu item.
     if (IsValidMenuItem(presContext, currFrame->GetContent(), aIsPopup)) {
-      return (currFrame->GetType() == nsGkAtoms::menuFrame) ?
-             static_cast<nsMenuFrame *>(currFrame) : nullptr;
+      return do_QueryFrame(currFrame);
     }
 
     currFrame = currFrame->GetNextSibling();
   }
 
   // No luck. Just return our start value.
   return aStart;
 }
@@ -1978,30 +1954,28 @@ nsXULPopupManager::GetPreviousMenuItem(n
   if (aStart)
     currFrame = aStart->GetPrevSibling();
   else
     currFrame = frames.LastChild();
 
   while (currFrame) {
     // See if it's a menu item.
     if (IsValidMenuItem(presContext, currFrame->GetContent(), aIsPopup)) {
-      return (currFrame->GetType() == nsGkAtoms::menuFrame) ?
-             static_cast<nsMenuFrame *>(currFrame) : nullptr;
+      return do_QueryFrame(currFrame);
     }
     currFrame = currFrame->GetPrevSibling();
   }
 
   currFrame = frames.LastChild();
 
   // Still don't have anything. Try cycling from the end.
   while (currFrame && currFrame != aStart) {
     // See if it's a menu item.
     if (IsValidMenuItem(presContext, currFrame->GetContent(), aIsPopup)) {
-      return (currFrame->GetType() == nsGkAtoms::menuFrame) ?
-             static_cast<nsMenuFrame *>(currFrame) : nullptr;
+      return do_QueryFrame(currFrame);
     }
 
     currFrame = currFrame->GetPrevSibling();
   }
 
   // No luck. Just return our start value.
   return aStart;
 }
@@ -2262,37 +2236,38 @@ nsXULMenuCommandEvent::Run()
 
   // The order of the nsIViewManager and nsIPresShell COM pointers is
   // important below.  We want the pres shell to get released before the
   // associated view manager on exit from this function.
   // See bug 54233.
   // XXXndeakin is this still needed?
 
   nsCOMPtr<nsIContent> popup;
-  nsMenuFrame* menuFrame = pm->GetMenuFrameForContent(mMenu);
+  nsMenuFrame* menuFrame = do_QueryFrame(mMenu->GetPrimaryFrame());
   nsWeakFrame weakFrame(menuFrame);
   if (menuFrame && mFlipChecked) {
     if (menuFrame->IsChecked()) {
       mMenu->UnsetAttr(kNameSpaceID_None, nsGkAtoms::checked, true);
     } else {
       mMenu->SetAttr(kNameSpaceID_None, nsGkAtoms::checked,
                      NS_LITERAL_STRING("true"), true);
     }
   }
 
   if (menuFrame && weakFrame.IsAlive()) {
     // Find the popup that the menu is inside. Below, this popup will
     // need to be hidden.
-    nsIFrame* popupFrame = menuFrame->GetParent();
-    while (popupFrame) {
-      if (popupFrame->GetType() == nsGkAtoms::menuPopupFrame) {
+    nsIFrame* frame = menuFrame->GetParent();
+    while (frame) {
+      nsMenuPopupFrame* popupFrame = do_QueryFrame(frame);
+      if (popupFrame) {
         popup = popupFrame->GetContent();
         break;
       }
-      popupFrame = popupFrame->GetParent();
+      frame = frame->GetParent();
     }
 
     nsPresContext* presContext = menuFrame->PresContext();
     nsCOMPtr<nsIPresShell> shell = presContext->PresShell();
     nsCOMPtr<nsIViewManager> kungFuDeathGrip = shell->GetViewManager();
 
     // Deselect ourselves.
     if (mCloseMenuMode != CloseMenuMode_None)
--- a/layout/xul/base/src/nsXULTooltipListener.cpp
+++ b/layout/xul/base/src/nsXULTooltipListener.cpp
@@ -630,25 +630,27 @@ nsXULTooltipListener::GetTooltipFor(nsIC
 {
   *aTooltip = nullptr;
   nsCOMPtr<nsIContent> tooltip;
   nsresult rv = FindTooltip(aTarget, getter_AddRefs(tooltip));
   if (NS_FAILED(rv) || !tooltip) {
     return rv;
   }
 
+#ifdef MOZ_XUL
   // Submenus can't be used as tooltips, see bug 288763.
   nsIContent* parent = tooltip->GetParent();
   if (parent) {
-    nsIFrame* frame = parent->GetPrimaryFrame();
-    if (frame && frame->GetType() == nsGkAtoms::menuFrame) {
+    nsMenuFrame* menu = do_QueryFrame(parent->GetPrimaryFrame());
+    if (menu) {
       NS_WARNING("Menu cannot be used as a tooltip");
       return NS_ERROR_FAILURE;
     }
   }
+#endif
 
   tooltip.swap(*aTooltip);
   return rv;
 }
 
 nsresult
 nsXULTooltipListener::DestroyTooltip()
 {