diff --git a/netwerk/protocol/http/src/nsHTTPChannel.cpp b/netwerk/protocol/http/src/nsHTTPChannel.cpp index cbbac6e3aca..d0c93b18f47 100644 --- a/netwerk/protocol/http/src/nsHTTPChannel.cpp +++ b/netwerk/protocol/http/src/nsHTTPChannel.cpp @@ -91,6 +91,7 @@ nsHTTPChannel::nsHTTPChannel(nsIURI* i_URL, nsHTTPHandler* i_Handler): mCachedContentIsValid(PR_FALSE), mFiredOnHeadersAvailable(PR_FALSE), mFiredOpenOnStartRequest(PR_FALSE), + mFiredOpenOnStopRequest (PR_FALSE), mAuthTriedWithPrehost(PR_FALSE), mProxy(0), mProxyPort(-1), @@ -98,7 +99,8 @@ nsHTTPChannel::nsHTTPChannel(nsIURI* i_URL, nsHTTPHandler* i_Handler): mBufferMaxSize(0), mStatus(NS_OK), mPipeliningAllowed (PR_TRUE), - mPipelinedRequest (nsnull) + mPipelinedRequest (nsnull), + mFinalListener (nsnull) { NS_INIT_REFCNT(); @@ -174,7 +176,17 @@ nsHTTPChannel::Cancel(nsresult status) rv = mHandler->CancelPendingChannel(this); } mStatus = status; - return mRequest->Cancel(status); + rv = mRequest->Cancel(status); + + if (mResponseDataListener) + mFinalListener -> FireNotifications (); + + if (mOpenObserver && !mFiredOpenOnStopRequest) + { + mFiredOpenOnStopRequest = PR_TRUE; + mOpenObserver->OnStopRequest(this, mOpenContext, status, nsnull); + } + return rv; } NS_IMETHODIMP @@ -228,9 +240,15 @@ nsHTTPChannel::OpenInputStream(nsIInputStream **o_Stream) nsresult rv; if (mConnected) return NS_ERROR_ALREADY_CONNECTED; + nsCOMPtr listener; + rv = NS_NewSyncStreamListener(o_Stream, getter_AddRefs(mBufOutputStream), - getter_AddRefs(mResponseDataListener)); + getter_AddRefs(listener)); + + mFinalListener = new nsHTTPFinalListener (this, listener, nsnull); + mResponseDataListener = mFinalListener; + if (NS_FAILED(rv)) return rv; mBufOutputStream = 0; @@ -283,7 +301,14 @@ nsHTTPChannel::AsyncRead(nsIStreamListener *listener, nsISupports *aContext) return NS_ERROR_NULL_POINTER; } - mResponseDataListener = listener; + if (listener) + { + mFinalListener = new nsHTTPFinalListener (this, listener, aContext); + mResponseDataListener = mFinalListener; + } + else + mResponseDataListener = listener; + mResponseContext = aContext; if (!mOpenObserver) @@ -1570,8 +1595,11 @@ nsresult nsHTTPChannel::ResponseCompleted( // // Finally, notify the OpenObserver that the request has completed. // - if (mOpenObserver) + if (mOpenObserver && !mFiredOpenOnStopRequest) + { + mFiredOpenOnStopRequest = PR_TRUE; mOpenObserver->OnStopRequest(this, mOpenContext, aStatus, aMsg); + } // Null out pointers that are no longer needed... diff --git a/netwerk/protocol/http/src/nsHTTPChannel.h b/netwerk/protocol/http/src/nsHTTPChannel.h index a1acc060398..374130bb7ca 100644 --- a/netwerk/protocol/http/src/nsHTTPChannel.h +++ b/netwerk/protocol/http/src/nsHTTPChannel.h @@ -162,6 +162,7 @@ protected: // Called mOpenObserver->OnStartRequest PRBool mFiredOpenOnStartRequest; + PRBool mFiredOpenOnStopRequest; // Auth related stuff- /* @@ -183,6 +184,7 @@ protected: PRBool mPipeliningAllowed; nsHTTPPipelinedRequest* mPipelinedRequest; nsCOMPtr mSecurityInfo; + nsHTTPFinalListener* mFinalListener; }; #endif /* _nsHTTPChannel_h_ */ diff --git a/netwerk/protocol/http/src/nsHTTPHandler.h b/netwerk/protocol/http/src/nsHTTPHandler.h index 622e09d2356..d879bda1bad 100644 --- a/netwerk/protocol/http/src/nsHTTPHandler.h +++ b/netwerk/protocol/http/src/nsHTTPHandler.h @@ -61,9 +61,9 @@ class nsHTTPChannel; // because of HTTP/1.1 is default now #define DEFAULT_ALLOWED_CAPABILITIES (DEFAULT_PROXY_CAPABILITIES|DEFAULT_SERVER_CAPABILITIES) -#define DEFAULT_HTTP_REQUEST_TIMEOUT 30 +#define DEFAULT_HTTP_REQUEST_TIMEOUT 120 #define DEFAULT_HTTP_CONNECT_TIMEOUT 30 -#define DEFAULT_MAX_ALLOWED_KEEPALIVES 30 +#define DEFAULT_MAX_ALLOWED_KEEPALIVES 20 #define DEFAULT_MAX_ALLOWED_KEEPALIVES_PER_SERVER 8 typedef struct BrokenServersTable_s diff --git a/netwerk/protocol/http/src/nsHTTPResponseListener.cpp b/netwerk/protocol/http/src/nsHTTPResponseListener.cpp index 18b4ef3332c..e014ef09db6 100644 --- a/netwerk/protocol/http/src/nsHTTPResponseListener.cpp +++ b/netwerk/protocol/http/src/nsHTTPResponseListener.cpp @@ -190,6 +190,7 @@ nsHTTPCacheListener::OnDataAvailable(nsIChannel *aChannel, aSourceOffset, aCount); if (NS_FAILED(rv)) return rv; } + return rv; } //////////////////////////////////////////////////////////////////////////////// @@ -996,3 +997,124 @@ nsHTTPServerListener::FinishedResponseHeaders () return rv; } + +// ----------------------------------------------------------------------------- +// nsHTTPFinalListener + +//////////////////////////////////////////////////////////////////////////////// +// nsISupports methods: + +NS_IMPL_THREADSAFE_ADDREF (nsHTTPFinalListener) +NS_IMPL_THREADSAFE_RELEASE(nsHTTPFinalListener) + +NS_IMPL_QUERY_INTERFACE2 (nsHTTPFinalListener, + nsIStreamListener, + nsIStreamObserver); + +nsHTTPFinalListener::nsHTTPFinalListener( + nsHTTPChannel* aChannel, nsIStreamListener* aListener, nsISupports *aContext) + : + mOnStartFired (PR_FALSE), + mOnStopFired (PR_FALSE) + +{ + PR_LOG(gHTTPLog, PR_LOG_ALWAYS, + ("Creating nsHTTPFinalListener [this=%x].\n", this)); + + NS_INIT_REFCNT(); + + mChannel = aChannel; + aContext = aContext; + mListener = aListener; + +} + +nsHTTPFinalListener::~nsHTTPFinalListener() +{ + PR_LOG(gHTTPLog, PR_LOG_ALWAYS, + ("Deleting nsHTTPFinalListener [this=%x].\n", this)); +} + +//////////////////////////////////////////////////////////////////////////////// +// nsIStreamObserver methods: + +NS_IMETHODIMP +nsHTTPFinalListener::OnStartRequest(nsIChannel *aChannel, + nsISupports *aContext) +{ + PR_LOG (gHTTPLog, PR_LOG_DEBUG, + ("nsHTTPFinalListener::OnStartRequest [this=%x]" + ", mOnStartFired=%u\n", this, mOnStartFired)); + + if (mOnStartFired) + return NS_OK; + + mOnStartFired = PR_TRUE; + return mListener -> OnStartRequest (aChannel, aContext); +} + +NS_IMETHODIMP +nsHTTPFinalListener::OnStopRequest(nsIChannel *aChannel, + nsISupports *aContext, + nsresult aStatus, + const PRUnichar *aErrorMsg) +{ + PR_LOG (gHTTPLog, PR_LOG_DEBUG, + ("nsHTTPFinalListener::OnStopRequest [this=%x]" + ", mOnStopFired=%u\n", this, mOnStopFired)); + + if (mOnStopFired) + return NS_OK; + + PRUint32 status; + mChannel -> GetStatus (&status); + + if (NS_FAILED (status) && NS_SUCCEEDED (aStatus)) + aStatus = status; + + if (!mOnStartFired) + { +// mOnStartFired = PR_TRUE; +// mListener -> OnStartRequest (aChannel, aContext); + } + + mOnStopFired = PR_TRUE; + return mListener -> OnStopRequest (aChannel, aContext, aStatus, aErrorMsg); +} + +//////////////////////////////////////////////////////////////////////////////// +// nsIStreamListener methods: + +NS_IMETHODIMP +nsHTTPFinalListener::OnDataAvailable(nsIChannel *aChannel, + nsISupports *aContext, + nsIInputStream *aStream, + PRUint32 aSourceOffset, + PRUint32 aCount) +{ + PR_LOG (gHTTPLog, PR_LOG_DEBUG, + ("nsHTTPFinalListener::OnDataAvailable [this=%x]\n", + this)); + + PRUint32 status; + mChannel -> GetStatus (&status); + + if (NS_SUCCEEDED (status)) + return mListener -> OnDataAvailable (aChannel, aContext, + aStream, aSourceOffset, aCount); + + return NS_OK; +} + +void +nsHTTPFinalListener::FireNotifications () +{ + PR_LOG (gHTTPLog, PR_LOG_DEBUG, + ("nsHTTPFinalListener::FireNotifications [this=%x]\n", + this)); + +// OnStartRequest (mChannel, mContext); + OnStopRequest (mChannel, mContext, NS_OK, nsnull); +} + +// ----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/src/nsHTTPResponseListener.h b/netwerk/protocol/http/src/nsHTTPResponseListener.h index f4618121308..3eb7cea1e49 100644 --- a/netwerk/protocol/http/src/nsHTTPResponseListener.h +++ b/netwerk/protocol/http/src/nsHTTPResponseListener.h @@ -149,5 +149,36 @@ public: virtual nsresult Abort(); }; +/* + * This is a final listener which enforces OnStart/OnStop/etc. policies + */ +class nsHTTPFinalListener : public nsIStreamListener +{ +public: + nsHTTPFinalListener (nsHTTPChannel* aChannel, + nsIStreamListener *aListener, nsISupports* aContext); + + virtual ~nsHTTPFinalListener(); + + // nsISupport methods... + NS_DECL_ISUPPORTS + + // nsIStreamObserver methods... + NS_DECL_NSISTREAMOBSERVER + + // nsIStreamListener methods... + NS_DECL_NSISTREAMLISTENER + + void FireNotifications (); + +private: + nsHTTPChannel* mChannel; + nsCOMPtr mContext; + nsCOMPtr mListener; + + PRBool mOnStartFired; + PRBool mOnStopFired; +}; + #endif /* _nsHTTPResponseListener_h_ */