author | Boris Zbarsky <bzbarsky@mit.edu> |
Thu, 08 Sep 2011 23:19:45 -0400 | |
changeset 76823 | b201507b95c7fb0e3c0e026f5520118af526d425 |
parent 76822 | 68b5bfaebb24e31f6c52bb4b2660c814eba09ac3 |
child 76824 | 7a8399ef753513fd59f0753d08fc2ef5d1405b1c |
push id | 21141 |
push user | eakhgari@mozilla.com |
push date | Fri, 09 Sep 2011 14:06:30 +0000 |
treeherder | mozilla-central@694520af9b18 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jst |
bugs | 489259 |
milestone | 9.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
uriloader/base/nsDocLoader.cpp | file | annotate | diff | comparison | revisions | |
uriloader/base/nsDocLoader.h | file | annotate | diff | comparison | revisions |
--- a/uriloader/base/nsDocLoader.cpp +++ b/uriloader/base/nsDocLoader.cpp @@ -941,36 +941,43 @@ void nsDocLoader::doStopDocumentLoad(nsI GetURIStringFromRequest(request, buffer); PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, ("DocLoader:%p: ++ Firing OnStateChange for end document load (...)." "\tURI: %s Status=%x\n", 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); + } } //////////////////////////////////////////////////////////////////////////////////// // The following section contains support for nsIWebProgress and related stuff //////////////////////////////////////////////////////////////////////////////////// NS_IMETHODIMP nsDocLoader::AddProgressListener(nsIWebProgressListener *aListener, @@ -1290,22 +1297,40 @@ void nsDocLoader::FireOnProgressChange(n if (mParent) { mParent->FireOnProgressChange(aLoadInitiator, request, aProgress, aProgressMax, aProgressDelta, aTotalProgress, aMaxTotalProgress); } } +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. // // The rule is to remove this bit, if the notification has been passed // up from a child WebProgress, and the current WebProgress is already // active... // if (mIsLoadingDocument && @@ -1354,21 +1379,16 @@ void nsDocLoader::FireOnStateChange(nsIW delete info; continue; } listener->OnStateChange(aProgress, aRequest, aStateFlags, aStatus); } mListenerInfoList.Compact(); - - // Pass the notification up to the parent... - if (mParent) { - mParent->FireOnStateChange(aProgress, aRequest, aStateFlags, aStatus); - } } void nsDocLoader::FireOnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsIURI *aUri)
--- a/uriloader/base/nsDocLoader.h +++ b/uriloader/base/nsDocLoader.h @@ -55,16 +55,17 @@ #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIChannelEventSink.h" #include "nsISecurityEventSink.h" #include "nsISupportsPriority.h" #include "nsCOMPtr.h" #include "pldhash.h" #include "prclist.h" +#include "nsAutoPtr.h" struct nsRequestInfo; struct nsListenerInfo; /**************************************************************************** * nsDocLoader implementation... ****************************************************************************/ @@ -149,21 +150,39 @@ protected: void FireOnProgressChange(nsDocLoader* aLoadInitiator, nsIRequest *request, PRInt64 aProgress, PRInt64 aProgressMax, PRInt64 aProgressDelta, 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, const PRUnichar* aMessage); void FireOnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsIURI *aUri);