Bug #35744 --> fix hang when fetching urls that don't exist. The fix was to

implement nsIWebProgressListener by the url fetcher. This will tell us when
we've failed to fetch the url. Also had to make sure we passed in a valid load group to the
channel. And added protection to make sure the OnStopRequest doesn't get processed twice.

One caveat is still left with this bug: you are still prompted after each url we fail to load. This
is pretty annoying.

r=bienvenu
This commit is contained in:
mscott%netscape.com 2000-07-14 06:18:44 +00:00
Родитель bfa5020e72
Коммит 565c0ffdb5
2 изменённых файлов: 84 добавлений и 4 удалений

Просмотреть файл

@ -39,6 +39,7 @@
#include "nsNetUtil.h"
#include "nsMimeTypes.h"
#include "nsIHTTPChannel.h"
#include "nsIWebProgress.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
@ -71,6 +72,7 @@ NS_INTERFACE_MAP_BEGIN(nsURLFetcher)
NS_INTERFACE_MAP_ENTRY(nsIStreamObserver)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIURIContentListener)
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
NS_INTERFACE_MAP_END
/*
@ -88,6 +90,7 @@ nsURLFetcher::nsURLFetcher()
mCallback = nsnull;
mContentType = nsnull;
mCharset = nsnull;
mOnStopRequestProcessed = PR_FALSE;
}
nsURLFetcher::~nsURLFetcher()
@ -95,6 +98,14 @@ nsURLFetcher::~nsURLFetcher()
mStillRunning = PR_FALSE;
PR_FREEIF(mContentType);
PR_FREEIF(mCharset);
// Remove the DocShell as a listener of the old WebProgress...
if (mLoadCookie)
{
nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(mLoadCookie));
if (webProgress)
webProgress->RemoveProgressListener(this);
}
}
NS_IMETHODIMP nsURLFetcher::GetInterface(const nsIID & aIID, void * *aInstancePtr)
@ -185,8 +196,27 @@ nsURLFetcher::GetLoadCookie(nsISupports ** aLoadCookie)
NS_IMETHODIMP
nsURLFetcher::SetLoadCookie(nsISupports * aLoadCookie)
{
// Remove the DocShell as a listener of the old WebProgress...
if (mLoadCookie)
{
nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(mLoadCookie));
if (webProgress)
webProgress->RemoveProgressListener(this);
}
mLoadCookie = aLoadCookie;
// Add the DocShell as a listener to the new WebProgress...
if (mLoadCookie)
{
nsCOMPtr<nsIWebProgress> webProgress(do_QueryInterface(mLoadCookie));
if (webProgress)
webProgress->AddProgressListener(this);
}
return NS_OK;
}
nsresult
@ -244,6 +274,13 @@ nsURLFetcher::OnStopRequest(nsIChannel *aChannel, nsISupports * /* ctxt */, nsre
printf("nsURLFetcher::OnStopRequest()\n");
#endif
// it's possible we could get in here from the channel calling us with an OnStopRequest and from our
// onStatusChange method (in the case of an error). So we should protect against this to make sure we
// don't process the on stop request twice...
if (mOnStopRequestProcessed) return NS_OK;
mOnStopRequestProcessed = PR_TRUE;
//
// Now complete the stream!
//
@ -321,14 +358,19 @@ nsURLFetcher::FireURLRequest(nsIURI *aURL, nsOutputFileStream *fOut,
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIChannel> channel;
NS_ENSURE_SUCCESS(NS_OpenURI(getter_AddRefs(channel), aURL, nsnull), NS_ERROR_FAILURE);
// we're about to fire a new url request so make sure the on stop request flag is cleared...
mOnStopRequestProcessed = PR_FALSE;
// let's try uri dispatching...
nsCOMPtr<nsIURILoader> pURILoader (do_GetService(NS_URI_LOADER_PROGID));
NS_ENSURE_TRUE(pURILoader, NS_ERROR_FAILURE);
nsCOMPtr<nsISupports> openContext;
nsCOMPtr<nsISupports> cntListener (do_QueryInterface(NS_STATIC_CAST(nsIStreamListener *, this)));
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsILoadGroup> loadGroup;
pURILoader->GetLoadGroupForContext(cntListener, getter_AddRefs(loadGroup));
NS_ENSURE_SUCCESS(NS_OpenURI(getter_AddRefs(channel), aURL, nsnull, loadGroup), NS_ERROR_FAILURE);
rv = pURILoader->OpenURI(channel, nsIURILoader::viewNormal, nsnull /* window target */,
cntListener);
@ -339,3 +381,36 @@ nsURLFetcher::FireURLRequest(nsIURI *aURL, nsOutputFileStream *fOut,
NS_ADDREF(this);
return NS_OK;
}
// web progress listener implementation
NS_IMETHODIMP
nsURLFetcher::OnProgressChange(nsIWebProgress *aProgress, nsIRequest *aRequest,
PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
{
return NS_OK;
}
NS_IMETHODIMP
nsURLFetcher::OnStateChange(nsIWebProgress *aProgress, nsIRequest *aRequest,
PRInt32 aStateFlags, nsresult aStatus)
{
// all we care about is the case where an error occurred (as in we were unable to locate the
// the url....
if (NS_FAILED(aStatus))
{
nsCOMPtr<nsIChannel> channel (do_QueryInterface(aRequest));
OnStopRequest(channel, nsnull, aStatus, nsnull);
}
return NS_OK;
}
NS_IMETHODIMP
nsURLFetcher::OnLocationChange(nsIURI *aURI)
{
return NS_OK;
}

Просмотреть файл

@ -30,6 +30,7 @@
#include "nsIInterfaceRequestor.h"
#include "nsCURILoader.h"
#include "nsIURIContentListener.h"
#include "nsIWebProgressListener.h"
//
// Callback declarations for URL completion
@ -41,7 +42,8 @@ typedef nsresult (*nsAttachSaveCompletionCallback) (nsIURI* aURL, nsresult aStat
PRInt32 totalSize, const PRUnichar* aMsg,
void *tagData);
class nsURLFetcher : public nsIStreamListener, public nsIURIContentListener, public nsIInterfaceRequestor {
class nsURLFetcher : public nsIStreamListener, public nsIURIContentListener, public nsIInterfaceRequestor,
public nsIWebProgressListener {
public:
nsURLFetcher();
virtual ~nsURLFetcher();
@ -66,8 +68,10 @@ public:
NS_DECL_NSISTREAMLISTENER
// Methods for nsIStreamObserver
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSIURICONTENTLISTENER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIWEBPROGRESSLISTENER
private:
nsOutputFileStream *mOutStream; // the output file stream
@ -79,6 +83,7 @@ private:
void *mTagData; // Tag data for callback...
nsAttachSaveCompletionCallback mCallback; // Callback to call once the file is saved...
nsCOMPtr<nsISupports> mLoadCookie; // load cookie used by the uri loader when we fetch the url
PRBool mOnStopRequestProcessed; // used to prevent calling OnStopRequest multiple times
};
/* this function will be used by the factory to generate an class access object....*/