Backed out changeset 6c2c039872b3 (bug 1574475) Backed out changeset 8a2a04743c5f (bug 1699222) Backed out changeset 9437c60798d6 (bug 1574475) Backed out changeset 7ef1884ac11b (bug 1574475) Backed out changeset ec8c237d5298 (bug 1574475) Backed out changeset 4a760b3f5d53 (bug 1574475) Backed out changeset b229b0eea1e7 (bug 1574475) Backed out changeset 03d34a2f10a6 (bug 1574475)
214 lines
6.0 KiB
C++
214 lines
6.0 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim:set ts=4 sts=2 sw=2 et cin: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "nsFTPChannel.h"
|
|
#include "nsFtpConnectionThread.h" // defines nsFtpState
|
|
|
|
#include "nsThreadUtils.h"
|
|
#include "mozilla/Attributes.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::net;
|
|
extern LazyLogModule gFTPLog;
|
|
|
|
// There are two transport connections established for an
|
|
// ftp connection. One is used for the command channel , and
|
|
// the other for the data channel. The command channel is the first
|
|
// connection made and is used to negotiate the second, data, channel.
|
|
// The data channel is driven by the command channel and is either
|
|
// initiated by the server (PORT command) or by the client (PASV command).
|
|
// Client initiation is the most common case and is attempted first.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMPL_ISUPPORTS_INHERITED(nsFtpChannel, nsBaseChannel, nsIUploadChannel,
|
|
nsIResumableChannel, nsIFTPChannel,
|
|
nsIProxiedChannel, nsIForcePendingChannel,
|
|
nsISupportsWeakReference)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
nsFtpChannel::SetUploadStream(nsIInputStream* stream,
|
|
const nsACString& contentType,
|
|
int64_t contentLength) {
|
|
NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
|
|
|
|
mUploadStream = stream;
|
|
|
|
// NOTE: contentLength is intentionally ignored here.
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFtpChannel::GetUploadStream(nsIInputStream** aStream) {
|
|
NS_ENSURE_ARG_POINTER(aStream);
|
|
nsCOMPtr<nsIInputStream> stream = mUploadStream;
|
|
stream.forget(aStream);
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
NS_IMETHODIMP
|
|
nsFtpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) {
|
|
NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
|
|
mEntityID = aEntityID;
|
|
mStartPos = aStartPos;
|
|
mResumeRequested = (mStartPos || !mEntityID.IsEmpty());
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFtpChannel::GetEntityID(nsACString& entityID) {
|
|
if (mEntityID.IsEmpty()) return NS_ERROR_NOT_RESUMABLE;
|
|
|
|
entityID = mEntityID;
|
|
return NS_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
NS_IMETHODIMP
|
|
nsFtpChannel::GetProxyInfo(nsIProxyInfo** aProxyInfo) {
|
|
nsCOMPtr<nsIProxyInfo> info = ProxyInfo();
|
|
info.forget(aProxyInfo);
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsFtpChannel::GetHttpProxyConnectResponseCode(
|
|
int32_t* aResponseCode) {
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
nsresult nsFtpChannel::OpenContentStream(bool async, nsIInputStream** result,
|
|
nsIChannel** channel) {
|
|
if (!async) return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
RefPtr<nsFtpState> state = new nsFtpState();
|
|
|
|
nsresult rv = state->Init(this);
|
|
if (NS_FAILED(rv)) {
|
|
return rv;
|
|
}
|
|
|
|
state.forget(result);
|
|
return NS_OK;
|
|
}
|
|
|
|
bool nsFtpChannel::GetStatusArg(nsresult status, nsString& statusArg) {
|
|
nsAutoCString host;
|
|
URI()->GetHost(host);
|
|
CopyUTF8toUTF16(host, statusArg);
|
|
return true;
|
|
}
|
|
|
|
void nsFtpChannel::OnCallbacksChanged() { mFTPEventSink = nullptr; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
namespace {
|
|
|
|
class FTPEventSinkProxy final : public nsIFTPEventSink {
|
|
~FTPEventSinkProxy() = default;
|
|
|
|
public:
|
|
explicit FTPEventSinkProxy(nsIFTPEventSink* aTarget)
|
|
: mTarget(aTarget), mEventTarget(GetCurrentEventTarget()) {}
|
|
|
|
NS_DECL_THREADSAFE_ISUPPORTS
|
|
NS_DECL_NSIFTPEVENTSINK
|
|
|
|
class OnFTPControlLogRunnable : public Runnable {
|
|
public:
|
|
OnFTPControlLogRunnable(nsIFTPEventSink* aTarget, bool aServer,
|
|
const char* aMessage)
|
|
: mozilla::Runnable("FTPEventSinkProxy::OnFTPControlLogRunnable"),
|
|
mTarget(aTarget),
|
|
mServer(aServer),
|
|
mMessage(aMessage) {}
|
|
|
|
NS_DECL_NSIRUNNABLE
|
|
|
|
private:
|
|
nsCOMPtr<nsIFTPEventSink> mTarget;
|
|
bool mServer;
|
|
nsCString mMessage;
|
|
};
|
|
|
|
private:
|
|
nsCOMPtr<nsIFTPEventSink> mTarget;
|
|
nsCOMPtr<nsIEventTarget> mEventTarget;
|
|
};
|
|
|
|
NS_IMPL_ISUPPORTS(FTPEventSinkProxy, nsIFTPEventSink)
|
|
|
|
NS_IMETHODIMP
|
|
FTPEventSinkProxy::OnFTPControlLog(bool aServer, const char* aMsg) {
|
|
RefPtr<OnFTPControlLogRunnable> r =
|
|
new OnFTPControlLogRunnable(mTarget, aServer, aMsg);
|
|
return mEventTarget->Dispatch(r, NS_DISPATCH_NORMAL);
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
FTPEventSinkProxy::OnFTPControlLogRunnable::Run() {
|
|
mTarget->OnFTPControlLog(mServer, mMessage.get());
|
|
return NS_OK;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink>& aResult) {
|
|
if (!mFTPEventSink) {
|
|
nsCOMPtr<nsIFTPEventSink> ftpSink;
|
|
GetCallback(ftpSink);
|
|
if (ftpSink) {
|
|
mFTPEventSink = new FTPEventSinkProxy(ftpSink);
|
|
}
|
|
}
|
|
aResult = mFTPEventSink;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFtpChannel::ForcePending(bool aForcePending) {
|
|
// Set true here so IsPending will return true.
|
|
// Required for callback diversion from child back to parent. In such cases
|
|
// OnStopRequest can be called in the parent before callbacks are diverted
|
|
// back from the child to the listener in the parent.
|
|
mForcePending = aForcePending;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFtpChannel::IsPending(bool* result) {
|
|
*result = Pending();
|
|
return NS_OK;
|
|
}
|
|
|
|
bool nsFtpChannel::Pending() const {
|
|
return nsBaseChannel::Pending() || mForcePending;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFtpChannel::Suspend() {
|
|
LOG(("nsFtpChannel::Suspend [this=%p]\n", this));
|
|
NS_ENSURE_TRUE(Pending(), NS_ERROR_NOT_AVAILABLE);
|
|
|
|
++mSuspendCount;
|
|
return nsBaseChannel::Suspend();
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsFtpChannel::Resume() {
|
|
LOG(("nsFtpChannel::Resume [this=%p]\n", this));
|
|
NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
|
|
--mSuspendCount;
|
|
return nsBaseChannel::Resume();
|
|
}
|