Fix for bug 81751. Add an extra layer of converted in order to be able to support multipart urls (like multipart/x-mixed-replace). R=varada, SR=mscott, A=asa

This commit is contained in:
ducarroz%netscape.com 2001-06-04 23:01:45 +00:00
Родитель f7d8b996ba
Коммит f58a4d9d49
6 изменённых файлов: 277 добавлений и 115 удалений

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

@ -22,11 +22,11 @@
#include "nsISupports.idl"
#include "nsIURI.idl"
#include "nsIFileStreams.idl"
#include "nsILocalFile.idl"
%{ C++
#include "nsFileStream.h"
//
// Callback declarations for URL completion
//
@ -39,7 +39,6 @@ typedef nsresult (*nsAttachSaveCompletionCallback) (nsresult aStatus,
%}
[ptr] native nsOutputFileStream(nsOutputFileStream);
native nsAttachSaveCompletionCallback(nsAttachSaveCompletionCallback);
@ -48,7 +47,7 @@ interface nsIURLFetcher : nsISupports
{
boolean stillRunning();
void fireURLRequest(in nsIURI aURL, in nsOutputFileStream fOut, in nsAttachSaveCompletionCallback cb, in voidPtr tagData);
void fireURLRequest(in nsIURI aURL, in nsILocalFile localFile, in nsIFileOutputStream fileStream, in nsAttachSaveCompletionCallback cb, in voidPtr tagData);
void initialize(in nsOutputFileStream fOut, in nsAttachSaveCompletionCallback cb, in voidPtr tagData);
void initialize(in nsILocalFile localFile, in nsIFileOutputStream fileStream, in nsAttachSaveCompletionCallback cb, in voidPtr tagData);
};

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

@ -100,7 +100,6 @@ nsMsgAttachmentHandler::nsMsgAttachmentHandler()
mCompFields = nsnull; // Message composition fields for the sender
mFileSpec = nsnull;
mOutFile = nsnull;
mURL = nsnull;
mRequest = nsnull;
@ -465,12 +464,17 @@ nsMsgAttachmentHandler::SnarfMsgAttachment(nsMsgCompFields *compFields)
rv = NS_ERROR_FAILURE;
goto done;
}
mOutFile = new nsOutputFileStream(*mFileSpec, PR_WRONLY | PR_CREATE_FILE, 00600);
if (!mOutFile)
nsCOMPtr<nsILocalFile> localFile;
nsCOMPtr<nsIOutputStream> outputStream;
NS_FileSpecToIFile(mFileSpec, getter_AddRefs(localFile));
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), localFile, -1, 00600);
if (NS_FAILED(rv) || !outputStream)
{
rv = NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
goto done;
}
mOutFile = do_QueryInterface(outputStream);
nsCOMPtr<nsIURLFetcher> fetcher = do_CreateInstance(NS_URLFETCHER_CONTRACTID, &rv);
if (NS_FAILED(rv) || !fetcher)
@ -480,7 +484,7 @@ nsMsgAttachmentHandler::SnarfMsgAttachment(nsMsgCompFields *compFields)
goto done;
}
rv = fetcher->Initialize(mOutFile, FetcherURLDoneCallback, this);
rv = fetcher->Initialize(localFile, mOutFile, FetcherURLDoneCallback, this);
rv = GetMessageServiceFromURI(m_uri, &messageService);
if (NS_SUCCEEDED(rv) && messageService)
{
@ -496,8 +500,7 @@ done:
{
if (mOutFile)
{
mOutFile->close();
delete mOutFile;
mOutFile->Close();
mOutFile = nsnull;
}
@ -550,13 +553,17 @@ nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields)
if (! mFileSpec )
return (NS_ERROR_FAILURE);
mOutFile = new nsOutputFileStream(*mFileSpec, PR_WRONLY | PR_CREATE_FILE, 00600);
if (!mOutFile)
nsCOMPtr<nsILocalFile> localFile;
nsCOMPtr<nsIOutputStream> outputStream;
NS_FileSpecToIFile(mFileSpec, getter_AddRefs(localFile));
status = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), localFile, -1, 00600);
if (NS_FAILED(status) || !outputStream)
{
delete mFileSpec;
mFileSpec = nsnull;
return NS_MSG_UNABLE_TO_OPEN_TMP_FILE;
}
mOutFile = do_QueryInterface(outputStream);
mURL->GetSpec(getter_Copies(url_string));
@ -616,25 +623,25 @@ nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields)
// then, if we have a resource fork, check the filename extension, maybe we don't need the resource fork!
if (sendResourceFork)
{
nsAutoString urlStr; urlStr.AssignWithConversion(url_string);
char *ext = nsMsgGetExtensionFromFileURL(urlStr);
if (ext && *ext)
{
sendResourceFork =
PL_strcasecmp(ext, "TXT") &&
PL_strcasecmp(ext, "JPG") &&
PL_strcasecmp(ext, "GIF") &&
PL_strcasecmp(ext, "TIF") &&
PL_strcasecmp(ext, "HTM") &&
PL_strcasecmp(ext, "HTML") &&
PL_strcasecmp(ext, "ART") &&
PL_strcasecmp(ext, "XUL") &&
PL_strcasecmp(ext, "XML") &&
PL_strcasecmp(ext, "CSS") &&
PL_strcasecmp(ext, "JS");
nsAutoString urlStr; urlStr.AssignWithConversion(url_string);
char *ext = nsMsgGetExtensionFromFileURL(urlStr);
if (ext && *ext)
{
sendResourceFork =
PL_strcasecmp(ext, "TXT") &&
PL_strcasecmp(ext, "JPG") &&
PL_strcasecmp(ext, "GIF") &&
PL_strcasecmp(ext, "TIF") &&
PL_strcasecmp(ext, "HTM") &&
PL_strcasecmp(ext, "HTML") &&
PL_strcasecmp(ext, "ART") &&
PL_strcasecmp(ext, "XUL") &&
PL_strcasecmp(ext, "XML") &&
PL_strcasecmp(ext, "CSS") &&
PL_strcasecmp(ext, "JS");
}
PR_FREEIF(ext);
}
PR_FREEIF(ext);
}
}
// Only use appledouble if we aren't uuencoding.
@ -825,7 +832,7 @@ nsMsgAttachmentHandler::SnarfAttachment(nsMsgCompFields *compFields)
return rv;
}
status = fetcher->FireURLRequest(mURL, mOutFile, FetcherURLDoneCallback, this);
status = fetcher->FireURLRequest(mURL, localFile, mOutFile, FetcherURLDoneCallback, this);
if (NS_FAILED(status))
return NS_ERROR_UNEXPECTED;
@ -892,9 +899,7 @@ nsMsgAttachmentHandler::UrlExit(nsresult status, const PRUnichar* aMsg)
// Close the file, but don't delete the disk file (or the file spec.)
if (mOutFile)
{
mOutFile->close();
delete mOutFile;
mOutFile->Close();
mOutFile = nsnull;
}

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

@ -29,6 +29,7 @@
#include "nsIMsgStatusFeedback.h"
#include "nsIRequest.h"
#include "nsIMsgSend.h"
#include "nsIFileStreams.h"
#ifdef XP_MAC
@ -81,7 +82,7 @@ private:
public:
nsIURI *mURL;
nsFileSpec *mFileSpec; // The temp file to which we save it
nsOutputFileStream *mOutFile; // The temp file stream pointer
nsCOMPtr<nsIFileOutputStream> mOutFile;
nsIRequest *mRequest; // The live request used while fetching an attachment
nsMsgCompFields *mCompFields; // Message composition fields for the sender
PRBool m_bogus_attachment; // This is to catch problem children...

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

@ -271,7 +271,7 @@ nsMsgComposeAndSend::Clear()
if (m_plaintext)
{
if (m_plaintext->mOutFile)
m_plaintext->mOutFile->close();
m_plaintext->mOutFile->Close();
if (m_plaintext->mFileSpec)
{
@ -357,8 +357,8 @@ nsMsgComposeAndSend::Clear()
PR_FREEIF (m_attachments [i].m_real_name);
PR_FREEIF (m_attachments [i].m_encoding);
PR_FREEIF (m_attachments [i].m_content_id);
if ( (m_attachments[i].mOutFile) && (m_attachments[i].mOutFile->is_open()) )
m_attachments[i].mOutFile->close();
if (m_attachments[i].mOutFile)
m_attachments[i].mOutFile->Close();
if (m_attachments[i].mFileSpec)
{
// Only Delete the file if this variable is set!

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

@ -42,10 +42,10 @@
#include "nsIWebProgress.h"
#include "nsMsgAttachmentHandler.h"
#include "nsMsgSend.h"
#include "nsIStreamConverterService.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
NS_IMPL_ISUPPORTS6(nsURLFetcher, nsIURLFetcher, nsIStreamListener, nsIURIContentListener, nsIInterfaceRequestor, nsIWebProgressListener, nsISupportsWeakReference)
@ -61,13 +61,15 @@ nsURLFetcher::nsURLFetcher()
NS_INIT_REFCNT();
// Init member variables...
mOutStream = nsnull;
mTotalWritten = 0;
mBuffer = nsnull;
mBufferSize = 0;
mStillRunning = PR_TRUE;
mCallback = nsnull;
mContentType = nsnull;
mCharset = nsnull;
mOnStopRequestProcessed = PR_FALSE;
nsURLFetcherStreamConsumer *consumer = new nsURLFetcherStreamConsumer(this);
mConverter = do_QueryInterface(consumer);
}
nsURLFetcher::~nsURLFetcher()
@ -77,8 +79,7 @@ nsURLFetcher::~nsURLFetcher()
#endif
mStillRunning = PR_FALSE;
PR_FREEIF(mContentType);
PR_FREEIF(mCharset);
PR_FREEIF(mBuffer);
// Remove the DocShell as a listener of the old WebProgress...
if (mLoadCookie)
{
@ -127,18 +128,11 @@ nsURLFetcher::CanHandleContent(const char * aContentType,
PRBool * aCanHandleContent)
{
// if the content type is unknown, we should let the unknown decoder take care of it.
// we will be called back again with a better content type!
if (nsCRT::strcasecmp(aContentType, UNKNOWN_CONTENT_TYPE) == 0)
*aCanHandleContent = PR_FALSE;
else
{
if (nsCRT::strcasecmp(aContentType, MESSAGE_RFC822) == 0)
*aDesiredContentType = nsCRT::strdup("text/html");
// since we explicilty loaded the url, we always want to handle it!
*aCanHandleContent = PR_TRUE;
}
return NS_OK;
}
@ -150,9 +144,24 @@ nsURLFetcher::DoContent(const char * aContentType,
PRBool * aAbortProcess)
{
nsresult rv = NS_OK;
if (aAbortProcess)
*aAbortProcess = PR_FALSE;
QueryInterface(NS_GET_IID(nsIStreamListener), (void **) aContentHandler);
/*
Check the content-type to see if we need to insert a converter
*/
if (nsCRT::strcasecmp(aContentType, UNKNOWN_CONTENT_TYPE) == 0 ||
nsCRT::strcasecmp(aContentType, MULTIPART_MIXED_REPLACE) == 0 ||
nsCRT::strcasecmp(aContentType, MULTIPART_MIXED) == 0 ||
nsCRT::strcasecmp(aContentType, MULTIPART_BYTERANGES) == 0)
{
rv = InsertConverter(aContentType);
if (NS_SUCCEEDED(rv))
mConverterContentType = aContentType;
}
return rv;
}
@ -216,31 +225,11 @@ nsresult
nsURLFetcher::OnDataAvailable(nsIRequest *request, nsISupports * ctxt, nsIInputStream *aIStream,
PRUint32 sourceOffset, PRUint32 aLength)
{
PRUint32 readLen = aLength;
PRUint32 wroteIt;
if (!mOutStream)
return NS_ERROR_INVALID_ARG;
char *buf = (char *)PR_Malloc(aLength);
if (!buf)
return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */
// read the data from the input stram...
nsresult rv = aIStream->Read(buf, aLength, &readLen);
if (NS_FAILED(rv)) return rv;
// write to the output file...
wroteIt = mOutStream->write(buf, readLen);
PR_FREEIF(buf);
if (wroteIt != readLen)
/* let our converter or consumer process the data */
if (!mConverter)
return NS_ERROR_FAILURE;
else
{
mTotalWritten += wroteIt;
return NS_OK;
}
return mConverter->OnDataAvailable(request, ctxt, aIStream, sourceOffset, aLength);
}
@ -248,6 +237,7 @@ nsURLFetcher::OnDataAvailable(nsIRequest *request, nsISupports * ctxt, nsIInputS
nsresult
nsURLFetcher::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
/* check if the user has canceld the operation */
nsMsgAttachmentHandler *attachmentHdl = (nsMsgAttachmentHandler *)mTagData;
if (attachmentHdl)
{
@ -268,23 +258,34 @@ nsURLFetcher::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
attachmentHdl->mRequest = request;
}
/* call our converter or consumer */
if (mConverter)
return mConverter->OnStartRequest(request, ctxt);
return NS_OK;
}
nsresult
nsURLFetcher::OnStopRequest(nsIRequest *request, nsISupports * /* ctxt */, nsresult aStatus)
nsURLFetcher::OnStopRequest(nsIRequest *request, nsISupports * ctxt, nsresult aStatus)
{
#if defined(DEBUG_ducarroz)
printf("nsURLFetcher::OnStopRequest()\n");
#endif
nsresult rv = NS_OK;
// it's possible we could get in here from the channel calling us with an OnStopRequest and from our
// onStatusChange method (in the case of an error). So we should protect against this to make sure we
// don't process the on stop request twice...
if (mOnStopRequestProcessed) return NS_OK;
if (mOnStopRequestProcessed)
return NS_OK;
mOnStopRequestProcessed = PR_TRUE;
/* first, call our converter or consumer */
if (mConverter)
rv = mConverter->OnStopRequest(request, ctxt, aStatus);
nsMsgAttachmentHandler *attachmentHdl = (nsMsgAttachmentHandler *)mTagData;
if (attachmentHdl)
attachmentHdl->mRequest = nsnull;
@ -294,70 +295,52 @@ nsURLFetcher::OnStopRequest(nsIRequest *request, nsISupports * /* ctxt */, nsres
//
mStillRunning = PR_FALSE;
// First close the output stream...
// time to close the output stream...
if (mOutStream)
{
mOutStream->close();
mOutStream->Close();
mOutStream = nsnull;
}
// Check the content type!
char *contentType = nsnull;
char *charset = nsnull;
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(request);
if(!aChannel) return NS_ERROR_FAILURE;
if (NS_SUCCEEDED(aChannel->GetContentType(&contentType)) && contentType)
/* In case of multipart/x-mixed-replace, we need to truncate the file to the current part size */
if (PL_strcasecmp(mConverterContentType, MULTIPART_MIXED_REPLACE) == 0)
{
if (PL_strcasecmp(contentType, UNKNOWN_CONTENT_TYPE))
{
mContentType = contentType;
}
}
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
if (httpChannel)
{
if (NS_SUCCEEDED(httpChannel->GetCharset(&charset)) && charset)
{
mCharset = charset;
PRInt64 fileSize;
LL_I2L(fileSize, mTotalWritten);
mLocalFile->SetFileSize(fileSize);
}
}
// Now if there is a callback, we need to call it...
if (mCallback)
mCallback (aStatus, mContentType, mCharset, mTotalWritten, nsnull, mTagData);
mCallback (aStatus, (const char *)mContentType, (const char *)mCharset, mTotalWritten, nsnull, mTagData);
// Time to return...
return NS_OK;
}
nsresult
nsURLFetcher::Initialize(nsOutputFileStream *fOut,
nsURLFetcher::Initialize(nsILocalFile *localFile,
nsIFileOutputStream *outputStream,
nsAttachSaveCompletionCallback cb,
void *tagData)
{
if (!fOut)
if (!outputStream || !localFile)
return NS_ERROR_INVALID_ARG;
if (!fOut->is_open())
return NS_ERROR_FAILURE;
mOutStream = fOut;
mOutStream = outputStream;
mLocalFile = localFile;
mCallback = cb; //JFD: Please, no more callback, use a listener...
mTagData = tagData; //JFD: TODO, WE SHOULD USE A NSCOMPTR to hold this stuff!!!
return NS_OK;
}
nsresult
nsURLFetcher::FireURLRequest(nsIURI *aURL, nsOutputFileStream *fOut,
nsURLFetcher::FireURLRequest(nsIURI *aURL, nsILocalFile *localFile, nsIFileOutputStream *outputStream,
nsAttachSaveCompletionCallback cb, void *tagData)
{
nsresult rv;
rv = Initialize(fOut, cb, tagData);
rv = Initialize(localFile, outputStream, cb, tagData);
NS_ENSURE_SUCCESS(rv, rv);
// we're about to fire a new url request so make sure the on stop request flag is cleared...
@ -378,6 +361,30 @@ nsURLFetcher::FireURLRequest(nsIURI *aURL, nsOutputFileStream *fOut,
return NS_OK;
}
nsresult
nsURLFetcher::InsertConverter(const char * aContentType)
{
nsresult rv;
nsCOMPtr<nsIStreamConverterService> convServ(do_GetService("@mozilla.org/streamConverters;1", &rv));
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsIStreamListener> toListener(mConverter);
nsCOMPtr<nsIStreamListener> fromListener;
nsAutoString contentType;
contentType.AssignWithConversion(aContentType);
rv = convServ->AsyncConvertData(contentType.get(),
NS_LITERAL_STRING("*/*").get(),
toListener,
nsnull,
getter_AddRefs(fromListener));
if (NS_SUCCEEDED(rv))
mConverter = fromListener;
}
return rv;
}
// web progress listener implementation
@ -432,3 +439,122 @@ nsURLFetcher::OnSecurityChange(nsIWebProgress *aWebProgress,
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/**
* Stream consumer used for handling special content type like multipart/x-mixed-replace
*/
NS_IMPL_ISUPPORTS2(nsURLFetcherStreamConsumer, nsIStreamListener, nsIRequestObserver)
nsURLFetcherStreamConsumer::nsURLFetcherStreamConsumer(nsURLFetcher* urlFetcher) :
mURLFetcher(urlFetcher)
{
#if defined(DEBUG_ducarroz)
printf("CREATE nsURLFetcherStreamConsumer: %x\n", this);
#endif
NS_INIT_ISUPPORTS();
}
nsURLFetcherStreamConsumer::~nsURLFetcherStreamConsumer()
{
#if defined(DEBUG_ducarroz)
printf("DISPOSE nsURLFetcherStreamConsumer: %x\n", this);
#endif
}
/** nsIRequestObserver methods **/
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP nsURLFetcherStreamConsumer::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt)
{
if (!mURLFetcher || !mURLFetcher->mOutStream)
return NS_ERROR_FAILURE;
/* In case of multipart/x-mixed-replace, we need to erase the output file content */
if (PL_strcasecmp(mURLFetcher->mConverterContentType, MULTIPART_MIXED_REPLACE) == 0)
{
nsCOMPtr<nsISeekableStream> seekStream = do_QueryInterface(mURLFetcher->mOutStream);
if (seekStream)
seekStream->Seek(nsISeekableStream::NS_SEEK_SET, 0);
mURLFetcher->mTotalWritten = 0;
}
return NS_OK;
}
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status); */
NS_IMETHODIMP nsURLFetcherStreamConsumer::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status)
{
if (!mURLFetcher)
return NS_ERROR_FAILURE;
// Check the content type!
char *contentType = nsnull;
char *charset = nsnull;
nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(aRequest);
if(!aChannel) return NS_ERROR_FAILURE;
if (NS_SUCCEEDED(aChannel->GetContentType(&contentType)) && contentType)
if (PL_strcasecmp(contentType, UNKNOWN_CONTENT_TYPE) != 0)
mURLFetcher->mContentType = contentType;
if (contentType)
nsCRT::free(contentType);
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
if (httpChannel)
if (NS_SUCCEEDED(httpChannel->GetCharset(&charset)) && charset)
mURLFetcher->mCharset = charset;
if (charset)
nsCRT::free(charset);
return NS_OK;
}
/** nsIStreamListener methods **/
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */
NS_IMETHODIMP nsURLFetcherStreamConsumer::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
{
PRUint32 readLen = count;
PRUint32 wroteIt;
if (!mURLFetcher)
return NS_ERROR_FAILURE;
if (!mURLFetcher->mOutStream)
return NS_ERROR_INVALID_ARG;
if (mURLFetcher->mBufferSize < count)
{
PR_FREEIF(mURLFetcher->mBuffer);
if (count > 0x1000)
mURLFetcher->mBufferSize = count;
else
mURLFetcher->mBufferSize = 0x1000;
mURLFetcher->mBuffer = (char *)PR_Malloc(mURLFetcher->mBufferSize);
if (!mURLFetcher->mBuffer)
return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */
}
// read the data from the input stram...
nsresult rv = inStr->Read(mURLFetcher->mBuffer, count, &readLen);
if (NS_FAILED(rv))
return rv;
// write to the output file...
mURLFetcher->mOutStream->Write(mURLFetcher->mBuffer, readLen, &wroteIt);
if (wroteIt != readLen)
return NS_ERROR_FAILURE;
else
{
mURLFetcher->mTotalWritten += wroteIt;
return NS_OK;
}
}

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

@ -33,7 +33,7 @@
#include "nsIURIContentListener.h"
#include "nsIWebProgressListener.h"
#include "nsWeakReference.h"
#include "nsXPIDLString.h"
class nsURLFetcher : public nsIURLFetcher,
public nsIStreamListener,
@ -67,16 +67,47 @@ public:
// Methods for nsIWebProgressListener
NS_DECL_NSIWEBPROGRESSLISTENER
protected:
nsresult InsertConverter(const char * aContentType);
private:
nsOutputFileStream *mOutStream; // the output file stream
nsCOMPtr<nsIFileOutputStream> mOutStream; // the output file stream
nsCOMPtr<nsILocalFile> mLocalFile; // the output file itself
nsCOMPtr<nsIStreamListener> mConverter; // the stream converter, if needed
nsXPIDLCString mConverterContentType; // The content type of the converter
PRBool mStillRunning; // Are we still running?
PRInt32 mTotalWritten; // Size counter variable
char *mContentType; // The content type retrieved from the server
char *mCharset; // The charset retrieved from the server
char *mBuffer; // Buffer used for reading the data
PRUint32 mBufferSize; // Buffer size;
nsXPIDLCString mContentType; // The content type retrieved from the server
nsXPIDLCString mCharset; // The charset retrieved from the server
void *mTagData; // Tag data for callback...
nsAttachSaveCompletionCallback mCallback; // Callback to call once the file is saved...
nsCOMPtr<nsISupports> mLoadCookie; // load cookie used by the uri loader when we fetch the url
PRBool mOnStopRequestProcessed; // used to prevent calling OnStopRequest multiple times
friend class nsURLFetcherStreamConsumer;
};
/**
* Stream consumer used for handling special content type like multipart/x-mixed-replace
*/
class nsURLFetcherStreamConsumer : public nsIStreamListener
{
public:
nsURLFetcherStreamConsumer(nsURLFetcher* urlFetcher);
virtual ~nsURLFetcherStreamConsumer();
/* additional members */
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
private:
nsURLFetcher* mURLFetcher;
};
#endif /* nsURLFetcher_h_ */