In modern C++, static constexpr member variables are automatically inline (aka weak) so the template trick is not needed. This also avoid duplication and reduces the amount of parsed code. No impact on generated binary (actually: smaller debuginfo, close to identical binary). Differential Revision: https://phabricator.services.mozilla.com/D247825
480 lines
20 KiB
C++
480 lines
20 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set sw=2 ts=8 et tw=80 : */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef mozilla_net_HttpChannelChild_h
|
|
#define mozilla_net_HttpChannelChild_h
|
|
|
|
#include "mozilla/Mutex.h"
|
|
#include "mozilla/StaticPrefsBase.h"
|
|
#include "mozilla/UniquePtr.h"
|
|
#include "mozilla/extensions/StreamFilterParent.h"
|
|
#include "mozilla/net/HttpBaseChannel.h"
|
|
#include "mozilla/net/NeckoTargetHolder.h"
|
|
#include "mozilla/net/PHttpChannelChild.h"
|
|
#include "mozilla/net/ChannelEventQueue.h"
|
|
|
|
#include "nsIStreamListener.h"
|
|
#include "nsIInterfaceRequestor.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "nsIProgressEventSink.h"
|
|
#include "nsICacheEntry.h"
|
|
#include "nsICacheInfoChannel.h"
|
|
#include "nsIResumableChannel.h"
|
|
#include "nsIProxiedChannel.h"
|
|
#include "nsIAsyncVerifyRedirectCallback.h"
|
|
#include "nsIChildChannel.h"
|
|
#include "nsIHttpChannelChild.h"
|
|
#include "nsIMultiPartChannel.h"
|
|
#include "nsIThreadRetargetableRequest.h"
|
|
#include "mozilla/net/DNS.h"
|
|
|
|
class nsIEventTarget;
|
|
class nsIInterceptedBodyCallback;
|
|
class nsISerialEventTarget;
|
|
class nsITransportSecurityInfo;
|
|
class nsInputStreamPump;
|
|
|
|
#define HTTP_CHANNEL_CHILD_IID \
|
|
{0x321bd99e, 0x2242, 0x4dc6, {0xbb, 0xec, 0xd5, 0x06, 0x29, 0x7c, 0x39, 0x83}}
|
|
|
|
namespace mozilla::net {
|
|
|
|
class HttpBackgroundChannelChild;
|
|
|
|
class HttpChannelChild final : public PHttpChannelChild,
|
|
public HttpBaseChannel,
|
|
public HttpAsyncAborter<HttpChannelChild>,
|
|
public nsICacheInfoChannel,
|
|
public nsIProxiedChannel,
|
|
public nsIAsyncVerifyRedirectCallback,
|
|
public nsIChildChannel,
|
|
public nsIHttpChannelChild,
|
|
public nsIMultiPartChannel,
|
|
public nsIThreadRetargetableRequest,
|
|
public NeckoTargetHolder {
|
|
virtual ~HttpChannelChild();
|
|
|
|
public:
|
|
NS_DECL_ISUPPORTS_INHERITED
|
|
NS_DECL_NSICACHEINFOCHANNEL
|
|
NS_DECL_NSIPROXIEDCHANNEL
|
|
NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK
|
|
NS_DECL_NSICHILDCHANNEL
|
|
NS_DECL_NSIHTTPCHANNELCHILD
|
|
NS_DECL_NSIMULTIPARTCHANNEL
|
|
NS_DECL_NSITHREADRETARGETABLEREQUEST
|
|
NS_INLINE_DECL_STATIC_IID(HTTP_CHANNEL_CHILD_IID)
|
|
|
|
HttpChannelChild();
|
|
|
|
// Methods HttpBaseChannel didn't implement for us or that we override.
|
|
//
|
|
// nsIRequest
|
|
NS_IMETHOD SetCanceledReason(const nsACString& aReason) override;
|
|
NS_IMETHOD GetCanceledReason(nsACString& aReason) override;
|
|
NS_IMETHOD CancelWithReason(nsresult status,
|
|
const nsACString& reason) override;
|
|
NS_IMETHOD Cancel(nsresult status) override;
|
|
NS_IMETHOD Suspend() override;
|
|
NS_IMETHOD Resume() override;
|
|
// nsIChannel
|
|
NS_IMETHOD GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo) override;
|
|
NS_IMETHOD AsyncOpen(nsIStreamListener* aListener) override;
|
|
|
|
// HttpBaseChannel::nsIHttpChannel
|
|
NS_IMETHOD SetRequestHeader(const nsACString& aHeader,
|
|
const nsACString& aValue, bool aMerge) override;
|
|
NS_IMETHOD SetEmptyRequestHeader(const nsACString& aHeader) override;
|
|
NS_IMETHOD RedirectTo(nsIURI* newURI) override;
|
|
NS_IMETHOD TransparentRedirectTo(nsIURI* newURI) override;
|
|
NS_IMETHOD UpgradeToSecure() override;
|
|
NS_IMETHOD GetProtocolVersion(nsACString& aProtocolVersion) override;
|
|
void DoDiagnosticAssertWhenOnStopNotCalledOnDestroy() override;
|
|
// nsIHttpChannelInternal
|
|
NS_IMETHOD GetIsAuthChannel(bool* aIsAuthChannel) override;
|
|
NS_IMETHOD SetEarlyHintObserver(nsIEarlyHintObserver* aObserver) override;
|
|
NS_IMETHOD SetWebTransportSessionEventListener(
|
|
WebTransportSessionEventListener* aListener) override;
|
|
|
|
NS_IMETHOD SetResponseOverride(
|
|
nsIReplacedHttpResponse* aReplacedHttpResponse) override {
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHOD SetResponseStatus(uint32_t aStatus,
|
|
const nsACString& aStatusText) override {
|
|
return NS_OK;
|
|
}
|
|
// nsISupportsPriority
|
|
NS_IMETHOD SetPriority(int32_t value) override;
|
|
// nsIClassOfService
|
|
NS_IMETHOD SetClassFlags(uint32_t inFlags) override;
|
|
NS_IMETHOD AddClassFlags(uint32_t inFlags) override;
|
|
NS_IMETHOD ClearClassFlags(uint32_t inFlags) override;
|
|
NS_IMETHOD SetClassOfService(ClassOfService inCos) override;
|
|
NS_IMETHOD SetIncremental(bool inIncremental) override;
|
|
// nsIResumableChannel
|
|
NS_IMETHOD ResumeAt(uint64_t startPos, const nsACString& entityID) override;
|
|
|
|
nsresult SetReferrerHeader(const nsACString& aReferrer,
|
|
bool aRespectBeforeConnect) override;
|
|
|
|
[[nodiscard]] bool IsSuspended();
|
|
|
|
// Callback while background channel is ready.
|
|
void OnBackgroundChildReady(HttpBackgroundChannelChild* aBgChild);
|
|
// Callback while background channel is destroyed.
|
|
void OnBackgroundChildDestroyed(HttpBackgroundChannelChild* aBgChild);
|
|
|
|
nsresult CrossProcessRedirectFinished(nsresult aStatus);
|
|
|
|
void RegisterStreamFilter(
|
|
RefPtr<extensions::StreamFilterParent>& aStreamFilter);
|
|
|
|
protected:
|
|
mozilla::ipc::IPCResult RecvOnStartRequestSent() override;
|
|
mozilla::ipc::IPCResult RecvFailedAsyncOpen(const nsresult& status) override;
|
|
mozilla::ipc::IPCResult RecvRedirect1Begin(
|
|
const uint32_t& registrarId, nsIURI* newOriginalURI,
|
|
const uint32_t& newLoadFlags, const uint32_t& redirectFlags,
|
|
const ParentLoadInfoForwarderArgs& loadInfoForwarder,
|
|
nsHttpResponseHead&& responseHead, nsITransportSecurityInfo* securityInfo,
|
|
const uint64_t& channelId, const NetAddr& oldPeerAddr,
|
|
const ResourceTimingStructArgs& aTiming) override;
|
|
mozilla::ipc::IPCResult RecvRedirect3Complete() override;
|
|
mozilla::ipc::IPCResult RecvRedirectFailed(const nsresult& status) override;
|
|
mozilla::ipc::IPCResult RecvDeleteSelf() override;
|
|
|
|
mozilla::ipc::IPCResult RecvReportSecurityMessage(
|
|
const nsAString& messageTag, const nsAString& messageCategory) override;
|
|
|
|
mozilla::ipc::IPCResult RecvSetPriority(const int16_t& aPriority) override;
|
|
|
|
mozilla::ipc::IPCResult RecvOriginalCacheInputStreamAvailable(
|
|
const Maybe<IPCStream>& aStream) override;
|
|
|
|
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
|
|
|
virtual void DoNotifyListenerCleanup() override;
|
|
|
|
virtual void DoAsyncAbort(nsresult aStatus) override;
|
|
|
|
nsresult AsyncCall(
|
|
void (HttpChannelChild::*funcPtr)(),
|
|
nsRunnableMethod<HttpChannelChild>** retval = nullptr) override {
|
|
// Normally, this method would just be implemented directly, but clang
|
|
// miscompiles the corresponding non-virtual thunk on linux x86.
|
|
// It however doesn't when going though a non-virtual method.
|
|
// https://bugs.llvm.org/show_bug.cgi?id=38466
|
|
return AsyncCallImpl(funcPtr, retval);
|
|
};
|
|
|
|
// Get event target for processing network events.
|
|
already_AddRefed<nsISerialEventTarget> GetNeckoTarget() override;
|
|
|
|
virtual mozilla::ipc::IPCResult RecvLogBlockedCORSRequest(
|
|
const nsAString& aMessage, const nsACString& aCategory,
|
|
const bool& aIsWarning) override;
|
|
NS_IMETHOD LogBlockedCORSRequest(const nsAString& aMessage,
|
|
const nsACString& aCategory,
|
|
bool aIsWarning = false) override;
|
|
|
|
virtual mozilla::ipc::IPCResult RecvLogMimeTypeMismatch(
|
|
const nsACString& aMessageName, const bool& aWarning,
|
|
const nsAString& aURL, const nsAString& aContentType) override;
|
|
NS_IMETHOD LogMimeTypeMismatch(const nsACString& aMessageName, bool aWarning,
|
|
const nsAString& aURL,
|
|
const nsAString& aContentType) override;
|
|
|
|
virtual void ExplicitSetUploadStreamLength(
|
|
uint64_t aContentLength, bool aSetContentLengthHeader) override;
|
|
|
|
private:
|
|
// We want to handle failure result of AsyncOpen, hence AsyncOpen calls the
|
|
// Internal method
|
|
nsresult AsyncOpenInternal(nsIStreamListener* aListener);
|
|
|
|
nsresult AsyncCallImpl(void (HttpChannelChild::*funcPtr)(),
|
|
nsRunnableMethod<HttpChannelChild>** retval);
|
|
|
|
// Sets the event target for future IPC messages. Messages will either be
|
|
// directed to the TabGroup or DocGroup, depending on the LoadInfo associated
|
|
// with the channel. Should be called when a new channel is being set up,
|
|
// before the constructor message is sent to the parent.
|
|
void SetEventTarget();
|
|
|
|
// Get event target for ODA.
|
|
already_AddRefed<nsIEventTarget> GetODATarget();
|
|
|
|
[[nodiscard]] nsresult ContinueAsyncOpen();
|
|
void ProcessOnStartRequest(const nsHttpResponseHead& aResponseHead,
|
|
const bool& aUseResponseHead,
|
|
const nsHttpHeaderArray& aRequestHeaders,
|
|
const HttpChannelOnStartRequestArgs& aArgs,
|
|
const HttpChannelAltDataStream& aAltData,
|
|
const TimeStamp& aOnStartRequestStartTime);
|
|
|
|
// Callbacks while receiving OnTransportAndData/OnStopRequest/OnProgress/
|
|
// OnStatus/FlushedForDiversion/DivertMessages on background IPC channel.
|
|
void ProcessOnTransportAndData(const nsresult& aChannelStatus,
|
|
const nsresult& aTransportStatus,
|
|
const uint64_t& aOffset,
|
|
const uint32_t& aCount,
|
|
const nsACString& aData,
|
|
const TimeStamp& aOnDataAvailableStartTime);
|
|
void ProcessOnStopRequest(const nsresult& aChannelStatus,
|
|
const ResourceTimingStructArgs& aTiming,
|
|
const nsHttpHeaderArray& aResponseTrailers,
|
|
nsTArray<ConsoleReportCollected>&& aConsoleReports,
|
|
bool aFromSocketProcess,
|
|
const TimeStamp& aOnStopRequestStartTime);
|
|
void ProcessOnConsoleReport(
|
|
nsTArray<ConsoleReportCollected>&& aConsoleReports);
|
|
|
|
void ProcessNotifyClassificationFlags(uint32_t aClassificationFlags,
|
|
bool aIsThirdParty);
|
|
void ProcessSetClassifierMatchedInfo(const nsACString& aList,
|
|
const nsACString& aProvider,
|
|
const nsACString& aFullHash);
|
|
void ProcessSetClassifierMatchedTrackingInfo(const nsACString& aLists,
|
|
const nsACString& aFullHashes);
|
|
void ProcessOnAfterLastPart(const nsresult& aStatus);
|
|
void ProcessOnProgress(const int64_t& aProgress, const int64_t& aProgressMax);
|
|
|
|
void ProcessOnStatus(const nsresult& aStatus);
|
|
|
|
void ProcessAttachStreamFilter(
|
|
Endpoint<extensions::PStreamFilterParent>&& aEndpoint);
|
|
void ProcessDetachStreamFilters();
|
|
|
|
// Return true if we need to tell the parent the size of unreported received
|
|
// data
|
|
bool NeedToReportBytesRead();
|
|
int32_t mUnreportBytesRead = 0;
|
|
|
|
void DoOnConsoleReport(nsTArray<ConsoleReportCollected>&& aConsoleReports);
|
|
void DoOnStartRequest(nsIRequest* aRequest);
|
|
void DoOnStatus(nsIRequest* aRequest, nsresult status);
|
|
void DoOnProgress(nsIRequest* aRequest, int64_t progress,
|
|
int64_t progressMax);
|
|
void DoOnDataAvailable(nsIRequest* aRequest, nsIInputStream* aStream,
|
|
uint64_t offset, uint32_t count);
|
|
void DoPreOnStopRequest(nsresult aStatus);
|
|
void DoOnStopRequest(nsIRequest* aRequest, nsresult aChannelStatus);
|
|
void ContinueOnStopRequest();
|
|
|
|
// Try send DeletingChannel message to parent side. Dispatch an async task to
|
|
// main thread if invoking on non-main thread.
|
|
void TrySendDeletingChannel();
|
|
|
|
// Try invoke Cancel if on main thread, or prepend a CancelEvent in mEventQ to
|
|
// ensure Cacnel is processed before any other channel events.
|
|
void CancelOnMainThread(nsresult aRv, const nsACString& aReason);
|
|
|
|
nsresult MaybeLogCOEPError(nsresult aStatus);
|
|
|
|
void RetargetDeliveryToImpl(nsISerialEventTarget* aNewTarget,
|
|
MutexAutoLock& aLockRef);
|
|
|
|
private:
|
|
// this section is for main-thread-only object
|
|
// all the references need to be proxy released on main thread.
|
|
nsCOMPtr<nsIChildChannel> mRedirectChannelChild;
|
|
|
|
// Proxy release all members above on main thread.
|
|
void ReleaseMainThreadOnlyReferences();
|
|
|
|
private:
|
|
nsCString mProtocolVersion;
|
|
|
|
RequestHeaderTuples mClientSetRequestHeaders;
|
|
RefPtr<ChannelEventQueue> mEventQ;
|
|
|
|
nsCOMPtr<nsIInputStreamReceiver> mOriginalInputStreamReceiver;
|
|
nsCOMPtr<nsIInputStream> mAltDataInputStream;
|
|
|
|
// Used to ensure atomicity of mBgChild and mBgInitFailCallback
|
|
Mutex mBgChildMutex{"HttpChannelChild::BgChildMutex"};
|
|
|
|
// Associated HTTP background channel
|
|
RefPtr<HttpBackgroundChannelChild> mBgChild MOZ_GUARDED_BY(mBgChildMutex);
|
|
|
|
// Error handling procedure if failed to establish PBackground IPC
|
|
nsCOMPtr<nsIRunnable> mBgInitFailCallback MOZ_GUARDED_BY(mBgChildMutex);
|
|
|
|
// Remove the association with background channel after OnStopRequest
|
|
// or AsyncAbort.
|
|
void CleanupBackgroundChannel();
|
|
|
|
// Target thread for delivering ODA.
|
|
nsCOMPtr<nsISerialEventTarget> mODATarget MOZ_GUARDED_BY(mEventTargetMutex);
|
|
Atomic<bool, mozilla::Relaxed> mGotDataAvailable{false};
|
|
// Used to ensure atomicity of mNeckoTarget / mODATarget;
|
|
Mutex mEventTargetMutex{"HttpChannelChild::EventTargetMutex"};
|
|
|
|
TimeStamp mLastStatusReported;
|
|
|
|
uint64_t mCacheEntryId{0};
|
|
|
|
uint32_t mCacheKey{0};
|
|
int32_t mCacheFetchCount{0};
|
|
uint32_t mCacheExpirationTime{
|
|
static_cast<uint32_t>(nsICacheEntry::NO_EXPIRATION_TIME)};
|
|
|
|
// If we're handling a multi-part response, then this is set to the current
|
|
// part ID during OnStartRequest.
|
|
Maybe<uint32_t> mMultiPartID;
|
|
|
|
// To ensure only one SendDeletingChannel is triggered.
|
|
Atomic<bool> mDeletingChannelSent{false};
|
|
|
|
Atomic<bool, SequentiallyConsistent> mIsFromCache{false};
|
|
Atomic<bool, SequentiallyConsistent> mIsRacing{false};
|
|
// Set if we get the result and cache |mNeedToReportBytesRead|
|
|
Atomic<bool, SequentiallyConsistent> mCacheNeedToReportBytesReadInitialized{
|
|
false};
|
|
// True if we need to tell the parent the size of unreported received data
|
|
Atomic<bool, SequentiallyConsistent> mNeedToReportBytesRead{true};
|
|
Atomic<uint32_t, mozilla::Relaxed> mOnProgressEventSent{false};
|
|
// Attached StreamFilterParents
|
|
// Using raw pointer here since StreamFilterParent owns the channel.
|
|
// Should be only accessed on the main thread.
|
|
using StreamFilters = nsTArray<extensions::StreamFilterParent*>;
|
|
StreamFilters mStreamFilters;
|
|
|
|
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
bool mDoDiagnosticAssertWhenOnStopNotCalledOnDestroy = false;
|
|
bool mAsyncOpenSucceeded = false;
|
|
bool mSuccesfullyRedirected = false;
|
|
bool mRemoteChannelExistedAtCancel = false;
|
|
bool mEverHadBgChildAtAsyncOpen = false;
|
|
bool mEverHadBgChildAtConnectParent = false;
|
|
bool mCreateBackgroundChannelFailed = false;
|
|
bool mBgInitFailCallbackTriggered = false;
|
|
bool mCanSendAtCancel = false;
|
|
// State of the HttpBackgroundChannelChild's event queue during destruction.
|
|
enum BckChildQueueStatus {
|
|
// BckChild never told us
|
|
BCKCHILD_UNKNOWN,
|
|
// BckChild was empty at the time of destruction
|
|
BCKCHILD_EMPTY,
|
|
// BckChild was keeping events in the queue at the destruction time!
|
|
BCKCHILD_NON_EMPTY
|
|
};
|
|
Atomic<BckChildQueueStatus> mBackgroundChildQueueFinalState{BCKCHILD_UNKNOWN};
|
|
Maybe<ActorDestroyReason> mActorDestroyReason;
|
|
#endif
|
|
|
|
uint8_t mCacheEntryAvailable : 1;
|
|
uint8_t mAltDataCacheEntryAvailable : 1;
|
|
|
|
// If ResumeAt is called before AsyncOpen, we need to send extra data upstream
|
|
uint8_t mSendResumeAt : 1;
|
|
|
|
uint8_t mKeptAlive : 1; // IPC kept open, but only for security info
|
|
|
|
// Set when ActorDestroy(ActorDestroyReason::Deletion) is called
|
|
// The channel must ignore any following OnStart/Stop/DataAvailable messages
|
|
uint8_t mIPCActorDeleted : 1;
|
|
|
|
// Set if SendSuspend is called. Determines if SendResume is needed when
|
|
// diverting callbacks to parent.
|
|
uint8_t mSuspendSent : 1;
|
|
|
|
// True if this channel is a multi-part channel, and the first part
|
|
// is currently being processed.
|
|
uint8_t mIsFirstPartOfMultiPart : 1;
|
|
|
|
// True if this channel is a multi-part channel, and the last part
|
|
// is currently being processed.
|
|
uint8_t mIsLastPartOfMultiPart : 1;
|
|
|
|
// True if this channel is suspended by ConnectParent and not resumed by
|
|
// CompleteRedirectSetup/RecvDeleteSelf.
|
|
uint8_t mSuspendForWaitCompleteRedirectSetup : 1;
|
|
|
|
// True if RecvOnStartRequestSent was received.
|
|
uint8_t mRecvOnStartRequestSentCalled : 1;
|
|
|
|
// True if this channel is for a document and suspended by waiting for
|
|
// permission or cookie. That is, RecvOnStartRequestSent is received.
|
|
uint8_t mSuspendedByWaitingForPermissionCookie : 1;
|
|
|
|
// HttpChannelChild::Release has some special logic that makes sure
|
|
// OnStart/OnStop are always called when releasing the channel.
|
|
// But we have to make sure we only do this once - otherwise we could
|
|
// get stuck in a loop.
|
|
uint8_t mAlreadyReleased : 1;
|
|
|
|
void CleanupRedirectingChannel(nsresult rv);
|
|
|
|
// Calls OnStartRequest and/or OnStopRequest on our listener in case we didn't
|
|
// do that so far. If we already did, it will just release references to
|
|
// cleanup.
|
|
void NotifyOrReleaseListeners(nsresult rv);
|
|
|
|
// true after successful AsyncOpen until OnStopRequest completes.
|
|
bool RemoteChannelExists() { return CanSend() && !mKeptAlive; }
|
|
|
|
void OnStartRequest(const nsHttpResponseHead& aResponseHead,
|
|
const bool& aUseResponseHead,
|
|
const nsHttpHeaderArray& aRequestHeaders,
|
|
const HttpChannelOnStartRequestArgs& aArgs);
|
|
void OnTransportAndData(const nsresult& channelStatus, const nsresult& status,
|
|
const uint64_t& offset, const uint32_t& count,
|
|
const nsACString& data);
|
|
void OnStopRequest(const nsresult& channelStatus,
|
|
const ResourceTimingStructArgs& timing,
|
|
const nsHttpHeaderArray& aResponseTrailers);
|
|
void FailedAsyncOpen(const nsresult& status);
|
|
void HandleAsyncAbort();
|
|
void Redirect1Begin(const uint32_t& registrarId, nsIURI* newOriginalURI,
|
|
const uint32_t& newLoadFlags,
|
|
const uint32_t& redirectFlags,
|
|
const ParentLoadInfoForwarderArgs& loadInfoForwarder,
|
|
const nsHttpResponseHead& responseHead,
|
|
nsITransportSecurityInfo* securityInfo,
|
|
const uint64_t& channelId,
|
|
const ResourceTimingStructArgs& timing);
|
|
void Redirect3Complete();
|
|
void DeleteSelf();
|
|
// aUseEventQueue should only be false when called from
|
|
// HttpChannelChild::Release to make sure OnStopRequest is called syncly.
|
|
void DoNotifyListener(bool aUseEventQueue = true);
|
|
void ContinueDoNotifyListener();
|
|
void OnAfterLastPart(const nsresult& aStatus);
|
|
void MaybeConnectToSocketProcess();
|
|
void OnDetachStreamFilters();
|
|
void SendOnDataFinished(const nsresult& aChannelStatus);
|
|
|
|
// Create a a new channel to be used in a redirection, based on the provided
|
|
// response headers.
|
|
[[nodiscard]] nsresult SetupRedirect(nsIURI* uri,
|
|
const nsHttpResponseHead* responseHead,
|
|
const uint32_t& redirectFlags,
|
|
nsIChannel** outChannel);
|
|
|
|
// Collect telemetry for mixed content.
|
|
void CollectMixedContentTelemetry();
|
|
|
|
friend class HttpAsyncAborter<HttpChannelChild>;
|
|
friend class InterceptStreamListener;
|
|
friend class InterceptedChannelContent;
|
|
friend class HttpBackgroundChannelChild;
|
|
friend class NeckoTargetChannelFunctionEvent;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// inline functions
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline bool HttpChannelChild::IsSuspended() { return mSuspendCount != 0; }
|
|
|
|
} // namespace mozilla::net
|
|
|
|
#endif // mozilla_net_HttpChannelChild_h
|