Bug 1407384 - P1: Notify "http-on-before-connect" and "http-on-modify-request" observers in DoAuthRetry r=mayhemer

The goal in this patch is to notify "http-on-before-connect" and "http-on-modify-request" observers in DoAuthRetry and also handle the case when the channel is canceled or suspended by observer.

Differential Revision: https://phabricator.services.mozilla.com/D10741

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kershaw Chang 2019-01-15 16:04:44 +00:00
parent 805e16ad13
commit b5b9e5d5c3
4 changed files with 255 additions and 114 deletions

View File

@ -793,7 +793,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(HttpBaseChannel, HTTP_BASE_CHANNEL_IID)
template <class T>
class HttpAsyncAborter {
public:
explicit HttpAsyncAborter(T *derived) : mThis(derived), mCallOnResume(0) {}
explicit HttpAsyncAborter(T *derived)
: mThis(derived), mCallOnResume(nullptr) {}
// Aborts channel: calls OnStart/Stop with provided status, removes channel
// from loadGroup.
@ -813,7 +814,7 @@ class HttpAsyncAborter {
protected:
// Function to be called at resume time
void (T::*mCallOnResume)(void);
std::function<nsresult(T *)> mCallOnResume;
};
template <class T>
@ -838,7 +839,10 @@ inline void HttpAsyncAborter<T>::HandleAsyncAbort() {
MOZ_LOG(
gHttpLog, LogLevel::Debug,
("Waiting until resume to do async notification [this=%p]\n", mThis));
mCallOnResume = &T::HandleAsyncAbort;
mCallOnResume = [](T *self) {
self->HandleAsyncAbort();
return NS_OK;
};
return;
}

View File

@ -2347,9 +2347,17 @@ HttpChannelChild::Resume() {
SendResume();
}
if (mCallOnResume) {
rv = AsyncCall(mCallOnResume);
NS_ENSURE_SUCCESS(rv, rv);
mCallOnResume = nullptr;
nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
MOZ_ASSERT(neckoTarget);
RefPtr<HttpChannelChild> self = this;
std::function<nsresult(HttpChannelChild*)> callOnResume = nullptr;
std::swap(callOnResume, mCallOnResume);
rv = neckoTarget->Dispatch(
NS_NewRunnableFunction(
"net::HttpChannelChild::mCallOnResume",
[callOnResume, self{std::move(self)}]() { callOnResume(self); }),
NS_DISPATCH_NORMAL);
}
}
if (mSynthesizedResponsePump) {
@ -3813,7 +3821,7 @@ HttpChannelChild::LogMimeTypeMismatch(const nsACString& aMessageName,
nsAutoString url(aURL);
nsAutoString contentType(aContentType);
const char16_t* params[] = { url.get(), contentType.get() };
const char16_t* params[] = {url.get(), contentType.get()};
nsContentUtils::ReportToConsole(
aWarning ? nsIScriptError::warningFlag : nsIScriptError::errorFlag,
NS_LITERAL_CSTRING("MIMEMISMATCH"), doc,

View File

@ -439,7 +439,10 @@ nsresult nsHttpChannel::PrepareToConnect() {
// We abandon the connection here if there was one.
LOG(("Waiting until resume OnBeforeConnect [this=%p]\n", this));
MOZ_ASSERT(!mCallOnResume);
mCallOnResume = &nsHttpChannel::HandleOnBeforeConnect;
mCallOnResume = [](nsHttpChannel *self) {
self->HandleOnBeforeConnect();
return NS_OK;
};
return NS_OK;
}
@ -454,7 +457,10 @@ void nsHttpChannel::HandleContinueCancelledByTrackingProtection() {
("Waiting until resume HandleContinueCancelledByTrackingProtection "
"[this=%p]\n",
this));
mCallOnResume = &nsHttpChannel::HandleContinueCancelledByTrackingProtection;
mCallOnResume = [](nsHttpChannel *self) {
self->HandleContinueCancelledByTrackingProtection();
return NS_OK;
};
return;
}
@ -469,7 +475,10 @@ void nsHttpChannel::HandleOnBeforeConnect() {
if (mSuspendCount) {
LOG(("Waiting until resume OnBeforeConnect [this=%p]\n", this));
mCallOnResume = &nsHttpChannel::HandleOnBeforeConnect;
mCallOnResume = [](nsHttpChannel *self) {
self->HandleOnBeforeConnect();
return NS_OK;
};
return;
}
@ -593,7 +602,10 @@ nsresult nsHttpChannel::OnBeforeConnect() {
// We abandon the connection here if there was one.
LOG(("Waiting until resume OnBeforeConnect [this=%p]\n", this));
MOZ_ASSERT(!mCallOnResume);
mCallOnResume = &nsHttpChannel::OnBeforeConnectContinue;
mCallOnResume = [](nsHttpChannel *self) {
self->OnBeforeConnectContinue();
return NS_OK;
};
return NS_OK;
}
@ -606,7 +618,10 @@ void nsHttpChannel::OnBeforeConnectContinue() {
if (mSuspendCount) {
LOG(("Waiting until resume OnBeforeConnect [this=%p]\n", this));
mCallOnResume = &nsHttpChannel::OnBeforeConnectContinue;
mCallOnResume = [](nsHttpChannel *self) {
self->OnBeforeConnectContinue();
return NS_OK;
};
return;
}
@ -774,14 +789,31 @@ nsresult nsHttpChannel::ContinueConnect() {
}
// hit the net...
return DoConnect();
}
nsresult nsHttpChannel::DoConnect(nsAHttpConnection *aConn) {
LOG(("nsHttpChannel::DoConnect [this=%p]\n", this));
nsresult rv = SetupTransaction();
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv)) {
return rv;
}
// transfer ownership of connection to transaction
if (aConn) {
mTransaction->SetConnection(aConn);
}
rv = gHttpHandler->InitiateTransaction(mTransaction, mPriority);
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv)) {
return rv;
}
rv = mTransactionPump->AsyncRead(this, nullptr);
if (NS_FAILED(rv)) return rv;
if (NS_FAILED(rv)) {
return rv;
}
uint32_t suspendCount = mSuspendCount;
if (mAsyncResumePending) {
@ -852,7 +884,10 @@ void nsHttpChannel::HandleAsyncRedirect() {
if (mSuspendCount) {
LOG(("Waiting until resume to do async redirect [this=%p]\n", this));
mCallOnResume = &nsHttpChannel::HandleAsyncRedirect;
mCallOnResume = [](nsHttpChannel *self) {
self->HandleAsyncRedirect();
return NS_OK;
};
return;
}
@ -918,7 +953,10 @@ void nsHttpChannel::HandleAsyncNotModified() {
if (mSuspendCount) {
LOG(("Waiting until resume to do async not-modified [this=%p]\n", this));
mCallOnResume = &nsHttpChannel::HandleAsyncNotModified;
mCallOnResume = [](nsHttpChannel *self) {
self->HandleAsyncNotModified();
return NS_OK;
};
return;
}
@ -938,7 +976,10 @@ void nsHttpChannel::HandleAsyncFallback() {
if (mSuspendCount) {
LOG(("Waiting until resume to do async fallback [this=%p]\n", this));
mCallOnResume = &nsHttpChannel::HandleAsyncFallback;
mCallOnResume = [](nsHttpChannel *self) {
self->HandleAsyncFallback();
return NS_OK;
};
return;
}
@ -2322,7 +2363,10 @@ nsresult nsHttpChannel::ContinueProcessResponse1() {
if (mSuspendCount) {
LOG(("Waiting until resume to finish processing response [this=%p]\n",
this));
mCallOnResume = &nsHttpChannel::AsyncContinueProcessResponse;
mCallOnResume = [](nsHttpChannel *self) {
self->AsyncContinueProcessResponse();
return NS_OK;
};
return NS_OK;
}
@ -2817,7 +2861,10 @@ void nsHttpChannel::HandleAsyncRedirectChannelToHttps() {
if (mSuspendCount) {
LOG(("Waiting until resume to do async redirect to https [this=%p]\n",
this));
mCallOnResume = &nsHttpChannel::HandleAsyncRedirectChannelToHttps;
mCallOnResume = [](nsHttpChannel *self) {
self->HandleAsyncRedirectChannelToHttps();
return NS_OK;
};
return;
}
@ -2849,7 +2896,10 @@ void nsHttpChannel::HandleAsyncAPIRedirect() {
if (mSuspendCount) {
LOG(("Waiting until resume to do async API redirect [this=%p]\n", this));
mCallOnResume = &nsHttpChannel::HandleAsyncAPIRedirect;
mCallOnResume = [](nsHttpChannel *self) {
self->HandleAsyncAPIRedirect();
return NS_OK;
};
return;
}
@ -5915,7 +5965,10 @@ nsHttpChannel::CancelForTrackingProtection() {
LOG(("Waiting until resume in Cancel [this=%p]\n", this));
MOZ_ASSERT(!mCallOnResume);
mTrackingProtectionCancellationPending = 1;
mCallOnResume = &nsHttpChannel::HandleContinueCancelledByTrackingProtection;
mCallOnResume = [](nsHttpChannel *self) {
self->HandleContinueCancelledByTrackingProtection();
return NS_OK;
};
return NS_OK;
}
@ -6498,12 +6551,6 @@ nsresult nsHttpChannel::BeginConnectActual() {
("Waiting for tracking protection cancellation in BeginConnectActual "
"[this=%p]\n",
this));
MOZ_ASSERT(
!mCallOnResume ||
mCallOnResume ==
&nsHttpChannel::HandleContinueCancelledByTrackingProtection,
"We should be paused waiting for cancellation from tracking "
"protection");
return NS_OK;
}
@ -6645,7 +6692,10 @@ nsresult nsHttpChannel::ContinueBeginConnectWithResult() {
if (mSuspendCount) {
LOG(("Waiting until resume to do async connect [this=%p]\n", this));
mCallOnResume = &nsHttpChannel::ContinueBeginConnect;
mCallOnResume = [](nsHttpChannel *self) {
self->ContinueBeginConnect();
return NS_OK;
};
rv = NS_OK;
} else if (mCanceled) {
// We may have been cancelled already, by nsChannelClassifier in that
@ -7414,56 +7464,93 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
// handle auth retry...
if (authRetry) {
mAuthRetryPending = false;
status = DoAuthRetry(conn);
if (NS_SUCCEEDED(status)) return NS_OK;
}
// If DoAuthRetry failed, or if we have been cancelled since showing
// the auth. dialog, then we need to send OnStartRequest now
if (authRetry || (mAuthRetryPending && NS_FAILED(status))) {
MOZ_ASSERT(NS_FAILED(status), "should have a failure code here");
// NOTE: since we have a failure status, we can ignore the return
// value from onStartRequest.
LOG((" calling mListener->OnStartRequest [this=%p, listener=%p]\n", this,
mListener.get()));
if (mListener) {
MOZ_ASSERT(!mOnStartRequestCalled,
"We should not call OnStartRequest twice.");
mListener->OnStartRequest(this, mListenerContext);
mOnStartRequestCalled = true;
} else {
NS_WARNING("OnStartRequest skipped because of null listener");
auto continueOSR = [authRetry, isFromNet, contentComplete,
stickyConn{std::move(stickyConn)}](auto *self,
nsresult aStatus) {
return self->ContinueOnStopRequestAfterAuthRetry(
aStatus, authRetry, isFromNet, contentComplete, stickyConn);
};
status = DoAuthRetry(conn, continueOSR);
if (NS_SUCCEEDED(status)) {
return NS_OK;
}
}
return ContinueOnStopRequestAfterAuthRetry(status, authRetry, isFromNet,
contentComplete, stickyConn);
}
// if this transaction has been replaced, then bail.
if (mTransactionReplaced) {
LOG(("Transaction replaced\n"));
// This was just the network check for a 304 response.
mFirstResponseSource = RESPONSE_PENDING;
return NS_OK;
}
return ContinueOnStopRequest(status, isFromNet, contentComplete);
}
bool upgradeWebsocket = mUpgradeProtocolCallback && stickyConn &&
mResponseHead &&
((mResponseHead->Status() == 101 &&
mResponseHead->Version() == HttpVersion::v1_1) ||
(mResponseHead->Status() == 200 &&
mResponseHead->Version() == HttpVersion::v2_0));
nsresult nsHttpChannel::ContinueOnStopRequestAfterAuthRetry(
nsresult aStatus, bool aAuthRetry, bool aIsFromNet, bool aContentComplete,
nsAHttpConnection *aStickyConn) {
LOG(
("nsHttpChannel::ContinueOnStopRequestAfterAuthRetry "
"[this=%p, aStatus=%" PRIx32
" aAuthRetry=%d, aIsFromNet=%d, aStickyConn=%p]\n",
this, static_cast<uint32_t>(aStatus), aAuthRetry, aIsFromNet,
aStickyConn));
bool upgradeConnect = mUpgradeProtocolCallback && stickyConn &&
(mCaps & NS_HTTP_CONNECT_ONLY) && mResponseHead &&
mResponseHead->Status() == 200;
if (aAuthRetry && NS_SUCCEEDED(aStatus)) {
return NS_OK;
}
if (upgradeWebsocket || upgradeConnect) {
nsresult rv = gHttpHandler->ConnMgr()->CompleteUpgrade(
stickyConn, mUpgradeProtocolCallback);
if (NS_FAILED(rv)) {
LOG((" CompleteUpgrade failed with %08x", static_cast<uint32_t>(rv)));
}
// If DoAuthRetry failed, or if we have been cancelled since showing
// the auth. dialog, then we need to send OnStartRequest now
if (aAuthRetry || (mAuthRetryPending && NS_FAILED(aStatus))) {
MOZ_ASSERT(NS_FAILED(aStatus), "should have a failure code here");
// NOTE: since we have a failure status, we can ignore the return
// value from onStartRequest.
LOG((" calling mListener->OnStartRequest [this=%p, listener=%p]\n", this,
mListener.get()));
if (mListener) {
MOZ_ASSERT(!mOnStartRequestCalled,
"We should not call OnStartRequest twice.");
mListener->OnStartRequest(this, mListenerContext);
mOnStartRequestCalled = true;
} else {
NS_WARNING("OnStartRequest skipped because of null listener");
}
}
// if this transaction has been replaced, then bail.
if (mTransactionReplaced) {
LOG(("Transaction replaced\n"));
// This was just the network check for a 304 response.
mFirstResponseSource = RESPONSE_PENDING;
return NS_OK;
}
bool upgradeWebsocket = mUpgradeProtocolCallback && aStickyConn &&
mResponseHead &&
((mResponseHead->Status() == 101 &&
mResponseHead->Version() == HttpVersion::v1_1) ||
(mResponseHead->Status() == 200 &&
mResponseHead->Version() == HttpVersion::v2_0));
bool upgradeConnect = mUpgradeProtocolCallback && aStickyConn &&
(mCaps & NS_HTTP_CONNECT_ONLY) && mResponseHead &&
mResponseHead->Status() == 200;
if (upgradeWebsocket || upgradeConnect) {
nsresult rv = gHttpHandler->ConnMgr()->CompleteUpgrade(
aStickyConn, mUpgradeProtocolCallback);
if (NS_FAILED(rv)) {
LOG((" CompleteUpgrade failed with %08x", static_cast<uint32_t>(rv)));
}
}
return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
}
nsresult nsHttpChannel::ContinueOnStopRequest(nsresult aStatus, bool aIsFromNet,
bool aContentComplete) {
LOG(
("nsHttpChannel::ContinueOnStopRequest "
"[this=%p aStatus=%" PRIx32 ", aIsFromNet=%d]\n",
this, static_cast<uint32_t>(aStatus), aIsFromNet));
// HTTP_CHANNEL_DISPOSITION TELEMETRY
enum ChannelDisposition {
kHttpCanceled = 0,
@ -7492,7 +7579,7 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
chanDisposition = kHttpDisk;
upgradeChanDisposition =
Telemetry::LABELS_HTTP_CHANNEL_DISPOSITION_UPGRADE::disk;
} else if (NS_SUCCEEDED(status) && mResponseHead &&
} else if (NS_SUCCEEDED(aStatus) && mResponseHead &&
mResponseHead->Version() != HttpVersion::v0_9) {
chanDisposition = kHttpNetOK;
upgradeChanDisposition =
@ -7540,7 +7627,7 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
Telemetry::Accumulate(Telemetry::HTTP_CHANNEL_DISPOSITION, chanDisposition);
// if needed, check cache entry has all data we expect
if (mCacheEntry && mCachePump && mConcurrentCacheAccess && contentComplete) {
if (mCacheEntry && mCachePump && mConcurrentCacheAccess && aContentComplete) {
int64_t size, contentLength;
nsresult rv = CheckPartial(mCacheEntry, &size, &contentLength);
if (NS_SUCCEEDED(rv)) {
@ -7571,7 +7658,7 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
}
LOG((" but range request perform failed 0x%08" PRIx32,
static_cast<uint32_t>(rv)));
status = NS_ERROR_NET_INTERRUPT;
aStatus = NS_ERROR_NET_INTERRUPT;
} else {
LOG((" but range request setup failed rv=0x%08" PRIx32
", failing load",
@ -7582,7 +7669,7 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
}
mIsPending = false;
mStatus = status;
mStatus = aStatus;
// perform any final cache operations before we close the cache entry.
if (mCacheEntry && mRequestTimeInitialized) {
@ -7598,7 +7685,7 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
}
}
ReportRcwnStats(isFromNet);
ReportRcwnStats(aIsFromNet);
// Register entry to the PerformanceStorage resource timing
MaybeReportTimingData();
@ -7608,7 +7695,7 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
MOZ_ASSERT(mOnStartRequestCalled,
"OnStartRequest should be called before OnStopRequest");
MOZ_ASSERT(!mOnStopRequestCalled, "We should not call OnStopRequest twice");
mListener->OnStopRequest(this, mListenerContext, status);
mListener->OnStopRequest(this, mListenerContext, aStatus);
mOnStopRequestCalled = true;
}
@ -7625,11 +7712,13 @@ nsHttpChannel::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
mAltDataCacheEntry = mCacheEntry;
}
CloseCacheEntry(!contentComplete);
CloseCacheEntry(!aContentComplete);
if (mOfflineCacheEntry) CloseOfflineCacheEntry();
if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, status);
if (mLoadGroup) {
mLoadGroup->RemoveRequest(this, nullptr, aStatus);
}
// We don't need this info anymore
CleanRedirectCacheChainIfNecessary();
@ -8195,15 +8284,19 @@ nsHttpChannel::ResumeAt(uint64_t aStartPos, const nsACString &aEntityID) {
return NS_OK;
}
nsresult nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn) {
nsresult nsHttpChannel::DoAuthRetry(
nsAHttpConnection *conn,
const std::function<nsresult(nsHttpChannel *, nsresult)>
&aContinueOnStopRequestFunc) {
LOG(("nsHttpChannel::DoAuthRetry [this=%p]\n", this));
MOZ_ASSERT(!mTransaction, "should not have a transaction");
nsresult rv;
// toggle mIsPending to allow nsIObserver implementations to modify
// the request headers (bug 95044).
mIsPending = false;
// Note that we don't have to toggle |mIsPending| anymore. See the reasons
// below.
// 1. We can't suspend the channel during "http-on-modify-request"
// when |mIsPending| is false.
// 2. We don't check |mIsPending| in SetRequestHeader now.
// Reset mRequestObserversCalled because we've probably called the request
// observers once already.
@ -8218,6 +8311,19 @@ nsresult nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn) {
// notify "http-on-modify-request" observers
CallOnModifyRequestObservers();
RefPtr<nsAHttpConnection> connRef(conn);
return CallOrWaitForResume(
[conn{std::move(connRef)}, aContinueOnStopRequestFunc](auto *self) {
return self->ContinueDoAuthRetry(conn, aContinueOnStopRequestFunc);
});
}
nsresult nsHttpChannel::ContinueDoAuthRetry(
nsAHttpConnection *aConn,
const std::function<nsresult(nsHttpChannel *, nsresult)>
&aContinueOnStopRequestFunc) {
LOG(("nsHttpChannel::ContinueDoAuthRetry [this=%p]\n", this));
mIsPending = true;
// get rid of the old response headers
@ -8226,7 +8332,9 @@ nsresult nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn) {
// rewind the upload stream
if (mUploadStream) {
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
if (seekable) seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
if (seekable) {
seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
}
}
// always set sticky connection flag
@ -8241,32 +8349,15 @@ nsresult nsHttpChannel::DoAuthRetry(nsAHttpConnection *conn) {
mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE;
}
// and create a new one...
rv = SetupTransaction();
if (NS_FAILED(rv)) return rv;
// notify "http-on-before-connect" observers
gHttpHandler->OnBeforeConnect(this);
// transfer ownership of connection to transaction
if (conn) mTransaction->SetConnection(conn);
rv = gHttpHandler->InitiateTransaction(mTransaction, mPriority);
if (NS_FAILED(rv)) return rv;
rv = mTransactionPump->AsyncRead(this, nullptr);
if (NS_FAILED(rv)) return rv;
uint32_t suspendCount = mSuspendCount;
if (mAsyncResumePending) {
LOG(
(" Suspend()'ing transaction pump once because of async resume pending"
", sc=%u, pump=%p, this=%p",
suspendCount, mTransactionPump.get(), this));
++suspendCount;
}
while (suspendCount--) {
mTransactionPump->Suspend();
}
return NS_OK;
RefPtr<nsAHttpConnection> connRef(aConn);
return CallOrWaitForResume(
[conn{std::move(connRef)}, aContinueOnStopRequestFunc](auto *self) {
nsresult rv = self->DoConnect(conn);
return aContinueOnStopRequestFunc(self, rv);
});
}
//-----------------------------------------------------------------------------
@ -8809,6 +8900,23 @@ nsHttpChannel::SuspendInternal() {
return NS_FAILED(rvTransaction) ? rvTransaction : rvCache;
}
nsresult nsHttpChannel::CallOrWaitForResume(
const std::function<nsresult(nsHttpChannel *)> &aFunc) {
if (mCanceled) {
MOZ_ASSERT(NS_FAILED(mStatus));
return mStatus;
}
if (mSuspendCount) {
LOG(("Waiting until resume [this=%p]\n", this));
MOZ_ASSERT(!mCallOnResume);
mCallOnResume = aFunc;
return NS_OK;
}
return aFunc(this);
}
NS_IMETHODIMP
nsHttpChannel::ResumeInternal() {
NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
@ -8828,8 +8936,8 @@ nsHttpChannel::ResumeInternal() {
MOZ_ASSERT(!mAsyncResumePending);
mAsyncResumePending = 1;
auto const callOnResume = mCallOnResume;
mCallOnResume = nullptr;
std::function<nsresult(nsHttpChannel *)> callOnResume = nullptr;
std::swap(callOnResume, mCallOnResume);
RefPtr<nsHttpChannel> self(this);
RefPtr<nsInputStreamPump> transactionPump = mTransactionPump;
@ -8837,11 +8945,15 @@ nsHttpChannel::ResumeInternal() {
nsresult rv = NS_DispatchToCurrentThread(NS_NewRunnableFunction(
"nsHttpChannel::CallOnResume",
[callOnResume, self{std::move(self)},
[callOnResume{std::move(callOnResume)}, self{std::move(self)},
transactionPump{std::move(transactionPump)},
cachePump{std::move(cachePump)}]() {
MOZ_ASSERT(self->mAsyncResumePending);
(self->*callOnResume)();
nsresult rv = self->CallOrWaitForResume(callOnResume);
if (NS_FAILED(rv)) {
self->CloseCacheEntry(false);
Unused << self->AsyncAbort(rv);
}
MOZ_ASSERT(self->mAsyncResumePending);
self->mAsyncResumePending = 0;

View File

@ -301,6 +301,12 @@ class nsHttpChannel final : public HttpBaseChannel,
private:
typedef nsresult (nsHttpChannel::*nsContinueRedirectionFunc)(nsresult result);
// Directly call |aFunc| if the channel is not canceled and not suspended.
// Otherwise, set |aFunc| to |mCallOnResume| and wait until the channel
// resumes.
nsresult CallOrWaitForResume(
const std::function<nsresult(nsHttpChannel *)> &aFunc);
bool RequestIsConditional();
void HandleContinueCancelledByTrackingProtection();
nsresult CancelInternal(nsresult status);
@ -411,7 +417,18 @@ class nsHttpChannel final : public HttpBaseChannel,
MOZ_MUST_USE nsresult ProcessPartialContent();
MOZ_MUST_USE nsresult OnDoneReadingPartialCacheEntry(bool *streamDone);
MOZ_MUST_USE nsresult DoAuthRetry(nsAHttpConnection *);
MOZ_MUST_USE nsresult
DoAuthRetry(nsAHttpConnection *,
const std::function<nsresult(nsHttpChannel *, nsresult)> &aOuter);
MOZ_MUST_USE nsresult ContinueDoAuthRetry(
nsAHttpConnection *aConn,
const std::function<nsresult(nsHttpChannel *, nsresult)> &aOuter);
MOZ_MUST_USE nsresult DoConnect(nsAHttpConnection *aConn = nullptr);
MOZ_MUST_USE nsresult ContinueOnStopRequestAfterAuthRetry(
nsresult aStatus, bool aAuthRetry, bool aIsFromNet, bool aContentComplete,
nsAHttpConnection *aStickyConn);
MOZ_MUST_USE nsresult ContinueOnStopRequest(nsresult status, bool aIsFromNet,
bool aContentComplete);
void HandleAsyncRedirectChannelToHttps();
MOZ_MUST_USE nsresult StartRedirectChannelToHttps();