зеркало из https://github.com/mozilla/gecko-dev.git
18725, r=sdagley. FTP is now cancellable.
* added new state to FTP. data channel reading state. * the FTP channel's SetConnectionQueue now handles a null arg and resets it's eventq if null is passed in.
This commit is contained in:
Родитель
d2b0b19ca8
Коммит
d16733f10b
|
@ -272,7 +272,7 @@ nsFTPChannel::AsyncRead(PRUint32 startPosition, PRInt32 readCount,
|
|||
mEventQueue, /* event queue for this thread */
|
||||
mHandler,
|
||||
this, ctxt, mEventSinkGetter);
|
||||
mHandler = 0; // XXX this can go away when the channel is no longer being leaked.
|
||||
mHandler = 0;
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(protocolInterpreter);
|
||||
return rv;
|
||||
|
@ -394,21 +394,27 @@ nsFTPChannel::SetOwner(nsISupports * aOwner)
|
|||
// nsIFTPChannel methods:
|
||||
NS_IMETHODIMP
|
||||
nsFTPChannel::SetConnectionQueue(nsIEventQueue *aEventQ) {
|
||||
nsresult rv;
|
||||
// create the proxy object so we can call into the FTP thread.
|
||||
NS_WITH_SERVICE(nsIProxyObjectManager, proxyManager, kProxyObjectManagerCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// change the thread request over to a proxy thread request.
|
||||
rv = proxyManager->GetProxyObject(aEventQ,
|
||||
NS_GET_IID(nsIRequest),
|
||||
mThreadRequest,
|
||||
PROXY_SYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(mProxiedThreadRequest));
|
||||
mThreadRequest = 0;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (aEventQ) {
|
||||
// create the proxy object so we can call into the FTP thread.
|
||||
NS_WITH_SERVICE(nsIProxyObjectManager, proxyManager, kProxyObjectManagerCID, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
// change the thread request over to a proxy thread request.
|
||||
rv = proxyManager->GetProxyObject(aEventQ,
|
||||
NS_GET_IID(nsIRequest),
|
||||
mThreadRequest,
|
||||
PROXY_SYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(mProxiedThreadRequest));
|
||||
mThreadRequest = 0;
|
||||
} else {
|
||||
// no event queue means the thread has effectively gone away.
|
||||
mThreadRequest = 0;
|
||||
mProxiedThreadRequest = 0;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -436,6 +442,7 @@ nsFTPChannel::OnStopRequest(nsIChannel* channel, nsISupports* context,
|
|||
nsresult aStatus,
|
||||
const PRUnichar* aMsg) {
|
||||
nsresult rv = NS_OK;
|
||||
mProxiedThreadRequest = 0; // we don't want anyone trying to use this when the underlying thread has left.
|
||||
if (mEventSink) {
|
||||
nsAutoString statusMsg("FTP transaction complete.");
|
||||
#ifndef BUG_16273_FIXED //TODO
|
||||
|
|
|
@ -215,6 +215,59 @@ nsFtpConnectionThread::Process() {
|
|||
}
|
||||
// END: FTP_READ_BUF
|
||||
|
||||
case FTP_READ_DATA_BUF:
|
||||
{
|
||||
|
||||
PRUint32 read = 0, readSoFar = 0;
|
||||
while (readSoFar < NS_FTP_BUFFER_READ_SIZE) {
|
||||
// suck in the data from the server
|
||||
PRUint32 avail;
|
||||
rv = mBufInStream->Available(&avail);
|
||||
if (NS_FAILED(rv)) {
|
||||
mInternalError = NS_ERROR_FAILURE;
|
||||
mState = FTP_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
rv = mBufOutStream->WriteFrom(mDInStream, NS_FTP_BUFFER_READ_SIZE-readSoFar, &read);
|
||||
if (NS_FAILED(rv)) {
|
||||
mInternalError = NS_ERROR_FAILURE;
|
||||
mState = FTP_ERROR;
|
||||
break;
|
||||
}
|
||||
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, mContext, mBufInStream, avail, readSoFar);
|
||||
if (NS_FAILED(rv)) {
|
||||
mInternalError = NS_ERROR_FAILURE;
|
||||
mState = FTP_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
// we're done filling this end of the pipe. close it.
|
||||
mBufOutStream->Close();
|
||||
|
||||
mState = FTP_READ_BUF;
|
||||
mNextState = FTP_COMPLETE;
|
||||
break; // this terminates the loop
|
||||
}
|
||||
|
||||
if (readSoFar == NS_FTP_BUFFER_READ_SIZE) {
|
||||
// we've filled our buffer, send the data off
|
||||
rv = mListener->OnDataAvailable(mChannel, mContext, mBufInStream, avail, NS_FTP_BUFFER_READ_SIZE);
|
||||
if (NS_FAILED(rv)) {
|
||||
mInternalError = NS_ERROR_FAILURE;
|
||||
mState = FTP_ERROR;
|
||||
break;
|
||||
}
|
||||
mState = FTP_READ_DATA_BUF;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// END: FTP_READ_DATA_BUF
|
||||
|
||||
case FTP_ERROR:
|
||||
{
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Process() - ERROR\n", mURL.get()));
|
||||
|
@ -232,10 +285,13 @@ nsFtpConnectionThread::Process() {
|
|||
case FTP_COMPLETE:
|
||||
{
|
||||
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("%x Process() - COMPLETE\n", mURL.get()));
|
||||
// push through all of the pertinent state into the cache entry;
|
||||
mConn->mCwd = mCwd;
|
||||
rv = mConnCache->InsertConn(mCacheKey.GetBuffer(), mConn);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_SUCCEEDED(mInternalError)) {
|
||||
// we only want to cache the connection if things are ok.
|
||||
// push through all of the pertinent state into the cache entry;
|
||||
mConn->mCwd = mCwd;
|
||||
rv = mConnCache->InsertConn(mCacheKey.GetBuffer(), mConn);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
rv = StopProcessing();
|
||||
break;
|
||||
|
@ -577,8 +633,6 @@ nsFtpConnectionThread::Process() {
|
|||
if (FTP_ERROR == mState)
|
||||
mInternalError = NS_ERROR_FAILURE;
|
||||
mNextState = FTP_COMPLETE;
|
||||
mDInStream->Close();
|
||||
mDInStream = 0;
|
||||
break;
|
||||
}
|
||||
// END: FTP_R_RETR
|
||||
|
@ -1114,11 +1168,6 @@ nsFtpConnectionThread::S_size() {
|
|||
// XXX should the actual file name be parsed out???
|
||||
mFilename = path;
|
||||
|
||||
/*if (mServerType == FTP_VMS_TYPE) {
|
||||
mState = FindGetState();
|
||||
break;
|
||||
}*/
|
||||
|
||||
nsCAutoString sizeBuf("SIZE ");
|
||||
sizeBuf.Append(path);
|
||||
sizeBuf.Append(FTP_CRLF);
|
||||
|
@ -1341,46 +1390,10 @@ nsFtpConnectionThread::R_retr() {
|
|||
|
||||
mSentStart = PR_TRUE;
|
||||
|
||||
nsIBufferInputStream *bufInStrm = nsnull;
|
||||
nsIBufferOutputStream *bufOutStrm = nsnull;
|
||||
rv = NS_NewPipe(&bufInStrm, &bufOutStrm);
|
||||
rv = NS_NewPipe(getter_AddRefs(mBufInStream), getter_AddRefs(mBufOutStream));
|
||||
if (NS_FAILED(rv)) return FTP_ERROR;
|
||||
|
||||
nsIInputStream *inStream = nsnull;
|
||||
rv = bufInStrm->QueryInterface(NS_GET_IID(nsIInputStream), (void**)&inStream);
|
||||
if (NS_FAILED(rv)) return FTP_ERROR;
|
||||
|
||||
PRUint32 read = 0, readSoFar = 0;
|
||||
while (readSoFar < NS_FTP_BUFFER_READ_SIZE) {
|
||||
// suck in the data from the server
|
||||
PRUint32 avail;
|
||||
rv = inStream->Available(&avail);
|
||||
if (NS_FAILED(rv)) return FTP_ERROR;
|
||||
|
||||
rv = bufOutStrm->WriteFrom(mDInStream, NS_FTP_BUFFER_READ_SIZE-readSoFar, &read);
|
||||
if (NS_FAILED(rv)) return FTP_ERROR;
|
||||
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, mContext, inStream, avail, readSoFar);
|
||||
if (NS_FAILED(rv)) return FTP_ERROR;
|
||||
|
||||
break; // this terminates the loop
|
||||
}
|
||||
|
||||
if (readSoFar == NS_FTP_BUFFER_READ_SIZE) {
|
||||
// we've filled our buffer, send the data off
|
||||
readSoFar = 0;
|
||||
rv = mListener->OnDataAvailable(mChannel, mContext, inStream, avail, NS_FTP_BUFFER_READ_SIZE);
|
||||
if (NS_FAILED(rv)) return FTP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// we're done filling this end of the pipe. close it.
|
||||
bufOutStrm->Close();
|
||||
NS_RELEASE(inStream);
|
||||
|
||||
return FTP_READ_BUF;
|
||||
return FTP_READ_DATA_BUF;
|
||||
|
||||
} else {
|
||||
if (mServerType == FTP_VMS_TYPE) {
|
||||
|
@ -1783,6 +1796,8 @@ nsFtpConnectionThread::Cancel(void)
|
|||
rv = mDPipe->Cancel();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
mInternalError = NS_ERROR_FAILURE; // XXX should be an FTP code.
|
||||
mState = FTP_COMPLETE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1919,6 +1934,20 @@ nsFtpConnectionThread::StopProcessing() {
|
|||
mCOutStream = 0;
|
||||
mCInStream = 0;
|
||||
|
||||
NS_WITH_SERVICE(nsIProxyObjectManager, pIProxyObjectManager, kProxyObjectManagerCID, &rv);
|
||||
if(NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIFTPChannel> ftpChannel;
|
||||
rv = pIProxyObjectManager->GetProxyObject(mOutsideEventQueue,
|
||||
NS_GET_IID(nsIFTPChannel),
|
||||
mChannel,
|
||||
PROXY_SYNC | PROXY_ALWAYS,
|
||||
getter_AddRefs(ftpChannel));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = ftpChannel->SetConnectionQueue(nsnull);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// if we haven't sent an OnStartRequest() yet, fire one now. We don't want
|
||||
// to blidly send an OnStop if we haven't "started" anything.
|
||||
if (!mSentStart) {
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef enum _FTP_STATE {
|
|||
//// Internal states
|
||||
///////////////////////
|
||||
FTP_READ_BUF,
|
||||
FTP_READ_DATA_BUF,
|
||||
FTP_ERROR,
|
||||
FTP_COMPLETE,
|
||||
|
||||
|
@ -253,6 +254,9 @@ private:
|
|||
nsXPIDLCString mURLSpec;
|
||||
nsCOMPtr<nsIEventSinkGetter> mEventSinkGetter;
|
||||
nsCOMPtr<nsIFTPChannel> mFTPChannel;
|
||||
|
||||
nsCOMPtr<nsIBufferInputStream> mBufInStream;
|
||||
nsCOMPtr<nsIBufferOutputStream> mBufOutStream;
|
||||
};
|
||||
|
||||
#define NS_FTP_BUFFER_READ_SIZE (8*1024)
|
||||
|
|
Загрузка…
Ссылка в новой задаче