From e2d1a317aa2e472966299fe199f20e92528f1fe4 Mon Sep 17 00:00:00 2001 From: "darin%meer.net" Date: Sun, 9 Nov 2003 22:49:57 +0000 Subject: [PATCH] fixes bug 224240 "nsURIChecker cleanup" r=biesi sr=bzbarsky git-svn-id: svn://10.0.0.236/trunk@149080 18797224-902f-48f8-a5cc-f745e15eee43 --- .../browser/base/content/contentAreaUtils.js | 8 +- .../ui/dialogs/content/EdLinkChecker.js | 7 +- mozilla/netwerk/base/public/nsIURIChecker.idl | 86 ++-- mozilla/netwerk/base/src/nsURIChecker.cpp | 408 +++++++++--------- mozilla/netwerk/base/src/nsURIChecker.h | 31 +- .../resources/content/contentAreaUtils.js | 8 +- 6 files changed, 282 insertions(+), 266 deletions(-) diff --git a/mozilla/browser/base/content/contentAreaUtils.js b/mozilla/browser/base/content/contentAreaUtils.js index bc2633ff7ed..59e88277869 100644 --- a/mozilla/browser/base/content/contentAreaUtils.js +++ b/mozilla/browser/base/content/contentAreaUtils.js @@ -451,7 +451,8 @@ function nsHeaderSniffer(aURL, aCallback, aData, aSkipPrompt) this.uri = makeURL(aURL); this.linkChecker = Components.classes["@mozilla.org/network/urichecker;1"] - .createInstance().QueryInterface(Components.interfaces.nsIURIChecker); + .createInstance(Components.interfaces.nsIURIChecker); + this.linkChecker.init(this.uri); var flags; if (aData.bypassCache) { @@ -459,8 +460,9 @@ function nsHeaderSniffer(aURL, aCallback, aData, aSkipPrompt) } else { flags = Components.interfaces.nsIRequest.LOAD_FROM_CACHE; } + this.linkChecker.loadFlags = flags; - this.linkChecker.asyncCheckURI(aURL, this, null, flags); + this.linkChecker.asyncCheck(this, null); } nsHeaderSniffer.prototype = { @@ -518,7 +520,7 @@ nsHeaderSniffer.prototype = { try { if (aStatus == 0) { // NS_BINDING_SUCCEEDED, so there's something there var linkChecker = aRequest.QueryInterface(Components.interfaces.nsIURIChecker); - var channel = linkChecker.baseRequest.QueryInterface(Components.interfaces.nsIChannel); + var channel = linkChecker.baseChannel; this.contentType = channel.contentType; try { var httpChannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel); diff --git a/mozilla/editor/ui/dialogs/content/EdLinkChecker.js b/mozilla/editor/ui/dialogs/content/EdLinkChecker.js index 042280a2feb..44b7b23bb46 100644 --- a/mozilla/editor/ui/dialogs/content/EdLinkChecker.js +++ b/mozilla/editor/ui/dialogs/content/EdLinkChecker.js @@ -46,7 +46,7 @@ var gRequestObserver = linkChecker.status = status; for (var i = 0; i < gNumLinksCalledBack; i++) { - if (linkChecker == gLinksBeingChecked[i]) + if (linkChecker == gLinksBeingChecked[i]) gLinksBeingChecked[i].status = status; } @@ -108,8 +108,9 @@ function Startup() = Components.classes["@mozilla.org/network/urichecker;1"] .createInstance() .QueryInterface(Components.interfaces.nsIURIChecker); - gLinksBeingChecked[gNumLinksToCheck].asyncCheckURI(uri, gRequestObserver, null, - Components.interfaces.nsIRequest.LOAD_NORMAL); + // XXX uri creation needs to be localized + gLinksBeingChecked[gNumLinksToCheck].init(GetIOService().newURI(uri, null, null)); + gLinksBeingChecked[gNumLinksToCheck].asyncCheck(gRequestObserver, null); // Add item var linkChecker = gLinksBeingChecked[gNumLinksToCheck].QueryInterface(Components.interfaces.nsIURIChecker); diff --git a/mozilla/netwerk/base/public/nsIURIChecker.idl b/mozilla/netwerk/base/public/nsIURIChecker.idl index c0256289996..cb4ecf219f4 100644 --- a/mozilla/netwerk/base/public/nsIURIChecker.idl +++ b/mozilla/netwerk/base/public/nsIURIChecker.idl @@ -16,11 +16,12 @@ * * The Initial Developer of the Original Code is * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 + * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Akkana Peck (original author) + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -36,43 +37,60 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsISupports.idl" #include "nsIRequest.idl" -interface nsIRequest; +interface nsIURI; +interface nsIChannel; interface nsIRequestObserver; -%{C++ -#include "nsAString.h" -%} - -[scriptable,uuid(0ce148b2-1dd2-11b2-ba70-af918b44b323)] -interface nsIURIChecker : nsISupports +/** + * nsIURIChecker + * + * The URI checker is a component that can be used to verify the existance + * of a resource at the location specified by a given URI. It will use + * protocol specific methods to verify the URI (e.g., use of HEAD request + * for HTTP URIs). + */ +[scriptable, uuid(4660c1a1-be2d-4c78-9baf-c22984176c28)] +interface nsIURIChecker : nsIRequest { - /** - * Begin asynchronous check for validity. - * Notification will be asynchronous through the callback. - * - * Our interpretations of the nsIRequestObserver errors: - * NS_BINDING_SUCCEEDED: link is valid - * NS_BINDING_FAILED: link is invalid (gave an error) - * NS_BINDING_ABORTED: timed out, or cancelled - * - * @param aURI The URI to be checked. - * @param aObserver The object to notify when the link is verified. - * We will call aObserver.OnStartRequest followed - * immediately by aObserver.OnStopRequest. - * It is recommended that the caller use - * OnStopRequest to act on the link's status. - * The underlying request will not be cancelled - * until after OnStopRequest has been called. - * @param aCtxt A closure that will be passed back to the - * nsIRequestObserver methods - * @param aLoadFlags Load flags to set on the base request. - */ - nsIRequest asyncCheckURI(in AUTF8String uri, in nsIRequestObserver aObserver, - in nsISupports aCtxt, in nsLoadFlags aLoadFlags); + /** + * Initializes the URI checker. After this method is called, it is valid + * to further configure the URI checker by calling its nsIRequest methods. + * This method creates the channel that will be used to verify the URI. + * In the case of the HTTP protocol, only a HEAD request will be issued. + * + * @param aURI + * The URI to be checked. + */ + void init(in nsIURI aURI); - readonly attribute nsIRequest baseRequest; + /** + * Returns the base channel that will be used to verify the URI. + */ + readonly attribute nsIChannel baseChannel; + + /** + * Begin asynchronous checking URI for validity. Notification will be + * asynchronous through the nsIRequestObserver callback interface. When + * OnStartRequest is fired, the baseChannel attribute will have been + * updated to reflect the final channel used (corresponding to any redirects + * that may have been followed). + * + * Our interpretations of the nsIRequestObserver status codes: + * NS_BINDING_SUCCEEDED: link is valid + * NS_BINDING_FAILED: link is invalid (gave an error) + * NS_BINDING_ABORTED: timed out, or cancelled + * + * @param aObserver + * The object to notify when the link is verified. We will + * call aObserver.OnStartRequest followed immediately by + * aObserver.OnStopRequest. It is recommended that the caller use + * OnStopRequest to act on the link's status. The underlying request + * will not be cancelled until after OnStopRequest has been called. + * @param aContext + * A closure that will be passed back to the nsIRequestObserver + * methods. + */ + void asyncCheck(in nsIRequestObserver aObserver, in nsISupports aContext); }; - diff --git a/mozilla/netwerk/base/src/nsURIChecker.cpp b/mozilla/netwerk/base/src/nsURIChecker.cpp index cab933e22da..5e2f58db754 100644 --- a/mozilla/netwerk/base/src/nsURIChecker.cpp +++ b/mozilla/netwerk/base/src/nsURIChecker.cpp @@ -16,11 +16,12 @@ * * The Initial Developer of the Original Code is * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 + * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Akkana Peck (original author) + * Darin Fisher * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -37,135 +38,204 @@ * ***** END LICENSE BLOCK ***** */ #include "nsURIChecker.h" - #include "nsIServiceManager.h" #include "nsIAuthPrompt.h" -#include "nsNetCID.h" -#include "nsNetUtil.h" #include "nsIHttpChannel.h" +#include "nsNetUtil.h" #include "nsString.h" -#include "nsReadableUtils.h" // for ToNewUnicode() -//Interfaces for addref, release and queryinterface -NS_IMPL_ISUPPORTS5(nsURIChecker, nsIURIChecker, - nsIRequest, nsIStreamListener, - nsIHttpEventSink, nsIInterfaceRequestor) +//----------------------------------------------------------------------------- -nsURIChecker::nsURIChecker() +static PRBool +ServerIsNES3x(nsIHttpChannel *httpChannel) { - mStatus = NS_OK; - mIsPending = PR_FALSE; + nsCAutoString server; + httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Server"), server); + // case sensitive string comparison is OK here. the server string + // is a well-known value, so we should not have to worry about it + // being case-smashed or otherwise case-mutated. + return StringBeginsWith(server, + NS_LITERAL_CSTRING("Netscape-Enterprise/3.")); } -nsURIChecker::~nsURIChecker() +//----------------------------------------------------------------------------- + +NS_IMPL_ISUPPORTS5(nsURIChecker, + nsIURIChecker, + nsIRequest, + nsIStreamListener, + nsIHttpEventSink, + nsIInterfaceRequestor) + +nsURIChecker::nsURIChecker() + : mStatus(NS_OK) + , mIsPending(PR_FALSE) + , mAllowHead(PR_TRUE) { } void -nsURIChecker::SetStatusAndCallBack(nsIRequest* aRequest, nsresult aStatus) +nsURIChecker::SetStatusAndCallBack(nsresult aStatus) { mStatus = aStatus; mIsPending = PR_FALSE; - mObserver->OnStartRequest(NS_STATIC_CAST(nsIRequest*, this), mCtxt); - mObserver->OnStopRequest(NS_STATIC_CAST(nsIRequest*, this), - mCtxt, mStatus); - - // We don't want to read the actual data, so cancel now: - if (aRequest) - aRequest->Cancel(NS_BINDING_ABORTED); + if (mObserver) { + mObserver->OnStartRequest(this, mObserverContext); + mObserver->OnStopRequest(this, mObserverContext, mStatus); + mObserver = nsnull; + mObserverContext = nsnull; + } } -///////////////////////////////////////////////////// -// nsIURIChecker methods -// -NS_IMETHODIMP -nsURIChecker::AsyncCheckURI(const nsACString &aURI, - nsIRequestObserver *aObserver, - nsISupports* aCtxt, - nsLoadFlags aLoadFlags, - nsIRequest** aRequestRet) +nsresult +nsURIChecker::CheckStatus() { - nsresult rv; + NS_ASSERTION(mChannel, "no channel"); - mStatus = NS_OK; - mIsPending = PR_TRUE; - mStatus = NS_BINDING_REDIRECTED; - mObserver = aObserver; - mCtxt = aCtxt; - if (aRequestRet) { - *aRequestRet = this; - NS_ADDREF(*aRequestRet); - } + nsresult status; + nsresult rv = mChannel->GetStatus(&status); + // DNS errors and other obvious problems will return failure status + if (NS_FAILED(rv) || NS_FAILED(status)) + return NS_BINDING_FAILED; - // Get the IO Service: - nsCOMPtr ios (do_GetIOService(&rv)); - if (NS_FAILED(rv)) return rv; - if (!ios) return NS_ERROR_UNEXPECTED; - - // Make the URI - nsCOMPtr URI; - rv = ios->NewURI(aURI, nsnull, nsnull, getter_AddRefs(URI)); // XXX need charset for i18n URLs - if (NS_FAILED(rv)) return rv; - - // Make a new channel: - rv = ios->NewChannelFromURI(URI, getter_AddRefs(mChannel)); - if (NS_FAILED(rv)) return rv; - - // Set the load flags - mChannel->SetLoadFlags(aLoadFlags); - - // See if it's an http channel, which needs special treatment: + // If status is zero, it might still be an error if it's http: + // http has data even when there's an error like a 404. nsCOMPtr httpChannel = do_QueryInterface(mChannel); - if (httpChannel) { - // We can have an HTTP channel that has a non-HTTP URL if - // we're doing FTP via an HTTP proxy, for example. See for - // example bug 148813 - nsCOMPtr channelURI; - mChannel->GetURI(getter_AddRefs(channelURI)); - if (channelURI) { - PRBool isReallyHTTP = PR_FALSE; - channelURI->SchemeIs("http", &isReallyHTTP); - if (!isReallyHTTP) - channelURI->SchemeIs("https", &isReallyHTTP); - if (isReallyHTTP) - httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("HEAD")); + if (!httpChannel) + return NS_BINDING_SUCCEEDED; + + PRUint32 responseStatus; + rv = httpChannel->GetResponseStatus(&responseStatus); + if (NS_FAILED(rv)) + return NS_BINDING_FAILED; + + // If it's between 200-299, it's valid: + if (responseStatus / 100 == 2) + return NS_BINDING_SUCCEEDED; + + // If we got a 404 (not found), we need some extra checking: + // toplevel urls from Netscape Enterprise Server 3.6, like the old AOL- + // hosted http://www.mozilla.org, generate a 404 and will have to be + // retried without the head. + if (responseStatus == 404) { + if (mAllowHead && ServerIsNES3x(httpChannel)) { + mAllowHead = PR_FALSE; + + // save the current value of mChannel in case we can't issue + // the new request for some reason. + nsCOMPtr lastChannel = mChannel; + + nsCOMPtr uri; + PRUint32 loadFlags; + + rv = lastChannel->GetOriginalURI(getter_AddRefs(uri)); + rv |= lastChannel->GetLoadFlags(&loadFlags); + + // XXX we are carrying over the load flags, but what about other + // parameters that may have been set on lastChannel?? + + if (NS_SUCCEEDED(rv)) { + rv = Init(uri); + if (NS_SUCCEEDED(rv)) { + rv = mChannel->SetLoadFlags(loadFlags); + if (NS_SUCCEEDED(rv)) { + rv = AsyncCheck(mObserver, mObserverContext); + // if we succeeded in loading the new channel, then we + // want to return without notifying our observer. + if (NS_SUCCEEDED(rv)) + return NS_BASE_STREAM_WOULD_BLOCK; + } + } + } + // it is important to update this so our observer will be able + // to access our baseChannel attribute if they want. + mChannel = lastChannel; } } + // If we get here, assume the resource does not exist. + return NS_BINDING_FAILED; +} + +//----------------------------------------------------------------------------- +// nsIURIChecker methods: +//----------------------------------------------------------------------------- + +NS_IMETHODIMP +nsURIChecker::Init(nsIURI *aURI) +{ + nsresult rv; + nsCOMPtr ios = do_GetIOService(&rv); + if (NS_FAILED(rv)) return rv; + + rv = ios->NewChannelFromURI(aURI, getter_AddRefs(mChannel)); + if (NS_FAILED(rv)) return rv; + + if (mAllowHead) { + mAllowHead = PR_FALSE; + // See if it's an http channel, which needs special treatment: + nsCOMPtr httpChannel = do_QueryInterface(mChannel); + if (httpChannel) { + // We can have an HTTP channel that has a non-HTTP URL if + // we're doing FTP via an HTTP proxy, for example. See for + // example bug 148813 + PRBool isReallyHTTP = PR_FALSE; + aURI->SchemeIs("http", &isReallyHTTP); + if (!isReallyHTTP) + aURI->SchemeIs("https", &isReallyHTTP); + if (isReallyHTTP) { + httpChannel->SetRequestMethod(NS_LITERAL_CSTRING("HEAD")); + // set back to true so we'll know that this request is issuing + // a HEAD request. this is used down in OnStartRequest to + // handle cases where we need to repeat the request as a normal + // GET to deal with server borkage. + mAllowHead = PR_TRUE; + } + } + } + return NS_OK; +} + +NS_IMETHODIMP +nsURIChecker::AsyncCheck(nsIRequestObserver *aObserver, + nsISupports *aObserverContext) +{ + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); + // Hook us up to listen to redirects and the like (this creates a reference // cycle!) mChannel->SetNotificationCallbacks(this); // and start the request: - rv = mChannel->AsyncOpen(this, nsnull); - - // break cycle if we fail to open the channel. + nsresult rv = mChannel->AsyncOpen(this, nsnull); if (NS_FAILED(rv)) mChannel = nsnull; + else { + // ok, wait for OnStartRequest to fire. + mIsPending = PR_TRUE; + mObserver = aObserver; + mObserverContext = aObserverContext; + } return rv; } NS_IMETHODIMP -nsURIChecker::GetBaseRequest(nsIRequest** aRequest) +nsURIChecker::GetBaseChannel(nsIChannel **aChannel) { - if (!mChannel) { - NS_ASSERTION(aRequest, "null out param!"); - *aRequest = 0; - return NS_ERROR_NOT_INITIALIZED; - } - return CallQueryInterface(mChannel, aRequest); + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); + NS_ADDREF(*aChannel = mChannel); + return NS_OK; } -///////////////////////////////////////////////////// -// nsIRequest methods -// +//----------------------------------------------------------------------------- +// nsIRequest methods: +//----------------------------------------------------------------------------- + NS_IMETHODIMP nsURIChecker::GetName(nsACString &aName) { - if (!mChannel) - return NS_ERROR_NOT_INITIALIZED; - + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); return mChannel->GetName(aName); } @@ -179,180 +249,103 @@ nsURIChecker::IsPending(PRBool *aPendingRet) NS_IMETHODIMP nsURIChecker::GetStatus(nsresult* aStatusRet) { - NS_ENSURE_ARG(aStatusRet); *aStatusRet = mStatus; return NS_OK; } -NS_IMETHODIMP nsURIChecker::Cancel(nsresult status) +NS_IMETHODIMP +nsURIChecker::Cancel(nsresult status) { - if (!mChannel) - return NS_ERROR_NOT_INITIALIZED; - + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); return mChannel->Cancel(status); } -NS_IMETHODIMP nsURIChecker::Suspend() +NS_IMETHODIMP +nsURIChecker::Suspend() { - if (!mChannel) - return NS_ERROR_NOT_INITIALIZED; - + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); return mChannel->Suspend(); } -NS_IMETHODIMP nsURIChecker::Resume() +NS_IMETHODIMP +nsURIChecker::Resume() { - if (!mChannel) - return NS_ERROR_NOT_INITIALIZED; - + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); return mChannel->Resume(); } -NS_IMETHODIMP nsURIChecker::GetLoadGroup(nsILoadGroup **aLoadGroup) +NS_IMETHODIMP +nsURIChecker::GetLoadGroup(nsILoadGroup **aLoadGroup) { - if (!mChannel) { - NS_ASSERTION(aLoadGroup, "null out param!"); - *aLoadGroup = 0; - return NS_ERROR_NOT_INITIALIZED; - } + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); return mChannel->GetLoadGroup(aLoadGroup); } -NS_IMETHODIMP nsURIChecker::SetLoadGroup(nsILoadGroup *aLoadGroup) +NS_IMETHODIMP +nsURIChecker::SetLoadGroup(nsILoadGroup *aLoadGroup) { - if (!mChannel) - return NS_ERROR_NOT_INITIALIZED; - + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); return mChannel->SetLoadGroup(aLoadGroup); } -NS_IMETHODIMP nsURIChecker::GetLoadFlags(nsLoadFlags *aLoadFlags) +NS_IMETHODIMP +nsURIChecker::GetLoadFlags(nsLoadFlags *aLoadFlags) { - if (!mChannel) - return NS_ERROR_NOT_INITIALIZED; - + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); return mChannel->GetLoadFlags(aLoadFlags); } -NS_IMETHODIMP nsURIChecker::SetLoadFlags(nsLoadFlags aLoadFlags) +NS_IMETHODIMP +nsURIChecker::SetLoadFlags(nsLoadFlags aLoadFlags) { - if (!mChannel) - return NS_ERROR_NOT_INITIALIZED; - + NS_ENSURE_TRUE(mChannel, NS_ERROR_NOT_INITIALIZED); return mChannel->SetLoadFlags(aLoadFlags); } -///////////////////////////////////////////////////// +//----------------------------------------------------------------------------- // nsIStreamListener methods: -// +//----------------------------------------------------------------------------- + NS_IMETHODIMP nsURIChecker::OnStartRequest(nsIRequest *aRequest, nsISupports *aCtxt) { - if (!aRequest) - return NS_ERROR_INVALID_ARG; - if (!mChannel) - return NS_ERROR_NOT_INITIALIZED; + NS_ASSERTION(aRequest == mChannel, "unexpected request"); - nsresult status; - nsresult rv = aRequest->GetStatus(&status); - // DNS errors and other obvious problems will return failure status - if (NS_FAILED(rv) || NS_FAILED(status)) { - SetStatusAndCallBack(nsnull, NS_BINDING_FAILED); - return NS_OK; - } + nsresult rv = CheckStatus(); + if (rv != NS_BASE_STREAM_WOULD_BLOCK) + SetStatusAndCallBack(rv); - // If status is zero, it might still be an error if it's http: - // http has data even when there's an error like a 404. - nsCOMPtr httpChannel = do_QueryInterface(aRequest); - if (!httpChannel) { - SetStatusAndCallBack(aRequest, NS_BINDING_SUCCEEDED); - return NS_OK; - } - PRUint32 responseStatus; - rv = httpChannel->GetResponseStatus(&responseStatus); - if (NS_FAILED(rv)) { - SetStatusAndCallBack(aRequest, NS_BINDING_FAILED); - return NS_OK; - } - // If it's between 200-299, it's valid: - if (responseStatus / 100 == 2) { - SetStatusAndCallBack(aRequest, NS_BINDING_SUCCEEDED); - return NS_OK; - } - // If we got a 404 (not found), we need some extra checking: - // toplevel urls from Netscape Enterprise Server 3.6, - // like http://www.mozilla.org, generate a 404 - // and will have to be retried without the head. - if (responseStatus == 404) - { - // We don't want to read the actual data, so cancel now: - aRequest->Cancel(NS_BINDING_ABORTED); - - nsCAutoString server; - rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Server"), server); - if (NS_SUCCEEDED(rv)) { - if (server.Equals(NS_LITERAL_CSTRING("Netscape-Enterprise/3.6"), - nsCaseInsensitiveCStringComparator())) { - mStatus = NS_OK; - // Open a new channel for a real (not head) request: - nsCOMPtr ios (do_GetIOService(&rv)); - if (NS_FAILED(rv)) return rv; - if (!ios) return NS_ERROR_UNEXPECTED; - nsCOMPtr URI; - rv = mChannel->GetOriginalURI(getter_AddRefs(URI)); - if (NS_FAILED(rv)) return rv; - rv = ios->NewChannelFromURI(URI, getter_AddRefs(mChannel)); - if (NS_FAILED(rv)) return rv; - return mChannel->AsyncOpen(this, nsnull); - } - } - - // Else it was a normal 404, so return as expected - SetStatusAndCallBack(aRequest, NS_BINDING_FAILED); - return NS_OK; - } - - // If we get here, then it's an http channel, not a 100, 200 or 404. - // Treat it as an error. - SetStatusAndCallBack(aRequest, NS_BINDING_FAILED); - return NS_OK; + // cancel the request (we don't care to look at the data). + return NS_BINDING_ABORTED; } NS_IMETHODIMP nsURIChecker::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult statusCode) { - // break reference cycle between us and the channel (see comment in - // AsyncCheckURI) - mChannel = nsnull; - - // also a good idea to release our reference to the observer since it - // may be owning us as well. - mObserver = nsnull; + // NOTE: we may have kicked off a subsequent request, so we should not do + // any cleanup unless this request matches the one we are currently using. + if (mChannel == request) { + // break reference cycle between us and the channel (see comment in + // AsyncCheckURI) + mChannel = nsnull; + } return NS_OK; } -// OnDataAvailable shouldn't generally be called, -// since we use head requests whenever possible, -// but in practice we're seeing it every time. NS_IMETHODIMP nsURIChecker::OnDataAvailable(nsIRequest *aRequest, nsISupports *aCtxt, nsIInputStream *aInput, PRUint32 aOffset, PRUint32 aCount) { -#ifdef DEBUG_akkana - nsCAutoString name; - GetName(name); - printf("OnDataAvailable: %s\n", name.get()); -#endif - // If we've gotten here, something went wrong with the previous cancel, - // so return a failure code to cancel the request: + NS_NOTREACHED("nsURIChecker::OnDataAvailable"); return NS_BINDING_ABORTED; } -///////////////////////////////////////////////////// +//----------------------------------------------------------------------------- // nsIInterfaceRequestor methods: -// +//----------------------------------------------------------------------------- + NS_IMETHODIMP nsURIChecker::GetInterface(const nsIID & aIID, void **aResult) { @@ -364,9 +357,10 @@ nsURIChecker::GetInterface(const nsIID & aIID, void **aResult) return QueryInterface(aIID, aResult); } -///////////////////////////////////////////////////// +//----------------------------------------------------------------------------- // nsIHttpEventSink methods: -// +//----------------------------------------------------------------------------- + NS_IMETHODIMP nsURIChecker::OnRedirect(nsIHttpChannel *aHttpChannel, nsIChannel *aNewChannel) { diff --git a/mozilla/netwerk/base/src/nsURIChecker.h b/mozilla/netwerk/base/src/nsURIChecker.h index b0a40ded05a..2647dc5eb34 100644 --- a/mozilla/netwerk/base/src/nsURIChecker.h +++ b/mozilla/netwerk/base/src/nsURIChecker.h @@ -16,7 +16,7 @@ * * The Initial Developer of the Original Code is * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 + * Portions created by the Initial Developer are Copyright (C) 2001 * the Initial Developer. All Rights Reserved. * * Contributor(s): @@ -40,44 +40,43 @@ #define nsURIChecker_h__ #include "nsIURIChecker.h" -#include "nsIRequest.h" #include "nsIChannel.h" #include "nsIStreamListener.h" #include "nsIHttpEventSink.h" #include "nsIInterfaceRequestor.h" -#include "nsIURI.h" - #include "nsIIOService.h" +#include "nsIURI.h" #include "nsCOMPtr.h" -class nsURIChecker : public nsIURIChecker, public nsIRequest, - public nsIStreamListener, public nsIHttpEventSink, +//----------------------------------------------------------------------------- + +class nsURIChecker : public nsIURIChecker, + public nsIStreamListener, + public nsIHttpEventSink, public nsIInterfaceRequestor { public: nsURIChecker(); - virtual ~nsURIChecker(); + virtual ~nsURIChecker() {} NS_DECL_ISUPPORTS - NS_DECL_NSIURICHECKER - NS_DECL_NSIREQUEST - NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER NS_DECL_NSIHTTPEVENTSINK NS_DECL_NSIINTERFACEREQUESTOR protected: - nsresult mStatus; - PRBool mIsPending; - - nsCOMPtr mChannel; + nsCOMPtr mChannel; nsCOMPtr mObserver; - nsCOMPtr mCtxt; + nsCOMPtr mObserverContext; + nsresult mStatus; + PRPackedBool mIsPending; + PRPackedBool mAllowHead; - void SetStatusAndCallBack(nsIRequest* aRequest, nsresult aStatus); + void SetStatusAndCallBack(nsresult aStatus); + nsresult CheckStatus(); }; #endif // nsURIChecker_h__ diff --git a/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js b/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js index 9dc6ea852e6..4ec6111b359 100644 --- a/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js +++ b/mozilla/xpfe/communicator/resources/content/contentAreaUtils.js @@ -418,7 +418,8 @@ function nsHeaderSniffer(aURL, aCallback, aData) this.uri = makeURL(aURL); this.linkChecker = Components.classes["@mozilla.org/network/urichecker;1"] - .createInstance().QueryInterface(Components.interfaces.nsIURIChecker); + .createInstance(Components.interfaces.nsIURIChecker); + this.linkChecker.init(this.uri); var flags; if (aData.bypassCache) { @@ -426,8 +427,9 @@ function nsHeaderSniffer(aURL, aCallback, aData) } else { flags = Components.interfaces.nsIRequest.LOAD_FROM_CACHE; } + this.linkChecker.loadFlags = flags; - this.linkChecker.asyncCheckURI(aURL, this, null, flags); + this.linkChecker.asyncCheck(this, null); } nsHeaderSniffer.prototype = { @@ -485,7 +487,7 @@ nsHeaderSniffer.prototype = { try { if (aStatus == 0) { // NS_BINDING_SUCCEEDED, so there's something there var linkChecker = aRequest.QueryInterface(Components.interfaces.nsIURIChecker); - var channel = linkChecker.baseRequest.QueryInterface(Components.interfaces.nsIChannel); + var channel = linkChecker.baseChannel; this.contentType = channel.contentType; try { var httpChannel = channel.QueryInterface(Components.interfaces.nsIHttpChannel);