Added AsyncOpen to nsIChannel for URL dispatching. Added ContentLength to InputStreamChannel. (r=rpotts,valeski)

This commit is contained in:
warren%netscape.com 1999-10-06 08:26:01 +00:00
parent 735f646940
commit 8603974025
39 changed files with 952 additions and 344 deletions

View File

@ -337,7 +337,9 @@ nsJSProtocolHandler::NewChannel(const char* verb, nsIURI* uri,
if (NS_FAILED(rv))
return rv;
rv = serv->NewInputStreamChannel(uri, "text/html", in, aGroup, &channel);
rv = serv->NewInputStreamChannel(uri, "text/html",
-1, // XXX need contentLength -- implies that the evaluation should happen here, not in Read
in, aGroup, &channel);
NS_RELEASE(in);
if (NS_FAILED(rv))
return rv;

View File

@ -514,9 +514,12 @@ nsMessenger::OpenAttachment(const char * url, const char * displayName,
}
aListener->m_channel = null_nsCOMPtr();
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID, &rv);
rv = netService->NewInputStreamChannel(aURL, nsnull,
nsnull, nsnull,
getter_AddRefs(aListener->m_channel));
rv = netService->NewInputStreamChannel(aURL,
nsnull, // contentType
-1, // contentLength
nsnull, // inputStream
nsnull, // loadGroup
getter_AddRefs(aListener->m_channel));
nsAutoString from, to;
from = "message/rfc822";
to = "text/xul";
@ -638,9 +641,12 @@ nsMessenger::SaveAs(const char* url, PRBool asFile)
aListener->m_channel = null_nsCOMPtr();
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID,
&rv);
rv = netService->NewInputStreamChannel(aURL, nsnull,
nsnull, nsnull,
getter_AddRefs(aListener->m_channel));
rv = netService->NewInputStreamChannel(aURL,
nsnull, // contentType
-1, // contentLength
nsnull, // inputStream
nsnull, // loadGroup
getter_AddRefs(aListener->m_channel));
nsAutoString from, to;
from = "message/rfc822";
to = saveAsFileType == 1 ? "text/html" : "text/plain";

View File

@ -269,6 +269,11 @@ NS_IMETHODIMP nsMsgProtocol::OpenOutputStream(PRUint32 startPosition, nsIOutputS
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgProtocol::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgProtocol::AsyncRead(PRUint32 startPosition, PRInt32 readCount, nsISupports *ctxt, nsIStreamListener *listener)
{
// set the stream listener and then load the url

View File

@ -266,7 +266,12 @@ SaveDraftMessageCompleteCallback(nsIURI *aURL, nsresult aExitCode, void *tagData
nsCOMPtr<nsIChannel> dummyChannel;
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID, &rv);
rv = netService->NewInputStreamChannel(aURL, nsnull, nsnull, nsnull, getter_AddRefs(dummyChannel));
rv = netService->NewInputStreamChannel(aURL,
nsnull, // contentType
-1, // contentLength
nsnull, // inputStream
nsnull, // loadGroup
getter_AddRefs(dummyChannel));
if (NS_FAILED(mimeParser->AsyncConvertData(nsnull, nsnull, nsnull, dummyChannel)))
{

View File

@ -51,9 +51,6 @@ nsMsgDisplayMessageByString(const PRUnichar * msg)
nsresult
nsMsgAskBooleanQuestionByID(PRInt32 msgID, PRBool *answer)
{
nsresult rv;
PRInt32 result;
PRUnichar * msg = ComposeGetStringByID(msgID);
nsMsgAskBooleanQuestionByString(msg, answer);
nsCRT::free(msg);

View File

@ -179,7 +179,11 @@ nsresult rv;
mQuoteChannel = null_nsCOMPtr();
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID, &rv);
rv = netService->NewInputStreamChannel(aURL, nsnull, nsnull, nsnull,
rv = netService->NewInputStreamChannel(aURL,
nsnull, // contentType
-1, // contentLength
nsnull, // inputStream
nsnull, // loadGroup
getter_AddRefs(mQuoteChannel));
NS_ASSERTION(!mQuoteListener, "Oops quote listener exists\n");

View File

@ -151,7 +151,8 @@ NS_IMETHODIMP nsImapProtocol::QueryInterface(const nsIID &aIID, void** aInstance
return NS_OK;
}
if (aIID.Equals(nsIStreamListener::GetIID()))
if (aIID.Equals(nsIStreamListener::GetIID()) ||
aIID.Equals(nsIStreamObserver::GetIID()))
{
*aInstancePtr = (nsIStreamListener *) this;
NS_ADDREF_THIS();
@ -6226,6 +6227,11 @@ NS_IMETHODIMP nsImapMockChannel::OpenOutputStream(PRUint32 startPosition, nsIOut
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsImapMockChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsImapMockChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount, nsISupports *ctxt, nsIStreamListener *listener)
{
// set the stream listener and then load the url

View File

@ -443,7 +443,9 @@ NS_IMETHODIMP nsStreamConverter::Init(nsIURI *aURI, nsIStreamListener * aOutList
// the following output channel stream is used to fake the content type for people who later
// call into us..
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID, &rv);
rv = netService->NewInputStreamChannel(aURI, mOutputFormat, nsnull, nsnull, getter_AddRefs(mOutgoingChannel));
rv = netService->NewInputStreamChannel(aURI, mOutputFormat,
-1, // XXX fix contentLength
nsnull, nsnull, getter_AddRefs(mOutgoingChannel));
// We will first find an appropriate emitter in the repository that supports
// the requested output format...note, the special exceptions are nsMimeMessageDraftOrTemplate

View File

@ -43,6 +43,7 @@ XPIDLSRCS = \
nsILoadGroup.idl \
nsIFileTransportService.idl \
nsISocketTransportService.idl \
nsIFileSystem.idl \
$(NULL)
EXPORTS = \

View File

@ -43,6 +43,7 @@ XPIDLSRCS = \
.\nsILoadGroup.idl \
.\nsISocketTransportService.idl \
.\nsIFileTransportService.idl \
.\nsIFileSystem.idl \
$(NULL)
include <$(DEPTH)/config/rules.mak>

View File

@ -48,7 +48,7 @@ interface nsIChannel : nsIRequest
* up to the end of the data is read. If greater than the end of
* the data, the amount available is returned in the stream.
*/
nsIInputStream OpenInputStream(in unsigned long startPosition,
nsIInputStream openInputStream(in unsigned long startPosition,
in long readCount);
/**
@ -56,7 +56,16 @@ interface nsIChannel : nsIRequest
* @param startPosition - The offset from the start of the data
* from which to begin writing.
*/
nsIOutputStream OpenOutputStream(in unsigned long startPosition);
nsIOutputStream openOutputStream(in unsigned long startPosition);
/**
* Opens the channel asynchronously. The nsIStreamObserver's OnStartRequest
* method is called back when the channel actually becomes open, providing
* the content type. Its OnStopRequest method is called when the channel
* becomes closed.
*/
void asyncOpen(in nsIStreamObserver observer,
in nsISupports ctxt);
/**
* Reads asynchronously from the URL's specified source. Notifications
@ -67,7 +76,7 @@ interface nsIChannel : nsIRequest
* If the readCount == -1 then all the available data is delivered to
* the stream listener.
*/
void AsyncRead(in unsigned long startPosition,
void asyncRead(in unsigned long startPosition,
in long readCount,
in nsISupports ctxt,
in nsIStreamListener listener);
@ -81,7 +90,7 @@ interface nsIChannel : nsIRequest
* If the writeCount == -1, then all the available data in the input
* stream is written.
*/
void AsyncWrite(in nsIInputStream fromStream,
void asyncWrite(in nsIInputStream fromStream,
in unsigned long startPosition,
in long writeCount,
in nsISupports ctxt,
@ -107,7 +116,7 @@ interface nsIChannel : nsIRequest
* and to not contribute to keeping any nsILoadGroup it may be contained
* in from firing its OnLoadComplete notification.
*/
attribute nsLoadFlags LoadAttributes;
attribute nsLoadFlags loadAttributes;
/**
* Returns the content MIME type of the channel if available. Note that the
@ -115,25 +124,25 @@ interface nsIChannel : nsIRequest
* MIME type, wrong document type stored on a server, etc.) and the caller
* most likely wants to verify with the actual data.
*/
readonly attribute string ContentType;
readonly attribute string contentType;
/**
* Returns the length of the data assiciated with the channel if available.
* If the length is unknown then -1 is returned.
*/
readonly attribute long ContentLength;
readonly attribute long contentLength;
/**
* Accesses the owner corresponding to the entity that is
* responsible for this channel. Used by security code to grant
* or diminish privileges to mobile code loaded from this channel.
*/
attribute nsISupports Owner;
attribute nsISupports owner;
/**
* Returns the load group in which the channel is a currently a member.
*/
readonly attribute nsILoadGroup LoadGroup;
readonly attribute nsILoadGroup loadGroup;
};

View File

@ -37,6 +37,8 @@ interface nsIFileTransportService : nsISupports
// This version can be used with an existing input stream to serve
// as a data pump:
nsIChannel CreateTransportFromStream(in nsIInputStream fromStream,
in string contentType,
in long contentLength,
in string command,
in nsIEventSinkGetter getter);

View File

@ -111,6 +111,8 @@ interface nsIIOService : nsISupports
/**
* Returns a new stream observer that marshals data from another
* stream observer over to the thread specified by an event queue.
* If the event queue is null, the current thread's event queue is
* used.
*/
nsIStreamObserver NewAsyncStreamObserver(in nsIStreamObserver receiver,
in nsIEventQueue eventQueue);
@ -154,6 +156,7 @@ interface nsIIOService : nsISupports
*/
nsIChannel NewInputStreamChannel(in nsIURI uri,
in string contentType,
in long contentLength,
in nsIInputStream inStr,
in nsILoadGroup group);
};

View File

@ -22,7 +22,13 @@
#include "nsString.h"
#include "nsCRT.h"
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIChannel.h"
#include "nsCOMPtr.h"
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
class nsAsyncStreamObserver : public nsIStreamObserver
{
@ -33,29 +39,40 @@ public:
NS_DECL_NSISTREAMOBSERVER
// nsAsyncStreamObserver methods:
nsAsyncStreamObserver(nsIEventQueue* aEventQ)
: mReceiver(nsnull), mStatus(NS_OK)
nsAsyncStreamObserver()
: mStatus(NS_OK)
{
NS_INIT_REFCNT();
mEventQueue = aEventQ;
NS_IF_ADDREF(mEventQueue);
}
virtual ~nsAsyncStreamObserver();
void Init(nsIStreamObserver* aListener) {
mReceiver = aListener;
NS_ADDREF(mReceiver);
nsresult Init(nsIStreamObserver* aObserver, nsIEventQueue* aEventQ) {
mReceiver = aObserver;
if (aEventQ) {
mEventQueue = aEventQ;
}
else {
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> eventQueue;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(),
getter_AddRefs(mEventQueue));
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}
nsISupports* GetReceiver() { return mReceiver; }
nsISupports* GetReceiver() { return mReceiver.get(); }
nsresult GetStatus() { return mStatus; }
void SetStatus(nsresult value) { mStatus = value; }
protected:
nsIEventQueue* mEventQueue;
nsIStreamObserver* mReceiver;
nsresult mStatus;
nsCOMPtr<nsIEventQueue> mEventQueue;
nsCOMPtr<nsIStreamObserver> mReceiver;
nsresult mStatus;
};
@ -86,13 +103,8 @@ public:
PRUint32 aLength);
// nsAsyncStreamListener methods:
nsAsyncStreamListener(nsIEventQueue* aEventQ)
: nsAsyncStreamObserver(aEventQ) {}
nsAsyncStreamListener() {}
void Init(nsIStreamListener* aListener) {
mReceiver = aListener;
NS_ADDREF(mReceiver);
}
};
////////////////////////////////////////////////////////////////////////////////
@ -185,8 +197,6 @@ nsStreamListenerEvent::Fire(nsIEventQueue* aEventQueue)
nsAsyncStreamObserver::~nsAsyncStreamObserver()
{
NS_RELEASE(mReceiver);
NS_IF_RELEASE(mEventQueue);
}
NS_IMPL_THREADSAFE_ISUPPORTS(nsAsyncStreamObserver,
@ -391,11 +401,15 @@ NS_NewAsyncStreamObserver(nsIStreamObserver* *result,
nsIStreamObserver* receiver)
{
nsAsyncStreamObserver* l =
new nsAsyncStreamObserver(eventQueue);
new nsAsyncStreamObserver();
if (l == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
l->Init(receiver);
NS_ADDREF(l);
nsresult rv = l->Init(receiver, eventQueue);
if (NS_FAILED(rv)) {
NS_RELEASE(l);
return rv;
}
*result = l;
return NS_OK;
}
@ -406,11 +420,15 @@ NS_NewAsyncStreamListener(nsIStreamListener* *result,
nsIStreamListener* receiver)
{
nsAsyncStreamListener* l =
new nsAsyncStreamListener(eventQueue);
new nsAsyncStreamListener();
if (l == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
l->Init(receiver);
NS_ADDREF(l);
nsresult rv = l->Init(receiver, eventQueue);
if (NS_FAILED(rv)) {
NS_RELEASE(l);
return rv;
}
*result = l;
return NS_OK;
}

View File

@ -64,7 +64,7 @@ nsDirectoryIndexStream::~nsDirectoryIndexStream()
nsresult
nsDirectoryIndexStream::Create(const nsFileSpec& aDir, nsISupports** aResult)
nsDirectoryIndexStream::Create(const nsFileSpec& aDir, nsIInputStream** aResult)
{
nsDirectoryIndexStream* result = new nsDirectoryIndexStream();
if (! result)

View File

@ -39,7 +39,7 @@ protected:
public:
static nsresult
Create(const nsFileSpec& aDir, nsISupports** aStreamResult);
Create(const nsFileSpec& aDir, nsIInputStream** aStreamResult);
// nsISupportsInterface
NS_DECL_ISUPPORTS

View File

@ -43,7 +43,6 @@
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#if defined(PR_LOGGING)
@ -64,12 +63,201 @@ PRLogModuleInfo* gFileTransportLog = nsnull;
////////////////////////////////////////////////////////////////////////////////
#define DEFAULT_TYPE "text/html"
class nsLocalFileSystem : public nsIFileSystem
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD Open(char **contentType, PRInt32 *contentLength) {
// don't actually open the file here -- we'll do it on demand in the
// GetInputStream/GetOutputStream methods
nsresult rv = NS_OK;
*contentLength = mSpec.GetFileSize();
if (mSpec.IsDirectory()) {
*contentType = nsCRT::strdup("application/http-index-format");
}
else {
const char* fileName = mSpec.GetLeafName();
PRInt32 len = nsCRT::strlen(fileName);
const char* ext = nsnull;
for (PRInt32 i = len; i >= 0; i--) {
if (fileName[i] == '.') {
ext = &fileName[i + 1];
break;
}
}
if (ext) {
NS_WITH_SERVICE(nsIMIMEService, mimeServ, kMIMEServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = mimeServ->GetTypeFromExtension(ext, contentType);
}
}
else
rv = NS_ERROR_FAILURE;
if (NS_FAILED(rv)) {
// if all else fails treat it as text/html?
*contentType = nsCRT::strdup(DEFAULT_TYPE);
if (*contentType == nsnull)
rv = NS_ERROR_OUT_OF_MEMORY;
else
rv = NS_OK;
}
}
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: logically opening %s: type=%s len=%d",
(const char*)mSpec, *contentType, *contentLength));
return rv;
}
NS_IMETHOD Close(nsresult status) {
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: logically closing %s: status=%x",
(const char*)mSpec, status));
return NS_OK;
}
NS_IMETHOD GetInputStream(nsIInputStream * *aInputStream) {
nsresult rv;
if (mSpec.IsDirectory()) {
rv = nsDirectoryIndexStream::Create(mSpec, aInputStream);
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: opening local dir %s for input (%x)",
(const char*)mSpec, rv));
return rv;
}
nsCOMPtr<nsISupports> in;
rv = NS_NewTypicalInputFileStream(getter_AddRefs(in), mSpec);
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: opening local file %s for input (%x)",
(const char*)mSpec, rv));
if (NS_FAILED(rv)) return rv;
return in->QueryInterface(NS_GET_IID(nsIInputStream), (void**)aInputStream);
}
NS_IMETHOD GetOutputStream(nsIOutputStream * *aOutputStream) {
nsresult rv;
nsCOMPtr<nsISupports> out;
if (mSpec.IsDirectory()) {
return NS_ERROR_FAILURE;
}
rv = NS_NewTypicalOutputFileStream(getter_AddRefs(out), mSpec);
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: opening local file %s for output (%x)",
(const char*)mSpec, rv));
if (NS_FAILED(rv)) return rv;
return out->QueryInterface(NS_GET_IID(nsIOutputStream), (void**)aOutputStream);
}
nsLocalFileSystem(nsFileSpec& fileSpec) : mSpec(fileSpec) {
NS_INIT_REFCNT();
}
virtual ~nsLocalFileSystem() {}
static nsresult Create(nsFileSpec& fileSpec, nsIFileSystem* *result) {
nsLocalFileSystem* fs = new nsLocalFileSystem(fileSpec);
if (fs == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(fs);
*result = fs;
return NS_OK;
}
protected:
nsFileSpec mSpec;
};
NS_IMPL_ISUPPORTS1(nsLocalFileSystem, nsIFileSystem);
////////////////////////////////////////////////////////////////////////////////
class nsInputStreamFileSystem : public nsIFileSystem
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD Open(char **contentType, PRInt32 *contentLength) {
*contentType = nsCRT::strdup(mContentType);
if (*contentType == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
*contentLength = mContentLength;
return NS_OK;
}
NS_IMETHOD Close(nsresult status) {
return NS_OK;
}
NS_IMETHOD GetInputStream(nsIInputStream * *aInputStream) {
*aInputStream = mInput;
NS_ADDREF(*aInputStream);
return NS_OK;
}
NS_IMETHOD GetOutputStream(nsIOutputStream * *aOutputStream) {
return NS_ERROR_FAILURE; // we only do input here
}
nsInputStreamFileSystem() {
NS_INIT_REFCNT();
}
nsresult Init(nsIInputStream* in, const char* contentType,
PRInt32 contentLength) {
mInput = in;
NS_ASSERTION(contentType, "content type not supplied");
mContentType = nsCRT::strdup(contentType);
if (mContentType == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
mContentLength = contentLength;
return NS_OK;
}
virtual ~nsInputStreamFileSystem() {
if (mContentType) nsCRT::free(mContentType);
}
static nsresult Create(nsIInputStream* in, const char* contentType,
PRInt32 contentLength, nsIFileSystem* *result) {
nsInputStreamFileSystem* fs = new nsInputStreamFileSystem();
if (fs == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(fs);
nsresult rv = fs->Init(in, contentType, contentLength);
if (NS_FAILED(rv)) {
NS_RELEASE(fs);
return rv;
}
*result = fs;
return NS_OK;
}
protected:
nsCOMPtr<nsIInputStream> mInput;
char* mContentType;
PRInt32 mContentLength;
};
NS_IMPL_ISUPPORTS1(nsInputStreamFileSystem, nsIFileSystem);
////////////////////////////////////////////////////////////////////////////////
nsFileTransport::nsFileTransport()
: mState(QUIESCENT),
: mContentType(nsnull),
mState(CLOSED),
mCommand(NONE),
mSuspended(PR_FALSE),
mMonitor(nsnull),
mStatus(NS_OK),
mOffset(0),
mTotalAmount(-1),
mTransferAmount(0),
mBuffer(nsnull)
{
NS_INIT_REFCNT();
@ -88,12 +276,16 @@ nsFileTransport::nsFileTransport()
nsresult
nsFileTransport::Init(nsFileSpec& spec, const char* command, nsIEventSinkGetter* getter)
{
nsresult rv;
if (mMonitor == nsnull) {
mMonitor = nsAutoMonitor::NewMonitor("nsFileTransport");
if (mMonitor == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
}
mSpec = spec;
rv = nsLocalFileSystem::Create(spec, getter_AddRefs(mFileObject));
if (NS_FAILED(rv))
return rv;
if (getter) {
nsCOMPtr<nsISupports> sink;
(void)getter->GetEventSink(command, nsIProgressEventSink::GetIID(), getter_AddRefs(sink));
@ -103,14 +295,16 @@ nsFileTransport::Init(nsFileSpec& spec, const char* command, nsIEventSinkGetter*
}
nsresult
nsFileTransport::Init(nsIInputStream* fromStream, const char* command, nsIEventSinkGetter* getter)
nsFileTransport::Init(nsIInputStream* fromStream, const char* contentType,
PRInt32 contentLength, const char* command, nsIEventSinkGetter* getter)
{
if (mMonitor == nsnull) {
mMonitor = nsAutoMonitor::NewMonitor("nsFileTransport");
if (mMonitor == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
}
mSource = fromStream;
nsInputStreamFileSystem::Create(fromStream, contentType, contentLength,
getter_AddRefs(mFileObject));
if (getter) {
nsCOMPtr<nsISupports> sink;
(void)getter->GetEventSink(command, nsIProgressEventSink::GetIID(), getter_AddRefs(sink));
@ -121,6 +315,10 @@ nsFileTransport::Init(nsIInputStream* fromStream, const char* command, nsIEventS
nsFileTransport::~nsFileTransport()
{
if (mState != CLOSED) {
mState = CLOSING;
Process();
}
NS_ASSERTION(mSource == nsnull, "transport not closed");
NS_ASSERTION(mBufferInputStream == nsnull, "transport not closed");
NS_ASSERTION(mBufferOutputStream == nsnull, "transport not closed");
@ -128,6 +326,8 @@ nsFileTransport::~nsFileTransport()
NS_ASSERTION(mBuffer == nsnull, "transport not closed");
if (mMonitor)
nsAutoMonitor::DestroyMonitor(mMonitor);
if (mContentType)
nsCRT::free(mContentType);
}
NS_IMETHODIMP
@ -176,7 +376,7 @@ nsFileTransport::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
NS_IMETHODIMP
nsFileTransport::IsPending(PRBool *result)
{
*result = mState != QUIESCENT;
*result = mState != CLOSED;
return NS_OK;
}
@ -250,7 +450,7 @@ nsFileTransport::OpenInputStream(PRUint32 startPosition, PRInt32 readCount,
nsresult rv;
if (mState != QUIESCENT)
if (mState != CLOSED)
return NS_ERROR_IN_PROGRESS;
if (!mSpec.Exists())
@ -266,9 +466,10 @@ nsFileTransport::OpenInputStream(PRUint32 startPosition, PRInt32 readCount,
rv = mBufferOutputStream->SetNonBlocking(PR_TRUE);
if (NS_FAILED(rv)) return rv;
mState = START_READ;
mState = OPENING;
mCommand = INITIATE_READ;
mOffset = startPosition;
mAmount = readCount;
mTransferAmount = readCount;
mListener = null_nsCOMPtr();
*result = mBufferInputStream.get();
@ -292,7 +493,7 @@ nsFileTransport::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **resu
nsresult rv;
if (mState != QUIESCENT)
if (mState != CLOSED)
return NS_ERROR_IN_PROGRESS;
NS_ASSERTION(startPosition == 0, "implement startPosition");
@ -307,6 +508,41 @@ nsFileTransport::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **resu
return rv;
}
NS_IMETHODIMP
nsFileTransport::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
nsAutoMonitor mon(mMonitor);
nsresult rv = NS_OK;
if (mState != CLOSED)
return NS_ERROR_IN_PROGRESS;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(observer, "need to supply an nsIStreamObserver");
rv = serv->NewAsyncStreamObserver(observer, nsnull, getter_AddRefs(mOpenObserver));
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(mOpenContext == nsnull, "context not released");
mOpenContext = ctxt;
mState = OPENING;
NS_ASSERTION(mCommand == NONE, "out of sync");
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: AsyncOpen [this=%x %s]",
this, (const char*)mSpec));
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = fts->DispatchRequest(this);
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
nsFileTransport::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
nsISupports *ctxt,
@ -316,18 +552,15 @@ nsFileTransport::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
nsresult rv = NS_OK;
if ((mState != CLOSED && mState != OPENING && mState != OPENED)
|| mCommand != NONE)
return NS_ERROR_IN_PROGRESS;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> eventQueue;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), getter_AddRefs(eventQueue));
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(listener, "need to supply an nsIStreamListener");
rv = serv->NewAsyncStreamListener(listener, eventQueue, getter_AddRefs(mListener));
rv = serv->NewAsyncStreamListener(listener, nsnull, getter_AddRefs(mListener));
if (NS_FAILED(rv)) return rv;
rv = NS_NewPipe(getter_AddRefs(mBufferInputStream),
@ -337,16 +570,19 @@ nsFileTransport::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
NS_FILE_TRANSPORT_BUFFER_SIZE);
if (NS_FAILED(rv)) return rv;
rv = mBufferInputStream->SetNonBlocking(PR_TRUE);
if (NS_FAILED(rv)) return rv;
rv = mBufferOutputStream->SetNonBlocking(PR_TRUE);
if (NS_FAILED(rv)) return rv;
NS_ASSERTION(mContext == nsnull, "context not released");
mContext = ctxt;
mState = START_READ;
if (mState == CLOSED)
mState = OPENING;
mCommand = INITIATE_READ;
mOffset = startPosition;
mAmount = readCount;
mTotalAmount = 0;
mTransferAmount = readCount;
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: AsyncRead [this=%x %s]",
@ -370,29 +606,27 @@ nsFileTransport::AsyncWrite(nsIInputStream *fromStream,
nsresult rv = NS_OK;
if ((mState != CLOSED && mState != OPENING && mState != OPENED)
|| mCommand != NONE)
return NS_ERROR_IN_PROGRESS;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIEventQueue> eventQueue;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), getter_AddRefs(eventQueue));
if (NS_FAILED(rv)) return rv;
if (observer) {
rv = serv->NewAsyncStreamObserver(observer, eventQueue, getter_AddRefs(mObserver));
rv = serv->NewAsyncStreamObserver(observer, nsnull, getter_AddRefs(mObserver));
if (NS_FAILED(rv)) return rv;
}
NS_ASSERTION(mContext == nsnull, "context not released");
mContext = ctxt;
mState = START_WRITE;
if (mState == CLOSED)
mState = OPENING;
mCommand = INITIATE_WRITE;
mOffset = startPosition;
mAmount = writeCount;
mTransferAmount = writeCount;
mSource = fromStream;
mTotalAmount = 0;
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: AsyncWrite [this=%x %s]",
@ -413,7 +647,7 @@ nsFileTransport::AsyncWrite(nsIInputStream *fromStream,
NS_IMETHODIMP
nsFileTransport::Run(void)
{
while (mState != QUIESCENT && !mSuspended) {
while (mState != CLOSED && mState != OPENED && !mSuspended) {
Process();
}
return NS_OK;
@ -437,33 +671,52 @@ nsFileTransport::Process(void)
nsAutoMonitor mon(mMonitor);
switch (mState) {
case START_READ: {
if (mListener) {
mStatus = mListener->OnStartRequest(this, mContext); // always send the start notification
case OPENING: {
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: OPENING [this=%x %s]",
this, (const char*)mSpec));
mStatus = mFileObject->Open(&mContentType, &mTotalAmount);
if (NS_FAILED(mStatus)) {
mState = CLOSING;
return;
}
if (mOpenObserver) {
mStatus = mOpenObserver->OnStartRequest(this, mOpenContext);
if (NS_FAILED(mStatus)) {
mState = END_READ;
mState = CLOSING;
return;
}
}
switch (mCommand) {
case INITIATE_READ:
mState = START_READ;
break;
case INITIATE_WRITE:
mState = START_WRITE;
break;
default:
mState = OPENED;
break;
}
break;
}
if (mSource == nsnull) {
nsCOMPtr<nsISupports> fs;
case OPENED: {
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: OPENED [this=%x %s]",
this, (const char*)mSpec));
break;
}
if (mSpec.IsDirectory()) {
mStatus = nsDirectoryIndexStream::Create(mSpec, getter_AddRefs(fs));
}
else {
mStatus = NS_NewTypicalInputFileStream(getter_AddRefs(fs), mSpec);
}
if (NS_FAILED(mStatus)) {
mState = END_READ;
return;
}
mSource = do_QueryInterface(fs, &mStatus);
if (NS_FAILED(mStatus)) {
mState = END_READ;
return;
}
case START_READ: {
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: START_READ [this=%x %s]",
this, (const char*)mSpec));
mStatus = mFileObject->GetInputStream(getter_AddRefs(mSource));
if (NS_FAILED(mStatus)) {
mState = END_READ;
return;
}
if (mOffset > 0) {
@ -483,123 +736,108 @@ nsFileTransport::Process(void)
}
// capture the total amount for progress information
if (mProgress) {
(void)mSource->Available(&mTotalAmount); // XXX should be content length
if (mTransferAmount < 0) {
mTransferAmount = mTotalAmount;
}
mTotalAmount = mTransferAmount;
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: START_READ [this=%x %s]",
this, (const char*)mSpec));
if (mListener) {
mStatus = mListener->OnStartRequest(this, mContext); // always send the start notification
if (NS_FAILED(mStatus)) {
mState = END_READ;
return;
}
}
mState = READING;
break;
}
case READING: {
if (NS_FAILED(mStatus)) {
mState = END_READ;
return;
}
PRUint32 inLen;
mStatus = mSource->Available(&inLen);
if (NS_FAILED(mStatus)) {
mState = END_READ;
return;
}
// if the user wanted to only read a fixed number of bytes
// we need to honor that...
if (mAmount >= 0)
inLen = PR_MIN(inLen, (PRUint32)mAmount);
PRUint32 amt;
mStatus = mBufferOutputStream->WriteFrom(mSource, inLen, &amt);
NS_ASSERTION(mTransferAmount >= 0, "bad mTransferAmount in READING");
PRUint32 writeAmt;
// and feed the buffer to the application via the buffer stream:
mStatus = mBufferOutputStream->WriteFrom(mSource, mTransferAmount, &writeAmt);
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: READING [this=%x %s] amt=%d status=%x",
this, (const char*)mSpec, amt, mStatus));
this, (const char*)mSpec, writeAmt, mStatus));
if (mStatus == NS_BASE_STREAM_WOULD_BLOCK) {
mStatus = NS_OK;
return;
}
if (NS_FAILED(mStatus) || amt == 0) {
if (NS_FAILED(mStatus) || writeAmt == 0) {
mState = END_READ;
return;
}
// and feed the buffer to the application via the buffer stream:
mTransferAmount -= writeAmt;
PRUint32 offset = mOffset;
mOffset += writeAmt;
if (mListener) {
mStatus = mListener->OnDataAvailable(this, mContext,
mBufferInputStream,
mOffset, amt);
offset, writeAmt);
if (NS_FAILED(mStatus)) {
mState = END_READ;
return;
}
}
mOffset += amt;
if (mProgress) {
(void)mProgress->OnProgress(this, mContext, mOffset, mTotalAmount);
nsresult rv = mProgress->OnProgress(this, mContext,
mTotalAmount - mTransferAmount,
mTotalAmount);
NS_ASSERTION(NS_SUCCEEDED(rv), "unexpected OnProgress failure");
}
if (mAmount >= 0) {
mAmount -= amt;
if (mAmount == 0) {
mState = END_READ;
return;
}
if (mTransferAmount == 0) {
mState = END_READ;
return;
}
// stay in the READING state
break;
}
case END_READ: {
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: ENDING [this=%x %s] status=%x",
("nsFileTransport: END_READ [this=%x %s] status=%x",
this, (const char*)mSpec, mStatus));
NS_ASSERTION(mTransferAmount == 0 || NS_FAILED(mStatus), "didn't transfer all the data");
mBufferOutputStream->Flush();
mBufferOutputStream = null_nsCOMPtr();
mBufferInputStream = null_nsCOMPtr();
mSource = null_nsCOMPtr();
mState = QUIESCENT;
mSource = null_nsCOMPtr();
if (mListener) {
// XXX where do we get the done message?
(void)mListener->OnStopRequest(this, mContext, mStatus, nsnull);
nsresult rv = mListener->OnStopRequest(this, mContext, mStatus, nsnull);
NS_ASSERTION(NS_SUCCEEDED(rv), "unexpected OnStopRequest failure");
mListener = null_nsCOMPtr();
}
if (mProgress) {
// XXX fix up this message for i18n
nsAutoString msg = "Read ";
msg += (const char*)mSpec;
(void)mProgress->OnStatus(this, mContext, msg.mUStr);
}
mContext = null_nsCOMPtr();
mState = OPENED; // stay in the opened state for the next read/write request
mCommand = NONE;
break;
}
case START_WRITE: {
if (mObserver) {
mStatus = mObserver->OnStartRequest(this, mContext); // always send the start notification
if (NS_FAILED(mStatus)) {
mState = END_WRITE;
return;
}
}
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: START_WRITE [this=%x %s]",
this, (const char*)mSpec));
if (mSink == nsnull) {
nsCOMPtr<nsISupports> fs;
mStatus = NS_NewTypicalOutputFileStream(getter_AddRefs(fs), mSpec);
if (NS_FAILED(mStatus)) {
mState = END_WRITE;
return;
}
mSink = do_QueryInterface(fs, &mStatus);
if (NS_FAILED(mStatus)) {
mState = END_WRITE;
return;
}
mStatus = mFileObject->GetOutputStream(getter_AddRefs(mSink));
if (NS_FAILED(mStatus)) {
mState = END_WRITE;
return;
}
if (mOffset > 0) {
@ -634,26 +872,22 @@ nsFileTransport::Process(void)
}
}
// capture the total amount for progress information
if (mProgress) {
(void)mSource->Available(&mTotalAmount); // XXX should be content length
if (mObserver) {
mStatus = mObserver->OnStartRequest(this, mContext); // always send the start notification
if (NS_FAILED(mStatus)) {
mState = END_WRITE;
return;
}
}
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: START_WRITE [this=%x %s]",
this, (const char*)mSpec));
mState = WRITING;
break;
}
case WRITING: {
if (NS_FAILED(mStatus)) {
mState = END_WRITE;
return;
}
case WRITING: {
PRUint32 transferAmt = NS_FILE_TRANSPORT_SEGMENT_SIZE;
if (mAmount >= 0)
transferAmt = PR_MIN(NS_FILE_TRANSPORT_SEGMENT_SIZE, mAmount);
if (mTransferAmount >= 0)
transferAmt = PR_MIN(NS_FILE_TRANSPORT_SEGMENT_SIZE, mTransferAmount);
PRUint32 writeAmt;
if (mBufferInputStream) {
mStatus = mBufferInputStream->ReadSegments(nsWriteToFile, mSink,
@ -684,18 +918,23 @@ nsFileTransport::Process(void)
return;
}
mTransferAmount -= writeAmt;
mOffset += writeAmt;
if (mProgress) {
(void)mProgress->OnProgress(this, mContext, mOffset, mTotalAmount);
(void)mProgress->OnProgress(this, mContext,
mTotalAmount - mTransferAmount,
mTotalAmount);
}
// stay in the WRITING state
break;
}
case END_WRITE: {
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: ENDING [this=%x %s] status=%x",
("nsFileTransport: END_WRITE [this=%x %s] status=%x",
this, (const char*)mSpec, mStatus));
mSink->Flush();
if (mBufferInputStream)
mBufferInputStream = null_nsCOMPtr();
@ -706,7 +945,7 @@ nsFileTransport::Process(void)
mSink = null_nsCOMPtr();
mSource = null_nsCOMPtr();
mState = QUIESCENT;
mState = OPENED;
if (mObserver) {
// XXX where do we get the done message?
@ -714,15 +953,38 @@ nsFileTransport::Process(void)
mObserver = null_nsCOMPtr();
}
if (mProgress) {
// XXX fix up this message for i18n
nsAutoString msg = "Wrote ";
msg += (const char*)mSpec;
(void)mProgress->OnStatus(this, mContext, msg.mUStr);
}
mContext = null_nsCOMPtr();
mState = OPENED; // stay in the opened state for the next read/write request
mCommand = NONE;
break;
}
case QUIESCENT: {
case CLOSING: {
PR_LOG(gFileTransportLog, PR_LOG_DEBUG,
("nsFileTransport: CLOSING [this=%x %s] status=%x",
this, (const char*)mSpec, mStatus));
if (mOpenObserver) {
(void)mOpenObserver->OnStopRequest(this, mOpenContext,
mStatus, nsnull); // XXX fix error message
mOpenObserver = null_nsCOMPtr();
mOpenContext = null_nsCOMPtr();
}
if (mFileObject) {
nsresult rv = mFileObject->Close(mStatus);
NS_ASSERTION(NS_SUCCEEDED(rv), "unexpected Close failure");
mFileObject = null_nsCOMPtr();
}
break;
}
case CLOSED: {
NS_NOTREACHED("trying to continue a quiescent file transfer");
break;
}
@ -776,13 +1038,17 @@ nsFileTransport::SetLoadAttributes(nsLoadFlags aLoadAttributes)
NS_IMETHODIMP
nsFileTransport::GetContentType(char * *aContentType)
{
return NS_ERROR_NOT_IMPLEMENTED;
*aContentType = nsCRT::strdup(mContentType);
if (*aContentType == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsFileTransport::GetContentLength(PRInt32 *aContentLength)
{
return NS_ERROR_NOT_IMPLEMENTED;
*aContentLength = mTotalAmount;
return NS_OK;
}
NS_IMETHODIMP

View File

@ -31,6 +31,7 @@
#include "nsIProgressEventSink.h"
#include "nsIBufferInputStream.h"
#include "nsIBufferOutputStream.h"
#include "nsIFileSystem.h"
class nsIEventSinkGetter;
@ -57,35 +58,52 @@ public:
const char* command,
nsIEventSinkGetter* getter);
nsresult Init(nsIInputStream* fromStream,
const char* contentType,
PRInt32 contentLength,
const char* command,
nsIEventSinkGetter* getter);
void Process(void);
enum State {
QUIESCENT,
CLOSED,
OPENING,
OPENED,
START_READ,
READING,
END_READ,
START_WRITE,
WRITING,
END_WRITE
END_WRITE,
CLOSING
};
enum Command {
NONE,
INITIATE_READ,
INITIATE_WRITE
};
protected:
nsCOMPtr<nsIProgressEventSink> mProgress;
nsFileSpec mSpec;
nsFileSpec mSpec; // eliminate?
nsCOMPtr<nsIFileSystem> mFileObject;
char* mContentType;
nsCOMPtr<nsIStreamObserver> mOpenObserver;
nsCOMPtr<nsISupports> mOpenContext;
nsCOMPtr<nsISupports> mContext;
State mState;
Command mCommand;
PRBool mSuspended;
PRMonitor* mMonitor;
// state variables:
nsresult mStatus;
PRUint32 mOffset;
PRInt32 mAmount;
PRUint32 mTotalAmount;
PRInt32 mTotalAmount;
PRInt32 mTransferAmount;
// reading state varialbles:
nsCOMPtr<nsIStreamListener> mListener;

View File

@ -34,7 +34,6 @@ static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
////////////////////////////////////////////////////////////////////////////////
nsFileTransportService::nsFileTransportService()
: mPool(nsnull), mSuspended(nsnull)
{
NS_INIT_REFCNT();
}
@ -45,7 +44,7 @@ nsresult
nsFileTransportService::Init()
{
nsresult rv;
rv = NS_NewThreadPool(&mPool, NS_FILE_TRANSPORT_WORKER_COUNT,
rv = NS_NewThreadPool(getter_AddRefs(mPool), NS_FILE_TRANSPORT_WORKER_COUNT,
NS_FILE_TRANSPORT_WORKER_COUNT,
NS_FILE_TRANSPORT_WORKER_STACK_SIZE);
return rv;
@ -54,8 +53,6 @@ nsFileTransportService::Init()
nsFileTransportService::~nsFileTransportService()
{
mPool->Shutdown();
NS_IF_RELEASE(mPool);
NS_IF_RELEASE(mSuspended);
}
NS_IMPL_ISUPPORTS(nsFileTransportService, NS_GET_IID(nsFileTransportService));
@ -102,6 +99,8 @@ nsFileTransportService::CreateTransport(nsFileSpec& spec,
NS_IMETHODIMP
nsFileTransportService::CreateTransportFromStream(nsIInputStream *fromStream,
const char* contentType,
PRInt32 contentLength,
const char *command,
nsIEventSinkGetter *getter,
nsIChannel** result)
@ -111,7 +110,7 @@ nsFileTransportService::CreateTransportFromStream(nsIInputStream *fromStream,
if (trans == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(trans);
rv = trans->Init(fromStream, command, getter);
rv = trans->Init(fromStream, contentType, contentLength, command, getter);
if (NS_FAILED(rv)) {
NS_RELEASE(trans);
return rv;
@ -146,7 +145,7 @@ nsFileTransportService::Suspend(nsIRunnable* request)
nsresult rv;
nsAutoCMonitor mon(this); // protect mSuspended
if (mSuspended == nsnull) {
rv = NS_NewISupportsArray(&mSuspended);
rv = NS_NewISupportsArray(getter_AddRefs(mSuspended));
if (NS_FAILED(rv)) return rv;
}
return mSuspended->AppendElement(request) ? NS_OK : NS_ERROR_FAILURE; // XXX this method incorrectly returns a bool

View File

@ -44,8 +44,9 @@ public:
nsresult Init();
protected:
nsIThreadPool* mPool;
nsISupportsArray* mSuspended;
nsCOMPtr<nsIThreadPool> mPool;
nsCOMPtr<nsISupportsArray> mOpened;
nsCOMPtr<nsISupportsArray> mSuspended;
};
#endif /* nsFileTransportService_h___ */

View File

@ -414,7 +414,8 @@ nsIOService::NewLoadGroup(nsISupports* outer, nsIStreamObserver* observer,
}
NS_IMETHODIMP
nsIOService::NewInputStreamChannel(nsIURI* uri, const char *contentType,
nsIOService::NewInputStreamChannel(nsIURI* uri, const char *contentType,
PRInt32 contentLength,
nsIInputStream *inStr, nsILoadGroup* group,
nsIChannel **result)
{
@ -423,7 +424,7 @@ nsIOService::NewInputStreamChannel(nsIURI* uri, const char *contentType,
rv = nsInputStreamChannel::Create(nsnull, NS_GET_IID(nsIChannel),
(void**)&channel);
if (NS_FAILED(rv)) return rv;
rv = channel->Init(uri, contentType, inStr, group);
rv = channel->Init(uri, contentType, contentLength, inStr, group);
if (NS_FAILED(rv)) {
NS_RELEASE(channel);
return rv;

View File

@ -22,6 +22,7 @@
#include "nsIServiceManager.h"
#include "nsIMIMEService.h"
#include "nsIFileTransportService.h"
#include "netCore.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_CID);
@ -31,7 +32,7 @@ static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
// nsInputStreamChannel methods:
nsInputStreamChannel::nsInputStreamChannel()
: mContentType(nsnull)
: mContentType(nsnull), mContentLength(-1)
{
NS_INIT_REFCNT();
}
@ -56,10 +57,12 @@ nsInputStreamChannel::Create(nsISupports *aOuter, REFNSIID aIID,
nsresult
nsInputStreamChannel::Init(nsIURI* uri, const char* contentType,
PRInt32 contentLength,
nsIInputStream* in, nsILoadGroup* group)
{
mURI = uri;
mLoadGroup = group;
mContentLength = contentLength;
nsCAutoString cType(contentType);
cType.ToLowerCase();
mContentType = cType.ToNewCString();
@ -122,6 +125,24 @@ nsInputStreamChannel::GetURI(nsIURI * *aURI)
return NS_OK;
}
NS_IMETHODIMP
nsInputStreamChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
if (mFileTransport)
return NS_ERROR_IN_PROGRESS;
nsresult rv;
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = fts->CreateTransportFromStream(mInputStream, mContentType, mContentLength,
"load", nsnull,
getter_AddRefs(mFileTransport));
if (NS_FAILED(rv)) return rv;
return mFileTransport->AsyncOpen(observer, ctxt);
}
NS_IMETHODIMP
nsInputStreamChannel::OpenInputStream(PRUint32 startPosition, PRInt32 readCount,
nsIInputStream **result)
@ -144,32 +165,6 @@ NS_IMETHODIMP
nsInputStreamChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
nsISupports *ctxt, nsIStreamListener *listener)
{
#if 0
// currently this happens before AsyncRead returns -- hope that's ok
nsresult rv;
// Do an extra AddRef so that this method's synchronous operation doesn't end up destroying
// the listener prematurely.
nsCOMPtr<nsIStreamListener> l(listener);
rv = listener->OnStartRequest(this, ctxt);
if (NS_FAILED(rv)) return rv;
PRUint32 amt;
while (PR_TRUE) {
rv = mInputStream->Available(&amt);
if (NS_FAILED(rv)) break;
if (amt == 0)
break;
if (readCount != -1)
amt = PR_MIN((PRUint32)readCount, amt);
rv = listener->OnDataAvailable(this, ctxt, mInputStream, 0, amt);
if (NS_FAILED(rv)) break;
}
rv = listener->OnStopRequest(this, ctxt, rv, nsnull); // XXX error message
return rv;
#else
nsresult rv;
mRealListener = listener;
@ -193,15 +188,17 @@ nsInputStreamChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
if (NS_FAILED(rv)) return rv;
}
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
if (mFileTransport == nsnull) {
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = fts->CreateTransportFromStream(mInputStream, "load", nsnull,
getter_AddRefs(mFileTransport));
if (NS_FAILED(rv)) return rv;
rv = fts->CreateTransportFromStream(mInputStream, mContentType, mContentLength,
"load", nsnull,
getter_AddRefs(mFileTransport));
if (NS_FAILED(rv)) return rv;
}
return mFileTransport->AsyncRead(startPosition, readCount, ctxt, this);
#endif
}
NS_IMETHODIMP
@ -227,55 +224,20 @@ nsInputStreamChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
return NS_OK;
}
#define DUMMY_TYPE "text/html"
NS_IMETHODIMP
nsInputStreamChannel::GetContentType(char * *aContentType)
{
nsresult rv = NS_OK;
// Parameter validation...
if (!aContentType) {
return NS_ERROR_NULL_POINTER;
*aContentType = nsCRT::strdup(mContentType);
if (*aContentType == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
*aContentType = nsnull;
// If we already have a content type, use it.
if (mContentType) {
*aContentType = nsCRT::strdup(mContentType);
if (!*aContentType) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
return rv;
}
//
// No response yet... Try to determine the content-type based
// on the file extension of the URI...
//
NS_WITH_SERVICE(nsIMIMEService, MIMEService, kMIMEServiceCID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = MIMEService->GetTypeFromURI(mURI, aContentType);
if (NS_SUCCEEDED(rv)) return rv;
}
// if all else fails treat it as text/html?
if (!*aContentType)
*aContentType = nsCRT::strdup(DUMMY_TYPE);
if (!*aContentType) {
rv = NS_ERROR_OUT_OF_MEMORY;
} else {
rv = NS_OK;
}
return rv;
return NS_OK;
}
NS_IMETHODIMP
nsInputStreamChannel::GetContentLength(PRInt32 *aContentLength)
{
// The content length is unknown...
*aContentLength = -1;
*aContentLength = mContentLength;
return NS_OK;
}

View File

@ -44,11 +44,13 @@ public:
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
nsresult Init(nsIURI* uri, const char* contentType,
PRInt32 contentLength,
nsIInputStream* in, nsILoadGroup* group);
protected:
nsCOMPtr<nsIURI> mURI;
char* mContentType;
PRInt32 mContentLength;
nsCOMPtr<nsIInputStream> mInputStream;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsISupports> mOwner;

View File

@ -35,7 +35,6 @@
#include "nsISocketProviderService.h"
#include "nsStdURL.h"
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kSocketProviderService, NS_SOCKETPROVIDERSERVICE_CID);
static NS_DEFINE_CID(kDNSService, NS_DNSSERVICE_CID);
@ -431,13 +430,16 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
case eSocketState_WaitConnect:
mStatus = doConnection(aSelectFlags);
if (NS_SUCCEEDED(mStatus) && mOpenObserver) {
mOpenObserver->OnStartRequest(this, mOpenContext);
}
break;
case eSocketState_WaitReadWrite:
// Process the read request...
if (GetReadType() != eSocketRead_None) {
mStatus = doRead(aSelectFlags);
if (NS_OK == mStatus) {
if (NS_SUCCEEDED(mStatus)) {
SetFlag(eSocketRead_Done);
break;
}
@ -446,7 +448,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
if ((NS_SUCCEEDED(mStatus) || mStatus == NS_BASE_STREAM_WOULD_BLOCK)
&& (GetWriteType() != eSocketWrite_None)) {
mStatus = doWrite(aSelectFlags);
if (NS_OK == mStatus) {
if (NS_SUCCEEDED(mStatus)) {
SetFlag(eSocketWrite_Done);
break;
}
@ -467,7 +469,7 @@ nsresult nsSocketTransport::Process(PRInt16 aSelectFlags)
// If the current state has successfully completed, then move to the
// next state for the current operation...
//
if (NS_OK == mStatus) {
if (NS_SUCCEEDED(mStatus)) {
mCurrentState = gStateTable[mOperation][mCurrentState];
}
else if (NS_BASE_STREAM_WOULD_BLOCK == mStatus) {
@ -1016,7 +1018,7 @@ nsresult nsSocketTransport::doWriteFromStream(PRUint32 *aCount)
nsresult rv = NS_OK;
*aCount = 0;
while (NS_OK == rv) {
while (NS_SUCCEEDED(rv)) {
// Determine the amount of data to read from the input stream...
if ((mWriteCount > 0) && (mWriteCount < MAX_IO_TRANSFER_SIZE)) {
maxBytesToRead = mWriteCount;
@ -1083,7 +1085,14 @@ nsresult nsSocketTransport::CloseConnection(void)
if (NS_SUCCEEDED(rv)) {
mCurrentState = eSocketState_Closed;
}
if (mOpenObserver) {
nsresult rv2 = mOpenObserver->OnStopRequest(this, mOpenContext,
rv, nsnull); // XXX need error message
if (NS_SUCCEEDED(rv))
rv = rv2;
mOpenObserver = null_nsCOMPtr();
mOpenContext = null_nsCOMPtr();
}
return rv;
}
@ -1398,12 +1407,52 @@ nsSocketTransport::GetURI(nsIURI * *aURL)
return rv;
}
NS_IMETHODIMP
nsSocketTransport::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
nsresult rv = NS_OK;
// Enter the socket transport lock...
nsAutoLock aLock(mLock);
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("+++ Entering nsSocketTransport::AsyncOpen() [this=%x]\n", this));
// If a read is already in progress then fail...
if (GetReadType() != eSocketRead_None) {
rv = NS_ERROR_IN_PROGRESS;
}
// Create a marshalling open observer to receive notifications...
if (NS_SUCCEEDED(rv)) {
rv = NS_NewAsyncStreamObserver(getter_AddRefs(mOpenObserver),
nsnull, observer);
}
if (NS_SUCCEEDED(rv)) {
// Store the context used for this read...
mOpenContext = ctxt;
mOperation = eSocketOperation_Connect;
SetReadType(eSocketRead_None);
rv = mService->AddToWorkQ(this);
}
PR_LOG(gSocketLog, PR_LOG_DEBUG,
("--- Leaving nsSocketTransport::AsyncOpen() [this=%x]. rv = %x.\n",
this, rv));
return rv;
}
NS_IMETHODIMP
nsSocketTransport::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
nsISupports* aContext,
nsIStreamListener* aListener)
{
// XXX deal with startPosition and readCount parameters
NS_ASSERTION(startPosition == 0, "can't deal with offsets in socket transport");
nsresult rv = NS_OK;
// Enter the socket transport lock...
@ -1437,18 +1486,8 @@ nsSocketTransport::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
// Create a marshalling stream listener to receive notifications...
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIEventQueue> eventQ;
// Get the event queue of the current thread...
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_SUCCEEDED(rv)) {
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(),
getter_AddRefs(eventQ));
}
if (NS_SUCCEEDED(rv)) {
rv = NS_NewAsyncStreamListener(getter_AddRefs(mReadListener),
eventQ, aListener);
}
rv = NS_NewAsyncStreamListener(getter_AddRefs(mReadListener),
nsnull, aListener);
}
if (NS_SUCCEEDED(rv)) {
@ -1497,18 +1536,8 @@ nsSocketTransport::AsyncWrite(nsIInputStream* aFromStream,
// Create a marshalling stream observer to receive notifications...
if (aObserver) {
nsCOMPtr<nsIEventQueue> eventQ;
// Get the event queue of the current thread...
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_SUCCEEDED(rv)) {
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(),
getter_AddRefs(eventQ));
}
if (NS_SUCCEEDED(rv)) {
rv = NS_NewAsyncStreamObserver(getter_AddRefs(mWriteObserver),
eventQ, aObserver);
}
rv = NS_NewAsyncStreamObserver(getter_AddRefs(mWriteObserver),
nsnull, aObserver);
}
mWriteCount = writeCount;

View File

@ -196,6 +196,9 @@ protected:
PRInt32 mPort;
char* mSocketType;
nsCOMPtr<nsIStreamObserver> mOpenObserver;
nsCOMPtr<nsISupports> mOpenContext;
nsCOMPtr<nsISupports> mReadContext;
nsCOMPtr<nsIStreamListener> mReadListener;
nsCOMPtr<nsIBufferInputStream> mReadPipeIn;

View File

@ -25,7 +25,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
NS_IMPL_ISUPPORTS(nsAboutBlank, NS_GET_IID(nsIAboutModule));
static const char kBlankPage[] = "<html><body></body></html>";
static const char kBlankPage[] = "";
NS_IMETHODIMP
nsAboutBlank::NewChannel(const char *verb,
@ -48,7 +48,9 @@ nsAboutBlank::NewChannel(const char *verb,
NS_RELEASE(s);
if (NS_FAILED(rv)) return rv;
rv = serv->NewInputStreamChannel(aURI, "text/html", in, aGroup, &channel);
rv = serv->NewInputStreamChannel(aURI, "text/html",
nsCRT::strlen(kBlankPage),
in, aGroup, &channel);
NS_RELEASE(in);
if (NS_FAILED(rv)) return rv;

View File

@ -278,6 +278,12 @@ nsDataChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **_retva
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDataChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDataChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
nsISupports *ctxt,
@ -292,13 +298,7 @@ nsDataChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
// we'll just fire everything off at once because we've already got all
// the data.
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
if (NS_FAILED(rv)) return rv;
rv = serv->NewAsyncStreamListener(aListener, eventQ, &listener);
rv = serv->NewAsyncStreamListener(aListener, nsnull, &listener);
NS_RELEASE(eventQ);
if (NS_FAILED(rv)) return rv;

View File

@ -245,6 +245,12 @@ nsFileChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **result
return mFileTransport->OpenOutputStream(startPosition, result);
}
NS_IMETHODIMP
nsFileChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsFileChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
nsISupports *ctxt,

View File

@ -255,6 +255,12 @@ nsFTPChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **_retval
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsFTPChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
nsISupports *ctxt,

View File

@ -225,6 +225,12 @@ nsHTTPChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream **_retva
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsHTTPChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports* ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsHTTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
nsISupports *aContext,

View File

@ -84,7 +84,7 @@ nsHTTPResponseListener::~nsHTTPResponseListener()
NS_IF_RELEASE(mConsumer);
}
NS_IMPL_ISUPPORTS(nsHTTPResponseListener,NS_GET_IID(nsIStreamListener));
NS_IMPL_ISUPPORTS2(nsHTTPResponseListener, nsIStreamListener, nsIStreamObserver);
static NS_DEFINE_IID(kProxyObjectManagerIID, NS_IPROXYEVENT_MANAGER_IID);
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);

View File

@ -123,7 +123,8 @@ nsFTPDirListingConv::AsyncConvertData(const PRUnichar *aFromType, const PRUnicha
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = serv->NewInputStreamChannel(uri, "application/http-index-format", nsnull, nsnull, &mPartChannel);
rv = serv->NewInputStreamChannel(uri, "application/http-index-format", -1, // XXX fix contentLength
nsnull, nsnull, &mPartChannel);
NS_RELEASE(uri);
if (NS_FAILED(rv)) return rv;

View File

@ -147,6 +147,7 @@ nsMultiMixedConv::OnDataAvailable(nsIChannel *channel, nsISupports *ctxt,
// channel and call through to our listener.
mBoundaryStart = PR_TRUE;
nsCString contentTypeStr;
PRInt32 contentLength = -1;
NS_IF_RELEASE(mPartChannel);
@ -177,12 +178,14 @@ nsMultiMixedConv::OnDataAvailable(nsIChannel *channel, nsISupports *ctxt,
if (headerStr.Equals("content-type")) {
contentTypeStr = headerVal;
NS_RELEASE(header);
}
else if (headerStr.Equals("content-length")) {
contentLength = atoi(headerVal);
} else {
// XXX we need a way to set other header's such as cookies :/
// XXX maybe we just handle cookies directly here.
NS_RELEASE(header);
}
NS_RELEASE(header);
}
*headerCStr = '\n';
@ -197,7 +200,7 @@ nsMultiMixedConv::OnDataAvailable(nsIChannel *channel, nsISupports *ctxt,
if (contentTypeStr.Length() < 1)
contentTypeStr = "text/html"; // default to text/html, that's all we'll ever see anyway
rv = serv->NewInputStreamChannel(partURI, contentTypeStr.GetBuffer(),
rv = serv->NewInputStreamChannel(partURI, contentTypeStr.GetBuffer(), contentLength,
nsnull, nsnull, &mPartChannel);
NS_RELEASE(partURI);
if (NS_FAILED(rv)) return rv;

View File

@ -276,6 +276,7 @@ main(int argc, char* argv[])
rv = serv->NewURI("http://neverneverland.com", nsnull, &dummyURI);
if (NS_FAILED(rv)) return rv;
rv = serv->NewInputStreamChannel(dummyURI, "multipart/x-mixed-replace;boundary= --aBoundary",
-1, // XXX fix contentLength
nsnull, nsnull, &dummyChannel);
NS_RELEASE(dummyURI);
if (NS_FAILED(rv)) return rv;

View File

@ -49,7 +49,8 @@ public:
NS_IMETHOD OnStopRequest(nsIChannel *channel, nsISupports *ctxt,
nsresult status, const PRUnichar *errorMsg) {
printf("ending status=%0x total=%d\n", status, mTotal);
gDone = PR_TRUE;
if (--mStopCount == 0)
gDone = PR_TRUE;
return NS_OK;
}
@ -75,7 +76,7 @@ public:
return NS_OK;
}
MyListener() : mTotal(0) {
MyListener(PRUint32 stopCount = 1) : mTotal(0), mStopCount(stopCount) {
NS_INIT_REFCNT();
}
@ -104,9 +105,10 @@ public:
protected:
nsCOMPtr<nsIOutputStream> mOut;
PRUint32 mTotal;
PRUint32 mStopCount;
};
NS_IMPL_ISUPPORTS(MyListener, nsIStreamListener::GetIID());
NS_IMPL_ISUPPORTS2(MyListener, nsIStreamListener, nsIStreamObserver);
////////////////////////////////////////////////////////////////////////////////
@ -115,15 +117,6 @@ TestAsyncRead(const char* fileName, PRUint32 offset, PRInt32 length)
{
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->CreateThreadEventQueue();
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &gEventQ);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
@ -163,15 +156,6 @@ TestAsyncWrite(const char* fileName, PRUint32 offset, PRInt32 length)
{
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->CreateThreadEventQueue();
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &gEventQ);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
@ -214,6 +198,91 @@ TestAsyncWrite(const char* fileName, PRUint32 offset, PRInt32 length)
////////////////////////////////////////////////////////////////////////////////
class MyOpenObserver : public nsIStreamObserver
{
public:
NS_DECL_ISUPPORTS
NS_IMETHOD OnStartRequest(nsIChannel *channel, nsISupports *ctxt) {
nsresult rv;
char* contentType;
rv = channel->GetContentType(&contentType);
if (NS_FAILED(rv)) return rv;
PRInt32 length;
rv = channel->GetContentLength(&length);
if (NS_FAILED(rv)) return rv;
printf("stream opened: content type = %s, length = %d\n",
contentType, length);
nsCRT::free(contentType);
return NS_OK;
}
NS_IMETHOD OnStopRequest(nsIChannel *channel, nsISupports *ctxt,
nsresult status, const PRUnichar *errorMsg) {
printf("stream closed: status %x\n", status);
return NS_OK;
}
MyOpenObserver() { NS_INIT_REFCNT(); }
virtual ~MyOpenObserver() {}
};
NS_IMPL_ISUPPORTS1(MyOpenObserver, nsIStreamObserver);
nsresult
TestAsyncOpen(const char* fileName, PRUint32 offset, PRInt32 length)
{
nsresult rv;
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
nsFileSpec fs(fileName);
nsIChannel* fileTrans;
rv = fts->CreateTransport(fs, "load", nsnull, &fileTrans);
if (NS_FAILED(rv)) return rv;
MyListener* listener = new MyListener(1);
if (listener == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(listener);
rv = listener->Init(fs);
if (NS_FAILED(rv)) return rv;
MyOpenObserver* openObserver = new MyOpenObserver();
if (openObserver == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(openObserver);
gDone = PR_FALSE;
rv = fileTrans->AsyncOpen(openObserver, nsnull);
if (NS_FAILED(rv)) return rv;
rv = fileTrans->AsyncRead(offset + 10, length, nsnull, listener);
if (NS_FAILED(rv)) return rv;
#if 0
rv = fileTrans->AsyncRead(offset, length, nsnull, listener);
if (NS_FAILED(rv)) return rv;
rv = fileTrans->AsyncRead(offset + 100, length, nsnull, listener);
if (NS_FAILED(rv)) return rv;
#endif
while (!gDone) {
PLEvent* event;
rv = gEventQ->GetEvent(&event);
if (NS_FAILED(rv)) return rv;
rv = gEventQ->HandleEvent(event);
if (NS_FAILED(rv)) return rv;
}
NS_RELEASE(openObserver);
NS_RELEASE(listener);
NS_RELEASE(fileTrans);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
nsresult
NS_AutoregisterComponents()
{
@ -235,6 +304,15 @@ main(int argc, char* argv[])
rv = NS_AutoregisterComponents();
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->CreateThreadEventQueue();
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &gEventQ);
if (NS_FAILED(rv)) return rv;
rv = TestAsyncRead(fileName, 0, -1);
NS_ASSERTION(NS_SUCCEEDED(rv), "TestAsyncRead failed");
@ -244,5 +322,9 @@ main(int argc, char* argv[])
rv = TestAsyncRead(fileName, 10, 100);
NS_ASSERTION(NS_SUCCEEDED(rv), "TestAsyncRead failed");
rv = TestAsyncOpen(fileName, 10, 100);
NS_ASSERTION(NS_SUCCEEDED(rv), "TestAsyncOpen failed");
NS_RELEASE(gEventQ);
return NS_OK;
}

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
@ -63,6 +63,7 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static int gKeepRunning = 0;
static PRBool gVerbose = PR_FALSE;
static nsIEventQueue* gEventQ = nsnull;
static PRBool gTestAsyncOpen = PR_FALSE;
class URLLoadInfo : public nsISupports
{
@ -243,6 +244,7 @@ TestHTTPEventSink::OnRedirect(nsISupports* context, nsIURI* i_NewLocation)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
class InputTestConsumer : public nsIStreamListener
{
@ -254,10 +256,68 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
NS_DECL_NSISTREAMLISTENER
void SetAsyncOpenCompleted() { mAsyncOpenCompleted = PR_TRUE; }
protected:
PRBool mAsyncOpenCompleted;
};
////////////////////////////////////////////////////////////////////////////////
class OpenObserver : public nsIStreamObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
OpenObserver(InputTestConsumer* cons)
: mInputConsumer(cons) {
NS_INIT_REFCNT();
}
virtual ~OpenObserver() {}
protected:
InputTestConsumer* mInputConsumer;
};
NS_IMPL_ISUPPORTS1(OpenObserver, nsIStreamObserver);
NS_IMETHODIMP
OpenObserver::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
printf("\n+++ OpenObserver::OnStartRequest +++. Context = %p\n", context);
char* type;
PRInt32 length = -1;
nsresult rv;
rv = channel->GetContentType(&type);
NS_ASSERTION(NS_SUCCEEDED(rv), "GetContentType failed");
rv = channel->GetContentLength(&length);
NS_ASSERTION(NS_SUCCEEDED(rv), "GetContentLength failed");
printf(" contentType = %s length = %d\n", type, length);
nsCRT::free(type);
mInputConsumer->SetAsyncOpenCompleted();
return NS_OK;
}
NS_IMETHODIMP
OpenObserver::OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg)
{
printf("\n+++ OpenObserver::OnStopRequest (status = %x) +++."
"\tContext = %p\n",
aStatus, context);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
InputTestConsumer::InputTestConsumer()
: mAsyncOpenCompleted(PR_FALSE)
{
NS_INIT_REFCNT();
}
@ -273,6 +333,8 @@ NS_IMPL_ISUPPORTS(InputTestConsumer,NS_GET_IID(nsIStreamListener));
NS_IMETHODIMP
InputTestConsumer::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
NS_ASSERTION(!gTestAsyncOpen || mAsyncOpenCompleted, "AsyncOpen failed");
URLLoadInfo* info = (URLLoadInfo*)context;
if (info) {
info->mConnectTime = PR_Now() - info->mConnectTime;
@ -305,6 +367,8 @@ InputTestConsumer::OnDataAvailable(nsIChannel* channel,
PRUint32 aSourceOffset,
PRUint32 aLength)
{
NS_ASSERTION(!gTestAsyncOpen || mAsyncOpenCompleted, "AsyncOpen failed");
char buf[1025];
PRUint32 amt, size;
nsresult rv;
@ -339,6 +403,8 @@ InputTestConsumer::OnStopRequest(nsIChannel* channel,
nsresult aStatus,
const PRUnichar* aMsg)
{
NS_ASSERTION(!gTestAsyncOpen || mAsyncOpenCompleted, "AsyncOpen failed");
URLLoadInfo* info = (URLLoadInfo*)context;
if (info) {
@ -484,12 +550,25 @@ nsresult StartLoadingURL(const char* aUrlString)
return NS_ERROR_OUT_OF_MEMORY;;
}
if (gTestAsyncOpen) {
OpenObserver* obs = new OpenObserver(listener);
if (obs == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(obs);
rv = pChannel->AsyncOpen(obs, nsnull);
NS_RELEASE(obs);
if (NS_FAILED(rv)) {
NS_ERROR("Error: AsyncOpen failed...");
return rv;
}
}
URLLoadInfo* info;
info = new URLLoadInfo(aUrlString);
NS_IF_ADDREF(info);
if (!info) {
NS_ERROR("Failed to create a load info!");
return NS_ERROR_OUT_OF_MEMORY;;
return NS_ERROR_OUT_OF_MEMORY;
}
@ -610,6 +689,11 @@ main(int argc, char* argv[])
continue;
}
if (PL_strcasecmp(argv[i], "-asyncopen") == 0) {
gTestAsyncOpen = PR_TRUE;
continue;
}
printf("\t%s\n", argv[i]);
rv = StartLoadingURL(argv[i]);
}

View File

@ -95,8 +95,6 @@ void Pump_PLEvents(nsIEventQueueService * eventQService)
}
// -----
//
// TestConnection class...
@ -107,7 +105,8 @@ class TestConnection : public nsIRunnable,
public nsIStreamListener
{
public:
TestConnection(const char* aHostName, PRInt32 aPort, PRBool aAsyncFlag);
TestConnection(const char* aHostName, PRInt32 aPort,
PRBool aAsyncFlag, PRBool testAsyncRead);
virtual ~TestConnection();
NS_DECL_ISUPPORTS
@ -124,6 +123,8 @@ public:
nsresult Suspend(void);
nsresult Resume(void);
void SetAsyncOpenCompleted() { mAsyncOpenCompleted = PR_TRUE; }
protected:
#ifndef NSPIPE2
nsIBuffer* mBuffer;
@ -142,12 +143,60 @@ protected:
char mBufferChar;
PRInt32 mBytesRead;
PRBool mTestAsyncOpen;
PRBool mAsyncOpenCompleted;
};
////////////////////////////////////////////////////////////////////////////////
class TestConnectionOpenObserver : public nsIStreamObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMOBSERVER
TestConnectionOpenObserver(TestConnection* test)
: mTestConnection(test) {
NS_INIT_REFCNT();
}
virtual ~TestConnectionOpenObserver() {}
protected:
TestConnection* mTestConnection;
};
NS_IMPL_ISUPPORTS1(TestConnectionOpenObserver, nsIStreamObserver);
NS_IMETHODIMP
TestConnectionOpenObserver::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
printf("\n+++ TestConnectionOpenObserver::OnStartRequest +++. Context = %p\n", context);
mTestConnection->SetAsyncOpenCompleted();
return NS_OK;
}
NS_IMETHODIMP
TestConnectionOpenObserver::OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg)
{
printf("\n+++ TestConnectionOpenObserver::OnStopRequest (status = %x) +++."
"\tContext = %p\n",
aStatus, context);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
TestConnection::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
NS_ASSERTION(!mTestAsyncOpen || mAsyncOpenCompleted, "AsyncOpen failed");
printf("\n+++ TestConnection::OnStartRequest +++. Context = %p\n", context);
return NS_OK;
}
@ -159,6 +208,8 @@ TestConnection::OnDataAvailable(nsIChannel* channel, nsISupports* context,
PRUint32 aSourceOffset,
PRUint32 aLength)
{
NS_ASSERTION(!mTestAsyncOpen || mAsyncOpenCompleted, "AsyncOpen failed");
char buf[1025];
PRUint32 amt;
@ -187,6 +238,8 @@ TestConnection::OnStopRequest(nsIChannel* channel,
nsresult aStatus,
const PRUnichar* aMsg)
{
NS_ASSERTION(!mTestAsyncOpen || mAsyncOpenCompleted, "AsyncOpen failed");
printf("\n+++ TestConnection::OnStopRequest (status = %x) +++."
"\tContext = %p\n",
aStatus, context);
@ -194,7 +247,8 @@ TestConnection::OnStopRequest(nsIChannel* channel,
}
TestConnection::TestConnection(const char* aHostName, PRInt32 aPort, PRBool aAsyncFlag)
TestConnection::TestConnection(const char* aHostName, PRInt32 aPort,
PRBool aAsyncFlag, PRBool testAsyncRead)
{
nsresult rv;
@ -202,6 +256,9 @@ TestConnection::TestConnection(const char* aHostName, PRInt32 aPort, PRBool aAsy
mIsAsync = aAsyncFlag;
mTestAsyncOpen = testAsyncRead;
mAsyncOpenCompleted = PR_FALSE;
mBufferLength = 255;
mBufferChar = 'a';
mBytesRead = 0;
@ -310,6 +367,19 @@ TestConnection::Run(void)
if (NS_SUCCEEDED(rv)) {
if (mIsAsync) {
if (mTestAsyncOpen) {
TestConnectionOpenObserver* obs = new TestConnectionOpenObserver(this);
if (obs == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(obs);
rv = mTransport->AsyncOpen(obs, nsnull);
NS_RELEASE(obs);
if (NS_FAILED(rv)) {
printf("Error: AsyncOpen failed...");
}
}
//
// Initiate an async read...
//
@ -529,6 +599,7 @@ main(int argc, char* argv[])
/// }
PRBool bIsAsync = PR_TRUE;
PRBool bTestAsyncOpen = PR_FALSE;
char* hostName = nsnull;
int i;
@ -539,6 +610,10 @@ main(int argc, char* argv[])
bIsAsync = PR_FALSE;
continue;
}
if (PL_strcasecmp(argv[i], "-asyncopen") == 0) {
bTestAsyncOpen = PR_TRUE;
continue;
}
hostName = argv[i];
}
@ -573,7 +648,7 @@ main(int argc, char* argv[])
// Create the connections and threads...
//
for (i=0; i<NUM_TEST_THREADS; i++) {
gConnections[i] = new TestConnection(hostName, 7, bIsAsync);
gConnections[i] = new TestConnection(hostName, 7, bIsAsync, bTestAsyncOpen);
rv = NS_NewThread(&gThreads[i], gConnections[i], 0, PR_JOINABLE_THREAD);
}

View File

@ -1430,7 +1430,7 @@ nsDocumentBindInfo::CancelRefreshURLTimers(void)
NS_IMPL_ISUPPORTS(nsChannelListener, nsCOMTypeInfo<nsIStreamListener>::GetIID());
NS_IMPL_ISUPPORTS2(nsChannelListener, nsIStreamObserver, nsIStreamListener);
nsChannelListener::nsChannelListener()
{

View File

@ -1430,7 +1430,7 @@ nsDocumentBindInfo::CancelRefreshURLTimers(void)
NS_IMPL_ISUPPORTS(nsChannelListener, nsCOMTypeInfo<nsIStreamListener>::GetIID());
NS_IMPL_ISUPPORTS2(nsChannelListener, nsIStreamObserver, nsIStreamListener);
nsChannelListener::nsChannelListener()
{