Http handler reorg to fix keep-alive raise condition and prepare for

pipeling changes. Also fix 32505, 31979. In case of a major bustage -
http11_reorg_point is the tag before the checkin; r=gagan, a=warren
This commit is contained in:
ruslan%netscape.com 2000-03-24 21:38:04 +00:00
Родитель b529051831
Коммит 77aabe9130
15 изменённых файлов: 498 добавлений и 335 удалений

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

@ -416,26 +416,6 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
// this is ugly, but so as this state machine. It's too late in doWrite to do anything; let
// me know if someone sees a better solution
if (mReuseCount > 0 && mReuseCount > mLastReuseCount
&& GetWriteType() != eSocketWrite_None)
{
PRBool isalive = PR_FALSE;
if (NS_SUCCEEDED (IsAlive (0, &isalive)) && !isalive)
{
if (mSocketFD)
{
PR_Close (mSocketFD);
mSocketFD = nsnull;
}
mCurrentState = eSocketState_WaitConnect;
mLastReuseCount = mReuseCount;
fireStatus (mCurrentState);
continue;
}
}
if (GetReadType() != eSocketRead_None) {
// Set the select flags for non-blocking reads...
mSelectFlags |= PR_POLL_READ;
@ -2113,7 +2093,7 @@ nsSocketTransport::IsAlive (PRUint32 seconds, PRBool *alive)
{
PRErrorCode code = PR_GetError ();
if (rval == 0 || code != PR_WOULD_BLOCK_ERROR)
if (rval < 0 && code != PR_WOULD_BLOCK_ERROR)
*alive = PR_FALSE;
}
}

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

@ -62,6 +62,7 @@ interface nsIHTTPProtocolHandler : nsIProtocolHandler
in unsigned long encodeFlags);
attribute string acceptLanguages;
attribute string acceptEncodings;
attribute unsigned long httpVersion;
/* i'll file a bug on the http guys to make nsAuthEngine scriptable
and then we can get rid of this no script code! */

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

@ -53,7 +53,6 @@
#include "nsIProxy.h"
#include "nsMimeTypes.h"
#include "nsIPrompt.h"
#include "nsISocketTransport.h"
// FIXME - Temporary include. Delete this when cache is enabled on all
// platforms
#include "nsIPref.h"
@ -92,7 +91,6 @@ nsHTTPChannel::nsHTTPChannel(nsIURI* i_URL,
mState(HS_IDLE),
mLoadAttributes(LOAD_NORMAL),
mLoadGroup(nsnull),
mTransport(nsnull),
mCachedResponse(nsnull),
mCachedContentIsAvailable(PR_FALSE),
mCachedContentIsValid(PR_FALSE),
@ -159,7 +157,7 @@ nsHTTPChannel::IsPending(PRBool *result)
}
NS_IMETHODIMP
nsHTTPChannel::Cancel(void)
nsHTTPChannel::Cancel (void)
{
nsresult rv;
@ -668,7 +666,7 @@ nsresult nsHTTPChannel::Init(nsILoadGroup *aLoadGroup)
Set up a request object - later set to a clone of a default
request from the handler. TODO
*/
mRequest = new nsHTTPRequest(mURI);
mRequest = new nsHTTPRequest(mURI, mHandler, mBufferSegmentSize, mBufferMaxSize);
if (!mRequest) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -942,7 +940,7 @@ nsHTTPChannel::ReadFromCache(PRUint32 aStartPosition, PRInt32 aReadCount)
// Create a listener that intercepts cache reads and fires off
// the appropriate events such as OnHeadersAvailable
nsHTTPResponseListener* listener;
listener = new nsHTTPCacheListener(this);
listener = new nsHTTPCacheListener(this, mHandler);
if (!listener)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(listener);
@ -1141,105 +1139,93 @@ nsHTTPChannel::Open(void)
}
}
rv = mHandler->RequestTransport(mURI, this,
mBufferSegmentSize, mBufferMaxSize,
getter_AddRefs(mTransport));
if (mState != HS_WAITING_FOR_OPEN)
{
// Check for any modules that want to set headers before we
// send out a request.
NS_WITH_SERVICE(nsINetModuleMgr, pNetModuleMgr, kNetModuleMgrCID, &rv);
if (NS_FAILED(rv)) return rv;
if (NS_ERROR_BUSY == rv) {
nsCOMPtr<nsISimpleEnumerator> pModules;
rv = pNetModuleMgr->EnumerateModules(
NS_NETWORK_MODULE_MANAGER_HTTP_REQUEST_PROGID,
getter_AddRefs(pModules));
if (NS_FAILED(rv)) return rv;
// Go through the external modules and notify each one.
nsCOMPtr<nsISupports> supEntry;
rv = pModules->GetNext(getter_AddRefs(supEntry));
while (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsINetModRegEntry> entry = do_QueryInterface(supEntry, &rv);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsINetNotify> syncNotifier;
entry->GetSyncProxy(getter_AddRefs(syncNotifier));
nsCOMPtr<nsIHTTPNotify> pNotify = do_QueryInterface(syncNotifier, &rv);
if (NS_SUCCEEDED(rv))
{
// send off the notification, and block.
// make the nsIHTTPNotify api call
pNotify->ModifyRequest((nsISupports*)(nsIRequest*)this);
// we could do something with the return code from the external
// module, but what????
}
rv = pModules->GetNext(getter_AddRefs(supEntry)); // go around again
}
// if using proxy...
nsXPIDLCString requestSpec;
rv = mRequest->GetOverrideRequestSpec(getter_Copies(requestSpec));
// no one has overwritten this value as yet...
if (!requestSpec && mProxy && *mProxy)
{
nsXPIDLCString strurl;
if(NS_SUCCEEDED(mURI->GetSpec(getter_Copies(strurl))))
mRequest->SetOverrideRequestSpec(strurl);
}
// Check to see if an authentication header is required
nsAuthEngine* pAuthEngine = nsnull;
if (NS_SUCCEEDED(mHandler->GetAuthEngine(&pAuthEngine)) && pAuthEngine)
{
nsXPIDLCString authStr;
if (NS_SUCCEEDED(pAuthEngine->GetAuthString(mURI,
getter_Copies(authStr))))
{
if (authStr && *authStr)
rv = mRequest->SetHeader(nsHTTPAtoms::Authorization, authStr);
}
if (mProxy && *mProxy)
{
nsXPIDLCString proxyAuthStr;
if (NS_SUCCEEDED(pAuthEngine->GetProxyAuthString(mProxy,
mProxyPort,
getter_Copies(proxyAuthStr))))
{
if (proxyAuthStr && *proxyAuthStr)
rv = mRequest->SetHeader(nsHTTPAtoms::Proxy_Authorization,
proxyAuthStr);
}
}
}
} /* WAITING_FOR_OPEN */
rv = mRequest -> WriteRequest ();
if (NS_ERROR_BUSY == rv)
{
mState = HS_WAITING_FOR_OPEN;
return NS_OK;
}
if (NS_FAILED(rv)) {
// Unable to create a transport... End the request...
(void) ResponseCompleted(mResponseDataListener, rv, nsnull);
return rv;
}
// pass ourself in to act as a proxy for progress callbacks
rv = mTransport->SetNotificationCallbacks(this);
if (NS_FAILED(rv)) {
// Unable to create a transport... End the request...
(void) ResponseCompleted(mResponseDataListener, rv, nsnull);
(void) ReleaseTransport(mTransport);
return rv;
}
// Check for any modules that want to set headers before we
// send out a request.
NS_WITH_SERVICE(nsINetModuleMgr, pNetModuleMgr, kNetModuleMgrCID, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsISimpleEnumerator> pModules;
rv = pNetModuleMgr->EnumerateModules(
NS_NETWORK_MODULE_MANAGER_HTTP_REQUEST_PROGID,
getter_AddRefs(pModules));
if (NS_FAILED(rv)) return rv;
// Go through the external modules and notify each one.
nsCOMPtr<nsISupports> supEntry;
rv = pModules->GetNext(getter_AddRefs(supEntry));
while (NS_SUCCEEDED(rv))
if (NS_FAILED(rv))
{
nsCOMPtr<nsINetModRegEntry> entry = do_QueryInterface(supEntry, &rv);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsINetNotify> syncNotifier;
entry->GetSyncProxy(getter_AddRefs(syncNotifier));
nsCOMPtr<nsIHTTPNotify> pNotify = do_QueryInterface(syncNotifier, &rv);
if (NS_SUCCEEDED(rv))
{
// send off the notification, and block.
// make the nsIHTTPNotify api call
pNotify->ModifyRequest((nsISupports*)(nsIRequest*)this);
// we could do something with the return code from the external
// module, but what????
}
rv = pModules->GetNext(getter_AddRefs(supEntry)); // go around again
ResponseCompleted (mResponseDataListener, rv, nsnull);
return rv;
}
mRequest->SetTransport(mTransport);
// if using proxy...
nsXPIDLCString requestSpec;
rv = mRequest->GetOverrideRequestSpec(getter_Copies(requestSpec));
// no one has overwritten this value as yet...
if (!requestSpec && mProxy && *mProxy)
{
nsXPIDLCString strurl;
if(NS_SUCCEEDED(mURI->GetSpec(getter_Copies(strurl))))
mRequest->SetOverrideRequestSpec(strurl);
}
// Check to see if an authentication header is required
nsAuthEngine* pAuthEngine = nsnull;
if (NS_SUCCEEDED(mHandler->GetAuthEngine(&pAuthEngine)) && pAuthEngine)
{
nsXPIDLCString authStr;
if (NS_SUCCEEDED(pAuthEngine->GetAuthString(mURI,
getter_Copies(authStr))))
{
if (authStr && *authStr)
rv = mRequest->SetHeader(nsHTTPAtoms::Authorization, authStr);
}
if (mProxy && *mProxy)
{
nsXPIDLCString proxyAuthStr;
if (NS_SUCCEEDED(pAuthEngine->GetProxyAuthString(mProxy,
mProxyPort,
getter_Copies(proxyAuthStr))))
{
if (proxyAuthStr && *proxyAuthStr)
rv = mRequest->SetHeader(nsHTTPAtoms::Proxy_Authorization,
proxyAuthStr);
}
}
}
rv = mRequest->WriteRequest();
if (NS_FAILED(rv)) return rv;
mState = HS_WAITING_FOR_RESPONSE;
mConnected = PR_TRUE;
@ -1404,17 +1390,6 @@ nsresult nsHTTPChannel::ResponseCompleted(nsIStreamListener *aListener,
return rv;
}
nsresult nsHTTPChannel::ReleaseTransport (nsIChannel *aTransport, PRBool keepAlive)
{
nsresult rv = NS_OK;
if (aTransport) {
(void) mRequest->ReleaseTransport (aTransport);
rv = mHandler->ReleaseTransport (aTransport, keepAlive);
}
return rv;
}
nsresult nsHTTPChannel::SetResponse(nsHTTPResponse* i_pResp)
{
NS_IF_RELEASE(mResponse);
@ -1859,7 +1834,7 @@ nsHTTPChannel::ProcessNotModifiedResponse(nsIStreamListener *aListener)
// Create a new HTTPCacheListener...
nsHTTPResponseListener *cacheListener;
cacheListener = new nsHTTPCacheListener(this);
cacheListener = new nsHTTPCacheListener(this, mHandler);
if (!cacheListener) {
return NS_ERROR_OUT_OF_MEMORY;
}
@ -2020,15 +1995,19 @@ nsHTTPChannel::GetUsingProxy(PRBool *aUsingProxy)
NS_IMETHODIMP
nsHTTPChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
nsHTTPChannel::GetSecurityInfo (nsISupports * *aSecurityInfo)
{
*aSecurityInfo = nsnull;
if (!aSecurityInfo)
return NS_ERROR_NULL_POINTER;
if (!mTransport)
return NS_OK;
return mTransport->GetSecurityInfo(aSecurityInfo);
nsIChannel * trans;
if (mRequest)
{
mRequest -> GetTransport (&trans);
if (trans)
return trans -> GetSecurityInfo (aSecurityInfo);
}
return NS_OK;
}

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

@ -98,7 +98,6 @@ public:
nsresult ResponseCompleted(nsIStreamListener* aListener,
nsresult aStatus,
const PRUnichar* aMsg);
nsresult ReleaseTransport (nsIChannel *aTransport, PRBool keepAlive = PR_FALSE);
nsresult SetResponse(nsHTTPResponse* i_pResp);
nsresult GetResponseContext(nsISupports** aContext);
@ -149,8 +148,6 @@ protected:
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsIChannel> mTransport;
// Cache-related members
nsCOMPtr<nsICachedNetData> mCacheEntry;
nsHTTPResponse* mCachedResponse;

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

@ -347,7 +347,7 @@ nsHTTPHandler::NewPostDataStream(PRBool isFile,
}
NS_IMETHODIMP
nsHTTPHandler::SetAcceptLanguages(const char* i_AcceptLanguages)
nsHTTPHandler::SetAcceptLanguages (const char* i_AcceptLanguages)
{
CRTFREEIF(mAcceptLanguages);
if (i_AcceptLanguages)
@ -359,7 +359,7 @@ nsHTTPHandler::SetAcceptLanguages(const char* i_AcceptLanguages)
}
NS_IMETHODIMP
nsHTTPHandler::GetAcceptLanguages(char* *o_AcceptLanguages)
nsHTTPHandler::GetAcceptLanguages (char* *o_AcceptLanguages)
{
if (!o_AcceptLanguages)
return NS_ERROR_NULL_POINTER;
@ -375,6 +375,36 @@ nsHTTPHandler::GetAcceptLanguages(char* *o_AcceptLanguages)
}
}
NS_IMETHODIMP
nsHTTPHandler::SetAcceptEncodings (const char* i_AcceptEncodings)
{
CRTFREEIF (mAcceptEncodings);
if (i_AcceptEncodings)
{
mAcceptEncodings = nsCRT::strdup (i_AcceptEncodings);
return (mAcceptEncodings == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
}
return NS_OK;
}
NS_IMETHODIMP
nsHTTPHandler::GetAcceptEncodings (char* *o_AcceptEncodings)
{
if (!o_AcceptEncodings)
return NS_ERROR_NULL_POINTER;
if (mAcceptEncodings)
{
*o_AcceptEncodings = nsCRT::strdup(mAcceptEncodings);
return (*o_AcceptEncodings == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK;
}
else
{
*o_AcceptEncodings = nsnull;
return NS_OK;
}
}
NS_IMETHODIMP
nsHTTPHandler::SetHttpVersion (unsigned int i_HttpVersion)
{
@ -596,6 +626,7 @@ nsHTTPHandler::SetMisc(const PRUnichar* aMisc)
nsHTTPHandler::nsHTTPHandler():
mAcceptLanguages(nsnull),
mAcceptEncodings(nsnull),
mHttpVersion(HTTP_ONE_ZERO),
mDoKeepAlive(PR_FALSE),
mKeepAliveTimeout(2*60),
@ -786,38 +817,20 @@ nsHTTPHandler::~nsHTTPHandler()
mPrefs->UnregisterCallback(NETWORK_PREFS,
HTTPPrefsCallback, (void*)this);
CRTFREEIF(mAcceptLanguages);
CRTFREEIF (mAcceptLanguages);
CRTFREEIF (mAcceptEncodings);
}
nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri,
nsHTTPChannel* i_Channel,
PRUint32 bufferSegmentSize,
PRUint32 bufferMaxSize,
nsIChannel** o_pTrans)
nsIChannel** o_pTrans,
PRUint32 flags)
{
nsresult rv;
PRUint32 count;
*o_pTrans = nsnull;
count = 0;
mTransportList->Count(&count);
if (count >= MAX_NUMBER_OF_OPEN_TRANSPORTS) {
// XXX this method incorrectly returns a bool
rv = mPendingChannelList->AppendElement(
(nsISupports*)(nsIRequest*)i_Channel)
? NS_OK : NS_ERROR_FAILURE;
NS_ASSERTION(NS_SUCCEEDED(rv), "AppendElement failed");
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("nsHTTPHandler::RequestTransport."
"\tAll socket transports are busy."
"\tAdding nsHTTPChannel [%x] to pending list.\n",
i_Channel));
return NS_ERROR_BUSY;
}
PRUint32 count = 0;
PRInt32 port;
nsXPIDLCString host;
@ -853,7 +866,7 @@ nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri,
// Check in the idle transports for a host/port match
count = 0;
PRInt32 index = 0;
if (mDoKeepAlive)
if (mDoKeepAlive && (flags & TRANSPORT_REUSE_ALIVE))
{
mIdleTransports -> Count (&count);
@ -914,16 +927,31 @@ nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri,
// if we didn't find any from the keep-alive idlelist
if (trans == nsnull)
{
if (! (flags & TRANSPORT_OPEN_ALWAYS) )
{
count = 0;
mTransportList -> Count (&count);
if (count >= MAX_NUMBER_OF_OPEN_TRANSPORTS)
{
// XXX this method incorrectly returns a bool
rv = mPendingChannelList -> AppendElement((nsISupports*)(nsIRequest*)i_Channel)
? NS_OK : NS_ERROR_FAILURE;
NS_ASSERTION (NS_SUCCEEDED(rv), "AppendElement failed");
PR_LOG (gHTTPLog, PR_LOG_ALWAYS,
("nsHTTPHandler::RequestTransport.""\tAll socket transports are busy."
"\tAdding nsHTTPChannel [%x] to pending list.\n",
i_Channel));
return NS_ERROR_BUSY;
}
}
if (usingProxy)
{
rv = CreateTransport(proxy, proxyPort, host,
bufferSegmentSize, bufferMaxSize, &trans);
}
rv = CreateTransport (proxy, proxyPort, host, bufferSegmentSize, bufferMaxSize, &trans);
else
{
rv = CreateTransport(host, port, host,
bufferSegmentSize, bufferMaxSize, &trans);
}
rv = CreateTransport (host, port, host, bufferSegmentSize, bufferMaxSize, &trans);
if (NS_FAILED(rv)) return rv;
}
@ -1173,6 +1201,12 @@ nsHTTPHandler::PrefsChanged(const char* pref)
if (NS_SUCCEEDED(rv))
SetAcceptLanguages(acceptLanguages);
}
nsXPIDLCString acceptEncodings;
rv = mPrefs -> CopyCharPref ("network.http.accept-encoding", getter_Copies (acceptEncodings));
if (NS_SUCCEEDED (rv))
SetAcceptEncodings (acceptEncodings);
}
PRInt32 PR_CALLBACK HTTPPrefsCallback(const char* pref, void* instance)

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

@ -49,6 +49,9 @@
class nsHashtable;
class nsHTTPChannel;
#define TRANSPORT_REUSE_ALIVE 1
#define TRANSPORT_OPEN_ALWAYS 2
class nsHTTPHandler : public nsIHTTPProtocolHandler
{
public:
@ -67,7 +70,7 @@ public:
nsHTTPChannel* i_Channel,
PRUint32 bufferSegmentSize,
PRUint32 bufferMaxSize,
nsIChannel** o_pTrans);
nsIChannel** o_pTrans, PRUint32 flags = TRANSPORT_REUSE_ALIVE);
/**
* Called to create a transport from RequestTransport to accually
@ -104,6 +107,7 @@ protected:
nsCOMPtr<nsISupportsArray> mIdleTransports;
char* mAcceptLanguages;
char* mAcceptEncodings;
PRUint32 mHttpVersion;
nsAuthEngine mAuthEngine;
PRBool mDoKeepAlive;

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

@ -99,13 +99,20 @@ nsHTTPHeaderArray::nsHTTPHeaderArray()
(void)NS_NewISupportsArray(getter_AddRefs(mHTTPHeaders));
}
void
nsHTTPHeaderArray::Clear ()
{
if (mHTTPHeaders)
mHTTPHeaders -> Clear ();
}
nsHTTPHeaderArray::~nsHTTPHeaderArray()
{
if (mHTTPHeaders) {
mHTTPHeaders->Clear();
}
mHTTPHeaders = null_nsCOMPtr();
if (mHTTPHeaders)
mHTTPHeaders -> Clear ();
mHTTPHeaders = null_nsCOMPtr ();
}

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

@ -60,6 +60,8 @@ public:
nsresult GetEnumerator(nsISimpleEnumerator** aResult);
static void GetStandardHeaderName(nsIAtom* aHeader, const char** aResult);
void Clear ();
protected:
PRInt32 GetEntry(nsIAtom* aHeader, nsHeaderEntry** aResult);
PRBool IsHeaderMultiple(nsIAtom* aHeader);
@ -80,7 +82,6 @@ public:
NS_IMETHOD HasMoreElements(PRBool* aResult);
NS_IMETHOD GetNext(nsISupports** aResult);
// Class methods:
nsHTTPHeaderEnumerator(nsISupportsArray* aHeaderArray);
virtual ~nsHTTPHeaderEnumerator();

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

@ -40,6 +40,7 @@
#include "nsIIOService.h"
#include "nsAuthEngine.h"
#include "nsIServiceManager.h"
#include "nsISocketTransport.h"
#include "plstr.h"
#if defined(PR_LOGGING)
@ -51,13 +52,18 @@ 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):
nsHTTPRequest::nsHTTPRequest(nsIURI* i_URL, nsHTTPHandler* i_Handler, PRUint32 bufferSegmentSize, PRUint32 bufferMaxSize, HTTPMethod i_Method)
:
mMethod(i_Method),
mVersion(HTTP_ONE_ZERO),
mRequestSpec(0),
mDoKeepAlive(PR_FALSE),
mKeepAliveTimeout (2*60)
{
mKeepAliveTimeout (2*60),
mBufferSegmentSize(bufferSegmentSize),
mBufferMaxSize(bufferMaxSize),
mAttempts (0),
mHandler (i_Handler)
{
NS_INIT_REFCNT();
NS_ASSERTION(i_URL, "No URL for the request!!");
@ -71,63 +77,10 @@ nsHTTPRequest::nsHTTPRequest(nsIURI* i_URL, HTTPMethod i_Method):
("Creating nsHTTPRequest [this=%x] for URI: %s.\n",
this, (const char *)urlCString));
#endif
nsXPIDLCString host;
mURI->GetHost(getter_Copies(host));
PRInt32 port = -1;
mURI->GetPort(&port);
// Send Host header by default
if (HTTP_ZERO_NINE != mVersion)
{
if (-1 != port)
{
char* tempHostPort =
PR_smprintf("%s:%d", (const char*)host, port);
if (tempHostPort)
{
SetHeader(nsHTTPAtoms::Host, tempHostPort);
PR_smprintf_free(tempHostPort);
tempHostPort = 0;
}
}
else
SetHeader(nsHTTPAtoms::Host, host);
}
// Add the user-agent
nsresult rv = NS_OK;
NS_WITH_SERVICE(nsIHTTPProtocolHandler, httpHandler,
kHTTPHandlerCID, &rv);
if (NS_FAILED(rv)) return;
nsXPIDLString ua;
if (NS_SUCCEEDED(httpHandler->GetUserAgent(getter_Copies(ua))))
{
nsCAutoString uaString((const PRUnichar*)ua);
SetHeader(nsHTTPAtoms::User_Agent, uaString.GetBuffer());
}
// Send */*. We're no longer chopping MIME-types for acceptance.
// MIME based content negotiation has died.
// SetHeader(nsHTTPAtoms::Accept, "image/gif, image/x-xbitmap, image/jpeg,
// image/pjpeg, image/png, */*");
SetHeader(nsHTTPAtoms::Accept, "*/*");
nsXPIDLCString acceptLanguages;
// Add the Accept-Language header
rv = httpHandler->GetAcceptLanguages(
getter_Copies(acceptLanguages));
if (NS_SUCCEEDED(rv))
{
if (acceptLanguages && *acceptLanguages)
SetHeader(nsHTTPAtoms::Accept_Language, acceptLanguages);
}
httpHandler -> GetHttpVersion ( &mVersion );
httpHandler -> GetDoKeepAlive (&mDoKeepAlive);
httpHandler -> GetKeepAliveTimeout (&mKeepAliveTimeout);
mHandler -> GetHttpVersion ( &mVersion );
mHandler -> GetDoKeepAlive (&mDoKeepAlive);
mHandler -> GetKeepAliveTimeout (&mKeepAliveTimeout);
}
@ -201,7 +154,7 @@ nsHTTPRequest::Resume(void)
// Finally our own methods...
nsresult nsHTTPRequest::WriteRequest()
nsresult nsHTTPRequest::WriteRequest ()
{
nsresult rv;
if (!mURI) {
@ -209,7 +162,22 @@ nsresult nsHTTPRequest::WriteRequest()
return NS_ERROR_NULL_POINTER;
}
NS_ASSERTION(mTransport, "No transport has been set on this request.");
if (mAttempts > 2)
return NS_ERROR_FAILURE;
rv = mHandler -> RequestTransport (mURI, mConnection, mBufferSegmentSize, mBufferMaxSize, getter_AddRefs (mTransport), mAttempts ? TRANSPORT_OPEN_ALWAYS : TRANSPORT_REUSE_ALIVE);
if (NS_FAILED (rv))
return rv;
rv = mTransport -> SetNotificationCallbacks (mConnection);
if (NS_FAILED (rv))
return rv;
mAttempts++;
formHeaders ();
PRUint32 loadAttributes;
mConnection->GetLoadAttributes(&loadAttributes);
@ -232,15 +200,6 @@ nsresult nsHTTPRequest::WriteRequest()
SetHeader(nsHTTPAtoms::Cache_Control, "max-age=0");
}
if (mDoKeepAlive)
{
char *p = PR_smprintf ("%d", mKeepAliveTimeout);
SetHeader (nsHTTPAtoms::Keep_Alive, p);
PR_smprintf_free (p);
}
//
// Build up the request into mRequestBuffer...
//
@ -257,7 +216,7 @@ nsresult nsHTTPRequest::WriteRequest()
//
// ie. Method SP Request-URI SP HTTP-Version CRLF
//
mRequestBuffer.Append(MethodToString(mMethod));
mRequestBuffer.Append (MethodToString (mMethod));
// Request spec gets set for proxied cases-
if (!mRequestSpec)
@ -305,7 +264,7 @@ nsresult nsHTTPRequest::WriteRequest()
// ie. field-name ":" [field-value] CRLF
//
nsCOMPtr<nsISimpleEnumerator> enumerator;
rv = mHeaders.GetEnumerator(getter_AddRefs(enumerator));
rv = mHeaders.GetEnumerator (getter_AddRefs (enumerator));
if (NS_SUCCEEDED(rv)) {
PRBool bMoreHeaders;
@ -403,12 +362,12 @@ nsresult nsHTTPRequest::GetPriority()
nsresult nsHTTPRequest::SetHeader(nsIAtom* i_Header, const char* i_Value)
{
return mHeaders.SetHeader(i_Header, i_Value);
return mHeaders.SetHeader (i_Header, i_Value);
}
nsresult nsHTTPRequest::GetHeader(nsIAtom* i_Header, char* *o_Value)
{
return mHeaders.GetHeader(i_Header, o_Value);
return mHeaders.GetHeader (i_Header, o_Value);
}
@ -459,57 +418,66 @@ nsHTTPRequest::OnStartRequest(nsIChannel* channel, nsISupports* i_Context)
}
NS_IMETHODIMP
nsHTTPRequest::OnStopRequest(nsIChannel* channel, nsISupports* i_Context,
nsresult iStatus,
const PRUnichar* i_Msg)
nsHTTPRequest::OnStopRequest (nsIChannel* channel, nsISupports* i_Context,
nsresult iStatus,
const PRUnichar* i_Msg)
{
nsresult rv = iStatus;
nsresult rv;
nsCOMPtr<nsISocketTransport> trans = do_QueryInterface (mTransport, &rv);
if (NS_SUCCEEDED(rv)) {
//
// Write the POST data out to the server...
//
if (mPostDataStream) {
NS_ASSERTION(mMethod == HM_POST, "Post data without a POST method?");
rv = iStatus;
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("nsHTTPRequest [this=%x]. Writing POST data to the server.\n",
this));
if (NS_SUCCEEDED (rv))
{
PRBool isAlive = PR_TRUE;
if (trans)
trans -> IsAlive (0, &isAlive);
rv = mTransport->AsyncWrite(mPostDataStream, 0, -1,
(nsISupports*)(nsIRequest*)mConnection, this);
if (isAlive)
{
//
// Write the POST data out to the server...
//
if (mPostDataStream)
{
NS_ASSERTION(mMethod == HM_POST, "Post data without a POST method?");
/* the mPostDataStream is released below... */
}
//
// Prepare to receive the response...
//
else {
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("nsHTTPRequest [this=%x]. Finished writing request to server."
"\tStatus: %x\n",
this, iStatus));
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("nsHTTPRequest [this=%x]. Writing POST data to the server.\n", this));
nsHTTPResponseListener* pListener =
new nsHTTPServerListener(mConnection);
if (pListener) {
NS_ADDREF(pListener);
rv = mTransport->AsyncRead(0, -1, i_Context, pListener);
NS_RELEASE(pListener);
} else {
rv = NS_ERROR_OUT_OF_MEMORY;
rv = mTransport -> AsyncWrite (mPostDataStream, 0, -1, (nsISupports*)(nsIRequest*)mConnection, this);
/* the mPostDataStream is released below... */
}
//
// Prepare to receive the response...
//
else
{
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("nsHTTPRequest [this=%x]. Finished writing request to server." "\tStatus: %x\n", this, iStatus));
nsHTTPResponseListener* pListener = new nsHTTPServerListener (mConnection, mHandler);
if (pListener)
{
NS_ADDREF (pListener);
rv = mTransport -> AsyncRead (0, -1, i_Context, pListener);
NS_RELEASE (pListener);
}
else
rv = NS_ERROR_OUT_OF_MEMORY;
}
}
}
}
else
rv = NS_ERROR_FAILURE; /* isAlive */
} /* NS_SUCCEEDED */
//
// An error occurred when trying to write the request to the server!
//
else {
PR_LOG(gHTTPLog, PR_LOG_ERROR,
("nsHTTPRequest [this=%x]. Error writing request to server."
"\tStatus: %x\n",
this, iStatus));
else
{
PR_LOG (gHTTPLog, PR_LOG_ERROR, ("nsHTTPRequest [this=%x]. Error writing request to server." "\tStatus: %x\n", this, iStatus));
rv = iStatus;
}
@ -517,23 +485,34 @@ nsHTTPRequest::OnStopRequest(nsIChannel* channel, nsISupports* i_Context,
// An error occurred... Finish the transaction and notify the consumer
// of the failure...
//
if (NS_FAILED(rv)) {
if (NS_FAILED (rv))
{
PRUint32 wasKeptAlive = 0;
if (trans)
trans -> GetReuseCount (&wasKeptAlive);
mHandler -> ReleaseTransport (mTransport, PR_FALSE);
if (wasKeptAlive)
{
rv = WriteRequest ();
if (NS_SUCCEEDED (rv))
return rv;
}
// Notify the HTTPChannel that the request has finished
nsCOMPtr<nsIStreamListener> consumer;
mConnection->GetResponseDataListener(getter_AddRefs(consumer));
mConnection->ResponseCompleted(consumer, rv, i_Msg);
mConnection->ReleaseTransport(mTransport);
NS_ASSERTION(!mTransport, "nsHTTRequest::ReleaseTransport() "
"was not called!");
mConnection -> GetResponseDataListener (getter_AddRefs (consumer));
mConnection -> ResponseCompleted (consumer, rv, i_Msg);
}
//
// These resouces are no longer needed...
//
mRequestBuffer.Truncate();
mRequestBuffer.Truncate ();
mPostDataStream = null_nsCOMPtr();
return rv;
@ -546,12 +525,18 @@ nsresult nsHTTPRequest::SetConnection(nsHTTPChannel* i_Connection)
return NS_OK;
}
nsresult nsHTTPRequest::SetTransport(nsIChannel *aTransport)
nsresult nsHTTPRequest::SetTransport (nsIChannel * aTransport)
{
mTransport = aTransport;
return NS_OK;
}
nsresult nsHTTPRequest::GetTransport (nsIChannel **aTransport)
{
*aTransport = mTransport;
return NS_OK;
}
/*
nsresult nsHTTPRequest::ReleaseTransport(nsIChannel *aTransport)
{
if (aTransport == mTransport.get()) {
@ -559,10 +544,10 @@ nsresult nsHTTPRequest::ReleaseTransport(nsIChannel *aTransport)
}
return NS_OK;
}
*/
nsresult nsHTTPRequest::GetHeaderEnumerator(nsISimpleEnumerator** aResult)
{
return mHeaders.GetEnumerator(aResult);
return mHeaders.GetEnumerator (aResult);
}
nsresult
@ -578,3 +563,82 @@ nsHTTPRequest::GetOverrideRequestSpec(char** o_Spec)
return DupString(o_Spec, mRequestSpec);
}
nsresult
nsHTTPRequest::formHeaders ()
{
nsXPIDLCString host;
mURI -> GetHost (getter_Copies (host));
PRInt32 port = -1;
mURI -> GetPort (&port);
mHeaders.Clear ();
// Send Host header by default
if (HTTP_ZERO_NINE != mVersion)
{
if (-1 != port)
{
char* tempHostPort =
PR_smprintf("%s:%d", (const char*)host, port);
if (tempHostPort)
{
SetHeader(nsHTTPAtoms::Host, tempHostPort);
PR_smprintf_free (tempHostPort);
tempHostPort = 0;
}
}
else
SetHeader(nsHTTPAtoms::Host, host);
}
// Add the user-agent
nsresult rv = NS_OK;
NS_WITH_SERVICE(nsIHTTPProtocolHandler, httpHandler, kHTTPHandlerCID, &rv);
if (NS_FAILED(rv)) return rv;
nsXPIDLString ua;
if (NS_SUCCEEDED (httpHandler -> GetUserAgent (getter_Copies(ua))))
{
nsCAutoString uaString ((const PRUnichar*)ua);
SetHeader (nsHTTPAtoms::User_Agent, uaString.GetBuffer ());
}
// Send */*. We're no longer chopping MIME-types for acceptance.
// MIME based content negotiation has died.
// SetHeader(nsHTTPAtoms::Accept, "image/gif, image/x-xbitmap, image/jpeg,
// image/pjpeg, image/png, */*");
SetHeader (nsHTTPAtoms::Accept, "*/*");
nsXPIDLCString acceptLanguages;
// Add the Accept-Language header
rv = httpHandler->GetAcceptLanguages (getter_Copies(acceptLanguages));
if (NS_SUCCEEDED(rv))
{
if (acceptLanguages && *acceptLanguages)
SetHeader (nsHTTPAtoms::Accept_Language, acceptLanguages);
}
nsXPIDLCString acceptEncodings;
rv = httpHandler -> GetAcceptEncodings (getter_Copies (acceptEncodings));
if (NS_SUCCEEDED(rv))
{
if (acceptEncodings && *acceptEncodings)
SetHeader (nsHTTPAtoms::Accept_Encoding, acceptEncodings);
}
if (mDoKeepAlive)
{
char *p = PR_smprintf ("%d", mKeepAliveTimeout);
SetHeader (nsHTTPAtoms::Keep_Alive, p);
PR_smprintf_free (p);
SetHeader (nsHTTPAtoms::Connection, "keep-alive");
}
else
SetHeader (nsHTTPAtoms::Connection, "close");
return NS_OK;
}

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

@ -32,6 +32,7 @@
#include "nsIChannel.h"
#include "nsHTTPHeaderArray.h"
#include "nsHTTPEnums.h"
#include "nsHTTPHandler.h"
class nsIInputStream;
class nsHTTPChannel;
@ -64,7 +65,7 @@ class nsHTTPRequest : public nsIStreamObserver,
public:
// Constructor
nsHTTPRequest(nsIURI* i_URL, HTTPMethod i_Method=HM_GET);
nsHTTPRequest(nsIURI* i_URL, nsHTTPHandler* i_Handler, PRUint32 bufferSegmentSize, PRUint32 bufferMaxSize, HTTPMethod i_Method=HM_GET);
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
@ -104,8 +105,9 @@ public:
nsresult SetConnection(nsHTTPChannel* i_Connection);
nsresult SetTransport(nsIChannel *aTransport);
nsresult ReleaseTransport(nsIChannel *aTransport);
nsresult SetTransport (nsIChannel * aTransport);
nsresult GetTransport (nsIChannel **aTransport);
// nsresult ReleaseTransport(nsIChannel *aTransport);
// Build the actual request string based on the settings.
nsresult WriteRequest();
@ -144,18 +146,23 @@ protected:
nsCOMPtr<nsIURL> mURI;
PRUint32 mVersion;
PRUint32 mKeepAliveTimeout;
PRUint32 mAttempts;
PRBool mDoKeepAlive;
nsCOMPtr<nsIChannel> mTransport;
nsHTTPChannel* mConnection;
nsHTTPHeaderArray mHeaders;
nsCString mRequestBuffer;
nsCOMPtr<nsIInputStream> mPostDataStream;
nsCString mRequestBuffer;
nsCOMPtr<nsIInputStream> mPostDataStream;
char* mRequestSpec;
nsHTTPHandler* mHandler;
PRUint32 mBufferSegmentSize;
PRUint32 mBufferMaxSize;
nsresult formHeaders ();
};
#define NS_HTTP_REQUEST_SEGMENT_SIZE (4*1024)
#define NS_HTTP_REQUEST_BUFFER_SIZE (16*1024)
#endif /* _nsHTTPRequest_h_ */

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

@ -58,8 +58,8 @@ static const int kMAX_HEADER_SIZE = 60000;
static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
nsHTTPResponseListener::nsHTTPResponseListener(nsHTTPChannel *aChannel)
: mChannel(aChannel)
nsHTTPResponseListener::nsHTTPResponseListener(nsHTTPChannel *aChannel, nsHTTPHandler *handler)
: mChannel(aChannel), mHandler (handler)
{
NS_INIT_REFCNT();
@ -114,8 +114,8 @@ NS_IMPL_QUERY_INTERFACE2(nsHTTPResponseListener,
// the cache.
//
///////////////////////////////////////////////////////////////////////////////
nsHTTPCacheListener::nsHTTPCacheListener(nsHTTPChannel* aChannel)
: nsHTTPResponseListener(aChannel)
nsHTTPCacheListener::nsHTTPCacheListener(nsHTTPChannel* aChannel, nsHTTPHandler *handler)
: nsHTTPResponseListener(aChannel, handler)
{
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("Creating nsHTTPCacheListener [this=%x].\n", this));
@ -210,13 +210,14 @@ nsresult nsHTTPCacheListener::Abort()
//
////////////////////////////////////////////////////////////////////////////////
nsHTTPServerListener::nsHTTPServerListener(nsHTTPChannel* aChannel)
: nsHTTPResponseListener(aChannel),
nsHTTPServerListener::nsHTTPServerListener(nsHTTPChannel* aChannel, nsHTTPHandler *handler)
: nsHTTPResponseListener (aChannel, handler),
mResponse(nsnull),
mFirstLineParsed(PR_FALSE),
mHeadersDone(PR_FALSE),
mBytesReceived(0),
mBodyBytesReceived (0)
mBodyBytesReceived (0),
mCompressHeaderChecked (PR_FALSE)
{
mChannel->mHTTPServerListener = this;
@ -373,6 +374,33 @@ nsHTTPServerListener::OnDataAvailable(nsIChannel* channel,
mChunkConverterPushed = PR_TRUE;
}
if (!mCompressHeaderChecked)
{
rv = mResponse -> GetHeader (nsHTTPAtoms::Content_Encoding, getter_Copies (mCompressHeader));
mCompressHeaderChecked = PR_TRUE;
if (NS_SUCCEEDED (rv) && mCompressHeader)
{
NS_WITH_SERVICE (nsIStreamConverterService,
StreamConvService, kStreamConverterServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsString2 fromStr ( mCompressHeader );
nsString2 toStr ( "uncompressed" );
nsCOMPtr<nsIStreamListener> converterListener;
rv = StreamConvService->AsyncConvertData(
fromStr.GetUnicode(),
toStr.GetUnicode(),
mResponseDataListener,
channel,
getter_AddRefs (converterListener));
if (NS_FAILED(rv)) return rv;
mResponseDataListener = converterListener;
}
}
PR_LOG(gHTTPLog, PR_LOG_ALWAYS,
("\tOnDataAvailable [this=%x]. Calling consumer "
"OnDataAvailable.\tlength:%d\n", this, i_Length));
@ -478,7 +506,7 @@ nsHTTPServerListener::OnStopRequest(nsIChannel* channel,
}
}
mChannel -> ReleaseTransport (channel, keepAlive);
mHandler -> ReleaseTransport (channel, keepAlive);
}
NS_IF_RELEASE(mChannel);

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

@ -29,6 +29,8 @@
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIInputStream.h"
#include "nsXPIDLString.h"
#include "nsHTTPHandler.h"
class nsIBufferInputStream;
class nsHTTPResponse;
@ -53,7 +55,7 @@ class nsHTTPChannel;
class nsHTTPResponseListener : public nsIStreamListener
{
public:
nsHTTPResponseListener(nsHTTPChannel* aConnection);
nsHTTPResponseListener (nsHTTPChannel* aConnection, nsHTTPHandler *handler);
virtual ~nsHTTPResponseListener();
// nsISupport methods...
@ -69,8 +71,9 @@ public:
void SetListener(nsIStreamListener *aListener);
protected:
nsCOMPtr<nsIStreamListener> mResponseDataListener;
nsHTTPChannel* mChannel;
nsCOMPtr<nsIStreamListener> mResponseDataListener;
nsHTTPChannel* mChannel;
nsHTTPHandler* mHandler;
};
@ -82,7 +85,7 @@ class nsHTTPServerListener : public nsHTTPResponseListener
public:
nsHTTPServerListener(nsHTTPChannel* aConnection);
nsHTTPServerListener(nsHTTPChannel* aConnection, nsHTTPHandler *handler);
virtual ~nsHTTPServerListener();
NS_DECL_NSISTREAMOBSERVER
@ -116,6 +119,9 @@ protected:
PRUint32 mBytesReceived;
PRBool mChunkConverterPushed;
PRInt32 mBodyBytesReceived;
nsXPIDLCString mCompressHeader;
PRBool mCompressHeaderChecked;
};
@ -125,7 +131,7 @@ protected:
class nsHTTPCacheListener : public nsHTTPResponseListener
{
public:
nsHTTPCacheListener(nsHTTPChannel* aChannel);
nsHTTPCacheListener(nsHTTPChannel* aChannel, nsHTTPHandler *handler);
virtual ~nsHTTPCacheListener();
// nsIStreamObserver methods...

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

@ -30,7 +30,7 @@ MODULE = converters
LIBRARY_NAME = converters
IS_COMPONENT = 1
REQUIRES = xpcom
REQUIRES = xpcom zlib
CPPSRCS = \
nsMultiMixedConv.cpp \
@ -39,6 +39,7 @@ CPPSRCS = \
mozTXTToHTMLConv.cpp \
nsUnknownDecoder.cpp \
nsHTTPChunkConv.cpp \
nsHTTPCompressConv.cpp \
$(NULL)
EXPORTS = \

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

@ -28,17 +28,19 @@ DLLNAME=cnvts
DLL=.\$(OBJDIR)\$(DLLNAME).dll
EXPORTS = \
nsMultiMixedConv.h \
nsFTPDirListingConv.h \
nsHTTPChunkConv.h \
nsMultiMixedConv.h \
nsFTPDirListingConv.h \
nsHTTPChunkConv.h \
nsHTTPCompressConv.h \
$(NULL)
LLIBS= $(LLIBS) \
$(DIST)\lib\xpcom.lib \
$(LIBNSPR) \
!ifdef MOZ_PERF
$(DIST)\lib\util.lib \
$(DIST)\lib\util.lib \
!endif
$(DIST)\lib\zlib.lib \
$(NULL)
#
@ -57,10 +59,11 @@ CPP_OBJS = \
.\$(OBJDIR)\nsConvFactories.obj \
.\$(OBJDIR)\mozTXTToHTMLConv.obj \
.\$(OBJDIR)\nsHTTPChunkConv.obj \
.\$(OBJDIR)\nsHTTPCompressConv.obj \
.\$(OBJDIR)\nsUnknownDecoder.obj \
$(NULL)
LOCAL_INCLUDES=-I.
LOCAL_INCLUDES=-I. -I$(XPDIST)\public\zlib
INCLUDES = $(LOCAL_INCLUDES)

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

@ -27,6 +27,7 @@
#include "nsFTPDirListingConv.h"
#include "nsMultiMixedConv.h"
#include "nsHTTPChunkConv.h"
#include "nsHTTPCompressConv.h"
#include "mozTXTToHTMLConv.h"
#include "nsUnknownDecoder.h"
@ -34,7 +35,7 @@ nsresult NS_NewFTPDirListingConv(nsFTPDirListingConv** result);
nsresult NS_NewMultiMixedConv (nsMultiMixedConv** result);
nsresult MOZ_NewTXTToHTMLConv (mozTXTToHTMLConv** result);
nsresult NS_NewHTTPChunkConv (nsHTTPChunkConv ** result);
nsresult NS_NewHTTPCompressConv (nsHTTPCompressConv ** result);
static NS_IMETHODIMP
CreateNewFTPDirListingConv(nsISupports* aOuter, REFNSIID aIID, void **aResult)
@ -132,6 +133,30 @@ CreateNewHTTPChunkConvFactory (nsISupports* aOuter, REFNSIID aIID, void **aResul
return rv;
}
static NS_IMETHODIMP
CreateNewHTTPCompressConvFactory (nsISupports* aOuter, REFNSIID aIID, void **aResult)
{
if (!aResult) {
return NS_ERROR_INVALID_POINTER;
}
if (aOuter) {
*aResult = nsnull;
return NS_ERROR_NO_AGGREGATION;
}
nsHTTPCompressConv* inst = nsnull;
nsresult rv = NS_NewHTTPCompressConv (&inst);
if (NS_FAILED(rv)) {
*aResult = nsnull;
return rv;
}
rv = inst->QueryInterface(aIID, aResult);
if (NS_FAILED(rv)) {
*aResult = nsnull;
}
NS_RELEASE(inst); /* get rid of extra refcnt */
return rv;
}
static NS_IMETHODIMP
CreateNewUnknownDecoderFactory(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
@ -211,6 +236,32 @@ static nsModuleComponentInfo components[] =
CreateNewHTTPChunkConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=gzip?to=uncompressed",
CreateNewHTTPCompressConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=x-gzip?to=uncompressed",
CreateNewHTTPCompressConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=compress?to=uncompressed",
CreateNewHTTPCompressConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=x-compress?to=uncompressed",
CreateNewHTTPCompressConvFactory
},
{ "HttpCompressConverter",
NS_HTTPCOMPRESSCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY "?from=deflate?to=uncompressed",
CreateNewHTTPCompressConvFactory
}
};
NS_IMPL_NSGETMODULE("nsConvModule", components);