Fix race condition where iframe's frame is created after document is loaded and body is parsed (bug 153815), kin@netscape.com's patch, r=jkeiser@netscape.com, sr=jst@netscape.com

git-svn-id: svn://10.0.0.236/trunk@128944 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
jkeiser%netscape.com
2002-09-06 05:44:31 +00:00
parent dfe90b74d6
commit d73bc69f1a
7 changed files with 125 additions and 0 deletions

View File

@@ -680,6 +680,19 @@ DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow)
NS_ENSURE_SUCCESS(rv, rv);
if (aDoInitialReflow) {
// Since InitialReflow() will create frames for *all* items
// that are currently in the document tree, we need to flush
// any pending notifications to prevent the content sink from
// duplicating layout frames for content it has added to the tree
// but hasn't notified the document about. (Bug 154018)
//
// Note that we are flushing before we add mPresShell as an observer
// to avoid bogus notifications.
mDocument->FlushPendingNotifications(PR_FALSE);
}
mPresShell->BeginObservingDocument();
// Initialize our view manager

View File

@@ -2993,6 +2993,49 @@ HTMLContentSink::OpenBody(const nsIParserNode& aNode)
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::OpenBody()\n"));
MOZ_TIMER_STOP(mWatch);
// Check to see if InitialReflow() has been called on any of our
// presShells. If so, the InitialReflow() call inside StartLayout()
// will be supressed, so we can't rely on it to construct the body
// frame for us, so we'll have to manually call NotifyInsert() or
// NotifyAppend() to make sure a body frame gets constructed. (Bug 153815)
PRBool didInitialReflow = PR_FALSE;
PRInt32 i, ns = mDocument->GetNumberOfShells();
for (i = 0; i < ns; i++) {
nsCOMPtr<nsIPresShell> shell;
mDocument->GetShellAt(i, getter_AddRefs(shell));
if (shell) {
shell->GetDidInitialReflow(&didInitialReflow);
if (didInitialReflow)
break;
}
}
if (didInitialReflow && mCurrentContext->mStackPos > 1) {
PRInt32 parentIndex = mCurrentContext->mStackPos - 2;
nsIHTMLContent *parent = mCurrentContext->mStack[parentIndex].mContent;
PRInt32 numFlushed = mCurrentContext->mStack[parentIndex].mNumFlushed;
PRInt32 insertionPoint = mCurrentContext->mStack[parentIndex].mInsertionPoint;
// XXX: I have yet to see a case where numFlushed is non-zero and
// insertionPoint is not -1, but this code will try to handle
// those cases too.
if (insertionPoint != -1) {
NotifyInsert(parent, mBody, insertionPoint - 1);
}
else {
// XXX: Would it be better to use |parent->ChildCount() - 1| so that
// we don't cause notifications for the <head> element and it's
// children?
NotifyAppend(parent, numFlushed);
}
}
StartLayout();
return NS_OK;
}
@@ -3755,6 +3798,24 @@ HTMLContentSink::StartLayout()
nsCOMPtr<nsIPresShell> shell;
mDocument->GetShellAt(i, getter_AddRefs(shell));
if (shell) {
// Make sure we don't call InitialReflow() for a shell that has
// already called it. This can happen when the layout frame for
// an iframe is constructed *between* the Embed() call for the
// docshell in the iframe, and the content sink's call to OpenBody().
// (Bug 153815)
PRBool didInitialReflow = PR_FALSE;
shell->GetDidInitialReflow(&didInitialReflow);
if (didInitialReflow) {
// XXX: The assumption here is that if something already called
// InitialReflow() on this shell, it also did some of the
// setup below, so we do nothing and just move on to the next
// shell in the list.
continue;
}
// Make shell an observer for next time
shell->BeginObservingDocument();

View File

@@ -680,6 +680,19 @@ DocumentViewerImpl::InitPresentationStuff(PRBool aDoInitialReflow)
NS_ENSURE_SUCCESS(rv, rv);
if (aDoInitialReflow) {
// Since InitialReflow() will create frames for *all* items
// that are currently in the document tree, we need to flush
// any pending notifications to prevent the content sink from
// duplicating layout frames for content it has added to the tree
// but hasn't notified the document about. (Bug 154018)
//
// Note that we are flushing before we add mPresShell as an observer
// to avoid bogus notifications.
mDocument->FlushPendingNotifications(PR_FALSE);
}
mPresShell->BeginObservingDocument();
// Initialize our view manager

View File

@@ -206,6 +206,13 @@ public:
// Make shell stop being a document observer
NS_IMETHOD EndObservingDocument() = 0;
/**
* Determine if InitialReflow() was previously called.
* @param aDidInitialReflow PR_TRUE if InitalReflow() was previously called,
* PR_FALSE otherwise.
*/
NS_IMETHOD GetDidInitialReflow(PRBool *aDidInitialReflow) = 0;
/**
* Perform the initial reflow. Constructs the frame for the root content
* object and then reflows the frame model into the specified width and

View File

@@ -1042,6 +1042,7 @@ public:
NS_IMETHOD BeginObservingDocument();
NS_IMETHOD EndObservingDocument();
NS_IMETHOD GetDidInitialReflow(PRBool *aDidInitialReflow);
NS_IMETHOD InitialReflow(nscoord aWidth, nscoord aHeight);
NS_IMETHOD ResizeReflow(nscoord aWidth, nscoord aHeight);
NS_IMETHOD StyleChangeReflow();
@@ -2712,6 +2713,17 @@ GetRootScrollFrame(nsIPresContext* aPresContext, nsIFrame* aRootFrame, nsIFrame*
return NS_OK;
}
NS_IMETHODIMP
PresShell::GetDidInitialReflow(PRBool *aDidInitialReflow)
{
if (!aDidInitialReflow)
return NS_ERROR_FAILURE;
*aDidInitialReflow = mDidInitialReflow;
return NS_OK;
}
NS_IMETHODIMP
PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
{

View File

@@ -206,6 +206,13 @@ public:
// Make shell stop being a document observer
NS_IMETHOD EndObservingDocument() = 0;
/**
* Determine if InitialReflow() was previously called.
* @param aDidInitialReflow PR_TRUE if InitalReflow() was previously called,
* PR_FALSE otherwise.
*/
NS_IMETHOD GetDidInitialReflow(PRBool *aDidInitialReflow) = 0;
/**
* Perform the initial reflow. Constructs the frame for the root content
* object and then reflows the frame model into the specified width and

View File

@@ -1042,6 +1042,7 @@ public:
NS_IMETHOD BeginObservingDocument();
NS_IMETHOD EndObservingDocument();
NS_IMETHOD GetDidInitialReflow(PRBool *aDidInitialReflow);
NS_IMETHOD InitialReflow(nscoord aWidth, nscoord aHeight);
NS_IMETHOD ResizeReflow(nscoord aWidth, nscoord aHeight);
NS_IMETHOD StyleChangeReflow();
@@ -2712,6 +2713,17 @@ GetRootScrollFrame(nsIPresContext* aPresContext, nsIFrame* aRootFrame, nsIFrame*
return NS_OK;
}
NS_IMETHODIMP
PresShell::GetDidInitialReflow(PRBool *aDidInitialReflow)
{
if (!aDidInitialReflow)
return NS_ERROR_FAILURE;
*aDidInitialReflow = mDidInitialReflow;
return NS_OK;
}
NS_IMETHODIMP
PresShell::InitialReflow(nscoord aWidth, nscoord aHeight)
{