Bug 508665 - part 3, Change GetContentInsertionFrame() to return a nsContainerFrame*, and return null for leaf frames. Deal with GetContentInsertionFrame() returning null in a couple of places. r=roc
authorMats Palmgren <matspal@gmail.com>
Sat, 24 May 2014 22:20:39 +0000
changeset 205135 75c14b62556ece809d3c47612b6ed2948e29a35f
parent 205134 1d60a59865d0e5a52f17c8ea626341014d0d569e
child 205136 8aa36dab27656347b615b29223d26f4294b73e83
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs508665
milestone32.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 508665 - part 3, Change GetContentInsertionFrame() to return a nsContainerFrame*, and return null for leaf frames. Deal with GetContentInsertionFrame() returning null in a couple of places. r=roc
layout/base/RestyleManager.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsCaret.cpp
layout/base/nsDocumentViewer.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/forms/nsColorControlFrame.cpp
layout/forms/nsColorControlFrame.h
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsComboboxControlFrame.h
layout/forms/nsGfxButtonControlFrame.cpp
layout/forms/nsGfxButtonControlFrame.h
layout/forms/nsHTMLButtonControlFrame.h
layout/forms/nsListControlFrame.cpp
layout/forms/nsListControlFrame.h
layout/generic/nsColumnSetFrame.h
layout/generic/nsContainerFrame.h
layout/generic/nsGfxScrollFrame.h
layout/generic/nsHTMLCanvasFrame.h
layout/generic/nsIFrame.h
layout/svg/SVGTextFrame.h
layout/svg/nsSVGForeignObjectFrame.h
layout/svg/nsSVGMarkerFrame.h
layout/svg/nsSVGOuterSVGFrame.h
layout/tables/nsTableCellFrame.h
layout/tables/nsTableOuterFrame.h
layout/xul/nsBoxFrame.cpp
layout/xul/nsBoxFrame.h
layout/xul/nsMenuBarFrame.cpp
layout/xul/nsMenuPopupFrame.cpp
layout/xul/nsXULPopupManager.cpp
layout/xul/nsXULPopupManager.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -2672,21 +2672,22 @@ ElementRestyler::RestyleUndisplayedChild
   }
 }
 
 void
 ElementRestyler::RestyleBeforePseudo()
 {
   // Make sure not to do this for pseudo-frames or frames that
   // can't have generated content.
+  nsContainerFrame* cif;
   if (!mFrame->StyleContext()->GetPseudo() &&
       ((mFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
        // Our content insertion frame might have gotten flagged
-       (mFrame->GetContentInsertionFrame()->GetStateBits() &
-        NS_FRAME_MAY_HAVE_GENERATED_CONTENT))) {
+       ((cif = mFrame->GetContentInsertionFrame()) &&
+        (cif->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT)))) {
     // Check for a new :before pseudo and an existing :before
     // frame, but only if the frame is the first continuation.
     nsIFrame* prevContinuation = mFrame->GetPrevContinuation();
     if (!prevContinuation) {
       // Checking for a :before frame is cheaper than getting the
       // :before style context.
       if (!nsLayoutUtils::GetBeforeFrame(mFrame) &&
           nsLayoutUtils::HasPseudoStyle(mFrame->GetContent(),
@@ -2706,21 +2707,22 @@ ElementRestyler::RestyleBeforePseudo()
  * aFrame is the last continuation or block-in-inline sibling that this
  * ElementRestyler is restyling.
  */
 void
 ElementRestyler::RestyleAfterPseudo(nsIFrame* aFrame)
 {
   // Make sure not to do this for pseudo-frames or frames that
   // can't have generated content.
+  nsContainerFrame* cif;
   if (!aFrame->StyleContext()->GetPseudo() &&
       ((aFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
        // Our content insertion frame might have gotten flagged
-       (aFrame->GetContentInsertionFrame()->GetStateBits() &
-        NS_FRAME_MAY_HAVE_GENERATED_CONTENT))) {
+       ((cif = aFrame->GetContentInsertionFrame()) &&
+        (cif->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT)))) {
     // Check for new :after content, but only if the frame is the
     // last continuation.
     nsIFrame* nextContinuation = aFrame->GetNextContinuation();
 
     if (!nextContinuation) {
       // Getting the :after frame is more expensive than getting the pseudo
       // context, so get the pseudo context first.
       if (nsLayoutUtils::HasPseudoStyle(aFrame->GetContent(),
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -331,17 +331,17 @@ AssertAnonymousFlexOrGridItemParent(cons
                "anonymous grid items should only exist as children "
                "of grid container frames");
   }
 }
 #else
 #define AssertAnonymousFlexOrGridItemParent(x, y) do { /* nothing */ } while(0)
 #endif
 
-static inline nsIFrame*
+static inline nsContainerFrame*
 GetFieldSetBlockFrame(nsIFrame* aFieldsetFrame)
 {
   // Depends on the fieldset child frame order - see ConstructFieldSetFrame() below.
   nsIFrame* firstChild = aFieldsetFrame->GetFirstPrincipalChild();
   nsIFrame* inner = firstChild && firstChild->GetNextSibling() ? firstChild->GetNextSibling() : firstChild;
   return inner ? inner->GetContentInsertionFrame() : nullptr;
 }
 
@@ -439,49 +439,49 @@ ReparentFrames(nsCSSFrameConstructor* aF
 // more easily.
 
 static inline bool
 IsFramePartOfIBSplit(nsIFrame* aFrame)
 {
   return (aFrame->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) != 0;
 }
 
-static nsIFrame* GetIBSplitSibling(nsIFrame* aFrame)
+static nsContainerFrame* GetIBSplitSibling(nsIFrame* aFrame)
 {
   NS_PRECONDITION(IsFramePartOfIBSplit(aFrame), "Shouldn't call this");
 
   // We only store the "ib-split sibling" annotation with the first
   // frame in the continuation chain. Walk back to find that frame now.
-  return static_cast<nsIFrame*>
+  return static_cast<nsContainerFrame*>
     (aFrame->FirstContinuation()->
        Properties().Get(nsIFrame::IBSplitSibling()));
 }
 
-static nsIFrame* GetIBSplitPrevSibling(nsIFrame* aFrame)
+static nsContainerFrame* GetIBSplitPrevSibling(nsIFrame* aFrame)
 {
   NS_PRECONDITION(IsFramePartOfIBSplit(aFrame), "Shouldn't call this");
 
   // We only store the ib-split sibling annotation with the first
   // frame in the continuation chain. Walk back to find that frame now.
-  return static_cast<nsIFrame*>
+  return static_cast<nsContainerFrame*>
     (aFrame->FirstContinuation()->
        Properties().Get(nsIFrame::IBSplitPrevSibling()));
 }
 
-static nsIFrame*
+static nsContainerFrame*
 GetLastIBSplitSibling(nsIFrame* aFrame, bool aReturnEmptyTrailingInline)
 {
   for (nsIFrame *frame = aFrame, *next; ; frame = next) {
     next = GetIBSplitSibling(frame);
     if (!next ||
         (!aReturnEmptyTrailingInline && !next->GetFirstPrincipalChild() &&
          !GetIBSplitSibling(next))) {
       NS_ASSERTION(!next || !frame->IsInlineOutside(),
                    "Should have a block here!");
-      return frame;
+      return static_cast<nsContainerFrame*>(frame);
     }
   }
   NS_NOTREACHED("unreachable code");
   return nullptr;
 }
 
 static void
 SetFrameIsIBSplit(nsIFrame* aFrame, nsIFrame* aIBSplitSibling)
@@ -586,35 +586,35 @@ FindFirstNonBlock(const nsFrameList& aLi
 inline void
 SetInitialSingleChild(nsIFrame* aParent, nsIFrame* aFrame)
 {
   NS_PRECONDITION(!aFrame->GetNextSibling(), "Should be using a frame list");
   nsFrameList temp(aFrame, aFrame);
   aParent->SetInitialChildList(kPrincipalList, temp);
 }
 
-static nsIFrame*
+static nsContainerFrame*
 GetContentInsertionFrameFor(nsIContent* aContent)
 {
   // Get the primary frame associated with the content
   nsIFrame* frame = aContent->GetPrimaryFrame();
 
   if (!frame)
     return nullptr;
 
   // If the content of the frame is not the desired content then this is not
   // really a frame for the desired content.
   // XXX This check is needed due to bug 135040. Remove it once that's fixed.
   if (frame->GetContent() != aContent) {
     return nullptr;
   }
 
-  nsIFrame* insertionFrame = frame->GetContentInsertionFrame();
-
-  NS_ASSERTION(insertionFrame == frame || !frame->IsLeaf(),
+  nsContainerFrame* insertionFrame = frame->GetContentInsertionFrame();
+
+  NS_ASSERTION(!insertionFrame || insertionFrame == frame || !frame->IsLeaf(),
     "The insertion frame is the primary frame or the primary frame isn't a leaf");
 
   return insertionFrame;
 }
 
 // -----------------------------------------------------------
 
 // Structure used when constructing formatting object trees.
@@ -3168,17 +3168,18 @@ nsCSSFrameConstructor::ConstructFieldSet
   ProcessChildren(aState, content, styleContext, blockFrame, true,
                   childItems, true, aItem.mPendingBinding);
 
   nsFrameItems fieldsetKids;
   fieldsetKids.AddChild(scrollFrame ? scrollFrame : blockFrame);
 
   for (nsFrameList::Enumerator e(childItems); !e.AtEnd(); e.Next()) {
     nsIFrame* child = e.get();
-    if (child->GetContentInsertionFrame()->GetType() == nsGkAtoms::legendFrame) {
+    nsContainerFrame* cif = child->GetContentInsertionFrame();
+    if (cif && cif->GetType() == nsGkAtoms::legendFrame) {
       // We want the legend to be the first frame in the fieldset child list.
       // That way the EventStateManager will do the right thing when tabbing
       // from a selection point within the legend (bug 236071), which is
       // used for implementing legend access keys (bug 81481).
       // GetAdjustedParentFrame() below depends on this frame order.
       childItems.RemoveFrame(child);
       // Make sure to reparent the legend so it has the fieldset as the parent.
       fieldsetKids.InsertFrame(fieldsetFrame, nullptr, child);
@@ -5760,20 +5761,20 @@ nsCSSFrameConstructor::GetFloatContainin
 }
 
 /**
  * This function will check whether aContainer has :after generated content.
  * If so, appending to it should actually insert.  The return value is the
  * parent to use for newly-appended content.  *aAfterFrame points to the :after
  * frame before which appended content should go, if there is one.
  */
-static nsIFrame*
+static nsContainerFrame*
 AdjustAppendParentForAfterContent(nsPresContext* aPresContext,
                                   nsIContent* aContainer,
-                                  nsIFrame* aParentFrame,
+                                  nsContainerFrame* aParentFrame,
                                   nsIFrame** aAfterFrame)
 {
   // See if the parent has an :after pseudo-element.  Check for the presence
   // of style first, since nsLayoutUtils::GetAfterFrame is sorta expensive.
   nsStyleContext* parentStyle = aParentFrame->StyleContext();
   if (nsLayoutUtils::HasPseudoStyle(aContainer, parentStyle,
                                     nsCSSPseudoElements::ePseudo_after,
                                     aPresContext)) {
@@ -5790,28 +5791,29 @@ AdjustAppendParentForAfterContent(nsPres
   *aAfterFrame = nullptr;
 
   if (IsFramePartOfIBSplit(aParentFrame)) {
     // We might be in a situation where the last part of the {ib} split was
     // empty.  Since we have no ::after pseudo-element, we do in fact want to be
     // appending to that last part, so advance to it if needed.  Note that here
     // aParentFrame is the result of a GetLastIBSplitSibling call, so must be
     // either the last or next to last ib-split sibling.
-    nsIFrame* trailingInline = GetIBSplitSibling(aParentFrame);
+    nsContainerFrame* trailingInline = GetIBSplitSibling(aParentFrame);
     if (trailingInline) {
       aParentFrame = trailingInline;
     }
 
     // Always make sure to look at the last continuation of the frame
     // for the {ib} case, even if that continuation is empty.  We
     // don't do this for the non-ib-split-frame case, since in the
     // other cases appending to the last nonempty continuation is fine
     // and in fact not doing that can confuse code that doesn't know
     // to pull kids from continuations other than its next one.
-    aParentFrame = aParentFrame->LastContinuation();
+    aParentFrame =
+      static_cast<nsContainerFrame*>(aParentFrame->LastContinuation());
   }
 
   return aParentFrame;
 }
 
 /**
  * This function will get the previous sibling to use for an append operation.
  * it takes a parent frame (must not be null) and its :after frame (may be
@@ -6018,17 +6020,20 @@ nsCSSFrameConstructor::IsValidSibling(ns
     }
     // Fall through; it's possible that the display type was overridden and
     // a different sort of frame was constructed, so we may need to return false
     // below.
   }
 
   if (IsFrameForFieldSet(parentFrame, parentType)) {
     // Legends can be sibling of legends but not of other content in the fieldset
-    nsIAtom* sibType = aSibling->GetContentInsertionFrame()->GetType();
+    if (nsContainerFrame* cif = aSibling->GetContentInsertionFrame()) {
+      aSibling = cif;
+    }
+    nsIAtom* sibType = aSibling->GetType();
     bool legendContent = aContent->IsHTML(nsGkAtoms::legend);
 
     if ((legendContent  && (nsGkAtoms::legendFrame != sibType)) ||
         (!legendContent && (nsGkAtoms::legendFrame == sibType)))
       return false;
   }
 
   return true;
@@ -6114,38 +6119,38 @@ nsCSSFrameConstructor::FindNextSibling(F
       return nextSibling;
     }
   }
 
   return nullptr;
 }
 
 // For fieldsets, returns the area frame, if the child is not a legend.
-static nsIFrame*
-GetAdjustedParentFrame(nsIFrame*       aParentFrame,
-                       nsIAtom*        aParentFrameType,
-                       nsIContent*     aChildContent)
+static nsContainerFrame*
+GetAdjustedParentFrame(nsContainerFrame* aParentFrame,
+                       nsIAtom*          aParentFrameType,
+                       nsIContent*       aChildContent)
 {
   NS_PRECONDITION(nsGkAtoms::tableOuterFrame != aParentFrameType,
                   "Shouldn't be happening!");
 
-  nsIFrame* newParent = nullptr;
+  nsContainerFrame* newParent = nullptr;
 
   if (nsGkAtoms::fieldSetFrame == aParentFrameType) {
     // If the parent is a fieldSet, use the fieldSet's area frame as the
     // parent unless the new content is a legend.
     if (!aChildContent->IsHTML(nsGkAtoms::legend)) {
       newParent = GetFieldSetBlockFrame(aParentFrame);
     }
   }
-  return (newParent) ? newParent : aParentFrame;
+  return newParent ? newParent : aParentFrame;
 }
 
 nsIFrame*
-nsCSSFrameConstructor::GetInsertionPrevSibling(nsIFrame*& aParentFrame,
+nsCSSFrameConstructor::GetInsertionPrevSibling(nsContainerFrame*& aParentFrame,
                                                nsIContent* aContainer,
                                                nsIContent* aChild,
                                                bool* aIsAppend,
                                                bool* aIsRangeInsertSafe,
                                                nsIContent* aStartSkipChild,
                                                nsIContent* aEndSkipChild)
 {
   *aIsAppend = false;
@@ -6499,27 +6504,27 @@ nsCSSFrameConstructor::IssueSingleInsert
       continue;
     }
     // Call ContentInserted with this node.
     ContentInserted(aContainer, child, mTempFrameTreeState,
                     aAllowLazyConstruction);
   }
 }
 
-nsIFrame*
+nsContainerFrame*
 nsCSSFrameConstructor::GetRangeInsertionPoint(nsIContent* aContainer,
                                               nsIContent* aStartChild,
                                               nsIContent* aEndChild,
                                               bool aAllowLazyConstruction)
 {
   // See if we have an XBL insertion point. If so, then that's our
   // real parent frame; if not, then the frame hasn't been built yet
   // and we just bail.
   bool multiple = false;
-  nsIFrame* insertionPoint = GetInsertionPoint(aContainer, nullptr, &multiple);
+  nsContainerFrame* insertionPoint = GetInsertionPoint(aContainer, nullptr, &multiple);
   if (!insertionPoint && !multiple)
     return nullptr; // Don't build the frames.
 
   bool hasInsertion = false;
   if (!multiple) {
     // XXXbz XBL2/sXBL issue
     nsIDocument* document = aStartChild->GetDocument();
     // XXXbz how would |document| be null here?
@@ -6640,17 +6645,17 @@ nsCSSFrameConstructor::ContentAppended(n
     nsIContent* bindingParent = aContainer->GetBindingParent();
     LAYOUT_PHASE_TEMP_EXIT();
     nsresult rv = RecreateFramesForContent(bindingParent, false);
     LAYOUT_PHASE_TEMP_REENTER();
     return rv;
   }
 
   // Get the frame associated with the content
-  nsIFrame* parentFrame = ::GetContentInsertionFrameFor(aContainer);
+  nsContainerFrame* parentFrame = ::GetContentInsertionFrameFor(aContainer);
 
   // See comment in ContentRangeInserted for why this is necessary.
   if (!parentFrame && !aContainer->IsActiveChildrenElement()) {
     return NS_OK;
   }
 
   if (aAllowLazyConstruction &&
       MaybeConstructLazily(CONTENTAPPEND, aContainer, aFirstNewContent)) {
@@ -7073,17 +7078,17 @@ nsCSSFrameConstructor::ContentRangeInser
     // the children of the host.
     nsIContent* bindingParent = aContainer->GetBindingParent();
     LAYOUT_PHASE_TEMP_EXIT();
     nsresult rv = RecreateFramesForContent(bindingParent, false);
     LAYOUT_PHASE_TEMP_REENTER();
     return rv;
   }
 
-  nsIFrame* parentFrame = ::GetContentInsertionFrameFor(aContainer);
+  nsContainerFrame* parentFrame = ::GetContentInsertionFrameFor(aContainer);
   // The xbl:children element won't have a frame, but default content can have the children as
   // a parent. While its uncommon to change the structure of the default content itself, a label,
   // for example, can be reframed by having its value attribute set or removed.
   if (!parentFrame && !aContainer->IsActiveChildrenElement()) {
     return NS_OK;
   }
 
   // Otherwise, we've got parent content. Find its frame.
@@ -7403,17 +7408,17 @@ nsCSSFrameConstructor::ContentRangeInser
   // outer table frame.
   if (captionItems.NotEmpty()) {
     NS_ASSERTION(nsGkAtoms::tableFrame == frameType ||
                  nsGkAtoms::tableOuterFrame == frameType,
                  "parent for caption is not table?");
     // We need to determine where to put the caption items; start with the
     // the parent frame that has already been determined and get the insertion
     // prevsibling of the first caption item.
-    nsIFrame* captionParent = parentFrame;
+    nsContainerFrame* captionParent = parentFrame;
     bool captionIsAppend;
     nsIFrame* captionPrevSibling = nullptr;
 
     // aIsRangeInsertSafe is ignored on purpose because it is irrelevant here.
     bool ignored;
     if (isSingleInsert) {
       captionPrevSibling =
         GetInsertionPrevSibling(captionParent, aContainer, aStartChild,
@@ -8335,17 +8340,17 @@ nsCSSFrameConstructor::ReplicateFixedFra
   // XXXbz this is a little screwed up, since the fixed frames will have
   // broken auto-positioning. Oh, well.
   NS_ASSERTION(!canvasFrame->GetFirstPrincipalChild(),
                "leaking frames; doc root continuation must be empty");
   canvasFrame->SetInitialChildList(kPrincipalList, fixedPlaceholders);
   return NS_OK;
 }
 
-nsIFrame*
+nsContainerFrame*
 nsCSSFrameConstructor::GetInsertionPoint(nsIContent*   aContainer,
                                          nsIContent*   aChildContent,
                                          bool*         aMultiple)
 {
   nsBindingManager *bindingManager = mDocument->BindingManager();
 
   nsIContent* insertionElement;
   if (aChildContent) {
@@ -8370,17 +8375,18 @@ nsCSSFrameConstructor::GetInsertionPoint
       return nullptr;
     }
   }
 
   if (!insertionElement) {
     insertionElement = aContainer;
   }
 
-  nsIFrame* insertionPoint = ::GetContentInsertionFrameFor(insertionElement);
+  nsContainerFrame* insertionPoint =
+    ::GetContentInsertionFrameFor(insertionElement);
 
   // fieldsets have multiple insertion points.  Note that we might
   // have to look at insertionElement here...
   if (aMultiple && insertionElement->IsHTML(nsGkAtoms::fieldset)) {
     *aMultiple = true;
   }
 
   return insertionPoint;
@@ -8497,17 +8503,18 @@ nsCSSFrameConstructor::MaybeRecreateCont
       printf(" is ib-split\n");
     }
 #endif
 
     *aResult = ReframeContainingBlock(aFrame);
     return true;
   }
 
-  if (aFrame->GetContentInsertionFrame()->GetType() == nsGkAtoms::legendFrame &&
+  nsContainerFrame* insertionFrame = aFrame->GetContentInsertionFrame();
+  if (insertionFrame && insertionFrame->GetType() == nsGkAtoms::legendFrame &&
       aFrame->GetParent()->GetType() == nsGkAtoms::fieldSetFrame) {
     // When we remove the legend for a fieldset, we should reframe
     // the fieldset to ensure another legend is used, if there is one
     *aResult = RecreateFramesForContent(aFrame->GetParent()->GetContent(), false);
     return true;
   }
 
   // Now check for possibly needing to reconstruct due to a pseudo parent
@@ -9306,17 +9313,18 @@ nsCSSFrameConstructor::ProcessChildren(n
                                        nsIFrame*                aFrame,
                                        const bool               aCanHaveGeneratedContent,
                                        nsFrameItems&            aFrameItems,
                                        const bool               aAllowBlockStyles,
                                        PendingBinding*          aPendingBinding,
                                        nsIFrame*                aPossiblyLeafFrame)
 {
   NS_PRECONDITION(aFrame, "Must have parent frame here");
-  NS_PRECONDITION(aFrame->GetContentInsertionFrame() == aFrame,
+  NS_PRECONDITION(!aFrame->GetContentInsertionFrame() ||
+                  aFrame->GetContentInsertionFrame() == aFrame,
                   "Parent frame in ProcessChildren should be its own "
                   "content insertion frame");
   const uint32_t kMaxDepth = 2 * MAX_REFLOW_DEPTH;
   static_assert(kMaxDepth <= UINT16_MAX, "mCurrentDepth type is too narrow");
   AutoRestore<uint16_t> savedDepth(mCurrentDepth);
   if (mCurrentDepth != UINT16_MAX) {
     ++mCurrentDepth;
   }
@@ -9607,17 +9615,17 @@ nsCSSFrameConstructor::AppendFirstLineFr
 // Special routine to handle inserting a new frame into a block
 // frame's child list. Takes care of placing the new frame into the
 // right place when first-line style is present.
 nsresult
 nsCSSFrameConstructor::InsertFirstLineFrames(
   nsFrameConstructorState& aState,
   nsIContent*              aContent,
   nsIFrame*                aBlockFrame,
-  nsIFrame**               aParentFrame,
+  nsContainerFrame**               aParentFrame,
   nsIFrame*                aPrevSibling,
   nsFrameItems&            aFrameItems)
 {
   nsresult rv = NS_OK;
   // XXXbz If you make this method actually do something, check to
   // make sure that the caller is passing what you expect.  In
   // particular, which content is aContent?  And audit the rest of
   // this code too; it makes bogus assumptions and may not build.
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -24,16 +24,17 @@
 
 struct nsFrameItems;
 struct nsAbsoluteItems;
 class nsStyleContext;
 struct nsStyleDisplay;
 class nsIDOMHTMLSelectElement;
 struct nsGenConInitializer;
 
+class nsContainerFrame;
 class nsFirstLineFrame;
 class nsICSSAnonBoxPseudo;
 class nsPageContentFrame;
 struct PendingBinding;
 class nsGenericDOMDataNode;
 
 class nsFrameConstructorState;
 class nsFrameConstructorSaveState;
@@ -106,20 +107,20 @@ private:
                                     nsIContent* aEndChild,
                                     bool aAllowLazyConstruction);
 
   // Checks if the children of aContainer in the range [aStartChild, aEndChild)
   // can be inserted/appended to one insertion point together. If so, returns
   // that insertion point. If not, returns null and issues single
   // ContentInserted calls for each child.  aEndChild = nullptr indicates that we
   // are dealing with an append.
-  nsIFrame* GetRangeInsertionPoint(nsIContent* aContainer,
-                                   nsIContent* aStartChild,
-                                   nsIContent* aEndChild,
-                                   bool aAllowLazyConstruction);
+  nsContainerFrame* GetRangeInsertionPoint(nsIContent* aContainer,
+                                           nsIContent* aStartChild,
+                                           nsIContent* aEndChild,
+                                           bool aAllowLazyConstruction);
 
   // Returns true if parent was recreated due to frameset child, false otherwise.
   bool MaybeRecreateForFrameset(nsIFrame* aParentFrame,
                                   nsIContent* aStartChild,
                                   nsIContent* aEndChild);
 
 public:
   /**
@@ -228,19 +229,19 @@ public:
                                   nsIFrame*       aFrame,
                                   nsIFrame*       aParentFrame,
                                   bool            aIsFluid = true);
 
   // Copy over fixed frames from aParentFrame's prev-in-flow
   nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
 
   // Get the XBL insertion point for a child
-  nsIFrame* GetInsertionPoint(nsIContent* aContainer,
-                              nsIContent* aChildContent,
-                              bool*       aMultiple = nullptr);
+  nsContainerFrame* GetInsertionPoint(nsIContent* aContainer,
+                                      nsIContent* aChildContent,
+                                      bool*       aMultiple = nullptr);
 
   nsresult CreateListBoxContent(nsPresContext* aPresContext,
                                 nsIFrame*       aParentFrame,
                                 nsIFrame*       aPrevFrame,
                                 nsIContent*     aChild,
                                 nsIFrame**      aResult,
                                 bool            aIsAppend,
                                 bool            aIsScrollbar,
@@ -1682,17 +1683,17 @@ private:
   void AppendFirstLineFrames(nsFrameConstructorState& aState,
                              nsIContent*              aContent,
                              nsIFrame*                aBlockFrame,
                              nsFrameItems&            aFrameItems);
 
   nsresult InsertFirstLineFrames(nsFrameConstructorState& aState,
                                  nsIContent*              aContent,
                                  nsIFrame*                aBlockFrame,
-                                 nsIFrame**               aParentFrame,
+                                 nsContainerFrame**       aParentFrame,
                                  nsIFrame*                aPrevSibling,
                                  nsFrameItems&            aFrameItems);
 
   // Find the right frame to use for aContent when looking for sibling
   // frames for aTargetContent.  If aPrevSibling is true, this
   // will look for last continuations, etc, as necessary.  This calls
   // IsValidSibling as needed; if that returns false it returns null.
   //
@@ -1723,17 +1724,17 @@ private:
   // aChild being the first child in the range. It is the callers'
   // responsibility to check whether a range insert is safe with regards to
   // fieldsets.
   // The skip parameters are used to ignore a range of children when looking
   // for a sibling. All nodes starting from aStartSkipChild and up to but not
   // including aEndSkipChild will be skipped over when looking for sibling
   // frames. Skipping a range can deal with XBL but not when there are multiple
   // insertion points.
-  nsIFrame* GetInsertionPrevSibling(nsIFrame*& aParentFrame, /* inout */
+  nsIFrame* GetInsertionPrevSibling(nsContainerFrame*& aParentFrame, /* inout */
                                     nsIContent* aContainer,
                                     nsIContent* aChild,
                                     bool* aIsAppend,
                                     bool* aIsRangeInsertSafe,
                                     nsIContent* aStartSkipChild = nullptr,
                                     nsIContent *aEndSkipChild = nullptr);
 
   // see if aContent and aSibling are legitimate siblings due to restrictions
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -296,18 +296,22 @@ nsCaret::GetGeometryForFrame(nsIFrame* a
                              nsRect*   aRect,
                              nscoord*  aBidiIndicatorSize)
 {
   nsPoint framePos(0, 0);
   nsresult rv = aFrame->GetPointFromOffset(aFrameOffset, &framePos);
   if (NS_FAILED(rv))
     return rv;
 
-  nsIFrame *frame = aFrame->GetContentInsertionFrame();
-  NS_ASSERTION(frame, "We should not be in the middle of reflow");
+  nsIFrame* frame = aFrame->GetContentInsertionFrame();
+  if (!frame) {
+    frame = aFrame;
+  }
+  NS_ASSERTION(!(frame->GetStateBits() & NS_FRAME_IN_REFLOW),
+               "We should not be in the middle of reflow");
   nscoord baseline = frame->GetCaretBaseline();
   nscoord ascent = 0, descent = 0;
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm),
     nsLayoutUtils::FontSizeInflationFor(aFrame));
   NS_ASSERTION(fm, "We should be able to get the font metrics");
   if (fm) {
     ascent = fm->MaxAscent();
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -2473,19 +2473,18 @@ nsDocumentViewer::FindContainerView()
         nsCOMPtr<nsIDocument> parentDoc = containerElement->GetCurrentDoc();
         if (parentDoc) {
           parentPresShell = parentDoc->GetShell();
         }
       }
       if (!parentPresShell) {
         NS_WARNING("Subdocument container has no presshell");
       } else {
-        nsIFrame* f = parentPresShell->GetRealPrimaryFrameFor(containerElement);
-        if (f) {
-          nsIFrame* subdocFrame = f->GetContentInsertionFrame();
+        nsIFrame* subdocFrame = parentPresShell->GetRealPrimaryFrameFor(containerElement);
+        if (subdocFrame) {
           // subdocFrame might not be a subdocument frame; the frame
           // constructor can treat a <frame> as an inline in some XBL
           // cases. Treat that as display:none, the document is not
           // displayed.
           if (subdocFrame->GetType() == nsGkAtoms::subDocumentFrame) {
             NS_ASSERTION(subdocFrame->GetView(), "Subdoc frames must have views");
             nsView* innerView =
               static_cast<nsSubDocumentFrame*>(subdocFrame)->EnsureInnerView();
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -904,26 +904,25 @@ bool
 nsLayoutUtils::GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult)
 {
   if (gfxPrefs::UseLowPrecisionBuffer()) {
     return GetDisplayPortImpl(aContent, aResult, 1.0f);
   }
   return false;
 }
 
-nsIFrame*
-nsLayoutUtils::LastContinuationWithChild(nsIFrame* aFrame)
+nsContainerFrame*
+nsLayoutUtils::LastContinuationWithChild(nsContainerFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
-  aFrame = aFrame->LastContinuation();
-  while (!aFrame->GetFirstPrincipalChild() &&
-         aFrame->GetPrevContinuation()) {
-    aFrame = aFrame->GetPrevContinuation();
-  }
-  return aFrame;
+  nsIFrame* f = aFrame->LastContinuation();
+  while (!f->GetFirstPrincipalChild() && f->GetPrevContinuation()) {
+    f = f->GetPrevContinuation();
+  }
+  return static_cast<nsContainerFrame*>(f);
 }
 
 /**
  * GetFirstChildFrame returns the first "real" child frame of a
  * given frame.  It will descend down into pseudo-frames (unless the
  * pseudo-frame is the :before generated frame).
  * @param aFrame the frame
  * @param aFrame the frame's content node
@@ -952,38 +951,39 @@ GetFirstChildFrame(nsIFrame*       aFram
 /**
  * GetLastChildFrame returns the last "real" child frame of a
  * given frame.  It will descend down into pseudo-frames (unless the
  * pseudo-frame is the :after generated frame).
  * @param aFrame the frame
  * @param aFrame the frame's content node
  */
 static nsIFrame*
-GetLastChildFrame(nsIFrame*       aFrame,
-                  nsIContent*     aContent)
+GetLastChildFrame(nsContainerFrame* aFrame,
+                  nsIContent*       aContent)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
 
   // Get the last continuation frame that's a parent
-  nsIFrame* lastParentContinuation =
+  nsContainerFrame* lastParentContinuation =
     nsLayoutUtils::LastContinuationWithChild(aFrame);
   nsIFrame* lastChildFrame =
     lastParentContinuation->GetLastChild(nsIFrame::kPrincipalList);
   if (lastChildFrame) {
     // Get the frame's first continuation. This matters in case the frame has
     // been continued across multiple lines or split by BiDi resolution.
     lastChildFrame = lastChildFrame->FirstContinuation();
 
     // If the last child frame is a pseudo-frame, then return its last child.
     // Note that the frame we create for the generated content is also a
     // pseudo-frame and so don't drill down in that case
     if (lastChildFrame &&
         lastChildFrame->IsPseudoFrame(aContent) &&
         !lastChildFrame->IsGeneratedContentFrame()) {
-      return GetLastChildFrame(lastChildFrame, aContent);
+      return GetLastChildFrame(static_cast<nsContainerFrame*>(lastChildFrame),
+                               aContent);
     }
 
     return lastChildFrame;
   }
 
   return nullptr;
 }
 
@@ -1089,35 +1089,39 @@ nsLayoutUtils::GetChildListNameFor(nsIFr
 nsIFrame*
 nsLayoutUtils::GetBeforeFrame(nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
   NS_ASSERTION(!aFrame->GetPrevContinuation(),
                "aFrame must be first continuation");
 
   nsIFrame* cif = aFrame->GetContentInsertionFrame();
+  if (!cif) {
+    return nullptr;
+  }
   nsIFrame* firstFrame = GetFirstChildFrame(cif, aFrame->GetContent());
-
   if (firstFrame && IsGeneratedContentFor(nullptr, firstFrame,
                                           nsCSSPseudoElements::before)) {
     return firstFrame;
   }
 
   return nullptr;
 }
 
 // static
 nsIFrame*
 nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "NULL frame pointer");
 
-  nsIFrame* cif = aFrame->GetContentInsertionFrame();
+  nsContainerFrame* cif = aFrame->GetContentInsertionFrame();
+  if (!cif) {
+    return nullptr;
+  }
   nsIFrame* lastFrame = GetLastChildFrame(cif, aFrame->GetContent());
-
   if (lastFrame && IsGeneratedContentFor(nullptr, lastFrame,
                                          nsCSSPseudoElements::after)) {
     return lastFrame;
   }
 
   return nullptr;
 }
 
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -40,16 +40,17 @@ class nsIDOMEvent;
 class nsRegion;
 class nsDisplayListBuilder;
 class nsDisplayItem;
 class nsFontMetrics;
 class nsFontFaceList;
 class nsIImageLoadingContent;
 class nsStyleContext;
 class nsBlockFrame;
+class nsContainerFrame;
 class gfxASurface;
 class gfxDrawable;
 class nsView;
 class nsIFrame;
 class nsStyleCoord;
 class nsStyleCorners;
 class gfxContext;
 class nsPIDOMWindow;
@@ -379,17 +380,17 @@ public:
                                        int32_t aIf1Ancestor,
                                        int32_t aIf2Ancestor,
                                        nsIFrame* aCommonAncestor);
 
   /**
    * LastContinuationWithChild gets the last continuation in aFrame's chain
    * that has a child, or the first continuation if the frame has no children.
    */
-  static nsIFrame* LastContinuationWithChild(nsIFrame* aFrame);
+  static nsContainerFrame* LastContinuationWithChild(nsContainerFrame* aFrame);
 
   /**
    * GetLastSibling simply finds the last sibling of aFrame, or returns nullptr if
    * aFrame is null.
    */
   static nsIFrame* GetLastSibling(nsIFrame* aFrame);
 
   /**
--- a/layout/forms/nsColorControlFrame.cpp
+++ b/layout/forms/nsColorControlFrame.cpp
@@ -120,17 +120,17 @@ nsColorControlFrame::AttributeChanged(in
   if (fctrl->GetType() == NS_FORM_INPUT_COLOR &&
       aNameSpaceID == kNameSpaceID_None && nsGkAtoms::value == aAttribute) {
     UpdateColor();
   }
   return nsColorControlFrameSuper::AttributeChanged(aNameSpaceID, aAttribute,
                                                     aModType);
 }
 
-nsIFrame*
+nsContainerFrame*
 nsColorControlFrame::GetContentInsertionFrame()
 {
   return this;
 }
 
 Element*
 nsColorControlFrame::GetPseudoElement(nsCSSPseudoElements::Type aType)
 {
--- a/layout/forms/nsColorControlFrame.h
+++ b/layout/forms/nsColorControlFrame.h
@@ -40,17 +40,17 @@ public:
   virtual void AppendAnonymousContentTo(nsBaseContentList& aElements,
                                         uint32_t aFilter) MOZ_OVERRIDE;
 
   // nsIFrame
   virtual nsresult AttributeChanged(int32_t  aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t  aModType) MOZ_OVERRIDE;
   virtual bool IsLeaf() const MOZ_OVERRIDE { return true; }
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
 
   virtual Element* GetPseudoElement(nsCSSPseudoElements::Type aType) MOZ_OVERRIDE;
 
   // Refresh the color swatch, using associated input's value
   nsresult UpdateColor();
 
 private:
   nsColorControlFrame(nsStyleContext* aContext);
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -1111,17 +1111,17 @@ nsComboboxControlFrame::SetFormProperty(
   nsIFormControlFrame* fcFrame = do_QueryFrame(mDropdownFrame);
   if (!fcFrame) {
     return NS_NOINTERFACE;
   }
 
   return fcFrame->SetFormProperty(aName, aValue);
 }
 
-nsIFrame*
+nsContainerFrame*
 nsComboboxControlFrame::GetContentInsertionFrame() {
   return mInRedisplayText ? mDisplayFrame : mDropdownFrame->GetContentInsertionFrame();
 }
 
 nsresult
 nsComboboxControlFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
 {
   // The frames used to display the combo box and the button used to popup the dropdown list
--- a/layout/forms/nsComboboxControlFrame.h
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -103,17 +103,17 @@ public:
   virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
 #endif
   virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
   virtual nsresult SetInitialChildList(ChildListID     aListID,
                                        nsFrameList&    aChildList) MOZ_OVERRIDE;
   virtual const nsFrameList& GetChildList(ChildListID aListID) const MOZ_OVERRIDE;
   virtual void GetChildLists(nsTArray<ChildList>* aLists) const MOZ_OVERRIDE;
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
 
   // nsIFormControlFrame
   virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE;
   /**
    * Inform the control that it got (or lost) focus.
    * If it lost focus, the dropdown menu will be rolled up if needed,
    * and FireOnChange() will be called.
    * @param aOn true if got focus, false if lost focus.
@@ -250,17 +250,17 @@ private:
   // If our total transform to the root frame of the root document is only a 2d
   // translation then return that translation, otherwise returns (0,0).
   nsPoint GetCSSTransformTranslation();
 
 protected:
   nsFrameList              mPopupFrames;             // additional named child list
   nsCOMPtr<nsIContent>     mDisplayContent;          // Anonymous content used to display the current selection
   nsCOMPtr<nsIContent>     mButtonContent;           // Anonymous content for the button
-  nsIFrame*                mDisplayFrame;            // frame to display selection
+  nsContainerFrame*        mDisplayFrame;            // frame to display selection
   nsIFrame*                mButtonFrame;             // button frame
   nsIFrame*                mDropdownFrame;           // dropdown list frame
   nsIListControlFrame *    mListControlFrame;        // ListControl Interface for the dropdown frame
 
   // The width of our display area.  Used by that frame's reflow to
   // size to the full width except the drop-marker.
   nscoord mDisplayWidth;
   
--- a/layout/forms/nsGfxButtonControlFrame.cpp
+++ b/layout/forms/nsGfxButtonControlFrame.cpp
@@ -205,17 +205,17 @@ nsGfxButtonControlFrame::AttributeChange
 }
 
 bool
 nsGfxButtonControlFrame::IsLeaf() const
 {
   return true;
 }
 
-nsIFrame*
+nsContainerFrame*
 nsGfxButtonControlFrame::GetContentInsertionFrame()
 {
   return this;
 }
 
 nsresult
 nsGfxButtonControlFrame::HandleEvent(nsPresContext* aPresContext, 
                                      WidgetGUIEvent* aEvent,
--- a/layout/forms/nsGfxButtonControlFrame.h
+++ b/layout/forms/nsGfxButtonControlFrame.h
@@ -45,17 +45,17 @@ public:
   virtual nsIFrame* CreateFrameFor(nsIContent* aContent) MOZ_OVERRIDE;
 
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) MOZ_OVERRIDE;
 
   virtual bool IsLeaf() const MOZ_OVERRIDE;
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
 
 protected:
   nsresult GetDefaultLabel(nsXPIDLString& aLabel) const;
 
   nsresult GetLabel(nsXPIDLString& aLabel);
 
   virtual bool IsInput() MOZ_OVERRIDE { return true; }
 private:
--- a/layout/forms/nsHTMLButtonControlFrame.h
+++ b/layout/forms/nsHTMLButtonControlFrame.h
@@ -75,17 +75,17 @@ public:
 
   virtual bool HonorPrintBackgroundSettings() MOZ_OVERRIDE { return false; }
 
   // nsIFormControlFrame
   void SetFocus(bool aOn, bool aRepaint) MOZ_OVERRIDE;
   virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE;
 
   // Inserted child content gets its frames parented by our child block
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     return GetFirstPrincipalChild()->GetContentInsertionFrame();
   }
 
   virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
   {
     return nsContainerFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -591,17 +591,17 @@ nsListControlFrame::GetScrollbarStyles()
 
 bool
 nsListControlFrame::ShouldPropagateComputedHeightToScrolledContent() const
 {
   return !IsInDropDownMode();
 }
 
 //---------------------------------------------------------
-nsIFrame*
+nsContainerFrame*
 nsListControlFrame::GetContentInsertionFrame() {
   return GetOptionsContainer()->GetContentInsertionFrame();
 }
 
 //---------------------------------------------------------
 bool
 nsListControlFrame::ExtendedSelection(int32_t aStartIndex,
                                       int32_t aEndIndex,
--- a/layout/forms/nsListControlFrame.h
+++ b/layout/forms/nsListControlFrame.h
@@ -81,17 +81,17 @@ public:
                          const nsHTMLReflowState*  aReflowState, 
                          nsDidReflowStatus         aStatus) MOZ_OVERRIDE;
   virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
 
   /**
    * Get the "type" of the frame
    *
    * @see nsGkAtoms::scrollFrame
    */
   virtual nsIAtom* GetType() const MOZ_OVERRIDE;
 
--- a/layout/generic/nsColumnSetFrame.h
+++ b/layout/generic/nsColumnSetFrame.h
@@ -34,17 +34,17 @@ public:
   virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE;
 
   /**
    * Retrieve the available height for content of this frame. The available content
    * height is the available height for the frame, minus borders and padding.
    */
   virtual nscoord GetAvailableContentHeight(const nsHTMLReflowState& aReflowState);
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     nsIFrame* frame = GetFirstPrincipalChild();
 
     // if no children return nullptr
     if (!frame)
       return nullptr;
 
     return frame->GetContentInsertionFrame();
   }
--- a/layout/generic/nsContainerFrame.h
+++ b/layout/generic/nsContainerFrame.h
@@ -56,16 +56,20 @@ public:
                                        nsFrameList& aChildList) MOZ_OVERRIDE;
   virtual nsresult AppendFrames(ChildListID  aListID,
                                 nsFrameList& aFrameList) MOZ_OVERRIDE;
   virtual nsresult InsertFrames(ChildListID aListID,
                                 nsIFrame* aPrevFrame,
                                 nsFrameList& aFrameList) MOZ_OVERRIDE;
   virtual nsresult RemoveFrame(ChildListID aListID,
                                nsIFrame* aOldFrame) MOZ_OVERRIDE;
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE
+  {
+    return this;
+  }
 
   virtual const nsFrameList& GetChildList(ChildListID aList) const MOZ_OVERRIDE;
   virtual void GetChildLists(nsTArray<ChildList>* aLists) const MOZ_OVERRIDE;
   virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
   virtual void ChildIsDirty(nsIFrame* aChild) MOZ_OVERRIDE;
 
   virtual bool IsLeaf() const MOZ_OVERRIDE;
   virtual FrameSearchResult PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE;
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -514,17 +514,17 @@ public:
 
   virtual nsresult RemoveFrame(ChildListID     aListID,
                                nsIFrame*       aOldFrame) MOZ_OVERRIDE;
 
   virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE {
     return this;
   }
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     return mHelper.GetScrolledFrame()->GetContentInsertionFrame();
   }
 
   virtual bool DoesClipChildren() MOZ_OVERRIDE { return true; }
   virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE;
 
   virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild) MOZ_OVERRIDE
   { nsPoint pt = aChild->GetPosition();
@@ -797,17 +797,17 @@ public:
 
   virtual nsresult RemoveFrame(ChildListID     aListID,
                                nsIFrame*       aOldFrame) MOZ_OVERRIDE;
 
   virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE {
     return this;
   }
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     return mHelper.GetScrolledFrame()->GetContentInsertionFrame();
   }
 
   virtual bool DoesClipChildren() MOZ_OVERRIDE { return true; }
   virtual nsSplittableType GetSplittableType() const MOZ_OVERRIDE;
 
   virtual nsPoint GetPositionOfChildIgnoringScrolling(nsIFrame* aChild) MOZ_OVERRIDE
   { nsPoint pt = aChild->GetPosition();
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -81,17 +81,17 @@ public:
     return nsSplittableFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced));
   }
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE;
 #endif
 
   // Inserted child content gets its frames parented by our child block
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     return GetFirstPrincipalChild()->GetContentInsertionFrame();
   }
 
 protected:
   virtual ~nsHTMLCanvasFrame();
 
   nscoord GetContinuationOffset(nscoord* aWidth = 0) const;
 
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -563,17 +563,17 @@ public:
    * Get the content object associated with this frame. Does not add a reference.
    */
   nsIContent* GetContent() const { return mContent; }
 
   /**
    * Get the frame that should be the parent for the frames of child elements
    * May return nullptr during reflow
    */
-  virtual nsIFrame* GetContentInsertionFrame() { return this; }
+  virtual nsContainerFrame* GetContentInsertionFrame() { return nullptr; }
 
   /**
    * Move any frames on our overflow list to the end of our principal list.
    * @return true if there were any overflow frames
    */
   virtual bool DrainSelfOverflowList() { return false; }
 
   /**
--- a/layout/svg/SVGTextFrame.h
+++ b/layout/svg/SVGTextFrame.h
@@ -274,17 +274,17 @@ public:
   virtual void Init(nsIContent* aContent,
                     nsIFrame*   aParent,
                     nsIFrame*   aPrevInFlow) MOZ_OVERRIDE;
 
   virtual nsresult AttributeChanged(int32_t aNamespaceID,
                                     nsIAtom* aAttribute,
                                     int32_t aModType) MOZ_OVERRIDE;
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE
   {
     return GetFirstPrincipalChild()->GetContentInsertionFrame();
   }
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists) MOZ_OVERRIDE;
 
--- a/layout/svg/nsSVGForeignObjectFrame.h
+++ b/layout/svg/nsSVGForeignObjectFrame.h
@@ -34,17 +34,17 @@ public:
   virtual void Init(nsIContent* aContent,
                     nsIFrame*   aParent,
                     nsIFrame*   aPrevInFlow) MOZ_OVERRIDE;
   virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE;
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) MOZ_OVERRIDE;
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     return GetFirstPrincipalChild()->GetContentInsertionFrame();
   }
 
   virtual void Reflow(nsPresContext*           aPresContext,
                       nsHTMLReflowMetrics&     aDesiredSize,
                       const nsHTMLReflowState& aReflowState,
                       nsReflowStatus&          aStatus) MOZ_OVERRIDE;
 
--- a/layout/svg/nsSVGMarkerFrame.h
+++ b/layout/svg/nsSVGMarkerFrame.h
@@ -74,17 +74,17 @@ public:
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE
   {
     return MakeFrameName(NS_LITERAL_STRING("SVGMarker"), aResult);
   }
 #endif
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     // Any children must be added to our single anonymous inner frame kid.
     NS_ABORT_IF_FALSE(GetFirstPrincipalChild() &&
                       GetFirstPrincipalChild()->GetType() ==
                         nsGkAtoms::svgMarkerAnonChildFrame,
                       "Where is our anonymous child?");
     return GetFirstPrincipalChild()->GetContentInsertionFrame();
   }
 
--- a/layout/svg/nsSVGOuterSVGFrame.h
+++ b/layout/svg/nsSVGOuterSVGFrame.h
@@ -83,17 +83,17 @@ public:
     return MakeFrameName(NS_LITERAL_STRING("SVGOuterSVG"), aResult);
   }
 #endif
 
   virtual nsresult  AttributeChanged(int32_t         aNameSpaceID,
                                      nsIAtom*        aAttribute,
                                      int32_t         aModType) MOZ_OVERRIDE;
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     // Any children must be added to our single anonymous inner frame kid.
     NS_ABORT_IF_FALSE(GetFirstPrincipalChild() &&
                       GetFirstPrincipalChild()->GetType() ==
                         nsGkAtoms::svgOuterSVGAnonChildFrame,
                       "Where is our anonymous child?");
     return GetFirstPrincipalChild()->GetContentInsertionFrame();
   }
 
--- a/layout/tables/nsTableCellFrame.h
+++ b/layout/tables/nsTableCellFrame.h
@@ -66,17 +66,17 @@ public:
   virtual nsresult AppendFrames(ChildListID     aListID,
                                 nsFrameList&    aFrameList) MOZ_OVERRIDE;
   virtual nsresult InsertFrames(ChildListID     aListID,
                                 nsIFrame*       aPrevFrame,
                                 nsFrameList&    aFrameList) MOZ_OVERRIDE;
   virtual nsresult RemoveFrame(ChildListID     aListID,
                                nsIFrame*       aOldFrame) MOZ_OVERRIDE;
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     return GetFirstPrincipalChild()->GetContentInsertionFrame();
   }
 
   virtual nsMargin GetUsedMargin() const MOZ_OVERRIDE;
 
   virtual void NotifyPercentHeight(const nsHTMLReflowState& aReflowState) MOZ_OVERRIDE;
 
   virtual bool NeedsToObserve(const nsHTMLReflowState& aReflowState) MOZ_OVERRIDE;
--- a/layout/tables/nsTableOuterFrame.h
+++ b/layout/tables/nsTableOuterFrame.h
@@ -81,17 +81,17 @@ public:
 
   virtual nsresult InsertFrames(ChildListID     aListID,
                                 nsIFrame*       aPrevFrame,
                                 nsFrameList&    aFrameList) MOZ_OVERRIDE;
 
   virtual nsresult RemoveFrame(ChildListID     aListID,
                                nsIFrame*       aOldFrame) MOZ_OVERRIDE;
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE {
     return GetFirstPrincipalChild()->GetContentInsertionFrame();
   }
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
 #endif
 
   virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
--- a/layout/xul/nsBoxFrame.cpp
+++ b/layout/xul/nsBoxFrame.cpp
@@ -1093,17 +1093,17 @@ nsBoxFrame::AppendFrames(ChildListID    
    if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
      PresContext()->PresShell()->
        FrameNeedsReflow(this, nsIPresShell::eTreeChange,
                         NS_FRAME_HAS_DIRTY_CHILDREN);
    }
    return NS_OK;
 }
 
-/* virtual */ nsIFrame*
+/* virtual */ nsContainerFrame*
 nsBoxFrame::GetContentInsertionFrame()
 {
   if (GetStateBits() & NS_STATE_BOX_WRAPS_KIDS_IN_BLOCK)
     return GetFirstPrincipalChild()->GetContentInsertionFrame();
   return nsContainerFrame::GetContentInsertionFrame();
 }
 
 nsresult
--- a/layout/xul/nsBoxFrame.h
+++ b/layout/xul/nsBoxFrame.h
@@ -94,17 +94,17 @@ public:
 
   virtual nsresult  InsertFrames(ChildListID     aListID,
                                  nsIFrame*       aPrevFrame,
                                  nsFrameList&    aFrameList) MOZ_OVERRIDE;
 
   virtual nsresult  RemoveFrame(ChildListID     aListID,
                                 nsIFrame*       aOldFrame) MOZ_OVERRIDE;
 
-  virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
+  virtual nsContainerFrame* GetContentInsertionFrame() MOZ_OVERRIDE;
 
   virtual nsresult  SetInitialChildList(ChildListID  aListID,
                                         nsFrameList& aChildList) MOZ_OVERRIDE;
 
   virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE;
 
   virtual nsIAtom* GetType() const MOZ_OVERRIDE;
 
--- a/layout/xul/nsMenuBarFrame.cpp
+++ b/layout/xul/nsMenuBarFrame.cpp
@@ -154,27 +154,16 @@ nsMenuBarFrame::ToggleMenuActiveState()
       // Track this item for keyboard navigation.
       mCurrentMenu = firstFrame;
     }
   }
 
   return nullptr;
 }
 
-static void
-GetInsertionPoint(nsIPresShell* aShell, nsIFrame* aFrame, nsIFrame* aChild,
-                  nsIFrame** aResult)
-{
-  nsIContent* child = nullptr;
-  if (aChild)
-    child = aChild->GetContent();
-  *aResult = aShell->FrameConstructor()->
-    GetInsertionPoint(aFrame->GetContent(), child);
-}
-
 nsMenuFrame*
 nsMenuBarFrame::FindMenuWithShortcut(nsIDOMKeyEvent* aKeyEvent)
 {
   uint32_t charCode;
   aKeyEvent->GetCharCode(&charCode);
 
   nsAutoTArray<uint32_t, 10> accessKeys;
   WidgetKeyboardEvent* nativeKeyEvent =
@@ -183,18 +172,18 @@ nsMenuBarFrame::FindMenuWithShortcut(nsI
     nsContentUtils::GetAccessKeyCandidates(nativeKeyEvent, accessKeys);
   if (accessKeys.IsEmpty() && charCode)
     accessKeys.AppendElement(charCode);
 
   if (accessKeys.IsEmpty())
     return nullptr; // no character was pressed so just return
 
   // Enumerate over our list of frames.
-  nsIFrame* immediateParent = nullptr;
-  GetInsertionPoint(PresContext()->PresShell(), this, nullptr, &immediateParent);
+  nsIFrame* immediateParent = PresContext()->PresShell()->FrameConstructor()->
+    GetInsertionPoint(GetContent(), nullptr);
   if (!immediateParent)
     immediateParent = this;
 
   // Find a most preferred accesskey which should be returned.
   nsIFrame* foundMenu = nullptr;
   size_t foundIndex = accessKeys.NoIndex;
   nsIFrame* currFrame = immediateParent->GetFirstPrincipalChild();
 
--- a/layout/xul/nsMenuPopupFrame.cpp
+++ b/layout/xul/nsMenuPopupFrame.cpp
@@ -1617,17 +1617,17 @@ nsMenuPopupFrame::FindMenuWithShortcut(n
 {
   uint32_t charCode, keyCode;
   aKeyEvent->GetCharCode(&charCode);
   aKeyEvent->GetKeyCode(&keyCode);
 
   doAction = false;
 
   // Enumerate over our list of frames.
-  nsIFrame* immediateParent = PresContext()->PresShell()->
+  nsContainerFrame* immediateParent = PresContext()->PresShell()->
     FrameConstructor()->GetInsertionPoint(GetContent(), nullptr);
   if (!immediateParent)
     immediateParent = this;
 
   uint32_t matchCount = 0, matchShortcutCount = 0;
   bool foundActive = false;
   bool isShortcut;
   nsMenuFrame* frameBefore = nullptr;
--- a/layout/xul/nsXULPopupManager.cpp
+++ b/layout/xul/nsXULPopupManager.cpp
@@ -2139,22 +2139,22 @@ nsXULPopupManager::HandleKeyboardEventWi
   if (consume) {
     aKeyEvent->StopPropagation();
     aKeyEvent->PreventDefault();
   }
   return true;
 }
 
 nsMenuFrame*
-nsXULPopupManager::GetNextMenuItem(nsIFrame* aParent,
+nsXULPopupManager::GetNextMenuItem(nsContainerFrame* aParent,
                                    nsMenuFrame* aStart,
                                    bool aIsPopup)
 {
   nsPresContext* presContext = aParent->PresContext();
-  nsIFrame* immediateParent = presContext->PresShell()->
+  nsContainerFrame* immediateParent = presContext->PresShell()->
     FrameConstructor()->GetInsertionPoint(aParent->GetContent(), nullptr);
   if (!immediateParent)
     immediateParent = aParent;
 
   nsIFrame* currFrame = nullptr;
   if (aStart)
     currFrame = aStart->GetNextSibling();
   else 
@@ -2180,22 +2180,22 @@ nsXULPopupManager::GetNextMenuItem(nsIFr
     currFrame = currFrame->GetNextSibling();
   }
 
   // No luck. Just return our start value.
   return aStart;
 }
 
 nsMenuFrame*
-nsXULPopupManager::GetPreviousMenuItem(nsIFrame* aParent,
+nsXULPopupManager::GetPreviousMenuItem(nsContainerFrame* aParent,
                                        nsMenuFrame* aStart,
                                        bool aIsPopup)
 {
   nsPresContext* presContext = aParent->PresContext();
-  nsIFrame* immediateParent = presContext->PresShell()->
+  nsContainerFrame* immediateParent = presContext->PresShell()->
     FrameConstructor()->GetInsertionPoint(aParent->GetContent(), nullptr);
   if (!immediateParent)
     immediateParent = aParent;
 
   const nsFrameList& frames(immediateParent->PrincipalChildList());
 
   nsIFrame* currFrame = nullptr;
   if (aStart)
--- a/layout/xul/nsXULPopupManager.h
+++ b/layout/xul/nsXULPopupManager.h
@@ -41,16 +41,17 @@
  * When a new popup is opened, it is appended to the popup chain, stored in a
  * linked list in mPopups for dismissable menus and panels or mNoHidePanels
  * for tooltips and panels with noautohide="true".
  * Popups are stored in this list linked from newest to oldest. When a click
  * occurs outside one of the open dismissable popups, the chain is closed by
  * calling Rollup.
  */
 
+class nsContainerFrame;
 class nsMenuFrame;
 class nsMenuPopupFrame;
 class nsMenuBarFrame;
 class nsMenuParent;
 class nsIDOMKeyEvent;
 class nsIDocShellTreeItem;
 class nsPIDOMWindow;
 
@@ -324,20 +325,20 @@ public:
   //
   // Both methods will loop around the beginning or end if needed.
   //
   // aParent - the parent menubar or menupopup
   // aStart - the menu/menuitem to start navigation from. GetPreviousMenuItem
   //          returns the item before it, while GetNextMenuItem returns the
   //          item after it.
   // aIsPopup - true for menupopups, false for menubars
-  static nsMenuFrame* GetPreviousMenuItem(nsIFrame* aParent,
+  static nsMenuFrame* GetPreviousMenuItem(nsContainerFrame* aParent,
                                           nsMenuFrame* aStart,
                                           bool aIsPopup);
-  static nsMenuFrame* GetNextMenuItem(nsIFrame* aParent,
+  static nsMenuFrame* GetNextMenuItem(nsContainerFrame* aParent,
                                       nsMenuFrame* aStart,
                                       bool aIsPopup);
 
   // returns true if the menu item aContent is a valid menuitem which may
   // be navigated to. aIsPopup should be true for items on a popup, or false
   // for items on a menubar.
   static bool IsValidMenuItem(nsPresContext* aPresContext,
                                 nsIContent* aContent,