Bug 489259. Grab the parent chain for our OnStateChange calls before we fire onload and possibly change the docshell tree. r=jst

This commit is contained in:
Boris Zbarsky 2011-09-08 23:19:45 -04:00
parent 7341083936
commit 453903551e
2 changed files with 55 additions and 16 deletions

View File

@ -946,26 +946,33 @@ void nsDocLoader::doStopDocumentLoad(nsIRequest *request,
this, buffer.get(), aStatus));
#endif /* DEBUG */
// Firing STATE_STOP|STATE_IS_DOCUMENT will fire onload handlers.
// Grab our parent chain before doing that so we can still dispatch
// STATE_STOP|STATE_IS_WINDW_STATE_IS_NETWORK to them all, even if
// the onload handlers rearrange the docshell tree.
WebProgressList list;
GatherAncestorWebProgresses(list);
//
// Fire an OnStateChange(...) notification indicating the the
// current document has finished loading...
//
FireOnStateChange(this,
request,
nsIWebProgressListener::STATE_STOP |
nsIWebProgressListener::STATE_IS_DOCUMENT,
aStatus);
PRInt32 flags = nsIWebProgressListener::STATE_STOP |
nsIWebProgressListener::STATE_IS_DOCUMENT;
for (PRUint32 i = 0; i < list.Length(); ++i) {
list[i]->DoFireOnStateChange(this, request, flags, aStatus);
}
//
// Fire a final OnStateChange(...) notification indicating the the
// current document has finished loading...
//
FireOnStateChange(this,
request,
nsIWebProgressListener::STATE_STOP |
nsIWebProgressListener::STATE_IS_WINDOW |
nsIWebProgressListener::STATE_IS_NETWORK,
aStatus);
flags = nsIWebProgressListener::STATE_STOP |
nsIWebProgressListener::STATE_IS_WINDOW |
nsIWebProgressListener::STATE_IS_NETWORK;
for (PRUint32 i = 0; i < list.Length(); ++i) {
list[i]->DoFireOnStateChange(this, request, flags, aStatus);
}
}
////////////////////////////////////////////////////////////////////////////////////
@ -1295,11 +1302,29 @@ void nsDocLoader::FireOnProgressChange(nsDocLoader *aLoadInitiator,
}
}
void nsDocLoader::GatherAncestorWebProgresses(WebProgressList& aList)
{
for (nsDocLoader* loader = this; loader; loader = loader->mParent) {
aList.AppendElement(loader);
}
}
void nsDocLoader::FireOnStateChange(nsIWebProgress *aProgress,
nsIRequest *aRequest,
PRInt32 aStateFlags,
nsresult aStatus)
{
WebProgressList list;
GatherAncestorWebProgresses(list);
for (PRUint32 i = 0; i < list.Length(); ++i) {
list[i]->DoFireOnStateChange(aProgress, aRequest, aStateFlags, aStatus);
}
}
void nsDocLoader::DoFireOnStateChange(nsIWebProgress * const aProgress,
nsIRequest * const aRequest,
PRInt32 &aStateFlags,
const nsresult aStatus)
{
//
// Remove the STATE_IS_NETWORK bit if necessary.
@ -1359,11 +1384,6 @@ void nsDocLoader::FireOnStateChange(nsIWebProgress *aProgress,
}
mListenerInfoList.Compact();
// Pass the notification up to the parent...
if (mParent) {
mParent->FireOnStateChange(aProgress, aRequest, aStateFlags, aStatus);
}
}

View File

@ -60,6 +60,7 @@
#include "nsCOMPtr.h"
#include "pldhash.h"
#include "prclist.h"
#include "nsAutoPtr.h"
struct nsRequestInfo;
struct nsListenerInfo;
@ -154,11 +155,29 @@ protected:
PRInt64 aTotalProgress,
PRInt64 aMaxTotalProgress);
// This should be at least 2 long since we'll generally always
// have the current page and the global docloader on the ancestor
// list. But to deal with frames it's better to make it a bit
// longer, and it's always a stack temporary so there's no real
// reason not to.
typedef nsAutoTArray<nsRefPtr<nsDocLoader>, 8> WebProgressList;
void GatherAncestorWebProgresses(WebProgressList& aList);
void FireOnStateChange(nsIWebProgress *aProgress,
nsIRequest* request,
PRInt32 aStateFlags,
nsresult aStatus);
// The guts of FireOnStateChange, but does not call itself on our ancestors.
// The arguments that are const are const so that we can detect cases when
// DoFireOnStateChange wants to propagate changes to the next web progress
// at compile time. The ones that are not, are references so that such
// changes can be propagated.
void DoFireOnStateChange(nsIWebProgress * const aProgress,
nsIRequest* const request,
PRInt32 &aStateFlags,
const nsresult aStatus);
void FireOnStatusChange(nsIWebProgress *aWebProgress,
nsIRequest *aRequest,
nsresult aStatus,