diff --git a/mozilla/browser/components/downloads/src/nsDownloadManager.cpp b/mozilla/browser/components/downloads/src/nsDownloadManager.cpp index 1854a469ce6..06bcd5f4b07 100644 --- a/mozilla/browser/components/downloads/src/nsDownloadManager.cpp +++ b/mozilla/browser/components/downloads/src/nsDownloadManager.cpp @@ -543,12 +543,17 @@ nsDownloadManager::CancelDownload(const PRUnichar* aPath) if (!mCurrDownloads.Exists(&key)) return RemoveDownload(aPath); // XXXBlake for now, to provide a workaround for stuck downloads - nsCOMPtr download; nsDownload* internalDownload = NS_STATIC_CAST(nsDownload*, mCurrDownloads.Get(&key)); - internalDownload->QueryInterface(NS_GET_IID(nsIDownload), (void**) getter_AddRefs(download)); + nsCOMPtr download; + CallQueryInterface(internalDownload, NS_STATIC_CAST(nsIDownload**, + getter_AddRefs(download))); if (!download) return NS_ERROR_FAILURE; - + + // Don't cancel if download is already finished + if (internalDownload->mDownloadState == FINISHED) + return NS_OK; + internalDownload->SetDownloadState(CANCELED); // if a persist was provided, we can do the cancel ourselves. @@ -1016,9 +1021,9 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress, if (mListener) mListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus); - if (mDialogListener) - mDialogListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus); - + // We need to update mDownloadState before updating the dialog, because + // that will close and call CancelDownload if it was the last open window. + nsresult rv = NS_OK; if (aStateFlags & STATE_STOP) { if (mDownloadState == DOWNLOADING || mDownloadState == NOTSTARTED) { mDownloadState = FINISHED; @@ -1031,10 +1036,11 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress, gObserverService->NotifyObservers(NS_STATIC_CAST(nsIDownload *, this), "dl-done", nsnull); nsAutoString path; - nsresult rv = mTarget->GetPath(path); - if (NS_FAILED(rv)) return rv; - - mDownloadManager->DownloadEnded(path.get(), nsnull); + rv = mTarget->GetPath(path); + // can't do an early return; have to break reference cycle below + if (NS_SUCCEEDED(rv)) { + mDownloadManager->DownloadEnded(path.get(), nsnull); + } } // break the cycle we created in AddDownload @@ -1042,7 +1048,10 @@ nsDownload::OnStateChange(nsIWebProgress* aWebProgress, mPersist->SetProgressListener(nsnull); } - return NS_OK; + if (mDialogListener) + mDialogListener->OnStateChange(aWebProgress, aRequest, aStateFlags, aStatus); + + return rv; } NS_IMETHODIMP