Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set sw=2 ts=8 et tw=80 : */
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/. */
6 :
7 : // HttpLog.h should generally be included first
8 : #include "HttpLog.h"
9 :
10 : #include "nsHttp.h"
11 : #include "NullHttpTransaction.h"
12 : #include "nsHttpHandler.h"
13 : #include "nsHttpRequestHead.h"
14 : #include "nsIHttpActivityObserver.h"
15 : #include "NullHttpChannel.h"
16 : #include "nsQueryObject.h"
17 : #include "nsNetUtil.h"
18 :
19 : namespace mozilla {
20 : namespace net {
21 :
22 : class CallObserveActivity final : public nsIRunnable
23 : {
24 0 : ~CallObserveActivity()
25 0 : {
26 0 : }
27 : public:
28 : NS_DECL_THREADSAFE_ISUPPORTS
29 0 : CallObserveActivity(nsIHttpActivityObserver *aActivityDistributor,
30 : const nsCString &aHost,
31 : int32_t aPort,
32 : bool aEndToEndSSL,
33 : uint32_t aActivityType,
34 : uint32_t aActivitySubtype,
35 : PRTime aTimestamp,
36 : uint64_t aExtraSizeData,
37 : const nsACString &aExtraStringData)
38 0 : : mActivityDistributor(aActivityDistributor)
39 : , mHost(aHost)
40 : , mPort(aPort)
41 : , mEndToEndSSL(aEndToEndSSL)
42 : , mActivityType(aActivityType)
43 : , mActivitySubtype(aActivitySubtype)
44 : , mTimestamp(aTimestamp)
45 : , mExtraSizeData(aExtraSizeData)
46 0 : , mExtraStringData(aExtraStringData)
47 : {
48 0 : }
49 0 : NS_IMETHOD Run() override
50 : {
51 0 : MOZ_ASSERT(NS_IsMainThread());
52 0 : nsCOMPtr<nsIURI> uri;
53 0 : nsAutoCString port(NS_LITERAL_CSTRING(""));
54 0 : if (mPort != -1 && ((mEndToEndSSL && mPort != 443) ||
55 0 : (!mEndToEndSSL && mPort != 80))) {
56 0 : port.AppendInt(mPort);
57 : }
58 :
59 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri),
60 0 : (mEndToEndSSL ? NS_LITERAL_CSTRING("https://")
61 0 : : NS_LITERAL_CSTRING("http://") ) + mHost + port);
62 0 : if (NS_FAILED(rv)) {
63 0 : return NS_OK;
64 : }
65 :
66 0 : RefPtr<NullHttpChannel> channel = new NullHttpChannel();
67 0 : rv = channel->Init(uri, 0, nullptr, 0, nullptr);
68 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
69 0 : rv = mActivityDistributor->ObserveActivity(
70 0 : nsCOMPtr<nsISupports>(do_QueryObject(channel)),
71 : mActivityType,
72 : mActivitySubtype,
73 : mTimestamp,
74 : mExtraSizeData,
75 0 : mExtraStringData);
76 0 : NS_ENSURE_SUCCESS(rv, rv);
77 :
78 0 : return NS_OK;
79 : }
80 : private:
81 : nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
82 : nsCString mHost;
83 : int32_t mPort;
84 : bool mEndToEndSSL;
85 : uint32_t mActivityType;
86 : uint32_t mActivitySubtype;
87 : PRTime mTimestamp;
88 : uint64_t mExtraSizeData;
89 : nsCString mExtraStringData;
90 : };
91 :
92 0 : NS_IMPL_ISUPPORTS(CallObserveActivity, nsIRunnable)
93 :
94 10 : NS_IMPL_ISUPPORTS(NullHttpTransaction, NullHttpTransaction, nsISupportsWeakReference)
95 :
96 5 : NullHttpTransaction::NullHttpTransaction(nsHttpConnectionInfo *ci,
97 : nsIInterfaceRequestor *callbacks,
98 5 : uint32_t caps)
99 : : mStatus(NS_OK)
100 5 : , mCaps(caps | NS_HTTP_ALLOW_KEEPALIVE)
101 : , mRequestHead(nullptr)
102 : , mCapsToClear(0)
103 : , mIsDone(false)
104 : , mClaimed(false)
105 : , mCallbacks(callbacks)
106 10 : , mConnectionInfo(ci)
107 : {
108 : nsresult rv;
109 10 : mActivityDistributor = do_GetService(NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID,
110 5 : &rv);
111 5 : if (NS_FAILED(rv)) {
112 0 : return;
113 : }
114 :
115 : bool activityDistributorActive;
116 5 : rv = mActivityDistributor->GetIsActive(&activityDistributorActive);
117 5 : if (NS_SUCCEEDED(rv) && activityDistributorActive) {
118 : // There are some observers registered at activity distributor.
119 0 : LOG(("NulHttpTransaction::NullHttpTransaction() "
120 : "mActivityDistributor is active "
121 : "[this=%p, %s]", this, ci->GetOrigin().get()));
122 : } else {
123 : // There is no observer, so don't use it.
124 5 : mActivityDistributor = nullptr;
125 : }
126 : }
127 :
128 15 : NullHttpTransaction::~NullHttpTransaction()
129 : {
130 5 : mCallbacks = nullptr;
131 5 : delete mRequestHead;
132 15 : }
133 :
134 : bool
135 0 : NullHttpTransaction::Claim()
136 : {
137 0 : if (mClaimed) {
138 0 : return false;
139 : }
140 0 : mClaimed = true;
141 0 : return true;
142 : }
143 :
144 : void
145 0 : NullHttpTransaction::Unclaim()
146 : {
147 0 : mClaimed = false;
148 0 : }
149 :
150 : void
151 0 : NullHttpTransaction::SetConnection(nsAHttpConnection *conn)
152 : {
153 0 : mConnection = conn;
154 0 : }
155 :
156 : nsAHttpConnection *
157 0 : NullHttpTransaction::Connection()
158 : {
159 0 : return mConnection.get();
160 : }
161 :
162 : void
163 0 : NullHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
164 : {
165 0 : nsCOMPtr<nsIInterfaceRequestor> copyCB(mCallbacks);
166 0 : *outCB = copyCB.forget().take();
167 0 : }
168 :
169 : void
170 0 : NullHttpTransaction::OnTransportStatus(nsITransport* transport,
171 : nsresult status, int64_t progress)
172 : {
173 0 : if (mActivityDistributor) {
174 0 : NS_DispatchToMainThread(new CallObserveActivity(mActivityDistributor,
175 0 : mConnectionInfo->GetOrigin(),
176 0 : mConnectionInfo->OriginPort(),
177 0 : mConnectionInfo->EndToEndSSL(),
178 : NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT,
179 : static_cast<uint32_t>(status),
180 0 : PR_Now(),
181 : progress,
182 0 : EmptyCString()));
183 : }
184 0 : }
185 :
186 : bool
187 0 : NullHttpTransaction::IsDone()
188 : {
189 0 : return mIsDone;
190 : }
191 :
192 : nsresult
193 0 : NullHttpTransaction::Status()
194 : {
195 0 : return mStatus;
196 : }
197 :
198 : uint32_t
199 5 : NullHttpTransaction::Caps()
200 : {
201 5 : return mCaps & ~mCapsToClear;
202 : }
203 :
204 : void
205 0 : NullHttpTransaction::SetDNSWasRefreshed()
206 : {
207 0 : MOZ_ASSERT(NS_IsMainThread(), "SetDNSWasRefreshed on main thread only!");
208 0 : mCapsToClear |= NS_HTTP_REFRESH_DNS;
209 0 : }
210 :
211 : nsresult
212 0 : NullHttpTransaction::ReadSegments(nsAHttpSegmentReader *reader,
213 : uint32_t count, uint32_t *countRead)
214 : {
215 0 : *countRead = 0;
216 0 : mIsDone = true;
217 0 : return NS_BASE_STREAM_CLOSED;
218 : }
219 :
220 : nsresult
221 0 : NullHttpTransaction::WriteSegments(nsAHttpSegmentWriter *writer,
222 : uint32_t count, uint32_t *countWritten)
223 : {
224 0 : *countWritten = 0;
225 0 : return NS_BASE_STREAM_CLOSED;
226 : }
227 :
228 : uint32_t
229 0 : NullHttpTransaction::Http1xTransactionCount()
230 : {
231 0 : return 0;
232 : }
233 :
234 : nsHttpRequestHead *
235 0 : NullHttpTransaction::RequestHead()
236 : {
237 : // We suport a requesthead at all so that a CONNECT tunnel transaction
238 : // can obtain a Host header from it, but we lazy-popualate that header.
239 :
240 0 : if (!mRequestHead) {
241 0 : mRequestHead = new nsHttpRequestHead();
242 :
243 0 : nsAutoCString hostHeader;
244 0 : nsCString host(mConnectionInfo->GetOrigin());
245 0 : nsresult rv = nsHttpHandler::GenerateHostPort(host,
246 : mConnectionInfo->OriginPort(),
247 0 : hostHeader);
248 0 : if (NS_SUCCEEDED(rv)) {
249 0 : rv = mRequestHead->SetHeader(nsHttp::Host, hostHeader);
250 0 : MOZ_ASSERT(NS_SUCCEEDED(rv));
251 0 : if (mActivityDistributor) {
252 : // Report request headers.
253 0 : nsCString reqHeaderBuf;
254 0 : mRequestHead->Flatten(reqHeaderBuf, false);
255 0 : NS_DispatchToMainThread(new CallObserveActivity(mActivityDistributor,
256 0 : mConnectionInfo->GetOrigin(),
257 0 : mConnectionInfo->OriginPort(),
258 0 : mConnectionInfo->EndToEndSSL(),
259 : NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
260 : NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER,
261 0 : PR_Now(), 0, reqHeaderBuf));
262 : }
263 : }
264 :
265 : // CONNECT tunnels may also want Proxy-Authorization but that is a lot
266 : // harder to determine, so for now we will let those connections fail in
267 : // the NullHttpTransaction and let them be retried from the pending queue
268 : // with a bound transaction
269 : }
270 :
271 0 : return mRequestHead;
272 : }
273 :
274 : nsresult
275 0 : NullHttpTransaction::TakeSubTransactions(
276 : nsTArray<RefPtr<nsAHttpTransaction> > &outTransactions)
277 : {
278 0 : return NS_ERROR_NOT_IMPLEMENTED;
279 : }
280 :
281 : void
282 0 : NullHttpTransaction::SetProxyConnectFailed()
283 : {
284 0 : }
285 :
286 : void
287 0 : NullHttpTransaction::Close(nsresult reason)
288 : {
289 0 : mStatus = reason;
290 0 : mConnection = nullptr;
291 0 : mIsDone = true;
292 0 : if (mActivityDistributor) {
293 : // Report that this transaction is closing.
294 0 : NS_DispatchToMainThread(new CallObserveActivity(mActivityDistributor,
295 0 : mConnectionInfo->GetOrigin(),
296 0 : mConnectionInfo->OriginPort(),
297 0 : mConnectionInfo->EndToEndSSL(),
298 : NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
299 : NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE,
300 0 : PR_Now(), 0, EmptyCString()));
301 : }
302 0 : }
303 :
304 : nsHttpConnectionInfo *
305 5 : NullHttpTransaction::ConnectionInfo()
306 : {
307 5 : return mConnectionInfo;
308 : }
309 :
310 : } // namespace net
311 : } // namespace mozilla
312 :
|