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
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #ifndef mozilla_net_HttpBaseChannel_h
9 #define mozilla_net_HttpBaseChannel_h
10
11 #include <utility>
12
13 #include "mozilla/AtomicBitfields.h"
14 #include "mozilla/Atomics.h"
15 #include "mozilla/dom/DOMTypes.h"
16 #include "mozilla/net/DNS.h"
17 #include "mozilla/net/NeckoCommon.h"
18 #include "mozilla/net/PrivateBrowsingChannel.h"
19 #include "nsCOMPtr.h"
20 #include "nsHashPropertyBag.h"
21 #include "nsHttp.h"
22 #include "nsHttpHandler.h"
23 #include "nsHttpRequestHead.h"
24 #include "nsIClassOfService.h"
25 #include "nsIClassifiedChannel.h"
26 #include "nsIConsoleReportCollector.h"
27 #include "nsIEncodedChannel.h"
28 #include "nsIForcePendingChannel.h"
29 #include "nsIFormPOSTActionChannel.h"
30 #include "nsIHttpChannel.h"
31 #include "nsIHttpChannelInternal.h"
32 #include "nsILoadInfo.h"
33 #include "nsIResumableChannel.h"
34 #include "nsIStringEnumerator.h"
35 #include "nsISupportsPriority.h"
36 #include "nsIThrottledInputChannel.h"
37 #include "nsITimedChannel.h"
38 #include "nsITraceableChannel.h"
39 #include "nsIURI.h"
40 #include "nsIUploadChannel2.h"
41 #include "nsStringEnumerator.h"
42 #include "nsTArray.h"
43 #include "nsThreadUtils.h"
44
45 #define HTTP_BASE_CHANNEL_IID \
46 { \
47 0x9d5cde03, 0xe6e9, 0x4612, { \
48 0xbf, 0xef, 0xbb, 0x66, 0xf3, 0xbb, 0x74, 0x46 \
49 } \
50 }
51
52 class nsIProgressEventSink;
53 class nsISecurityConsoleMessage;
54 class nsIPrincipal;
55
56 namespace mozilla {
57
58 namespace dom {
59 class PerformanceStorage;
60 class ContentParent;
61 } // namespace dom
62
63 class LogCollector;
64
65 namespace net {
66 extern mozilla::LazyLogModule gHttpLog;
67
68 class OpaqueResponseBlockingInfo;
69 class PreferredAlternativeDataTypeParams;
70
71 enum CacheDisposition : uint8_t {
72 kCacheUnresolved = 0,
73 kCacheHit = 1,
74 kCacheHitViaReval = 2,
75 kCacheMissedViaReval = 3,
76 kCacheMissed = 4,
77 kCacheUnknown = 5
78 };
79
80 /*
81 * This class is a partial implementation of nsIHttpChannel. It contains code
82 * shared by nsHttpChannel and HttpChannelChild.
83 * - Note that this class has nothing to do with nsBaseChannel, which is an
84 * earlier effort at a base class for channels that somehow never made it all
85 * the way to the HTTP channel.
86 */
87 class HttpBaseChannel : public nsHashPropertyBag,
88 public nsIEncodedChannel,
89 public nsIHttpChannel,
90 public nsIHttpChannelInternal,
91 public nsIFormPOSTActionChannel,
92 public nsIUploadChannel2,
93 public nsISupportsPriority,
94 public nsIClassOfService,
95 public nsIResumableChannel,
96 public nsITraceableChannel,
97 public PrivateBrowsingChannel<HttpBaseChannel>,
98 public nsITimedChannel,
99 public nsIForcePendingChannel,
100 public nsIConsoleReportCollector,
101 public nsIThrottledInputChannel,
102 public nsIClassifiedChannel {
103 protected:
104 virtual ~HttpBaseChannel();
105
106 public:
107 NS_DECL_ISUPPORTS_INHERITED
108 NS_DECL_NSIUPLOADCHANNEL
109 NS_DECL_NSIFORMPOSTACTIONCHANNEL
110 NS_DECL_NSIUPLOADCHANNEL2
111 NS_DECL_NSITRACEABLECHANNEL
112 NS_DECL_NSITIMEDCHANNEL
113 NS_DECL_NSITHROTTLEDINPUTCHANNEL
114 NS_DECL_NSICLASSIFIEDCHANNEL
115
116 NS_DECLARE_STATIC_IID_ACCESSOR(HTTP_BASE_CHANNEL_IID)
117
118 HttpBaseChannel();
119
120 [[nodiscard]] virtual nsresult Init(nsIURI* aURI, uint32_t aCaps,
121 nsProxyInfo* aProxyInfo,
122 uint32_t aProxyResolveFlags,
123 nsIURI* aProxyURI, uint64_t aChannelId,
124 ExtContentPolicyType aContentPolicyType);
125
126 // nsIRequest
127 NS_IMETHOD GetName(nsACString& aName) override;
128 NS_IMETHOD IsPending(bool* aIsPending) override;
129 NS_IMETHOD GetStatus(nsresult* aStatus) override;
130 NS_IMETHOD GetLoadGroup(nsILoadGroup** aLoadGroup) override;
131 NS_IMETHOD SetLoadGroup(nsILoadGroup* aLoadGroup) override;
132 NS_IMETHOD GetLoadFlags(nsLoadFlags* aLoadFlags) override;
133 NS_IMETHOD SetLoadFlags(nsLoadFlags aLoadFlags) override;
134 NS_IMETHOD GetTRRMode(nsIRequest::TRRMode* aTRRMode) override;
135 NS_IMETHOD SetTRRMode(nsIRequest::TRRMode aTRRMode) override;
136 NS_IMETHOD SetDocshellUserAgentOverride();
137
138 // nsIChannel
139 NS_IMETHOD GetOriginalURI(nsIURI** aOriginalURI) override;
140 NS_IMETHOD SetOriginalURI(nsIURI* aOriginalURI) override;
141 NS_IMETHOD GetURI(nsIURI** aURI) override;
142 NS_IMETHOD GetOwner(nsISupports** aOwner) override;
143 NS_IMETHOD SetOwner(nsISupports* aOwner) override;
144 NS_IMETHOD GetLoadInfo(nsILoadInfo** aLoadInfo) override;
145 NS_IMETHOD SetLoadInfo(nsILoadInfo* aLoadInfo) override;
146 NS_IMETHOD GetIsDocument(bool* aIsDocument) override;
147 NS_IMETHOD GetNotificationCallbacks(
148 nsIInterfaceRequestor** aCallbacks) override;
149 NS_IMETHOD SetNotificationCallbacks(
150 nsIInterfaceRequestor* aCallbacks) override;
151 NS_IMETHOD GetContentType(nsACString& aContentType) override;
152 NS_IMETHOD SetContentType(const nsACString& aContentType) override;
153 NS_IMETHOD GetContentCharset(nsACString& aContentCharset) override;
154 NS_IMETHOD SetContentCharset(const nsACString& aContentCharset) override;
155 NS_IMETHOD GetContentDisposition(uint32_t* aContentDisposition) override;
156 NS_IMETHOD SetContentDisposition(uint32_t aContentDisposition) override;
157 NS_IMETHOD GetContentDispositionFilename(
158 nsAString& aContentDispositionFilename) override;
159 NS_IMETHOD SetContentDispositionFilename(
160 const nsAString& aContentDispositionFilename) override;
161 NS_IMETHOD GetContentDispositionHeader(
162 nsACString& aContentDispositionHeader) override;
163 NS_IMETHOD GetContentLength(int64_t* aContentLength) override;
164 NS_IMETHOD SetContentLength(int64_t aContentLength) override;
165 NS_IMETHOD Open(nsIInputStream** aResult) override;
166 NS_IMETHOD GetBlockAuthPrompt(bool* aValue) override;
167 NS_IMETHOD SetBlockAuthPrompt(bool aValue) override;
168 NS_IMETHOD GetCanceled(bool* aCanceled) override;
169
170 // nsIEncodedChannel
171 NS_IMETHOD GetApplyConversion(bool* value) override;
172 NS_IMETHOD SetApplyConversion(bool value) override;
173 NS_IMETHOD GetContentEncodings(nsIUTF8StringEnumerator** aEncodings) override;
174 NS_IMETHOD DoApplyContentConversions(nsIStreamListener* aNextListener,
175 nsIStreamListener** aNewNextListener,
176 nsISupports* aCtxt) override;
177
178 // HttpBaseChannel::nsIHttpChannel
179 NS_IMETHOD GetRequestMethod(nsACString& aMethod) override;
180 NS_IMETHOD SetRequestMethod(const nsACString& aMethod) override;
181 NS_IMETHOD GetReferrerInfo(nsIReferrerInfo** aReferrerInfo) override;
182 NS_IMETHOD SetReferrerInfo(nsIReferrerInfo* aReferrerInfo) override;
183 NS_IMETHOD SetReferrerInfoWithoutClone(
184 nsIReferrerInfo* aReferrerInfo) override;
185 NS_IMETHOD GetRequestHeader(const nsACString& aHeader,
186 nsACString& aValue) override;
187 NS_IMETHOD SetRequestHeader(const nsACString& aHeader,
188 const nsACString& aValue, bool aMerge) override;
189 NS_IMETHOD SetNewReferrerInfo(const nsACString& aUrl,
190 nsIReferrerInfo::ReferrerPolicyIDL aPolicy,
191 bool aSendReferrer) override;
192 NS_IMETHOD SetEmptyRequestHeader(const nsACString& aHeader) override;
193 NS_IMETHOD VisitRequestHeaders(nsIHttpHeaderVisitor* visitor) override;
194 NS_IMETHOD VisitNonDefaultRequestHeaders(
195 nsIHttpHeaderVisitor* visitor) override;
196 NS_IMETHOD ShouldStripRequestBodyHeader(const nsACString& aMethod,
197 bool* aResult) override;
198 NS_IMETHOD GetResponseHeader(const nsACString& header,
199 nsACString& value) override;
200 NS_IMETHOD SetResponseHeader(const nsACString& header,
201 const nsACString& value, bool merge) override;
202 NS_IMETHOD VisitResponseHeaders(nsIHttpHeaderVisitor* visitor) override;
203 NS_IMETHOD GetOriginalResponseHeader(const nsACString& aHeader,
204 nsIHttpHeaderVisitor* aVisitor) override;
205 NS_IMETHOD VisitOriginalResponseHeaders(
206 nsIHttpHeaderVisitor* aVisitor) override;
207 NS_IMETHOD GetAllowPipelining(bool* value) override; // deprecated
208 NS_IMETHOD SetAllowPipelining(bool value) override; // deprecated
209 NS_IMETHOD GetAllowSTS(bool* value) override;
210 NS_IMETHOD SetAllowSTS(bool value) override;
211 NS_IMETHOD GetRedirectionLimit(uint32_t* value) override;
212 NS_IMETHOD SetRedirectionLimit(uint32_t value) override;
213 NS_IMETHOD IsNoStoreResponse(bool* value) override;
214 NS_IMETHOD IsNoCacheResponse(bool* value) override;
215 NS_IMETHOD IsPrivateResponse(bool* value) override;
216 NS_IMETHOD GetResponseStatus(uint32_t* aValue) override;
217 NS_IMETHOD GetResponseStatusText(nsACString& aValue) override;
218 NS_IMETHOD GetRequestSucceeded(bool* aValue) override;
219 NS_IMETHOD RedirectTo(nsIURI* newURI) override;
220 NS_IMETHOD UpgradeToSecure() override;
221 NS_IMETHOD GetRequestContextID(uint64_t* aRCID) override;
222 NS_IMETHOD GetTransferSize(uint64_t* aTransferSize) override;
223 NS_IMETHOD GetRequestSize(uint64_t* aRequestSize) override;
224 NS_IMETHOD GetDecodedBodySize(uint64_t* aDecodedBodySize) override;
225 NS_IMETHOD GetEncodedBodySize(uint64_t* aEncodedBodySize) override;
226 NS_IMETHOD GetSupportsHTTP3(bool* aSupportsHTTP3) override;
227 NS_IMETHOD GetHasHTTPSRR(bool* aHasHTTPSRR) override;
228 NS_IMETHOD SetRequestContextID(uint64_t aRCID) override;
229 NS_IMETHOD GetIsMainDocumentChannel(bool* aValue) override;
230 NS_IMETHOD SetIsMainDocumentChannel(bool aValue) override;
231 NS_IMETHOD GetProtocolVersion(nsACString& aProtocolVersion) override;
232 NS_IMETHOD GetChannelId(uint64_t* aChannelId) override;
233 NS_IMETHOD SetChannelId(uint64_t aChannelId) override;
234 NS_IMETHOD GetTopLevelContentWindowId(uint64_t* aContentWindowId) override;
235 NS_IMETHOD SetTopLevelContentWindowId(uint64_t aContentWindowId) override;
236 NS_IMETHOD GetTopBrowsingContextId(uint64_t* aId) override;
237 NS_IMETHOD SetTopBrowsingContextId(uint64_t aId) override;
238
239 NS_IMETHOD GetFlashPluginState(
240 nsIHttpChannel::FlashPluginState* aState) override;
241
242 using nsIClassifiedChannel::IsThirdPartyTrackingResource;
243
SetSource(UniquePtr<ProfileChunkedBuffer> aSource)244 virtual void SetSource(UniquePtr<ProfileChunkedBuffer> aSource) override {
245 mSource = std::move(aSource);
246 }
247
248 // nsIHttpChannelInternal
249 NS_IMETHOD GetDocumentURI(nsIURI** aDocumentURI) override;
250 NS_IMETHOD SetDocumentURI(nsIURI* aDocumentURI) override;
251 NS_IMETHOD GetRequestVersion(uint32_t* major, uint32_t* minor) override;
252 NS_IMETHOD GetResponseVersion(uint32_t* major, uint32_t* minor) override;
253 NS_IMETHOD SetCookie(const nsACString& aCookieHeader) override;
254 NS_IMETHOD GetThirdPartyFlags(uint32_t* aForce) override;
255 NS_IMETHOD SetThirdPartyFlags(uint32_t aForce) override;
256 NS_IMETHOD GetForceAllowThirdPartyCookie(bool* aForce) override;
257 NS_IMETHOD SetForceAllowThirdPartyCookie(bool aForce) override;
258 NS_IMETHOD GetChannelIsForDownload(bool* aChannelIsForDownload) override;
259 NS_IMETHOD SetChannelIsForDownload(bool aChannelIsForDownload) override;
260 NS_IMETHOD SetCacheKeysRedirectChain(nsTArray<nsCString>* cacheKeys) override;
261 NS_IMETHOD GetLocalAddress(nsACString& addr) override;
262 NS_IMETHOD GetLocalPort(int32_t* port) override;
263 NS_IMETHOD GetRemoteAddress(nsACString& addr) override;
264 NS_IMETHOD GetRemotePort(int32_t* port) override;
265 NS_IMETHOD GetOnlyConnect(bool* aOnlyConnect) override;
266 NS_IMETHOD SetConnectOnly() override;
267 NS_IMETHOD GetAllowSpdy(bool* aAllowSpdy) override;
268 NS_IMETHOD SetAllowSpdy(bool aAllowSpdy) override;
269 NS_IMETHOD GetAllowHttp3(bool* aAllowHttp3) override;
270 NS_IMETHOD SetAllowHttp3(bool aAllowHttp3) override;
271 NS_IMETHOD GetAllowAltSvc(bool* aAllowAltSvc) override;
272 NS_IMETHOD SetAllowAltSvc(bool aAllowAltSvc) override;
273 NS_IMETHOD GetBeConservative(bool* aBeConservative) override;
274 NS_IMETHOD SetBeConservative(bool aBeConservative) override;
275 NS_IMETHOD GetBypassProxy(bool* aBypassProxy) override;
276 NS_IMETHOD SetBypassProxy(bool aBypassProxy) override;
277 bool BypassProxy();
278
279 NS_IMETHOD GetIsTRRServiceChannel(bool* aTRR) override;
280 NS_IMETHOD SetIsTRRServiceChannel(bool aTRR) override;
281 NS_IMETHOD GetIsResolvedByTRR(bool* aResolvedByTRR) override;
282 NS_IMETHOD GetIsLoadedBySocketProcess(bool* aResult) override;
283 NS_IMETHOD GetIsOCSP(bool* value) override;
284 NS_IMETHOD SetIsOCSP(bool value) override;
285 NS_IMETHOD GetTlsFlags(uint32_t* aTlsFlags) override;
286 NS_IMETHOD SetTlsFlags(uint32_t aTlsFlags) override;
287 NS_IMETHOD GetApiRedirectToURI(nsIURI** aApiRedirectToURI) override;
288 [[nodiscard]] virtual nsresult AddSecurityMessage(
289 const nsAString& aMessageTag, const nsAString& aMessageCategory);
290 NS_IMETHOD TakeAllSecurityMessages(
291 nsCOMArray<nsISecurityConsoleMessage>& aMessages) override;
292 NS_IMETHOD GetResponseTimeoutEnabled(bool* aEnable) override;
293 NS_IMETHOD SetResponseTimeoutEnabled(bool aEnable) override;
294 NS_IMETHOD GetInitialRwin(uint32_t* aRwin) override;
295 NS_IMETHOD SetInitialRwin(uint32_t aRwin) override;
296 NS_IMETHOD ForcePending(bool aForcePending) override;
297 NS_IMETHOD GetLastModifiedTime(PRTime* lastModifiedTime) override;
298 NS_IMETHOD GetCorsIncludeCredentials(bool* aInclude) override;
299 NS_IMETHOD SetCorsIncludeCredentials(bool aInclude) override;
300 NS_IMETHOD GetCorsMode(uint32_t* aCorsMode) override;
301 NS_IMETHOD SetCorsMode(uint32_t aCorsMode) override;
302 NS_IMETHOD GetRedirectMode(uint32_t* aRedirectMode) override;
303 NS_IMETHOD SetRedirectMode(uint32_t aRedirectMode) override;
304 NS_IMETHOD GetFetchCacheMode(uint32_t* aFetchCacheMode) override;
305 NS_IMETHOD SetFetchCacheMode(uint32_t aFetchCacheMode) override;
306 NS_IMETHOD GetTopWindowURI(nsIURI** aTopWindowURI) override;
307 NS_IMETHOD SetTopWindowURIIfUnknown(nsIURI* aTopWindowURI) override;
308 NS_IMETHOD GetProxyURI(nsIURI** proxyURI) override;
309 virtual void SetCorsPreflightParameters(
310 const nsTArray<nsCString>& unsafeHeaders,
311 bool aShouldStripRequestBodyHeader) override;
312 virtual void SetAltDataForChild(bool aIsForChild) override;
DisableAltDataCache()313 virtual void DisableAltDataCache() override {
314 StoreDisableAltDataCache(true);
315 };
316
317 NS_IMETHOD GetConnectionInfoHashKey(
318 nsACString& aConnectionInfoHashKey) override;
319 NS_IMETHOD GetIntegrityMetadata(nsAString& aIntegrityMetadata) override;
320 NS_IMETHOD SetIntegrityMetadata(const nsAString& aIntegrityMetadata) override;
321 NS_IMETHOD GetLastRedirectFlags(uint32_t* aValue) override;
322 NS_IMETHOD SetLastRedirectFlags(uint32_t aValue) override;
323 NS_IMETHOD GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) override;
324 NS_IMETHOD SetNavigationStartTimeStamp(TimeStamp aTimeStamp) override;
325 NS_IMETHOD CancelByURLClassifier(nsresult aErrorCode) override;
326 virtual void SetIPv4Disabled(void) override;
327 virtual void SetIPv6Disabled(void) override;
328 NS_IMETHOD GetCrossOriginOpenerPolicy(
329 nsILoadInfo::CrossOriginOpenerPolicy* aCrossOriginOpenerPolicy) override;
330 NS_IMETHOD ComputeCrossOriginOpenerPolicy(
331 nsILoadInfo::CrossOriginOpenerPolicy aInitiatorPolicy,
332 nsILoadInfo::CrossOriginOpenerPolicy* aOutPolicy) override;
333 NS_IMETHOD HasCrossOriginOpenerPolicyMismatch(bool* aIsMismatch) override;
334 NS_IMETHOD GetResponseEmbedderPolicy(
335 nsILoadInfo::CrossOriginEmbedderPolicy* aOutPolicy) override;
336
CleanRedirectCacheChainIfNecessary()337 inline void CleanRedirectCacheChainIfNecessary() {
338 mRedirectedCachekeys = nullptr;
339 }
340 NS_IMETHOD HTTPUpgrade(const nsACString& aProtocolName,
341 nsIHttpUpgradeListener* aListener) override;
342 void DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() override;
343
344 NS_IMETHOD SetWaitForHTTPSSVCRecord() override;
345
346 virtual void SetConnectionInfo(
347 mozilla::net::nsHttpConnectionInfo* aCI) override;
348
349 // nsISupportsPriority
350 NS_IMETHOD GetPriority(int32_t* value) override;
351 NS_IMETHOD AdjustPriority(int32_t delta) override;
352
353 // nsIClassOfService
GetClassFlags(uint32_t * outFlags)354 NS_IMETHOD GetClassFlags(uint32_t* outFlags) override {
355 *outFlags = mClassOfService;
356 return NS_OK;
357 }
358
359 // nsIResumableChannel
360 NS_IMETHOD GetEntityID(nsACString& aEntityID) override;
361
362 // nsIConsoleReportCollector
363 void AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory,
364 nsContentUtils::PropertiesFile aPropertiesFile,
365 const nsACString& aSourceFileURI, uint32_t aLineNumber,
366 uint32_t aColumnNumber, const nsACString& aMessageName,
367 const nsTArray<nsString>& aStringParams) override;
368
369 void FlushReportsToConsole(
370 uint64_t aInnerWindowID,
371 ReportAction aAction = ReportAction::Forget) override;
372
373 void FlushReportsToConsoleForServiceWorkerScope(
374 const nsACString& aScope,
375 ReportAction aAction = ReportAction::Forget) override;
376
377 void FlushConsoleReports(
378 dom::Document* aDocument,
379 ReportAction aAction = ReportAction::Forget) override;
380
381 void FlushConsoleReports(
382 nsILoadGroup* aLoadGroup,
383 ReportAction aAction = ReportAction::Forget) override;
384
385 void FlushConsoleReports(nsIConsoleReportCollector* aCollector) override;
386
387 void StealConsoleReports(
388 nsTArray<net::ConsoleReportCollected>& aReports) override;
389
390 void ClearConsoleReports() override;
391
392 class nsContentEncodings : public nsStringEnumeratorBase {
393 public:
394 NS_DECL_ISUPPORTS
395 NS_DECL_NSIUTF8STRINGENUMERATOR
396
397 using nsStringEnumeratorBase::GetNext;
398
399 nsContentEncodings(nsIHttpChannel* aChannel, const char* aEncodingHeader);
400
401 private:
402 virtual ~nsContentEncodings() = default;
403
404 [[nodiscard]] nsresult PrepareForNext(void);
405
406 // We do not own the buffer. The channel owns it.
407 const char* mEncodingHeader;
408 const char* mCurStart; // points to start of current header
409 const char* mCurEnd; // points to end of current header
410
411 // Hold a ref to our channel so that it can't go away and take the
412 // header with it.
413 nsCOMPtr<nsIHttpChannel> mChannel;
414
415 bool mReady;
416 };
417
GetResponseHead()418 nsHttpResponseHead* GetResponseHead() const { return mResponseHead.get(); }
GetRequestHead()419 nsHttpRequestHead* GetRequestHead() { return &mRequestHead; }
GetResponseTrailers()420 nsHttpHeaderArray* GetResponseTrailers() const {
421 return mResponseTrailers.get();
422 }
423
424 void SetDummyChannelForImageCache();
425
GetSelfAddr()426 const NetAddr& GetSelfAddr() { return mSelfAddr; }
GetPeerAddr()427 const NetAddr& GetPeerAddr() { return mPeerAddr; }
428
429 [[nodiscard]] nsresult OverrideSecurityInfo(nsISupports* aSecurityInfo);
430
431 public: /* Necko internal use only... */
GetAltDataLength()432 int64_t GetAltDataLength() { return mAltDataLength; }
433 bool IsNavigation();
434
IsDeliveringAltData()435 bool IsDeliveringAltData() const { return LoadDeliveringAltData(); }
436
437 static void PropagateReferenceIfNeeded(nsIURI* aURI,
438 nsCOMPtr<nsIURI>& aRedirectURI);
439
440 // Return whether upon a redirect code of httpStatus for method, the
441 // request method should be rewritten to GET.
442 static bool ShouldRewriteRedirectToGET(
443 uint32_t httpStatus, nsHttpRequestHead::ParsedMethodType method);
444
445 // Like nsIEncodedChannel::DoApplyConversions except context is set to
446 // mListenerContext.
447 [[nodiscard]] nsresult DoApplyContentConversions(
448 nsIStreamListener* aNextListener, nsIStreamListener** aNewNextListener);
449
450 // Callback on STS thread called by CopyComplete when NS_AsyncCopy()
451 // is finished. This function works as a proxy function to dispatch
452 // |EnsureUploadStreamIsCloneableComplete| to main thread.
453 virtual void OnCopyComplete(nsresult aStatus);
454
455 void AddClassificationFlags(uint32_t aClassificationFlags,
456 bool aIsThirdParty);
457
458 void SetFlashPluginState(nsIHttpChannel::FlashPluginState aState);
459
ChannelId()460 const uint64_t& ChannelId() const { return mChannelId; }
461
InternalSetUploadStream(nsIInputStream * uploadStream)462 void InternalSetUploadStream(nsIInputStream* uploadStream) {
463 mUploadStream = uploadStream;
464 }
465
InternalSetUploadStreamLength(uint64_t aLength)466 void InternalSetUploadStreamLength(uint64_t aLength) {
467 mReqContentLength = aLength;
468 }
469
SetUploadStreamHasHeaders(bool hasHeaders)470 void SetUploadStreamHasHeaders(bool hasHeaders) {
471 StoreUploadStreamHasHeaders(hasHeaders);
472 }
473
474 virtual nsresult SetReferrerHeader(const nsACString& aReferrer,
475 bool aRespectBeforeConnect = true) {
476 if (aRespectBeforeConnect) {
477 ENSURE_CALLED_BEFORE_CONNECT();
478 }
479 return mRequestHead.SetHeader(nsHttp::Referer, aReferrer);
480 }
481
ClearReferrerHeader()482 nsresult ClearReferrerHeader() {
483 ENSURE_CALLED_BEFORE_CONNECT();
484 return mRequestHead.ClearHeader(nsHttp::Referer);
485 }
486
SetTopWindowURI(nsIURI * aTopWindowURI)487 void SetTopWindowURI(nsIURI* aTopWindowURI) { mTopWindowURI = aTopWindowURI; }
488
489 // Set referrerInfo and compute the referrer header if neccessary.
490 // Pass true for aSetOriginal if this is a new referrer and should
491 // overwrite the 'original' value, false if this is a mutation (like
492 // stripping the path).
493 nsresult SetReferrerInfoInternal(nsIReferrerInfo* aReferrerInfo, bool aClone,
494 bool aCompute, bool aRespectBeforeConnect);
495
496 struct ReplacementChannelConfig {
497 ReplacementChannelConfig() = default;
498 explicit ReplacementChannelConfig(
499 const dom::ReplacementChannelConfigInit& aInit);
500
501 uint32_t redirectFlags = 0;
502 uint32_t classOfService = 0;
503 Maybe<bool> privateBrowsing = Nothing();
504 Maybe<nsCString> method;
505 nsCOMPtr<nsIReferrerInfo> referrerInfo;
506 Maybe<dom::TimedChannelInfo> timedChannelInfo;
507 nsCOMPtr<nsIInputStream> uploadStream;
508 uint64_t uploadStreamLength = 0;
509 bool uploadStreamHasHeaders = false;
510 Maybe<nsCString> contentType;
511 Maybe<nsCString> contentLength;
512
513 dom::ReplacementChannelConfigInit Serialize(dom::ContentParent* aParent);
514 };
515
516 enum class ReplacementReason {
517 Redirect,
518 InternalRedirect,
519 DocumentChannel,
520 };
521
522 // Create a ReplacementChannelConfig object that can be used to duplicate the
523 // current channel.
524 ReplacementChannelConfig CloneReplacementChannelConfig(
525 bool aPreserveMethod, uint32_t aRedirectFlags, ReplacementReason aReason);
526
527 static void ConfigureReplacementChannel(nsIChannel*,
528 const ReplacementChannelConfig&,
529 ReplacementReason);
530
531 // Called before we create the redirect target channel.
532 already_AddRefed<nsILoadInfo> CloneLoadInfoForRedirect(
533 nsIURI* aNewURI, uint32_t aRedirectFlags);
534
535 // True if we've already applied content conversion to the data
536 // passed to mListener.
HasAppliedConversion()537 bool HasAppliedConversion() { return LoadHasAppliedConversion(); }
538
539 protected:
540 nsresult GetTopWindowURI(nsIURI* aURIBeingLoaded, nsIURI** aTopWindowURI);
541
542 // Handle notifying listener, removing from loadgroup if request failed.
543 void DoNotifyListener();
544 virtual void DoNotifyListenerCleanup() = 0;
545
546 // drop reference to listener, its callbacks, and the progress sink
547 virtual void ReleaseListeners();
548
549 // Call AsyncAbort().
550 virtual void DoAsyncAbort(nsresult aStatus) = 0;
551
552 // This is fired only when a cookie is created due to the presence of
553 // Set-Cookie header in the response header of any network request.
554 // This notification will come only after the "http-on-examine-response"
555 // was fired.
556 void NotifySetCookie(const nsACString& aCookie);
557
558 mozilla::dom::PerformanceStorage* GetPerformanceStorage();
559 void MaybeReportTimingData();
560 nsIURI* GetReferringPage();
561 nsPIDOMWindowInner* GetInnerDOMWindow();
562
563 void AddCookiesToRequest();
564 [[nodiscard]] virtual nsresult SetupReplacementChannel(
565 nsIURI*, nsIChannel*, bool preserveMethod, uint32_t redirectFlags);
566
567 // bundle calling OMR observers and marking flag into one function
CallOnModifyRequestObservers()568 inline void CallOnModifyRequestObservers() {
569 gHttpHandler->OnModifyRequest(this);
570 MOZ_ASSERT(!LoadRequestObserversCalled());
571 StoreRequestObserversCalled(true);
572 }
573
574 // Helper function to simplify getting notification callbacks.
575 template <class T>
GetCallback(nsCOMPtr<T> & aResult)576 void GetCallback(nsCOMPtr<T>& aResult) {
577 NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
578 NS_GET_TEMPLATE_IID(T),
579 getter_AddRefs(aResult));
580 }
581
582 // Redirect tracking
583 // Checks whether or not aURI and mOriginalURI share the same domain.
584 virtual bool SameOriginWithOriginalUri(nsIURI* aURI);
585
586 [[nodiscard]] bool BypassServiceWorker() const;
587
588 // Returns true if this channel should intercept the network request and
589 // prepare for a possible synthesized response instead.
590 bool ShouldIntercept(nsIURI* aURI = nullptr);
591
592 // Callback on main thread when NS_AsyncCopy() is finished populating
593 // the new mUploadStream.
594 void EnsureUploadStreamIsCloneableComplete(nsresult aStatus);
595
596 #ifdef DEBUG
597 // Check if mPrivateBrowsingId matches between LoadInfo and LoadContext.
598 void AssertPrivateBrowsingId();
599 #endif
600
601 static void CallTypeSniffers(void* aClosure, const uint8_t* aData,
602 uint32_t aCount);
603
604 nsresult CheckRedirectLimit(uint32_t aRedirectFlags) const;
605
606 bool MaybeWaitForUploadStreamLength(nsIStreamListener* aListener,
607 nsISupports* aContext);
608
609 void MaybeFlushConsoleReports();
610
611 bool IsBrowsingContextDiscarded() const;
612
613 nsresult ProcessCrossOriginEmbedderPolicyHeader();
614
615 nsresult ProcessCrossOriginResourcePolicyHeader();
616
617 nsresult ComputeCrossOriginOpenerPolicyMismatch();
618
619 nsresult ProcessCrossOriginSecurityHeaders();
620
621 nsresult ValidateMIMEType();
622
623 bool EnsureOpaqueResponseIsAllowed();
624
625 Result<bool, nsresult> EnsureOpaqueResponseIsAllowedAfterSniff();
626
627 bool Http3Allowed() const;
628
629 friend class PrivateBrowsingChannel<HttpBaseChannel>;
630 friend class InterceptFailedOnStop;
631
632 protected:
633 // this section is for main-thread-only object
634 // all the references need to be proxy released on main thread.
635 nsCOMPtr<nsIURI> mURI;
636 nsCOMPtr<nsIURI> mOriginalURI;
637 nsCOMPtr<nsIURI> mDocumentURI;
638 nsCOMPtr<nsILoadGroup> mLoadGroup;
639 nsCOMPtr<nsILoadInfo> mLoadInfo;
640 nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
641 nsCOMPtr<nsIProgressEventSink> mProgressSink;
642 nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
643 nsCOMPtr<nsIURI> mAPIRedirectToURI;
644 nsCOMPtr<nsIURI> mProxyURI;
645 nsCOMPtr<nsIPrincipal> mPrincipal;
646 nsCOMPtr<nsIURI> mTopWindowURI;
647 nsCOMPtr<nsIStreamListener> mListener;
648 // An instance of nsHTTPCompressConv
649 nsCOMPtr<nsIStreamListener> mCompressListener;
650 nsCOMPtr<nsIEventTarget> mCurrentThread;
651
652 private:
653 // WHATWG Fetch Standard 4.4. HTTP-redirect fetch, step 10
654 bool ShouldTaintReplacementChannelOrigin(nsIURI* aNewURI);
655
656 // Proxy release all members above on main thread.
657 void ReleaseMainThreadOnlyReferences();
658
659 void ExplicitSetUploadStreamLength(uint64_t aContentLength,
660 bool aStreamHasHeaders);
661
662 void MaybeResumeAsyncOpen();
663
664 protected:
665 nsCString mSpec; // ASCII encoded URL spec
666 nsCString mContentTypeHint;
667 nsCString mContentCharsetHint;
668 nsCString mUserSetCookieHeader;
669 // HTTP Upgrade Data
670 nsCString mUpgradeProtocol;
671 // Resumable channel specific data
672 nsCString mEntityID;
673 // The initiator type (for this resource) - how was the resource referenced in
674 // the HTML file.
675 nsString mInitiatorType;
676 // Holds the name of the preferred alt-data type for each contentType.
677 nsTArray<PreferredAlternativeDataTypeParams> mPreferredCachedAltDataTypes;
678 // Holds the name of the alternative data type the channel returned.
679 nsCString mAvailableCachedAltDataType;
680 nsString mIntegrityMetadata;
681
682 // Classified channel's matched information
683 nsCString mMatchedList;
684 nsCString mMatchedProvider;
685 nsCString mMatchedFullHash;
686
687 nsTArray<nsCString> mMatchedTrackingLists;
688 nsTArray<nsCString> mMatchedTrackingFullHashes;
689
690 nsCOMPtr<nsISupports> mOwner;
691
692 nsHttpRequestHead mRequestHead;
693 // Upload throttling.
694 nsCOMPtr<nsIInputChannelThrottleQueue> mThrottleQueue;
695 nsCOMPtr<nsIInputStream> mUploadStream;
696 nsCOMPtr<nsIRunnable> mUploadCloneableCallback;
697 UniquePtr<nsHttpResponseHead> mResponseHead;
698 UniquePtr<nsHttpHeaderArray> mResponseTrailers;
699 RefPtr<nsHttpConnectionInfo> mConnectionInfo;
700 nsCOMPtr<nsIProxyInfo> mProxyInfo;
701 nsCOMPtr<nsISupports> mSecurityInfo;
702 nsCOMPtr<nsIHttpUpgradeListener> mUpgradeProtocolCallback;
703 UniquePtr<nsString> mContentDispositionFilename;
704 nsCOMPtr<nsIConsoleReportCollector> mReportCollector;
705
706 RefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive
707 UniquePtr<nsTArray<nsCString>> mRedirectedCachekeys;
708 nsCOMPtr<nsIRequestContext> mRequestContext;
709
710 RefPtr<OpaqueResponseBlockingInfo> mOpaqueResponseBlockingInfo;
711
712 NetAddr mSelfAddr;
713 NetAddr mPeerAddr;
714
715 nsTArray<std::pair<nsString, nsString>> mSecurityConsoleMessages;
716 nsTArray<nsCString> mUnsafeHeaders;
717
718 // A time value equal to the starting time of the fetch that initiates the
719 // redirect.
720 mozilla::TimeStamp mRedirectStartTimeStamp;
721 // A time value equal to the time immediately after receiving the last byte of
722 // the response of the last redirect.
723 mozilla::TimeStamp mRedirectEndTimeStamp;
724
725 PRTime mChannelCreationTime;
726 TimeStamp mChannelCreationTimestamp;
727 TimeStamp mAsyncOpenTime;
728 TimeStamp mCacheReadStart;
729 TimeStamp mCacheReadEnd;
730 TimeStamp mLaunchServiceWorkerStart;
731 TimeStamp mLaunchServiceWorkerEnd;
732 TimeStamp mDispatchFetchEventStart;
733 TimeStamp mDispatchFetchEventEnd;
734 TimeStamp mHandleFetchEventStart;
735 TimeStamp mHandleFetchEventEnd;
736 // copied from the transaction before we null out mTransaction
737 // so that the timing can still be queried from OnStopRequest
738 TimingStruct mTransactionTimings;
739
740 // Gets computed during ComputeCrossOriginOpenerPolicyMismatch so we have
741 // the channel's policy even if we don't know policy initiator.
742 nsILoadInfo::CrossOriginOpenerPolicy mComputedCrossOriginOpenerPolicy;
743
744 uint64_t mStartPos;
745 uint64_t mTransferSize;
746 uint64_t mRequestSize;
747 uint64_t mDecodedBodySize;
748 // True only when the channel supports any of the versions of HTTP3
749 bool mSupportsHTTP3;
750 uint64_t mEncodedBodySize;
751 uint64_t mRequestContextID;
752 // ID of the top-level document's inner window this channel is being
753 // originated from.
754 uint64_t mContentWindowId;
755 uint64_t mTopBrowsingContextId;
756 int64_t mAltDataLength;
757 uint64_t mChannelId;
758 uint64_t mReqContentLength;
759
760 Atomic<nsresult, ReleaseAcquire> mStatus;
761
762 // Use Release-Acquire ordering to ensure the OMT ODA is ignored while channel
763 // is canceled on main thread.
764 Atomic<bool, ReleaseAcquire> mCanceled;
765 Atomic<uint32_t, ReleaseAcquire> mFirstPartyClassificationFlags;
766 Atomic<uint32_t, ReleaseAcquire> mThirdPartyClassificationFlags;
767 Atomic<uint32_t, ReleaseAcquire> mFlashPluginState;
768
769 UniquePtr<ProfileChunkedBuffer> mSource;
770
771 uint32_t mLoadFlags;
772 uint32_t mCaps;
773 uint32_t mClassOfService;
774
775 // clang-format off
776 MOZ_ATOMIC_BITFIELDS(mAtomicBitfields1, 32, (
777 (uint32_t, UpgradeToSecure, 1),
778 (uint32_t, ApplyConversion, 1),
779 // Set to true if DoApplyContentConversions has been applied to
780 // our default mListener.
781 (uint32_t, HasAppliedConversion, 1),
782 (uint32_t, IsPending, 1),
783 (uint32_t, WasOpened, 1),
784 // if 1 all "http-on-{opening|modify|etc}-request" observers have been
785 // called.
786 (uint32_t, RequestObserversCalled, 1),
787 (uint32_t, ResponseHeadersModified, 1),
788 (uint32_t, AllowSTS, 1),
789 (uint32_t, ThirdPartyFlags, 3),
790 (uint32_t, UploadStreamHasHeaders, 1),
791 (uint32_t, ChannelIsForDownload, 1),
792 (uint32_t, TracingEnabled, 1),
793 // True if timing collection is enabled
794 (uint32_t, TimingEnabled, 1),
795 (uint32_t, ReportTiming, 1),
796 (uint32_t, AllowSpdy, 1),
797 (uint32_t, AllowHttp3, 1),
798 (uint32_t, AllowAltSvc, 1),
799 // !!! This is also used by the URL classifier to exempt channels from
800 // classification. If this is changed or removed, make sure we also update
801 // NS_ShouldClassifyChannel accordingly !!!
802 (uint32_t, BeConservative, 1),
803 // If the current channel is used to as a TRR connection.
804 (uint32_t, IsTRRServiceChannel, 1),
805 // If the request was performed to a TRR resolved IP address.
806 // Will be false if loading the resource does not create a connection
807 // (for example when it's loaded from the cache).
808 (uint32_t, ResolvedByTRR, 1),
809 (uint32_t, ResponseTimeoutEnabled, 1),
810 // A flag that should be false only if a cross-domain redirect occurred
811 (uint32_t, AllRedirectsSameOrigin, 1),
812
813 // Is 1 if no redirects have occured or if all redirects
814 // pass the Resource Timing timing-allow-check
815 (uint32_t, AllRedirectsPassTimingAllowCheck, 1),
816
817 // True if this channel was intercepted and could receive a synthesized
818 // response.
819 (uint32_t, ResponseCouldBeSynthesized, 1),
820
821 (uint32_t, BlockAuthPrompt, 1),
822
823 // If true, we behave as if the LOAD_FROM_CACHE flag has been set.
824 // Used to enforce that flag's behavior but not expose it externally.
825 (uint32_t, AllowStaleCacheContent, 1),
826
827 // If true, we behave as if the VALIDATE_ALWAYS flag has been set.
828 // Used to force validate the cached content.
829 (uint32_t, ForceValidateCacheContent, 1),
830
831 // If true, we prefer the LOAD_FROM_CACHE flag over LOAD_BYPASS_CACHE or
832 // LOAD_BYPASS_LOCAL_CACHE.
833 (uint32_t, PreferCacheLoadOverBypass, 1)
834 ))
835
836 // Broken up into two bitfields to avoid alignment requirements of uint64_t.
837 // (Too many bits used for one uint32_t.)
838 MOZ_ATOMIC_BITFIELDS(mAtomicBitfields2, 32, (
839 // True iff this request has been calculated in its request context as
840 // a non tail request. We must remove it again when this channel is done.
841 (uint32_t, AddedAsNonTailRequest, 1),
842
843 // True if AsyncOpen() is called when the stream length is still unknown.
844 // AsyncOpen() will be retriggered when InputStreamLengthHelper execs the
845 // callback, passing the stream length value.
846 (uint32_t, AsyncOpenWaitingForStreamLength, 1),
847
848 // Defaults to true. This is set to false when it is no longer possible
849 // to upgrade the request to a secure channel.
850 (uint32_t, UpgradableToSecure, 1),
851
852 // Tainted origin flag of a request, specified by
853 // WHATWG Fetch Standard 2.2.5.
854 (uint32_t, TaintedOriginFlag, 1),
855
856 // If the channel is being used to check OCSP
857 (uint32_t, IsOCSP, 1),
858
859 // Used by system requests such as remote settings and updates to
860 // retry requests without proxies.
861 (uint32_t, BypassProxy, 1),
862
863 // Indicate whether the response of this channel is coming from
864 // socket process.
865 (uint32_t, LoadedBySocketProcess, 1)
866 ))
867 // clang-format on
868
869 // An opaque flags for non-standard behavior of the TLS system.
870 // It is unlikely this will need to be set outside of telemetry studies
871 // relating to the TLS implementation.
872 uint32_t mTlsFlags;
873
874 // Current suspension depth for this channel object
875 uint32_t mSuspendCount;
876
877 // Per channel transport window override (0 means no override)
878 uint32_t mInitialRwin;
879
880 uint32_t mProxyResolveFlags;
881
882 uint32_t mContentDispositionHint;
883
884 uint32_t mCorsMode;
885 uint32_t mRedirectMode;
886
887 // If this channel was created as the result of a redirect, then this value
888 // will reflect the redirect flags passed to the SetupReplacementChannel()
889 // method.
890 uint32_t mLastRedirectFlags;
891
892 int16_t mPriority;
893 uint8_t mRedirectionLimit;
894
895 // Performance tracking
896 // Number of redirects that has occurred.
897 int8_t mRedirectCount;
898 // Number of internal redirects that has occurred.
899 int8_t mInternalRedirectCount;
900
901 enum class SnifferCategoryType {
902 NetContent = 0,
903 OpaqueResponseBlocking,
904 All
905 };
906 SnifferCategoryType mSnifferCategoryType = SnifferCategoryType::NetContent;
907 const bool mCachedOpaqueResponseBlockingPref;
908 bool mBlockOpaqueResponseAfterSniff;
909 bool mCheckIsOpaqueResponseAllowedAfterSniff;
910 bool mDummyChannelForImageCache;
911
912 // clang-format off
913 MOZ_ATOMIC_BITFIELDS(mAtomicBitfields3, 8, (
914 (bool, AsyncOpenTimeOverriden, 1),
915 (bool, ForcePending, 1),
916
917 // true if the channel is deliving alt-data.
918 (bool, DeliveringAltData, 1),
919
920 (bool, CorsIncludeCredentials, 1),
921
922 // These parameters are used to ensure that we do not call OnStartRequest
923 // and OnStopRequest more than once.
924 (bool, OnStartRequestCalled, 1),
925 (bool, OnStopRequestCalled, 1),
926
927 // Defaults to false. Is set to true at the begining of OnStartRequest.
928 // Used to ensure methods can't be called before OnStartRequest.
929 (bool, AfterOnStartRequestBegun, 1),
930
931 (bool, RequireCORSPreflight, 1)
932 ))
933
934 // Broken up into two bitfields to avoid alignment requirements of uint16_t.
935 // (Too many bits used for one uint8_t.)
936 MOZ_ATOMIC_BITFIELDS(mAtomicBitfields4, 8, (
937 // This flag will be true if the consumer is requesting alt-data AND the
938 // consumer is in the child process.
939 (bool, AltDataForChild, 1),
940 // This flag will be true if the consumer cannot process alt-data. This
941 // is used in the webextension StreamFilter handler. If true, we bypass
942 // using alt-data for the request.
943 (bool, DisableAltDataCache, 1),
944
945 (bool, ForceMainDocumentChannel, 1),
946 // This is set true if the channel is waiting for the
947 // InputStreamLengthHelper::GetAsyncLength callback.
948 (bool, PendingInputStreamLengthOperation, 1),
949
950 // Set to true if our listener has indicated that it requires
951 // content conversion to be done by us.
952 (bool, ListenerRequiresContentConversion, 1),
953
954 // True if this is a navigation to a page with a different cross origin
955 // opener policy ( see ComputeCrossOriginOpenerPolicyMismatch )
956 (uint32_t, HasCrossOriginOpenerPolicyMismatch, 1),
957
958 // True if HTTPS RR is used during the connection establishment of this
959 // channel.
960 (uint32_t, HasHTTPSRR, 1)
961 ))
962 // clang-format on
963
964 bool EnsureRequestContextID();
965 bool EnsureRequestContext();
966
967 // Adds/removes this channel as a non-tailed request in its request context
968 // these helpers ensure we add it only once and remove it only when added
969 // via AddedAsNonTailRequest member tracking.
970 void AddAsNonTailRequest();
971 void RemoveAsNonTailRequest();
972
973 void EnsureTopBrowsingContextId();
974
975 void InitiateORBTelemetry();
976
977 void ReportORBTelemetry(const nsCString& aKey);
978 void ReportORBTelemetry(int64_t aContentLength);
979 };
980
NS_DEFINE_STATIC_IID_ACCESSOR(HttpBaseChannel,HTTP_BASE_CHANNEL_IID)981 NS_DEFINE_STATIC_IID_ACCESSOR(HttpBaseChannel, HTTP_BASE_CHANNEL_IID)
982
983 // Share some code while working around C++'s absurd inability to handle casting
984 // of member functions between base/derived types.
985 // - We want to store member function pointer to call at resume time, but one
986 // such function--HandleAsyncAbort--we want to share between the
987 // nsHttpChannel/HttpChannelChild. Can't define it in base class, because
988 // then we'd have to cast member function ptr between base/derived class
989 // types. Sigh...
990 template <class T>
991 class HttpAsyncAborter {
992 public:
993 explicit HttpAsyncAborter(T* derived)
994 : mThis(derived), mCallOnResume(nullptr) {}
995
996 // Aborts channel: calls OnStart/Stop with provided status, removes channel
997 // from loadGroup.
998 [[nodiscard]] nsresult AsyncAbort(nsresult status);
999
1000 // Does most the actual work.
1001 void HandleAsyncAbort();
1002
1003 // AsyncCall calls a member function asynchronously (via an event).
1004 // retval isn't refcounted and is set only when event was successfully
1005 // posted, the event is returned for the purpose of cancelling when needed
1006 [[nodiscard]] virtual nsresult AsyncCall(
1007 void (T::*funcPtr)(), nsRunnableMethod<T>** retval = nullptr);
1008
1009 private:
1010 T* mThis;
1011
1012 protected:
1013 // Function to be called at resume time
1014 std::function<nsresult(T*)> mCallOnResume;
1015 };
1016
1017 template <class T>
AsyncAbort(nsresult status)1018 [[nodiscard]] nsresult HttpAsyncAborter<T>::AsyncAbort(nsresult status) {
1019 MOZ_LOG(gHttpLog, LogLevel::Debug,
1020 ("HttpAsyncAborter::AsyncAbort [this=%p status=%" PRIx32 "]\n", mThis,
1021 static_cast<uint32_t>(status)));
1022
1023 mThis->mStatus = status;
1024
1025 // if this fails? Callers ignore our return value anyway....
1026 return AsyncCall(&T::HandleAsyncAbort);
1027 }
1028
1029 // Each subclass needs to define its own version of this (which just calls this
1030 // base version), else we wind up casting base/derived member function ptrs
1031 template <class T>
HandleAsyncAbort()1032 inline void HttpAsyncAborter<T>::HandleAsyncAbort() {
1033 MOZ_ASSERT(!mCallOnResume, "How did that happen?");
1034
1035 if (mThis->mSuspendCount) {
1036 MOZ_LOG(
1037 gHttpLog, LogLevel::Debug,
1038 ("Waiting until resume to do async notification [this=%p]\n", mThis));
1039 mCallOnResume = [](T* self) {
1040 self->HandleAsyncAbort();
1041 return NS_OK;
1042 };
1043 return;
1044 }
1045
1046 mThis->DoNotifyListener();
1047
1048 // finally remove ourselves from the load group.
1049 if (mThis->mLoadGroup) {
1050 mThis->mLoadGroup->RemoveRequest(mThis, nullptr, mThis->mStatus);
1051 }
1052 }
1053
1054 template <class T>
AsyncCall(void (T::* funcPtr)(),nsRunnableMethod<T> ** retval)1055 nsresult HttpAsyncAborter<T>::AsyncCall(void (T::*funcPtr)(),
1056 nsRunnableMethod<T>** retval) {
1057 nsresult rv;
1058
1059 RefPtr<nsRunnableMethod<T>> event =
1060 NewRunnableMethod("net::HttpAsyncAborter::AsyncCall", mThis, funcPtr);
1061 rv = NS_DispatchToCurrentThread(event);
1062 if (NS_SUCCEEDED(rv) && retval) {
1063 *retval = event;
1064 }
1065
1066 return rv;
1067 }
1068
1069 class ProxyReleaseRunnable final : public mozilla::Runnable {
1070 public:
ProxyReleaseRunnable(nsTArray<nsCOMPtr<nsISupports>> && aDoomed)1071 explicit ProxyReleaseRunnable(nsTArray<nsCOMPtr<nsISupports>>&& aDoomed)
1072 : Runnable("ProxyReleaseRunnable"), mDoomed(std::move(aDoomed)) {}
1073
1074 NS_IMETHOD
Run()1075 Run() override {
1076 mDoomed.Clear();
1077 return NS_OK;
1078 }
1079
1080 private:
1081 virtual ~ProxyReleaseRunnable() = default;
1082
1083 nsTArray<nsCOMPtr<nsISupports>> mDoomed;
1084 };
1085
1086 } // namespace net
1087 } // namespace mozilla
1088
1089 #endif // mozilla_net_HttpBaseChannel_h
1090