backing out my latest patch for bug 312760 to clear Tp regression.

This commit is contained in:
darin%meer.net 2006-03-01 18:30:51 +00:00
Родитель 3d690cd807
Коммит 6942519245
25 изменённых файлов: 2253 добавлений и 1386 удалений

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

@ -1011,17 +1011,4 @@ NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor *callbacks,
return NS_NewInterfaceRequestorAggregation(callbacks, cbs, result);
}
/**
* Helper function for testing online/offline state of the browser.
*/
inline PRBool
NS_IsOffline()
{
PRBool offline = PR_TRUE;
nsCOMPtr<nsIIOService> ios = do_GetIOService();
if (ios)
ios->GetOffline(&offline);
return offline;
}
#endif // !nsNetUtil_h__

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

@ -219,31 +219,6 @@ nsBaseChannel::PushStreamConverter(const char *fromType,
return rv;
}
nsresult
nsBaseChannel::BeginPumpingData()
{
nsCOMPtr<nsIInputStream> stream;
nsresult rv = OpenContentStream(PR_TRUE, getter_AddRefs(stream));
if (NS_FAILED(rv))
return rv;
// By assigning mPump, we flag this channel as pending (see IsPending). It's
// important that the pending flag is set when we call into the stream (the
// call to AsyncRead results in the stream's AsyncWait method being called)
// and especially when we call into the loadgroup. Our caller takes care to
// release mPump if we return an error.
mPump = new nsInputStreamPump();
if (!mPump)
return NS_ERROR_OUT_OF_MEMORY;
rv = mPump->Init(stream, -1, -1, 0, 0, PR_TRUE);
if (NS_SUCCEEDED(rv))
rv = mPump->AsyncRead(this, nsnull);
return rv;
}
//-----------------------------------------------------------------------------
// nsBaseChannel::nsISupports
@ -475,25 +450,28 @@ nsBaseChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
if (NS_FAILED(rv))
return rv;
// Store the listener and context early so that OpenContentStream and the
// stream's AsyncWait method (called by AsyncRead) can have access to them
// via PushStreamConverter and the StreamListener methods. However, since
// this typically introduces a reference cycle between this and the listener,
// we need to be sure to break the reference if this method does not succeed.
mListener = listener;
mListenerContext = ctxt;
nsCOMPtr<nsIInputStream> stream;
rv = OpenContentStream(PR_TRUE, getter_AddRefs(stream));
if (NS_FAILED(rv))
return rv;
// This method assigns mPump as a side-effect. We need to clear mPump if
// this method fails.
rv = BeginPumpingData();
mPump = new nsInputStreamPump();
if (!mPump)
return NS_ERROR_OUT_OF_MEMORY;
rv = mPump->Init(stream, -1, -1, 0, 0, PR_TRUE);
if (NS_FAILED(rv)) {
mPump = nsnull;
mListener = nsnull;
mListenerContext = nsnull;
return rv;
}
// At this point, we are going to return success no matter what.
rv = mPump->AsyncRead(this, nsnull);
if (NS_FAILED(rv)) {
mPump = nsnull;
return rv;
}
mListener = listener;
mListenerContext = ctxt;
SUSPEND_PUMP_FOR_SCOPE();
@ -575,8 +553,6 @@ nsBaseChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
mPump->PeekStream(CallTypeSniffers, NS_STATIC_CAST(nsIChannel*, this));
}
SUSPEND_PUMP_FOR_SCOPE();
return mListener->OnStartRequest(this, mListenerContext);
}
@ -617,8 +593,6 @@ nsBaseChannel::OnDataAvailable(nsIRequest *request, nsISupports *ctxt,
nsIInputStream *stream, PRUint32 offset,
PRUint32 count)
{
SUSPEND_PUMP_FOR_SCOPE();
nsresult rv = mListener->OnDataAvailable(this, mListenerContext, stream,
offset, count);
if (mSynthProgressEvents && NS_SUCCEEDED(rv)) {

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

@ -85,13 +85,11 @@ public:
return nsHashPropertyBag::Init();
}
protected:
// -----------------------------------------------
// Methods to be implemented by the derived class:
virtual ~nsBaseChannel() {}
private:
// Implemented by subclass to supply data stream. The parameter, async, is
// true when called from nsIChannel::AsyncOpen and false otherwise. When
// async is true, the resulting stream will be used with a nsIInputStreamPump
@ -117,11 +115,6 @@ private:
return PR_FALSE;
}
// Called when the callbacks available to this channel may have changed.
virtual void OnCallbacksChanged() {
}
public:
// ----------------------------------------------
// Methods provided for use by the derived class:
@ -199,15 +192,6 @@ public:
mSynthProgressEvents = enable;
}
// Some subclasses may wish to manually insert a stream listener between this
// and the channel's listener. The following methods make that possible.
void SetStreamListener(nsIStreamListener *listener) {
mListener = listener;
}
nsIStreamListener *StreamListener() {
return mListener;
}
// Pushes a new stream converter in front of the channel's stream listener.
// The fromType and toType values are passed to nsIStreamConverterService's
// AsyncConvertData method. If invalidatesContentLength is true, then the
@ -223,14 +207,10 @@ private:
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
// Called to setup mPump and call AsyncRead on it.
nsresult BeginPumpingData();
// Called when the callbacks available to this channel may have changed.
void CallbacksChanged() {
mProgressSink = nsnull;
mQueriedProgressSink = PR_FALSE;
OnCallbacksChanged();
}
nsRefPtr<nsInputStreamPump> mPump;

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

@ -107,10 +107,6 @@ nsBaseContentStream::ReadSegments(nsWriteSegmentFun fun, void *closure,
if (mStatus == NS_BASE_STREAM_CLOSED)
return NS_OK;
// No data yet
if (!IsClosed() && IsNonBlocking())
return NS_BASE_STREAM_WOULD_BLOCK;
return mStatus;
}
@ -156,15 +152,9 @@ nsBaseContentStream::AsyncWait(nsIInputStreamCallback *callback, PRUint32 flags,
mCallback = callback;
mCallbackTarget = target;
if (!mCallback)
return NS_OK;
// If we're already closed, then dispatch this callback immediately.
if (IsClosed()) {
if (IsClosed())
DispatchCallback();
return NS_OK;
}
OnCallbackPending();
return NS_OK;
}

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

@ -96,14 +96,6 @@ public:
// Helper function to make code more self-documenting.
void DispatchCallbackSync() { DispatchCallback(PR_FALSE); }
protected:
virtual ~nsBaseContentStream() {}
private:
// Called from the base stream's AsyncWait method when a pending callback
// is installed on the stream.
virtual void OnCallbackPending() {}
private:
nsCOMPtr<nsIInputStreamCallback> mCallback;
nsCOMPtr<nsIEventTarget> mCallbackTarget;

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

@ -57,17 +57,6 @@ static PRLogModuleInfo *gStreamPumpLog = nsnull;
#endif
#define LOG(args) PR_LOG(gStreamPumpLog, PR_LOG_DEBUG, args)
//-----------------------------------------------------------------------------
static NS_METHOD
GetBytesAvailable(nsIInputStream *stream, void *closure, const char *segment,
PRUint32 offset, PRUint32 count, PRUint32 *result)
{
PRUint32 *avail = NS_STATIC_CAST(PRUint32 *, closure);
*avail = count;
return NS_ERROR_ABORT; // return from ReadSegments call
}
//-----------------------------------------------------------------------------
// nsInputStreamPump methods
//-----------------------------------------------------------------------------
@ -362,11 +351,11 @@ nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream *stream)
// this function has been called from a PLEvent, so we can safely call
// any listener or progress sink methods directly from here.
mWaiting = PR_FALSE;
for (;;) {
if (mSuspendCount || mState == STATE_IDLE)
if (mSuspendCount || mState == STATE_IDLE) {
mWaiting = PR_FALSE;
break;
}
PRUint32 nextState;
switch (mState) {
@ -385,6 +374,7 @@ nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream *stream)
NS_ASSERTION(mState == STATE_TRANSFER, "unexpected state");
NS_ASSERTION(NS_SUCCEEDED(mStatus), "unexpected status");
mWaiting = PR_FALSE;
mStatus = EnsureWaiting();
if (NS_SUCCEEDED(mStatus))
break;
@ -520,20 +510,13 @@ nsInputStreamPump::OnStateTransfer()
if (NS_SUCCEEDED(mStatus)) {
if (NS_FAILED(rv))
mStatus = rv;
else {
// Check to see if stream will have more data. If so, then stay in
// the STATE_TRANSFER state. Otherwise, advance to STATE_STOP.
//
// NOTE: Calling Available is insufficient since that method could
// return 0 bytes available and NS_OK when it is at end-of-
// file but not closed. We would not be able to distinguish
// that case from a stream that is merely waiting for more
// data to become available. By using ReadSegments we can
// tell if the stream will ever have more data.
//
PRUint32 n;
rv = mAsyncStream->ReadSegments(GetBytesAvailable, &avail, 1, &n);
if (rv == NS_BASE_STREAM_WOULD_BLOCK || (NS_SUCCEEDED(rv) && avail))
else if (avail) {
// if stream is now closed, advance to STATE_STOP right away.
// Available may return 0 bytes available at the moment; that
// would not mean that we are done.
// XXX async streams should have a GetStatus method!
rv = mAsyncStream->Available(&avail);
if (NS_SUCCEEDED(rv))
return STATE_TRANSFER;
}
}

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

@ -417,7 +417,7 @@ nsSocketInputStream::AsyncWait(nsIInputStreamCallback *callback,
{
nsAutoLock lock(mTransport->mLock);
if (callback && target) {
if (target) {
//
// build event proxy
//
@ -648,7 +648,7 @@ nsSocketOutputStream::AsyncWait(nsIOutputStreamCallback *callback,
{
nsAutoLock lock(mTransport->mLock);
if (callback && target) {
if (target) {
//
// build event proxy
//

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

@ -35,26 +35,20 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
#include "nsIChannel.idl"
interface nsIRequestObserver;
/**
* This interface may be used to determine if a channel is a FTP channel.
*/
[scriptable, uuid(2315d831-8b40-446a-9138-fe09ebb1b720)]
interface nsIFTPChannel : nsISupports
// this interface provides a way for the FTP connection to
// synchronize with the owning channel.
[scriptable, uuid(3476df52-1dd2-11b2-b928-925d89b33bc0)]
interface nsIFTPChannel : nsIChannel
{
};
/**
* This interface may be defined as a notification callback on the FTP
* channel. It allows a consumer to receive a log of the FTP control
* connection conversation.
*/
[scriptable, uuid(455d4234-0330-43d2-bbfb-99afbecbfeb0)]
interface nsIFTPEventSink : nsISupports
{
/**
* XXX document this method! (see bug 328915)
*/
void OnFTPControlLog(in boolean server, in string msg);
};

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

@ -36,9 +36,8 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsFTPChannel.h"
#include "nsFtpConnectionThread.h" // defines nsFtpState
#include "nsFTPChannel.h"
#include "nsIStreamListener.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
@ -59,7 +58,12 @@ extern PRLogModuleInfo* gFTPLog;
static inline PRUint32
PRTimeToSeconds(PRTime t_usec)
{
return PRUint32(t_usec / PR_USEC_PER_SEC);
PRTime usec_per_sec;
PRUint32 t_sec;
LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
LL_DIV(t_usec, t_usec, usec_per_sec);
LL_L2I(t_sec, t_usec);
return t_sec;
}
#define NowInSeconds() PRTimeToSeconds(PR_Now())
@ -74,53 +78,209 @@ PRTimeToSeconds(PRTime t_usec)
// initiated by the server (PORT command) or by the client (PASV command).
// Client initiation is the most common case and is attempted first.
//-----------------------------------------------------------------------------
nsFTPChannel::nsFTPChannel()
: mIsPending(0),
mLoadFlags(LOAD_NORMAL),
mSourceOffset(0),
mAmount(0),
mContentLength(-1),
mFTPState(nsnull),
mStatus(NS_OK),
mCanceled(PR_FALSE),
mStartPos(LL_MaxUint())
{
}
NS_IMPL_ISUPPORTS_INHERITED3(nsFtpChannel,
nsBaseChannel,
nsIUploadChannel,
nsIResumableChannel,
nsIFTPChannel)
nsFTPChannel::~nsFTPChannel()
{
#if defined(PR_LOGGING)
nsCAutoString spec;
mURL->GetAsciiSpec(spec);
PR_LOG(gFTPLog, PR_LOG_ALWAYS, ("~nsFTPChannel() for %s", spec.get()));
#endif
NS_IF_RELEASE(mFTPState);
}
//-----------------------------------------------------------------------------
NS_IMPL_ADDREF_INHERITED(nsFTPChannel, nsHashPropertyBag)
NS_IMPL_RELEASE_INHERITED(nsFTPChannel, nsHashPropertyBag)
NS_INTERFACE_MAP_BEGIN(nsFTPChannel)
NS_INTERFACE_MAP_ENTRY(nsIChannel)
NS_INTERFACE_MAP_ENTRY(nsIFTPChannel)
NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)
NS_INTERFACE_MAP_ENTRY(nsIRequest)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
NS_INTERFACE_MAP_ENTRY(nsICacheListener)
NS_INTERFACE_MAP_END_INHERITING(nsHashPropertyBag)
nsresult
nsFTPChannel::Init(nsIURI* uri, nsIProxyInfo* proxyInfo, nsICacheSession* session)
{
nsresult rv = nsHashPropertyBag::Init();
if (NS_FAILED(rv))
return rv;
// setup channel state
mURL = uri;
mProxyInfo = proxyInfo;
mIOService = do_GetIOService(&rv);
if (NS_FAILED(rv)) return rv;
mCacheSession = session;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIRequest methods:
// The FTP channel doesn't maintain any connection state. Nor does it
// interpret the protocol. The FTP connection thread is responsible for
// these things and thus, the FTP channel simply calls through to the
// FTP connection thread using an xpcom proxy object to make the
// cross thread call.
NS_IMETHODIMP
nsFtpChannel::SetUploadStream(nsIInputStream *stream,
const nsACString &contentType,
PRInt32 contentLength)
nsFTPChannel::GetName(nsACString &result)
{
NS_ENSURE_TRUE(!IsPending(), NS_ERROR_IN_PROGRESS);
return mURL->GetSpec(result);
}
mUploadStream = stream;
// NOTE: contentLength is intentionally ignored here.
NS_IMETHODIMP
nsFTPChannel::IsPending(PRBool *result) {
*result = mIsPending;
return NS_OK;
}
NS_IMETHODIMP
nsFtpChannel::GetUploadStream(nsIInputStream **stream)
nsFTPChannel::GetStatus(nsresult *status)
{
NS_ENSURE_ARG_POINTER(stream);
*stream = mUploadStream;
NS_IF_ADDREF(*stream);
*status = mStatus;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsFTPChannel::Cancel(nsresult status) {
PR_LOG(gFTPLog,
PR_LOG_DEBUG,
("nsFTPChannel::Cancel() called [this=%x, status=%x, mCanceled=%d]\n",
this, status, mCanceled));
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
if (mCanceled)
return NS_OK;
mCanceled = PR_TRUE;
mStatus = status;
if (mFTPState)
(void)mFTPState->Cancel(status);
return NS_OK;
}
NS_IMETHODIMP
nsFtpChannel::ResumeAt(PRUint64 aStartPos, const nsACString& aEntityID)
nsFTPChannel::Suspend(void) {
PR_LOG(gFTPLog, PR_LOG_DEBUG,
("nsFTPChannel::Suspend() called [this=%x]\n", this));
if (mFTPState) {
return mFTPState->Suspend();
}
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::Resume(void) {
PR_LOG(gFTPLog, PR_LOG_DEBUG,
("nsFTPChannel::Resume() called [this=%x]\n", this));
if (mFTPState) {
return mFTPState->Resume();
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIChannel methods:
NS_IMETHODIMP
nsFTPChannel::GetOriginalURI(nsIURI* *aURL)
{
*aURL = mOriginalURI ? mOriginalURI : mURL;
NS_ADDREF(*aURL);
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetOriginalURI(nsIURI* aURL)
{
mOriginalURI = aURL;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::GetURI(nsIURI* *aURL)
{
*aURL = mURL;
NS_ADDREF(*aURL);
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::Open(nsIInputStream **result)
{
return NS_ImplementChannelOpen(this, result);
}
nsresult
nsFTPChannel::GenerateCacheKey(nsACString &cacheKey)
{
cacheKey.SetLength(0);
nsCAutoString spec;
mURL->GetAsciiSpec(spec);
// Strip any trailing #ref from the URL before using it as the key
const char *p = strchr(spec.get(), '#');
if (p)
cacheKey.Append(Substring(spec, 0, p - spec.get()));
else
cacheKey.Append(spec);
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
{
nsresult rv = AsyncOpenAt(listener, ctxt, mStartPos, mEntityID);
// mEntityID no longer needed, clear it to avoid returning a wrong entity
// id when someone asks us
mEntityID.Truncate();
return rv;
}
NS_IMETHODIMP
nsFTPChannel::ResumeAt(PRUint64 aStartPos, const nsACString& aEntityID)
{
NS_ENSURE_TRUE(!IsPending(), NS_ERROR_IN_PROGRESS);
mEntityID = aEntityID;
mStartPos = aStartPos;
mResumeRequested = (mStartPos || !mEntityID.IsEmpty());
return NS_OK;
}
NS_IMETHODIMP
nsFtpChannel::GetEntityID(nsACString& entityID)
nsFTPChannel::GetEntityID(nsACString& entityID)
{
if (mEntityID.IsEmpty())
return NS_ERROR_NOT_RESUMABLE;
@ -129,48 +289,70 @@ nsFtpChannel::GetEntityID(nsACString& entityID)
return NS_OK;
}
//-----------------------------------------------------------------------------
nsresult
nsFtpChannel::OpenContentStream(PRBool async, nsIInputStream **result)
nsFTPChannel::AsyncOpenAt(nsIStreamListener *listener, nsISupports *ctxt,
PRUint64 startPos, const nsACString& entityID)
{
if (!async)
return NS_ERROR_NOT_IMPLEMENTED;
nsFtpState *state = new nsFtpState();
if (!state)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(state);
nsresult rv = state->Init(this);
if (NS_FAILED(rv)) {
NS_RELEASE(state);
PRInt32 port;
nsresult rv = mURL->GetPort(&port);
if (NS_FAILED(rv))
return rv;
rv = NS_CheckPortSafety(port, "ftp", mIOService);
if (NS_FAILED(rv))
return rv;
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::AsyncOpen() called\n"));
mListener = listener;
mUserContext = ctxt;
// Add this request to the load group
if (mLoadGroup)
mLoadGroup->AddRequest(this, nsnull);
PRBool offline;
// If we're starting from the beginning, then its OK to use the cache,
// because the entire file must be there (the cache doesn't support
// partial entries yet)
// Note that ftp doesn't store metadata, so disable caching if there was
// an entityID. Storing this metadata isn't worth it until we can
// get partial data out of the cache anyway...
if (mCacheSession && !mUploadStream && entityID.IsEmpty() &&
(startPos==0 || startPos==PRUint32(-1))) {
mIOService->GetOffline(&offline);
// Set the desired cache access mode accordingly...
nsCacheAccessMode accessRequested;
if (offline) {
// Since we are offline, we can only read from the cache.
accessRequested = nsICache::ACCESS_READ;
}
else if (mLoadFlags & LOAD_BYPASS_CACHE)
accessRequested = nsICache::ACCESS_WRITE; // replace cache entry
else
accessRequested = nsICache::ACCESS_READ_WRITE; // normal browsing
nsCAutoString cacheKey;
GenerateCacheKey(cacheKey);
rv = mCacheSession->AsyncOpenCacheEntry(cacheKey,
accessRequested,
this);
if (NS_SUCCEEDED(rv))
return rv;
// If we failed to use the cache, try without
PR_LOG(gFTPLog, PR_LOG_DEBUG,
("Opening cache entry failed [rv=%x]", rv));
}
*result = state;
return NS_OK;
}
PRBool
nsFtpChannel::GetStatusArg(nsresult status, nsString &statusArg)
{
nsCAutoString host;
URI()->GetHost(host);
CopyUTF8toUTF16(host, statusArg);
return PR_TRUE;
return SetupState(startPos, entityID);
// XXX this function must not fail since we have already called AddRequest!
}
void
nsFtpChannel::OnCallbacksChanged()
{
mFTPEventSink = nsnull;
}
//-----------------------------------------------------------------------------
void
nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
nsFTPChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
{
if (!mFTPEventSink) {
nsCOMPtr<nsIFTPEventSink> ftpSink;
@ -184,3 +366,369 @@ nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
}
aResult = mFTPEventSink;
}
void
nsFTPChannel::InitProgressSink()
{
// Build a proxy for the progress event sink since we may need to call it
// while we are deep inside some of our state logic, and we wouldn't want
// to worry about some weird re-entrancy scenario.
nsCOMPtr<nsIProgressEventSink> progressSink;
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, progressSink);
if (progressSink)
NS_GetProxyForObject(NS_CURRENT_EVENTQ,
NS_GET_IID(nsIProgressEventSink),
progressSink,
PROXY_ASYNC | PROXY_ALWAYS,
getter_AddRefs(mProgressSink));
}
nsresult
nsFTPChannel::SetupState(PRUint64 startPos, const nsACString& entityID)
{
if (!mFTPState) {
NS_NEWXPCOM(mFTPState, nsFtpState);
if (!mFTPState) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(mFTPState);
}
nsresult rv = mFTPState->Init(this,
mCacheEntry,
mProxyInfo,
startPos,
entityID);
if (NS_FAILED(rv)) return rv;
(void) mFTPState->SetWriteStream(mUploadStream);
rv = mFTPState->Connect();
if (NS_FAILED(rv)) return rv;
mIsPending = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::GetLoadFlags(PRUint32 *aLoadFlags)
{
*aLoadFlags = mLoadFlags;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetLoadFlags(PRUint32 aLoadFlags)
{
mLoadFlags = aLoadFlags;
return NS_OK;
}
// FTP does not provide a file typing mechanism. We fallback to file
// extension mapping.
NS_IMETHODIMP
nsFTPChannel::GetContentType(nsACString &aContentType)
{
if (mContentType.IsEmpty()) {
aContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
} else {
aContentType = mContentType;
}
PR_LOG(gFTPLog, PR_LOG_DEBUG, ("nsFTPChannel::GetContentType() returned %s\n", PromiseFlatCString(aContentType).get()));
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetContentType(const nsACString &aContentType)
{
PRBool dummy;
net_ParseContentType(aContentType, mContentType, mContentCharset, &dummy);
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::GetContentCharset(nsACString &aContentCharset)
{
aContentCharset = mContentCharset;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetContentCharset(const nsACString &aContentCharset)
{
mContentCharset = aContentCharset;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::GetContentLength(PRInt32 *aContentLength)
{
*aContentLength = mContentLength;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetContentLength(PRInt32 aContentLength)
{
mContentLength = aContentLength;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
mProgressSink = nsnull;
mFTPEventSink = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get();
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetOwner(nsISupports* aOwner)
{
mOwner = aOwner;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
NS_IF_ADDREF(*aNotificationCallbacks = mCallbacks);
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
mProgressSink = nsnull;
mFTPEventSink = nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
*aSecurityInfo = nsnull;
return NS_OK;
}
// nsIInterfaceRequestor method
NS_IMETHODIMP
nsFTPChannel::GetInterface(const nsIID &aIID, void **aResult)
{
// capture the progress event sink stuff. pass the rest through.
if (aIID.Equals(NS_GET_IID(nsIProgressEventSink))) {
*aResult = NS_STATIC_CAST(nsIProgressEventSink*, this);
NS_ADDREF(this);
return NS_OK;
}
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, aIID, aResult);
return aResult ? NS_OK : NS_ERROR_NO_INTERFACE;
}
// nsIProgressEventSink methods
NS_IMETHODIMP
nsFTPChannel::OnStatus(nsIRequest *request, nsISupports *aContext,
nsresult aStatus, const PRUnichar* aStatusArg)
{
if (!mProgressSink)
InitProgressSink();
if (aStatus == NS_NET_STATUS_CONNECTED_TO)
{
// The state machine needs to know that the data connection
// was successfully started so that it can issue data commands
// securely.
if (mFTPState)
mFTPState->DataConnectionEstablished();
else
NS_ERROR("ftp state is null.");
}
if (!mProgressSink || (mLoadFlags & LOAD_BACKGROUND) || !mIsPending || NS_FAILED(mStatus))
return NS_OK;
nsCAutoString host;
mURL->GetHost(host);
return mProgressSink->OnStatus(this, mUserContext, aStatus,
NS_ConvertUTF8toUTF16(host).get());
}
NS_IMETHODIMP
nsFTPChannel::OnProgress(nsIRequest *request, nsISupports* aContext,
PRUint64 aProgress, PRUint64 aProgressMax)
{
if (!mProgressSink)
InitProgressSink();
if (!mProgressSink || (mLoadFlags & LOAD_BACKGROUND) || !mIsPending)
return NS_OK;
return mProgressSink->OnProgress(this, mUserContext,
aProgress, aProgressMax);
}
// nsIRequestObserver methods.
NS_IMETHODIMP
nsFTPChannel::OnStopRequest(nsIRequest *request, nsISupports* aContext,
nsresult aStatus)
{
PR_LOG(gFTPLog,
PR_LOG_DEBUG,
("nsFTPChannel::OnStopRequest() called [this=%x, request=%x, aStatus=%x]\n",
this, request, aStatus));
nsresult rv = NS_OK;
if (NS_SUCCEEDED(mStatus))
mStatus = aStatus;
if (mListener) {
(void) mListener->OnStopRequest(this, mUserContext, mStatus);
}
if (mLoadGroup) {
(void) mLoadGroup->RemoveRequest(this, nsnull, mStatus);
}
if (mCacheEntry) {
if (NS_SUCCEEDED(mStatus)) {
(void) mCacheEntry->SetExpirationTime( NowInSeconds() + 900 ); // valid for 15 minutes.
(void) mCacheEntry->MarkValid();
}
else {
(void) mCacheEntry->Doom();
}
mCacheEntry->Close();
mCacheEntry = 0;
}
if (mUploadStream)
mUploadStream->Close();
if (mFTPState) {
mFTPState->DataConnectionComplete();
NS_RELEASE(mFTPState);
}
mIsPending = PR_FALSE;
// Drop notification callbacks to prevent cycles.
mCallbacks = nsnull;
mProgressSink = nsnull;
mFTPEventSink = nsnull;
return rv;
}
NS_IMETHODIMP
nsFTPChannel::OnStartRequest(nsIRequest *request, nsISupports *aContext)
{
PR_LOG(gFTPLog,
PR_LOG_DEBUG,
("nsFTPChannel::OnStartRequest() called [this=%x, request=%x]\n",
this, request));
if (NS_SUCCEEDED(mStatus))
request->GetStatus(&mStatus);
nsCOMPtr<nsIResumableChannel> resumable = do_QueryInterface(request);
if (resumable) {
resumable->GetEntityID(mEntityID);
}
nsresult rv = NS_OK;
if (mListener) {
if (mContentType.IsEmpty()) {
// Time to sniff!
nsCOMPtr<nsIStreamConverterService> serv =
do_GetService("@mozilla.org/streamConverters;1", &rv);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIStreamListener> converter;
rv = serv->AsyncConvertData(UNKNOWN_CONTENT_TYPE,
"*/*",
mListener,
mUserContext,
getter_AddRefs(converter));
if (NS_SUCCEEDED(rv)) {
mListener = converter;
}
}
}
rv = mListener->OnStartRequest(this, mUserContext);
if (NS_FAILED(rv)) return rv;
}
return rv;
}
// nsIStreamListener method
NS_IMETHODIMP
nsFTPChannel::OnDataAvailable(nsIRequest *request, nsISupports* aContext,
nsIInputStream *aInputStream, PRUint32 aSourceOffset,
PRUint32 aLength) {
return mListener->OnDataAvailable(this, mUserContext, aInputStream, aSourceOffset, aLength);
}
//-----------------------------------------------------------------------------
// nsFTPChannel::nsICacheListener
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsFTPChannel::OnCacheEntryAvailable(nsICacheEntryDescriptor *entry,
nsCacheAccessMode access,
nsresult status)
{
nsresult rv;
if (mCanceled) {
NS_ASSERTION(NS_FAILED(mStatus), "Must be canceled with a failure status code");
OnStartRequest(NS_STATIC_CAST(nsIRequest*, this), nsnull);
OnStopRequest(NS_STATIC_CAST(nsIRequest*, this), nsnull, mStatus);
return mStatus;
}
if (NS_SUCCEEDED(status)) {
mCacheEntry = entry;
}
rv = SetupState(PRUint32(-1), EmptyCString());
if (NS_FAILED(rv)) {
Cancel(rv);
}
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::SetUploadStream(nsIInputStream *stream, const nsACString &contentType, PRInt32 contentLength)
{
mUploadStream = stream;
return NS_OK;
}
NS_IMETHODIMP
nsFTPChannel::GetUploadStream(nsIInputStream **stream)
{
NS_ENSURE_ARG_POINTER(stream);
*stream = mUploadStream;
NS_IF_ADDREF(*stream);
return NS_OK;
}

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

@ -1,5 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim:set ts=4 sw=4 sts=4 et cindent: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
@ -41,8 +40,6 @@
#ifndef nsFTPChannel_h___
#define nsFTPChannel_h___
#include "nsBaseChannel.h"
#include "nsIIOService.h"
#include "nsIURI.h"
#include "nsString.h"
@ -75,63 +72,94 @@
#define FTP_DATA_CHANNEL_SEG_SIZE (4*1024)
#define FTP_DATA_CHANNEL_SEG_COUNT 8
class nsFtpChannel : public nsBaseChannel,
#define FTP_CACHE_CONTROL_CONNECTION 1
class nsFTPChannel : public nsHashPropertyBag,
public nsIFTPChannel,
public nsIUploadChannel,
public nsIInterfaceRequestor,
public nsIProgressEventSink,
public nsIStreamListener,
public nsICacheListener,
public nsIResumableChannel
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
NS_DECL_NSIUPLOADCHANNEL
NS_DECL_NSIFTPCHANNEL
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIPROGRESSEVENTSINK
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSICACHELISTENER
NS_DECL_NSIRESUMABLECHANNEL
nsFtpChannel(nsIURI *uri, nsIProxyInfo *pi)
: mProxyInfo(pi)
, mStartPos(0)
, mResumeRequested(PR_FALSE)
{
SetURI(uri);
}
// nsFTPChannel methods:
nsFTPChannel();
virtual ~nsFTPChannel();
// initializes the channel.
nsresult Init(nsIURI* uri,
nsIProxyInfo* proxyInfo,
nsICacheSession* session);
nsIProxyInfo *ProxyInfo() {
return mProxyInfo;
}
nsresult SetupState(PRUint64 startPos, const nsACString& entityID);
nsresult GenerateCacheKey(nsACString &cacheKey);
nsresult AsyncOpenAt(nsIStreamListener *listener, nsISupports *ctxt,
PRUint64 startPos, const nsACString& entityID);
// Were we asked to resume a download?
PRBool ResumeRequested() { return mResumeRequested; }
// Download from this byte offset
PRUint64 StartPos() { return mStartPos; }
// ID of the entity to resume downloading
const nsCString &EntityID() {
return mEntityID;
}
void SetEntityID(const nsCSubstring &entityID) {
mEntityID = entityID;
}
// Data stream to upload
nsIInputStream *UploadStream() {
return mUploadStream;
// Helper function to simplify getting notification callbacks.
template <class T>
void GetCallback(nsCOMPtr<T> &aResult) {
GetInterface(NS_GET_TEMPLATE_IID(T), getter_AddRefs(aResult));
}
// Helper function for getting the nsIFTPEventSink.
void GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult);
protected:
virtual ~nsFtpChannel() {}
virtual nsresult OpenContentStream(PRBool async, nsIInputStream **result);
virtual PRBool GetStatusArg(nsresult status, nsString &statusArg);
virtual void OnCallbacksChanged();
void InitProgressSink();
private:
nsCOMPtr<nsIProxyInfo> mProxyInfo;
nsCOMPtr<nsIFTPEventSink> mFTPEventSink;
nsCOMPtr<nsIInputStream> mUploadStream;
PRUint64 mStartPos;
nsCString mEntityID;
PRPackedBool mResumeRequested;
protected:
nsCOMPtr<nsIURI> mOriginalURI;
nsCOMPtr<nsIURI> mURL;
nsCOMPtr<nsIInputStream> mUploadStream;
// various callback interfaces
nsCOMPtr<nsIProgressEventSink> mProgressSink;
nsCOMPtr<nsIFTPEventSink> mFTPEventSink;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
PRBool mIsPending;
PRUint32 mLoadFlags;
PRUint32 mSourceOffset;
PRInt32 mAmount;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCString mContentType;
nsCString mContentCharset;
PRInt32 mContentLength;
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsIStreamListener> mListener;
nsFtpState* mFTPState;
nsCOMPtr<nsISupports> mUserContext;
nsresult mStatus;
PRPackedBool mCanceled;
nsCOMPtr<nsIIOService> mIOService;
nsCOMPtr<nsICacheSession> mCacheSession;
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
nsCOMPtr<nsIProxyInfo> mProxyInfo;
nsCString mEntityID;
PRUint64 mStartPos;
};
#endif /* nsFTPChannel_h___ */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -40,9 +40,6 @@
#define __nsFtpState__h_
#include "ftpCore.h"
#include "nsFTPChannel.h"
#include "nsBaseContentStream.h"
#include "nsInt64.h"
#include "nsIThread.h"
#include "nsIRunnable.h"
@ -50,14 +47,13 @@
#include "nsISocketTransport.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
#include "nsICacheListener.h"
#include "nsIURI.h"
#include "prtime.h"
#include "nsString.h"
#include "nsIFTPChannel.h"
#include "nsIProtocolHandler.h"
#include "nsCOMPtr.h"
#include "nsIAsyncInputStream.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsAutoLock.h"
#include "nsAutoPtr.h"
@ -70,7 +66,6 @@
#include "nsFtpControlConnection.h"
#include "nsICacheEntryDescriptor.h"
#include "nsICacheListener.h"
// ftp server types
#define FTP_GENERIC_TYPE 0
@ -83,9 +78,6 @@
typedef enum _FTP_STATE {
///////////////////////
//// Internal states
FTP_INIT,
FTP_WAIT_CACHE,
FTP_READ_CACHE,
FTP_COMMAND_CONNECT,
FTP_READ_BUF,
FTP_ERROR,
@ -112,46 +104,38 @@ typedef enum _FTP_STATE {
// higher level ftp actions
typedef enum _FTP_ACTION {GET, PUT} FTP_ACTION;
class nsFtpChannel;
class DataRequestForwarder;
class nsFTPChannel;
// The nsFtpState object is the content stream for the channel. It implements
// nsIInputStreamCallback, so it can read data from the control connection. It
// implements nsITransportEventSink so it can mix status events from both the
// control connection and the data connection.
class nsFtpState : public nsBaseContentStream,
public nsIInputStreamCallback,
public nsITransportEventSink,
public nsICacheListener,
public nsIRequestObserver,
public nsFtpControlConnectionListener {
class nsFtpState : public nsIStreamListener,
public nsIRequest {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSITRANSPORTEVENTSINK
NS_DECL_NSICACHELISTENER
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
// Override input stream methods:
NS_IMETHOD CloseWithStatus(nsresult status);
NS_IMETHOD Available(PRUint32 *result);
NS_IMETHOD ReadSegments(nsWriteSegmentFun fun, void *closure,
PRUint32 count, PRUint32 *result);
// nsFtpControlConnectionListener methods:
virtual void OnControlDataAvailable(const char *data, PRUint32 dataLen);
virtual void OnControlError(nsresult status);
NS_DECL_NSIREQUEST
nsFtpState();
nsresult Init(nsFtpChannel *channel);
protected:
// Notification from nsBaseContentStream::AsyncWait
virtual void OnCallbackPending();
private:
virtual ~nsFtpState();
nsresult Init(nsFTPChannel *aChannel,
nsICacheEntryDescriptor* cacheEntry,
nsIProxyInfo* proxyInfo,
PRUint64 startPos,
const nsACString& entity);
// use this to provide a stream to be written to the server.
nsresult SetWriteStream(nsIInputStream* aInStream);
nsresult GetEntityID(nsACString& aEntityID);
nsresult Connect();
// lets the data forwarder tell us when the the data pipe has been created
// and when the data pipe has finished.
void DataConnectionEstablished();
void DataConnectionComplete();
private:
///////////////////////////////////
// BEGIN: STATE METHODS
nsresult S_user(); FTP_STATE R_user();
@ -181,60 +165,13 @@ private:
void KillControlConnection();
nsresult StopProcessing();
nsresult EstablishControlConnection();
nsresult SendFTPCommand(const nsCSubstring& command);
nsresult SendFTPCommand(nsCString& command);
void ConvertFilespecToVMS(nsCString& fileSpec);
void ConvertDirspecToVMS(nsCString& fileSpec);
void ConvertDirspecFromVMS(nsCString& fileSpec);
nsresult BuildStreamConverter(nsIStreamListener** convertStreamListener);
nsresult SetContentType();
/**
* This method is called to kick-off the FTP state machine. mState is
* reset to FTP_COMMAND_CONNECT, and the FTP state machine progresses from
* there. This method is initially called (indirectly) from the channel's
* AsyncOpen implementation.
*/
void Connect();
/**
* This method opens a cache entry for reading or writing depending on the
* state of the channel and of the system (e.g., opened for reading if we
* are offline). This method is responsible for setting mCacheEntry if
* there is a cache entry that can be used. It returns true if it ends up
* waiting (asynchronously) for access to the cache entry. In that case,
* the nsFtpState's OnCacheEntryAvailable method will be called once the
* cache entry is available or if an error occurs.
*/
PRBool CheckCache();
/**
* This method returns true if the data for this URL can be read from the
* cache. This method assumes that mCacheEntry is non-null.
*/
PRBool CanReadCacheEntry();
/**
* This method causes the cache entry to be read. Data from the cache
* entry will be fed to the channel's listener. This method returns true
* if successfully reading from the cache. This method assumes that
* mCacheEntry is non-null and opened with read access.
*/
PRBool ReadCacheEntry();
/**
* This method configures mDataStream with an asynchronous input stream to
* the cache entry. The cache entry is read on a background thread. This
* method assumes that mCacheEntry is non-null and opened with read access.
*/
nsresult OpenCacheDataStream();
/**
* This method inserts the cache entry's output stream into the stream
* listener chain for the FTP channel. As a result, the cache entry
* receives data as data is pushed to the channel's listener. This method
* assumes that mCacheEntry is non-null and opened with write access.
*/
nsresult InstallCacheListener();
PRBool CanReadEntry();
///////////////////////////////////
// Private members
@ -244,22 +181,27 @@ private:
FTP_STATE mNextState; // the next state
PRPackedBool mKeepRunning; // thread event loop boolean
PRInt32 mResponseCode; // the last command response code
nsCString mResponseMsg; // the last command response text
nsCAutoString mResponseMsg; // the last command response text
// ****** channel/transport/stream vars
nsRefPtr<nsFtpControlConnection> mControlConnection; // cacheable control connection (owns mCPipe)
nsFtpControlConnection* mControlConnection; // cacheable control connection (owns mCPipe)
PRPackedBool mReceivedControlData;
PRPackedBool mTryingCachedControl; // retrying the password
PRPackedBool mWaitingForDConn; // Are we wait for a data connection
PRPackedBool mRETRFailed; // Did we already try a RETR and it failed?
nsCOMPtr<nsISocketTransport> mDPipe; // the data transport
nsCOMPtr<nsIRequest> mDPipeRequest;
DataRequestForwarder* mDRequestForwarder;
PRUint64 mFileSize;
nsCString mModTime;
// ****** consumer vars
nsRefPtr<nsFtpChannel> mChannel; // our owning FTP channel we pass through our events
nsRefPtr<nsFTPChannel> mChannel; // our owning FTP channel we pass through our events
nsCOMPtr<nsIProxyInfo> mProxyInfo;
// ****** connection cache vars
PRInt32 mServerType; // What kind of server are we talking to
PRPackedBool mList; // Use LIST instead of NLST
// ****** protocol interpretation related state vars
nsString mUsername; // username
@ -270,28 +212,35 @@ private:
nsresult mInternalError; // represents internal state errors
// ****** URI vars
nsCOMPtr<nsIURI> mURL; // the uri we're connecting to
PRInt32 mPort; // the port to connect to
nsString mFilename; // url filename (if any)
nsCString mPath; // the url's path
nsCString mPwd; // login Path
// ****** other vars
nsCOMPtr<nsITransport> mDataTransport;
nsCOMPtr<nsIAsyncInputStream> mDataStream;
nsCOMPtr<nsIRequest> mUploadRequest;
PRPackedBool mIPv6Checked;
PRUint8 mSuspendCount;// number of times we've been suspended.
PRUint32 mBufferSegmentSize;
PRUint32 mBufferMaxSize;
PRLock *mLock;
nsCOMPtr<nsIInputStream> mWriteStream; // This stream is written to the server.
PRUint32 mWriteCount;
PRPackedBool mIPv6Checked;
static PRUint32 mSessionStartTime;
nsAutoArrayPtr<char> mIPv6ServerAddress; // Server IPv6 address; null if server not IPv6
char *mIPv6ServerAddress; // Server IPv6 address; null if server not IPv6
// ***** control read gvars
nsresult mControlStatus;
nsCString mControlReadCarryOverBuf;
nsCAutoString mControlReadCarryOverBuf;
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
nsUint64 mStartPos;
nsCString mSuppliedEntityID;
nsCString mEntityID;
};
#endif //__nsFtpState__h_

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

@ -47,172 +47,130 @@
#include "nsEventQueueUtils.h"
#include "nsCRT.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo* gFTPLog;
#endif
#define LOG(args) PR_LOG(gFTPLog, PR_LOG_DEBUG, args)
#define LOG_ALWAYS(args) PR_LOG(gFTPLog, PR_LOG_ALWAYS, args)
#else
#define LOG(args)
#define LOG_ALWAYS(args)
#endif
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
//
// nsFtpControlConnection implementation ...
//
NS_IMPL_ISUPPORTS1(nsFtpControlConnection, nsIInputStreamCallback)
NS_IMPL_THREADSAFE_ISUPPORTS2(nsFtpControlConnection,
nsIStreamListener,
nsIRequestObserver)
NS_IMETHODIMP
nsFtpControlConnection::OnInputStreamReady(nsIAsyncInputStream *stream)
nsFtpControlConnection::nsFtpControlConnection(const char* host, PRUint32 port)
: mServerType(0), mPort(port)
{
char data[4096];
LOG_ALWAYS(("(%x) nsFtpControlConnection created", this));
// Consume data whether we have a listener or not.
PRUint32 avail;
nsresult rv = stream->Available(&avail);
if (NS_SUCCEEDED(rv)) {
if (avail > sizeof(data))
avail = sizeof(data);
PRUint32 n;
rv = stream->Read(data, avail, &n);
if (NS_SUCCEEDED(rv) && n != avail)
avail = n;
}
// It's important that we null out mListener before calling one of its
// methods as it may call WaitData, which would queue up another read.
nsRefPtr<nsFtpControlConnectionListener> listener;
listener.swap(mListener);
if (!listener)
return NS_OK;
if (NS_FAILED(rv)) {
listener->OnControlError(rv);
} else {
listener->OnControlDataAvailable(data, avail);
}
return NS_OK;
}
nsFtpControlConnection::nsFtpControlConnection(const nsCSubstring& host, PRUint32 port)
: mServerType(0), mHost(host), mPort(port)
{
LOG_ALWAYS(("FTP:CC created @%p", this));
mHost.Assign(host);
}
nsFtpControlConnection::~nsFtpControlConnection()
{
LOG_ALWAYS(("FTP:CC destroyed @%p", this));
LOG_ALWAYS(("(%x) nsFtpControlConnection destroyed", this));
}
PRBool
nsFtpControlConnection::IsAlive()
{
if (!mSocket)
if (!mCPipe)
return PR_FALSE;
PRBool isAlive = PR_FALSE;
mSocket->IsAlive(&isAlive);
mCPipe->IsAlive(&isAlive);
return isAlive;
}
nsresult
nsFtpControlConnection::Connect(nsIProxyInfo* proxyInfo,
nsITransportEventSink* eventSink)
{
if (mSocket)
return NS_OK;
// build our own
nsresult rv;
nsCOMPtr<nsISocketTransportService> sts =
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_FAILED(rv))
return rv;
rv = sts->CreateTransport(nsnull, 0, mHost, mPort, proxyInfo,
getter_AddRefs(mSocket)); // the command transport
if (NS_FAILED(rv))
return rv;
if (!mCPipe) {
// build our own
nsCOMPtr<nsISocketTransportService> sts =
do_GetService(kSocketTransportServiceCID, &rv);
// proxy transport events back to current thread
if (eventSink) {
nsCOMPtr<nsIEventQueue> eventQ;
rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ));
if (NS_SUCCEEDED(rv))
mSocket->SetEventSink(eventSink, eventQ);
rv = sts->CreateTransport(nsnull, 0, mHost, mPort, proxyInfo,
getter_AddRefs(mCPipe)); // the command transport
if (NS_FAILED(rv)) return rv;
// proxy transport events back to current thread
if (eventSink) {
nsCOMPtr<nsIEventQueue> eventQ;
rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ));
if (NS_SUCCEEDED(rv))
mCPipe->SetEventSink(eventSink, eventQ);
}
// open buffered, blocking output stream to socket. so long as commands
// do not exceed 1024 bytes in length, the writing thread (the main thread)
// will not block. this should be OK.
rv = mCPipe->OpenOutputStream(nsITransport::OPEN_BLOCKING, 1024, 1,
getter_AddRefs(mOutStream));
if (NS_FAILED(rv)) return rv;
// open buffered, non-blocking/asynchronous input stream to socket.
nsCOMPtr<nsIInputStream> inStream;
rv = mCPipe->OpenInputStream(0,
FTP_COMMAND_CHANNEL_SEG_SIZE,
FTP_COMMAND_CHANNEL_SEG_COUNT,
getter_AddRefs(inStream));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIInputStreamPump> pump;
rv = NS_NewInputStreamPump(getter_AddRefs(pump), inStream);
if (NS_FAILED(rv)) return rv;
// get the ball rolling by reading on the control socket.
rv = pump->AsyncRead(NS_STATIC_CAST(nsIStreamListener*, this), nsnull);
if (NS_FAILED(rv)) return rv;
// cyclic reference!
mReadRequest = pump;
}
// open buffered, blocking output stream to socket. so long as commands
// do not exceed 1024 bytes in length, the writing thread (the main thread)
// will not block. this should be OK.
rv = mSocket->OpenOutputStream(nsITransport::OPEN_BLOCKING, 1024, 1,
getter_AddRefs(mSocketOutput));
if (NS_FAILED(rv))
return rv;
// open buffered, non-blocking/asynchronous input stream to socket.
nsCOMPtr<nsIInputStream> inStream;
rv = mSocket->OpenInputStream(0,
FTP_COMMAND_CHANNEL_SEG_SIZE,
FTP_COMMAND_CHANNEL_SEG_COUNT,
getter_AddRefs(inStream));
if (NS_SUCCEEDED(rv))
mSocketInput = do_QueryInterface(inStream);
return rv;
}
nsresult
nsFtpControlConnection::WaitData(nsFtpControlConnectionListener *listener)
{
LOG(("FTP:(%p) wait data [listener=%p]\n", this, listener));
// If listener is null, then simply disconnect the listener. Otherwise,
// ensure that we are listening.
if (!listener) {
mListener = nsnull;
return NS_OK;
}
NS_ENSURE_STATE(mSocketInput);
nsCOMPtr<nsIEventQueue> eventQ;
NS_GetCurrentEventQ(getter_AddRefs(eventQ));
NS_ENSURE_STATE(eventQ);
mListener = listener;
return mSocketInput->AsyncWait(this, 0, 0, eventQ);
return NS_OK;
}
nsresult
nsFtpControlConnection::Disconnect(nsresult status)
{
if (!mSocket)
return NS_OK; // already disconnected
if (!mCPipe) return NS_ERROR_FAILURE;
LOG_ALWAYS(("FTP:(%p) CC disconnecting (%x)", this, status));
LOG_ALWAYS(("(%x) nsFtpControlConnection disconnecting (%x)", this, status));
if (NS_FAILED(status)) {
// break cyclic reference!
mSocket->Close(status);
mSocket = 0;
mSocketInput->AsyncWait(nsnull, 0, 0, nsnull); // clear any observer
mSocketInput = nsnull;
mSocketOutput = nsnull;
mOutStream = 0;
mReadRequest->Cancel(status);
mReadRequest = 0;
mCPipe->Close(status);
mCPipe = 0;
}
return NS_OK;
}
nsresult
nsFtpControlConnection::Write(const nsCSubstring& command)
nsFtpControlConnection::Write(nsCString& command, PRBool suspend)
{
NS_ENSURE_STATE(mSocketOutput);
if (!mCPipe)
return NS_ERROR_FAILURE;
PRUint32 len = command.Length();
PRUint32 cnt;
nsresult rv = mSocketOutput->Write(command.Data(), len, &cnt);
nsresult rv = mOutStream->Write(command.get(), len, &cnt);
if (NS_FAILED(rv))
return rv;
@ -220,5 +178,59 @@ nsFtpControlConnection::Write(const nsCSubstring& command)
if (len != cnt)
return NS_ERROR_FAILURE;
if (suspend)
return NS_OK;
return NS_OK;
}
NS_IMETHODIMP
nsFtpControlConnection::OnStartRequest(nsIRequest *request, nsISupports *aContext)
{
if (!mCPipe)
return NS_OK;
if (!mListener)
return NS_OK;
// In case our listener tries to remove itself via SetStreamListener(nsnull),
// we need to keep an extra reference to it on the stack.
nsCOMPtr<nsIStreamListener> deathGrip = mListener;
return mListener->OnStartRequest(request, aContext);
}
NS_IMETHODIMP
nsFtpControlConnection::OnStopRequest(nsIRequest *request, nsISupports *aContext,
nsresult aStatus)
{
if (!mCPipe)
return NS_OK;
if (!mListener)
return NS_OK;
// In case our listener tries to remove itself via SetStreamListener(nsnull),
// we need to keep an extra reference to it on the stack.
nsCOMPtr<nsIStreamListener> deathGrip = mListener;
return mListener->OnStopRequest(request, aContext, aStatus);
}
NS_IMETHODIMP
nsFtpControlConnection::OnDataAvailable(nsIRequest *request,
nsISupports *aContext,
nsIInputStream *aInStream,
PRUint32 aOffset,
PRUint32 aCount)
{
if (!mCPipe)
return NS_OK;
if (!mListener)
return NS_OK;
// In case our listener tries to remove itself via SetStreamListener(nsnull),
// we need to keep an extra reference to it on the stack.
nsCOMPtr<nsIStreamListener> deathGrip = mListener;
return mListener->OnDataAvailable(request, aContext, aInStream,
aOffset, aCount);
}

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

@ -46,57 +46,33 @@
#include "nsIRequest.h"
#include "nsISocketTransport.h"
#include "nsIOutputStream.h"
#include "nsIAsyncInputStream.h"
#include "nsIInputStream.h"
#include "nsAutoLock.h"
#include "nsAutoPtr.h"
#include "nsString.h"
class nsIProxyInfo;
class nsITransportEventSink;
class nsFtpControlConnectionListener : public nsISupports {
public:
/**
* Called when a chunk of data arrives on the control connection.
* @param data
* The new data or null if an error occured.
* @param dataLen
* The data length in bytes.
*/
virtual void OnControlDataAvailable(const char *data, PRUint32 dataLen) = 0;
/**
* Called when an error occurs on the control connection.
* @param status
* A failure code providing more info about the error.
*/
virtual void OnControlError(nsresult status) = 0;
};
class nsFtpControlConnection : public nsIInputStreamCallback
class nsFtpControlConnection : public nsIStreamListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIREQUESTOBSERVER
nsFtpControlConnection(const nsCSubstring& host, PRUint32 port);
nsFtpControlConnection(const char* host, PRUint32 port);
~nsFtpControlConnection();
nsresult Connect(nsIProxyInfo* proxyInfo, nsITransportEventSink* eventSink);
nsresult Disconnect(nsresult status);
nsresult Write(const nsCSubstring& command);
nsresult Write(nsCString& command, PRBool suspend);
PRBool IsAlive();
nsITransport *Transport() { return mSocket; }
nsIRequest *ReadRequest() { return mReadRequest; }
nsITransport *Transport() { return mCPipe; }
/**
* Call this function to be notified asynchronously when there is data
* available for the socket. The listener passed to this method replaces
* any existing listener, and the listener can be null to disconnect the
* previous listener.
*/
nsresult WaitData(nsFtpControlConnectionListener *listener);
void SetStreamListener(nsIStreamListener *l) { mListener = l; }
PRUint32 mServerType; // what kind of server is it.
nsString mPassword;
@ -107,11 +83,10 @@ private:
nsCString mHost;
PRUint32 mPort;
nsCOMPtr<nsISocketTransport> mSocket;
nsCOMPtr<nsIOutputStream> mSocketOutput;
nsCOMPtr<nsIAsyncInputStream> mSocketInput;
nsRefPtr<nsFtpControlConnectionListener> mListener;
nsCOMPtr<nsIRequest> mReadRequest;
nsCOMPtr<nsISocketTransport> mCPipe;
nsCOMPtr<nsIOutputStream> mOutStream;
nsCOMPtr<nsIStreamListener> mListener;
};
#endif

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

@ -73,7 +73,7 @@
//
// To enable logging (see prlog.h for full details):
//
// set NSPR_LOG_MODULES=nsFtp:5
// set NSPR_LOG_MODULES=nsFTPProtocol:5
// set NSPR_LOG_FILE=nspr.log
//
// this enables PR_LOG_DEBUG level information and places all output in
@ -86,7 +86,7 @@ PRLogModuleInfo* gFTPLog = nsnull;
//-----------------------------------------------------------------------------
#define IDLE_TIMEOUT_PREF "network.ftp.idleConnectionTimeout"
#define IDLE_CONNECTION_LIMIT 8 /* TODO pref me */
#define IDLE_CONNECTION_LIMIT 8 /* XXX pref me */
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
@ -99,17 +99,16 @@ nsFtpProtocolHandler::nsFtpProtocolHandler()
: mIdleTimeout(-1)
{
#if defined(PR_LOGGING)
if (!gFTPLog)
gFTPLog = PR_NewLogModule("nsFtp");
if (!gFTPLog) gFTPLog = PR_NewLogModule("nsFTPProtocol");
#endif
LOG(("FTP:creating handler @%x\n", this));
LOG(("Creating nsFtpProtocolHandler @%x\n", this));
gFtpHandler = this;
}
nsFtpProtocolHandler::~nsFtpProtocolHandler()
{
LOG(("FTP:destroying handler @%x\n", this));
LOG(("Destroying nsFtpProtocolHandler @%x\n", this));
NS_ASSERTION(mRootConnectionList.Count() == 0, "why wasn't Observe called?");
@ -144,7 +143,7 @@ nsFtpProtocolHandler::Init()
if (observerService)
observerService->AddObserver(this,
"network:offline-about-to-go-offline",
PR_TRUE);
PR_FALSE);
return NS_OK;
}
@ -212,17 +211,27 @@ nsFtpProtocolHandler::NewChannel(nsIURI* url, nsIChannel* *result)
}
NS_IMETHODIMP
nsFtpProtocolHandler::NewProxiedChannel(nsIURI* uri, nsIProxyInfo* proxyInfo,
nsIChannel* *result)
nsFtpProtocolHandler::NewProxiedChannel(nsIURI* url, nsIProxyInfo* proxyInfo, nsIChannel* *result)
{
NS_ENSURE_ARG_POINTER(uri);
nsFtpChannel *channel = new nsFtpChannel(uri, proxyInfo);
NS_ENSURE_ARG_POINTER(url);
nsFTPChannel *channel = new nsFTPChannel();
if (!channel)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(channel);
nsresult rv = channel->Init();
nsCOMPtr<nsICacheService> cache = do_GetService(kCacheServiceCID);
if (cache) {
cache->CreateSession("FTP",
nsICache::STORE_ANYWHERE,
nsICache::STREAM_BASED,
getter_AddRefs(mCacheSession));
if (mCacheSession)
mCacheSession->SetDoomEntriesIfExpired(PR_FALSE);
}
nsresult rv = channel->Init(url, proxyInfo, mCacheSession);
if (NS_FAILED(rv)) {
LOG(("nsFtpProtocolHandler::NewChannel() FAILED\n"));
NS_RELEASE(channel);
return rv;
}
@ -243,7 +252,7 @@ nsFtpProtocolHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retva
void
nsFtpProtocolHandler::Timeout(nsITimer *aTimer, void *aClosure)
{
LOG(("FTP:timeout reached for %p\n", aClosure));
LOG(("Timeout reached for %0x\n", aClosure));
PRBool found = gFtpHandler->mRootConnectionList.RemoveElement(aClosure);
if (!found) {
@ -266,7 +275,7 @@ nsFtpProtocolHandler::RemoveConnection(nsIURI *aKey, nsFtpControlConnection* *_r
nsCAutoString spec;
aKey->GetPrePath(spec);
LOG(("FTP:removing connection for %s\n", spec.get()));
LOG(("Removing connection for %s\n", spec.get()));
timerStruct* ts = nsnull;
PRInt32 i;
@ -301,7 +310,7 @@ nsFtpProtocolHandler::InsertConnection(nsIURI *aKey, nsFtpControlConnection *aCo
nsCAutoString spec;
aKey->GetPrePath(spec);
LOG(("FTP:inserting connection for %s\n", spec.get()));
LOG(("Inserting connection for %s\n", spec.get()));
nsresult rv;
nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
@ -364,7 +373,7 @@ nsFtpProtocolHandler::Observe(nsISupports *aSubject,
const char *aTopic,
const PRUnichar *aData)
{
LOG(("FTP:observing [%s]\n", aTopic));
LOG(("nsFtpProtocolHandler::Observe [topic=%s]\n", aTopic));
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(aSubject);
@ -376,12 +385,14 @@ nsFtpProtocolHandler::Observe(nsISupports *aSubject,
nsresult rv = branch->GetIntPref(IDLE_TIMEOUT_PREF, &timeout);
if (NS_SUCCEEDED(rv))
mIdleTimeout = timeout;
} else if (!strcmp(aTopic, "network:offline-about-to-go-offline")) {
}
else if (!strcmp(aTopic, "network:offline-about-to-go-offline")) {
PRInt32 i;
for (i=0;i<mRootConnectionList.Count();++i)
delete (timerStruct*)mRootConnectionList[i];
mRootConnectionList.Clear();
} else {
}
else {
NS_NOTREACHED("unexpected topic");
}

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

@ -50,7 +50,6 @@
#include "nsITXTToHTMLConv.h"
#include "nsIPrompt.h"
#include "nsEventQueueUtils.h"
#include "nsStreamUtils.h"
#include "nsMimeTypes.h"
#include "nsNetCID.h"
#include "nsCOMPtr.h"
@ -80,6 +79,8 @@ public:
NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void *closure,
PRUint32 count, PRUint32 *result);
NS_IMETHOD CloseWithStatus(nsresult status);
NS_IMETHOD AsyncWait(nsIInputStreamCallback *callback, PRUint32 flags,
PRUint32 count, nsIEventTarget *target);
nsGopherContentStream(nsGopherChannel *channel)
: nsBaseContentStream(PR_TRUE) // non-blocking
@ -93,9 +94,6 @@ public:
void UpdateContentType(char type);
nsresult SendRequest();
protected:
virtual void OnCallbackPending();
private:
nsRefPtr<nsGopherChannel> mChannel;
nsCOMPtr<nsISocketTransport> mSocket;
@ -121,15 +119,14 @@ NS_IMETHODIMP
nsGopherContentStream::ReadSegments(nsWriteSegmentFun writer, void *closure,
PRUint32 count, PRUint32 *result)
{
// Insert a thunk here so that the input stream passed to the writer is
// this input stream instead of mSocketInput.
if (mSocketInput) {
nsWriteSegmentThunk thunk = { this, writer, closure };
return mSocketInput->ReadSegments(NS_WriteSegmentThunk, &thunk, count,
result);
}
// TODO: Insert a thunk here so that the input stream passed to the writer
// is this input stream instead of mSocketInput. This thunk should be
// some generic thunk available from nsStreamUtils.
if (mSocketInput)
return mSocketInput->ReadSegments(writer, closure, count, result);
return nsBaseContentStream::ReadSegments(writer, closure, count, result);
// No data yet
return NS_BASE_STREAM_WOULD_BLOCK;
}
NS_IMETHODIMP
@ -144,6 +141,26 @@ nsGopherContentStream::CloseWithStatus(nsresult status)
return nsBaseContentStream::CloseWithStatus(status);
}
NS_IMETHODIMP
nsGopherContentStream::AsyncWait(nsIInputStreamCallback *callback, PRUint32 flags,
PRUint32 count, nsIEventTarget *target)
{
nsresult rv = nsBaseContentStream::AsyncWait(callback, flags, count, target);
if (NS_FAILED(rv) && IsClosed())
return rv;
// We have a callback, so failure means we should close the stream.
if (!mSocket) {
rv = OpenSocket(target);
} else if (mSocketInput) {
rv = mSocketInput->AsyncWait(this, 0, 0, target);
}
if (NS_FAILED(rv))
CloseWithStatus(rv);
return NS_OK;
}
NS_IMETHODIMP
nsGopherContentStream::OnInputStreamReady(nsIAsyncInputStream *stream)
{
@ -166,22 +183,6 @@ nsGopherContentStream::OnOutputStreamReady(nsIAsyncOutputStream *stream)
return NS_OK;
}
void
nsGopherContentStream::OnCallbackPending()
{
nsresult rv;
// We have a callback, so failure means we should close the stream.
if (!mSocket) {
rv = OpenSocket(CallbackTarget());
} else if (mSocketInput) {
rv = mSocketInput->AsyncWait(this, 0, 0, CallbackTarget());
}
if (NS_FAILED(rv))
CloseWithStatus(rv);
}
nsresult
nsGopherContentStream::OpenSocket(nsIEventTarget *target)
{

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

@ -3646,7 +3646,7 @@ nsHttpChannel::SetUploadStream(nsIInputStream *stream, const nsACString &content
mUploadStreamHasHeaders = PR_FALSE;
mRequestHead.SetMethod(nsHttp::Get); // revert to GET request
}
mUploadStream = stream;
mUploadStream = stream;
return NS_OK;
}

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

@ -97,12 +97,28 @@ NS_IMETHODIMP
nsFTPDirListingConv::AsyncConvertData(const char *aFromType, const char *aToType,
nsIStreamListener *aListener, nsISupports *aCtxt) {
NS_ASSERTION(aListener && aFromType && aToType, "null pointer passed into FTP dir listing converter");
nsresult rv;
// hook up our final listener. this guy gets the various On*() calls we want to throw
// at him.
mFinalListener = aListener;
NS_ADDREF(mFinalListener);
// we need our own channel that represents the content-type of the
// converted data.
NS_ASSERTION(aCtxt, "FTP dir listing needs a context (the uri)");
nsIURI *uri;
rv = aCtxt->QueryInterface(NS_GET_IID(nsIURI), (void**)&uri);
if (NS_FAILED(rv)) return rv;
// XXX this seems really wrong!!
rv = NS_NewInputStreamChannel(&mPartChannel,
uri,
nsnull,
NS_LITERAL_CSTRING(APPLICATION_HTTP_INDEX_FORMAT));
NS_RELEASE(uri);
if (NS_FAILED(rv)) return rv;
PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG,
("nsFTPDirListingConv::AsyncConvertData() converting FROM raw, TO application/http-index-format\n"));
@ -196,7 +212,7 @@ nsFTPDirListingConv::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
rv = NS_NewCStringInputStream(getter_AddRefs(inputData), indexFormat);
NS_ENSURE_SUCCESS(rv, rv);
rv = mFinalListener->OnDataAvailable(request, ctxt, inputData, 0, indexFormat.Length());
rv = mFinalListener->OnDataAvailable(mPartChannel, ctxt, inputData, 0, indexFormat.Length());
return rv;
}
@ -207,7 +223,7 @@ NS_IMETHODIMP
nsFTPDirListingConv::OnStartRequest(nsIRequest* request, nsISupports *ctxt) {
// we don't care about start. move along... but start masqeurading
// as the http-index channel now.
return mFinalListener->OnStartRequest(request, ctxt);
return mFinalListener->OnStartRequest(mPartChannel, ctxt);
}
NS_IMETHODIMP
@ -215,18 +231,33 @@ nsFTPDirListingConv::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
nsresult aStatus) {
// we don't care about stop. move along...
return mFinalListener->OnStopRequest(request, ctxt, aStatus);
nsresult rv;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsILoadGroup> loadgroup;
rv = channel->GetLoadGroup(getter_AddRefs(loadgroup));
if (NS_FAILED(rv)) return rv;
if (loadgroup)
(void)loadgroup->RemoveRequest(mPartChannel, nsnull, aStatus);
return mFinalListener->OnStopRequest(mPartChannel, ctxt, aStatus);
}
// nsFTPDirListingConv methods
nsFTPDirListingConv::nsFTPDirListingConv() {
mFinalListener = nsnull;
mPartChannel = nsnull;
mSentHeading = PR_FALSE;
}
nsFTPDirListingConv::~nsFTPDirListingConv() {
NS_IF_RELEASE(mFinalListener);
NS_IF_RELEASE(mPartChannel);
}
nsresult

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

@ -81,6 +81,8 @@ private:
PRBool mSentHeading; // have we sent 100, 101, 200, and 300 lines yet?
nsIStreamListener *mFinalListener; // this guy gets the converted data via his OnDataAvailable()
nsIChannel *mPartChannel; // the channel for the given part we're processing.
// one channel per part.
};
#endif /* __nsftpdirlistingdconv__h__ */

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

@ -129,7 +129,6 @@ void XXXNeverCalled()
NS_CopySegmentToStream(nsnull, nsnull, nsnull, 0, 0, nsnull);
NS_CopySegmentToBuffer(nsnull, nsnull, nsnull, 0, 0, nsnull);
NS_DiscardSegment(nsnull, nsnull, nsnull, 0, 0, nsnull);
NS_WriteSegmentThunk(nsnull, nsnull, nsnull, 0, 0, 0);
NS_NewByteInputStream(nsnull, nsnull, 0, NS_ASSIGNMENT_COPY);
NS_NewCStringInputStream(nsnull, nsCString());
NS_NewStringInputStream(nsnull, nsString());

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

@ -91,8 +91,7 @@ interface nsIAsyncInputStream : nsIInputStream
* event will be dispatched when the stream becomes readable or closed.
*
* @param aCallback
* This object is notified when the stream becomes ready. This
* parameter may be null to clear an existing callback.
* This object is notified when the stream becomes ready.
* @param aFlags
* This parameter specifies optional flags passed in to configure
* the behavior of this method. Pass zero to specify no flags.

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

@ -91,8 +91,7 @@ interface nsIAsyncOutputStream : nsIOutputStream
* event will be dispatched when the stream becomes writable or closed.
*
* @param aCallback
* This object is notified when the stream becomes ready. This
* parameter may be null to clear an existing callback.
* This object is notified when the stream becomes ready.
* @param aFlags
* This parameter specifies optional flags passed in to configure
* the behavior of this method. Pass zero to specify no flags.

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

@ -813,9 +813,6 @@ nsPipeInputStream::AsyncWait(nsIInputStreamCallback *callback,
mCallback = 0;
mCallbackFlags = 0;
if (!callback)
return NS_OK;
nsCOMPtr<nsIInputStreamCallback> proxy;
if (target) {
nsresult rv = NS_NewInputStreamReadyEvent(getter_AddRefs(proxy),
@ -1187,9 +1184,6 @@ nsPipeOutputStream::AsyncWait(nsIOutputStreamCallback *callback,
mCallback = 0;
mCallbackFlags = 0;
if (!callback)
return NS_OK;
nsCOMPtr<nsIOutputStreamCallback> proxy;
if (target) {
nsresult rv = NS_NewOutputStreamReadyEvent(getter_AddRefs(proxy),

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

@ -721,18 +721,3 @@ NS_DiscardSegment(nsIInputStream *inStr,
*countWritten = count;
return NS_OK;
}
//-----------------------------------------------------------------------------
NS_COM NS_METHOD
NS_WriteSegmentThunk(nsIInputStream *inStr,
void *closure,
const char *buffer,
PRUint32 offset,
PRUint32 count,
PRUint32 *countWritten)
{
nsWriteSegmentThunk *thunk = NS_STATIC_CAST(nsWriteSegmentThunk *, closure);
return thunk->mFun(thunk->mStream, thunk->mClosure, buffer, offset, count,
countWritten);
}

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

@ -39,8 +39,8 @@
#define nsStreamUtils_h__
#include "nsStringFwd.h"
#include "nsIInputStream.h"
class nsIInputStream;
class nsIOutputStream;
class nsIInputStreamCallback;
class nsIOutputStreamCallback;
@ -204,26 +204,4 @@ NS_DiscardSegment(nsIInputStream *aInputStream, void *aClosure,
const char *aFromSegment, PRUint32 aToOffset,
PRUint32 aCount, PRUint32 *aWriteCount);
/**
* This function is intended to be passed to nsIInputStream::ReadSegments to
* adjust the aInputStream parameter passed to a consumer's WriteSegmentFun.
* The aClosure parameter must be a pointer to a nsWriteSegmentThunk object.
* The mStream and mClosure members of that object will be passed to the mFun
* function, with the remainder of the parameters being what are passed to
* NS_WriteSegmentThunk.
*
* This function comes in handy when implementing ReadSegments in terms of an
* inner stream's ReadSegments.
*/
extern NS_COM NS_METHOD
NS_WriteSegmentThunk(nsIInputStream *aInputStream, void *aClosure,
const char *aFromSegment, PRUint32 aToOffset,
PRUint32 aCount, PRUint32 *aWriteCount);
struct nsWriteSegmentThunk {
nsIInputStream *mStream;
nsWriteSegmentFun mFun;
void *mClosure;
};
#endif // !nsStreamUtils_h__