mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Added AsyncOpen to nsIChannel for URL dispatching. Added ContentLength to InputStreamChannel. (r=rpotts,valeski)
This commit is contained in:
parent
735f646940
commit
8603974025
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
|
@ -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)))
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -43,6 +43,7 @@ XPIDLSRCS = \
|
||||
nsILoadGroup.idl \
|
||||
nsIFileTransportService.idl \
|
||||
nsISocketTransportService.idl \
|
||||
nsIFileSystem.idl \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
|
@ -43,6 +43,7 @@ XPIDLSRCS = \
|
||||
.\nsILoadGroup.idl \
|
||||
.\nsISocketTransportService.idl \
|
||||
.\nsIFileTransportService.idl \
|
||||
.\nsIFileSystem.idl \
|
||||
$(NULL)
|
||||
|
||||
include <$(DEPTH)/config/rules.mak>
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -39,7 +39,7 @@ protected:
|
||||
|
||||
public:
|
||||
static nsresult
|
||||
Create(const nsFileSpec& aDir, nsISupports** aStreamResult);
|
||||
Create(const nsFileSpec& aDir, nsIInputStream** aStreamResult);
|
||||
|
||||
// nsISupportsInterface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -44,8 +44,9 @@ public:
|
||||
nsresult Init();
|
||||
|
||||
protected:
|
||||
nsIThreadPool* mPool;
|
||||
nsISupportsArray* mSuspended;
|
||||
nsCOMPtr<nsIThreadPool> mPool;
|
||||
nsCOMPtr<nsISupportsArray> mOpened;
|
||||
nsCOMPtr<nsISupportsArray> mSuspended;
|
||||
};
|
||||
|
||||
#endif /* nsFileTransportService_h___ */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -196,6 +196,9 @@ protected:
|
||||
PRInt32 mPort;
|
||||
char* mSocketType;
|
||||
|
||||
nsCOMPtr<nsIStreamObserver> mOpenObserver;
|
||||
nsCOMPtr<nsISupports> mOpenContext;
|
||||
|
||||
nsCOMPtr<nsISupports> mReadContext;
|
||||
nsCOMPtr<nsIStreamListener> mReadListener;
|
||||
nsCOMPtr<nsIBufferInputStream> mReadPipeIn;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -1430,7 +1430,7 @@ nsDocumentBindInfo::CancelRefreshURLTimers(void)
|
||||
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsChannelListener, nsCOMTypeInfo<nsIStreamListener>::GetIID());
|
||||
NS_IMPL_ISUPPORTS2(nsChannelListener, nsIStreamObserver, nsIStreamListener);
|
||||
|
||||
nsChannelListener::nsChannelListener()
|
||||
{
|
||||
|
@ -1430,7 +1430,7 @@ nsDocumentBindInfo::CancelRefreshURLTimers(void)
|
||||
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsChannelListener, nsCOMTypeInfo<nsIStreamListener>::GetIID());
|
||||
NS_IMPL_ISUPPORTS2(nsChannelListener, nsIStreamObserver, nsIStreamListener);
|
||||
|
||||
nsChannelListener::nsChannelListener()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user