From 9a44c012ba70cb26fb02e55002d100959b1e20d3 Mon Sep 17 00:00:00 2001 From: "bryner%brianryner.com" Date: Sat, 22 May 2004 01:17:00 +0000 Subject: [PATCH] Fix crashes when dynamically removing input type=file elements by not calling GetValue() during Destroy() since that re-adds the frame to the primary frame map. Bug 203041, 238906, patch originally by mats.palmgren@bredband.net, updated by me, r+sr=bzbarsky. git-svn-id: svn://10.0.0.236/trunk@156745 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/forms/nsFileControlFrame.cpp | 29 +++++++++++++++++-- mozilla/layout/forms/nsFileControlFrame.h | 11 +++++++ .../html/forms/src/nsFileControlFrame.cpp | 29 +++++++++++++++++-- .../html/forms/src/nsFileControlFrame.h | 11 +++++++ 4 files changed, 74 insertions(+), 6 deletions(-) diff --git a/mozilla/layout/forms/nsFileControlFrame.cpp b/mozilla/layout/forms/nsFileControlFrame.cpp index 926574901e7..93c48f638bf 100644 --- a/mozilla/layout/forms/nsFileControlFrame.cpp +++ b/mozilla/layout/forms/nsFileControlFrame.cpp @@ -97,7 +97,8 @@ NS_NewFileControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) nsFileControlFrame::nsFileControlFrame(): mTextFrame(nsnull), - mCachedState(nsnull) + mCachedState(nsnull), + mDidPreDestroy(PR_FALSE) { //Shrink the area around it's contents SetFlags(NS_BLOCK_SHRINK_WRAP); @@ -117,8 +118,8 @@ nsFileControlFrame::~nsFileControlFrame() } } -NS_IMETHODIMP -nsFileControlFrame::Destroy(nsIPresContext* aPresContext) +void +nsFileControlFrame::PreDestroy(nsIPresContext* aPresContext) { // Toss the value into the control from the anonymous content, which is about // to get lost. @@ -131,10 +132,32 @@ nsFileControlFrame::Destroy(nsIPresContext* aPresContext) nsCOMPtr fileInput = do_QueryInterface(mContent); fileInput->TakeTextFrameValue(value); } + mDidPreDestroy = PR_TRUE; +} + +NS_IMETHODIMP +nsFileControlFrame::Destroy(nsIPresContext* aPresContext) +{ + if (!mDidPreDestroy) { + PreDestroy(aPresContext); + } mTextFrame = nsnull; return nsAreaFrame::Destroy(aPresContext); } +void +nsFileControlFrame::RemovedAsPrimaryFrame(nsIPresContext* aPresContext) +{ + if (!mDidPreDestroy) { + PreDestroy(aPresContext); + } +#ifdef DEBUG + else { + NS_ERROR("RemovedAsPrimaryFrame called after PreDestroy"); + } +#endif +} + NS_IMETHODIMP nsFileControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList) diff --git a/mozilla/layout/forms/nsFileControlFrame.h b/mozilla/layout/forms/nsFileControlFrame.h index 8392e457400..62f21d85663 100644 --- a/mozilla/layout/forms/nsFileControlFrame.h +++ b/mozilla/layout/forms/nsFileControlFrame.h @@ -88,6 +88,9 @@ public: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + + virtual void RemovedAsPrimaryFrame(nsIPresContext* aPresContext); + NS_IMETHOD Destroy(nsIPresContext *aPresContext); #ifdef NS_DEBUG @@ -226,8 +229,16 @@ private: void SyncAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRBool aWhichControls); + /** + * We call this when we are being destroyed or removed from the PFM. + * @param aPresContext the current pres context + */ + void PreDestroy(nsIPresContext* aPresContext); + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + + PRBool mDidPreDestroy; // has PreDestroy been called }; #endif diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp index 926574901e7..93c48f638bf 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp @@ -97,7 +97,8 @@ NS_NewFileControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) nsFileControlFrame::nsFileControlFrame(): mTextFrame(nsnull), - mCachedState(nsnull) + mCachedState(nsnull), + mDidPreDestroy(PR_FALSE) { //Shrink the area around it's contents SetFlags(NS_BLOCK_SHRINK_WRAP); @@ -117,8 +118,8 @@ nsFileControlFrame::~nsFileControlFrame() } } -NS_IMETHODIMP -nsFileControlFrame::Destroy(nsIPresContext* aPresContext) +void +nsFileControlFrame::PreDestroy(nsIPresContext* aPresContext) { // Toss the value into the control from the anonymous content, which is about // to get lost. @@ -131,10 +132,32 @@ nsFileControlFrame::Destroy(nsIPresContext* aPresContext) nsCOMPtr fileInput = do_QueryInterface(mContent); fileInput->TakeTextFrameValue(value); } + mDidPreDestroy = PR_TRUE; +} + +NS_IMETHODIMP +nsFileControlFrame::Destroy(nsIPresContext* aPresContext) +{ + if (!mDidPreDestroy) { + PreDestroy(aPresContext); + } mTextFrame = nsnull; return nsAreaFrame::Destroy(aPresContext); } +void +nsFileControlFrame::RemovedAsPrimaryFrame(nsIPresContext* aPresContext) +{ + if (!mDidPreDestroy) { + PreDestroy(aPresContext); + } +#ifdef DEBUG + else { + NS_ERROR("RemovedAsPrimaryFrame called after PreDestroy"); + } +#endif +} + NS_IMETHODIMP nsFileControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList) diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.h b/mozilla/layout/html/forms/src/nsFileControlFrame.h index 8392e457400..62f21d85663 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.h +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.h @@ -88,6 +88,9 @@ public: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + + virtual void RemovedAsPrimaryFrame(nsIPresContext* aPresContext); + NS_IMETHOD Destroy(nsIPresContext *aPresContext); #ifdef NS_DEBUG @@ -226,8 +229,16 @@ private: void SyncAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute, PRBool aWhichControls); + /** + * We call this when we are being destroyed or removed from the PFM. + * @param aPresContext the current pres context + */ + void PreDestroy(nsIPresContext* aPresContext); + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + + PRBool mDidPreDestroy; // has PreDestroy been called }; #endif