18419. *removed nsIFTPContext and associated impl of it. we no longer pass this context between the FTP thread and the channel thread, we use nsISupports proxies to move back and forth.*added SetcontentLength() method to nsIFTPChannel so we can move the content length from the FTP thread to the channel thread. nsFTPChannel impls this meth now.*made a couple FTP channel logging changes for better description*nsCOMPtrized a bit*added nsFTPChannel to load group when avail (this starts/stops the throbber for url bar loaded ftp urls.*the FTP protocl handler (a service) is now an observer of XPCOM shutdown. this allows the handler to join w/ all the threads it has created (that are still running) if we try and shutdown the main thread whill ftp is still running.

This commit is contained in:
valeski%netscape.com 1999-11-11 02:14:23 +00:00
Родитель 4e3281f9e6
Коммит 9fed6b2933
5 изменённых файлов: 96 добавлений и 132 удалений

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

@ -32,7 +32,6 @@
#include "nsIEventQueueService.h"
#include "nsIProgressEventSink.h"
#include "nsIEventSinkGetter.h"
#include "nsIFTPContext.h"
#include "nsIMIMEService.h"
#include "nsProxyObjectManager.h"
@ -108,7 +107,11 @@ nsFTPChannel::Init(const char* verb, nsIURI* uri, nsILoadGroup *aGroup,
mOriginalURI = originalURI ? originalURI : uri;
mURL = uri;
mLoadGroup = aGroup;
if (aGroup) {
mLoadGroup = aGroup;
rv = mLoadGroup->AddChannel(this, nsnull);
if (NS_FAILED(rv)) return rv;
}
mEventSinkGetter = getter;
@ -270,8 +273,10 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
mHandler,
this, ctxt, mEventSinkGetter);
mHandler = 0; // XXX this can go away when the channel is no longer being leaked.
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv)) {
NS_RELEASE(protocolInterpreter);
return rv;
}
rv = mPool->DispatchRequest((nsIRunnable*)protocolInterpreter);
NS_RELEASE(protocolInterpreter);
@ -326,7 +331,7 @@ nsFTPChannel::GetContentType(char* *aContentType) {
if (!*aContentType) {
rv = NS_ERROR_OUT_OF_MEMORY;
}
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::NewChannel() returned %s\n", *aContentType));
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::GetContentType() returned %s\n", *aContentType));
return rv;
}
@ -335,7 +340,7 @@ nsFTPChannel::GetContentType(char* *aContentType) {
rv = MIMEService->GetTypeFromURI(mURL, aContentType);
if (NS_SUCCEEDED(rv)) {
mContentType = *aContentType;
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::NewChannel() returned %s\n", *aContentType));
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::GetContentType() returned %s\n", *aContentType));
return rv;
}
}
@ -406,6 +411,12 @@ nsFTPChannel::SetConnectionQueue(nsIEventQueue *aEventQ) {
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetContentLength(PRInt32 aLength) {
mContentLength = aLength;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIStreamObserver methods:
@ -438,6 +449,9 @@ nsFTPChannel::OnStopRequest(nsIChannel* channel, nsISupports* context,
if (mListener) {
rv = mListener->OnStopRequest(channel, mContext, aStatus, aMsg);
}
if (mLoadGroup)
rv = mLoadGroup->RemoveChannel(this, nsnull, aStatus, aMsg);
return rv;
}
@ -453,23 +467,6 @@ nsFTPChannel::OnDataAvailable(nsIChannel* channel, nsISupports* context,
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::OnDataAvailable(channel = %x, context = %x, stream = %x, srcOffset = %d, length = %d)\n", channel, context, aIStream, aSourceOffset, aLength));
if (context) {
nsCOMPtr<nsIFTPContext> ftpCtxt = do_QueryInterface(context, &rv);
if (NS_FAILED(rv)) return rv;
char *type = nsnull;
rv = ftpCtxt->GetContentType(&type);
if (NS_FAILED(rv)) return rv;
nsCAutoString cType(type);
cType.ToLowerCase();
mContentType = cType.GetBuffer();
nsAllocator::Free(type);
rv = ftpCtxt->GetContentLength(&mContentLength);
if (NS_FAILED(rv)) return rv;
}
if (mListener) {
rv = mListener->OnDataAvailable(channel, mContext, aIStream, aSourceOffset, aLength);
}

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

@ -59,61 +59,12 @@ static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kFTPHandlerCID, NS_FTPPROTOCOLHANDLER_CID);
static NS_DEFINE_IID(kIFTPContextIID, NS_IFTPCONTEXT_IID);
#define FTP_CRLF "\r\n"
#if defined(PR_LOGGING)
extern PRLogModuleInfo* gFTPLog;
#endif /* PR_LOGGING */
class nsFTPContext : nsIFTPContext {
public:
// nsISupports methods
NS_DECL_ISUPPORTS
// nsIFTPContext methods
NS_IMETHOD IsCmdResponse(PRBool *_retval) {
*_retval = mCmdResponse;
return NS_OK;
};
NS_IMETHOD SetContentType(const char *aContentType) {
mContentType = aContentType;
return NS_OK;
};
NS_IMETHOD GetContentType(char * *aContentType) {
*aContentType = mContentType.ToNewCString();
return NS_OK;
};
NS_IMETHOD SetContentLength(PRInt32 aLength) {
mLength = aLength;
return NS_OK;
};
NS_IMETHOD GetContentLength(PRInt32 *aLength) {
*aLength = mLength;
return NS_OK;
}
// nsFTPContext methods
nsFTPContext() {
NS_INIT_REFCNT();
mCmdResponse = PR_TRUE;
mLength = -1;
};
virtual ~nsFTPContext() {};
PRBool mCmdResponse;
nsAutoString mContentType;
PRInt32 mLength;
};
NS_IMPL_ISUPPORTS(nsFTPContext, kIFTPContextIID);
// BEGIN: nsFtpConnectionThread implementation
NS_IMETHODIMP_(nsrefcnt) nsFtpConnectionThread::AddRef(void)
{
@ -140,12 +91,13 @@ NS_IMPL_QUERY_INTERFACE2(nsFtpConnectionThread, nsIRunnable, nsIRequest);
nsFtpConnectionThread::nsFtpConnectionThread() {
NS_INIT_REFCNT();
mSTS = nsnull;
mAction = GET;
mUsePasv = PR_TRUE;
mState = FTP_S_USER;
mNextState = FTP_S_USER;
mBin = PR_TRUE;
mLength = 0;
mLength = -1;
mConnected = PR_FALSE;
mResetMode = PR_FALSE;
mList = PR_FALSE;
@ -157,13 +109,11 @@ nsFtpConnectionThread::nsFtpConnectionThread() {
mInternalError = NS_OK; // start out on the up 'n up.
mSentStart = PR_FALSE;
mConn = nsnull;
mFTPContext = nsnull;
}
nsFtpConnectionThread::~nsFtpConnectionThread() {
// lose the socket transport
NS_RELEASE(mSTS);
NS_RELEASE(mFTPContext);
NS_IF_RELEASE(mSTS);
}
nsresult
@ -1180,11 +1130,13 @@ nsFtpConnectionThread::S_size() {
FTP_STATE
nsFtpConnectionThread::R_size() {
nsresult rv;
if (mResponseCode == 2) {
PRInt32 conversionError;
mLength = mResponseMsg.ToInteger(&conversionError);
mFTPContext->SetContentLength(mLength);
rv = mFTPChannel->SetContentLength(mLength);
if (NS_FAILED(rv)) return FTP_ERROR;
} if (mResponseCode == 5) {
// couldn't get the size of what we asked for, must be a dir.
mBin = PR_FALSE;
@ -1338,7 +1290,7 @@ nsFtpConnectionThread::R_list() {
nsCOMPtr<nsIInputStream> listStream = do_QueryInterface(stringStreamSup, &rv);
rv = converterListener->OnDataAvailable(mChannel, mFTPContext, listStream, 0, read);
rv = converterListener->OnDataAvailable(mChannel, mContext, listStream, 0, read);
if (NS_FAILED(rv)) return FTP_ERROR;
}
@ -1388,19 +1340,6 @@ nsFtpConnectionThread::R_retr() {
mSentStart = PR_TRUE;
// build up context info for the nsFTPChannel
NS_WITH_SERVICE(nsIMIMEService, MIMEService, kMIMEServiceCID, &rv);
if (NS_FAILED(rv)) return FTP_ERROR;
nsXPIDLCString contentType;
rv = MIMEService->GetTypeFromURI(mURL, getter_Copies(contentType));
// if we fail, we want to push the data on up anyway. let the app figure
// out what to do.
if (NS_SUCCEEDED(rv)) {
mFTPContext->SetContentType(contentType);
}
nsIBufferInputStream *bufInStrm = nsnull;
nsIBufferOutputStream *bufOutStrm = nsnull;
rv = NS_NewPipe(&bufInStrm, &bufOutStrm);
@ -1422,7 +1361,7 @@ nsFtpConnectionThread::R_retr() {
readSoFar += read;
if (read == 0) {
// we've exhausted the stream, send any data we have left and get out of dodge.
rv = mListener->OnDataAvailable(mChannel, mFTPContext, inStream, avail, readSoFar);
rv = mListener->OnDataAvailable(mChannel, mContext, inStream, avail, readSoFar);
if (NS_FAILED(rv)) return FTP_ERROR;
break; // this terminates the loop
@ -1546,7 +1485,7 @@ nsFtpConnectionThread::R_pasv() {
// we're connected figure out what type of transfer we're doing (ascii or binary)
nsXPIDLCString type;
rv = mChannel->GetContentType(getter_Copies(type));
rv = mFTPChannel->GetContentType(getter_Copies(type));
nsCAutoString typeStr;
if (NS_FAILED(rv) || !type)
typeStr = "bin";
@ -1903,11 +1842,16 @@ nsFtpConnectionThread::Init(nsIURI* aUrl,
getter_AddRefs(mSyncListener));
if (NS_FAILED(rv)) return rv;
// a straight com ptr to the channel
mChannel = aChannel;
// This proxied channel is used to set channel related
// state on the *real* channel back in the main thread.
rv = pIProxyObjectManager->GetProxyObject(mOutsideEventQueue,
NS_GET_IID(nsIChannel),
NS_GET_IID(nsIFTPChannel),
aChannel,
PROXY_SYNC | PROXY_ALWAYS,
getter_AddRefs(mChannel));
getter_AddRefs(mFTPChannel));
if (NS_FAILED(rv)) return rv;
// get a proxied ptr to the FTP protocol handler service so we can control
@ -1948,22 +1892,6 @@ nsFtpConnectionThread::Init(nsIURI* aUrl,
mCacheKey.SetString(host);
mCacheKey.Append(port);
// this context is used to get channel specific info back into the FTP channel
nsFTPContext *dataCtxt = new nsFTPContext();
if (!dataCtxt) return NS_ERROR_OUT_OF_MEMORY;
rv = dataCtxt->QueryInterface(NS_GET_IID(nsIFTPContext), (void**)&mFTPContext);
//mFTPContext = NS_STATIC_CAST(nsIFTPContext*, dataCtxt);
if (NS_FAILED(rv)) return rv;
// get a proxied ptr to the FTP protocol handler service so we can control
// the connection cache from here.
rv = pIProxyObjectManager->GetProxyObject(nsnull,
NS_GET_IID(nsIConnectionCache),
aHandler,
PROXY_SYNC | PROXY_ALWAYS,
getter_AddRefs(mConnCache));
if (NS_FAILED(rv)) return rv;
return NS_OK;
}

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

@ -37,7 +37,7 @@
#include "nsIEventQueue.h"
#include "nsHashtable.h"
#include "nsIChannel.h"
#include "nsIFTPContext.h"
#include "nsIFTPChannel.h"
#include "nsIConnectionCache.h"
#include "nsConnectionCacheObj.h"
#include "nsIProtocolHandler.h"
@ -214,7 +214,7 @@ private:
nsString2 mUsername;
nsString2 mPassword;
nsString2 mFilename; // url filename (if any)
PRUint32 mLength; // length of the file
PRInt32 mLength; // length of the file
PRTime mLastModified; // last modified time for file
// these members should be hung off of a specific transport connection
@ -245,7 +245,6 @@ private:
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsISupports> mContext;
nsIFTPContext* mFTPContext; // FTP channel specific context.
nsCOMPtr<nsIConnectionCache> mConnCache; // the nsISupports proxy ptr to the FTP proto handler
nsConnectionCacheObj* mConn; // The cached connection.
PRBool mKeepRunning; // thread event loop boolean
@ -253,6 +252,7 @@ private:
nsString2 mContentType; // the content type of the data we're dealing w/.
nsXPIDLCString mURLSpec;
nsCOMPtr<nsIEventSinkGetter> mEventSinkGetter;
nsCOMPtr<nsIFTPChannel> mFTPChannel;
};
#define NS_FTP_BUFFER_READ_SIZE (8*1024)

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

@ -26,7 +26,6 @@
#include "nsIURL.h"
#include "nsCRT.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIEventSinkGetter.h"
#include "nsIProgressEventSink.h"
#include "nsConnectionCacheObj.h"
@ -53,22 +52,9 @@ static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
nsFtpProtocolHandler::nsFtpProtocolHandler() {
NS_INIT_REFCNT();
NS_NEWXPCOM(mRootConnectionList, nsHashtable);
NS_NewThreadPool(getter_AddRefs(mPool), NS_FTP_CONNECTION_COUNT,
NS_FTP_CONNECTION_COUNT,
NS_FTP_CONNECTION_STACK_SIZE);
}
// cleans up a connection list entry
PRBool CleanupConnEntry(nsHashKey *aKey, void *aData, void *closure) {
// XXX do we need to explicitly close the streams?
delete (nsConnectionCacheObj*)aData;
return PR_TRUE;
}
nsFtpProtocolHandler::~nsFtpProtocolHandler() {
mRootConnectionList->Reset(CleanupConnEntry);
NS_DELETEXPCOM(mRootConnectionList);
}
@ -93,8 +79,7 @@ NS_IMETHODIMP_(nsrefcnt) nsFtpProtocolHandler::Release(void)
return mRefCnt;
}
NS_IMPL_QUERY_INTERFACE2(nsFtpProtocolHandler, nsIProtocolHandler, nsIConnectionCache);
//NS_IMPL_ISUPPORTS2(nsFtpProtocolHandler, nsIProtocolHandler, nsIConnectionCache);
NS_IMPL_QUERY_INTERFACE3(nsFtpProtocolHandler, nsIProtocolHandler, nsIConnectionCache, nsIObserver);
NS_METHOD
nsFtpProtocolHandler::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
@ -114,10 +99,30 @@ nsFtpProtocolHandler::Create(nsISupports* aOuter, const nsIID& aIID, void* *aRes
if (ph == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(ph);
nsresult rv = ph->QueryInterface(aIID, aResult);
nsresult rv = ph->Init();
if (NS_FAILED(rv)) return rv;
rv = ph->QueryInterface(aIID, aResult);
NS_RELEASE(ph);
return rv;
}
nsresult
nsFtpProtocolHandler::Init() {
nsresult rv;
NS_NEWXPCOM(mRootConnectionList, nsHashtable);
if (!mRootConnectionList) return NS_ERROR_OUT_OF_MEMORY;
rv = NS_NewThreadPool(getter_AddRefs(mPool), NS_FTP_CONNECTION_COUNT,
NS_FTP_CONNECTION_COUNT,
NS_FTP_CONNECTION_STACK_SIZE);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIObserverService, obsServ, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_SUCCEEDED(rv)) {
nsAutoString topic(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
obsServ->AddObserver(this, topic.GetUnicode());
}
return rv;
}
////////////////////////////////////////////////////////////////////////////////
// nsIProtocolHandler methods:
@ -222,4 +227,30 @@ nsFtpProtocolHandler::InsertConn(const char *aKey, nsConnectionCacheObj *aConn)
return NS_OK;
}
// cleans up a connection list entry
PRBool CleanupConnEntry(nsHashKey *aKey, void *aData, void *closure) {
// XXX do we need to explicitly close the streams?
delete (nsConnectionCacheObj*)aData;
return PR_TRUE;
}
// nsIObserver method
NS_IMETHODIMP
nsFtpProtocolHandler::Observe(nsISupports *aSubject,
const PRUnichar *aTopic,
const PRUnichar *someData ) {
nsresult rv;
if (mRootConnectionList) {
mRootConnectionList->Reset(CleanupConnEntry);
NS_DELETEXPCOM(mRootConnectionList);
mRootConnectionList = nsnull;
}
// remove ourself from the observer service.
NS_WITH_SERVICE(nsIObserverService, obsServ, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_SUCCEEDED(rv)) {
nsAutoString topic(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
obsServ->RemoveObserver(this, topic.GetUnicode());
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////

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

@ -23,19 +23,23 @@
#ifndef nsFtpProtocolHandler_h___
#define nsFtpProtocolHandler_h___
#include "nsIServiceManager.h"
#include "nsIProtocolHandler.h"
#include "nsHashtable.h"
#include "nsVoidArray.h"
#include "nsIConnectionCache.h"
#include "nsConnectionCacheObj.h"
#include "nsIThreadPool.h"
#include "nsIObserverService.h"
#include "nsIObserver.h"
// {25029490-F132-11d2-9588-00805F369F95}
#define NS_FTPPROTOCOLHANDLER_CID \
{ 0x25029490, 0xf132, 0x11d2, { 0x95, 0x88, 0x0, 0x80, 0x5f, 0x36, 0x9f, 0x95 } }
class nsFtpProtocolHandler : public nsIProtocolHandler,
public nsIConnectionCache
public nsIConnectionCache,
public nsIObserver
{
public:
NS_DECL_ISUPPORTS
@ -46,6 +50,9 @@ public:
// nsIConnectionCache methods
NS_DECL_NSICONNECTIONCACHE
// nsIObserver methods
NS_DECL_NSIOBSERVER
// nsFtpProtocolHandler methods:
nsFtpProtocolHandler();
virtual ~nsFtpProtocolHandler();
@ -53,6 +60,7 @@ public:
// Define a Create method to be used with a factory:
static NS_METHOD
Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult);
nsresult Init();
protected:
nsISupports* mEventSinkGetter;