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