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 GetIsTRRServiceChannel(bool* aTRR) override;
276   NS_IMETHOD SetIsTRRServiceChannel(bool aTRR) override;
277   NS_IMETHOD GetIsResolvedByTRR(bool* aResolvedByTRR) override;
278   NS_IMETHOD GetIsOCSP(bool* value) override;
279   NS_IMETHOD SetIsOCSP(bool value) override;
280   NS_IMETHOD GetTlsFlags(uint32_t* aTlsFlags) override;
281   NS_IMETHOD SetTlsFlags(uint32_t aTlsFlags) override;
282   NS_IMETHOD GetApiRedirectToURI(nsIURI** aApiRedirectToURI) override;
283   [[nodiscard]] virtual nsresult AddSecurityMessage(
284       const nsAString& aMessageTag, const nsAString& aMessageCategory);
285   NS_IMETHOD TakeAllSecurityMessages(
286       nsCOMArray<nsISecurityConsoleMessage>& aMessages) override;
287   NS_IMETHOD GetResponseTimeoutEnabled(bool* aEnable) override;
288   NS_IMETHOD SetResponseTimeoutEnabled(bool aEnable) override;
289   NS_IMETHOD GetInitialRwin(uint32_t* aRwin) override;
290   NS_IMETHOD SetInitialRwin(uint32_t aRwin) override;
291   NS_IMETHOD ForcePending(bool aForcePending) override;
292   NS_IMETHOD GetLastModifiedTime(PRTime* lastModifiedTime) override;
293   NS_IMETHOD GetCorsIncludeCredentials(bool* aInclude) override;
294   NS_IMETHOD SetCorsIncludeCredentials(bool aInclude) override;
295   NS_IMETHOD GetCorsMode(uint32_t* aCorsMode) override;
296   NS_IMETHOD SetCorsMode(uint32_t aCorsMode) override;
297   NS_IMETHOD GetRedirectMode(uint32_t* aRedirectMode) override;
298   NS_IMETHOD SetRedirectMode(uint32_t aRedirectMode) override;
299   NS_IMETHOD GetFetchCacheMode(uint32_t* aFetchCacheMode) override;
300   NS_IMETHOD SetFetchCacheMode(uint32_t aFetchCacheMode) override;
301   NS_IMETHOD GetTopWindowURI(nsIURI** aTopWindowURI) override;
302   NS_IMETHOD SetTopWindowURIIfUnknown(nsIURI* aTopWindowURI) override;
303   NS_IMETHOD GetProxyURI(nsIURI** proxyURI) override;
304   virtual void SetCorsPreflightParameters(
305       const nsTArray<nsCString>& unsafeHeaders,
306       bool aShouldStripRequestBodyHeader) override;
307   virtual void SetAltDataForChild(bool aIsForChild) override;
DisableAltDataCache()308   virtual void DisableAltDataCache() override {
309     StoreDisableAltDataCache(true);
310   };
311 
312   NS_IMETHOD GetConnectionInfoHashKey(
313       nsACString& aConnectionInfoHashKey) override;
314   NS_IMETHOD GetIntegrityMetadata(nsAString& aIntegrityMetadata) override;
315   NS_IMETHOD SetIntegrityMetadata(const nsAString& aIntegrityMetadata) override;
316   NS_IMETHOD GetLastRedirectFlags(uint32_t* aValue) override;
317   NS_IMETHOD SetLastRedirectFlags(uint32_t aValue) override;
318   NS_IMETHOD GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) override;
319   NS_IMETHOD SetNavigationStartTimeStamp(TimeStamp aTimeStamp) override;
320   NS_IMETHOD CancelByURLClassifier(nsresult aErrorCode) override;
321   virtual void SetIPv4Disabled(void) override;
322   virtual void SetIPv6Disabled(void) override;
323   NS_IMETHOD GetCrossOriginOpenerPolicy(
324       nsILoadInfo::CrossOriginOpenerPolicy* aCrossOriginOpenerPolicy) override;
325   NS_IMETHOD ComputeCrossOriginOpenerPolicy(
326       nsILoadInfo::CrossOriginOpenerPolicy aInitiatorPolicy,
327       nsILoadInfo::CrossOriginOpenerPolicy* aOutPolicy) override;
328   NS_IMETHOD HasCrossOriginOpenerPolicyMismatch(bool* aIsMismatch) override;
329   NS_IMETHOD GetResponseEmbedderPolicy(
330       nsILoadInfo::CrossOriginEmbedderPolicy* aOutPolicy) override;
331 
CleanRedirectCacheChainIfNecessary()332   inline void CleanRedirectCacheChainIfNecessary() {
333     mRedirectedCachekeys = nullptr;
334   }
335   NS_IMETHOD HTTPUpgrade(const nsACString& aProtocolName,
336                          nsIHttpUpgradeListener* aListener) override;
337   void DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() override;
338 
339   NS_IMETHOD SetWaitForHTTPSSVCRecord() override;
340 
341   // nsISupportsPriority
342   NS_IMETHOD GetPriority(int32_t* value) override;
343   NS_IMETHOD AdjustPriority(int32_t delta) override;
344 
345   // nsIClassOfService
GetClassFlags(uint32_t * outFlags)346   NS_IMETHOD GetClassFlags(uint32_t* outFlags) override {
347     *outFlags = mClassOfService;
348     return NS_OK;
349   }
350 
351   // nsIResumableChannel
352   NS_IMETHOD GetEntityID(nsACString& aEntityID) override;
353 
354   // nsIConsoleReportCollector
355   void AddConsoleReport(uint32_t aErrorFlags, const nsACString& aCategory,
356                         nsContentUtils::PropertiesFile aPropertiesFile,
357                         const nsACString& aSourceFileURI, uint32_t aLineNumber,
358                         uint32_t aColumnNumber, const nsACString& aMessageName,
359                         const nsTArray<nsString>& aStringParams) override;
360 
361   void FlushReportsToConsole(
362       uint64_t aInnerWindowID,
363       ReportAction aAction = ReportAction::Forget) override;
364 
365   void FlushReportsToConsoleForServiceWorkerScope(
366       const nsACString& aScope,
367       ReportAction aAction = ReportAction::Forget) override;
368 
369   void FlushConsoleReports(
370       dom::Document* aDocument,
371       ReportAction aAction = ReportAction::Forget) override;
372 
373   void FlushConsoleReports(
374       nsILoadGroup* aLoadGroup,
375       ReportAction aAction = ReportAction::Forget) override;
376 
377   void FlushConsoleReports(nsIConsoleReportCollector* aCollector) override;
378 
379   void StealConsoleReports(
380       nsTArray<net::ConsoleReportCollected>& aReports) override;
381 
382   void ClearConsoleReports() override;
383 
384   class nsContentEncodings : public nsStringEnumeratorBase {
385    public:
386     NS_DECL_ISUPPORTS
387     NS_DECL_NSIUTF8STRINGENUMERATOR
388 
389     using nsStringEnumeratorBase::GetNext;
390 
391     nsContentEncodings(nsIHttpChannel* aChannel, const char* aEncodingHeader);
392 
393    private:
394     virtual ~nsContentEncodings() = default;
395 
396     [[nodiscard]] nsresult PrepareForNext(void);
397 
398     // We do not own the buffer.  The channel owns it.
399     const char* mEncodingHeader;
400     const char* mCurStart;  // points to start of current header
401     const char* mCurEnd;    // points to end of current header
402 
403     // Hold a ref to our channel so that it can't go away and take the
404     // header with it.
405     nsCOMPtr<nsIHttpChannel> mChannel;
406 
407     bool mReady;
408   };
409 
GetResponseHead()410   nsHttpResponseHead* GetResponseHead() const { return mResponseHead.get(); }
GetRequestHead()411   nsHttpRequestHead* GetRequestHead() { return &mRequestHead; }
GetResponseTrailers()412   nsHttpHeaderArray* GetResponseTrailers() const {
413     return mResponseTrailers.get();
414   }
415 
GetSelfAddr()416   const NetAddr& GetSelfAddr() { return mSelfAddr; }
GetPeerAddr()417   const NetAddr& GetPeerAddr() { return mPeerAddr; }
418 
419   [[nodiscard]] nsresult OverrideSecurityInfo(nsISupports* aSecurityInfo);
420 
421  public: /* Necko internal use only... */
GetAltDataLength()422   int64_t GetAltDataLength() { return mAltDataLength; }
423   bool IsNavigation();
424 
IsDeliveringAltData()425   bool IsDeliveringAltData() const { return LoadDeliveringAltData(); }
426 
427   static void PropagateReferenceIfNeeded(nsIURI* aURI,
428                                          nsCOMPtr<nsIURI>& aRedirectURI);
429 
430   // Return whether upon a redirect code of httpStatus for method, the
431   // request method should be rewritten to GET.
432   static bool ShouldRewriteRedirectToGET(
433       uint32_t httpStatus, nsHttpRequestHead::ParsedMethodType method);
434 
435   // Like nsIEncodedChannel::DoApplyConversions except context is set to
436   // mListenerContext.
437   [[nodiscard]] nsresult DoApplyContentConversions(
438       nsIStreamListener* aNextListener, nsIStreamListener** aNewNextListener);
439 
440   // Callback on STS thread called by CopyComplete when NS_AsyncCopy()
441   // is finished. This function works as a proxy function to dispatch
442   // |EnsureUploadStreamIsCloneableComplete| to main thread.
443   virtual void OnCopyComplete(nsresult aStatus);
444 
445   void AddClassificationFlags(uint32_t aClassificationFlags,
446                               bool aIsThirdParty);
447 
448   void SetFlashPluginState(nsIHttpChannel::FlashPluginState aState);
449 
ChannelId()450   const uint64_t& ChannelId() const { return mChannelId; }
451 
InternalSetUploadStream(nsIInputStream * uploadStream)452   void InternalSetUploadStream(nsIInputStream* uploadStream) {
453     mUploadStream = uploadStream;
454   }
455 
InternalSetUploadStreamLength(uint64_t aLength)456   void InternalSetUploadStreamLength(uint64_t aLength) {
457     mReqContentLength = aLength;
458   }
459 
SetUploadStreamHasHeaders(bool hasHeaders)460   void SetUploadStreamHasHeaders(bool hasHeaders) {
461     StoreUploadStreamHasHeaders(hasHeaders);
462   }
463 
464   virtual nsresult SetReferrerHeader(const nsACString& aReferrer,
465                                      bool aRespectBeforeConnect = true) {
466     if (aRespectBeforeConnect) {
467       ENSURE_CALLED_BEFORE_CONNECT();
468     }
469     return mRequestHead.SetHeader(nsHttp::Referer, aReferrer);
470   }
471 
ClearReferrerHeader()472   nsresult ClearReferrerHeader() {
473     ENSURE_CALLED_BEFORE_CONNECT();
474     return mRequestHead.ClearHeader(nsHttp::Referer);
475   }
476 
SetTopWindowURI(nsIURI * aTopWindowURI)477   void SetTopWindowURI(nsIURI* aTopWindowURI) { mTopWindowURI = aTopWindowURI; }
478 
479   // Set referrerInfo and compute the referrer header if neccessary.
480   // Pass true for aSetOriginal if this is a new referrer and should
481   // overwrite the 'original' value, false if this is a mutation (like
482   // stripping the path).
483   nsresult SetReferrerInfoInternal(nsIReferrerInfo* aReferrerInfo, bool aClone,
484                                    bool aCompute, bool aRespectBeforeConnect);
485 
486   struct ReplacementChannelConfig {
487     ReplacementChannelConfig() = default;
488     explicit ReplacementChannelConfig(
489         const dom::ReplacementChannelConfigInit& aInit);
490 
491     uint32_t redirectFlags = 0;
492     uint32_t classOfService = 0;
493     Maybe<bool> privateBrowsing = Nothing();
494     Maybe<nsCString> method;
495     nsCOMPtr<nsIReferrerInfo> referrerInfo;
496     Maybe<dom::TimedChannelInfo> timedChannel;
497     nsCOMPtr<nsIInputStream> uploadStream;
498     uint64_t uploadStreamLength = 0;
499     bool uploadStreamHasHeaders = false;
500     Maybe<nsCString> contentType;
501     Maybe<nsCString> contentLength;
502 
503     dom::ReplacementChannelConfigInit Serialize(dom::ContentParent* aParent);
504   };
505 
506   enum class ReplacementReason {
507     Redirect,
508     InternalRedirect,
509     DocumentChannel,
510   };
511 
512   // Create a ReplacementChannelConfig object that can be used to duplicate the
513   // current channel.
514   ReplacementChannelConfig CloneReplacementChannelConfig(
515       bool aPreserveMethod, uint32_t aRedirectFlags, ReplacementReason aReason);
516 
517   static void ConfigureReplacementChannel(nsIChannel*,
518                                           const ReplacementChannelConfig&,
519                                           ReplacementReason);
520 
521   // Called before we create the redirect target channel.
522   already_AddRefed<nsILoadInfo> CloneLoadInfoForRedirect(
523       nsIURI* aNewURI, uint32_t aRedirectFlags);
524 
525   // True if we've already applied content conversion to the data
526   // passed to mListener.
HasAppliedConversion()527   bool HasAppliedConversion() { return LoadHasAppliedConversion(); }
528 
529  protected:
530   nsresult GetTopWindowURI(nsIURI* aURIBeingLoaded, nsIURI** aTopWindowURI);
531 
532   // Handle notifying listener, removing from loadgroup if request failed.
533   void DoNotifyListener();
534   virtual void DoNotifyListenerCleanup() = 0;
535 
536   // drop reference to listener, its callbacks, and the progress sink
537   virtual void ReleaseListeners();
538 
539   // Call AsyncAbort().
540   virtual void DoAsyncAbort(nsresult aStatus) = 0;
541 
542   // This is fired only when a cookie is created due to the presence of
543   // Set-Cookie header in the response header of any network request.
544   // This notification will come only after the "http-on-examine-response"
545   // was fired.
546   void NotifySetCookie(const nsACString& aCookie);
547 
548   mozilla::dom::PerformanceStorage* GetPerformanceStorage();
549   void MaybeReportTimingData();
550   nsIURI* GetReferringPage();
551   nsPIDOMWindowInner* GetInnerDOMWindow();
552 
553   void AddCookiesToRequest();
554   [[nodiscard]] virtual nsresult SetupReplacementChannel(
555       nsIURI*, nsIChannel*, bool preserveMethod, uint32_t redirectFlags);
556 
557   // bundle calling OMR observers and marking flag into one function
CallOnModifyRequestObservers()558   inline void CallOnModifyRequestObservers() {
559     gHttpHandler->OnModifyRequest(this);
560     MOZ_ASSERT(!LoadRequestObserversCalled());
561     StoreRequestObserversCalled(true);
562   }
563 
564   // Helper function to simplify getting notification callbacks.
565   template <class T>
GetCallback(nsCOMPtr<T> & aResult)566   void GetCallback(nsCOMPtr<T>& aResult) {
567     NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
568                                   NS_GET_TEMPLATE_IID(T),
569                                   getter_AddRefs(aResult));
570   }
571 
572   // Redirect tracking
573   // Checks whether or not aURI and mOriginalURI share the same domain.
574   virtual bool SameOriginWithOriginalUri(nsIURI* aURI);
575 
576   // GetPrincipal Returns the channel's URI principal.
577   nsIPrincipal* GetURIPrincipal();
578 
579   [[nodiscard]] bool BypassServiceWorker() const;
580 
581   // Returns true if this channel should intercept the network request and
582   // prepare for a possible synthesized response instead.
583   bool ShouldIntercept(nsIURI* aURI = nullptr);
584 
585   // Callback on main thread when NS_AsyncCopy() is finished populating
586   // the new mUploadStream.
587   void EnsureUploadStreamIsCloneableComplete(nsresult aStatus);
588 
589 #ifdef DEBUG
590   // Check if mPrivateBrowsingId matches between LoadInfo and LoadContext.
591   void AssertPrivateBrowsingId();
592 #endif
593 
594   static void CallTypeSniffers(void* aClosure, const uint8_t* aData,
595                                uint32_t aCount);
596 
597   nsresult CheckRedirectLimit(uint32_t aRedirectFlags) const;
598 
599   bool MaybeWaitForUploadStreamLength(nsIStreamListener* aListener,
600                                       nsISupports* aContext);
601 
602   void MaybeFlushConsoleReports();
603 
604   bool IsBrowsingContextDiscarded() const;
605 
606   nsresult ProcessCrossOriginEmbedderPolicyHeader();
607 
608   nsresult ProcessCrossOriginResourcePolicyHeader();
609 
610   nsresult ComputeCrossOriginOpenerPolicyMismatch();
611 
612   nsresult ValidateMIMEType();
613 
614   bool EnsureOpaqueResponseIsAllowed();
615 
616   Result<bool, nsresult> EnsureOpaqueResponseIsAllowedAfterSniff();
617 
618   friend class PrivateBrowsingChannel<HttpBaseChannel>;
619   friend class InterceptFailedOnStop;
620 
621  protected:
622   // this section is for main-thread-only object
623   // all the references need to be proxy released on main thread.
624   nsCOMPtr<nsIURI> mURI;
625   nsCOMPtr<nsIURI> mOriginalURI;
626   nsCOMPtr<nsIURI> mDocumentURI;
627   nsCOMPtr<nsILoadGroup> mLoadGroup;
628   nsCOMPtr<nsILoadInfo> mLoadInfo;
629   nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
630   nsCOMPtr<nsIProgressEventSink> mProgressSink;
631   nsCOMPtr<nsIReferrerInfo> mReferrerInfo;
632   nsCOMPtr<nsIURI> mAPIRedirectToURI;
633   nsCOMPtr<nsIURI> mProxyURI;
634   nsCOMPtr<nsIPrincipal> mPrincipal;
635   nsCOMPtr<nsIURI> mTopWindowURI;
636   nsCOMPtr<nsIStreamListener> mListener;
637   // An instance of nsHTTPCompressConv
638   nsCOMPtr<nsIStreamListener> mCompressListener;
639   nsCOMPtr<nsIEventTarget> mCurrentThread;
640 
641  private:
642   // WHATWG Fetch Standard 4.4. HTTP-redirect fetch, step 10
643   bool ShouldTaintReplacementChannelOrigin(nsIURI* aNewURI);
644 
645   // Proxy release all members above on main thread.
646   void ReleaseMainThreadOnlyReferences();
647 
648   void ExplicitSetUploadStreamLength(uint64_t aContentLength,
649                                      bool aStreamHasHeaders);
650 
651   void MaybeResumeAsyncOpen();
652 
653  protected:
654   nsCString mSpec;  // ASCII encoded URL spec
655   nsCString mContentTypeHint;
656   nsCString mContentCharsetHint;
657   nsCString mUserSetCookieHeader;
658   // HTTP Upgrade Data
659   nsCString mUpgradeProtocol;
660   // Resumable channel specific data
661   nsCString mEntityID;
662   // The initiator type (for this resource) - how was the resource referenced in
663   // the HTML file.
664   nsString mInitiatorType;
665   // Holds the name of the preferred alt-data type for each contentType.
666   nsTArray<PreferredAlternativeDataTypeParams> mPreferredCachedAltDataTypes;
667   // Holds the name of the alternative data type the channel returned.
668   nsCString mAvailableCachedAltDataType;
669   nsString mIntegrityMetadata;
670 
671   // Classified channel's matched information
672   nsCString mMatchedList;
673   nsCString mMatchedProvider;
674   nsCString mMatchedFullHash;
675 
676   nsTArray<nsCString> mMatchedTrackingLists;
677   nsTArray<nsCString> mMatchedTrackingFullHashes;
678 
679   nsCOMPtr<nsISupports> mOwner;
680 
681   nsHttpRequestHead mRequestHead;
682   // Upload throttling.
683   nsCOMPtr<nsIInputChannelThrottleQueue> mThrottleQueue;
684   nsCOMPtr<nsIInputStream> mUploadStream;
685   nsCOMPtr<nsIRunnable> mUploadCloneableCallback;
686   UniquePtr<nsHttpResponseHead> mResponseHead;
687   UniquePtr<nsHttpHeaderArray> mResponseTrailers;
688   RefPtr<nsHttpConnectionInfo> mConnectionInfo;
689   nsCOMPtr<nsIProxyInfo> mProxyInfo;
690   nsCOMPtr<nsISupports> mSecurityInfo;
691   nsCOMPtr<nsIHttpUpgradeListener> mUpgradeProtocolCallback;
692   UniquePtr<nsString> mContentDispositionFilename;
693   nsCOMPtr<nsIConsoleReportCollector> mReportCollector;
694 
695   RefPtr<nsHttpHandler> mHttpHandler;  // keep gHttpHandler alive
696   UniquePtr<nsTArray<nsCString>> mRedirectedCachekeys;
697   nsCOMPtr<nsIRequestContext> mRequestContext;
698 
699   RefPtr<OpaqueResponseBlockingInfo> mOpaqueResponseBlockingInfo;
700 
701   NetAddr mSelfAddr;
702   NetAddr mPeerAddr;
703 
704   nsTArray<std::pair<nsString, nsString>> mSecurityConsoleMessages;
705   nsTArray<nsCString> mUnsafeHeaders;
706 
707   // A time value equal to the starting time of the fetch that initiates the
708   // redirect.
709   mozilla::TimeStamp mRedirectStartTimeStamp;
710   // A time value equal to the time immediately after receiving the last byte of
711   // the response of the last redirect.
712   mozilla::TimeStamp mRedirectEndTimeStamp;
713 
714   PRTime mChannelCreationTime;
715   TimeStamp mChannelCreationTimestamp;
716   TimeStamp mAsyncOpenTime;
717   TimeStamp mCacheReadStart;
718   TimeStamp mCacheReadEnd;
719   TimeStamp mLaunchServiceWorkerStart;
720   TimeStamp mLaunchServiceWorkerEnd;
721   TimeStamp mDispatchFetchEventStart;
722   TimeStamp mDispatchFetchEventEnd;
723   TimeStamp mHandleFetchEventStart;
724   TimeStamp mHandleFetchEventEnd;
725   // copied from the transaction before we null out mTransaction
726   // so that the timing can still be queried from OnStopRequest
727   TimingStruct mTransactionTimings;
728 
729   // Gets computed during ComputeCrossOriginOpenerPolicyMismatch so we have
730   // the channel's policy even if we don't know policy initiator.
731   nsILoadInfo::CrossOriginOpenerPolicy mComputedCrossOriginOpenerPolicy;
732 
733   uint64_t mStartPos;
734   uint64_t mTransferSize;
735   uint64_t mRequestSize;
736   uint64_t mDecodedBodySize;
737   // True only when the channel supports any of the versions of HTTP3
738   bool mSupportsHTTP3;
739   uint64_t mEncodedBodySize;
740   uint64_t mRequestContextID;
741   // ID of the top-level document's inner window this channel is being
742   // originated from.
743   uint64_t mContentWindowId;
744   uint64_t mTopBrowsingContextId;
745   int64_t mAltDataLength;
746   uint64_t mChannelId;
747   uint64_t mReqContentLength;
748 
749   Atomic<nsresult, ReleaseAcquire> mStatus;
750 
751   // Use Release-Acquire ordering to ensure the OMT ODA is ignored while channel
752   // is canceled on main thread.
753   Atomic<bool, ReleaseAcquire> mCanceled;
754   Atomic<uint32_t, ReleaseAcquire> mFirstPartyClassificationFlags;
755   Atomic<uint32_t, ReleaseAcquire> mThirdPartyClassificationFlags;
756   Atomic<uint32_t, ReleaseAcquire> mFlashPluginState;
757 
758   UniquePtr<ProfileChunkedBuffer> mSource;
759 
760   uint32_t mLoadFlags;
761   uint32_t mCaps;
762   uint32_t mClassOfService;
763 
764   // clang-format off
765   MOZ_ATOMIC_BITFIELDS(mAtomicBitfields1, 32, (
766     (uint32_t, UpgradeToSecure, 1),
767     (uint32_t, ApplyConversion, 1),
768     // Set to true if DoApplyContentConversions has been applied to
769     // our default mListener.
770     (uint32_t, HasAppliedConversion, 1),
771     (uint32_t, IsPending, 1),
772     (uint32_t, WasOpened, 1),
773     // if 1 all "http-on-{opening|modify|etc}-request" observers have been
774     // called.
775     (uint32_t, RequestObserversCalled, 1),
776     (uint32_t, ResponseHeadersModified, 1),
777     (uint32_t, AllowSTS, 1),
778     (uint32_t, ThirdPartyFlags, 3),
779     (uint32_t, UploadStreamHasHeaders, 1),
780     (uint32_t, ChannelIsForDownload, 1),
781     (uint32_t, TracingEnabled, 1),
782     // True if timing collection is enabled
783     (uint32_t, TimingEnabled, 1),
784     (uint32_t, ReportTiming, 1),
785     (uint32_t, AllowSpdy, 1),
786     (uint32_t, AllowHttp3, 1),
787     (uint32_t, AllowAltSvc, 1),
788     // !!! This is also used by the URL classifier to exempt channels from
789     // classification. If this is changed or removed, make sure we also update
790     // NS_ShouldClassifyChannel accordingly !!!
791     (uint32_t, BeConservative, 1),
792     // If the current channel is used to as a TRR connection.
793     (uint32_t, IsTRRServiceChannel, 1),
794     // If the request was performed to a TRR resolved IP address.
795     // Will be false if loading the resource does not create a connection
796     // (for example when it's loaded from the cache).
797     (uint32_t, ResolvedByTRR, 1),
798     (uint32_t, ResponseTimeoutEnabled, 1),
799     // A flag that should be false only if a cross-domain redirect occurred
800     (uint32_t, AllRedirectsSameOrigin, 1),
801 
802     // Is 1 if no redirects have occured or if all redirects
803     // pass the Resource Timing timing-allow-check
804     (uint32_t, AllRedirectsPassTimingAllowCheck, 1),
805 
806     // True if this channel was intercepted and could receive a synthesized
807     // response.
808     (uint32_t, ResponseCouldBeSynthesized, 1),
809 
810     (uint32_t, BlockAuthPrompt, 1),
811 
812     // If true, we behave as if the LOAD_FROM_CACHE flag has been set.
813     // Used to enforce that flag's behavior but not expose it externally.
814     (uint32_t, AllowStaleCacheContent, 1),
815 
816     // If true, we prefer the LOAD_FROM_CACHE flag over LOAD_BYPASS_CACHE or
817     // LOAD_BYPASS_LOCAL_CACHE.
818     (uint32_t, PreferCacheLoadOverBypass, 1)
819   ))
820 
821   // Broken up into two bitfields to avoid alignment requirements of uint64_t.
822   // (Too many bits used for one uint32_t.)
823   MOZ_ATOMIC_BITFIELDS(mAtomicBitfields2, 32, (
824     // True iff this request has been calculated in its request context as
825     // a non tail request.  We must remove it again when this channel is done.
826     (uint32_t, AddedAsNonTailRequest, 1),
827 
828     // True if AsyncOpen() is called when the stream length is still unknown.
829     // AsyncOpen() will be retriggered when InputStreamLengthHelper execs the
830     // callback, passing the stream length value.
831     (uint32_t, AsyncOpenWaitingForStreamLength, 1),
832 
833     // Defaults to true.  This is set to false when it is no longer possible
834     // to upgrade the request to a secure channel.
835     (uint32_t, UpgradableToSecure, 1),
836 
837     // Tainted origin flag of a request, specified by
838     // WHATWG Fetch Standard 2.2.5.
839     (uint32_t, TaintedOriginFlag, 1),
840 
841     // If the channel is being used to check OCSP
842     (uint32_t, IsOCSP, 1)
843   ))
844   // clang-format on
845 
846   // An opaque flags for non-standard behavior of the TLS system.
847   // It is unlikely this will need to be set outside of telemetry studies
848   // relating to the TLS implementation.
849   uint32_t mTlsFlags;
850 
851   // Current suspension depth for this channel object
852   uint32_t mSuspendCount;
853 
854   // Per channel transport window override (0 means no override)
855   uint32_t mInitialRwin;
856 
857   uint32_t mProxyResolveFlags;
858 
859   uint32_t mContentDispositionHint;
860 
861   uint32_t mCorsMode;
862   uint32_t mRedirectMode;
863 
864   // If this channel was created as the result of a redirect, then this value
865   // will reflect the redirect flags passed to the SetupReplacementChannel()
866   // method.
867   uint32_t mLastRedirectFlags;
868 
869   int16_t mPriority;
870   uint8_t mRedirectionLimit;
871 
872   // Performance tracking
873   // Number of redirects that has occurred.
874   int8_t mRedirectCount;
875   // Number of internal redirects that has occurred.
876   int8_t mInternalRedirectCount;
877 
878   enum class SnifferCategoryType {
879     NetContent = 0,
880     OpaqueResponseBlocking,
881     All
882   };
883   SnifferCategoryType mSnifferCategoryType = SnifferCategoryType::NetContent;
884   const bool mCachedOpaqueResponseBlockingPref;
885   bool mBlockOpaqueResponseAfterSniff;
886   bool mCheckIsOpaqueResponseAllowedAfterSniff;
887 
888   // clang-format off
889   MOZ_ATOMIC_BITFIELDS(mAtomicBitfields3, 8, (
890     (bool, AsyncOpenTimeOverriden, 1),
891     (bool, ForcePending, 1),
892 
893     // true if the channel is deliving alt-data.
894     (bool, DeliveringAltData, 1),
895 
896     (bool, CorsIncludeCredentials, 1),
897 
898     // These parameters are used to ensure that we do not call OnStartRequest
899     // and OnStopRequest more than once.
900     (bool, OnStartRequestCalled, 1),
901     (bool, OnStopRequestCalled, 1),
902 
903     // Defaults to false. Is set to true at the begining of OnStartRequest.
904     // Used to ensure methods can't be called before OnStartRequest.
905     (bool, AfterOnStartRequestBegun, 1),
906 
907     (bool, RequireCORSPreflight, 1)
908   ))
909 
910   // Broken up into two bitfields to avoid alignment requirements of uint16_t.
911   // (Too many bits used for one uint8_t.)
912   MOZ_ATOMIC_BITFIELDS(mAtomicBitfields4, 8, (
913     // This flag will be true if the consumer is requesting alt-data AND the
914     // consumer is in the child process.
915     (bool, AltDataForChild, 1),
916     // This flag will be true if the consumer cannot process alt-data.  This
917     // is used in the webextension StreamFilter handler.  If true, we bypass
918     // using alt-data for the request.
919     (bool, DisableAltDataCache, 1),
920 
921     (bool, ForceMainDocumentChannel, 1),
922     // This is set true if the channel is waiting for the
923     // InputStreamLengthHelper::GetAsyncLength callback.
924     (bool, PendingInputStreamLengthOperation, 1),
925 
926     // Set to true if our listener has indicated that it requires
927     // content conversion to be done by us.
928     (bool, ListenerRequiresContentConversion, 1),
929 
930     // True if this is a navigation to a page with a different cross origin
931     // opener policy ( see ComputeCrossOriginOpenerPolicyMismatch )
932     (uint32_t, HasCrossOriginOpenerPolicyMismatch, 1),
933 
934     // True if HTTPS RR is used during the connection establishment of this
935     // channel.
936     (uint32_t, HasHTTPSRR, 1)
937   ))
938   // clang-format on
939 
940   bool EnsureRequestContextID();
941   bool EnsureRequestContext();
942 
943   // Adds/removes this channel as a non-tailed request in its request context
944   // these helpers ensure we add it only once and remove it only when added
945   // via AddedAsNonTailRequest member tracking.
946   void AddAsNonTailRequest();
947   void RemoveAsNonTailRequest();
948 
949   void EnsureTopBrowsingContextId();
950 
951   void InitiateORBTelemetry();
952 
953   void ReportORBTelemetry(const nsCString& aKey);
954   void ReportORBTelemetry(int64_t aContentLength);
955 };
956 
NS_DEFINE_STATIC_IID_ACCESSOR(HttpBaseChannel,HTTP_BASE_CHANNEL_IID)957 NS_DEFINE_STATIC_IID_ACCESSOR(HttpBaseChannel, HTTP_BASE_CHANNEL_IID)
958 
959 // Share some code while working around C++'s absurd inability to handle casting
960 // of member functions between base/derived types.
961 // - We want to store member function pointer to call at resume time, but one
962 //   such function--HandleAsyncAbort--we want to share between the
963 //   nsHttpChannel/HttpChannelChild.  Can't define it in base class, because
964 //   then we'd have to cast member function ptr between base/derived class
965 //   types.  Sigh...
966 template <class T>
967 class HttpAsyncAborter {
968  public:
969   explicit HttpAsyncAborter(T* derived)
970       : mThis(derived), mCallOnResume(nullptr) {}
971 
972   // Aborts channel: calls OnStart/Stop with provided status, removes channel
973   // from loadGroup.
974   [[nodiscard]] nsresult AsyncAbort(nsresult status);
975 
976   // Does most the actual work.
977   void HandleAsyncAbort();
978 
979   // AsyncCall calls a member function asynchronously (via an event).
980   // retval isn't refcounted and is set only when event was successfully
981   // posted, the event is returned for the purpose of cancelling when needed
982   [[nodiscard]] virtual nsresult AsyncCall(
983       void (T::*funcPtr)(), nsRunnableMethod<T>** retval = nullptr);
984 
985  private:
986   T* mThis;
987 
988  protected:
989   // Function to be called at resume time
990   std::function<nsresult(T*)> mCallOnResume;
991 };
992 
993 template <class T>
AsyncAbort(nsresult status)994 [[nodiscard]] nsresult HttpAsyncAborter<T>::AsyncAbort(nsresult status) {
995   MOZ_LOG(gHttpLog, LogLevel::Debug,
996           ("HttpAsyncAborter::AsyncAbort [this=%p status=%" PRIx32 "]\n", mThis,
997            static_cast<uint32_t>(status)));
998 
999   mThis->mStatus = status;
1000 
1001   // if this fails?  Callers ignore our return value anyway....
1002   return AsyncCall(&T::HandleAsyncAbort);
1003 }
1004 
1005 // Each subclass needs to define its own version of this (which just calls this
1006 // base version), else we wind up casting base/derived member function ptrs
1007 template <class T>
HandleAsyncAbort()1008 inline void HttpAsyncAborter<T>::HandleAsyncAbort() {
1009   MOZ_ASSERT(!mCallOnResume, "How did that happen?");
1010 
1011   if (mThis->mSuspendCount) {
1012     MOZ_LOG(
1013         gHttpLog, LogLevel::Debug,
1014         ("Waiting until resume to do async notification [this=%p]\n", mThis));
1015     mCallOnResume = [](T* self) {
1016       self->HandleAsyncAbort();
1017       return NS_OK;
1018     };
1019     return;
1020   }
1021 
1022   mThis->DoNotifyListener();
1023 
1024   // finally remove ourselves from the load group.
1025   if (mThis->mLoadGroup) {
1026     mThis->mLoadGroup->RemoveRequest(mThis, nullptr, mThis->mStatus);
1027   }
1028 }
1029 
1030 template <class T>
AsyncCall(void (T::* funcPtr)(),nsRunnableMethod<T> ** retval)1031 nsresult HttpAsyncAborter<T>::AsyncCall(void (T::*funcPtr)(),
1032                                         nsRunnableMethod<T>** retval) {
1033   nsresult rv;
1034 
1035   RefPtr<nsRunnableMethod<T>> event =
1036       NewRunnableMethod("net::HttpAsyncAborter::AsyncCall", mThis, funcPtr);
1037   rv = NS_DispatchToCurrentThread(event);
1038   if (NS_SUCCEEDED(rv) && retval) {
1039     *retval = event;
1040   }
1041 
1042   return rv;
1043 }
1044 
1045 class ProxyReleaseRunnable final : public mozilla::Runnable {
1046  public:
ProxyReleaseRunnable(nsTArray<nsCOMPtr<nsISupports>> && aDoomed)1047   explicit ProxyReleaseRunnable(nsTArray<nsCOMPtr<nsISupports>>&& aDoomed)
1048       : Runnable("ProxyReleaseRunnable"), mDoomed(std::move(aDoomed)) {}
1049 
1050   NS_IMETHOD
Run()1051   Run() override {
1052     mDoomed.Clear();
1053     return NS_OK;
1054   }
1055 
1056  private:
1057   virtual ~ProxyReleaseRunnable() = default;
1058 
1059   nsTArray<nsCOMPtr<nsISupports>> mDoomed;
1060 };
1061 
1062 }  // namespace net
1063 }  // namespace mozilla
1064 
1065 #endif  // mozilla_net_HttpBaseChannel_h
1066