Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:set ts=4 sts=4 sw=4 et cin: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsFTPChannel.h"
8 #include "nsFtpConnectionThread.h" // defines nsFtpState
10 #include "nsThreadUtils.h"
11 #include "mozilla/Attributes.h"
13 #if defined(PR_LOGGING)
14 extern PRLogModuleInfo* gFTPLog;
15 #endif /* PR_LOGGING */
17 // There are two transport connections established for an
18 // ftp connection. One is used for the command channel , and
19 // the other for the data channel. The command channel is the first
20 // connection made and is used to negotiate the second, data, channel.
21 // The data channel is driven by the command channel and is either
22 // initiated by the server (PORT command) or by the client (PASV command).
23 // Client initiation is the most common case and is attempted first.
25 //-----------------------------------------------------------------------------
27 NS_IMPL_ISUPPORTS_INHERITED(nsFtpChannel,
28 nsBaseChannel,
29 nsIUploadChannel,
30 nsIResumableChannel,
31 nsIFTPChannel,
32 nsIProxiedChannel)
34 //-----------------------------------------------------------------------------
36 NS_IMETHODIMP
37 nsFtpChannel::SetUploadStream(nsIInputStream *stream,
38 const nsACString &contentType,
39 int64_t contentLength)
40 {
41 NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
43 mUploadStream = stream;
45 // NOTE: contentLength is intentionally ignored here.
47 return NS_OK;
48 }
50 NS_IMETHODIMP
51 nsFtpChannel::GetUploadStream(nsIInputStream **stream)
52 {
53 NS_ENSURE_ARG_POINTER(stream);
54 *stream = mUploadStream;
55 NS_IF_ADDREF(*stream);
56 return NS_OK;
57 }
59 //-----------------------------------------------------------------------------
61 NS_IMETHODIMP
62 nsFtpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID)
63 {
64 NS_ENSURE_TRUE(!Pending(), NS_ERROR_IN_PROGRESS);
65 mEntityID = aEntityID;
66 mStartPos = aStartPos;
67 mResumeRequested = (mStartPos || !mEntityID.IsEmpty());
68 return NS_OK;
69 }
71 NS_IMETHODIMP
72 nsFtpChannel::GetEntityID(nsACString& entityID)
73 {
74 if (mEntityID.IsEmpty())
75 return NS_ERROR_NOT_RESUMABLE;
77 entityID = mEntityID;
78 return NS_OK;
79 }
81 //-----------------------------------------------------------------------------
82 NS_IMETHODIMP
83 nsFtpChannel::GetProxyInfo(nsIProxyInfo** aProxyInfo)
84 {
85 *aProxyInfo = ProxyInfo();
86 NS_IF_ADDREF(*aProxyInfo);
87 return NS_OK;
88 }
90 //-----------------------------------------------------------------------------
92 nsresult
93 nsFtpChannel::OpenContentStream(bool async, nsIInputStream **result,
94 nsIChannel** channel)
95 {
96 if (!async)
97 return NS_ERROR_NOT_IMPLEMENTED;
99 nsFtpState *state = new nsFtpState();
100 if (!state)
101 return NS_ERROR_OUT_OF_MEMORY;
102 NS_ADDREF(state);
104 nsresult rv = state->Init(this);
105 if (NS_FAILED(rv)) {
106 NS_RELEASE(state);
107 return rv;
108 }
110 *result = state;
111 return NS_OK;
112 }
114 bool
115 nsFtpChannel::GetStatusArg(nsresult status, nsString &statusArg)
116 {
117 nsAutoCString host;
118 URI()->GetHost(host);
119 CopyUTF8toUTF16(host, statusArg);
120 return true;
121 }
123 void
124 nsFtpChannel::OnCallbacksChanged()
125 {
126 mFTPEventSink = nullptr;
127 }
129 //-----------------------------------------------------------------------------
131 namespace {
133 class FTPEventSinkProxy MOZ_FINAL : public nsIFTPEventSink
134 {
135 public:
136 FTPEventSinkProxy(nsIFTPEventSink* aTarget)
137 : mTarget(aTarget)
138 , mTargetThread(do_GetCurrentThread())
139 { }
141 NS_DECL_THREADSAFE_ISUPPORTS
142 NS_DECL_NSIFTPEVENTSINK
144 class OnFTPControlLogRunnable : public nsRunnable
145 {
146 public:
147 OnFTPControlLogRunnable(nsIFTPEventSink* aTarget,
148 bool aServer,
149 const char* aMessage)
150 : mTarget(aTarget)
151 , mServer(aServer)
152 , mMessage(aMessage)
153 { }
155 NS_DECL_NSIRUNNABLE
157 private:
158 nsCOMPtr<nsIFTPEventSink> mTarget;
159 bool mServer;
160 nsCString mMessage;
161 };
163 private:
164 nsCOMPtr<nsIFTPEventSink> mTarget;
165 nsCOMPtr<nsIThread> mTargetThread;
166 };
168 NS_IMPL_ISUPPORTS(FTPEventSinkProxy, nsIFTPEventSink)
170 NS_IMETHODIMP
171 FTPEventSinkProxy::OnFTPControlLog(bool aServer, const char* aMsg)
172 {
173 nsRefPtr<OnFTPControlLogRunnable> r =
174 new OnFTPControlLogRunnable(mTarget, aServer, aMsg);
175 return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL);
176 }
178 NS_IMETHODIMP
179 FTPEventSinkProxy::OnFTPControlLogRunnable::Run()
180 {
181 mTarget->OnFTPControlLog(mServer, mMessage.get());
182 return NS_OK;
183 }
185 } // anonymous namespace
187 void
188 nsFtpChannel::GetFTPEventSink(nsCOMPtr<nsIFTPEventSink> &aResult)
189 {
190 if (!mFTPEventSink) {
191 nsCOMPtr<nsIFTPEventSink> ftpSink;
192 GetCallback(ftpSink);
193 if (ftpSink) {
194 mFTPEventSink = new FTPEventSinkProxy(ftpSink);
195 }
196 }
197 aResult = mFTPEventSink;
198 }
200 void
201 nsFtpChannel::ForcePending(bool aForcePending)
202 {
203 // Set true here so IsPending will return true.
204 // Required for callback diversion from child back to parent. In such cases
205 // OnStopRequest can be called in the parent before callbacks are diverted
206 // back from the child to the listener in the parent.
207 mForcePending = aForcePending;
208 }
210 NS_IMETHODIMP
211 nsFtpChannel::IsPending(bool *result)
212 {
213 *result = Pending();
214 return NS_OK;
215 }
217 bool
218 nsFtpChannel::Pending() const
219 {
220 return nsBaseChannel::Pending() || mForcePending;
221 }