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
This commit is contained in:
bzbarsky%mit.edu 2003-04-21 23:57:47 +00:00
Родитель de711ed4d0
Коммит c72ee5ce87
14 изменённых файлов: 276 добавлений и 176 удалений

Просмотреть файл

@ -1421,10 +1421,18 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIPresContext* aPresContex
content->SetDocument(aDocument, PR_TRUE, PR_TRUE); content->SetDocument(aDocument, PR_TRUE, PR_TRUE);
// Create an image frame and initialize it // Create an image frame and initialize it
nsIFrame* imageFrame; nsIFrame* imageFrame = nsnull;
NS_NewImageFrame(shell, &imageFrame); rv = NS_NewImageFrame(shell, &imageFrame);
imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull); 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 // Return the image frame
*aFrame = imageFrame; *aFrame = imageFrame;
@ -4973,69 +4981,89 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell,
} }
} }
InitAndRestoreFrame(aPresContext, aState, aContent, rv = InitAndRestoreFrame(aPresContext, aState, aContent,
geometricParent, aStyleContext, nsnull, newFrame); 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 if (aTag != nsHTMLAtoms::img && aTag != nsHTMLAtoms::input) {
// positioned // XXXbz This should really be made to work for <object> too...
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame, return NS_OK;
aStyleContext, aParentFrame, PR_FALSE); }
// Process the child content if requested // Try to construct the alternate frame
nsFrameItems childItems; newFrame = nsnull;
if (processChildren) { rv = ConstructAlternateFrame(aPresShell, aPresContext, aContent,
if (isPositionedContainingBlock) { aStyleContext, geometricParent,
// The area frame becomes a container for child frames that are aParentFrame, newFrame);
// absolutely positioned NS_ENSURE_SUCCESS(rv, rv);
nsFrameConstructorSaveState absoluteSaveState; NS_ASSERTION(newFrame, "ConstructAlternateFrame needs better error-checking");
aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState); } 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 // Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE); PR_TRUE, childItems, PR_FALSE);
// Set the frame's absolute list if there were any absolutely positioned children // Set the frame's absolute list if there were any absolutely positioned children
if (aState.mAbsoluteItems.childList) { if (aState.mAbsoluteItems.childList) {
newFrame->SetInitialChildList(aPresContext, newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::absoluteList, nsLayoutAtoms::absoluteList,
aState.mAbsoluteItems.childList); 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 { // if there are any anonymous children create frames for them
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE); 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 // If the frame is positioned, then create a placeholder frame
@ -10757,7 +10785,8 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext, nsIPresContext* aPresContext,
nsIContent* aContent, nsIContent* aContent,
nsStyleContext* aStyleContext, nsStyleContext* aStyleContext,
nsIFrame* aParentFrame, nsIFrame* aGeometricParent,
nsIFrame* aContentParent,
nsIFrame*& aFrame) nsIFrame*& aFrame)
{ {
nsresult rv; nsresult rv;
@ -10802,9 +10831,10 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell,
} else { } else {
NS_NewInlineFrame(aPresShell, &containerFrame); NS_NewInlineFrame(aPresShell, &containerFrame);
} }
containerFrame->Init(aPresContext, aContent, aParentFrame, aStyleContext, nsnull); containerFrame->Init(aPresContext, aContent, aGeometricParent, aStyleContext, nsnull);
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame, 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 the frame is out-of-flow, then mark it as such
if (isOutOfFlow) { if (isOutOfFlow) {
@ -10942,7 +10972,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
// image can't be rendered // image can't be rendered
nsIFrame* newFrame; nsIFrame* newFrame;
rv = ConstructAlternateFrame(aPresShell, aPresContext, content, styleContext, rv = ConstructAlternateFrame(aPresShell, aPresContext, content, styleContext,
parentFrame, newFrame); parentFrame, nsnull, newFrame);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIFrameManager> frameManager; nsCOMPtr<nsIFrameManager> frameManager;
@ -10956,6 +10986,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
frameManager->SetPrimaryFrameFor(content, newFrame); frameManager->SetPrimaryFrameFor(content, newFrame);
// Replace the old frame with the new frame // 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, frameManager->ReplaceFrame(aPresContext, *presShell, parentFrame,
listName, aFrame, newFrame); listName, aFrame, newFrame);
@ -12035,11 +12066,21 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext,
// state onto a temporary state object. // state onto a temporary state object.
CaptureStateForFramesOf(aPresContext, aContent, mTempFrameTreeState); 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; nsIFrame* parent = nsnull;
if (frame) if (frame) {
frame->GetParent(&parent); 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 // Remove the frames associated with the content object on which the
// attribute change occurred. // attribute change occurred.
rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE); rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE);

Просмотреть файл

@ -472,7 +472,8 @@ protected:
nsIPresContext* aPresContext, nsIPresContext* aPresContext,
nsIContent* aContent, nsIContent* aContent,
nsStyleContext* aStyleContext, nsStyleContext* aStyleContext,
nsIFrame* aParentFrame, nsIFrame* aGeometricParent,
nsIFrame* aContentParent,
nsIFrame*& aFrame); nsIFrame*& aFrame);
nsWidgetRendering GetFormElementRenderingMode(nsIPresContext* aPresContext, nsWidgetRendering GetFormElementRenderingMode(nsIPresContext* aPresContext,

Просмотреть файл

@ -56,4 +56,8 @@
#define NS_POSITION_BEFORE_TABLE \ #define NS_POSITION_BEFORE_TABLE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 3) 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___ #endif // nsLayoutErrors_h___

Просмотреть файл

@ -56,4 +56,8 @@
#define NS_POSITION_BEFORE_TABLE \ #define NS_POSITION_BEFORE_TABLE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_LAYOUT, 3) 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___ #endif // nsLayoutErrors_h___

Просмотреть файл

@ -326,15 +326,15 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext,
// find the highest ancestor that is a frameset // find the highest ancestor that is a frameset
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsIFrame* parentFrame = nsnull; nsIFrame* parentFrame = nsnull;
GetParent((nsIFrame**)&parentFrame); GetParent(&parentFrame);
mTopLevelFrameset = (nsHTMLFramesetFrame*)this; mTopLevelFrameset = (nsHTMLFramesetFrame*)this;
while (parentFrame) { while (parentFrame) {
nsHTMLFramesetFrame* frameset; nsHTMLFramesetFrame* frameset = nsnull;
rv = parentFrame->QueryInterface(NS_GET_IID(nsHTMLFramesetFrame), CallQueryInterface(parentFrame, &frameset);
(void**)&frameset);
if (NS_SUCCEEDED(rv)) { if (frameset) {
mTopLevelFrameset = frameset; mTopLevelFrameset = frameset;
parentFrame->GetParent((nsIFrame**)&parentFrame); parentFrame->GetParent(&parentFrame);
} else { } else {
break; break;
} }
@ -342,8 +342,7 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext,
// create the view. a view is needed since it needs to be a mouse grabber // create the view. a view is needed since it needs to be a mouse grabber
nsIView* view; nsIView* view;
nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), nsresult result = CallCreateInstance(kViewCID, &view);
(void **)&view);
nsCOMPtr<nsIPresShell> presShell; nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell)); aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIViewManager> viewMan; nsCOMPtr<nsIViewManager> viewMan;

Просмотреть файл

@ -98,6 +98,8 @@
#include "nsIPrefService.h" #include "nsIPrefService.h"
#include "gfxIImageFrame.h" #include "gfxIImageFrame.h"
#include "nsLayoutErrors.h"
#ifdef DEBUG #ifdef DEBUG
#undef NOISY_IMAGE_LOADING #undef NOISY_IMAGE_LOADING
#undef NOISY_ICON_LOADING #undef NOISY_ICON_LOADING
@ -320,8 +322,8 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
PRBool loadBlocked = PR_FALSE; PRBool loadBlocked = PR_FALSE;
imageLoader->GetImageBlocked(&loadBlocked); imageLoader->GetImageBlocked(&loadBlocked);
HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE, rv = HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE,
presShell); presShell);
} }
return rv; return rv;
@ -425,14 +427,14 @@ nsImageFrame::ConvertPxRectToTwips(const nsRect& aRect) const
NSIntPixelsToTwips(aRect.height, p2t)); // height NSIntPixelsToTwips(aRect.height, p2t)); // height
} }
void nsresult
nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
{ {
if (aStatus == NS_ERROR_IMAGE_BLOCKED && if (aStatus == NS_ERROR_IMAGE_BLOCKED &&
!(mIconLoad && mIconLoad->mPrefAllImagesBlocked)) { !(mIconLoad && mIconLoad->mPrefAllImagesBlocked)) {
// don't display any alt feedback in this case; we're blocking images // 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 // 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 // If we have an image map, don't do anything here
@ -442,7 +444,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
nsAutoString usemap; nsAutoString usemap;
mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::usemap, usemap); mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::usemap, usemap);
if (!usemap.IsEmpty()) { 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 // 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 // check for style property that indicates the icon should always be shown
const nsStyleUIReset* styleData; const nsStyleUIReset* styleData;
GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData); ::GetStyleData(this, &styleData);
if (styleData->mForceBrokenImageIcon) { if (styleData->mForceBrokenImageIcon) {
forceIcon = PR_TRUE; forceIcon = PR_TRUE;
} }
@ -489,11 +491,13 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
aPresShell->GetPrimaryFrameFor(mContent, &primaryFrame); aPresShell->GetPrimaryFrameFor(mContent, &primaryFrame);
aPresShell->CantRenderReplacedElement(mPresContext, aPresShell->CantRenderReplacedElement(mPresContext,
primaryFrame ? primaryFrame : this); primaryFrame ? primaryFrame : this);
} else { return NS_ERROR_FRAME_REPLACED;
// we are handling it
// invalidate the icon area (it may change states)
InvalidateIcon(mPresContext);
} }
// we are handling it
// invalidate the icon area (it may change states)
InvalidateIcon(mPresContext);
return NS_OK;
} }
nsresult nsresult

Просмотреть файл

@ -233,9 +233,10 @@ private:
/** /**
* Function to call when a load fails; this handles things like alt * 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; nsImageMap* mImageMap;

Просмотреть файл

@ -638,13 +638,13 @@ nsObjectFrame::Init(nsIPresContext* aPresContext,
aPresContext->GetShell(getter_AddRefs(shell)); aPresContext->GetShell(getter_AddRefs(shell));
nsIFrame * aNewFrame = nsnull; nsIFrame * aNewFrame = nsnull;
rv = NS_NewImageFrame(shell, &aNewFrame); rv = NS_NewImageFrame(shell, &aNewFrame);
if(rv != NS_OK) if (NS_FAILED(rv))
return rv; return rv;
// XXX we're using the same style context for ourselves and the // XXX we're using the same style context for ourselves and the
// image frame. If this ever changes, please fix HandleChild() to deal. // image frame. If this ever changes, please fix HandleChild() to deal.
rv = aNewFrame->Init(aPresContext, aContent, this, aContext, aPrevInFlow); rv = aNewFrame->Init(aPresContext, aContent, this, aContext, aPrevInFlow);
if(rv == NS_OK) if (NS_SUCCEEDED(rv))
{ {
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, aContext, nsnull, PR_FALSE); nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, aContext, nsnull, PR_FALSE);
mFrames.AppendFrame(this, aNewFrame); mFrames.AppendFrame(this, aNewFrame);

Просмотреть файл

@ -98,6 +98,8 @@
#include "nsIPrefService.h" #include "nsIPrefService.h"
#include "gfxIImageFrame.h" #include "gfxIImageFrame.h"
#include "nsLayoutErrors.h"
#ifdef DEBUG #ifdef DEBUG
#undef NOISY_IMAGE_LOADING #undef NOISY_IMAGE_LOADING
#undef NOISY_ICON_LOADING #undef NOISY_ICON_LOADING
@ -320,8 +322,8 @@ nsImageFrame::Init(nsIPresContext* aPresContext,
PRBool loadBlocked = PR_FALSE; PRBool loadBlocked = PR_FALSE;
imageLoader->GetImageBlocked(&loadBlocked); imageLoader->GetImageBlocked(&loadBlocked);
HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE, rv = HandleLoadError(loadBlocked ? NS_ERROR_IMAGE_BLOCKED : NS_ERROR_FAILURE,
presShell); presShell);
} }
return rv; return rv;
@ -425,14 +427,14 @@ nsImageFrame::ConvertPxRectToTwips(const nsRect& aRect) const
NSIntPixelsToTwips(aRect.height, p2t)); // height NSIntPixelsToTwips(aRect.height, p2t)); // height
} }
void nsresult
nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell) nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
{ {
if (aStatus == NS_ERROR_IMAGE_BLOCKED && if (aStatus == NS_ERROR_IMAGE_BLOCKED &&
!(mIconLoad && mIconLoad->mPrefAllImagesBlocked)) { !(mIconLoad && mIconLoad->mPrefAllImagesBlocked)) {
// don't display any alt feedback in this case; we're blocking images // 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 // 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 // If we have an image map, don't do anything here
@ -442,7 +444,7 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
nsAutoString usemap; nsAutoString usemap;
mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::usemap, usemap); mContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::usemap, usemap);
if (!usemap.IsEmpty()) { 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 // 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 // check for style property that indicates the icon should always be shown
const nsStyleUIReset* styleData; const nsStyleUIReset* styleData;
GetStyleData(eStyleStruct_UIReset, (const nsStyleStruct*&) styleData); ::GetStyleData(this, &styleData);
if (styleData->mForceBrokenImageIcon) { if (styleData->mForceBrokenImageIcon) {
forceIcon = PR_TRUE; forceIcon = PR_TRUE;
} }
@ -489,11 +491,13 @@ nsImageFrame::HandleLoadError(nsresult aStatus, nsIPresShell* aPresShell)
aPresShell->GetPrimaryFrameFor(mContent, &primaryFrame); aPresShell->GetPrimaryFrameFor(mContent, &primaryFrame);
aPresShell->CantRenderReplacedElement(mPresContext, aPresShell->CantRenderReplacedElement(mPresContext,
primaryFrame ? primaryFrame : this); primaryFrame ? primaryFrame : this);
} else { return NS_ERROR_FRAME_REPLACED;
// we are handling it
// invalidate the icon area (it may change states)
InvalidateIcon(mPresContext);
} }
// we are handling it
// invalidate the icon area (it may change states)
InvalidateIcon(mPresContext);
return NS_OK;
} }
nsresult nsresult

Просмотреть файл

@ -233,9 +233,10 @@ private:
/** /**
* Function to call when a load fails; this handles things like alt * 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; nsImageMap* mImageMap;

Просмотреть файл

@ -638,13 +638,13 @@ nsObjectFrame::Init(nsIPresContext* aPresContext,
aPresContext->GetShell(getter_AddRefs(shell)); aPresContext->GetShell(getter_AddRefs(shell));
nsIFrame * aNewFrame = nsnull; nsIFrame * aNewFrame = nsnull;
rv = NS_NewImageFrame(shell, &aNewFrame); rv = NS_NewImageFrame(shell, &aNewFrame);
if(rv != NS_OK) if (NS_FAILED(rv))
return rv; return rv;
// XXX we're using the same style context for ourselves and the // XXX we're using the same style context for ourselves and the
// image frame. If this ever changes, please fix HandleChild() to deal. // image frame. If this ever changes, please fix HandleChild() to deal.
rv = aNewFrame->Init(aPresContext, aContent, this, aContext, aPrevInFlow); rv = aNewFrame->Init(aPresContext, aContent, this, aContext, aPrevInFlow);
if(rv == NS_OK) if (NS_SUCCEEDED(rv))
{ {
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, aContext, nsnull, PR_FALSE); nsHTMLContainerFrame::CreateViewForFrame(aPresContext, aNewFrame, aContext, nsnull, PR_FALSE);
mFrames.AppendFrame(this, aNewFrame); mFrames.AppendFrame(this, aNewFrame);

Просмотреть файл

@ -326,15 +326,15 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext,
// find the highest ancestor that is a frameset // find the highest ancestor that is a frameset
nsresult rv = NS_OK; nsresult rv = NS_OK;
nsIFrame* parentFrame = nsnull; nsIFrame* parentFrame = nsnull;
GetParent((nsIFrame**)&parentFrame); GetParent(&parentFrame);
mTopLevelFrameset = (nsHTMLFramesetFrame*)this; mTopLevelFrameset = (nsHTMLFramesetFrame*)this;
while (parentFrame) { while (parentFrame) {
nsHTMLFramesetFrame* frameset; nsHTMLFramesetFrame* frameset = nsnull;
rv = parentFrame->QueryInterface(NS_GET_IID(nsHTMLFramesetFrame), CallQueryInterface(parentFrame, &frameset);
(void**)&frameset);
if (NS_SUCCEEDED(rv)) { if (frameset) {
mTopLevelFrameset = frameset; mTopLevelFrameset = frameset;
parentFrame->GetParent((nsIFrame**)&parentFrame); parentFrame->GetParent(&parentFrame);
} else { } else {
break; break;
} }
@ -342,8 +342,7 @@ nsHTMLFramesetFrame::Init(nsIPresContext* aPresContext,
// create the view. a view is needed since it needs to be a mouse grabber // create the view. a view is needed since it needs to be a mouse grabber
nsIView* view; nsIView* view;
nsresult result = nsComponentManager::CreateInstance(kViewCID, nsnull, NS_GET_IID(nsIView), nsresult result = CallCreateInstance(kViewCID, &view);
(void **)&view);
nsCOMPtr<nsIPresShell> presShell; nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell)); aPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIViewManager> viewMan; nsCOMPtr<nsIViewManager> viewMan;

Просмотреть файл

@ -1421,10 +1421,18 @@ nsCSSFrameConstructor::CreateGeneratedFrameFor(nsIPresContext* aPresContex
content->SetDocument(aDocument, PR_TRUE, PR_TRUE); content->SetDocument(aDocument, PR_TRUE, PR_TRUE);
// Create an image frame and initialize it // Create an image frame and initialize it
nsIFrame* imageFrame; nsIFrame* imageFrame = nsnull;
NS_NewImageFrame(shell, &imageFrame); rv = NS_NewImageFrame(shell, &imageFrame);
imageFrame->Init(aPresContext, content, aParentFrame, aStyleContext, nsnull); 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 // Return the image frame
*aFrame = imageFrame; *aFrame = imageFrame;
@ -4973,69 +4981,89 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsIPresShell* aPresShell,
} }
} }
InitAndRestoreFrame(aPresContext, aState, aContent, rv = InitAndRestoreFrame(aPresContext, aState, aContent,
geometricParent, aStyleContext, nsnull, newFrame); 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 if (aTag != nsHTMLAtoms::img && aTag != nsHTMLAtoms::input) {
// positioned // XXXbz This should really be made to work for <object> too...
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, newFrame, return NS_OK;
aStyleContext, aParentFrame, PR_FALSE); }
// Process the child content if requested // Try to construct the alternate frame
nsFrameItems childItems; newFrame = nsnull;
if (processChildren) { rv = ConstructAlternateFrame(aPresShell, aPresContext, aContent,
if (isPositionedContainingBlock) { aStyleContext, geometricParent,
// The area frame becomes a container for child frames that are aParentFrame, newFrame);
// absolutely positioned NS_ENSURE_SUCCESS(rv, rv);
nsFrameConstructorSaveState absoluteSaveState; NS_ASSERTION(newFrame, "ConstructAlternateFrame needs better error-checking");
aState.PushAbsoluteContainingBlock(aPresContext, newFrame, absoluteSaveState); } 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 // Process the child frames
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE); PR_TRUE, childItems, PR_FALSE);
// Set the frame's absolute list if there were any absolutely positioned children // Set the frame's absolute list if there were any absolutely positioned children
if (aState.mAbsoluteItems.childList) { if (aState.mAbsoluteItems.childList) {
newFrame->SetInitialChildList(aPresContext, newFrame->SetInitialChildList(aPresContext,
nsLayoutAtoms::absoluteList, nsLayoutAtoms::absoluteList,
aState.mAbsoluteItems.childList); 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 { // if there are any anonymous children create frames for them
rv = ProcessChildren(aPresShell, aPresContext, aState, aContent, newFrame, CreateAnonymousFrames(aPresShell, aPresContext, aTag, aState, aContent, newFrame,
PR_TRUE, childItems, PR_FALSE); 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 // If the frame is positioned, then create a placeholder frame
@ -10757,7 +10785,8 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell,
nsIPresContext* aPresContext, nsIPresContext* aPresContext,
nsIContent* aContent, nsIContent* aContent,
nsStyleContext* aStyleContext, nsStyleContext* aStyleContext,
nsIFrame* aParentFrame, nsIFrame* aGeometricParent,
nsIFrame* aContentParent,
nsIFrame*& aFrame) nsIFrame*& aFrame)
{ {
nsresult rv; nsresult rv;
@ -10802,9 +10831,10 @@ nsCSSFrameConstructor::ConstructAlternateFrame(nsIPresShell* aPresShell,
} else { } else {
NS_NewInlineFrame(aPresShell, &containerFrame); NS_NewInlineFrame(aPresShell, &containerFrame);
} }
containerFrame->Init(aPresContext, aContent, aParentFrame, aStyleContext, nsnull); containerFrame->Init(aPresContext, aContent, aGeometricParent, aStyleContext, nsnull);
nsHTMLContainerFrame::CreateViewForFrame(aPresContext, containerFrame, 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 the frame is out-of-flow, then mark it as such
if (isOutOfFlow) { if (isOutOfFlow) {
@ -10942,7 +10972,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
// image can't be rendered // image can't be rendered
nsIFrame* newFrame; nsIFrame* newFrame;
rv = ConstructAlternateFrame(aPresShell, aPresContext, content, styleContext, rv = ConstructAlternateFrame(aPresShell, aPresContext, content, styleContext,
parentFrame, newFrame); parentFrame, nsnull, newFrame);
if (NS_SUCCEEDED(rv)) { if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIFrameManager> frameManager; nsCOMPtr<nsIFrameManager> frameManager;
@ -10956,6 +10986,7 @@ nsCSSFrameConstructor::CantRenderReplacedElement(nsIPresShell* aPresShell,
frameManager->SetPrimaryFrameFor(content, newFrame); frameManager->SetPrimaryFrameFor(content, newFrame);
// Replace the old frame with the new frame // 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, frameManager->ReplaceFrame(aPresContext, *presShell, parentFrame,
listName, aFrame, newFrame); listName, aFrame, newFrame);
@ -12035,11 +12066,21 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext,
// state onto a temporary state object. // state onto a temporary state object.
CaptureStateForFramesOf(aPresContext, aContent, mTempFrameTreeState); 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; nsIFrame* parent = nsnull;
if (frame) if (frame) {
frame->GetParent(&parent); 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 // Remove the frames associated with the content object on which the
// attribute change occurred. // attribute change occurred.
rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE); rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE);

Просмотреть файл

@ -472,7 +472,8 @@ protected:
nsIPresContext* aPresContext, nsIPresContext* aPresContext,
nsIContent* aContent, nsIContent* aContent,
nsStyleContext* aStyleContext, nsStyleContext* aStyleContext,
nsIFrame* aParentFrame, nsIFrame* aGeometricParent,
nsIFrame* aContentParent,
nsIFrame*& aFrame); nsIFrame*& aFrame);
nsWidgetRendering GetFormElementRenderingMode(nsIPresContext* aPresContext, nsWidgetRendering GetFormElementRenderingMode(nsIPresContext* aPresContext,