Bug 500882 part 4. Switch content module to using the new GetPrimaryFrame API. r=smaug, sr=roc
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 24 Dec 2009 16:20:05 -0500
changeset 36655 5824db6f9c71d84c20f8207239d7c88153a4ae87
parent 36654 7bd4d3a35bd3dc2186d2107392b25a2075b747f2
child 36656 8b6f32659aa66634e8417d15952b8f2d6c9299f9
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerssmaug, roc
bugs500882
milestone1.9.3a1pre
Bug 500882 part 4. Switch content module to using the new GetPrimaryFrame API. r=smaug, sr=roc
content/base/src/nsFrameLoader.cpp
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/base/src/nsObjectLoadingContent.cpp
content/base/src/nsRange.cpp
content/events/src/nsContentEventHandler.cpp
content/events/src/nsEventStateManager.cpp
content/events/src/nsIMEStateManager.cpp
content/html/content/src/nsGenericHTMLElement.cpp
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsHTMLCanvasElement.cpp
content/html/content/src/nsHTMLMediaElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/html/document/src/nsPluginDocument.cpp
content/svg/content/src/nsSVGSVGElement.cpp
content/xbl/src/nsXBLResourceLoader.cpp
content/xbl/src/nsXBLService.cpp
content/xul/content/src/nsXULElement.cpp
content/xul/content/src/nsXULPopupListener.cpp
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -742,18 +742,18 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   // Fire pageshow events on still-loading pages, and then fire pagehide
   // events.  Note that we do NOT fire these in the normal way, but just fire
   // them on the chrome event handlers.
   FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_FALSE);
   FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_FALSE);
   FirePageHideEvent(ourTreeItem, ourChromeEventHandler);
   FirePageHideEvent(otherTreeItem, otherChromeEventHandler);
   
-  nsIFrame* ourFrame = ourShell->GetPrimaryFrameFor(ourContent);
-  nsIFrame* otherFrame = otherShell->GetPrimaryFrameFor(otherContent);
+  nsIFrame* ourFrame = ourContent->GetPrimaryFrame();
+  nsIFrame* otherFrame = otherContent->GetPrimaryFrame();
   if (!ourFrame || !otherFrame) {
     mInSwap = aOther->mInSwap = PR_FALSE;
     FirePageShowEvent(ourTreeItem, ourChromeEventHandler, PR_TRUE);
     FirePageShowEvent(otherTreeItem, otherChromeEventHandler, PR_TRUE);
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   nsIFrameFrame* ourFrameFrame = do_QueryFrame(ourFrame);
@@ -821,18 +821,18 @@ nsFrameLoader::SwapWithOtherLoader(nsFra
   if (ourInternalHistory) {
     ourInternalHistory->EvictAllContentViewers();
   }
   if (otherInternalHistory) {
     otherInternalHistory->EvictAllContentViewers();
   }
 
   // We shouldn't have changed frames, but be really careful about it
-  if (ourFrame == ourShell->GetPrimaryFrameFor(ourContent) &&
-      otherFrame == otherShell->GetPrimaryFrameFor(otherContent)) {
+  if (ourFrame == ourContent->GetPrimaryFrame() &&
+      otherFrame == otherContent->GetPrimaryFrame()) {
     ourFrameFrame->EndSwapDocShells(otherFrame);
   }
 
   ourParentDocument->FlushPendingNotifications(Flush_Layout);
   otherParentDocument->FlushPendingNotifications(Flush_Layout);
   
   FirePageShowEvent(ourTreeItem, otherChromeEventHandler, PR_TRUE);
   FirePageShowEvent(otherTreeItem, ourChromeEventHandler, PR_TRUE);
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -391,18 +391,19 @@ nsINode::GetSelectionRootContent(nsIPres
 {
   NS_ENSURE_TRUE(aPresShell, nsnull);
 
   if (IsNodeOfType(eDOCUMENT))
     return static_cast<nsIDocument*>(this)->GetRootContent();
   if (!IsNodeOfType(eCONTENT))
     return nsnull;
 
-  nsIFrame* frame =
-    aPresShell->GetPrimaryFrameFor(static_cast<nsIContent*>(this));
+  NS_ASSERTION(GetCurrentDoc() == aPresShell->GetDocument(),
+               "Wrong document somewhere");
+  nsIFrame* frame = static_cast<nsIContent*>(this)->GetPrimaryFrame();
   if (frame && frame->GetStateBits() & NS_FRAME_INDEPENDENT_SELECTION) {
     // This node should be a descendant of input/textarea editor.
     nsIContent* content = GetTextEditorRootContent();
     if (content)
       return content;
   }
 
   nsPresContext* presContext = aPresShell->GetPresContext();
@@ -3484,53 +3485,28 @@ nsGenericElement::DispatchClickEvent(nsP
   event.isControl = aSourceEvent->isControl;
   event.isAlt = aSourceEvent->isAlt;
   event.isMeta = aSourceEvent->isMeta;
 
   return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus);
 }
 
 nsIFrame*
-nsGenericElement::GetPrimaryFrame()
-{
-  nsIDocument* doc = GetCurrentDoc();
-  if (!doc) {
-    return nsnull;
-  }
-
-  return GetPrimaryFrameFor(this, doc);
-}
-
-nsIFrame*
 nsGenericElement::GetPrimaryFrame(mozFlushType aType)
 {
   nsIDocument* doc = GetCurrentDoc();
   if (!doc) {
     return nsnull;
   }
 
   // Cause a flush, so we get up-to-date frame
   // information
   doc->FlushPendingNotifications(aType);
 
-  return GetPrimaryFrameFor(this, doc);
-}
-
-/* static */
-nsIFrame*
-nsGenericElement::GetPrimaryFrameFor(nsIContent* aContent,
-                                     nsIDocument* aDocument)
-{
-  // Get presentation shell 0
-  nsIPresShell *presShell = aDocument->GetPrimaryShell();
-  if (!presShell) {
-    return nsnull;
-  }
-
-  return presShell->GetPrimaryFrameFor(aContent);
+  return GetPrimaryFrame();
 }
 
 void
 nsGenericElement::DestroyContent()
 {
   nsIDocument *document = GetOwnerDoc();
   if (document) {
     document->BindingManager()->ChangeDocumentFor(this, document, nsnull);
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -700,42 +700,25 @@ public:
    */
   static nsresult DispatchEvent(nsPresContext* aPresContext,
                                 nsEvent* aEvent,
                                 nsIContent* aTarget,
                                 PRBool aFullDispatch,
                                 nsEventStatus* aStatus);
 
   /**
-   * Get the primary frame for this content without flushing (see
-   * GetPrimaryFrameFor)
-   *
-   * @return the primary frame
-   */
-  nsIFrame* GetPrimaryFrame();
-
-  /**
-   * Get the primary frame for this content with flushing (see
-   * GetPrimaryFrameFor).
+   * Get the primary frame for this content with flushing
    *
    * @param aType the kind of flush to do, typically Flush_Frames or
    *              Flush_Layout
    * @return the primary frame
    */
   nsIFrame* GetPrimaryFrame(mozFlushType aType);
-
-  /**
-   * Get the primary frame for a piece of content without flushing.
-   *
-   * @param aContent the content to get the primary frame for
-   * @param aDocument the document for this content
-   * @return the primary frame
-   */
-  static nsIFrame* GetPrimaryFrameFor(nsIContent* aContent,
-                                      nsIDocument* aDocument);
+  // Work around silly C++ name hiding stuff
+  nsIFrame* GetPrimaryFrame() const { return nsIContent::GetPrimaryFrame(); }
 
   /**
    * Struct that stores info on an attribute.  The name and value must
    * either both be null or both be non-null.
    */
   struct nsAttrInfo {
     nsAttrInfo(const nsAttrName* aName, const nsAttrValue* aValue) :
       mName(aName), mValue(aValue) {}
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -1660,37 +1660,29 @@ nsIObjectFrame*
 nsObjectLoadingContent::GetExistingFrame(FlushType aFlushType)
 {
   nsCOMPtr<nsIContent> thisContent = 
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   NS_ASSERTION(thisContent, "must be a content");
 
   nsIFrame* frame;
   do {
-    nsIDocument* doc = thisContent->GetCurrentDoc();
-    if (!doc) {
-      return nsnull; // No current doc -> no frame
-    }
-
-    nsIPresShell* shell = doc->GetPrimaryShell();
-    if (!shell) {
-      return nsnull; // No presentation -> no frame
-    }
-
-    frame = shell->GetPrimaryFrameFor(thisContent);
+    frame = thisContent->GetPrimaryFrame();
     if (!frame) {
       return nsnull;
     }
 
     if (aFlushType == eDontFlush) {
       break;
     }
     
     // OK, let's flush out and try again.  Note that we want to reget
     // the document, etc, since flushing might run script.
+    nsIDocument* doc = thisContent->GetCurrentDoc();
+    NS_ASSERTION(doc, "Frame but no document?");
     mozFlushType flushType =
       aFlushType == eFlushLayout ? Flush_Layout : Flush_ContentAndNotify;
     doc->FlushPendingNotifications(flushType);
 
     aFlushType = eDontFlush;
   } while (1);
 
   nsIObjectFrame* objFrame = do_QueryFrame(frame);
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -2056,20 +2056,20 @@ static void ExtractRectFromOffset(nsIFra
   if (aKeepLeft) {
     aR->width = point.x - aR->x;
   } else {
     aR->width = aR->XMost() - point.x;
     aR->x = point.x;
   }
 }
 
-static nsresult GetPartialTextRect(nsLayoutUtils::RectCallback* aCallback, nsIPresShell* aPresShell, 
+static nsresult GetPartialTextRect(nsLayoutUtils::RectCallback* aCallback,
                                    nsIContent* aContent, PRInt32 aStartOffset, PRInt32 aEndOffset)
 {
-  nsIFrame* frame = aPresShell->GetPrimaryFrameFor(aContent);
+  nsIFrame* frame = aContent->GetPrimaryFrame();
   if (frame && frame->GetType() == nsGkAtoms::textFrame) {
     nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
     nsIFrame* relativeTo = nsLayoutUtils::GetContainingBlockForClientRect(textFrame);
     for (nsTextFrame* f = textFrame; f; f = static_cast<nsTextFrame*>(f->GetNextContinuation())) {
       PRInt32 fstart = f->GetContentOffset(), fend = f->GetContentEnd();
       PRBool rtl = f->GetTextRun()->IsRightToLeft();
       if (fend <= aStartOffset || fstart >= aEndOffset)
         continue;
@@ -2085,53 +2085,47 @@ static nsresult GetPartialTextRect(nsLay
         ExtractRectFromOffset(f, relativeTo, aEndOffset, &r, !rtl);
       }
       aCallback->AddRect(r);
     }
   }
   return NS_OK;
 }
 
-static nsIPresShell* GetPresShell(nsINode* aNode, PRBool aFlush)
-{
-  nsCOMPtr<nsIDocument> document = aNode->GetCurrentDoc();
-  if (!document)
-    return nsnull;
-
-  if (aFlush) {
-    document->FlushPendingNotifications(Flush_Layout);
-  }
-
-  return document->GetPrimaryShell();
-}
-
 static void CollectClientRects(nsLayoutUtils::RectCallback* aCollector, 
                                nsRange* aRange,
                                nsINode* aStartParent, PRInt32 aStartOffset,
                                nsINode* aEndParent, PRInt32 aEndOffset)
 {
+  // Hold strong pointers across the flush
   nsCOMPtr<nsIDOMNode> startContainer = do_QueryInterface(aStartParent);
   nsCOMPtr<nsIDOMNode> endContainer = do_QueryInterface(aEndParent);
 
-  nsIPresShell* presShell = GetPresShell(aStartParent, PR_TRUE);
-  if (!presShell) {
-    //not in the document
+  // Flush out layout so our frames are up to date.
+  if (!aStartParent->IsInDoc()) {
+    return;
+  }
+
+  aStartParent->GetCurrentDoc()->FlushPendingNotifications(Flush_Layout);
+
+  // Recheck whether we're still in the document
+  if (!aStartParent->IsInDoc()) {
     return;
   }
 
   RangeSubtreeIterator iter;
 
   nsresult rv = iter.Init(aRange);
   if (NS_FAILED(rv)) return;
 
   if (iter.IsDone()) {
     // the range is collapsed, only continue if the cursor is in a text node
     nsCOMPtr<nsIContent> content = do_QueryInterface(aStartParent);
     if (content->IsNodeOfType(nsINode::eTEXT)) {
-      nsIFrame* frame = presShell->GetPrimaryFrameFor(content);
+      nsIFrame* frame = content->GetPrimaryFrame();
       if (frame && frame->GetType() == nsGkAtoms::textFrame) {
         nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
         PRInt32 outOffset;
         nsIFrame* outFrame;
         textFrame->GetChildFrameContainingOffset(aStartOffset, PR_FALSE, 
           &outOffset, &outFrame);
         if (outFrame) {
            nsIFrame* relativeTo = 
@@ -2149,27 +2143,25 @@ static void CollectClientRects(nsLayoutU
   do {
     nsCOMPtr<nsIDOMNode> node(iter.GetCurrentNode());
     iter.Next();
     nsCOMPtr<nsIContent> content = do_QueryInterface(node);
     if (content->IsNodeOfType(nsINode::eTEXT)) {
        if (node == startContainer) {
          PRInt32 offset = startContainer == endContainer ? 
            aEndOffset : content->GetText()->GetLength();
-         GetPartialTextRect(aCollector, presShell, content, 
-           aStartOffset, offset);
+         GetPartialTextRect(aCollector, content, aStartOffset, offset);
          continue;
        } else if (node == endContainer) {
-         GetPartialTextRect(aCollector, presShell, content, 
-           0, aEndOffset);
+         GetPartialTextRect(aCollector, content, 0, aEndOffset);
          continue;	 
        }
     }
 
-    nsIFrame* frame = presShell->GetPrimaryFrameFor(content);
+    nsIFrame* frame = content->GetPrimaryFrame();
     if (frame) {
       nsLayoutUtils::GetAllInFlowRects(frame,
         nsLayoutUtils::GetContainingBlockForClientRect(frame), aCollector);
     }
   } while (!iter.IsDone());
 }
 
 NS_IMETHODIMP
@@ -2177,20 +2169,16 @@ nsRange::GetBoundingClientRect(nsIDOMCli
 {
   // Weak ref, since we addref it below
   nsClientRect* rect = new nsClientRect();
   if (!rect)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult = rect);
 
-  nsIPresShell* presShell = GetPresShell(mStartParent, PR_FALSE);
-  if (!presShell)
-    return NS_OK;
-
   nsLayoutUtils::RectAccumulator accumulator;
   
   CollectClientRects(&accumulator, this, mStartParent, mStartOffset, 
     mEndParent, mEndOffset);
 
   nsRect r = accumulator.mResultRect.IsEmpty() ? accumulator.mFirstRect : 
     accumulator.mResultRect;
   rect->SetLayoutRect(r);
@@ -2201,22 +2189,16 @@ NS_IMETHODIMP
 nsRange::GetClientRects(nsIDOMClientRectList** aResult)
 {
   *aResult = nsnull;
 
   nsRefPtr<nsClientRectList> rectList = new nsClientRectList();
   if (!rectList)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  nsIPresShell* presShell = GetPresShell(mStartParent, PR_FALSE);
-  if (!presShell) {
-    rectList.forget(aResult);
-    return NS_OK;
-  }
-
   nsLayoutUtils::RectListBuilder builder(rectList);
 
   CollectClientRects(&builder, this, mStartParent, mStartOffset, 
     mEndParent, mEndOffset);
 
   if (NS_FAILED(builder.mRV))
     return builder.mRV;
   rectList.forget(aResult);
--- a/content/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsContentEventHandler.cpp
@@ -489,26 +489,25 @@ static nsINode* AdjustTextRectNode(nsINo
           static_cast<nsIContent*>(node)->TextLength() : 1;
     }
   }
   return node;
 }
 
 // Similar to nsFrameSelection::GetFrameForNodeOffset,
 // but this is more flexible for OnQueryTextRect to use
-static nsresult GetFrameForTextRect(nsIPresShell* aPresShell,
-                                    nsINode* aNode,
+static nsresult GetFrameForTextRect(nsINode* aNode,
                                     PRInt32 aOffset,
                                     PRBool aHint,
                                     nsIFrame** aReturnFrame)
 {
   NS_ENSURE_TRUE(aNode && aNode->IsNodeOfType(nsINode::eCONTENT),
                  NS_ERROR_UNEXPECTED);
   nsIContent* content = static_cast<nsIContent*>(aNode);
-  nsIFrame* frame = aPresShell->GetPrimaryFrameFor(content);
+  nsIFrame* frame = content->GetPrimaryFrame();
   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
   PRInt32 childOffset = 0;
   return frame->GetChildFrameContainingOffset(aOffset, aHint, &childOffset,
                                               aReturnFrame);
 }
 
 nsresult
 nsContentEventHandler::OnQueryTextRect(nsQueryContentEvent* aEvent)
@@ -534,18 +533,17 @@ nsContentEventHandler::OnQueryTextRect(n
 
   // get the starting frame
   PRInt32 offset = range->StartOffset();
   nsINode* node = iter->GetCurrentNode();
   if (!node) {
     node = AdjustTextRectNode(range->GetStartParent(), offset);
   }
   nsIFrame* firstFrame = nsnull;
-  rv = GetFrameForTextRect(mPresShell, node, offset,
-                           PR_TRUE, &firstFrame);
+  rv = GetFrameForTextRect(node, offset, PR_TRUE, &firstFrame);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // get the starting frame rect
   nsRect rect(nsPoint(0, 0), firstFrame->GetRect().Size());
   rv = ConvertToRootViewRelativeOffset(firstFrame, rect);
   NS_ENSURE_SUCCESS(rv, rv);
   nsRect frameRect = rect;
   nsPoint ptOffset;
@@ -553,30 +551,29 @@ nsContentEventHandler::OnQueryTextRect(n
   // minus 1 to avoid creating an empty rect
   rect.x += ptOffset.x - 1;
   rect.width -= ptOffset.x - 1;
 
   // get the ending frame
   offset = range->EndOffset();
   node = AdjustTextRectNode(range->GetEndParent(), offset);
   nsIFrame* lastFrame = nsnull;
-  rv = GetFrameForTextRect(mPresShell, node, offset,
-                           range->Collapsed(), &lastFrame);
+  rv = GetFrameForTextRect(node, offset, range->Collapsed(), &lastFrame);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // iterate over all covered frames
   for (nsIFrame* frame = firstFrame; frame != lastFrame;) {
     frame = frame->GetNextContinuation();
     if (!frame) {
       do {
         iter->Next();
         node = iter->GetCurrentNode();
         if (!node || !node->IsNodeOfType(nsINode::eCONTENT))
           continue;
-        frame = mPresShell->GetPrimaryFrameFor(static_cast<nsIContent*>(node));
+        frame = static_cast<nsIContent*>(node)->GetPrimaryFrame();
       } while (!frame && !iter->IsDone());
       if (!frame) {
         // this can happen when the end offset of the range is 0.
         frame = lastFrame;
       }
     }
     frameRect.SetRect(nsPoint(0, 0), frame->GetRect().Size());
     rv = ConvertToRootViewRelativeOffset(frame, frameRect);
@@ -605,17 +602,17 @@ nsContentEventHandler::OnQueryTextRect(n
 
 nsresult
 nsContentEventHandler::OnQueryEditorRect(nsQueryContentEvent* aEvent)
 {
   nsresult rv = Init(aEvent);
   if (NS_FAILED(rv))
     return rv;
 
-  nsIFrame* frame = mPresShell->GetPrimaryFrameFor(mRootContent);
+  nsIFrame* frame = mRootContent->GetPrimaryFrame();
   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
   // get rect for first frame
   nsRect resultRect(nsPoint(0, 0), frame->GetRect().Size());
   rv = ConvertToRootViewRelativeOffset(frame, resultRect);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // account for any additional frames
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -1439,22 +1439,22 @@ nsEventStateManager::ExecuteAccessKey(ns
   nsIFrame *frame;
   PRInt32 length = mAccessKeys.Count();
   for (PRUint32 i = 0; i < aAccessCharCodes.Length(); ++i) {
     PRUint32 ch = aAccessCharCodes[i];
     nsAutoString accessKey;
     AppendUCS4ToUTF16(ch, accessKey);
     for (count = 1; count <= length; ++count) {
       content = mAccessKeys[(start + count) % length];
-      frame = mPresContext->PresShell()->GetPrimaryFrameFor(content);
+      frame = content->GetPrimaryFrame();
       if (IsAccessKeyTarget(content, frame, accessKey)) {
         PRBool shouldActivate = sKeyCausesActivation;
         while (shouldActivate && ++count <= length) {
           nsIContent *oc = mAccessKeys[(start + count) % length];
-          nsIFrame *of = mPresContext->PresShell()->GetPrimaryFrameFor(oc);
+          nsIFrame *of = oc->GetPrimaryFrame();
           if (IsAccessKeyTarget(oc, of, accessKey))
             shouldActivate = PR_FALSE;
         }
         if (shouldActivate)
           content->PerformAccesskey(shouldActivate, aIsTrustedEvent);
         else {
           nsIFocusManager* fm = nsFocusManager::GetFocusManager();
           if (fm) {
@@ -1678,103 +1678,98 @@ nsEventStateManager::FireContextClick()
   nsEventStatus status = nsEventStatus_eIgnore;
 
   // Dispatch to the DOM. We have to fake out the ESM and tell it that the
   // current target frame is actually where the mouseDown occurred, otherwise it
   // will use the frame the mouse is currently over which may or may not be
   // the same. (Note: saari and I have decided that we don't have to reset |mCurrentTarget|
   // when we're through because no one else is doing anything more with this
   // event and it will get reset on the very next event to the correct frame).
-  mCurrentTarget = nsnull;
-  nsIPresShell *shell = mPresContext->GetPresShell();
-  if ( shell ) {
-    mCurrentTarget = shell->GetPrimaryFrameFor(mGestureDownFrameOwner);
-
-    if ( mCurrentTarget ) {
-      NS_ASSERTION(mPresContext == mCurrentTarget->PresContext(),
-                   "a prescontext returned a primary frame that didn't belong to it?");
-
-      // before dispatching, check that we're not on something that
-      // doesn't get a context menu
-      nsIAtom *tag = mGestureDownContent->Tag();
-      PRBool allowedToDispatch = PR_TRUE;
-
-      if (mGestureDownContent->IsXUL()) {
-        if (tag == nsGkAtoms::scrollbar ||
-            tag == nsGkAtoms::scrollbarbutton ||
-            tag == nsGkAtoms::button)
+  mCurrentTarget = mPresContext->GetPrimaryFrameFor(mGestureDownContent);
+  if (mCurrentTarget) {
+    NS_ASSERTION(mPresContext == mCurrentTarget->PresContext(),
+                 "a prescontext returned a primary frame that didn't belong to it?");
+
+    // before dispatching, check that we're not on something that
+    // doesn't get a context menu
+    nsIAtom *tag = mGestureDownContent->Tag();
+    PRBool allowedToDispatch = PR_TRUE;
+
+    if (mGestureDownContent->IsXUL()) {
+      if (tag == nsGkAtoms::scrollbar ||
+          tag == nsGkAtoms::scrollbarbutton ||
+          tag == nsGkAtoms::button)
+        allowedToDispatch = PR_FALSE;
+      else if (tag == nsGkAtoms::toolbarbutton) {
+        // a <toolbarbutton> that has the container attribute set
+        // will already have its own dropdown.
+        if (nsContentUtils::HasNonEmptyAttr(mGestureDownContent,
+                kNameSpaceID_None, nsGkAtoms::container)) {
           allowedToDispatch = PR_FALSE;
-        else if (tag == nsGkAtoms::toolbarbutton) {
-          // a <toolbarbutton> that has the container attribute set
-          // will already have its own dropdown.
-          if (nsContentUtils::HasNonEmptyAttr(mGestureDownContent,
-                  kNameSpaceID_None, nsGkAtoms::container)) {
+        } else {
+          // If the toolbar button has an open menu, don't attempt to open
+            // a second menu
+          if (mGestureDownContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::open,
+                                               nsGkAtoms::_true, eCaseMatters)) {
             allowedToDispatch = PR_FALSE;
-          } else {
-            // If the toolbar button has an open menu, don't attempt to open
-            // a second menu
-            if (mGestureDownContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::open,
-                                                 nsGkAtoms::_true, eCaseMatters)) {
-              allowedToDispatch = PR_FALSE;
-            }
           }
         }
       }
-      else if (mGestureDownContent->IsHTML()) {
-        nsCOMPtr<nsIFormControl> formCtrl(do_QueryInterface(mGestureDownContent));
-
-        if (formCtrl) {
-          // of all form controls, only ones dealing with text are
-          // allowed to have context menus
-          PRInt32 type = formCtrl->GetType();
-
-          allowedToDispatch = (type == NS_FORM_INPUT_TEXT ||
-                               type == NS_FORM_INPUT_PASSWORD ||
-                               type == NS_FORM_INPUT_FILE ||
-                               type == NS_FORM_TEXTAREA);
-        }
-        else if (tag == nsGkAtoms::applet ||
-                 tag == nsGkAtoms::embed  ||
-                 tag == nsGkAtoms::object) {
-          allowedToDispatch = PR_FALSE;
+    }
+    else if (mGestureDownContent->IsHTML()) {
+      nsCOMPtr<nsIFormControl> formCtrl(do_QueryInterface(mGestureDownContent));
+
+      if (formCtrl) {
+        // of all form controls, only ones dealing with text are
+        // allowed to have context menus
+        PRInt32 type = formCtrl->GetType();
+
+        allowedToDispatch = (type == NS_FORM_INPUT_TEXT ||
+                             type == NS_FORM_INPUT_PASSWORD ||
+                             type == NS_FORM_INPUT_FILE ||
+                             type == NS_FORM_TEXTAREA);
+      }
+      else if (tag == nsGkAtoms::applet ||
+               tag == nsGkAtoms::embed  ||
+               tag == nsGkAtoms::object) {
+        allowedToDispatch = PR_FALSE;
+      }
+    }
+
+    if (allowedToDispatch) {
+      // make sure the widget sticks around
+      nsCOMPtr<nsIWidget> targetWidget(mCurrentTarget->GetWindow());
+      // init the event while mCurrentTarget is still good
+      nsMouseEvent event(PR_TRUE, NS_CONTEXTMENU,
+                         targetWidget,
+                         nsMouseEvent::eReal);
+      event.clickCount = 1;
+      FillInEventFromGestureDown(&event);
+        
+      // stop selection tracking, we're in control now
+      if (mCurrentTarget)
+      {
+        nsCOMPtr<nsFrameSelection> frameSel =
+          mCurrentTarget->GetFrameSelection();
+        
+        if (frameSel && frameSel->GetMouseDownState()) {
+          // note that this can cause selection changed events to fire if we're in
+          // a text field, which will null out mCurrentTarget
+          frameSel->SetMouseDownState(PR_FALSE);
         }
       }
 
-      if (allowedToDispatch) {
-        // make sure the widget sticks around
-        nsCOMPtr<nsIWidget> targetWidget(mCurrentTarget->GetWindow());
-        // init the event while mCurrentTarget is still good
-        nsMouseEvent event(PR_TRUE, NS_CONTEXTMENU,
-                           targetWidget,
-                           nsMouseEvent::eReal);
-        event.clickCount = 1;
-        FillInEventFromGestureDown(&event);
-        
-        // stop selection tracking, we're in control now
-        if (mCurrentTarget)
-        {
-          nsCOMPtr<nsFrameSelection> frameSel =
-            mCurrentTarget->GetFrameSelection();
-        
-          if (frameSel && frameSel->GetMouseDownState()) {
-            // note that this can cause selection changed events to fire if we're in
-            // a text field, which will null out mCurrentTarget
-            frameSel->SetMouseDownState(PR_FALSE);
-          }
-        }
-
-        // dispatch to DOM
-        nsEventDispatcher::Dispatch(mGestureDownContent, mPresContext, &event,
-                                    nsnull, &status);
-
-        // We don't need to dispatch to frame handling because no frames
-        // watch NS_CONTEXTMENU except for nsMenuFrame and that's only for
-        // dismissal. That's just as well since we don't really know
-        // which frame to send it to.
-      }
+      // dispatch to DOM
+      nsEventDispatcher::Dispatch(mGestureDownContent, mPresContext, &event,
+                                  nsnull, &status);
+
+      // We don't need to dispatch to frame handling because no frames
+      // watch NS_CONTEXTMENU except for nsMenuFrame and that's only for
+      // dismissal. That's just as well since we don't really know
+      // which frame to send it to.
     }
   }
 
   // now check if the event has been handled. If so, stop tracking a drag
   if ( status == nsEventStatus_eConsumeNoDefault ) {
     StopTrackingDragGesture();
   }
 
@@ -1869,17 +1864,17 @@ nsEventStateManager::FillInEventFromGest
 // Do we need to do anything about this? Let's wait and see.
 //
 void
 nsEventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
                                          nsMouseEvent *aEvent)
 {
   NS_ASSERTION(aPresContext, "This shouldn't happen.");
   if ( IsTrackingDragGesture() ) {
-    mCurrentTarget = aPresContext->GetPresShell()->GetPrimaryFrameFor(mGestureDownFrameOwner);
+    mCurrentTarget = mGestureDownFrameOwner->GetPrimaryFrame();
 
     if (!mCurrentTarget) {
       StopTrackingDragGesture();
       return;
     }
 
     // Check if selection is tracking drag gestures, if so
     // don't interfere!
@@ -2211,26 +2206,19 @@ nsEventStateManager::DoDefaultDragStart(
     // tree to ensure that the drag feedback gets clipped to those
     // rows. For other content, region should be null.
     nsCOMPtr<nsIScriptableRegion> region;
 #ifdef MOZ_XUL
     if (dragTarget && !dragImage) {
       nsCOMPtr<nsIContent> content = do_QueryInterface(dragTarget);
       if (content->NodeInfo()->Equals(nsGkAtoms::treechildren,
                                       kNameSpaceID_XUL)) {
-        nsIDocument* doc = content->GetCurrentDoc();
-        if (doc) {
-          nsIPresShell* presShell = doc->GetPrimaryShell();
-          if (presShell) {
-            nsIFrame* frame = presShell->GetPrimaryFrameFor(content);
-            if (frame) {
-              nsTreeBodyFrame* treeBody = do_QueryFrame(frame);
-              treeBody->GetSelectionRegion(getter_AddRefs(region));
-            }
-          }
+        nsTreeBodyFrame* treeBody = do_QueryFrame(content->GetPrimaryFrame());
+        if (treeBody) {
+          treeBody->GetSelectionRegion(getter_AddRefs(region));
         }
       }
     }
 #endif
 
     dragService->InvokeDragSessionWithImage(dragTarget, transArray,
                                             region, action, dragImage,
                                             imageX, imageY, domDragEvent,
@@ -2783,17 +2771,17 @@ nsEventStateManager::GetParentScrollingV
 
   /*
     get this content node's frame, and use it as the new event target,
     so the event can be processed in the parent docshell.
     Note that we don't actually need to translate the event coordinates
     because they are not used by DoScrollText().
   */
 
-  nsIFrame* frameFrame = pPresShell->GetPrimaryFrameFor(frameContent);
+  nsIFrame* frameFrame = frameContent->GetPrimaryFrame();
   if (!frameFrame) return NS_ERROR_FAILURE;
 
   NS_IF_ADDREF(presCtxOuter = pPresShell->GetPresContext());
   targetOuterFrame = frameFrame;
 
   return NS_OK;
 }
 
@@ -3572,24 +3560,21 @@ nsEventStateManager::SetCursor(PRInt32 a
 class NS_STACK_CLASS nsESMEventCB : public nsDispatchingCallback
 {
 public:
   nsESMEventCB(nsIContent* aTarget) : mTarget(aTarget) {}
 
   virtual void HandleEvent(nsEventChainPostVisitor& aVisitor)
   {
     if (aVisitor.mPresContext) {
-      nsIPresShell* shell = aVisitor.mPresContext->GetPresShell();
-      if (shell) {
-        nsIFrame* frame = shell->GetPrimaryFrameFor(mTarget);
-        if (frame) {
-          frame->HandleEvent(aVisitor.mPresContext,
-                             (nsGUIEvent*) aVisitor.mEvent,
-                             &aVisitor.mEventStatus);
-        }
+      nsIFrame* frame = aVisitor.mPresContext->GetPrimaryFrameFor(mTarget);
+      if (frame) {
+        frame->HandleEvent(aVisitor.mPresContext,
+                           (nsGUIEvent*) aVisitor.mEvent,
+                           &aVisitor.mEventStatus);
       }
     }
   }
 
   nsCOMPtr<nsIContent> mTarget;
 };
 
 nsIFrame*
@@ -3611,22 +3596,21 @@ nsEventStateManager::DispatchMouseEvent(
   mCurrentTargetContent = aTargetContent;
 
   nsIFrame* targetFrame = nsnull;
   if (aTargetContent) {
     nsESMEventCB callback(aTargetContent);
     nsEventDispatcher::Dispatch(aTargetContent, mPresContext, &event, nsnull,
                                 &status, &callback);
 
-    nsIPresShell *shell = mPresContext ? mPresContext->GetPresShell() : nsnull;
-    if (shell) {
-      // Although the primary frame was checked in event callback, 
-      // it may not be the same object after event dispatching and handling.
-      // So we need to refetch it.
-      targetFrame = shell->GetPrimaryFrameFor(aTargetContent);
+    // Although the primary frame was checked in event callback, 
+    // it may not be the same object after event dispatching and handling.
+    // So we need to refetch it.
+    if (mPresContext) {
+      targetFrame = mPresContext->GetPrimaryFrameFor(aTargetContent);
     }
   }
 
   mCurrentTargetContent = nsnull;
 
   return targetFrame;
 }
 
@@ -4054,17 +4038,17 @@ nsEventStateManager::GetEventTarget(nsIF
   if (mCurrentTarget ||
       !mPresContext ||
       !(shell = mPresContext->GetPresShell())) {
     *aFrame = mCurrentTarget;
     return NS_OK;
   }
 
   if (mCurrentTargetContent) {
-    mCurrentTarget = shell->GetPrimaryFrameFor(mCurrentTargetContent);
+    mCurrentTarget = mPresContext->GetPrimaryFrameFor(mCurrentTargetContent);
     if (mCurrentTarget) {
       *aFrame = mCurrentTarget;
       return NS_OK;
     }
   }
 
   nsIFrame* frame = nsnull;
   shell->GetEventTargetFrame(&frame);
@@ -4227,18 +4211,20 @@ nsEventStateManager::SetContentState(nsI
 
   nsCOMPtr<nsIContent> commonHoverAncestor, oldHover, newHover;
   if ((aState & NS_EVENT_STATE_HOVER) && (aContent != mHoverContent)) {
     oldHover = mHoverContent;
 
     if (!mPresContext || mPresContext->IsDynamic()) {
       newHover = aContent;
     } else {
-      nsIFrame *frame = aContent ?
-        mPresContext->PresShell()->GetPrimaryFrameFor(aContent) : nsnull;
+      NS_ASSERTION(!aContent ||
+                   aContent->GetCurrentDoc() == mPresContext->PresShell()->GetDocument(),
+                   "Unexpected document");
+      nsIFrame *frame = aContent ? aContent->GetPrimaryFrame() : nsnull;
       if (frame && nsLayoutUtils::IsViewportScrollbarFrame(frame)) {
         // The scrollbars of viewport should not ignore the hover state.
         // Because they are *not* the content of the web page.
         newHover = aContent;
       } else {
         // All contents of the web page should ignore the hover state.
         newHover = nsnull;
       }
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -280,18 +280,17 @@ nsTextStateManager::Init(nsIWidget* aWid
 {
   mWidget = aWidget;
 
   nsIPresShell* presShell = aPresContext->PresShell();
 
   // get selection and root content
   nsCOMPtr<nsISelectionController> selCon;
   if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
-    nsIFrame* frame = presShell->GetPrimaryFrameFor(
-                                     static_cast<nsIContent*>(aNode));
+    nsIFrame* frame = static_cast<nsIContent*>(aNode)->GetPrimaryFrame();
     NS_ENSURE_TRUE(frame, NS_ERROR_UNEXPECTED);
 
     frame->GetSelectionController(aPresContext,
                                   getter_AddRefs(selCon));
   } else {
     // aNode is a document
     selCon = do_QueryInterface(presShell);
   }
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -1240,27 +1240,24 @@ nsGenericHTMLElement::IsAttributeMapped(
 }
 
 nsMapRuleToAttributesFunc
 nsGenericHTMLElement::GetAttributeMappingFunction() const
 {
   return &MapCommonAttributesInto;
 }
 
-// static
 nsIFormControlFrame*
-nsGenericHTMLElement::GetFormControlFrameFor(nsIContent* aContent,
-                                             nsIDocument* aDocument,
-                                             PRBool aFlushContent)
+nsGenericHTMLElement::GetFormControlFrame(PRBool aFlushFrames)
 {
-  if (aFlushContent) {
+  if (aFlushFrames && IsInDoc()) {
     // Cause a flush of the frames, so we get up-to-date frame information
-    aDocument->FlushPendingNotifications(Flush_Frames);
+    GetCurrentDoc()->FlushPendingNotifications(Flush_Frames);
   }
-  nsIFrame* frame = GetPrimaryFrameFor(aContent, aDocument);
+  nsIFrame* frame = GetPrimaryFrame();
   if (frame) {
     nsIFormControlFrame* form_frame = do_QueryFrame(frame);
     if (form_frame) {
       return form_frame;
     }
 
     // If we have generated content, the primary frame will be a
     // wrapper frame..  out real frame will be in its child list.
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -227,31 +227,23 @@ public:
    * but certain content carries a local base for backward
    * compatibility.
    *
    * @param aBaseTarget the base target [OUT]
    */
   void GetBaseTarget(nsAString& aBaseTarget) const;
 
   /**
-   * Get the primary form control frame for this content (see
-   * GetFormControlFrameFor)
+   * Get the primary form control frame for this element.  Same as
+   * GetPrimaryFrame(), except it QI's to nsIFormControlFrame.
    *
-   * @param aFlushContent whether to flush the content sink
-   * @return the primary form control frame (or null)
+   * @param aFlush whether to flush out frames so that they're up to date.
+   * @return the primary frame as nsIFormControlFrame
    */
-  nsIFormControlFrame* GetFormControlFrame(PRBool aFlushContent)
-  {
-    nsIDocument* doc = GetCurrentDoc();
-    if (!doc) {
-      return nsnull;
-    }
-
-    return GetFormControlFrameFor(this, doc, aFlushContent);
-  }
+  nsIFormControlFrame* GetFormControlFrame(PRBool aFlushFrames);
 
   //----------------------------------------
 
   /**
    * Parse an alignment attribute (top/middle/bottom/baseline)
    *
    * @param aString the string to parse
    * @param aResult the resulting HTMLValue
@@ -440,29 +432,16 @@ public:
    *
    * @param aAttributes the list of attributes to map
    * @param aData the returned rule data [INOUT]
    * @see GetAttributeMappingFunction
    */
   static void MapScrollingAttributeInto(const nsMappedAttributes* aAttributes,
                                         nsRuleData* aData);
   /**
-   * Get the primary form control frame for a piece of content.  Same as
-   * GetPrimaryFrameFor, except it QI's to nsIFormControlFrame.
-   *
-   * @param aContent the content to get the primary frame for
-   * @param aDocument the document for this content
-   * @param aFlushContent whether to flush the content sink, which creates
-   *        frames for content that do not already have it.  EXPENSIVE.
-   * @return the primary frame as nsIFormControlFrame
-   */
-  static nsIFormControlFrame* GetFormControlFrameFor(nsIContent* aContent,
-                                                     nsIDocument* aDocument,
-                                                     PRBool aFlushContent);
-  /**
    * Get the presentation state for a piece of content, or create it if it does
    * not exist.  Generally used by SaveState().
    *
    * @param aContent the content to get presentation state for.
    * @param aPresState the presentation state (out param)
    */
   static nsresult GetPrimaryPresState(nsGenericHTMLElement* aContent,
                                       nsPresState** aPresState);
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -516,44 +516,34 @@ void
 nsHTMLCanvasElement::SetWriteOnly()
 {
   mWriteOnly = PR_TRUE;
 }
 
 NS_IMETHODIMP
 nsHTMLCanvasElement::InvalidateFrame()
 {
-  nsIDocument* doc = GetCurrentDoc();
-  if (!doc) {
-    return NS_OK;
-  }
-
   // We don't need to flush anything here; if there's no frame or if
   // we plan to reframe we don't need to invalidate it anyway.
-  nsIFrame *frame = GetPrimaryFrameFor(this, doc);
+  nsIFrame *frame = GetPrimaryFrame();
   if (frame) {
     nsRect r = frame->GetRect();
     r.x = r.y = 0;
     frame->Invalidate(r);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLCanvasElement::InvalidateFrameSubrect(const gfxRect& damageRect)
 {
-  nsIDocument* doc = GetCurrentDoc();
-  if (!doc) {
-    return NS_OK;
-  }
-
   // We don't need to flush anything here; if there's no frame or if
   // we plan to reframe we don't need to invalidate it anyway.
-  nsIFrame *frame = GetPrimaryFrameFor(this, doc);
+  nsIFrame *frame = GetPrimaryFrame();
   if (frame) {
     // Frame might be dirty, but we don't care about that; if the geometry
     // changes the right invalidates will happen anyway.  Don't assert on our
     // geometry getters.
     nsAutoDisableGetUsedXAssertions noAssert;
     
     nsRect contentArea(frame->GetContentRect());
     nsIntSize size = GetWidthHeight();
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -947,25 +947,21 @@ void nsHTMLMediaElement::StopSuspendingA
 void nsHTMLMediaElement::SetPlayedOrSeeked(PRBool aValue)
 {
   if (aValue == mHasPlayedOrSeeked)
     return;
 
   mHasPlayedOrSeeked = aValue;
 
   // Force a reflow so that the poster frame hides or shows immediately.
-  nsIDocument *doc = GetDocument();
-  if (!doc) return;
-  nsIPresShell *presShell = doc->GetPrimaryShell();
-  if (!presShell) return;
-  nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
+  nsIFrame* frame = GetPrimaryFrame();
   if (!frame) return;
-  presShell->FrameNeedsReflow(frame,
-                              nsIPresShell::eTreeChange,
-                              NS_FRAME_IS_DIRTY);
+  frame->PresContext()->PresShell()->FrameNeedsReflow(frame,
+                                                      nsIPresShell::eTreeChange,
+                                                      NS_FRAME_IS_DIRTY);
 }
 
 NS_IMETHODIMP nsHTMLMediaElement::Play()
 {
   StopSuspendingAfterFirstFrame();
   SetPlayedOrSeeked(PR_TRUE);
 
   if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY) {
@@ -2022,19 +2018,17 @@ nsHTMLMediaElement::CopyInnerTo(nsGeneri
   nsresult rv = nsGenericHTMLElement::CopyInnerTo(aDest);
   NS_ENSURE_SUCCESS(rv, rv);
   if (aDest->GetOwnerDoc()->IsStaticDocument()) {
     nsHTMLMediaElement* dest = static_cast<nsHTMLMediaElement*>(aDest);
     if (mPrintSurface) {
       dest->mPrintSurface = mPrintSurface;
       dest->mMediaSize = mMediaSize;
     } else {
-      nsIFrame* frame =
-        GetPrimaryFrameFor(const_cast<nsHTMLMediaElement*>(this),
-                           GetOwnerDoc());
+      nsIFrame* frame = GetPrimaryFrame();
       nsCOMPtr<nsIDOMElement> elem;
       if (frame && frame->GetType() == nsGkAtoms::HTMLVideoFrame &&
           static_cast<nsVideoFrame*>(frame)->ShouldDisplayPoster()) {
         elem = do_QueryInterface(static_cast<nsVideoFrame*>(frame)->
                                  GetPosterImage());
       } else {
         elem = do_QueryInterface(const_cast<nsHTMLMediaElement*>(this));
       }
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2316,30 +2316,25 @@ nsHTMLDocument::GetNumFormsSynchronous()
 nsresult
 nsHTMLDocument::GetBodySize(PRInt32* aWidth,
                             PRInt32* aHeight)
 {
   *aWidth = *aHeight = 0;
 
   FlushPendingNotifications(Flush_Layout);
 
-  nsCOMPtr<nsIPresShell> shell = GetPrimaryShell();
-  
-  if (!shell)
-    return NS_OK;
-
   // Find the <body> element: this is what we'll want to use for the
   // document's width and height values.
   nsIContent* body = GetBodyContent();
   if (!body) {
     return NS_OK;
   }
 
   // Now grab its frame
-  nsIFrame* frame = shell->GetPrimaryFrameFor(body);
+  nsIFrame* frame = body->GetPrimaryFrame();
   if (!frame)
     return NS_OK;
   
   nsSize size = frame->GetSize();
 
   *aWidth = nsPresContext::AppUnitsToIntCSSPixels(size.width);
   *aHeight = nsPresContext::AppUnitsToIntCSSPixels(size.height);
 
--- a/content/html/document/src/nsPluginDocument.cpp
+++ b/content/html/document/src/nsPluginDocument.cpp
@@ -133,17 +133,17 @@ nsPluginStreamListener::SetupPlugin()
     return NS_BINDING_ABORTED;
   }
 
   // Flush out layout before we go to instantiate, because some
   // plug-ins depend on NPP_SetWindow() being called early enough and
   // nsObjectFrame does that at the end of reflow.
   shell->FlushPendingNotifications(Flush_Layout);
 
-  nsIFrame* frame = shell->GetPrimaryFrameFor(embed);
+  nsIFrame* frame = embed->GetPrimaryFrame();
   if (!frame) {
     mPluginDoc->AllowNormalInstantiation();
     return NS_OK;
   }
 
   nsIObjectFrame* objFrame = do_QueryFrame(frame);
   if (!objFrame) {
     mPluginDoc->AllowNormalInstantiation();
@@ -336,25 +336,18 @@ nsPluginDocument::SetStreamListener(nsIS
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPluginDocument::Print()
 {
   NS_ENSURE_TRUE(mPluginContent, NS_ERROR_FAILURE);
 
-  nsIPresShell *shell = GetPrimaryShell();
-  if (!shell) {
-    return NS_OK;
-  }
-
-  nsIFrame* frame = shell->GetPrimaryFrameFor(mPluginContent);
-  NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
-
-  nsIObjectFrame* objectFrame = do_QueryFrame(frame);
+  nsIObjectFrame* objectFrame =
+    do_QueryFrame(mPluginContent->GetPrimaryFrame());
   if (objectFrame) {
     nsCOMPtr<nsIPluginInstance> pi;
     objectFrame->GetPluginInstance(*getter_AddRefs(pi));
 
     if (pi) {
       NPPrint npprint;
       npprint.mode = NP_FULL;
       npprint.print.fullPrint.pluginPrinted = PR_FALSE;
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -1086,36 +1086,28 @@ nsSVGSVGElement::WillBeOutermostSVG(nsIC
 
   return PR_TRUE;
 }
 #endif // MOZ_SMIL
 
 void
 nsSVGSVGElement::InvalidateTransformNotifyFrame()
 {
-  nsIDocument* doc = GetCurrentDoc();
-  if (!doc) return;
-  nsIPresShell* presShell = doc->GetPrimaryShell();
-  if (!presShell) return;
-
-  nsIFrame* frame = presShell->GetPrimaryFrameFor(this);
-  if (frame) {
-    nsISVGSVGFrame* svgframe = do_QueryFrame(frame);
-    if (svgframe) {
-      svgframe->NotifyViewportChange();
-    }
+  nsISVGSVGFrame* svgframe = do_QueryFrame(GetPrimaryFrame());
+  if (svgframe) {
+    svgframe->NotifyViewportChange();
+  }
 #ifdef DEBUG
-    else {
-      // XXX we get here during nsSVGOuterSVGFrame::Init() since that
-      // function is called before the presshell association between us
-      // and our frame is established.
-      NS_WARNING("wrong frame type");
-    }
+  else {
+    // XXX we get here during nsSVGOuterSVGFrame::Init() since that
+    // function is called before the presshell association between us
+    // and our frame is established.
+    NS_WARNING("wrong frame type");
+  }
 #endif
-  }
 }
 
 //----------------------------------------------------------------------
 // nsSVGSVGElement
 
 float
 nsSVGSVGElement::GetLength(PRUint8 aCtxType)
 {
--- a/content/xbl/src/nsXBLResourceLoader.cpp
+++ b/content/xbl/src/nsXBLResourceLoader.cpp
@@ -260,17 +260,17 @@ nsXBLResourceLoader::NotifyBoundElements
         // notification of its parent.  (We can know about both if the
         // binding loads were triggered from the DOM rather than frame
         // construction.)  So we have to check both whether the element
         // has a primary frame and whether it's in the undisplayed map
         // before sending a ContentInserted notification, or bad things
         // will happen.
         nsIPresShell *shell = doc->GetPrimaryShell();
         if (shell) {
-          nsIFrame* childFrame = shell->GetPrimaryFrameFor(content);
+          nsIFrame* childFrame = content->GetPrimaryFrame();
           if (!childFrame) {
             // Check to see if it's in the undisplayed content map.
             nsStyleContext* sc =
               shell->FrameManager()->GetUndisplayedContent(content);
 
             if (!sc) {
               shell->RecreateFramesFor(content);
             }
--- a/content/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -210,17 +210,17 @@ public:
     // notification of its parent.  (We can know about both if the
     // binding loads were triggered from the DOM rather than frame
     // construction.)  So we have to check both whether the element
     // has a primary frame and whether it's in the undisplayed map
     // before sending a ContentInserted notification, or bad things
     // will happen.
     nsIPresShell *shell = doc->GetPrimaryShell();
     if (shell) {
-      nsIFrame* childFrame = shell->GetPrimaryFrameFor(mBoundElement);
+      nsIFrame* childFrame = mBoundElement->GetPrimaryFrame();
       if (!childFrame) {
         // Check to see if it's in the undisplayed content map.
         nsStyleContext* sc =
           shell->FrameManager()->GetUndisplayedContent(mBoundElement);
 
         if (!sc) {
           shell->RecreateFramesFor(mBoundElement);
         }
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -627,25 +627,17 @@ nsXULElement::PerformAccesskey(PRBool aK
         // here we'll either change |content| to the element referenced by
         // |element|, or clear it.
         content = do_QueryInterface(element);
 
         if (!content)
             return;
     }
 
-    nsIDocument* doc = GetCurrentDoc();
-    if (!doc)
-        return;
-
-    nsIPresShell *shell = doc->GetPrimaryShell();
-    if (!shell)
-        return;
-
-    nsIFrame* frame = shell->GetPrimaryFrameFor(content);
+    nsIFrame* frame = content->GetPrimaryFrame();
     if (!frame)
         return;
 
     const nsStyleVisibility* vis = frame->GetStyleVisibility();
 
     if (vis->mVisible == NS_STYLE_VISIBILITY_COLLAPSE ||
         vis->mVisible == NS_STYLE_VISIBILITY_HIDDEN ||
         !frame->AreAncestorViewsVisible())
@@ -2380,18 +2372,17 @@ nsXULElement::HideWindowChrome(PRBool aS
 
     // only top level chrome documents can hide the window chrome
     if (!doc->IsRootDisplayDocument())
       return NS_OK;
 
     nsIPresShell *shell = doc->GetPrimaryShell();
 
     if (shell) {
-        nsIContent* content = static_cast<nsIContent*>(this);
-        nsIFrame* frame = shell->GetPrimaryFrameFor(content);
+        nsIFrame* frame = GetPrimaryFrame();
 
         nsPresContext *presContext = shell->GetPresContext();
 
         if (frame && presContext && presContext->IsChrome()) {
             nsIView* view = frame->GetClosestView();
 
             if (view) {
                 nsIWidget* w = view->GetWidget();
--- a/content/xul/content/src/nsXULPopupListener.cpp
+++ b/content/xul/content/src/nsXULPopupListener.cpp
@@ -269,20 +269,21 @@ nsXULPopupListener::FireFocusOnTargetCon
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
 
     // Get nsIDOMElement for targetNode
     nsIPresShell *shell = doc->GetPrimaryShell();
     if (!shell)
       return NS_ERROR_FAILURE;
 
     // strong reference to keep this from going away between events
+    // XXXbz between what events?  We don't use this local at all!
     nsCOMPtr<nsPresContext> context = shell->GetPresContext();
  
     nsCOMPtr<nsIContent> content = do_QueryInterface(aTargetNode);
-    nsIFrame* targetFrame = shell->GetPrimaryFrameFor(content);
+    nsIFrame* targetFrame = content->GetPrimaryFrame();
     if (!targetFrame) return NS_ERROR_FAILURE;
 
     const nsStyleUserInterface* ui = targetFrame->GetStyleUserInterface();
     PRBool suppressBlur = (ui->mUserFocus == NS_STYLE_USER_FOCUS_IGNORE);
 
     nsCOMPtr<nsIDOMElement> element;
     nsCOMPtr<nsIContent> newFocus = do_QueryInterface(content);
 
@@ -446,19 +447,17 @@ 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) {
-    nsIDocument* doc = parent->GetCurrentDoc();
-    nsIPresShell* presShell = doc ? doc->GetPrimaryShell() : nsnull;
-    nsIFrame* frame = presShell ? presShell->GetPrimaryFrameFor(parent) : nsnull;
+    nsIFrame* frame = parent->GetPrimaryFrame();
     if (frame && frame->GetType() == nsGkAtoms::menuFrame)
       return NS_OK;
   }
 
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (!pm)
     return NS_OK;