From c72ee5ce8739c1dc0cf80f90130d7378062245e1 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Mon, 21 Apr 2003 23:57:47 +0000 Subject: [PATCH] Make sure that Init() failures for image frames don't mean no alt text. Also fixes a crasher when reframing fixed-pos frames. This change adds an assertion in ConstructHTMLFrame that InitAndRestoreFrame should succeed (unless it returns NS_ERROR_FRAME_REPLACED). This is an interim change; eventually we want to bail out on errors, but there may be frame impls that return errors in non-error conditions from Init() (eg nsFrameSetFrame did that) and we're a little close to freeze. Bug 202506, r=rbs, sr=roc+moz --- layout/base/nsCSSFrameConstructor.cpp | 171 +++++++++++------- layout/base/nsCSSFrameConstructor.h | 3 +- layout/base/nsLayoutErrors.h | 4 + layout/base/public/nsLayoutErrors.h | 4 + layout/generic/nsFrameSetFrame.cpp | 15 +- layout/generic/nsImageFrame.cpp | 24 ++- layout/generic/nsImageFrame.h | 5 +- layout/generic/nsObjectFrame.cpp | 4 +- layout/html/base/src/nsImageFrame.cpp | 24 ++- layout/html/base/src/nsImageFrame.h | 5 +- layout/html/base/src/nsObjectFrame.cpp | 4 +- layout/html/document/src/nsFrameSetFrame.cpp | 15 +- .../html/style/src/nsCSSFrameConstructor.cpp | 171 +++++++++++------- layout/html/style/src/nsCSSFrameConstructor.h | 3 +- 14 files changed, 276 insertions(+), 176 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 5da4e09930a..64296d125ed 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1421,10 +1421,18 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIPresContext* aPresContex content->SetDocument(aDocument, PR_TRUE, PR_TRUE); // Create an image frame and initialize it - nsIFrame* imageFrame; - NS_NewImageFrame(shell, &imageFrame); - imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull); - + nsIFrame* imageFrame = nsnull; + rv = NS_NewImageFrame(shell, &imageFrame); + if (!imageFrame) { + return rv; + } + + rv = imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull); + if (NS_FAILED(rv)) { + imageFrame->Destroy(aPresContext); + return rv == NS_ERROR_FRAME_REPLACED ? NS_OK : rv; + } + // Return the image frame *aFrame = imageFrame; @@ -4973,69 +4981,89 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell, } } - InitAndRestoreFrame(aPresContext, aState, aContent, - geometricParent, aStyleContext, nsnull, newFrame); + rv = InitAndRestoreFrame(aPresContext, aState, aContent, + geometricParent, aStyleContext, nsnull, newFrame); + if (rv == NS_ERROR_FRAME_REPLACED) { + // The frame called CantRenderReplacedElement from inside Init(). That + // failed to do anything useful, since the frame was not in the frame + // tree yet... Create an alternate frame ourselves + newFrame->Destroy(aPresContext); - // See if we need to create a view, e.g. the frame is absolutely - // positioned - nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame, - aStyleContext, aParentFrame, PR_FALSE); + if (aTag != nsHTMLAtoms::img && aTag != nsHTMLAtoms::input) { + // XXXbz This should really be made to work for too... + return NS_OK; + } - // Process the child content if requested - nsFrameItems childItems; - if (processChildren) { - if (isPositionedContainingBlock) { - // The area frame becomes a container for child frames that are - // absolutely positioned - nsFrameConstructorSaveState absoluteSaveState; - aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState); + // Try to construct the alternate frame + newFrame = nsnull; + rv = ConstructAlternateFrame(aPresShell, aPresContext, aContent, + aStyleContext, geometricParent, + aParentFrame, newFrame); + NS_ENSURE_SUCCESS(rv, rv); + NS_ASSERTION(newFrame, "ConstructAlternateFrame needs better error-checking"); + } else { + NS_ASSERTION(NS_SUCCEEDED(rv), "InitAndRestoreFrame failed"); + // See if we need to create a view, e.g. the frame is absolutely + // positioned + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame, + aStyleContext, aParentFrame, PR_FALSE); + + // Process the child content if requested + nsFrameItems childItems; + if (processChildren) { + if (isPositionedContainingBlock) { + // The area frame becomes a container for child frames that are + // absolutely positioned + nsFrameConstructorSaveState absoluteSaveState; + aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState); - // Process the child frames - rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, - PR_TRUE, childItems, PR_FALSE); + // Process the child frames + rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, + PR_TRUE, childItems, PR_FALSE); - // Set the frame's absolute list if there were any absolutely positioned children - if (aState.mAbsoluteItems.childList) { - newFrame->SetInitialChildList(aPresContext, - nsLayoutAtoms::absoluteList, - aState.mAbsoluteItems.childList); + // Set the frame's absolute list if there were any absolutely positioned children + if (aState.mAbsoluteItems.childList) { + newFrame->SetInitialChildList(aPresContext, + nsLayoutAtoms::absoluteList, + aState.mAbsoluteItems.childList); + } + } + else if (isFloaterContainer) { + // If the frame can contain floaters, then push a floater + // containing block + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); + nsFrameConstructorSaveState floaterSaveState; + aState.PushFloaterContainingBlock(newFrame, floaterSaveState, + PR_FALSE, PR_FALSE); + + // Process the child frames + rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, + PR_TRUE, childItems, PR_FALSE); + + // Set the frame's floater list if there were any floated children + if (aState.mFloatedItems.childList) { + newFrame->SetInitialChildList(aPresContext, + nsLayoutAtoms::floaterList, + aState.mFloatedItems.childList); + } + + } else { + rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, + PR_TRUE, childItems, PR_FALSE); } } - else if (isFloaterContainer) { - // If the frame can contain floaters, then push a floater - // containing block - PRBool haveFirstLetterStyle, haveFirstLineStyle; - HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, - &haveFirstLetterStyle, &haveFirstLineStyle); - nsFrameConstructorSaveState floaterSaveState; - aState.PushFloaterContainingBlock(newFrame, floaterSaveState, - PR_FALSE, PR_FALSE); - - // Process the child frames - rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, - PR_TRUE, childItems, PR_FALSE); - - // Set the frame's floater list if there were any floated children - if (aState.mFloatedItems.childList) { - newFrame->SetInitialChildList(aPresContext, - nsLayoutAtoms::floaterList, - aState.mFloatedItems.childList); - } - } else { - rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, - PR_TRUE, childItems, PR_FALSE); + // if there are any anonymous children create frames for them + CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, + PR_FALSE, childItems); + + // Set the frame's initial child list + if (childItems.childList) { + newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); } } - - // if there are any anonymous children create frames for them - CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, - PR_FALSE, childItems); - - // Set the frame's initial child list - if (childItems.childList) { - newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); - } } // If the frame is positioned, then create a placeholder frame @@ -10757,7 +10785,8 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell, nsIPresContext* aPresContext, nsIContent* aContent, nsStyleContext* aStyleContext, - nsIFrame* aParentFrame, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIFrame*& aFrame) { nsresult rv; @@ -10802,9 +10831,10 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell, } else { NS_NewInlineFrame(aPresShell, &containerFrame); } - containerFrame->Init(aPresContext, aContent, aParentFrame, aStyleContext, nsnull); + containerFrame->Init(aPresContext, aContent, aGeometricParent, aStyleContext, nsnull); nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame, - aStyleContext, nsnull, PR_FALSE); + aStyleContext, aContentParent, + PR_FALSE); // If the frame is out-of-flow, then mark it as such if (isOutOfFlow) { @@ -10942,7 +10972,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell, // image can't be rendered nsIFrame* newFrame; rv = ConstructAlternateFrame(aPresShell, aPresContext, content, styleContext, - parentFrame, newFrame); + parentFrame, nsnull, newFrame); if (NS_SUCCEEDED(rv)) { nsCOMPtr frameManager; @@ -10956,6 +10986,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell, frameManager->SetPrimaryFrameFor(content, newFrame); // Replace the old frame with the new frame + // XXXbz If this fails, we leak the content node newFrame points to! frameManager->ReplaceFrame(aPresContext, *presShell, parentFrame, listName, aFrame, newFrame); @@ -12035,11 +12066,21 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, // state onto a temporary state object. CaptureStateForFramesOf(aPresContext, aContent, mTempFrameTreeState); - // Save parent frame because this frame is going away + // Save parent frame because this frame is going away. But if + // this is an out-of-flow, we want to get the _placeholder_'s + // parent. nsIFrame* parent = nsnull; - if (frame) - frame->GetParent(&parent); + if (frame) { + nsFrameState state; + frame->GetFrameState(&state); + if (state & NS_FRAME_OUT_OF_FLOW) { + shell->GetPlaceholderFrameFor(frame, &frame); + NS_ASSERTION(frame, "Out-of-flow with no placeholder?"); + } + frame->GetParent(&parent); + } + // Remove the frames associated with the content object on which the // attribute change occurred. rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE); diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index af53d4a5799..29c385c91ef 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -472,7 +472,8 @@ protected: nsIPresContext* aPresContext, nsIContent* aContent, nsStyleContext* aStyleContext, - nsIFrame* aParentFrame, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIFrame*& aFrame); nsWidgetRendering GetFormElementRenderingMode(nsIPresContext* aPresContext, diff --git a/layout/base/nsLayoutErrors.h b/layout/base/nsLayoutErrors.h index da587a39c04..41b81e20e87 100644 --- a/layout/base/nsLayoutErrors.h +++ b/layout/base/nsLayoutErrors.h @@ -56,4 +56,8 @@ #define NS_POSITION_BEFORE_TABLE \ NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 3) +/** Error code to return from nsIFrame::Init() if the frame got + replaced by alt text or something like that **/ +#define NS_ERROR_FRAME_REPLACED \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LAYOUT, 4) #endif // nsLayoutErrors_h___ diff --git a/layout/base/public/nsLayoutErrors.h b/layout/base/public/nsLayoutErrors.h index da587a39c04..41b81e20e87 100644 --- a/layout/base/public/nsLayoutErrors.h +++ b/layout/base/public/nsLayoutErrors.h @@ -56,4 +56,8 @@ #define NS_POSITION_BEFORE_TABLE \ NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 3) +/** Error code to return from nsIFrame::Init() if the frame got + replaced by alt text or something like that **/ +#define NS_ERROR_FRAME_REPLACED \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_LAYOUT, 4) #endif // nsLayoutErrors_h___ diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index ca734b8be83..146b3fb844a 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -326,15 +326,15 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext, // find the highest ancestor that is a frameset nsresult rv = NS_OK; nsIFrame* parentFrame = nsnull; - GetParent((nsIFrame**)&parentFrame); + GetParent(&parentFrame); mTopLevelFrameset = (nsHTMLFramesetFrame*)this; while (parentFrame) { - nsHTMLFramesetFrame* frameset; - rv = parentFrame->QueryInterface(NS_GET_IID(nsHTMLFramesetFrame), - (void**)&frameset); - if (NS_SUCCEEDED(rv)) { + nsHTMLFramesetFrame* frameset = nsnull; + CallQueryInterface(parentFrame, &frameset); + + if (frameset) { mTopLevelFrameset = frameset; - parentFrame->GetParent((nsIFrame**)&parentFrame); + parentFrame->GetParent(&parentFrame); } else { break; } @@ -342,8 +342,7 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext, // create the view. a view is needed since it needs to be a mouse grabber nsIView* view; - nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), - (void **)&view); + nsresult result = CallCreateInstance(kViewCID, &view); nsCOMPtr presShell; aPresContext->GetShell(getter_AddRefs(presShell)); nsCOMPtr viewMan; diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 7ca12769b1f..ab713389be8 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -98,6 +98,8 @@ #include "nsIPrefService.h" #include "gfxIImageFrame.h" +#include "nsLayoutErrors.h" + #ifdef DEBUG #undef NOISY_IMAGE_LOADING #undef NOISY_ICON_LOADING @@ -320,8 +322,8 @@ nsImageFrame::Init(nsIPresContext* aPresContext, PRBool loadBlocked = PR_FALSE; imageLoader->GetImageBlocked(&loadBlocked); - HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE, - presShell); + rv = HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE, + presShell); } return rv; @@ -425,14 +427,14 @@ nsImageFrame::ConvertPxRectToTwips(const nsRect& aRect) const NSIntPixelsToTwips(aRect.height, p2t)); // height } -void +nsresult nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) { if (aStatus == NS_ERROR_IMAGE_BLOCKED && !(mIconLoad && mIconLoad->mPrefAllImagesBlocked)) { // don't display any alt feedback in this case; we're blocking images // from that site and don't care to see anything from them - return; + return NS_OK; } // If we have an image map, don't do anything here @@ -442,7 +444,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) nsAutoString usemap; mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::usemap, usemap); if (!usemap.IsEmpty()) { - return; + return NS_OK; } // check if we want to honor the ALT text in the IMG frame, or let the preShell make it into inline text @@ -465,7 +467,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) // check for style property that indicates the icon should always be shown const nsStyleUIReset* styleData; - GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData); + ::GetStyleData(this, &styleData); if (styleData->mForceBrokenImageIcon) { forceIcon = PR_TRUE; } @@ -489,11 +491,13 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) aPresShell->GetPrimaryFrameFor(mContent, &primaryFrame); aPresShell->CantRenderReplacedElement(mPresContext, primaryFrame ? primaryFrame : this); - } else { - // we are handling it - // invalidate the icon area (it may change states) - InvalidateIcon(mPresContext); + return NS_ERROR_FRAME_REPLACED; } + + // we are handling it + // invalidate the icon area (it may change states) + InvalidateIcon(mPresContext); + return NS_OK; } nsresult diff --git a/layout/generic/nsImageFrame.h b/layout/generic/nsImageFrame.h index 4011326a428..d5edf7b8929 100644 --- a/layout/generic/nsImageFrame.h +++ b/layout/generic/nsImageFrame.h @@ -233,9 +233,10 @@ private: /** * Function to call when a load fails; this handles things like alt - * text, broken image icons, etc + * text, broken image icons, etc. Returns NS_ERROR_FRAME_REPLACED + * if it called CantRenderReplacedElement, NS_OK otherwise. */ - void HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell); + nsresult HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell); nsImageMap* mImageMap; diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index 57193c89575..294b4dddfc0 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -638,13 +638,13 @@ nsObjectFrame::Init(nsIPresContext* aPresContext, aPresContext->GetShell(getter_AddRefs(shell)); nsIFrame * aNewFrame = nsnull; rv = NS_NewImageFrame(shell, &aNewFrame); - if(rv != NS_OK) + if (NS_FAILED(rv)) return rv; // XXX we're using the same style context for ourselves and the // image frame. If this ever changes, please fix HandleChild() to deal. rv = aNewFrame->Init(aPresContext, aContent, this, aContext, aPrevInFlow); - if(rv == NS_OK) + if (NS_SUCCEEDED(rv)) { nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, aContext, nsnull, PR_FALSE); mFrames.AppendFrame(this, aNewFrame); diff --git a/layout/html/base/src/nsImageFrame.cpp b/layout/html/base/src/nsImageFrame.cpp index 7ca12769b1f..ab713389be8 100644 --- a/layout/html/base/src/nsImageFrame.cpp +++ b/layout/html/base/src/nsImageFrame.cpp @@ -98,6 +98,8 @@ #include "nsIPrefService.h" #include "gfxIImageFrame.h" +#include "nsLayoutErrors.h" + #ifdef DEBUG #undef NOISY_IMAGE_LOADING #undef NOISY_ICON_LOADING @@ -320,8 +322,8 @@ nsImageFrame::Init(nsIPresContext* aPresContext, PRBool loadBlocked = PR_FALSE; imageLoader->GetImageBlocked(&loadBlocked); - HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE, - presShell); + rv = HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE, + presShell); } return rv; @@ -425,14 +427,14 @@ nsImageFrame::ConvertPxRectToTwips(const nsRect& aRect) const NSIntPixelsToTwips(aRect.height, p2t)); // height } -void +nsresult nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) { if (aStatus == NS_ERROR_IMAGE_BLOCKED && !(mIconLoad && mIconLoad->mPrefAllImagesBlocked)) { // don't display any alt feedback in this case; we're blocking images // from that site and don't care to see anything from them - return; + return NS_OK; } // If we have an image map, don't do anything here @@ -442,7 +444,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) nsAutoString usemap; mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::usemap, usemap); if (!usemap.IsEmpty()) { - return; + return NS_OK; } // check if we want to honor the ALT text in the IMG frame, or let the preShell make it into inline text @@ -465,7 +467,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) // check for style property that indicates the icon should always be shown const nsStyleUIReset* styleData; - GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData); + ::GetStyleData(this, &styleData); if (styleData->mForceBrokenImageIcon) { forceIcon = PR_TRUE; } @@ -489,11 +491,13 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) aPresShell->GetPrimaryFrameFor(mContent, &primaryFrame); aPresShell->CantRenderReplacedElement(mPresContext, primaryFrame ? primaryFrame : this); - } else { - // we are handling it - // invalidate the icon area (it may change states) - InvalidateIcon(mPresContext); + return NS_ERROR_FRAME_REPLACED; } + + // we are handling it + // invalidate the icon area (it may change states) + InvalidateIcon(mPresContext); + return NS_OK; } nsresult diff --git a/layout/html/base/src/nsImageFrame.h b/layout/html/base/src/nsImageFrame.h index 4011326a428..d5edf7b8929 100644 --- a/layout/html/base/src/nsImageFrame.h +++ b/layout/html/base/src/nsImageFrame.h @@ -233,9 +233,10 @@ private: /** * Function to call when a load fails; this handles things like alt - * text, broken image icons, etc + * text, broken image icons, etc. Returns NS_ERROR_FRAME_REPLACED + * if it called CantRenderReplacedElement, NS_OK otherwise. */ - void HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell); + nsresult HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell); nsImageMap* mImageMap; diff --git a/layout/html/base/src/nsObjectFrame.cpp b/layout/html/base/src/nsObjectFrame.cpp index 57193c89575..294b4dddfc0 100644 --- a/layout/html/base/src/nsObjectFrame.cpp +++ b/layout/html/base/src/nsObjectFrame.cpp @@ -638,13 +638,13 @@ nsObjectFrame::Init(nsIPresContext* aPresContext, aPresContext->GetShell(getter_AddRefs(shell)); nsIFrame * aNewFrame = nsnull; rv = NS_NewImageFrame(shell, &aNewFrame); - if(rv != NS_OK) + if (NS_FAILED(rv)) return rv; // XXX we're using the same style context for ourselves and the // image frame. If this ever changes, please fix HandleChild() to deal. rv = aNewFrame->Init(aPresContext, aContent, this, aContext, aPrevInFlow); - if(rv == NS_OK) + if (NS_SUCCEEDED(rv)) { nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, aContext, nsnull, PR_FALSE); mFrames.AppendFrame(this, aNewFrame); diff --git a/layout/html/document/src/nsFrameSetFrame.cpp b/layout/html/document/src/nsFrameSetFrame.cpp index ca734b8be83..146b3fb844a 100644 --- a/layout/html/document/src/nsFrameSetFrame.cpp +++ b/layout/html/document/src/nsFrameSetFrame.cpp @@ -326,15 +326,15 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext, // find the highest ancestor that is a frameset nsresult rv = NS_OK; nsIFrame* parentFrame = nsnull; - GetParent((nsIFrame**)&parentFrame); + GetParent(&parentFrame); mTopLevelFrameset = (nsHTMLFramesetFrame*)this; while (parentFrame) { - nsHTMLFramesetFrame* frameset; - rv = parentFrame->QueryInterface(NS_GET_IID(nsHTMLFramesetFrame), - (void**)&frameset); - if (NS_SUCCEEDED(rv)) { + nsHTMLFramesetFrame* frameset = nsnull; + CallQueryInterface(parentFrame, &frameset); + + if (frameset) { mTopLevelFrameset = frameset; - parentFrame->GetParent((nsIFrame**)&parentFrame); + parentFrame->GetParent(&parentFrame); } else { break; } @@ -342,8 +342,7 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext, // create the view. a view is needed since it needs to be a mouse grabber nsIView* view; - nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), - (void **)&view); + nsresult result = CallCreateInstance(kViewCID, &view); nsCOMPtr presShell; aPresContext->GetShell(getter_AddRefs(presShell)); nsCOMPtr viewMan; diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 5da4e09930a..64296d125ed 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -1421,10 +1421,18 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIPresContext* aPresContex content->SetDocument(aDocument, PR_TRUE, PR_TRUE); // Create an image frame and initialize it - nsIFrame* imageFrame; - NS_NewImageFrame(shell, &imageFrame); - imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull); - + nsIFrame* imageFrame = nsnull; + rv = NS_NewImageFrame(shell, &imageFrame); + if (!imageFrame) { + return rv; + } + + rv = imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull); + if (NS_FAILED(rv)) { + imageFrame->Destroy(aPresContext); + return rv == NS_ERROR_FRAME_REPLACED ? NS_OK : rv; + } + // Return the image frame *aFrame = imageFrame; @@ -4973,69 +4981,89 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell, } } - InitAndRestoreFrame(aPresContext, aState, aContent, - geometricParent, aStyleContext, nsnull, newFrame); + rv = InitAndRestoreFrame(aPresContext, aState, aContent, + geometricParent, aStyleContext, nsnull, newFrame); + if (rv == NS_ERROR_FRAME_REPLACED) { + // The frame called CantRenderReplacedElement from inside Init(). That + // failed to do anything useful, since the frame was not in the frame + // tree yet... Create an alternate frame ourselves + newFrame->Destroy(aPresContext); - // See if we need to create a view, e.g. the frame is absolutely - // positioned - nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame, - aStyleContext, aParentFrame, PR_FALSE); + if (aTag != nsHTMLAtoms::img && aTag != nsHTMLAtoms::input) { + // XXXbz This should really be made to work for too... + return NS_OK; + } - // Process the child content if requested - nsFrameItems childItems; - if (processChildren) { - if (isPositionedContainingBlock) { - // The area frame becomes a container for child frames that are - // absolutely positioned - nsFrameConstructorSaveState absoluteSaveState; - aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState); + // Try to construct the alternate frame + newFrame = nsnull; + rv = ConstructAlternateFrame(aPresShell, aPresContext, aContent, + aStyleContext, geometricParent, + aParentFrame, newFrame); + NS_ENSURE_SUCCESS(rv, rv); + NS_ASSERTION(newFrame, "ConstructAlternateFrame needs better error-checking"); + } else { + NS_ASSERTION(NS_SUCCEEDED(rv), "InitAndRestoreFrame failed"); + // See if we need to create a view, e.g. the frame is absolutely + // positioned + nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame, + aStyleContext, aParentFrame, PR_FALSE); + + // Process the child content if requested + nsFrameItems childItems; + if (processChildren) { + if (isPositionedContainingBlock) { + // The area frame becomes a container for child frames that are + // absolutely positioned + nsFrameConstructorSaveState absoluteSaveState; + aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState); - // Process the child frames - rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, - PR_TRUE, childItems, PR_FALSE); + // Process the child frames + rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, + PR_TRUE, childItems, PR_FALSE); - // Set the frame's absolute list if there were any absolutely positioned children - if (aState.mAbsoluteItems.childList) { - newFrame->SetInitialChildList(aPresContext, - nsLayoutAtoms::absoluteList, - aState.mAbsoluteItems.childList); + // Set the frame's absolute list if there were any absolutely positioned children + if (aState.mAbsoluteItems.childList) { + newFrame->SetInitialChildList(aPresContext, + nsLayoutAtoms::absoluteList, + aState.mAbsoluteItems.childList); + } + } + else if (isFloaterContainer) { + // If the frame can contain floaters, then push a floater + // containing block + PRBool haveFirstLetterStyle, haveFirstLineStyle; + HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, + &haveFirstLetterStyle, &haveFirstLineStyle); + nsFrameConstructorSaveState floaterSaveState; + aState.PushFloaterContainingBlock(newFrame, floaterSaveState, + PR_FALSE, PR_FALSE); + + // Process the child frames + rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, + PR_TRUE, childItems, PR_FALSE); + + // Set the frame's floater list if there were any floated children + if (aState.mFloatedItems.childList) { + newFrame->SetInitialChildList(aPresContext, + nsLayoutAtoms::floaterList, + aState.mFloatedItems.childList); + } + + } else { + rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, + PR_TRUE, childItems, PR_FALSE); } } - else if (isFloaterContainer) { - // If the frame can contain floaters, then push a floater - // containing block - PRBool haveFirstLetterStyle, haveFirstLineStyle; - HaveSpecialBlockStyle(aPresContext, aContent, aStyleContext, - &haveFirstLetterStyle, &haveFirstLineStyle); - nsFrameConstructorSaveState floaterSaveState; - aState.PushFloaterContainingBlock(newFrame, floaterSaveState, - PR_FALSE, PR_FALSE); - - // Process the child frames - rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, - PR_TRUE, childItems, PR_FALSE); - - // Set the frame's floater list if there were any floated children - if (aState.mFloatedItems.childList) { - newFrame->SetInitialChildList(aPresContext, - nsLayoutAtoms::floaterList, - aState.mFloatedItems.childList); - } - } else { - rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, - PR_TRUE, childItems, PR_FALSE); + // if there are any anonymous children create frames for them + CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, + PR_FALSE, childItems); + + // Set the frame's initial child list + if (childItems.childList) { + newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); } } - - // if there are any anonymous children create frames for them - CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame, - PR_FALSE, childItems); - - // Set the frame's initial child list - if (childItems.childList) { - newFrame->SetInitialChildList(aPresContext, nsnull, childItems.childList); - } } // If the frame is positioned, then create a placeholder frame @@ -10757,7 +10785,8 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell, nsIPresContext* aPresContext, nsIContent* aContent, nsStyleContext* aStyleContext, - nsIFrame* aParentFrame, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIFrame*& aFrame) { nsresult rv; @@ -10802,9 +10831,10 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell, } else { NS_NewInlineFrame(aPresShell, &containerFrame); } - containerFrame->Init(aPresContext, aContent, aParentFrame, aStyleContext, nsnull); + containerFrame->Init(aPresContext, aContent, aGeometricParent, aStyleContext, nsnull); nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame, - aStyleContext, nsnull, PR_FALSE); + aStyleContext, aContentParent, + PR_FALSE); // If the frame is out-of-flow, then mark it as such if (isOutOfFlow) { @@ -10942,7 +10972,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell, // image can't be rendered nsIFrame* newFrame; rv = ConstructAlternateFrame(aPresShell, aPresContext, content, styleContext, - parentFrame, newFrame); + parentFrame, nsnull, newFrame); if (NS_SUCCEEDED(rv)) { nsCOMPtr frameManager; @@ -10956,6 +10986,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell, frameManager->SetPrimaryFrameFor(content, newFrame); // Replace the old frame with the new frame + // XXXbz If this fails, we leak the content node newFrame points to! frameManager->ReplaceFrame(aPresContext, *presShell, parentFrame, listName, aFrame, newFrame); @@ -12035,11 +12066,21 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, // state onto a temporary state object. CaptureStateForFramesOf(aPresContext, aContent, mTempFrameTreeState); - // Save parent frame because this frame is going away + // Save parent frame because this frame is going away. But if + // this is an out-of-flow, we want to get the _placeholder_'s + // parent. nsIFrame* parent = nsnull; - if (frame) - frame->GetParent(&parent); + if (frame) { + nsFrameState state; + frame->GetFrameState(&state); + if (state & NS_FRAME_OUT_OF_FLOW) { + shell->GetPlaceholderFrameFor(frame, &frame); + NS_ASSERTION(frame, "Out-of-flow with no placeholder?"); + } + frame->GetParent(&parent); + } + // Remove the frames associated with the content object on which the // attribute change occurred. rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE); diff --git a/layout/html/style/src/nsCSSFrameConstructor.h b/layout/html/style/src/nsCSSFrameConstructor.h index af53d4a5799..29c385c91ef 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.h +++ b/layout/html/style/src/nsCSSFrameConstructor.h @@ -472,7 +472,8 @@ protected: nsIPresContext* aPresContext, nsIContent* aContent, nsStyleContext* aStyleContext, - nsIFrame* aParentFrame, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIFrame*& aFrame); nsWidgetRendering GetFormElementRenderingMode(nsIPresContext* aPresContext,