зеркало из https://github.com/mozilla/gecko-dev.git
bug #24711 (r=gagan). Changed cache channels to behave like transports rather than protocol channels...
This commit is contained in:
Родитель
a14179a92e
Коммит
7cf8d22c22
|
@ -91,7 +91,7 @@ nsHTTPChannel::nsHTTPChannel(nsIURI* i_URL,
|
|||
PRUint32 bufferMaxSize):
|
||||
mResponse(nsnull),
|
||||
mHandler(dont_QueryInterface(i_Handler)),
|
||||
mRawResponseListener(nsnull),
|
||||
mHTTPServerListener(nsnull),
|
||||
mResponseContext(nsnull),
|
||||
mOriginalURI(dont_QueryInterface(originalURI ? originalURI : i_URL)),
|
||||
mURI(dont_QueryInterface(i_URL)),
|
||||
|
@ -112,8 +112,14 @@ nsHTTPChannel::nsHTTPChannel(nsIURI* i_URL,
|
|||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("Creating nsHTTPChannel [this=%x].\n", this));
|
||||
#if defined(PR_LOGGING)
|
||||
nsXPIDLCString urlCString;
|
||||
mURI->GetSpec(getter_Copies(urlCString));
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_DEBUG,
|
||||
("Creating nsHTTPChannel [this=%x] for URI: %s.\n",
|
||||
this, (const char *)urlCString));
|
||||
#endif
|
||||
|
||||
mVerb = i_Verb;
|
||||
}
|
||||
|
@ -280,8 +286,12 @@ nsHTTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
|
|||
ReadFromCache(startPosition, readCount);
|
||||
} else if (mOpenObserver) {
|
||||
// we were AsyncOpen()'d
|
||||
NS_ASSERTION(mRawResponseListener, "our pointer to the response was never set");
|
||||
return mRawResponseListener->FireSingleOnData(listener, aContext);
|
||||
NS_ASSERTION(mHTTPServerListener, "ResponseListener was not set!.");
|
||||
if (mHTTPServerListener) {
|
||||
rv = mHTTPServerListener->FireSingleOnData(listener, aContext);
|
||||
} else {
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -873,47 +883,6 @@ nsHTTPChannel::CheckCache()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsCachedHTTPListener : public nsIStreamListener {
|
||||
public:
|
||||
nsCachedHTTPListener(nsIStreamListener *aListener, nsHTTPChannel* aChannel):
|
||||
mListener(aListener), mChannel(aChannel) {
|
||||
NS_INIT_REFCNT();
|
||||
NS_IF_ADDREF(mChannel);
|
||||
}
|
||||
|
||||
|
||||
virtual ~nsCachedHTTPListener() { NS_IF_RELEASE(mChannel); }
|
||||
|
||||
private:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD
|
||||
OnDataAvailable(nsIChannel *aChannel, nsISupports *aContext,
|
||||
nsIInputStream *aStream, PRUint32 aSourceOffset,
|
||||
PRUint32 aCount)
|
||||
{
|
||||
return mListener->OnDataAvailable(mChannel, aContext,
|
||||
aStream, aSourceOffset, aCount);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStartRequest(nsIChannel *aChannel, nsISupports *aContext) {
|
||||
return mListener->OnStartRequest(mChannel, aContext);
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
OnStopRequest(nsIChannel *aChannel, nsISupports *aContext,
|
||||
nsresult aStatus, const PRUnichar *aErrorMsg) {
|
||||
return mChannel->ResponseCompleted(nsnull, mListener, aStatus, aErrorMsg);
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
nsHTTPChannel* mChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsCachedHTTPListener, nsIStreamListener, nsIStreamObserver)
|
||||
|
||||
// If the data in the cache hasn't expired, then there's no need to
|
||||
// talk with the server, not even to do an if-modified-since. This
|
||||
|
@ -934,48 +903,52 @@ nsHTTPChannel::ReadFromCache(PRUint32 aStartPosition, PRInt32 aReadCount)
|
|||
if (!mResponseDataListener)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIChannel> cacheChannel;
|
||||
rv = mCacheEntry->NewChannel(mLoadGroup, this, getter_AddRefs(cacheChannel));
|
||||
#if defined(PR_LOGGING)
|
||||
nsresult log_rv;
|
||||
char *URLSpec;
|
||||
|
||||
log_rv = mURI->GetSpec(&URLSpec);
|
||||
if (NS_FAILED(log_rv)) {
|
||||
URLSpec = nsCRT::strdup("?");
|
||||
}
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("nsHTTPChannel::ReadFromCache [this=%x].\t"
|
||||
"Using cache copy for: %s\n",
|
||||
this, URLSpec));
|
||||
nsAllocator::Free(URLSpec);
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
// Create a cache transport to read the cached response...
|
||||
nsCOMPtr<nsIChannel> cacheTransport;
|
||||
rv = mCacheEntry->NewChannel(mLoadGroup, this, getter_AddRefs(cacheTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mRequest->SetTransport(cacheTransport);
|
||||
|
||||
// Fake it so that HTTP headers come from cached versions
|
||||
NS_IF_RELEASE(mResponse);
|
||||
mResponse = mCachedResponse;
|
||||
NS_ADDREF(mResponse);
|
||||
SetResponse(mCachedResponse);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> loadGroupListener = mResponseDataListener;
|
||||
if (mLoadGroup) {
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
|
||||
//
|
||||
// Create a load group "proxy" listener...
|
||||
//
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (NS_SUCCEEDED(rv) && factory) {
|
||||
factory->CreateLoadGroupListener(mResponseDataListener,
|
||||
getter_AddRefs(loadGroupListener));
|
||||
}
|
||||
}
|
||||
|
||||
// Create a listener that intercepts cache reads and fires off the appropriate
|
||||
// events such as OnHeadersAvailable
|
||||
nsCachedHTTPListener* listener;
|
||||
listener = new nsCachedHTTPListener(loadGroupListener, this);
|
||||
nsHTTPResponseListener* listener;
|
||||
listener = new nsHTTPCacheListener(this);
|
||||
if (!listener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(listener);
|
||||
|
||||
|
||||
listener->SetListener(mResponseDataListener);
|
||||
mConnected = PR_TRUE;
|
||||
|
||||
// Fire all the normal events for header arrival
|
||||
FinishedResponseHeaders();
|
||||
|
||||
// Pump the cache data downstream
|
||||
rv = cacheChannel->AsyncRead(aStartPosition, aReadCount,
|
||||
rv = cacheTransport->AsyncRead(aStartPosition, aReadCount,
|
||||
mResponseContext, listener);
|
||||
NS_RELEASE(listener);
|
||||
if (NS_FAILED(rv)) {
|
||||
ResponseCompleted(0, nsnull, rv, 0);
|
||||
ResponseCompleted(nsnull, rv, 0);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -1161,7 +1134,7 @@ nsHTTPChannel::Open(void)
|
|||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
// Unable to create a transport... End the request...
|
||||
(void) ResponseCompleted(nsnull, mResponseDataListener, rv, nsnull);
|
||||
(void) ResponseCompleted(mResponseDataListener, rv, nsnull);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1169,7 +1142,8 @@ nsHTTPChannel::Open(void)
|
|||
rv = transport->SetNotificationCallbacks(this);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Unable to create a transport... End the request...
|
||||
(void) ResponseCompleted(nsnull, mResponseDataListener, rv, nsnull);
|
||||
(void) ResponseCompleted(mResponseDataListener, rv, nsnull);
|
||||
(void) ReleaseTransport(transport);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1207,7 +1181,9 @@ nsHTTPChannel::Open(void)
|
|||
rv = pModules->GetNext(getter_AddRefs(supEntry)); // go around again
|
||||
}
|
||||
|
||||
rv = mRequest->WriteRequest(transport, (mProxy && *mProxy));
|
||||
mRequest->SetTransport(transport);
|
||||
|
||||
rv = mRequest->WriteRequest((mProxy && *mProxy));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mState = HS_WAITING_FOR_RESPONSE;
|
||||
|
@ -1324,8 +1300,7 @@ nsresult nsHTTPChannel::Redirect(const char *aNewLocation,
|
|||
}
|
||||
|
||||
|
||||
nsresult nsHTTPChannel::ResponseCompleted(nsIChannel* aTransport,
|
||||
nsIStreamListener *aListener,
|
||||
nsresult nsHTTPChannel::ResponseCompleted(nsIStreamListener *aListener,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg)
|
||||
{
|
||||
|
@ -1346,11 +1321,6 @@ nsresult nsHTTPChannel::ResponseCompleted(nsIChannel* aTransport,
|
|||
}
|
||||
}
|
||||
|
||||
// Release the transport...
|
||||
if (aTransport) {
|
||||
(void)mHandler->ReleaseTransport(aTransport);
|
||||
}
|
||||
|
||||
//
|
||||
// After the consumer has been notified, remove the channel from its
|
||||
// load group... This will trigger an OnStopRequest from the load group.
|
||||
|
@ -1378,6 +1348,17 @@ nsresult nsHTTPChannel::ResponseCompleted(nsIChannel* aTransport,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsHTTPChannel::ReleaseTransport(nsIChannel *aTransport)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
if (aTransport) {
|
||||
(void) mRequest->ReleaseTransport(aTransport);
|
||||
rv = mHandler->ReleaseTransport(aTransport);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsHTTPChannel::SetResponse(nsHTTPResponse* i_pResp)
|
||||
{
|
||||
NS_IF_RELEASE(mResponse);
|
||||
|
@ -1404,8 +1385,8 @@ nsresult nsHTTPChannel::Abort()
|
|||
// Disconnect the consumer from this response listener...
|
||||
// This allows the entity that follows to be discarded
|
||||
// without notifying the consumer...
|
||||
if (mRawResponseListener) {
|
||||
mRawResponseListener->Abort();
|
||||
if (mHTTPServerListener) {
|
||||
mHTTPServerListener->Abort();
|
||||
}
|
||||
|
||||
// Null out pointers that are no longer needed...
|
||||
|
@ -1687,21 +1668,8 @@ nsHTTPChannel::ProcessStatusCode(void)
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener = mResponseDataListener;
|
||||
if (mLoadGroup) {
|
||||
nsCOMPtr<nsILoadGroupListenerFactory> factory;
|
||||
|
||||
//
|
||||
// Create a load group "proxy" listener...
|
||||
//
|
||||
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
|
||||
if (NS_SUCCEEDED(rv) && factory) {
|
||||
factory->CreateLoadGroupListener(mResponseDataListener,
|
||||
getter_AddRefs(listener));
|
||||
}
|
||||
}
|
||||
|
||||
statusClass = statusCode / 100;
|
||||
|
||||
switch (statusClass) {
|
||||
//
|
||||
// Informational: 1xx
|
||||
|
@ -1744,10 +1712,11 @@ nsHTTPChannel::ProcessStatusCode(void)
|
|||
if (statusCode == 304) {
|
||||
rv = ProcessNotModifiedResponse(listener);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
break;
|
||||
}
|
||||
|
||||
// 300 (Multiple choices) or 301 (Redirect) results can be cached
|
||||
else if ((statusCode == 300) || (statusCode == 301)) {
|
||||
if ((statusCode == 300) || (statusCode == 301)) {
|
||||
nsCOMPtr<nsIStreamListener> listener2;
|
||||
CacheReceivedResponse(listener, getter_AddRefs(listener2));
|
||||
if (listener2) {
|
||||
|
@ -1792,8 +1761,8 @@ nsHTTPChannel::ProcessStatusCode(void)
|
|||
// If mResponseDataListener is null this means that the response has been
|
||||
// aborted... So, do not update the response listener because this
|
||||
// is being discarded...
|
||||
if (mResponseDataListener && mRawResponseListener) {
|
||||
mRawResponseListener->SetResponseDataListener(listener);
|
||||
if (mResponseDataListener && mHTTPServerListener) {
|
||||
mHTTPServerListener->SetListener(listener);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -1804,21 +1773,75 @@ nsHTTPChannel::ProcessNotModifiedResponse(nsIStreamListener *aListener)
|
|||
nsresult rv;
|
||||
NS_ASSERTION(!mCachedContentIsValid, "We should never have cached a 304 response");
|
||||
|
||||
// Abort the current response... This will disconnect the consumer from
|
||||
// the response listener... Thus allowing the entity that follows to
|
||||
// be discarded without notifying the consumer...
|
||||
Abort();
|
||||
#if defined(PR_LOGGING)
|
||||
nsresult log_rv;
|
||||
char *URLSpec;
|
||||
|
||||
log_rv = mURI->GetSpec(&URLSpec);
|
||||
if (NS_FAILED(log_rv)) {
|
||||
URLSpec = nsCRT::strdup("?");
|
||||
}
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("nsHTTPChannel::ProcessNotModifiedResponse [this=%x].\t"
|
||||
"Using cache copy for: %s\n",
|
||||
this, URLSpec));
|
||||
nsAllocator::Free(URLSpec);
|
||||
#endif /* PR_LOGGING */
|
||||
|
||||
// Orphan the current nsHTTPServerListener instance... It will be
|
||||
// replaced with a nsHTTPCacheListener instance.
|
||||
NS_ASSERTION(mHTTPServerListener, "No nsHTTPServerResponse available!");
|
||||
if (mHTTPServerListener) {
|
||||
mHTTPServerListener->Abort();
|
||||
}
|
||||
|
||||
// Update the cached headers with any more recent ones from the
|
||||
// server - see RFC2616 [13.5.3]
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
rv = mResponse->GetHeaderEnumerator(getter_AddRefs(enumerator));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mCachedResponse->UpdateHeaders(enumerator);
|
||||
|
||||
// Store the updated HTTP headers in the cache
|
||||
// XXX: Should the Expires value be recaluclated too?
|
||||
nsCString allHeaders;
|
||||
rv = mCachedResponse->EmitHeaders(allHeaders);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mCacheEntry->SetAnnotation("HTTP headers", allHeaders.Length()+1,
|
||||
allHeaders.GetBuffer());
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Fake it so that HTTP headers come from cached versions
|
||||
SetResponse(mCachedResponse);
|
||||
|
||||
// We don't set a load group for the cache channel because the HTTP
|
||||
// channel is handling the load group interactions
|
||||
nsCOMPtr<nsIChannel> cacheChannel;
|
||||
rv = mCacheEntry->NewChannel(mLoadGroup, this, getter_AddRefs(cacheChannel));
|
||||
// Create a cache transport to read the cached response...
|
||||
nsCOMPtr<nsIChannel> cacheTransport;
|
||||
rv = mCacheEntry->NewChannel(mLoadGroup, this, getter_AddRefs(cacheTransport));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return cacheChannel->AsyncRead(0, -1, mResponseContext, aListener);
|
||||
mRequest->SetTransport(cacheTransport);
|
||||
|
||||
// Create a new HTTPCacheListener...
|
||||
nsHTTPResponseListener *cacheListener;
|
||||
cacheListener = new nsHTTPCacheListener(this);
|
||||
if (!cacheListener) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_ADDREF(cacheListener);
|
||||
|
||||
cacheListener->SetListener(aListener);
|
||||
mResponseDataListener = aListener;
|
||||
|
||||
rv = cacheTransport->AsyncRead(0, -1, mResponseContext, cacheListener);
|
||||
if (NS_FAILED(rv)) {
|
||||
ResponseCompleted(cacheListener, rv, nsnull);
|
||||
}
|
||||
NS_RELEASE(cacheListener);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -94,10 +94,10 @@ public:
|
|||
nsresult Redirect(const char *aURL,
|
||||
nsIChannel **aResult);
|
||||
|
||||
nsresult ResponseCompleted(nsIChannel* aTransport,
|
||||
nsIStreamListener* aListener,
|
||||
nsresult ResponseCompleted(nsIStreamListener* aListener,
|
||||
nsresult aStatus,
|
||||
const PRUnichar* aMsg);
|
||||
nsresult ReleaseTransport(nsIChannel *aTransport);
|
||||
|
||||
nsresult SetResponse(nsHTTPResponse* i_pResp);
|
||||
nsresult GetResponseContext(nsISupports** aContext);
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
|
||||
nsHTTPHandler* mHandler;
|
||||
nsHTTPRequest* mRequest;
|
||||
nsHTTPResponseListener* mRawResponseListener;
|
||||
nsHTTPResponseListener* mHTTPServerListener;
|
||||
nsCOMPtr<nsISupports> mResponseContext;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -50,23 +50,25 @@ static NS_DEFINE_CID(kHTTPHandlerCID, NS_IHTTPHANDLER_CID);
|
|||
|
||||
extern nsresult DupString(char* *o_Dest, const char* i_Src);
|
||||
|
||||
nsHTTPRequest::nsHTTPRequest(nsIURI* i_URL, HTTPMethod i_Method,
|
||||
nsIChannel* i_Transport):
|
||||
nsHTTPRequest::nsHTTPRequest(nsIURI* i_URL, HTTPMethod i_Method):
|
||||
mMethod(i_Method),
|
||||
mVersion(HTTP_ONE_ZERO),
|
||||
mUsingProxy(PR_FALSE),
|
||||
mRequestSpec(0)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
NS_ASSERTION(i_URL, "No URL for the request!!");
|
||||
mURI = do_QueryInterface(i_URL);
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("Creating nsHTTPRequest [this=%x].\n", this));
|
||||
#if defined(PR_LOGGING)
|
||||
nsXPIDLCString urlCString;
|
||||
mURI->GetSpec(getter_Copies(urlCString));
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_DEBUG,
|
||||
("Creating nsHTTPRequest [this=%x] for URI: %s.\n",
|
||||
this, (const char *)urlCString));
|
||||
#endif
|
||||
|
||||
mTransport = i_Transport;
|
||||
|
||||
NS_ASSERTION(mURI, "No URI for the request!!");
|
||||
|
||||
nsXPIDLCString host;
|
||||
mURI->GetHost(getter_Copies(host));
|
||||
|
@ -143,7 +145,7 @@ nsHTTPRequest::~nsHTTPRequest()
|
|||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("Deleting nsHTTPRequest [this=%x].\n", this));
|
||||
|
||||
mTransport = null_nsCOMPtr();
|
||||
mTransport = 0;
|
||||
CRTFREEIF(mRequestSpec);
|
||||
}
|
||||
|
||||
|
@ -230,7 +232,7 @@ nsHTTPRequest::Resume(void)
|
|||
|
||||
// Finally our own methods...
|
||||
|
||||
nsresult nsHTTPRequest::WriteRequest(nsIChannel *aTransport, PRBool aIsProxied)
|
||||
nsresult nsHTTPRequest::WriteRequest(PRBool aIsProxied)
|
||||
{
|
||||
nsresult rv;
|
||||
if (!mURI) {
|
||||
|
@ -238,10 +240,7 @@ nsresult nsHTTPRequest::WriteRequest(nsIChannel *aTransport, PRBool aIsProxied)
|
|||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mTransport, "Transport being overwritten!");
|
||||
mTransport = aTransport;
|
||||
|
||||
mUsingProxy = aIsProxied;
|
||||
NS_ASSERTION(mTransport, "No transport has been set on this request.");
|
||||
|
||||
PRUint32 loadAttributes;
|
||||
mConnection->GetLoadAttributes(&loadAttributes);
|
||||
|
@ -287,7 +286,7 @@ nsresult nsHTTPRequest::WriteRequest(nsIChannel *aTransport, PRBool aIsProxied)
|
|||
mRequestBuffer.Append(mRequestSpec);
|
||||
else
|
||||
{
|
||||
if (mUsingProxy) {
|
||||
if (aIsProxied) {
|
||||
rv = mURI->GetSpec(getter_Copies(autoBuffer));
|
||||
} else {
|
||||
rv = mURI->GetPath(getter_Copies(autoBuffer));
|
||||
|
@ -372,7 +371,7 @@ nsresult nsHTTPRequest::WriteRequest(nsIChannel *aTransport, PRBool aIsProxied)
|
|||
//
|
||||
// Write the request to the server.
|
||||
//
|
||||
rv = aTransport->AsyncWrite(stream, 0, mRequestBuffer.Length(),
|
||||
rv = mTransport->AsyncWrite(stream, 0, mRequestBuffer.Length(),
|
||||
(nsISupports*)(nsIRequest*)mConnection, this);
|
||||
return rv;
|
||||
}
|
||||
|
@ -492,7 +491,7 @@ nsHTTPRequest::OnStopRequest(nsIChannel* channel, nsISupports* i_Context,
|
|||
"\tStatus: %x\n",
|
||||
this, iStatus));
|
||||
|
||||
nsHTTPResponseListener* pListener = new nsHTTPResponseListener(mConnection);
|
||||
nsHTTPResponseListener* pListener = new nsHTTPServerListener(mConnection);
|
||||
if (pListener) {
|
||||
NS_ADDREF(pListener);
|
||||
rv = mTransport->AsyncRead(0, -1, i_Context, pListener);
|
||||
|
@ -511,16 +510,24 @@ nsHTTPRequest::OnStopRequest(nsIChannel* channel, nsISupports* i_Context,
|
|||
"\tStatus: %x\n",
|
||||
this, iStatus));
|
||||
|
||||
rv = iStatus;
|
||||
}
|
||||
|
||||
//
|
||||
// An error occurred... Finish the transaction and notify the consumer
|
||||
// of the failure...
|
||||
//
|
||||
if (NS_FAILED(rv)) {
|
||||
// Notify the HTTPChannel that the request has finished
|
||||
nsCOMPtr<nsIStreamListener> consumer;
|
||||
|
||||
mConnection->GetResponseDataListener(getter_AddRefs(consumer));
|
||||
|
||||
mConnection->ResponseCompleted(mTransport, consumer, iStatus, i_Msg);
|
||||
mConnection->ResponseCompleted(consumer, rv, i_Msg);
|
||||
mConnection->ReleaseTransport(mTransport);
|
||||
|
||||
mTransport = null_nsCOMPtr();
|
||||
|
||||
rv = iStatus;
|
||||
NS_ASSERTION(!mTransport, "nsHTTRequest::ReleaseTransport() "
|
||||
"was not called!");
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -539,6 +546,19 @@ nsresult nsHTTPRequest::SetConnection(nsHTTPChannel* i_Connection)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsHTTPRequest::SetTransport(nsIChannel *aTransport)
|
||||
{
|
||||
mTransport = aTransport;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsHTTPRequest::ReleaseTransport(nsIChannel *aTransport)
|
||||
{
|
||||
if (aTransport == mTransport) {
|
||||
mTransport = 0;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsHTTPRequest::GetHeaderEnumerator(nsISimpleEnumerator** aResult)
|
||||
{
|
||||
|
|
|
@ -64,7 +64,7 @@ class nsHTTPRequest : public nsIStreamObserver,
|
|||
public:
|
||||
|
||||
// Constructor
|
||||
nsHTTPRequest(nsIURI* i_URL=0, HTTPMethod i_Method=HM_GET, nsIChannel* i_Tranport = nsnull);
|
||||
nsHTTPRequest(nsIURI* i_URL, HTTPMethod i_Method=HM_GET);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
@ -104,9 +104,11 @@ public:
|
|||
|
||||
nsresult SetConnection(nsHTTPChannel* i_Connection);
|
||||
|
||||
nsresult SetTransport(nsIChannel *aTransport);
|
||||
nsresult ReleaseTransport(nsIChannel *aTransport);
|
||||
|
||||
// Build the actual request string based on the settings.
|
||||
nsresult WriteRequest(nsIChannel *aChannel,
|
||||
PRBool aIsProxied = PR_FALSE);
|
||||
nsresult WriteRequest(PRBool aIsProxied = PR_FALSE);
|
||||
|
||||
nsresult GetPostDataStream(nsIInputStream* *aResult);
|
||||
nsresult SetPostDataStream(nsIInputStream* aStream);
|
||||
|
@ -145,7 +147,6 @@ protected:
|
|||
nsHTTPChannel* mConnection;
|
||||
|
||||
nsHTTPHeaderArray mHeaders;
|
||||
PRBool mUsingProxy;
|
||||
|
||||
nsCString mRequestBuffer;
|
||||
nsCOMPtr<nsIInputStream> mPostDataStream;
|
||||
|
|
|
@ -715,6 +715,8 @@ nsresult nsHTTPResponse::EmitHeaders(nsCString& aResponseBuffer)
|
|||
headerAtomRaw == nsHTTPAtoms::Trailer ||
|
||||
headerAtomRaw == nsHTTPAtoms::Transfer_Encoding ||
|
||||
headerAtomRaw == nsHTTPAtoms::Upgrade ||
|
||||
// XXX: This seems wrong. See RFC 2109 [4.3.2]
|
||||
// Should depend on Cache-control: no-cache="set-cookie"
|
||||
headerAtomRaw == nsHTTPAtoms::Set_Cookie)
|
||||
continue;
|
||||
|
||||
|
@ -753,3 +755,102 @@ nsresult nsHTTPResponse::ParseHeaders(nsCString& aAllHeaders)
|
|||
beginLineOffset = endLineOffset + 2; // Skip past CRLF
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// This routine is used to update the Response Headers after a 304
|
||||
// Response has been received.
|
||||
//
|
||||
// + The nsISimpleEnumerator contains the response headers from the
|
||||
// 304 response.
|
||||
// + These headers replace the cached headers. See RFC 2616 [13.5.3]
|
||||
// + Wacky headers which are send by certain servers are also ignored.
|
||||
//
|
||||
nsresult nsHTTPResponse::UpdateHeaders(nsISimpleEnumerator *aEnumerator)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
PRBool bMoreHeaders = PR_FALSE;
|
||||
nsCOMPtr<nsISupports> item;
|
||||
nsCOMPtr<nsIHTTPHeader> header;
|
||||
nsCOMPtr<nsIAtom> headerAtom;
|
||||
nsXPIDLCString headerValue;
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_DEBUG,
|
||||
("nsHTTPResponse::UpdateHeaders [this=%x].\n", this));
|
||||
|
||||
rv = aEnumerator->HasMoreElements(&bMoreHeaders);
|
||||
|
||||
while (NS_SUCCEEDED(rv) && bMoreHeaders) {
|
||||
rv = aEnumerator->GetNext(getter_AddRefs(item));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
header = do_QueryInterface(item, &rv);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Bad HTTP header.");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = header->GetField(getter_AddRefs(headerAtom));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsIAtom *atom = headerAtom;
|
||||
// Ignore any hop-by-hop headers...
|
||||
if (atom == nsHTTPAtoms::Connection ||
|
||||
atom == nsHTTPAtoms::Keep_Alive ||
|
||||
atom == nsHTTPAtoms::Proxy_Authenticate ||
|
||||
atom == nsHTTPAtoms::Proxy_Authorization ||
|
||||
atom == nsHTTPAtoms::TE ||
|
||||
atom == nsHTTPAtoms::Trailer ||
|
||||
atom == nsHTTPAtoms::Transfer_Encoding ||
|
||||
atom == nsHTTPAtoms::Upgrade ||
|
||||
// Ignore any non-modifiable headers
|
||||
atom == nsHTTPAtoms::Content_Location ||
|
||||
atom == nsHTTPAtoms::Content_MD5 ||
|
||||
atom == nsHTTPAtoms::ETag ||
|
||||
atom == nsHTTPAtoms::Last_Modified ||
|
||||
// Assume Cache-Control: "no-transform"
|
||||
atom == nsHTTPAtoms::Content_Encoding ||
|
||||
atom == nsHTTPAtoms::Content_Range ||
|
||||
atom == nsHTTPAtoms::Content_Type ||
|
||||
// Ignore wacky headers too...
|
||||
// This one is for MS Servers that send a Content-Length:0
|
||||
// on 304 responses...
|
||||
atom == nsHTTPAtoms::Content_Length) {
|
||||
#if defined(PR_LOGGING)
|
||||
nsCAutoString nameBuffer;
|
||||
const PRUnichar *name = nsnull;
|
||||
|
||||
// Convert the atom name from unicode to ascii...
|
||||
atom->GetUnicode(&name);
|
||||
nameBuffer.Assign(name);
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("\tUpdateHeaders [this=%x]."
|
||||
"\tIgnoring response header: \'%s\'\n",
|
||||
this, nameBuffer.GetBuffer()));
|
||||
#endif /* PR_LOGGING */
|
||||
} else {
|
||||
// Delete the current header value (if any)...
|
||||
mHeaders.SetHeader(headerAtom, nsnull);
|
||||
|
||||
// Copy the new header value...
|
||||
rv = header->GetValue(getter_Copies(headerValue));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mHeaders.SetHeader(headerAtom, headerValue);
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
nsCAutoString nameBuffer;
|
||||
const PRUnichar *name = nsnull;
|
||||
|
||||
atom->GetUnicode(&name);
|
||||
nameBuffer.Assign(name);
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("\tUpdateHeaders [this=%x].\tNew response header: \'%s: %s\'\n",
|
||||
this, nameBuffer.GetBuffer(), (const char*)headerValue));
|
||||
#endif /* PR_LOGGING */
|
||||
}
|
||||
}
|
||||
rv = aEnumerator->HasMoreElements(&bMoreHeaders);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,9 @@ public:
|
|||
nsresult ParseHeaders(nsCString& aAllHeaders);
|
||||
nsresult ProcessHeader(nsIAtom* aHeader, nsCString& aValue);
|
||||
nsresult EmitHeaders(nsCString& aResult);
|
||||
|
||||
|
||||
nsresult UpdateHeaders(nsISimpleEnumerator *aEnumerator);
|
||||
|
||||
PRBool IsStale(PRBool aUseHeuristicExpiration);
|
||||
nsresult ParseDateHeader(nsIAtom *aAtom, PRTime *aResultTime, PRBool *aHeaderIsPresent);
|
||||
|
||||
|
|
|
@ -55,35 +55,52 @@ extern PRLogModuleInfo* gHTTPLog;
|
|||
static const int kMAX_HEADER_SIZE = 60000;
|
||||
|
||||
|
||||
nsHTTPResponseListener::nsHTTPResponseListener(nsHTTPChannel* aConnection):
|
||||
mResponse(nsnull),
|
||||
mFirstLineParsed(PR_FALSE),
|
||||
mHeadersDone(PR_FALSE),
|
||||
mBytesReceived(0)
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// nsHTTPResponseListener Implementation (abstract base class)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
nsHTTPResponseListener::nsHTTPResponseListener(nsHTTPChannel *aChannel)
|
||||
: mChannel(aChannel)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
NS_ASSERTION(aConnection, "HTTPChannel is null.");
|
||||
mChannel = aConnection;
|
||||
NS_ADDREF(mChannel);
|
||||
mChannel->mRawResponseListener = this;
|
||||
// mChannel is not an interface pointer, so COMPtrs cannot be used :-(
|
||||
NS_ASSERTION(aChannel, "HTTPChannel is null.");
|
||||
NS_ADDREF(mChannel);
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
nsCOMPtr<nsIURI> url;
|
||||
nsXPIDLCString urlCString;
|
||||
|
||||
aChannel->GetURI(getter_AddRefs(url));
|
||||
if (url) {
|
||||
url->GetSpec(getter_Copies(urlCString));
|
||||
}
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_DEBUG,
|
||||
("Creating nsHTTPResponseListener [this=%x] for URI: %s.\n",
|
||||
this, (const char *)urlCString));
|
||||
#endif
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("Creating nsHTTPResponseListener [this=%x].\n", this));
|
||||
|
||||
}
|
||||
|
||||
nsHTTPResponseListener::~nsHTTPResponseListener()
|
||||
{
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("Deleting nsHTTPResponseListener [this=%x].\n", this));
|
||||
|
||||
// These two should go away in the OnStopRequest() callback.
|
||||
// But, just in case...
|
||||
NS_IF_RELEASE(mChannel);
|
||||
NS_IF_RELEASE(mResponse);
|
||||
// mChannel is not an interface pointer, so COMPtrs cannot be used :-(
|
||||
NS_IF_RELEASE(mChannel);
|
||||
}
|
||||
|
||||
|
||||
void nsHTTPResponseListener::SetListener(nsIStreamListener *aListener)
|
||||
{
|
||||
mResponseDataListener = aListener;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports methods:
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsHTTPResponseListener)
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsHTTPResponseListener)
|
||||
|
||||
|
@ -91,6 +108,135 @@ NS_IMPL_QUERY_INTERFACE2(nsHTTPResponseListener,
|
|||
nsIStreamListener,
|
||||
nsIStreamObserver);
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// nsHTTPCacheListener Implementation
|
||||
//
|
||||
// This subclass of nsHTTPResponseListener processes responses from
|
||||
// the cache.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
nsHTTPCacheListener::nsHTTPCacheListener(nsHTTPChannel* aChannel)
|
||||
: nsHTTPResponseListener(aChannel)
|
||||
{
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("Creating nsHTTPCacheListener [this=%x].\n", this));
|
||||
|
||||
}
|
||||
|
||||
nsHTTPCacheListener::~nsHTTPCacheListener()
|
||||
{
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("Deleting nsHTTPCacheListener [this=%x].\n", this));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIStreamObserver methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPCacheListener::OnStartRequest(nsIChannel *aChannel,
|
||||
nsISupports *aContext)
|
||||
{
|
||||
PR_LOG(gHTTPLog, PR_LOG_DEBUG,
|
||||
("nsHTTPCacheListener::OnStartRequest [this=%x].\n",
|
||||
this));
|
||||
|
||||
return mResponseDataListener->OnStartRequest(mChannel, aContext);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPCacheListener::OnStopRequest(nsIChannel *aChannel,
|
||||
nsISupports *aContext,
|
||||
nsresult aStatus,
|
||||
const PRUnichar *aErrorMsg)
|
||||
{
|
||||
PR_LOG(gHTTPLog, PR_LOG_DEBUG,
|
||||
("nsHTTPCacheListener::OnStopRequest [this=%x]."
|
||||
"\tStatus = %x\n", this, aStatus));
|
||||
|
||||
//
|
||||
// Notify the channel that the response has finished. Since there
|
||||
// is no socket transport involved nsnull is passed as the
|
||||
// transport...
|
||||
//
|
||||
return mChannel->ResponseCompleted(mResponseDataListener,
|
||||
aStatus,
|
||||
aErrorMsg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIStreamListener methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPCacheListener::OnDataAvailable(nsIChannel *aChannel,
|
||||
nsISupports *aContext,
|
||||
nsIInputStream *aStream,
|
||||
PRUint32 aSourceOffset,
|
||||
PRUint32 aCount)
|
||||
{
|
||||
return mResponseDataListener->OnDataAvailable(mChannel,
|
||||
aContext,
|
||||
aStream,
|
||||
aSourceOffset,
|
||||
aCount);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTTPResponseListener methods:
|
||||
|
||||
nsresult
|
||||
nsHTTPCacheListener::FireSingleOnData(nsIStreamListener *aListener,
|
||||
nsISupports *aContext)
|
||||
{
|
||||
NS_ASSERTION(0, "nsHTTPCacheListener::FireSingleOnData(...) "
|
||||
"should never be called.");
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsHTTPCacheListener::Abort()
|
||||
{
|
||||
NS_ASSERTION(0, "nsHTTPCachedResponseListener::Abort() "
|
||||
"should never be called.");
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// nsHTTPServerListener Implementation
|
||||
//
|
||||
// This subclass of nsHTTPResponseListener processes responses from
|
||||
// HTTP servers.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTTPServerListener::nsHTTPServerListener(nsHTTPChannel* aChannel)
|
||||
: nsHTTPResponseListener(aChannel),
|
||||
mResponse(nsnull),
|
||||
mFirstLineParsed(PR_FALSE),
|
||||
mHeadersDone(PR_FALSE),
|
||||
mBytesReceived(0)
|
||||
{
|
||||
mChannel->mHTTPServerListener = this;
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("Creating nsHTTPServerListener [this=%x].\n", this));
|
||||
}
|
||||
|
||||
nsHTTPServerListener::~nsHTTPServerListener()
|
||||
{
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("Deleting nsHTTPServerListener [this=%x].\n", this));
|
||||
|
||||
// These two should go away in the OnStopRequest() callback.
|
||||
// But, just in case...
|
||||
NS_IF_RELEASE(mResponse);
|
||||
}
|
||||
|
||||
static NS_DEFINE_IID(kProxyObjectManagerIID, NS_IPROXYEVENT_MANAGER_IID);
|
||||
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kNetModuleMgrCID, NS_NETMODULEMGR_CID);
|
||||
|
@ -99,11 +245,11 @@ static NS_DEFINE_CID(kNetModuleMgrCID, NS_NETMODULEMGR_CID);
|
|||
// nsIStreamListener methods:
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPResponseListener::OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *i_pStream,
|
||||
PRUint32 i_SourceOffset,
|
||||
PRUint32 i_Length)
|
||||
nsHTTPServerListener::OnDataAvailable(nsIChannel* channel,
|
||||
nsISupports* context,
|
||||
nsIInputStream *i_pStream,
|
||||
PRUint32 i_SourceOffset,
|
||||
PRUint32 i_Length)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRUint32 actualBytesRead;
|
||||
|
@ -111,7 +257,7 @@ nsHTTPResponseListener::OnDataAvailable(nsIChannel* channel,
|
|||
nsCOMPtr<nsIBufferInputStream> bufferInStream = do_QueryInterface(i_pStream);
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("nsHTTPResponseListener::OnDataAvailable [this=%x].\n"
|
||||
("nsHTTPServerListener::OnDataAvailable [this=%x].\n"
|
||||
"\tstream=%x. \toffset=%d. \tlength=%d.\n",
|
||||
this, i_pStream, i_SourceOffset, i_Length));
|
||||
|
||||
|
@ -211,10 +357,10 @@ nsHTTPResponseListener::OnDataAvailable(nsIChannel* channel,
|
|||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPResponseListener::OnStartRequest(nsIChannel* channel, nsISupports* i_pContext)
|
||||
nsHTTPServerListener::OnStartRequest(nsIChannel* channel, nsISupports* i_pContext)
|
||||
{
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("nsHTTPResponseListener::OnStartRequest [this=%x].\n", this));
|
||||
("nsHTTPServerListener::OnStartRequest [this=%x].\n", this));
|
||||
|
||||
// Initialize header varaibles...
|
||||
mHeadersDone = PR_FALSE;
|
||||
|
@ -224,15 +370,15 @@ nsHTTPResponseListener::OnStartRequest(nsIChannel* channel, nsISupports* i_pCont
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTTPResponseListener::OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* i_pContext,
|
||||
nsresult i_Status,
|
||||
const PRUnichar* i_pMsg)
|
||||
nsHTTPServerListener::OnStopRequest(nsIChannel* channel,
|
||||
nsISupports* i_pContext,
|
||||
nsresult i_Status,
|
||||
const PRUnichar* i_pMsg)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("nsHTTPResponseListener::OnStopRequest [this=%x]."
|
||||
("nsHTTPServerListener::OnStopRequest [this=%x]."
|
||||
"\tStatus = %x\n", this, i_Status));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !mHeadersDone) {
|
||||
|
@ -253,11 +399,23 @@ nsHTTPResponseListener::OnStopRequest(nsIChannel* channel,
|
|||
// Notify the HTTPChannel that the response has completed...
|
||||
NS_ASSERTION(mChannel, "HTTPChannel is null.");
|
||||
if (mChannel) {
|
||||
mChannel->ResponseCompleted(channel, mResponseDataListener,
|
||||
i_Status, i_pMsg);
|
||||
PRUint32 status = 0;
|
||||
|
||||
// The HTTPChannel is no longer needed...
|
||||
mChannel->mRawResponseListener = 0;
|
||||
if (mResponse) {
|
||||
mResponse->GetStatus(&status);
|
||||
}
|
||||
|
||||
if (status != 304) {
|
||||
mChannel->ResponseCompleted(mResponseDataListener,
|
||||
i_Status, i_pMsg);
|
||||
// The HTTPChannel no longer needs a reference to this object.
|
||||
mChannel->mHTTPServerListener = 0;
|
||||
} else {
|
||||
PR_LOG(gHTTPLog, PR_LOG_DEBUG,
|
||||
("nsHTTPServerListener::OnStopRequest [this=%x]. "
|
||||
"Discarding 304 response\n", this));
|
||||
}
|
||||
mChannel->ReleaseTransport(channel);
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(mChannel);
|
||||
|
@ -267,12 +425,12 @@ nsHTTPResponseListener::OnStopRequest(nsIChannel* channel,
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTTPResponseListener methods:
|
||||
// nsHTTPServerListener methods:
|
||||
|
||||
nsresult nsHTTPResponseListener::Abort()
|
||||
nsresult nsHTTPServerListener::Abort()
|
||||
{
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("nsHTTPResponseListener::Abort [this=%x].", this));
|
||||
("nsHTTPServerListener::Abort [this=%x].", this));
|
||||
|
||||
//
|
||||
// Clearing the data consumer will cause the response to abort. This
|
||||
|
@ -284,7 +442,7 @@ nsresult nsHTTPResponseListener::Abort()
|
|||
}
|
||||
|
||||
|
||||
nsresult nsHTTPResponseListener::FireSingleOnData(nsIStreamListener *aListener, nsISupports *aContext)
|
||||
nsresult nsHTTPServerListener::FireSingleOnData(nsIStreamListener *aListener, nsISupports *aContext)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
@ -318,9 +476,9 @@ nsWriteToString(void* closure,
|
|||
}
|
||||
|
||||
|
||||
nsresult nsHTTPResponseListener::ParseStatusLine(nsIBufferInputStream* in,
|
||||
PRUint32 aLength,
|
||||
PRUint32 *aBytesRead)
|
||||
nsresult nsHTTPServerListener::ParseStatusLine(nsIBufferInputStream* in,
|
||||
PRUint32 aLength,
|
||||
PRUint32 *aBytesRead)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -328,7 +486,7 @@ nsresult nsHTTPResponseListener::ParseStatusLine(nsIBufferInputStream* in,
|
|||
PRUint32 offsetOfEnd, totalBytesToRead, actualBytesRead;
|
||||
|
||||
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
|
||||
("nsHTTPResponseListener::ParseStatusLine [this=%x].\taLength=%d\n",
|
||||
("nsHTTPServerListener::ParseStatusLine [this=%x].\taLength=%d\n",
|
||||
this, aLength));
|
||||
|
||||
*aBytesRead = 0;
|
||||
|
@ -405,9 +563,9 @@ nsresult nsHTTPResponseListener::ParseStatusLine(nsIBufferInputStream* in,
|
|||
|
||||
|
||||
|
||||
nsresult nsHTTPResponseListener::ParseHTTPHeader(nsIBufferInputStream* in,
|
||||
PRUint32 aLength,
|
||||
PRUint32 *aBytesRead)
|
||||
nsresult nsHTTPServerListener::ParseHTTPHeader(nsIBufferInputStream* in,
|
||||
PRUint32 aLength,
|
||||
PRUint32 *aBytesRead)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -508,7 +666,7 @@ nsresult nsHTTPResponseListener::ParseHTTPHeader(nsIBufferInputStream* in,
|
|||
return mResponse->ParseHeader(mHeaderBuffer);
|
||||
}
|
||||
|
||||
nsresult nsHTTPResponseListener::FinishedResponseHeaders(void)
|
||||
nsresult nsHTTPServerListener::FinishedResponseHeaders(void)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
|
@ -529,3 +687,6 @@ nsresult nsHTTPResponseListener::FinishedResponseHeaders(void)
|
|||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -52,21 +52,48 @@ class nsHTTPChannel;
|
|||
*/
|
||||
class nsHTTPResponseListener : public nsIStreamListener
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
nsHTTPResponseListener(nsHTTPChannel* aConnection);
|
||||
virtual ~nsHTTPResponseListener();
|
||||
|
||||
// nsISupport methods...
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
|
||||
// abstract methods implemented by the various ResponseListener
|
||||
// subclasses...
|
||||
virtual nsresult FireSingleOnData(nsIStreamListener *aListener,
|
||||
nsISupports *aContext) = 0;
|
||||
virtual nsresult Abort() = 0;
|
||||
|
||||
void SetListener(nsIStreamListener *aListener);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIStreamListener> mResponseDataListener;
|
||||
nsHTTPChannel* mChannel;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This class pocesses responses from HTTP servers...
|
||||
*/
|
||||
class nsHTTPServerListener : public nsHTTPResponseListener
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
nsHTTPServerListener(nsHTTPChannel* aConnection);
|
||||
virtual ~nsHTTPServerListener();
|
||||
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
nsresult FireSingleOnData(nsIStreamListener *aListener, nsISupports *aContext);
|
||||
nsresult Abort();
|
||||
void SetResponseDataListener(nsIStreamListener *aListener) {
|
||||
mResponseDataListener = aListener;
|
||||
}
|
||||
virtual nsresult FireSingleOnData(nsIStreamListener *aListener,
|
||||
nsISupports *aContext);
|
||||
virtual nsresult Abort();
|
||||
|
||||
nsresult Discard304Response(void);
|
||||
|
||||
|
||||
protected:
|
||||
// nsHTTPResponseListener methods...
|
||||
|
@ -80,15 +107,35 @@ protected:
|
|||
PRUint32* aBytesRead);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIStreamListener> mResponseDataListener;
|
||||
nsCString mHeaderBuffer;
|
||||
nsHTTPChannel* mChannel;
|
||||
nsHTTPResponse* mResponse;
|
||||
PRBool mFirstLineParsed;
|
||||
PRBool mHeadersDone;
|
||||
PRBool mFirstLineParsed;
|
||||
PRBool mHeadersDone;
|
||||
|
||||
nsCOMPtr<nsIInputStream> mDataStream;
|
||||
PRUint32 mBytesReceived;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This class processes responses from the cache...
|
||||
*/
|
||||
class nsHTTPCacheListener : public nsHTTPResponseListener
|
||||
{
|
||||
public:
|
||||
nsHTTPCacheListener(nsHTTPChannel* aChannel);
|
||||
virtual ~nsHTTPCacheListener();
|
||||
|
||||
// nsIStreamObserver methods...
|
||||
NS_DECL_NSISTREAMOBSERVER
|
||||
|
||||
// nsIStreamListener methods...
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
|
||||
virtual nsresult FireSingleOnData(nsIStreamListener *aListener,
|
||||
nsISupports *aContext);
|
||||
virtual nsresult Abort();
|
||||
};
|
||||
|
||||
|
||||
#endif /* _nsHTTPResponseListener_h_ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче