Bug 509929 - Reference cycle between nsProgressNotificationProxy and nsHttpChannel on channel redirect. r=biesi

This commit is contained in:
Bobby Holley 2009-08-13 13:20:41 +02:00
parent bfc896c351
commit 6be6d69d7c
2 changed files with 41 additions and 1 deletions

View File

@ -49,6 +49,7 @@
#include "nsIPrefBranch2.h"
#include "nsIPrefService.h"
#include "nsIProgressEventSink.h"
#include "nsIChannelEventSink.h"
#include "nsIProxyObjectManager.h"
#include "nsIServiceManager.h"
#include "nsIFileURL.h"
@ -118,6 +119,7 @@ static void PrintImageDecoders()
* and forwards everything else to the channel's notification callbacks.
*/
class nsProgressNotificationProxy : public nsIProgressEventSink
, public nsIChannelEventSink
, public nsIInterfaceRequestor
{
public:
@ -129,6 +131,7 @@ class nsProgressNotificationProxy : public nsIProgressEventSink
NS_DECL_ISUPPORTS
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
private:
~nsProgressNotificationProxy() {}
@ -138,8 +141,9 @@ class nsProgressNotificationProxy : public nsIProgressEventSink
nsCOMPtr<nsIRequest> mImageRequest;
};
NS_IMPL_ISUPPORTS2(nsProgressNotificationProxy,
NS_IMPL_ISUPPORTS3(nsProgressNotificationProxy,
nsIProgressEventSink,
nsIChannelEventSink,
nsIInterfaceRequestor)
NS_IMETHODIMP
@ -178,6 +182,30 @@ nsProgressNotificationProxy::OnStatus(nsIRequest* request,
return target->OnStatus(mImageRequest, ctxt, status, statusArg);
}
NS_IMETHODIMP
nsProgressNotificationProxy::OnChannelRedirect(nsIChannel *oldChannel,
nsIChannel *newChannel,
PRUint32 flags) {
// The 'old' channel should match the current one
NS_ABORT_IF_FALSE(oldChannel == mChannel,
"old channel doesn't match current!");
// Save the new channel
mChannel = newChannel;
// Tell the original original callbacks about it too
nsCOMPtr<nsILoadGroup> loadGroup;
mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
nsCOMPtr<nsIChannelEventSink> target;
NS_QueryNotificationCallbacks(mOriginalCallbacks,
loadGroup,
NS_GET_IID(nsIChannelEventSink),
getter_AddRefs(target));
if (!target)
return NS_OK;
return target->OnChannelRedirect(oldChannel, newChannel, flags);
}
NS_IMETHODIMP
nsProgressNotificationProxy::GetInterface(const nsIID& iid,
void** result) {
@ -186,6 +214,11 @@ nsProgressNotificationProxy::GetInterface(const nsIID& iid,
NS_ADDREF_THIS();
return NS_OK;
}
if (iid.Equals(NS_GET_IID(nsIChannelEventSink))) {
*result = static_cast<nsIChannelEventSink*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
if (mOriginalCallbacks)
return mOriginalCallbacks->GetInterface(iid, result);
return NS_NOINTERFACE;

View File

@ -1279,8 +1279,15 @@ nsHttpChannel::DoReplaceWithProxy(nsIProxyInfo* pi)
return rv;
mStatus = NS_BINDING_REDIRECTED;
// disconnect from the old listeners...
mListener = nsnull;
mListenerContext = nsnull;
// ...and the old callbacks
mCallbacks = nsnull;
mProgressSink = nsnull;
return rv;
}