Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http/./../../../../netwerk/protocol/http/nsHttpChannel.cpp
Warning:line 5888, column 3
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_protocol_http4.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_APP_UA_NAME="" -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/netwerk/protocol/http -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/dom/base -I /root/firefox-clang/netwerk/base -I /root/firefox-clang/netwerk/cookie -I /root/firefox-clang/netwerk/dns -I /root/firefox-clang/netwerk/ipc -I /root/firefox-clang/netwerk/socket/neqo_glue -I /root/firefox-clang/netwerk/url-classifier -I /root/firefox-clang/extensions/auth -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-11-12-001017-1011516-1 -x c++ Unified_cpp_protocol_http4.cpp
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5// HttpLog.h should generally be included first
6#include "nsHttpChannel.h"
7
8#include <inttypes.h>
9
10#include "AlternateServices.h"
11#include "CacheControlParser.h"
12#include "CacheStorageService.h"
13#include "CookieService.h"
14#include "HttpChannelParent.h"
15#include "HttpLog.h"
16#include "HttpTrafficAnalyzer.h"
17#include "InterceptedHttpChannel.h"
18#include "LNAPermissionRequest.h"
19#include "LoadContextInfo.h"
20#include "NetworkMarker.h"
21#include "ThirdPartyUtil.h"
22#include "mozilla/AntiTrackingRedirectHeuristic.h"
23#include "mozilla/AntiTrackingUtils.h"
24#include "mozilla/Attributes.h"
25#include "mozilla/BasePrincipal.h"
26#include "mozilla/Components.h"
27#include "mozilla/ContentBlockingAllowList.h"
28#include "mozilla/DebugOnly.h"
29#include "mozilla/FlowMarkers.h"
30#include "mozilla/LoadInfo.h"
31#include "mozilla/NullPrincipal.h"
32#include "mozilla/PerfStats.h"
33#include "mozilla/ProfilerDumpOrCrash.h"
34#include "mozilla/ProfilerLabels.h"
35#include "mozilla/ScopeExit.h"
36#include "mozilla/Services.h"
37#include "mozilla/Sprintf.h"
38#include "mozilla/StaticPrefs_dom.h"
39#include "mozilla/StaticPrefs_network.h"
40#include "mozilla/StaticPrefs_privacy.h"
41#include "mozilla/StaticPrefs_security.h"
42#include "mozilla/StoragePrincipalHelper.h"
43#include "mozilla/Telemetry.h"
44#include "mozilla/TimeStamp.h"
45#include "mozilla/ToString.h"
46#include "mozilla/dom/ClientInfo.h"
47#include "mozilla/dom/Document.h"
48#include "mozilla/dom/NavigatorLogin.h"
49#include "mozilla/dom/PerformanceStorage.h"
50#include "mozilla/dom/PolicyContainer.h"
51#include "mozilla/dom/ReferrerInfo.h"
52#include "mozilla/dom/RemoteType.h"
53#include "mozilla/dom/SecFetch.h"
54#include "mozilla/dom/ServiceWorkerUtils.h"
55#include "mozilla/dom/WindowGlobalParent.h"
56#include "mozilla/dom/nsCSPContext.h"
57#include "mozilla/dom/nsHTTPSOnlyStreamListener.h"
58#include "mozilla/dom/nsHTTPSOnlyUtils.h"
59#include "mozilla/extensions/StreamFilterParent.h"
60#include "mozilla/glean/AntitrackingMetrics.h"
61#include "mozilla/glean/DomSecurityMetrics.h"
62#include "mozilla/glean/NetwerkMetrics.h"
63#include "mozilla/glean/NetwerkProtocolHttpMetrics.h"
64#include "mozilla/net/AsyncUrlChannelClassifier.h"
65#include "mozilla/net/CaptivePortalService.h"
66#include "mozilla/net/ChannelClassifierUtils.h"
67#include "mozilla/net/CookieJarSettings.h"
68#include "mozilla/net/CookieServiceParent.h"
69#include "mozilla/net/NeckoChannelParams.h"
70#include "mozilla/net/NoVarySearchUtils.h"
71#include "mozilla/net/OpaqueResponseUtils.h"
72#include "mozilla/net/SFVService.h"
73#include "mozilla/net/TRRService.h"
74#include "mozilla/net/URLPatternGlue.h"
75#include "mozilla/net/urlpattern_glue.h"
76#include "netCore.h"
77#include "nsCOMPtr.h"
78#include "nsCORSListenerProxy.h"
79#include "nsCRT.h"
80#include "nsChannelClassifier.h"
81#include "nsCharSeparatedTokenizer.h"
82#include "nsComponentManagerUtils.h"
83#include "nsContentSecurityManager.h"
84#include "nsContentSecurityUtils.h"
85#include "nsContentUtils.h"
86#include "nsDNSPrefetch.h"
87#include "nsError.h"
88#include "nsEscape.h"
89#include "nsHttp.h"
90#include "nsHttpChannelAuthProvider.h"
91#include "nsHttpConnectionMgr.h"
92#include "nsHttpHandler.h"
93#include "nsHttpTransaction.h"
94#include "nsICacheEntry.h"
95#include "nsICacheStorage.h"
96#include "nsICacheStorageService.h"
97#include "nsICancelable.h"
98#include "nsIClassOfService.h"
99#include "nsICompressConvStats.h"
100#include "nsIConsoleService.h"
101#include "nsICookieNotification.h"
102#include "nsICryptoHash.h"
103#include "nsIDNSRecord.h"
104#include "nsIEffectiveTLDService.h"
105#include "nsIHttpChannelInternal.h"
106#include "nsIHttpHeaderVisitor.h"
107#include "nsINetworkErrorLogging.h"
108#include "nsINetworkInterceptController.h"
109#include "nsINetworkLinkService.h"
110#include "nsIOService.h"
111#include "nsIPrincipal.h"
112#include "nsIPrompt.h"
113#include "nsIProtocolProxyService2.h"
114#include "nsIRedirectResultListener.h"
115#include "nsIScriptError.h"
116#include "nsIScriptSecurityManager.h"
117#include "nsISeekableStream.h"
118#include "nsISiteIntegrityService.h"
119#include "nsISiteSecurityService.h"
120#include "nsISocketProvider.h"
121#include "nsISocketTransport.h"
122#include "nsIStreamConverter.h"
123#include "nsIStreamConverterService.h"
124#include "nsIStreamListenerTee.h"
125#include "nsIStreamTransportService.h"
126#include "nsIStringBundle.h"
127#include "nsISystemInfo.h"
128#include "nsITransportSecurityInfo.h"
129#include "nsIURIMutator.h"
130#include "nsIURLQueryStringStripper.h"
131#include "nsIWebProgressListener.h"
132#include "nsIWebTransport.h"
133#include "nsInputStreamPump.h"
134#include "nsMimeTypes.h"
135#include "nsMixedContentBlocker.h"
136#include "nsNetCID.h"
137#include "nsNetUtil.h"
138#include "nsPrintfCString.h"
139#include "nsQueryObject.h"
140#include "nsStreamUtils.h"
141#include "nsString.h"
142#include "nsStringStream.h"
143#include "nsThreadUtils.h"
144#include "nsURLHelper.h"
145#include "nsUnknownDecoder.h"
146#include "prnetdb.h"
147#include "sslt.h"
148#ifdef XP_WIN
149# include "HttpWinUtils.h"
150#endif
151#ifdef XP_MACOSX
152# include "MicrosoftEntraSSOUtils.h"
153#endif
154#ifdef FUZZING
155# include "mozilla/StaticPrefs_fuzzing.h"
156#endif
157
158#include "mozilla/dom/ReportDeliver.h"
159#include "mozilla/dom/ReportingHeader.h"
160
161namespace mozilla {
162
163using namespace dom;
164
165namespace net {
166
167namespace {
168
169// True if the local cache should be bypassed when processing a request.
170#define BYPASS_LOCAL_CACHE(loadFlags, isPreferCacheLoadOverBypass)((loadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((loadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (isPreferCacheLoadOverBypass)))
\
171 ((loadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | \
172 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE) && \
173 !(((loadFlags) & nsIRequest::LOAD_FROM_CACHE) && \
174 (isPreferCacheLoadOverBypass)))
175
176#define RECOVER_FROM_CACHE_FILE_ERROR(result)((result) == NS_ERROR_FILE_NOT_FOUND || (result) == NS_ERROR_FILE_CORRUPTED
|| (result) == NS_ERROR_OUT_OF_MEMORY)
\
177 ((result) == NS_ERROR_FILE_NOT_FOUND || \
178 (result) == NS_ERROR_FILE_CORRUPTED || (result) == NS_ERROR_OUT_OF_MEMORY)
179
180static NS_DEFINE_CID(kStreamListenerTeeCID, NS_STREAMLISTENERTEE_CID)const nsCID kStreamListenerTeeCID = { 0x831f8f13, 0x7aa8, 0x485f
, {0xb0, 0x2e, 0x77, 0xc8, 0x81, 0xcc, 0x57, 0x73}}
;
181
182enum ChannelDisposition {
183 kHttpCanceled = 0,
184 kHttpDisk = 1,
185 kHttpNetOK = 2,
186 kHttpNetEarlyFail = 3,
187 kHttpNetLateFail = 4,
188 kHttpsCanceled = 8,
189 kHttpsDisk = 9,
190 kHttpsNetOK = 10,
191 kHttpsNetEarlyFail = 11,
192 kHttpsNetLateFail = 12
193};
194
195static nsLiteralCString CacheDispositionToTelemetryLabel(
196 nsICacheInfoChannel::CacheDisposition hitOrMiss) {
197 switch (hitOrMiss) {
198 case nsICacheInfoChannel::kCacheUnresolved:
199 return "Unresolved"_ns;
200 case nsICacheInfoChannel::kCacheHit:
201 return "Hit"_ns;
202 case nsICacheInfoChannel::kCacheHitViaReval:
203 return "HitViaReval"_ns;
204 case nsICacheInfoChannel::kCacheMissedViaReval:
205 return "MissedViaReval"_ns;
206 case nsICacheInfoChannel::kCacheMissed:
207 return "Missed"_ns;
208 case nsICacheInfoChannel::kCacheUnknown:
209 return "Unknown"_ns;
210 default:
211 return "Invalid"_ns;
212 }
213}
214
215void AccumulateCacheHitTelemetry(
216 nsICacheInfoChannel::CacheDisposition hitOrMiss, nsIChannel* aChannel) {
217 nsCString key("UNKNOWN");
218
219 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
220
221 nsAutoCString contentType;
222 if (NS_SUCCEEDED(aChannel->GetContentType(contentType))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aChannel->GetContentType
(contentType))), 1)))
) {
223 if (nsContentUtils::IsJavascriptMIMEType(
224 NS_ConvertUTF8toUTF16(contentType))) {
225 key.AssignLiteral("JAVASCRIPT");
226 } else if (StringBeginsWith(contentType, "text/css"_ns) ||
227 (loadInfo && loadInfo->GetExternalContentPolicyType() ==
228 ExtContentPolicy::TYPE_STYLESHEET)) {
229 key.AssignLiteral("STYLESHEET");
230 } else if (StringBeginsWith(contentType, "application/wasm"_ns)) {
231 key.AssignLiteral("WASM");
232 } else if (StringBeginsWith(contentType, "image/"_ns)) {
233 key.AssignLiteral("IMAGE");
234 } else if (StringBeginsWith(contentType, "video/"_ns)) {
235 key.AssignLiteral("MEDIA");
236 } else if (StringBeginsWith(contentType, "audio/"_ns)) {
237 key.AssignLiteral("MEDIA");
238 } else if (!StringBeginsWith(contentType,
239 nsLiteralCString(UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type"))) {
240 key.AssignLiteral("OTHER");
241 }
242 }
243
244 nsLiteralCString label = CacheDispositionToTelemetryLabel(hitOrMiss);
245 glean::http::cache_disposition.Get(key, label).Add();
246 glean::http::cache_disposition.Get("ALL"_ns, label).Add();
247}
248
249// Computes and returns a SHA1 hash of the input buffer. The input buffer
250// must be a null-terminated string.
251nsresult Hash(const char* buf, nsACString& hash) {
252 nsresult rv;
253
254 nsCOMPtr<nsICryptoHash> hasher =
255 do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID"@mozilla.org/security/hash;1", &rv);
256 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 256); return rv; } } while (false)
;
257
258 rv = hasher->Init(nsICryptoHash::SHA1);
259 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 259); return rv; } } while (false)
;
260
261 rv = hasher->Update(reinterpret_cast<unsigned const char*>(buf), strlen(buf));
262 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 262); return rv; } } while (false)
;
263
264 rv = hasher->Finish(true, hash);
265 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 265); return rv; } } while (false)
;
266
267 return NS_OK;
268}
269
270class CookieVisitor final {
271 public:
272 explicit CookieVisitor(nsHttpResponseHead* aResponseHead) {
273 nsAutoCString cookieHeader;
274 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Set_Cookie, cookieHeader))), 1)))
275 aResponseHead->GetHeader(nsHttp::Set_Cookie, cookieHeader))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Set_Cookie, cookieHeader))), 1)))
) {
276 for (const auto& cookie : cookieHeader.Split('\n')) {
277 mCookieHeaders.AppendElement(cookie);
278 }
279 }
280 }
281
282 ~CookieVisitor() = default;
283
284 const nsTArray<nsCString>& CookieHeaders() const { return mCookieHeaders; }
285
286 private:
287 nsTArray<nsCString> mCookieHeaders;
288};
289
290class CookieObserver final : public nsIObserver,
291 public nsSupportsWeakReference {
292 public:
293 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
294 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
295
296 static already_AddRefed<CookieObserver> Create(bool aPrivateBrowsing);
297
298 void StealChanges(nsTArray<CookieChange>& aChanges) {
299 aChanges.SwapElements(mChanges);
300 }
301
302 private:
303 CookieObserver() = default;
304 ~CookieObserver() = default;
305
306 nsTArray<CookieChange> mChanges;
307};
308
309NS_IMPL_ISUPPORTS(CookieObserver, nsIObserver, nsISupportsWeakReference)MozExternalRefCountType CookieObserver::AddRef(void) { static_assert
(!std::is_destructible_v<CookieObserver>, "Reference-counted class "
"CookieObserver" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 309
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CookieObserver" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CookieObserver" != nullptr)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"CookieObserver\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CookieObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 309); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("CookieObserver" " not thread-safe"); nsrefcnt count = ++mRefCnt
; NS_LogAddRef((this), (count), ("CookieObserver"), (uint32_t
)(sizeof(*this))); return count; } MozExternalRefCountType CookieObserver
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 309
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CookieObserver" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CookieObserver" != nullptr)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"CookieObserver\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 309); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CookieObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 309); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("CookieObserver" " not thread-safe"); const char* const nametmp
= "CookieObserver"; nsrefcnt count = --mRefCnt; NS_LogRelease
((this), (count), (nametmp)); if (count == 0) { mRefCnt = 1; delete
(this); return 0; } return count; } nsresult CookieObserver::
QueryInterface(const nsIID& aIID, void** aInstancePtr) { do
{ if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 309); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<CookieObserver, nsIObserver>, int32_t
( reinterpret_cast<char*>(static_cast<nsIObserver*>
((CookieObserver*)0x1000)) - reinterpret_cast<char*>((CookieObserver
*)0x1000))}, {&mozilla::detail::kImplementedIID<CookieObserver
, nsISupportsWeakReference>, int32_t( reinterpret_cast<
char*>(static_cast<nsISupportsWeakReference*>((CookieObserver
*)0x1000)) - reinterpret_cast<char*>((CookieObserver*)0x1000
))}, {&mozilla::detail::kImplementedIID<CookieObserver
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIObserver*>((CookieObserver
*)0x1000))) - reinterpret_cast<char*>((CookieObserver*)
0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table) >
1, "need at least 1 interface"); rv = NS_TableDrivenQI(static_cast
<void*>(this), aIID, aInstancePtr, table); return rv; }
310
311// static
312already_AddRefed<CookieObserver> CookieObserver::Create(bool aPrivateBrowsing) {
313 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 313
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 313); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
314
315 RefPtr<CookieObserver> observer = new CookieObserver();
316
317 nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
318 if (NS_WARN_IF(!os)NS_warn_if_impl(!os, "!os", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 318)
) {
319 return nullptr;
320 }
321
322 nsresult rv = os->AddObserver(
323 observer, aPrivateBrowsing ? "private-cookie-changed" : "cookie-changed",
324 true);
325 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 325)
) {
326 return nullptr;
327 }
328
329 return observer.forget();
330}
331
332NS_IMETHODIMPnsresult
333CookieObserver::Observe(nsISupports* aSubject, const char* aTopic,
334 const char16_t* aData) {
335 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 335
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 335); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
336
337 nsCOMPtr<nsICookieNotification> notification = do_QueryInterface(aSubject);
338 NS_ENSURE_TRUE(notification, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(notification)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "notification" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 338); return NS_ERROR_FAILURE; } } while (false)
;
339
340 nsCOMPtr<nsICookie> xpcCookie;
341 nsresult rv = notification->GetCookie(getter_AddRefs(xpcCookie));
342 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 342)
) {
343 return rv;
344 }
345
346 if (!xpcCookie) {
347 return NS_OK;
348 }
349
350 const Cookie& cookie = xpcCookie->AsCookie();
351
352 nsICookieNotification::Action action = notification->GetAction();
353
354 switch (action) {
355 case nsICookieNotification::COOKIE_DELETED:
356 mChanges.AppendElement(CookieChange{/* added */ false, cookie.ToIPC(),
357 cookie.OriginAttributesRef()});
358 break;
359
360 case nsICookieNotification::COOKIE_ADDED:
361 [[fallthrough]];
362 case nsICookieNotification::COOKIE_CHANGED:
363 mChanges.AppendElement(CookieChange{/* added */ true, cookie.ToIPC(),
364 cookie.OriginAttributesRef()});
365 break;
366
367 default:
368 // We don't care about other actions because none of them can be
369 // triggered by the Set-Cookie header.
370 break;
371 }
372
373 return NS_OK;
374}
375
376void MaybeInitializeCookieProcessingGuard(
377 nsHttpChannel* aChannel, CookieServiceParent::CookieProcessingGuard& aGuard,
378 RefPtr<CookieObserver>& aCookieObserver,
379 RefPtr<HttpChannelParent>& aHttpChannelParent, uint32_t aHttpStatus) {
380 nsCOMPtr<nsIParentChannel> parentChannel;
381 NS_QueryNotificationCallbacks(aChannel, parentChannel);
382 aHttpChannelParent = do_QueryObject(parentChannel);
383 if (!aHttpChannelParent) {
384 return;
385 }
386
387 aCookieObserver = CookieObserver::Create(NS_UsePrivateBrowsing(aChannel));
388
389 PNeckoParent* neckoParent = aHttpChannelParent->Manager();
390 if (!neckoParent) {
391 return;
392 }
393
394 PCookieServiceParent* csParent =
395 LoneManagedOrNullAsserts(neckoParent->ManagedPCookieServiceParent());
396 CookieServiceParent* cookieServiceParent =
397 static_cast<CookieServiceParent*>(csParent);
398 if (!cookieServiceParent) {
399 return;
400 }
401
402 // on redirect we don't want to use processing guard
403 // because it will prevent cookies from being set in the
404 // content process that originated the request
405 if (nsHttpChannel::IsRedirectStatus(aHttpStatus)) {
406 return;
407 }
408
409 aGuard.Initialize(cookieServiceParent);
410}
411
412} // unnamed namespace
413
414// We only treat 3xx responses as redirects if they have a Location header and
415// the status code is in a whitelist.
416bool nsHttpChannel::WillRedirect(const nsHttpResponseHead& response) {
417 return IsRedirectStatus(response.Status()) &&
418 response.HasHeader(nsHttp::Location);
419}
420
421nsresult StoreAuthorizationMetaData(nsICacheEntry* entry,
422 nsHttpRequestHead* requestHead);
423
424class MOZ_STACK_CLASS AutoRedirectVetoNotifier {
425 public:
426 explicit AutoRedirectVetoNotifier(nsHttpChannel* channel, nsresult& aRv)
427 : mChannel(channel), mRv(aRv) {
428 if (mChannel->LoadHasAutoRedirectVetoNotifier()) {
429 MOZ_CRASH("Nested AutoRedirectVetoNotifier on the stack")do { do { } while (false); MOZ_ReportCrash("" "Nested AutoRedirectVetoNotifier on the stack"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 429
); AnnotateMozCrashReason("MOZ_CRASH(" "Nested AutoRedirectVetoNotifier on the stack"
")"); do { MOZ_CrashSequence(__null, 429); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
430 mChannel = nullptr;
431 return;
432 }
433
434 mChannel->StoreHasAutoRedirectVetoNotifier(true);
435 }
436 ~AutoRedirectVetoNotifier() { ReportRedirectResult(mRv); }
437 void RedirectSucceeded() { ReportRedirectResult(NS_OK); }
438
439 private:
440 nsHttpChannel* mChannel;
441 bool mCalledReport = false;
442 nsresult& mRv;
443 void ReportRedirectResult(nsresult aRv);
444};
445
446void AutoRedirectVetoNotifier::ReportRedirectResult(nsresult aRv) {
447 if (!mChannel) return;
448
449 if (mCalledReport) {
450 return;
451 }
452 mCalledReport = true;
453
454 mChannel->mRedirectChannel = nullptr;
455
456 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))) {
457 mChannel->RemoveAsNonTailRequest();
458 }
459
460 nsCOMPtr<nsIRedirectResultListener> vetoHook;
461 NS_QueryNotificationCallbacks(mChannel, NS_GET_IID(nsIRedirectResultListener)(nsIRedirectResultListener::kIID),
462 getter_AddRefs(vetoHook));
463
464 nsHttpChannel* channel = mChannel;
465 mChannel = nullptr;
466
467 if (vetoHook) vetoHook->OnRedirectResult(aRv);
468
469 // Drop after the notification
470 channel->StoreHasAutoRedirectVetoNotifier(false);
471}
472
473//-----------------------------------------------------------------------------
474// nsHttpChannel <public>
475//-----------------------------------------------------------------------------
476
477nsHttpChannel::nsHttpChannel() : HttpAsyncAborter<nsHttpChannel>(this) {
478 LOG(("Creating nsHttpChannel [this=%p, nsIChannel=%p]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Creating nsHttpChannel [this=%p, nsIChannel=%p]\n", this, static_cast
<nsIChannel*>(this)); } } while (0)
479 static_cast<nsIChannel*>(this)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Creating nsHttpChannel [this=%p, nsIChannel=%p]\n", this, static_cast
<nsIChannel*>(this)); } } while (0)
;
480 mChannelCreationTime = PR_Now();
481 mChannelCreationTimestamp = TimeStamp::Now();
482}
483
484nsHttpChannel::~nsHttpChannel() {
485 MOZ_ASSERT(NS_IsMainThread(), "Must be released on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Must be released on main thread" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 485); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be released on main thread" ")"); do { MOZ_CrashSequence
(__null, 485); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
486 PROFILER_MARKER("~nsHttpChannel", NETWORK, {}, TerminatingFlowMarker,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("~nsHttpChannel", ::geckoprofiler::category::NETWORK, {}, ::
geckoprofiler::markers::TerminatingFlowMarker{}, Flow::FromPointer
(this)); } } while (false); } while (false)
487 Flow::FromPointer(this))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("~nsHttpChannel", ::geckoprofiler::category::NETWORK, {}, ::
geckoprofiler::markers::TerminatingFlowMarker{}, Flow::FromPointer
(this)); } } while (false); } while (false)
;
488 LOG(("Destroying nsHttpChannel [this=%p, nsIChannel=%p]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Destroying nsHttpChannel [this=%p, nsIChannel=%p]\n", this
, static_cast<nsIChannel*>(this)); } } while (0)
489 static_cast<nsIChannel*>(this)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Destroying nsHttpChannel [this=%p, nsIChannel=%p]\n", this
, static_cast<nsIChannel*>(this)); } } while (0)
;
490
491 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
492 nsCString webExtension;
493 this->GetPropertyAsACString(u"cancelledByExtension"_ns, webExtension);
494 if (!webExtension.IsEmpty()) {
495 LOG(("channel [%p] cancelled by extension [id=%s]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "channel [%p] cancelled by extension [id=%s]", this, webExtension
.get()); } } while (0)
496 webExtension.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "channel [%p] cancelled by extension [id=%s]", this, webExtension
.get()); } } while (0)
;
497 }
498 }
499
500 if (mAuthProvider) {
501 DebugOnly<nsresult> rv = mAuthProvider->Disconnect(NS_ERROR_ABORT);
502 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 502); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
503 }
504
505 if (gHttpHandler) {
506 gHttpHandler->RemoveHttpChannel(mChannelId);
507 }
508
509 if (mDictDecompress && mUsingDictionary) {
510 mDictDecompress->UseCompleted();
511 }
512}
513
514nsresult nsHttpChannel::Init(nsIURI* uri, uint32_t caps, nsProxyInfo* proxyInfo,
515 uint32_t proxyResolveFlags, nsIURI* proxyURI,
516 uint64_t channelId, nsILoadInfo* aLoadInfo) {
517 LOG1(("nsHttpChannel::Init [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Error)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Error, "nsHttpChannel::Init [this=%p]\n"
, this); } } while (0)
;
518 nsresult rv = HttpBaseChannel::Init(uri, caps, proxyInfo, proxyResolveFlags,
519 proxyURI, channelId, aLoadInfo);
520
521 return rv;
522}
523
524nsresult nsHttpChannel::AddSecurityMessage(const nsAString& aMessageTag,
525 const nsAString& aMessageCategory) {
526 if (mWarningReporter) {
527 RefPtr<HttpChannelSecurityWarningReporter> reporter(mWarningReporter);
528 return reporter->ReportSecurityMessage(aMessageTag, aMessageCategory);
529 }
530 return HttpBaseChannel::AddSecurityMessage(aMessageTag, aMessageCategory);
531}
532
533NS_IMETHODIMPnsresult
534nsHttpChannel::LogBlockedCORSRequest(const nsAString& aMessage,
535 const nsACString& aCategory,
536 bool aIsWarning) {
537 if (mWarningReporter) {
538 RefPtr<HttpChannelSecurityWarningReporter> reporter(mWarningReporter);
539 return reporter->LogBlockedCORSRequest(aMessage, aCategory, aIsWarning);
540 }
541 return NS_ERROR_UNEXPECTED;
542}
543
544NS_IMETHODIMPnsresult
545nsHttpChannel::LogMimeTypeMismatch(const nsACString& aMessageName,
546 bool aWarning, const nsAString& aURL,
547 const nsAString& aContentType) {
548 if (mWarningReporter) {
549 RefPtr<HttpChannelSecurityWarningReporter> reporter(mWarningReporter);
550 return reporter->LogMimeTypeMismatch(aMessageName, aWarning, aURL,
551 aContentType);
552 }
553 return NS_ERROR_UNEXPECTED;
554}
555
556//-----------------------------------------------------------------------------
557// nsHttpChannel <private>
558//-----------------------------------------------------------------------------
559
560void nsHttpChannel::AddStorageAccessHeadersToRequest() {
561 if (!StaticPrefs::dom_storage_access_enabled() ||
562 !StaticPrefs::dom_storage_access_headers_enabled()) {
563 return;
564 }
565
566 // check if request is eligible for storage-access
567 uint32_t cookiePolicy = 0;
568 if (mLoadInfo->GetCookiePolicy(&cookiePolicy) != NS_OK) {
569 return;
570 }
571 if (cookiePolicy != nsILoadInfo::SEC_COOKIES_INCLUDE) {
572 return;
573 }
574
575 // check whether we have storage-access permission set in channel
576 nsILoadInfo::StoragePermissionState storageAccess =
577 AntiTrackingUtils::GetStoragePermissionStateInParent(this);
578
579 switch (storageAccess) {
580 case nsILoadInfo::HasStoragePermission:
581 case nsILoadInfo::StoragePermissionAllowListed:
582 SetRequestHeader(nsHttp::Sec_Fetch_Storage_Access.val(), "active"_ns,
583 false);
584 break;
585 case nsILoadInfo::InactiveStoragePermission:
586 SetRequestHeader(nsHttp::Sec_Fetch_Storage_Access.val(), "inactive"_ns,
587 false);
588 break;
589 case nsILoadInfo::DisabledStoragePermission:
590 SetRequestHeader(nsHttp::Sec_Fetch_Storage_Access.val(), "none"_ns,
591 false);
592 break;
593 case nsILoadInfo::NoStoragePermission:
594 break;
595 }
596}
597
598bool nsHttpChannel::StorageAccessReloadedChannel() {
599 return LoadStorageAccessReloadChannel();
600}
601
602void nsHttpChannel::PrimeSuspendAfterExamineResponse() {
603 mSuspendAfterExamineResponse = Some(true);
604}
605
606void nsHttpChannel::CancelSuspendOrResumeAfterExamineResponse() {
607 if (mSuspendAfterExamineResponse.isNothing()) {
608 return;
609 }
610 mSuspendAfterExamineResponse.ref() = false;
611 if (mSuspendedForExamineResponse.exchange(false)) {
612 Resume();
613 }
614}
615
616void nsHttpChannel::MaybeSuspendAfterExamineResponse() {
617 if (mSuspendAfterExamineResponse.isNothing()) {
618 return;
619 }
620 bool oldValue = mSuspendAfterExamineResponse.ref().exchange(false);
621 if (oldValue) {
622 mSuspendedForExamineResponse = true;
623 Suspend();
624 }
625}
626
627nsresult nsHttpChannel::PrepareToConnect() {
628 LOG(("nsHttpChannel::PrepareToConnect [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::PrepareToConnect [this=%p]\n", this); } } while
(0)
;
629
630 // This may be async; the dictionary headers may need to fetch an origin
631 // dictionary cache entry from disk before adding the headers. We can
632 // continue with channel creation, and just block on this being done later
633 AUTO_PROFILER_FLOW_MARKER("nsHttpHandler::AddAcceptAndDictionaryHeaders",::mozilla::AutoProfilerFlowMarker raiiObject634( "nsHttpHandler::AddAcceptAndDictionaryHeaders"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
634 NETWORK, Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject634( "nsHttpHandler::AddAcceptAndDictionaryHeaders"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
635 // AddAcceptAndDictionaryHeaders must call this->Suspend before kicking
636 // off the async operation that can result in calling the lambda (which
637 // will Resume), to avoid a race condition.
638 nsresult rv = gHttpHandler->AddAcceptAndDictionaryHeaders(
639 mURI, mLoadInfo->GetExternalContentPolicyType(), &mRequestHead, IsHTTPS(),
640 this, nsHttpChannel::StaticSuspend,
641 [self = RefPtr(this)](bool aNeedsResume, DictionaryCacheEntry* aDict) {
642 if (aNeedsResume) {
643 LOG_DICTIONARIES(("Resuming after getting Dictionary headers"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Resuming after getting Dictionary headers"
); } } while (0)
;
644 self->Resume();
645 }
646 if (!aDict) {
647 return true;
648 }
649 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added dictionary header for %p, DictionaryCacheEntry %p"
, self.get(), aDict); } } while (0)
650 ("Added dictionary header for %p, DictionaryCacheEntry %p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added dictionary header for %p, DictionaryCacheEntry %p"
, self.get(), aDict); } } while (0)
651 self.get(), aDict))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Added dictionary header for %p, DictionaryCacheEntry %p"
, self.get(), aDict); } } while (0)
;
652 AUTO_PROFILER_FLOW_MARKER(::mozilla::AutoProfilerFlowMarker raiiObject655( "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "
"Available-Dictionary", ::mozilla::baseprofiler::category::NETWORK
, Flow::FromPointer(self))
653 "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "::mozilla::AutoProfilerFlowMarker raiiObject655( "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "
"Available-Dictionary", ::mozilla::baseprofiler::category::NETWORK
, Flow::FromPointer(self))
654 "Available-Dictionary",::mozilla::AutoProfilerFlowMarker raiiObject655( "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "
"Available-Dictionary", ::mozilla::baseprofiler::category::NETWORK
, Flow::FromPointer(self))
655 NETWORK, Flow::FromPointer(self))::mozilla::AutoProfilerFlowMarker raiiObject655( "nsHttpHandler::AddAcceptAndDictionaryHeaders Add "
"Available-Dictionary", ::mozilla::baseprofiler::category::NETWORK
, Flow::FromPointer(self))
;
656 // These need to be set before calling prefetch
657 self->mDictDecompress = aDict;
658 self->mDictDecompress->InUse();
659 self->mUsingDictionary = true;
660 // If this fails, we won't add the dictionary and the
661 // Available-Dictionary header.
662 RefPtr<LoadContextInfo> lci = GetLoadContextInfo(self);
663 if (NS_SUCCEEDED(aDict->Prefetch(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
664 lci, self->mShouldSuspendForDictionary,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
665 [self](nsresult aResult) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
666 // this is called when the prefetch is complete to((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
667 // un-Suspend the channel((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
668 PROFILER_MARKER("Dictionary Prefetch", NETWORK,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
669 MarkerTiming::IntervalEnd(), FlowMarker,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
670 Flow::FromPointer(self));((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
671 if (NS_FAILED(aResult)) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
672 LOG(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
673 ("nsHttpChannel::SetupChannelForTransaction [this=%p] "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
674 "Dictionary prefetch failed: 0x%08" PRIx32,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
675 self.get(), static_cast<uint32_t>(aResult)));((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
676 if (self->mUsingDictionary) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
677 self->mDictDecompress->UseCompleted();((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
678 self->mUsingDictionary = false;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
679 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
680 self->mDictDecompress = nullptr;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
681 if (self->mSuspendedForDictionary) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
682 self->mSuspendedForDictionary = false;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
683 self->Cancel(aResult);((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
684 self->Resume();((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
685 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
686 return;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
687 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
688 if (!self->mDictDecompress) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
689 // The request already completed and released the dictionary((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
690 // (SetDecompressDictionary(nullptr) from the compress((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
691 // converter's OnStopRequest) before this async prefetch((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
692 // callback ran. Nothing left to resume.((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
693 return;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
694 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
695 MOZ_ASSERT(self->mDictDecompress->DictionaryReady());((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
696 if (self->mSuspendedForDictionary) {((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
697 LOG(((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
698 ("nsHttpChannel::SetupChannelForTransaction [this=%p] "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
699 "Resuming channel "((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
700 "suspended for Dictionary",((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
701 self.get()));((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
702 self->mSuspendedForDictionary = false;((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
703 self->Resume();((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
704 }((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
705 }))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aDict->Prefetch
( lci, self->mShouldSuspendForDictionary, [self](nsresult aResult
) { do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalEnd(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false); if (
((bool)(__builtin_expect(!!(NS_FAILED_impl(aResult)), 0)))) {
do { const ::mozilla::LogModule* moz_real_module = mozilla::
net::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p] " "Dictionary prefetch failed: 0x%08"
"x", self.get(), static_cast<uint32_t>(aResult)); } } while
(0); if (self->mUsingDictionary) { self->mDictDecompress
->UseCompleted(); self->mUsingDictionary = false; } self
->mDictDecompress = nullptr; if (self->mSuspendedForDictionary
) { self->mSuspendedForDictionary = false; self->Cancel
(aResult); self->Resume(); } return; } if (!self->mDictDecompress
) { return; } do { static_assert( mozilla::detail::AssertionConditionType
<decltype(self->mDictDecompress->DictionaryReady())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(self->mDictDecompress->DictionaryReady()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("self->mDictDecompress->DictionaryReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 695
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 695); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); if (self->
mSuspendedForDictionary) { do { const ::mozilla::LogModule* moz_real_module
= mozilla::net::gHttpLog; if ((__builtin_expect(!!(mozilla::
detail::log_test(moz_real_module, mozilla::LogLevel::Verbose)
), 0))) { mozilla::detail::log_print(moz_real_module, mozilla
::LogLevel::Verbose, "nsHttpChannel::SetupChannelForTransaction [this=%p] "
"Resuming channel " "suspended for Dictionary", self.get());
} } while (0); self->mSuspendedForDictionary = false; self
->Resume(); } }))), 1)))
) {
706 PROFILER_MARKER("Dictionary Prefetch", NETWORK,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalStart(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false)
707 MarkerTiming::IntervalStart(), FlowMarker,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalStart(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false)
708 Flow::FromPointer(self))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Dictionary Prefetch", ::geckoprofiler::category::NETWORK, MarkerTiming
::IntervalStart(), ::geckoprofiler::markers::FlowMarker{}, Flow
::FromPointer(self)); } } while (false); } while (false)
;
709 return true;
710 }
711 // Need to undo these if we're not going to be able to use the dict
712 self->mDictDecompress->UseCompleted();
713 self->mDictDecompress = nullptr;
714 self->mUsingDictionary = false;
715 LOG_DICTIONARIES(("** Prefetch failed!!!!"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "** Prefetch failed!!!!"
); } } while (0)
;
716 return false;
717 });
718 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
719
720 // notify "http-on-modify-request-before-cookies" observers
721 gHttpHandler->OnModifyRequestBeforeCookies(this);
722
723 if (mStaleRevalidation) {
724 // This is a revalidating channel.
725 // The cookies (user set cookies + cookies from the cookeservice) are
726 // already copied to the request headers when opening this channel in
727 // PerformBackgroundCacheRevalidationNow().
728 } else {
729 AddCookiesToRequest();
730 }
731
732#if defined(XP_WIN) || defined(XP_MACOSX)
733
734 auto prefEnabledForCurrentContainer = [&]() {
735 uint32_t containerId = mLoadInfo->GetOriginAttributes().mUserContextId;
736 // Make sure that the default container ID is 0
737 static_assert(nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID == 0);
738
739 nsAutoCString prefName;
740# ifdef XP_WIN
741 prefName = nsPrintfCString("network.http.windows-sso.container-enabled.%u",
742 containerId);
743# endif
744
745# ifdef XP_MACOSX
746 prefName = nsPrintfCString(
747 "network.http.microsoft-entra-sso.container-enabled.%u", containerId);
748# endif
749
750 bool enabled = false;
751 Preferences::GetBool(prefName.get(), &enabled);
752
753 LOG(("Pref for %s is %d\n", prefName.get(), enabled))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Pref for %s is %d\n", prefName.get(), enabled); } } while (
0)
;
754
755 return enabled;
756 };
757
758 auto deviceOnlyForCurrentContainer = [&]() {
759 uint32_t containerId = mLoadInfo->GetOriginAttributes().mUserContextId;
760 bool deviceOnly = Preferences::GetBool(
761 nsPrintfCString("network.http.microsoft-entra-sso.device-only.%u",
762 containerId)
763 .get(),
764 StaticPrefs::network_http_microsoft_entra_sso_device_only());
765
766 LOG(("Device-only for container %u is %d\n", containerId, deviceOnly))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Device-only for container %u is %d\n", containerId, deviceOnly
); } } while (0)
;
767
768 return deviceOnly;
769 };
770
771#endif // defined(XP_WIN) || defined(XP_MACOSX)
772
773#ifdef XP_WIN
774
775 // If Windows 10 SSO is enabled, we potentially add auth
776 // information to secure top level loads (DOCUMENTs) and iframes
777 // (SUBDOCUMENTs) that aren't anonymous or private browsing.
778 if (StaticPrefs::network_http_windows_sso_enabled() && IsHTTPS() &&
779 !(mLoadFlags & LOAD_ANONYMOUS) && !mPrivateBrowsing) {
780 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
781 if ((type == ExtContentPolicy::TYPE_DOCUMENT ||
782 type == ExtContentPolicy::TYPE_SUBDOCUMENT) &&
783 prefEnabledForCurrentContainer()) {
784 AddWindowsSSO(this, deviceOnlyForCurrentContainer());
785 }
786 }
787#endif
788
789#ifdef XP_MACOSX
790
791 auto isUriMSAuthority = [&]() {
792 nsAutoCString endPoint;
793 nsresult rv = mURI->GetHost(endPoint);
794 if (!NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
795 return false;
796 }
797 LOG(("endPoint is %s\n", endPoint.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "endPoint is %s\n", endPoint.get()); } } while (0)
;
798
799 return gHttpHandler->IsHostMSAuthority(endPoint);
800 };
801
802 // If macOS SSO is enabled, we potentially add auth
803 // information to secure top level loads (DOCUMENTs) and iframes
804 // (SUBDOCUMENTs) that aren't anonymous or private browsing.
805 if (StaticPrefs::network_http_microsoft_entra_sso_enabled() && IsHTTPS() &&
806 !(mLoadFlags & LOAD_ANONYMOUS) && !mPrivateBrowsing) {
807 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
808 if ((type == ExtContentPolicy::TYPE_DOCUMENT ||
809 type == ExtContentPolicy::TYPE_SUBDOCUMENT) &&
810 prefEnabledForCurrentContainer() && isUriMSAuthority()) {
811 nsMainThreadPtrHandle<nsHttpChannel> self(
812 new nsMainThreadPtrHolder<nsHttpChannel>(
813 "nsHttpChannel::PrepareToConnect::self", this));
814 auto resultCallback = [self(self)]() {
815 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 815
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 815); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
816 nsresult rv = self->ContinuePrepareToConnect();
817 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
818 self->CloseCacheEntry(false);
819 (void)self->AsyncAbort(rv);
820 }
821 };
822
823 nsresult rv = AddMicrosoftEntraSSO(this, deviceOnlyForCurrentContainer(),
824 std::move(resultCallback));
825
826 // Returns NS_OK if performRequests is called in MicrosoftEntraSSOUtils
827 // This temporarily stops the channel setup for the delegate.
828 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
829 return rv;
830 }
831 }
832 }
833
834#endif
835
836 return ContinuePrepareToConnect();
837}
838
839nsresult nsHttpChannel::ContinuePrepareToConnect() {
840 // notify "http-on-modify-request" observers
841 CallOnModifyRequestObservers();
842
843 return CallOrWaitForResume(
844 [](auto* self) { return self->OnBeforeConnect(); });
845}
846
847void nsHttpChannel::HandleContinueCancellingByURLClassifier(
848 nsresult aErrorCode) {
849 MOZ_ASSERT(ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ChannelClassifierUtils::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(ChannelClassifierUtils::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 849
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 849); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
850 MOZ_ASSERT(!mCallOnResume, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCallOnResume)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCallOnResume))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mCallOnResume"
" (" "How did that happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 850); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
851
852 if (mSuspendCount) {
853 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume HandleContinueCancellingByURLClassifier "
"[this=%p]\n", this); } } while (0)
854 ("Waiting until resume HandleContinueCancellingByURLClassifier "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume HandleContinueCancellingByURLClassifier "
"[this=%p]\n", this); } } while (0)
855 "[this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume HandleContinueCancellingByURLClassifier "
"[this=%p]\n", this); } } while (0)
856 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume HandleContinueCancellingByURLClassifier "
"[this=%p]\n", this); } } while (0)
;
857 mCallOnResume = [aErrorCode](nsHttpChannel* self) {
858 self->HandleContinueCancellingByURLClassifier(aErrorCode);
859 return NS_OK;
860 };
861 return;
862 }
863
864 LOG(("nsHttpChannel::HandleContinueCancellingByURLClassifier [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::HandleContinueCancellingByURLClassifier [this=%p]\n"
, this); } } while (0)
865 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::HandleContinueCancellingByURLClassifier [this=%p]\n"
, this); } } while (0)
;
866 ContinueCancellingByURLClassifier(aErrorCode);
867}
868
869void nsHttpChannel::SetPriorityHeader() {
870 nsAutoCString userSetPriority;
871 (void)GetRequestHeader("Priority"_ns, userSetPriority);
872 if (!userSetPriority.IsEmpty()) {
873 // If the Priority header is set by the user, do not override it.
874 return;
875 }
876
877 uint8_t urgency =
878 nsHttpHandler::UrgencyFromCoSFlags(mClassOfService.Flags(), mPriority);
879 bool incremental = mClassOfService.Incremental();
880
881 nsPrintfCString value(
882 "%s", urgency != 3 ? nsPrintfCString("u=%d", urgency).get() : "");
883
884 if (incremental) {
885 if (!value.IsEmpty()) {
886 value.Append(", ");
887 }
888 value.Append("i");
889 }
890
891 if (!value.IsEmpty()) {
892 SetRequestHeader("Priority"_ns, value, false);
893 }
894}
895
896nsresult nsHttpChannel::OnBeforeConnect() {
897 nsresult rv = NS_OK;
898
899 // Check if request was cancelled during suspend AFTER on-modify-request
900 if (mCanceled) {
901 return mStatus;
902 }
903
904 // Check to see if we should redirect this channel elsewhere by
905 // nsIHttpChannel.redirectTo API request
906 if (mAPIRedirectTo) {
907 return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
908 }
909
910 // Note that we are only setting the "Upgrade-Insecure-Requests" request
911 // header for *all* navigational requests instead of all requests as
912 // defined in the spec, see:
913 // https://www.w3.org/TR/upgrade-insecure-requests/#preference
914 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
915
916 if (type == ExtContentPolicy::TYPE_DOCUMENT ||
917 type == ExtContentPolicy::TYPE_SUBDOCUMENT) {
918 rv = SetRequestHeader("Upgrade-Insecure-Requests"_ns, "1"_ns, false);
919 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 919); return rv; } } while (false)
;
920 }
921
922 if (LoadAuthRedirectedChannel()) {
923 // This channel is a result of a redirect due to auth retry
924 // We have already checked for HSTS upgarde in the redirecting channel.
925 // We can safely skip those checks
926 return ContinueOnBeforeConnect(false, rv);
927 }
928
929 SecFetch::AddSecFetchHeader(this);
930
931 // Check to see if we should redirect this channel to the unstripped URI. To
932 // revert the query stripping if the loading channel is in the content
933 // blocking allow list.
934 if (ContentBlockingAllowList::Check(this)) {
935 nsCOMPtr<nsIURI> unstrippedURI;
936 mLoadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
937
938 if (unstrippedURI) {
939 return AsyncCall(&nsHttpChannel::HandleAsyncRedirectToUnstrippedURI);
940 }
941 }
942
943 nsCOMPtr<nsIPrincipal> resultPrincipal;
944 if (!IsHTTPS()) {
945 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
946 this, getter_AddRefs(resultPrincipal));
947 }
948
949 // Check if we already know about the HSTS status of the host
950 nsISiteSecurityService* sss = gHttpHandler->GetSSService();
951 NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(sss)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sss" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 951); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
952 bool isSecureURI;
953 OriginAttributes originAttributes;
954 if (!StoragePrincipalHelper::GetOriginAttributesForHSTS(this,
955 originAttributes)) {
956 return NS_ERROR_FAILURE;
957 }
958 rv = sss->IsSecureURI(mURI, originAttributes, &isSecureURI);
959 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 959); return rv; } } while (false)
;
960 // Save that on the loadInfo so it can later be consumed by
961 // SecurityInfo.sys.mjs
962 mLoadInfo->SetHstsStatus(isSecureURI);
963
964 // If bypassing the cache and we're forced offline
965 // we can just return the error here.
966 if (IsForcedOffline() &&
967 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
968 return NS_ERROR_OFFLINE;
969 }
970
971 // At this point it is no longer possible to call
972 // HttpBaseChannel::UpgradeToSecure.
973 StoreUpgradableToSecure(false);
974 bool shouldUpgrade = LoadUpgradeToSecure();
975 if (mURI->SchemeIs("http")) {
976 OriginAttributes originAttributes;
977 if (!StoragePrincipalHelper::GetOriginAttributesForHSTS(this,
978 originAttributes)) {
979 return NS_ERROR_FAILURE;
980 }
981
982 if (!shouldUpgrade) {
983 // Make sure http channel is released on main thread.
984 // See bug 1539148 for details.
985 nsMainThreadPtrHandle<nsHttpChannel> self(
986 new nsMainThreadPtrHolder<nsHttpChannel>(
987 "nsHttpChannel::OnBeforeConnect::self", this));
988 auto resultCallback = [self(self)](bool aResult, nsresult aStatus) {
989 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 989
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 989); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
990
991 nsresult rv = self->MaybeUseHTTPSRRForUpgrade(aResult, aStatus);
992 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
993 self->CloseCacheEntry(false);
994 (void)self->AsyncAbort(rv);
995 }
996 };
997
998 bool willCallback = false;
999 rv = NS_ShouldSecureUpgrade(mURI, mLoadInfo, this, resultPrincipal,
1000 LoadAllowSTS(), originAttributes,
1001 shouldUpgrade, std::move(resultCallback),
1002 willCallback);
1003 // If the request gets upgraded because of the HTTPS-Only mode, but no
1004 // event listener has been registered so far, we want to do that here.
1005 uint32_t httpOnlyStatus = mLoadInfo->GetHttpsOnlyStatus();
1006 if (httpOnlyStatus &
1007 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED) {
1008 RefPtr<nsHTTPSOnlyStreamListener> httpsOnlyListener =
1009 new nsHTTPSOnlyStreamListener(mListener, mLoadInfo);
1010 mListener = httpsOnlyListener;
1011
1012 httpOnlyStatus ^=
1013 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED;
1014 httpOnlyStatus |= nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED;
1015 mLoadInfo->SetHttpsOnlyStatus(httpOnlyStatus);
1016 }
1017 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnBeforeConnect " "[this=%p willCallback=%d rv=%"
"x" "]\n", this, willCallback, static_cast<uint32_t>(rv
)); } } while (0)
1018 ("nsHttpChannel::OnBeforeConnect "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnBeforeConnect " "[this=%p willCallback=%d rv=%"
"x" "]\n", this, willCallback, static_cast<uint32_t>(rv
)); } } while (0)
1019 "[this=%p willCallback=%d rv=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnBeforeConnect " "[this=%p willCallback=%d rv=%"
"x" "]\n", this, willCallback, static_cast<uint32_t>(rv
)); } } while (0)
1020 this, willCallback, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnBeforeConnect " "[this=%p willCallback=%d rv=%"
"x" "]\n", this, willCallback, static_cast<uint32_t>(rv
)); } } while (0)
;
1021
1022 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || MOZ_UNLIKELY(willCallback)(__builtin_expect(!!(willCallback), 0))) {
1023 return rv;
1024 }
1025 }
1026 }
1027
1028 return MaybeUseHTTPSRRForUpgrade(shouldUpgrade, NS_OK);
1029}
1030
1031// Returns true if the network connectivity checker indicated
1032// that HTTPS records can be resolved on this network - false otherwise.
1033// When TRR is enabled, we always return true, as resolving HTTPS
1034// records don't depend on the network.
1035static bool canUseHTTPSRRonNetwork(bool& aTRREnabled) {
1036 // Respect the pref.
1037 if (StaticPrefs::network_dns_force_use_https_rr()) {
1038 aTRREnabled = true;
1039 return true;
1040 }
1041
1042 aTRREnabled = false;
1043
1044 if (nsCOMPtr<nsIDNSService> dns = mozilla::components::DNS::Service()) {
1045 nsIDNSService::ResolverMode mode;
1046 // If the browser is currently using TRR/DoH, then it can
1047 // definitely resolve HTTPS records.
1048 if (NS_SUCCEEDED(dns->GetCurrentTrrMode(&mode))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dns->GetCurrentTrrMode
(&mode))), 1)))
) {
1049 if (mode == nsIDNSService::MODE_TRRFIRST) {
1050 RefPtr<TRRService> trr = TRRService::Get();
1051 if (trr && trr->IsConfirmed()) {
1052 aTRREnabled = true;
1053 }
1054 } else if (mode == nsIDNSService::MODE_TRRONLY) {
1055 aTRREnabled = true;
1056 }
1057 if (aTRREnabled) {
1058 return true;
1059 }
1060 }
1061 }
1062
1063 // With Happy Eyeballs enabled we can allow native HTTPS RR queries: HE's
1064 // resolution-delay timer lets connection attempts proceed using the A/AAAA
1065 // results even when the native HTTPS RR lookup is slow or blocked.
1066 if (StaticPrefs::network_http_happy_eyeballs_enabled()) {
1067 return true;
1068 }
1069
1070 if (RefPtr<NetworkConnectivityService> ncs =
1071 NetworkConnectivityService::GetSingleton()) {
1072 nsINetworkConnectivityService::ConnectivityState state;
1073 if (NS_SUCCEEDED(ncs->GetDNS_HTTPS(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetDNS_HTTPS
(&state))), 1)))
&&
1074 state == nsINetworkConnectivityService::NOT_AVAILABLE) {
1075 return false;
1076 }
1077 }
1078 return true;
1079}
1080
1081nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade,
1082 nsresult aStatus) {
1083 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
1084 return aStatus;
1085 }
1086
1087 bool forceOffline = IsForcedOffline();
1088
1089 if (IsHTTPS() || aShouldUpgrade || !LoadUseHTTPSSVC() || forceOffline) {
1090 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
1091 }
1092
1093 auto shouldSkipUpgradeWithHTTPSRR = [&]() -> bool {
1094 if (mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) {
1095 return true;
1096 }
1097
1098 // Skip using HTTPS RR to upgrade when this is not a top-level load and the
1099 // loading principal is http.
1100 if ((mLoadInfo->GetExternalContentPolicyType() !=
1101 ExtContentPolicy::TYPE_DOCUMENT) &&
1102 (mLoadInfo->GetLoadingPrincipal() &&
1103 mLoadInfo->GetLoadingPrincipal()->SchemeIs("http"))) {
1104 return true;
1105 }
1106
1107 // If the network connectivity checker indicates the network is
1108 // blocking HTTPS requests, then we should skip them so we don't
1109 // needlessly wait for a timeout.
1110 bool trrEnabled = false;
1111 if (!canUseHTTPSRRonNetwork(trrEnabled)) {
1112 return true;
1113 }
1114
1115 // Don't block the channel when TRR is not used.
1116 if (!trrEnabled) {
1117 return true;
1118 }
1119
1120 auto dnsStrategy = ComputeProxyDNSStrategy();
1121 if (dnsStrategy != nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN) {
1122 return true;
1123 }
1124
1125 nsAutoCString uriHost;
1126 mURI->GetAsciiHost(uriHost);
1127
1128 return gHttpHandler->IsHostExcludedForHTTPSRR(uriHost);
1129 };
1130
1131 if (shouldSkipUpgradeWithHTTPSRR()) {
1132 StoreUseHTTPSSVC(false);
1133 // If the website does not want to use HTTPS RR, we should set
1134 // NS_HTTP_DISALLOW_HTTPS_RR. This is for avoiding HTTPS RR being used by
1135 // the transaction.
1136 DisallowHTTPSRR(mCaps);
1137 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
1138 }
1139
1140 if (mHTTPSSVCRecord.isSome()) {
1141 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] mHTTPSSVCRecord is some"
, this); } } while (0)
1142 "nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] mHTTPSSVCRecord is some",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] mHTTPSSVCRecord is some"
, this); } } while (0)
1143 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] mHTTPSSVCRecord is some"
, this); } } while (0)
;
1144 StoreWaitHTTPSSVCRecord(false);
1145 bool hasHTTPSRR = (mHTTPSSVCRecord.ref() != nullptr);
1146 return ContinueOnBeforeConnect(hasHTTPSRR, aStatus, hasHTTPSRR);
1147 }
1148
1149 LOG(("nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] wait for HTTPS RR",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] wait for HTTPS RR"
, this); } } while (0)
1150 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeUseHTTPSRRForUpgrade [%p] wait for HTTPS RR"
, this); } } while (0)
;
1151
1152 OriginAttributes originAttributes;
1153 StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(this, originAttributes);
1154
1155 RefPtr<nsDNSPrefetch> resolver =
1156 new nsDNSPrefetch(mURI, originAttributes, nsIRequest::GetTRRMode());
1157 nsWeakPtr weakPtrThis(
1158 do_GetWeakReference(static_cast<nsIHttpChannel*>(this)));
1159 nsresult rv = resolver->FetchHTTPSSVC(
1160 mCaps & NS_HTTP_REFRESH_DNS(1 << 3), !LoadUseHTTPSSVC(),
1161 [weakPtrThis](nsIDNSHTTPSSVCRecord* aRecord) {
1162 nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(weakPtrThis);
1163 RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(channel);
1164 if (httpChannelImpl) {
1165 httpChannelImpl->OnHTTPSRRAvailable(aRecord);
1166 }
1167 });
1168 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1169 LOG((" FetchHTTPSSVC failed with 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " FetchHTTPSSVC failed with 0x%08" "x", static_cast<uint32_t
>(rv)); } } while (0)
1170 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " FetchHTTPSSVC failed with 0x%08" "x", static_cast<uint32_t
>(rv)); } } while (0)
;
1171 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
1172 }
1173
1174 StoreWaitHTTPSSVCRecord(true);
1175 return NS_OK;
1176}
1177
1178nsresult nsHttpChannel::ContinueOnBeforeConnect(bool aShouldUpgrade,
1179 nsresult aStatus,
1180 bool aUpgradeWithHTTPSRR) {
1181 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnBeforeConnect " "[this=%p aShouldUpgrade=%d rv=%"
"x" "]\n", this, aShouldUpgrade, static_cast<uint32_t>
(aStatus)); } } while (0)
1182 ("nsHttpChannel::ContinueOnBeforeConnect "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnBeforeConnect " "[this=%p aShouldUpgrade=%d rv=%"
"x" "]\n", this, aShouldUpgrade, static_cast<uint32_t>
(aStatus)); } } while (0)
1183 "[this=%p aShouldUpgrade=%d rv=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnBeforeConnect " "[this=%p aShouldUpgrade=%d rv=%"
"x" "]\n", this, aShouldUpgrade, static_cast<uint32_t>
(aStatus)); } } while (0)
1184 this, aShouldUpgrade, static_cast<uint32_t>(aStatus)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnBeforeConnect " "[this=%p aShouldUpgrade=%d rv=%"
"x" "]\n", this, aShouldUpgrade, static_cast<uint32_t>
(aStatus)); } } while (0)
;
1185
1186 MOZ_ASSERT(!LoadWaitHTTPSSVCRecord())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadWaitHTTPSSVCRecord())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadWaitHTTPSSVCRecord())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadWaitHTTPSSVCRecord()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 1186
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadWaitHTTPSSVCRecord()"
")"); do { MOZ_CrashSequence(__null, 1186); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1187
1188 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
1189 return aStatus;
1190 }
1191
1192 if (aShouldUpgrade && !IsHTTPS()) {
1193 // only set HTTPS_RR to be responsbile for the upgrade in the loadinfo
1194 // if it actually was responsible, otherwise the correct flag is
1195 // already present in the loadinfo.
1196 if (aUpgradeWithHTTPSRR) {
1197 mLoadInfo->SetHttpsUpgradeTelemetry(nsILoadInfo::HTTPS_RR);
1198 NS_LogSecureUpgradeToConsole(mURI, mLoadInfo, this, "HTTPS RR"_ns);
1199 }
1200 return AsyncCall(&nsHttpChannel::HandleAsyncRedirectChannelToHttps);
1201 }
1202
1203 // ensure that we are using a valid hostname
1204 if (!net_IsValidDNSHost(nsDependentCString(mConnectionInfo->Origin()))) {
1205 return NS_ERROR_UNKNOWN_HOST;
1206 }
1207
1208 if (mUpgradeProtocolCallback) {
1209 // Websockets can run over HTTP/2, but other upgrades can't.
1210 if (mUpgradeProtocol.EqualsLiteral("websocket") &&
1211 StaticPrefs::network_http_http2_websockets()) {
1212 // Need to tell the conn manager that we're ok with http/2 even with
1213 // the allow keepalive bit not set. That bit needs to stay off,
1214 // though, in case we end up having to fallback to http/1.1 (where
1215 // we absolutely do want to disable keepalive).
1216 mCaps |= NS_HTTP_ALLOW_SPDY_WITHOUT_KEEPALIVE(1 << 15);
1217 } else {
1218 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
1219 }
1220 // Upgrades cannot use HTTP/3 -- extended CONNECT can't be issued before the
1221 // peer's SETTINGS are known. A MASQUE proxy is the exception: its outer hop
1222 // *is* HTTP/3 (CONNECT-UDP) and the upgrade rides the inner tunnel, so
1223 // disallowing h3 leaves only a TCP attempt against a QUIC-only port, which
1224 // can never connect. Only Happy Eyeballs dispatches the upgrade onto that
1225 // tunnel, so the exception is tied to the same pref. Keep Http3Allowed() in
1226 // sync.
1227 bool masqueProxy =
1228 mProxyInfo &&
1229 static_cast<nsProxyInfo*>(mProxyInfo.get())->IsHttp3Proxy() &&
1230 StaticPrefs::network_http_happy_eyeballs_proxy_enabled();
1231 if (!masqueProxy) {
1232 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
1233 }
1234 // NS_HTTP_STICKY_CONNECTION breaks the (non-Happy-Eyeballs) HTTPS RR
1235 // fallback mechanism, which restarts the transaction to fall back. Happy
1236 // Eyeballs instead races endpoints (honoring the HTTPS RR port, hints and
1237 // ALPN) and dispatches the sticky upgrade onto the winner with no restart,
1238 // so it can safely use HTTPS RR. Without Happy Eyeballs, upgrades can only
1239 // use HTTPS RR when nsHttpTransaction is allowed to restart them for the
1240 // HTTPS RR fallback.
1241 if (!(mCaps & NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30)) &&
1242 !StaticPrefs::network_http_upgrade_use_https_rr()) {
1243 DisallowHTTPSRR(mCaps);
1244 }
1245 }
1246
1247 if (LoadIsTRRServiceChannel()) {
1248 mCaps |= NS_HTTP_LARGE_KEEPALIVE(1 << 1);
1249 DisallowHTTPSRR(mCaps);
1250 }
1251
1252 if (mTransactionSticky) {
1253 MOZ_ASSERT(LoadAuthRedirectedChannel())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadAuthRedirectedChannel())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadAuthRedirectedChannel())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("LoadAuthRedirectedChannel()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 1253
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadAuthRedirectedChannel()"
")"); do { MOZ_CrashSequence(__null, 1253); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1254 // this means this is a redirected channel channel due to auth retry and a
1255 // connection based auth scheme was used
1256 // we have a reference to the old-transaction with sticky connection which
1257 // we need to use
1258 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
1259 }
1260
1261 mCaps |= NS_HTTP_TRR_FLAGS_FROM_MODE(nsIRequest::GetTRRMode())((static_cast<uint32_t>(nsIRequest::GetTRRMode()) &
3) << 19)
;
1262
1263 // Finalize ConnectionInfo flags before SpeculativeConnect
1264 mConnectionInfo =
1265 mConnectionInfo->Mutate()
1266 .SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0)
1267 .SetPrivate(mPrivateBrowsing)
1268 .SetNoSpdy(mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7))
1269 .SetBeConservative((mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) ||
1270 LoadBeConservative())
1271 .SetTlsFlags(mTlsFlags)
1272 .SetIsTrrServiceChannel(LoadIsTRRServiceChannel())
1273 .SetTRRMode(nsIRequest::GetTRRMode())
1274 .SetIPv4Disabled(mCaps & NS_HTTP_DISABLE_IPV4(1 << 17))
1275 .SetIPv6Disabled(mCaps & NS_HTTP_DISABLE_IPV6(1 << 18))
1276 .SetHttp3Policy((mCaps & NS_HTTP_DISALLOW_HTTP3(1 << 21))
1277 ? Http3Policy::Disabled
1278 : Http3Policy::Allowed)
1279 .SetAnonymousAllowClientCert(
1280 (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) != 0)
1281 .Finalize();
1282
1283 if (mWebTransportSessionEventListener) {
1284 nsTArray<RefPtr<nsIWebTransportHash>> aServerCertHashes;
1285 nsresult rv;
1286 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
1287 do_QueryInterface(mWebTransportSessionEventListener, &rv);
1288 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1288); return rv; } } while (false)
;
1289
1290 wtconSettings->GetServerCertificateHashes(aServerCertHashes);
1291 gHttpHandler->ConnMgr()->StoreServerCertHashes(
1292 mConnectionInfo, gHttpHandler->IsHttp2Excluded(mConnectionInfo),
1293 !Http3Allowed(), std::move(aServerCertHashes));
1294 }
1295
1296 if (ShouldIntercept()) {
1297 return RedirectToInterceptedChannel();
1298 }
1299
1300 // notify "http-on-before-connect" observers
1301 gHttpHandler->OnBeforeConnect(this);
1302
1303 return CallOrWaitForResume([](auto* self) { return self->Connect(); });
1304}
1305
1306class MOZ_STACK_CLASS AddResponseHeadersToResponseHead final
1307 : public nsIHttpHeaderVisitor {
1308 public:
1309 explicit AddResponseHeadersToResponseHead(nsHttpResponseHead* aResponseHead)
1310 : mResponseHead(aResponseHead) {}
1311
1312 NS_IMETHODvirtual nsresult VisitHeader(const nsACString& aHeader,
1313 const nsACString& aValue) override {
1314 nsAutoCString headerLine = aHeader + ": "_ns + aValue;
1315 DebugOnly<nsresult> rv = mResponseHead->ParseHeaderLine(headerLine);
1316 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1316); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1317
1318 return NS_OK;
1319 }
1320
1321 NS_IMETHODvirtual nsresult QueryInterface(REFNSIIDconst nsIID& aIID, void** aInstancePtr) override;
1322
1323 // Stub AddRef/Release since this is a stack class.
1324 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType AddRef(void) override {
1325 return ++mRefCnt;
1326 }
1327
1328 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType Release(void) override {
1329 return --mRefCnt;
1330 }
1331
1332 virtual ~AddResponseHeadersToResponseHead() {
1333 MOZ_DIAGNOSTIC_ASSERT(mRefCnt == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRefCnt == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRefCnt == 0))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mRefCnt == 0", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1333); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mRefCnt == 0"
")"); do { MOZ_CrashSequence(__null, 1333); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1334 }
1335
1336 private:
1337 nsHttpResponseHead* mResponseHead;
1338
1339 nsrefcnt mRefCnt = 0;
1340};
1341
1342NS_IMPL_QUERY_INTERFACE(AddResponseHeadersToResponseHead, nsIHttpHeaderVisitor)nsresult AddResponseHeadersToResponseHead::QueryInterface(const
nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1342); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<AddResponseHeadersToResponseHead, nsIHttpHeaderVisitor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIHttpHeaderVisitor
*>((AddResponseHeadersToResponseHead*)0x1000)) - reinterpret_cast
<char*>((AddResponseHeadersToResponseHead*)0x1000))}, {
&mozilla::detail::kImplementedIID<AddResponseHeadersToResponseHead
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIHttpHeaderVisitor*>
((AddResponseHeadersToResponseHead*)0x1000))) - reinterpret_cast
<char*>((AddResponseHeadersToResponseHead*)0x1000))}, {
nullptr, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
1343
1344nsresult nsHttpChannel::HandleOverrideResponse() {
1345 // Start building a response with the data from mOverrideResponse.
1346 mResponseHead = std::make_unique<nsHttpResponseHead>();
1347
1348 // Apply override response status code and status text.
1349 uint32_t statusCode;
1350 nsresult rv = mOverrideResponse->GetResponseStatus(&statusCode);
1351 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1351); return rv; } } while (false)
;
1352
1353 nsAutoCString statusText;
1354 rv = mOverrideResponse->GetResponseStatusText(statusText);
1355 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1355); return rv; } } while (false)
;
1356
1357 // Hardcoding protocol HTTP/1.1
1358 nsPrintfCString line("HTTP/1.1 %u %s", statusCode, statusText.get());
1359 rv = mResponseHead->ParseStatusLine(line);
1360 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1360); return rv; } } while (false)
;
1361
1362 // Apply override response headers.
1363 AddResponseHeadersToResponseHead visitor(mResponseHead.get());
1364 rv = mOverrideResponse->VisitResponseHeaders(&visitor);
1365 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1365); return rv; } } while (false)
;
1366
1367 // This block parses the cookie header, collects any cookie changes,
1368 // and sends them to the parent actor.
1369 {
1370 RefPtr<HttpChannelParent> httpParent;
1371 RefPtr<CookieObserver> cookieObserver;
1372
1373 CookieServiceParent::CookieProcessingGuard cookieProcessingGuard;
1374 MaybeInitializeCookieProcessingGuard(
1375 this, cookieProcessingGuard, cookieObserver, httpParent, statusCode);
1376
1377 // Handle Set-Cookie headers as if the response was from networking.
1378 CookieVisitor cookieVisitor(mResponseHead.get());
1379 SetCookieHeaders(cookieVisitor.CookieHeaders());
1380
1381 if (cookieObserver) {
1382 nsTArray<CookieChange> cookieChanges;
1383 cookieObserver->StealChanges(cookieChanges);
1384
1385 if (!cookieChanges.IsEmpty()) {
1386 MOZ_ASSERT(httpParent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(httpParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(httpParent))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("httpParent", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpParent"
")"); do { MOZ_CrashSequence(__null, 1386); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1387 httpParent->SetCookieChanges(std::move(cookieChanges));
1388 }
1389 }
1390 }
1391
1392 rv = ProcessWAICTHeader();
1393 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1394 return rv;
1395 }
1396
1397 if (NS_FAILED(ProcessSecurityHeaders())((bool)(__builtin_expect(!!(NS_FAILED_impl(ProcessSecurityHeaders
())), 0)))
) {
1398 NS_WARNING("ProcessSecurityHeaders failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSecurityHeaders failed, continuing load."
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1398)
;
1399 }
1400
1401 if ((statusCode < 500) && (statusCode != 421)) {
1402 ProcessAltService();
1403 }
1404
1405 if (WillRedirect(*mResponseHead)) {
1406 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
1407 // to avoid event dispatching latency.
1408 LOG(("Skipping read of overridden response redirect entity\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Skipping read of overridden response redirect entity\n"); }
} while (0)
;
1409 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
1410 }
1411
1412 nsAutoCString body;
1413 rv = mOverrideResponse->GetResponseBody(body);
1414 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1414); return rv; } } while (false)
;
1415
1416 nsCOMPtr<nsIInputStream> stringStream;
1417 rv = NS_NewCStringInputStream(getter_AddRefs(stringStream), body);
1418 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1418); return rv; } } while (false)
;
1419 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), stringStream, 0, 0,
1420 true);
1421 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1422 stringStream->Close();
1423 return rv;
1424 }
1425
1426 rv = mCachePump->AsyncRead(this);
1427 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1428
1429 return NS_OK;
1430}
1431
1432nsresult nsHttpChannel::Connect() {
1433 LOG(("nsHttpChannel::Connect [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Connect [this=%p]\n", this); } } while (0)
;
1434
1435 if (mAPIRedirectTo) {
1436 LOG(("nsHttpChannel::Connect [transparent=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Connect [transparent=%d]\n", mAPIRedirectTo
->second()); } } while (0)
1437 mAPIRedirectTo->second()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Connect [transparent=%d]\n", mAPIRedirectTo
->second()); } } while (0)
;
1438
1439 nsresult rv = StartRedirectChannelToURI(
1440 mAPIRedirectTo->first(),
1441 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_PERMANENT |
1442 nsIChannelEventSink::REDIRECT_TRANSPARENT
1443 : nsIChannelEventSink::REDIRECT_PERMANENT);
1444 mAPIRedirectTo = Nothing();
1445 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1446 return NS_OK;
1447 }
1448 return NS_ERROR_FAILURE;
1449 }
1450
1451 // If mOverrideResponse is set, bypass the rest of the connection and reply
1452 // immediately with a response built using the data from mOverrideResponse.
1453 if (mOverrideResponse) {
1454 return HandleOverrideResponse();
1455 }
1456
1457 // Don't allow resuming when cache must be used
1458 if (LoadResuming() && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
1459 LOG(("Resuming from cache is not supported yet"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Resuming from cache is not supported yet"); } } while (0)
;
1460 return NS_ERROR_DOCUMENT_NOT_CACHED;
1461 }
1462
1463 // Step 8.18 of HTTP-network-or-cache fetch
1464 // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
1465 nsAutoCString rangeVal;
1466 if (NS_SUCCEEDED(GetRequestHeader("Range"_ns, rangeVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Range"_ns, rangeVal))), 1)))
) {
1467 SetRequestHeader("Accept-Encoding"_ns, "identity"_ns, false);
1468 }
1469
1470 if (mRequestHead.IsPost() || mRequestHead.IsPatch()) {
1471 // If the post id is already set then this is an attempt to replay
1472 // a post/patch transaction via the cache. Otherwise, we need a unique
1473 // post id for this transaction.
1474 if (mPostID == 0) {
1475 mPostID = gHttpHandler->GenerateUniqueID();
1476 }
1477
1478 if (StaticPrefs::network_http_idempotencyKey_enabled() &&
1479 !mRequestHead.HasHeader(nsHttp::Idempotency_Key)) {
1480 // check if we need to add
1481 // idempotency-key header
1482 // See Bug 1830022 for more details
1483 nsAutoCString key;
1484 gHttpHandler->GenerateIdempotencyKeyForPost(mPostID, mLoadInfo, key);
1485 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))
), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 1486
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
")"); do { MOZ_CrashSequence(__null, 1486); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1486 mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))
), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 1486
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
")"); do { MOZ_CrashSequence(__null, 1486); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1487 }
1488 }
1489
1490#ifdef MOZ_WIDGET_ANDROID
1491 bool val = false;
1492 if (nsIOService::ShouldAddAdditionalSearchHeaders(mURI, &val)) {
1493 SetRequestHeader("X-Search-Subdivision"_ns, val ? "1"_ns : "0"_ns, false);
1494 }
1495#endif
1496
1497 bool isTrackingResource = IsThirdPartyTrackingResource();
1498 LOG(("nsHttpChannel %p tracking resource=%d, cos=%lu, inc=%d", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p tracking resource=%d, cos=%lu, inc=%d", this
, isTrackingResource, mClassOfService.Flags(), mClassOfService
.Incremental()); } } while (0)
1499 isTrackingResource, mClassOfService.Flags(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p tracking resource=%d, cos=%lu, inc=%d", this
, isTrackingResource, mClassOfService.Flags(), mClassOfService
.Incremental()); } } while (0)
1500 mClassOfService.Incremental()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p tracking resource=%d, cos=%lu, inc=%d", this
, isTrackingResource, mClassOfService.Flags(), mClassOfService
.Incremental()); } } while (0)
;
1501
1502 if (isTrackingResource) {
1503 AddClassFlags(nsIClassOfService::Tail);
1504 }
1505
1506 if (WaitingForTailUnblock()) {
1507 MOZ_DIAGNOSTIC_ASSERT(!mOnTailUnblock)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mOnTailUnblock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mOnTailUnblock))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mOnTailUnblock"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 1507
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 1507); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1508 mOnTailUnblock = &nsHttpChannel::ConnectOnTailUnblock;
1509 return NS_OK;
1510 }
1511
1512 return ConnectOnTailUnblock();
1513}
1514
1515nsresult nsHttpChannel::ConnectOnTailUnblock() {
1516 nsresult rv;
1517
1518 LOG(("nsHttpChannel::ConnectOnTailUnblock [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ConnectOnTailUnblock [this=%p]\n", this); }
} while (0)
;
1519 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ConnectOnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject1520( "nsHttpChannel::ConnectOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
1520 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject1520( "nsHttpChannel::ConnectOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
1521
1522 // Consider opening a TCP connection right away.
1523 SpeculativeConnect();
1524
1525 // open a cache entry for this channel...
1526 rv = OpenCacheEntry(IsHTTPS());
1527
1528 // do not continue if asyncOpenCacheEntry is in progress
1529 if (AwaitingCacheCallbacks()) {
1530 LOG(("nsHttpChannel::Connect %p AwaitingCacheCallbacks forces async\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Connect %p AwaitingCacheCallbacks forces async\n"
, this); } } while (0)
1531 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Connect %p AwaitingCacheCallbacks forces async\n"
, this); } } while (0)
;
1532 MOZ_ASSERT(NS_SUCCEEDED(rv), "Unexpected state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))" " ("
"Unexpected state" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Unexpected state" ")"); do { MOZ_CrashSequence(__null
, 1532); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1533
1534 // Backstop against a wedged cache entry that never delivers its callback.
1535 MaybeStartCacheWaitTimer();
1536
1537 if (mNetworkTriggered && mWaitingForProxy) {
1538 // Someone has called TriggerNetwork(), meaning we are racing the
1539 // network with the cache.
1540 mWaitingForProxy = false;
1541 return ContinueConnect();
1542 }
1543
1544 return NS_OK;
1545 }
1546
1547 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1548 LOG(("OpenCacheEntry failed [rv=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "OpenCacheEntry failed [rv=%" "x" "]\n", static_cast<uint32_t
>(rv)); } } while (0)
1549 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "OpenCacheEntry failed [rv=%" "x" "]\n", static_cast<uint32_t
>(rv)); } } while (0)
;
1550 // if this channel is only allowed to pull from the cache, then
1551 // we must fail if we were unable to open a cache entry.
1552 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1553 return NS_ERROR_DOCUMENT_NOT_CACHED;
1554 }
1555 // otherwise, let's just proceed without using the cache.
1556 }
1557
1558 return TriggerNetwork();
1559}
1560
1561nsresult nsHttpChannel::ContinueConnect() {
1562 // If we need to start a CORS preflight, do it now!
1563 // Note that it is important to do this before the early returns below.
1564 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ContinueConnect", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject1565( "nsHttpChannel::ContinueConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
1565 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject1565( "nsHttpChannel::ContinueConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
1566 if (!LoadIsCorsPreflightDone() && LoadRequireCORSPreflight()) {
1567 MOZ_ASSERT(!mPreflightChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mPreflightChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mPreflightChannel))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mPreflightChannel"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 1567
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPreflightChannel"
")"); do { MOZ_CrashSequence(__null, 1567); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1568 nsresult rv = nsCORSListenerProxy::StartCORSPreflight(
1569 this, this, mUnsafeHeaders, getter_AddRefs(mPreflightChannel));
1570 return rv;
1571 }
1572
1573 MOZ_RELEASE_ASSERT(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()" " ("
"CORS preflight must have been finished by the time we " "do the rest of ContinueConnect"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1575); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"do the rest of ContinueConnect" ")"); do { MOZ_CrashSequence
(__null, 1575); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1574 "CORS preflight must have been finished by the time we "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()" " ("
"CORS preflight must have been finished by the time we " "do the rest of ContinueConnect"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1575); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"do the rest of ContinueConnect" ")"); do { MOZ_CrashSequence
(__null, 1575); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1575 "do the rest of ContinueConnect")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()" " ("
"CORS preflight must have been finished by the time we " "do the rest of ContinueConnect"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1575); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"do the rest of ContinueConnect" ")"); do { MOZ_CrashSequence
(__null, 1575); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1576
1577 bool forceOffline = IsForcedOffline();
1578
1579 // we may or may not have a cache entry at this point
1580 if (mCacheEntry) {
1581 // read straight from the cache if possible...
1582 if (CachedContentIsValid()) {
1583 // If we're forced offline, and set to bypass the cache, return offline.
1584 if (forceOffline &&
1585 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
1586 return NS_ERROR_OFFLINE;
1587 }
1588
1589 nsRunnableMethod<nsHttpChannel>* event = nullptr;
1590 nsresult rv;
1591 if (!LoadCachedContentIsPartial()) {
1592 rv = AsyncCall(&nsHttpChannel::AsyncOnExamineCachedResponse, &event);
1593 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1594 LOG((" AsyncCall failed (%08x)", static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " AsyncCall failed (%08x)", static_cast<uint32_t>(rv
)); } } while (0)
;
1595 }
1596 }
1597 rv = ReadFromCache();
1598 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && event) {
1599 event->Revoke();
1600 }
1601
1602 AccumulateCacheHitTelemetry(kCacheHit, this);
1603 mCacheDisposition = kCacheHit;
1604
1605 return rv;
1606 }
1607 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1608 // the cache contains the requested resource, but it must be
1609 // validated before we can reuse it. since we are not allowed
1610 // to hit the net, there's nothing more to do. the document
1611 // is effectively not in the cache.
1612 LOG((" !CachedContentIsValid() && mLoadFlags & LOAD_ONLY_FROM_CACHE"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " !CachedContentIsValid() && mLoadFlags & LOAD_ONLY_FROM_CACHE"
); } } while (0)
;
1613 return NS_ERROR_DOCUMENT_NOT_CACHED;
1614 }
1615 } else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1616 LOG((" !mCacheEntry && mLoadFlags & LOAD_ONLY_FROM_CACHE"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " !mCacheEntry && mLoadFlags & LOAD_ONLY_FROM_CACHE"
); } } while (0)
;
1617 return NS_ERROR_DOCUMENT_NOT_CACHED;
1618 }
1619
1620 if (mLoadFlags & LOAD_NO_NETWORK_IO) {
1621 LOG((" mLoadFlags & LOAD_NO_NETWORK_IO"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " mLoadFlags & LOAD_NO_NETWORK_IO"); } } while (0)
;
1622 return NS_ERROR_DOCUMENT_NOT_CACHED;
1623 }
1624
1625 // We're about to hit the network. Don't if we're forced offline.
1626 if (forceOffline) {
1627 return NS_ERROR_OFFLINE;
1628 }
1629
1630 // Not served from cache, so drop any caller-set cacheReadStart.
1631 mCacheReadStart = TimeStamp();
1632
1633 // hit the net...
1634 nsresult rv = DoConnect(mTransactionSticky);
1635 mTransactionSticky = nullptr;
1636 return rv;
1637}
1638
1639nsresult nsHttpChannel::DoConnect(HttpTransactionShell* aTransWithStickyConn) {
1640 LOG(("nsHttpChannel::DoConnect [this=%p, aTransWithStickyConn=%p]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::DoConnect [this=%p, aTransWithStickyConn=%p]\n"
, this, aTransWithStickyConn); } } while (0)
1641 aTransWithStickyConn))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::DoConnect [this=%p, aTransWithStickyConn=%p]\n"
, this, aTransWithStickyConn); } } while (0)
;
1642
1643 nsresult rv = SetupChannelForTransaction();
1644 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1645 return rv;
1646 }
1647
1648 return CallOrWaitForResume(
1649 [trans = RefPtr(aTransWithStickyConn)](auto* self) {
1650 return self->DispatchTransaction(trans);
1651 });
1652}
1653
1654nsresult nsHttpChannel::DispatchTransaction(
1655 HttpTransactionShell* aTransWithStickyConn) {
1656 LOG(("nsHttpChannel::DispatchTransaction [this=%p, aTransWithStickyConn=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::DispatchTransaction [this=%p, aTransWithStickyConn=%p]"
, this, aTransWithStickyConn); } } while (0)
1657 this, aTransWithStickyConn))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::DispatchTransaction [this=%p, aTransWithStickyConn=%p]"
, this, aTransWithStickyConn); } } while (0)
;
1658 nsresult rv = InitTransaction();
1659 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1660 return rv;
1661 }
1662 if (aTransWithStickyConn) {
1663 rv = gHttpHandler->InitiateTransactionWithStickyConn(
1664 mTransaction, mPriority, aTransWithStickyConn);
1665 } else {
1666 rv = gHttpHandler->InitiateTransaction(mTransaction, mPriority);
1667 }
1668
1669 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1670 return rv;
1671 }
1672
1673 rv = mTransaction->AsyncRead(this, getter_AddRefs(mTransactionPump));
1674 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1675 // The transaction is already on the socket thread and points at our
1676 // request head; don't let it outlive us.
1677 (void)gHttpHandler->CancelTransaction(mTransaction, rv);
1678 return rv;
1679 }
1680
1681 uint32_t suspendCount = mSuspendCount;
1682 if (LoadAsyncResumePending()) {
1683 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Suspend()'ing transaction pump once because of async resume pending"
", sc=%u, pump=%p, this=%p", suspendCount, mTransactionPump.
get(), this); } } while (0)
1684 (" Suspend()'ing transaction pump once because of async resume pending"do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Suspend()'ing transaction pump once because of async resume pending"
", sc=%u, pump=%p, this=%p", suspendCount, mTransactionPump.
get(), this); } } while (0)
1685 ", sc=%u, pump=%p, this=%p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Suspend()'ing transaction pump once because of async resume pending"
", sc=%u, pump=%p, this=%p", suspendCount, mTransactionPump.
get(), this); } } while (0)
1686 suspendCount, mTransactionPump.get(), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Suspend()'ing transaction pump once because of async resume pending"
", sc=%u, pump=%p, this=%p", suspendCount, mTransactionPump.
get(), this); } } while (0)
;
1687 ++suspendCount;
1688 }
1689 while (suspendCount--) {
1690 mTransactionPump->Suspend();
1691 }
1692
1693 return NS_OK;
1694}
1695
1696void nsHttpChannel::SpeculativeConnect() {
1697 // Before we take the latency hit of dealing with the cache, try and
1698 // get the TCP (and SSL) handshakes going so they can overlap.
1699
1700 // don't speculate if we are offline, when doing http upgrade (i.e.
1701 // websockets bootstrap), or if we can't do keep-alive (because then we
1702 // couldn't reuse the speculative connection anyhow).
1703 if (gIOService->IsOffline() || mUpgradeProtocolCallback ||
1704 !(mCaps & NS_HTTP_ALLOW_KEEPALIVE(1 << 0)) || IsForcedOffline()) {
1705 return;
1706 }
1707
1708 // LOAD_ONLY_FROM_CACHE and LOAD_NO_NETWORK_IO must not hit network.
1709 // LOAD_FROM_CACHE is unlikely to hit network, so skip preconnects for it.
1710 if (mLoadFlags &
1711 (LOAD_ONLY_FROM_CACHE | LOAD_FROM_CACHE | LOAD_NO_NETWORK_IO)) {
1712 return;
1713 }
1714
1715 if (LoadAllowStaleCacheContent()) {
1716 return;
1717 }
1718
1719 nsCOMPtr<nsIInterfaceRequestor> callbacks;
1720 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
1721 getter_AddRefs(callbacks));
1722 if (!callbacks) return;
1723 // Disable HTTPS RR, since the new HappyEyeballs implementation will handle
1724 // it.
1725 bool httpsRRAllowed = !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) &&
1726 !(mCaps & NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30));
1727 (void)gHttpHandler->MaybeSpeculativeConnectWithHTTPSRR(
1728 mConnectionInfo, callbacks,
1729 mCaps & (NS_HTTP_DISALLOW_SPDY(1 << 7) | NS_HTTP_TRR_MODE_MASK((1 << 19) | (1 << 20)) |
1730 NS_HTTP_DISABLE_IPV4(1 << 17) | NS_HTTP_DISABLE_IPV6(1 << 18) |
1731 NS_HTTP_DISALLOW_HTTP3(1 << 21) | NS_HTTP_REFRESH_DNS(1 << 3)),
1732 nsHttpHandler::EchConfigEnabled() && httpsRRAllowed);
1733}
1734
1735void nsHttpChannel::DoNotifyListenerCleanup() {
1736 // We don't need this info anymore
1737 CleanRedirectCacheChainIfNecessary();
1738}
1739
1740void nsHttpChannel::ReleaseListeners() {
1741 HttpBaseChannel::ReleaseListeners();
1742
1743 mChannelClassifier = nullptr;
1744 mWarningReporter = nullptr;
1745 mEarlyHintObserver = nullptr;
1746 mWebTransportSessionEventListener = nullptr;
1747
1748 for (StreamFilterRequest& request : mStreamFilterRequests) {
1749 request.mPromise->Reject(false, __func__);
1750 }
1751 mStreamFilterRequests.Clear();
1752}
1753
1754void nsHttpChannel::DoAsyncAbort(nsresult aStatus) {
1755 (void)AsyncAbort(aStatus);
1756}
1757
1758void nsHttpChannel::HandleAsyncRedirect() {
1759 MOZ_ASSERT(!mCallOnResume, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCallOnResume)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCallOnResume))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mCallOnResume"
" (" "How did that happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1759); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 1759); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1760
1761 if (mSuspendCount) {
1762 LOG(("Waiting until resume to do async redirect [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to do async redirect [this=%p]\n", this
); } } while (0)
;
1763 mCallOnResume = [](nsHttpChannel* self) {
1764 self->HandleAsyncRedirect();
1765 return NS_OK;
1766 };
1767 return;
1768 }
1769
1770 nsresult rv = NS_OK;
1771
1772 LOG(("nsHttpChannel::HandleAsyncRedirect [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::HandleAsyncRedirect [this=%p]\n", this); } }
while (0)
;
1773
1774 // since this event is handled asynchronously, it is possible that this
1775 // channel could have been canceled, in which case there would be no point
1776 // in processing the redirect.
1777 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) {
1778 PushRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1779 rv = AsyncProcessRedirection(mResponseHead->Status());
1780 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1781 PopRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1782 // TODO: if !DoNotRender3xxBody(), render redirect body instead.
1783 // But first we need to cache 3xx bodies (bug 748510)
1784 rv = ContinueHandleAsyncRedirect(rv);
1785 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1785); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1786 }
1787 } else {
1788 rv = ContinueHandleAsyncRedirect(mStatus);
1789 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1789); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1789); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1790 }
1791}
1792
1793nsresult nsHttpChannel::ContinueHandleAsyncRedirect(nsresult rv) {
1794 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1795 // If AsyncProcessRedirection fails, then we have to send out the
1796 // OnStart/OnStop notifications.
1797 LOG(("ContinueHandleAsyncRedirect got failure result [rv=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueHandleAsyncRedirect got failure result [rv=%" "x" "]\n"
, static_cast<uint32_t>(rv)); } } while (0)
1798 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueHandleAsyncRedirect got failure result [rv=%" "x" "]\n"
, static_cast<uint32_t>(rv)); } } while (0)
;
1799
1800 bool redirectsEnabled = !mLoadInfo->GetDontFollowRedirects();
1801
1802 if (redirectsEnabled) {
1803 // TODO: stop failing original channel if redirect vetoed?
1804 mStatus = rv;
1805
1806 DoNotifyListener();
1807
1808 // Blow away cache entry if we couldn't process the redirect
1809 // for some reason (the cache entry might be corrupt).
1810 if (mCacheEntry) {
1811 mCacheEntry->AsyncDoom(nullptr);
1812 }
1813 } else {
1814 DoNotifyListener();
1815 }
1816 }
1817
1818 CloseCacheEntry(true);
1819
1820 StoreIsPending(false);
1821
1822 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1823
1824 return NS_OK;
1825}
1826
1827void nsHttpChannel::HandleAsyncNotModified() {
1828 MOZ_ASSERT(!mCallOnResume, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCallOnResume)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCallOnResume))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mCallOnResume"
" (" "How did that happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1828); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 1828); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1829
1830 if (mSuspendCount) {
1831 LOG(("Waiting until resume to do async not-modified [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to do async not-modified [this=%p]\n"
, this); } } while (0)
;
1832 mCallOnResume = [](nsHttpChannel* self) {
1833 self->HandleAsyncNotModified();
1834 return NS_OK;
1835 };
1836 return;
1837 }
1838
1839 LOG(("nsHttpChannel::HandleAsyncNotModified [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::HandleAsyncNotModified [this=%p]\n", this);
} } while (0)
;
1840
1841 DoNotifyListener();
1842
1843 CloseCacheEntry(false);
1844
1845 StoreIsPending(false);
1846
1847 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1848}
1849
1850nsresult nsHttpChannel::SetupChannelForTransaction() {
1851 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p, cos=%lu, inc=%d "
"prio=%d]\n", this, mClassOfService.Flags(), mClassOfService
.Incremental(), mPriority); } } while (0)
1852 "nsHttpChannel::SetupChannelForTransaction [this=%p, cos=%lu, inc=%d "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p, cos=%lu, inc=%d "
"prio=%d]\n", this, mClassOfService.Flags(), mClassOfService
.Incremental(), mPriority); } } while (0)
1853 "prio=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p, cos=%lu, inc=%d "
"prio=%d]\n", this, mClassOfService.Flags(), mClassOfService
.Incremental(), mPriority); } } while (0)
1854 this, mClassOfService.Flags(), mClassOfService.Incremental(), mPriority))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupChannelForTransaction [this=%p, cos=%lu, inc=%d "
"prio=%d]\n", this, mClassOfService.Flags(), mClassOfService
.Incremental(), mPriority); } } while (0)
;
1855
1856 NS_ENSURE_TRUE(!mTransaction, NS_ERROR_ALREADY_INITIALIZED)do { if ((__builtin_expect(!!(!(!mTransaction)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!mTransaction" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1856); return NS_ERROR_ALREADY_INITIALIZED; } } while (false
)
;
1857
1858 nsresult rv;
1859
1860 if (StaticPrefs::network_http_priority_header_enabled()) {
1861 SetPriorityHeader();
1862 }
1863
1864 StoreUsedNetwork(1);
1865
1866 if (!LoadAllowSpdy()) {
1867 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
1868 }
1869 if (!LoadAllowHttp3()) {
1870 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
1871 }
1872 if (LoadBeConservative()) {
1873 mCaps |= NS_HTTP_BE_CONSERVATIVE(1 << 11);
1874 }
1875
1876 if (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) {
1877 mCaps |= NS_HTTP_LOAD_ANONYMOUS_CONNECT_ALLOW_CLIENT_CERT(1 << 23);
1878 }
1879
1880 if (nsContentUtils::ShouldResistFingerprinting(this,
1881 RFPTarget::HttpUserAgent)) {
1882 mCaps |= NS_HTTP_USE_RFP(1 << 26);
1883 }
1884
1885 // Use the URI path if not proxying (transparent proxying such as proxy
1886 // CONNECT does not count here). Also figure out what HTTP version to use.
1887 nsAutoCString buf, path;
1888 nsCString* requestURI;
1889
1890 // This is the normal e2e H1 path syntax "/index.html"
1891 rv = mURI->GetPathQueryRef(path);
1892 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1893 return rv;
1894 }
1895
1896 // path may contain UTF-8 characters, so ensure that they're escaped.
1897 if (NS_EscapeURL(path.get(), path.Length(), esc_OnlyNonASCII | esc_Spaces,
1898 buf)) {
1899 requestURI = &buf;
1900 } else {
1901 requestURI = &path;
1902 }
1903
1904 // trim off the #ref portion if any...
1905 int32_t ref1 = requestURI->FindChar('#');
1906 if (ref1 != kNotFound) {
1907 requestURI->SetLength(ref1);
1908 }
1909
1910 if (mConnectionInfo->UsingConnect() || !mConnectionInfo->UsingHttpProxy()) {
1911 mRequestHead.SetVersion(gHttpHandler->HttpVersion());
1912 } else {
1913 mRequestHead.SetPath(*requestURI);
1914
1915 // RequestURI should be the absolute uri H1 proxy syntax
1916 // "http://foo/index.html" so we will overwrite the relative version in
1917 // requestURI
1918 rv = mURI->GetUserPass(buf);
1919 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1920 if (!buf.IsEmpty() && ((strncmp(mSpec.get(), "http:", 5) == 0) ||
1921 strncmp(mSpec.get(), "https:", 6) == 0)) {
1922 nsCOMPtr<nsIURI> tempURI = nsIOService::CreateExposableURI(mURI);
1923 rv = tempURI->GetAsciiSpec(path);
1924 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1925 requestURI = &path;
1926 } else {
1927 requestURI = &mSpec;
1928 }
1929
1930 // trim off the #ref portion if any...
1931 int32_t ref2 = requestURI->FindChar('#');
1932 if (ref2 != kNotFound) {
1933 requestURI->SetLength(ref2);
1934 }
1935
1936 mRequestHead.SetVersion(gHttpHandler->ProxyHttpVersion());
1937 }
1938
1939 mRequestHead.SetRequestURI(*requestURI);
1940
1941 // set the request time for cache expiration calculations
1942 mRequestTime = NowInSeconds()PRTimeToSeconds(PR_Now());
1943 StoreRequestTimeInitialized(true);
1944
1945 // if doing a reload, force end-to-end
1946 if (mLoadFlags & LOAD_BYPASS_CACHE) {
1947 // We need to send 'Pragma:no-cache' to inhibit proxy caching even if
1948 // no proxy is configured since we might be talking with a transparent
1949 // proxy, i.e. one that operates at the network level. See bug #14772.
1950 // But we should not touch Pragma if Cache-Control is already set
1951 // (https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A3)
1952 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1953 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
1954 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1954); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1955 }
1956 // If we're configured to speak HTTP/1.1 then also send 'Cache-control:
1957 // no-cache'. But likewise don't touch Cache-Control if it's already set.
1958 if (mRequestHead.Version() >= HttpVersion::v1_1 &&
1959 !mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1960 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "no-cache", true);
1961 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1961); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1961); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1962 }
1963 } else if (mLoadFlags & VALIDATE_ALWAYS) {
1964 // We need to send 'Cache-Control: max-age=0' to force each cache along
1965 // the path to the origin server to revalidate its own entry, if any,
1966 // with the next cache or server. See bug #84847.
1967 //
1968 // If we're configured to speak HTTP/1.0 then just send 'Pragma: no-cache'
1969 //
1970 // But don't send the headers if they're already set:
1971 // https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A2
1972 if (mRequestHead.Version() >= HttpVersion::v1_1) {
1973 if (!mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1974 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "max-age=0",
1975 true);
1976 }
1977 } else {
1978 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1979 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
1980 }
1981 }
1982 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1982); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1982); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1983 }
1984
1985 if (LoadResuming()) {
1986 char byteRange[32];
1987 SprintfLiteral(byteRange, "bytes=%" PRIu64"l" "u" "-", mStartPos);
1988 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(byteRange));
1989 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1989); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1990
1991 if (!mEntityID.IsEmpty()) {
1992 // Also, we want an error if this resource changed in the meantime
1993 // Format of the entity id is: escaped_etag/size/lastmod
1994 nsCString::const_iterator start, end, slash;
1995 mEntityID.BeginReading(start);
1996 mEntityID.EndReading(end);
1997 mEntityID.BeginReading(slash);
1998
1999 if (FindCharInReadable('/', slash, end)) {
2000 nsAutoCString ifMatch;
2001 rv = mRequestHead.SetHeader(
2002 nsHttp::If_Match,
2003 NS_UnescapeURL(Substring(start, slash), 0, ifMatch));
2004 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2004); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2004); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2005
2006 ++slash; // Incrementing, so that searching for '/' won't find
2007 // the same slash again
2008 }
2009
2010 if (FindCharInReadable('/', slash, end)) {
2011 rv = mRequestHead.SetHeader(nsHttp::If_Unmodified_Since,
2012 Substring(++slash, end));
2013 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2013); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2013); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2014 }
2015 }
2016 }
2017
2018 // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
2019 if (mLoadFlags & LOAD_ANONYMOUS) mCaps |= NS_HTTP_LOAD_ANONYMOUS(1 << 4);
2020
2021 if (mUpgradeProtocolCallback) {
2022 rv = mRequestHead.SetHeader(nsHttp::Upgrade, mUpgradeProtocol, false);
2023 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2023); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2023); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2024 rv = mRequestHead.SetHeaderOnce(nsHttp::Connection, nsHttp::Upgrade.get(),
2025 false);
2026 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2026); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2026); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2027 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
2028 mCaps &= ~NS_HTTP_ALLOW_KEEPALIVE(1 << 0);
2029 }
2030
2031 if (mWebTransportSessionEventListener) {
2032 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
2033 }
2034
2035 return NS_OK;
2036}
2037
2038// Updates mLNAPermission members based on existing permission and tracking
2039// flags in load info
2040LNAPermission nsHttpChannel::UpdateLocalNetworkAccessPermissions(
2041 const nsACString& aPermissionType) {
2042 // We should arrive at this point after LNA has been detected at the
2043 // transaction layer and has errored
2044
2045 MOZ_ASSERT(aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY ||
aPermissionType == LOCAL_NETWORK_PERMISSION_KEY)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType
== LOCAL_NETWORK_PERMISSION_KEY))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2046
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
")"); do { MOZ_CrashSequence(__null, 2046); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2046 aPermissionType == LOCAL_NETWORK_PERMISSION_KEY)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY ||
aPermissionType == LOCAL_NETWORK_PERMISSION_KEY)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType
== LOCAL_NETWORK_PERMISSION_KEY))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2046
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
")"); do { MOZ_CrashSequence(__null, 2046); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2047 LNAPermission userPerms = aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY
2048 ? mLNAPermission.mLocalHostPermission
2049 : mLNAPermission.mLocalNetworkPermission;
2050
2051 if (NS_WARN_IF(userPerms != LNAPermission::Pending)NS_warn_if_impl(userPerms != LNAPermission::Pending, "userPerms != LNAPermission::Pending"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2051
)
) {
2052 // Unexpected condition, we should not hit this case
2053 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2055); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2054 "UpdateLocalNetworkAccessPermissions called with non-pending "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2055); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2055 "permission")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2055); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2055); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
2056 return userPerms;
2057 }
2058
2059 MOZ_ASSERT(mLoadInfo->TriggeringPrincipal(), "need triggering principal")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->TriggeringPrincipal())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo->TriggeringPrincipal
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mLoadInfo->TriggeringPrincipal()" " (" "need triggering principal"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2059); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->TriggeringPrincipal()"
") (" "need triggering principal" ")"); do { MOZ_CrashSequence
(__null, 2059); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2060
2061 // Skip LNA checks if the triggering principal and target are same origin.
2062 // Note: This could be a case where there is a network change or device
2063 // migration to a private or corporate network.
2064 //
2065 // This only holds when we connect directly to the origin's own endpoint. If
2066 // the connection was rerouted via Alt-Svc to a different host/port, a
2067 // same-origin URL no longer implies we are talking to the origin itself: a
2068 // public origin could steer same-origin traffic to an attacker-selected
2069 // private address. Don't grant the exemption in that case.
2070 bool reroutedElsewhere =
2071 mConnectionInfo && !mConnectionInfo->GetRoutedHost().IsEmpty() &&
2072 (!mConnectionInfo->GetRoutedHost().Equals(mConnectionInfo->GetOrigin()) ||
2073 mConnectionInfo->RoutedPort() != mConnectionInfo->OriginPort());
2074 // This exemption (same origin) should apply only to secure contexts.
2075 const bool triggeringPrincipalIsPotentiallyTrustworthy =
2076 mLoadInfo->TriggeringPrincipal()->GetIsOriginPotentiallyTrustworthy();
2077 bool isSameOrigin = false;
2078 nsresult rv =
2079 mLoadInfo->TriggeringPrincipal()->IsSameOrigin(mURI, &isSameOrigin);
2080 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && isSameOrigin && !reroutedElsewhere &&
2081 triggeringPrincipalIsPotentiallyTrustworthy) {
2082 userPerms = LNAPermission::Granted;
2083 return userPerms;
2084 }
2085
2086 // Skip LNA checks if captive portal is active
2087 nsCOMPtr<nsICaptivePortalService> cps = CaptivePortalService::GetSingleton();
2088 if (cps) {
2089 int32_t state = cps->State();
2090 if (state == nsICaptivePortalService::LOCKED_PORTAL &&
2091 aPermissionType == LOCAL_NETWORK_PERMISSION_KEY) {
2092 userPerms = LNAPermission::Granted;
2093 return userPerms;
2094 }
2095 }
2096
2097 // Step 1. Check for Existing Allow or Deny permission
2098 if (nsContentUtils::IsExactSitePermAllow(mLoadInfo->TriggeringPrincipal(),
2099 aPermissionType)) {
2100 userPerms = LNAPermission::Granted;
2101 return userPerms;
2102 }
2103
2104 if (nsContentUtils::IsExactSitePermDeny(mLoadInfo->TriggeringPrincipal(),
2105 aPermissionType)) {
2106 userPerms = LNAPermission::Denied;
2107 return userPerms;
2108 }
2109
2110 // Step 2.If this is from third Party Tracker, just block
2111 uint32_t flags = 0;
2112 using CF = nsIClassifiedChannel::ClassificationFlags;
2113 if (StaticPrefs::network_lna_block_trackers() &&
2114 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
2115 mLoadInfo->GetTriggeringThirdPartyClassificationFlags(&flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
&&
2116 (flags & (CF::CLASSIFIED_ANY_BASIC_TRACKING |
2117 CF::CLASSIFIED_ANY_SOCIAL_TRACKING)) != 0) {
2118 userPerms = LNAPermission::Denied;
2119 return userPerms;
2120 }
2121
2122 // Check if we should block LNA requests from insecure contexts
2123 if (StaticPrefs::network_lna_block_insecure_contexts() &&
2124 !triggeringPrincipalIsPotentiallyTrustworthy) {
2125 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::UpdateLocalNetworkAccessPermissions [this=%p] "
"blocking LNA request from insecure context\n", this); } } while
(0)
2126 ("nsHttpChannel::UpdateLocalNetworkAccessPermissions [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::UpdateLocalNetworkAccessPermissions [this=%p] "
"blocking LNA request from insecure context\n", this); } } while
(0)
2127 "blocking LNA request from insecure context\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::UpdateLocalNetworkAccessPermissions [this=%p] "
"blocking LNA request from insecure context\n", this); } } while
(0)
2128 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::UpdateLocalNetworkAccessPermissions [this=%p] "
"blocking LNA request from insecure context\n", this); } } while
(0)
;
2129 userPerms = LNAPermission::Denied;
2130 return userPerms;
2131 }
2132
2133 // Step 3
2134 // could not determine the permission, lets prompt user
2135 // for permission if lna blocking is enabled
2136 if (StaticPrefs::network_lna_blocking()) {
2137 return userPerms;
2138 }
2139
2140 // we dont have reasons to block the request so we allow this LNA request
2141 // Ideally we should not hit this case once the feature is fully shipped
2142 userPerms = LNAPermission::Granted;
2143 return userPerms;
2144}
2145
2146nsresult nsHttpChannel::InitTransaction() {
2147 nsresult rv;
2148 // create wrapper for this channel's notification callbacks
2149 nsCOMPtr<nsIInterfaceRequestor> callbacks;
2150 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
2151 getter_AddRefs(callbacks));
2152
2153 // create the transaction object
2154 mTransaction = new nsHttpTransaction();
2155 LOG1(("nsHttpChannel %p created nsHttpTransaction %p\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Error)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Error, "nsHttpChannel %p created nsHttpTransaction %p\n"
, this, mTransaction.get()); } } while (0)
2156 mTransaction.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Error)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Error, "nsHttpChannel %p created nsHttpTransaction %p\n"
, this, mTransaction.get()); } } while (0)
;
2157
2158 // Save the mapping of channel id and the channel. We need this mapping for
2159 // nsIHttpActivityObserver.
2160 gHttpHandler->AddHttpChannel(mChannelId, ToSupports(this));
2161
2162 EnsureBrowserId();
2163 EnsureRequestContext();
2164
2165 HttpTrafficCategory category = CreateTrafficCategory();
2166 mTransaction->SetIsForWebTransport(!!mWebTransportSessionEventListener);
2167 mTransaction->SetRequestBodyIsStreaming(LoadUploadStreamIsStreaming());
2168
2169 RefPtr<mozilla::dom::BrowsingContext> bc;
2170 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
2171
2172 nsILoadInfo::IPAddressSpace parentAddressSpace =
2173 mozilla::net::GetParentIPAddressSpace(mLoadInfo);
2174
2175 // Check if this is a top-level navigation load and grant LNA permissions
2176 // to skip local network access verification for navigational loads
2177 if (mLoadInfo && StaticPrefs::network_lna_allow_top_level_navigation()) {
2178 ExtContentPolicyType contentPolicyType =
2179 mLoadInfo->GetExternalContentPolicyType();
2180 if (contentPolicyType == ExtContentPolicy::TYPE_DOCUMENT) {
2181 // Grant permissions for top-level navigation loads
2182 mLNAPermission.mLocalHostPermission = LNAPermission::Granted;
2183 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
2184 }
2185 }
2186
2187 // Grant LNA permissions for captive portal tabs to allow them to access
2188 // local network resources without prompting the user
2189 if (bc && bc->GetIsCaptivePortalTab()) {
2190 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
2191 }
2192
2193 rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead, mUploadStream,
2194 mReqContentLength, GetCurrentSerialEventTarget(),
2195 callbacks, this, mBrowserId, category,
2196 mRequestContext, mClassOfService, mInitialRwin,
2197 LoadResponseTimeoutEnabled(), mChannelId,
2198 parentAddressSpace, mLNAPermission);
2199 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2200 mTransaction = nullptr;
2201 return rv;
2202 }
2203
2204 return rv;
2205}
2206
2207HttpTrafficCategory nsHttpChannel::CreateTrafficCategory() {
2208 MOZ_ASSERT(!mFirstPartyClassificationFlags ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2209
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 2209); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2209 !mThirdPartyClassificationFlags)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2209
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 2209); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2210
2211 if (!StaticPrefs::network_traffic_analyzer_enabled()) {
2212 return HttpTrafficCategory::eInvalid;
2213 }
2214
2215 HttpTrafficAnalyzer::ClassOfService cos;
2216 {
2217 if ((mClassOfService.Flags() & nsIClassOfService::Leader) &&
2218 mLoadInfo->GetExternalContentPolicyType() ==
2219 ExtContentPolicy::TYPE_SCRIPT) {
2220 cos = HttpTrafficAnalyzer::ClassOfService::eLeader;
2221 } else if (mLoadFlags & nsIRequest::LOAD_BACKGROUND) {
2222 cos = HttpTrafficAnalyzer::ClassOfService::eBackground;
2223 } else {
2224 cos = HttpTrafficAnalyzer::ClassOfService::eOther;
2225 }
2226 }
2227
2228 bool isThirdParty = AntiTrackingUtils::IsThirdPartyChannel(this);
2229
2230 HttpTrafficAnalyzer::TrackingClassification tc;
2231 {
2232 uint32_t flags = isThirdParty ? mThirdPartyClassificationFlags
2233 : mFirstPartyClassificationFlags;
2234
2235 using CF = nsIClassifiedChannel::ClassificationFlags;
2236 using TC = HttpTrafficAnalyzer::TrackingClassification;
2237
2238 if (flags & CF::CLASSIFIED_TRACKING_CONTENT) {
2239 tc = TC::eContent;
2240 } else if (flags & CF::CLASSIFIED_FINGERPRINTING_CONTENT) {
2241 tc = TC::eFingerprinting;
2242 } else if (flags & CF::CLASSIFIED_ANY_BASIC_TRACKING) {
2243 tc = TC::eBasic;
2244 } else {
2245 tc = TC::eNone;
2246 }
2247 }
2248
2249 bool isSystemPrincipal =
2250 mLoadInfo->GetLoadingPrincipal() &&
2251 mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal();
2252 return HttpTrafficAnalyzer::CreateTrafficCategory(
2253 NS_UsePrivateBrowsing(this), isSystemPrincipal, isThirdParty, cos, tc);
2254}
2255
2256void nsHttpChannel::SetCachedContentType() {
2257 if (!mResponseHead) {
2258 return;
2259 }
2260
2261 nsAutoCString contentTypeStr;
2262 mResponseHead->ContentType(contentTypeStr);
2263
2264 uint8_t contentType = nsICacheEntry::CONTENT_TYPE_OTHER;
2265 if (nsContentUtils::IsJavascriptMIMEType(
2266 NS_ConvertUTF8toUTF16(contentTypeStr))) {
2267 contentType = nsICacheEntry::CONTENT_TYPE_JAVASCRIPT;
2268 } else if (StringBeginsWith(contentTypeStr, "text/css"_ns) ||
2269 (mLoadInfo->GetExternalContentPolicyType() ==
2270 ExtContentPolicy::TYPE_STYLESHEET)) {
2271 contentType = nsICacheEntry::CONTENT_TYPE_STYLESHEET;
2272 } else if (StringBeginsWith(contentTypeStr, "application/wasm"_ns)) {
2273 contentType = nsICacheEntry::CONTENT_TYPE_WASM;
2274 } else if (StringBeginsWith(contentTypeStr, "image/"_ns)) {
2275 contentType = nsICacheEntry::CONTENT_TYPE_IMAGE;
2276 } else if (StringBeginsWith(contentTypeStr, "video/"_ns)) {
2277 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
2278 } else if (StringBeginsWith(contentTypeStr, "audio/"_ns)) {
2279 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
2280 }
2281
2282 mCacheEntry->SetContentType(contentType);
2283}
2284
2285static bool ShouldSniffMisconfiguredType(nsHttpResponseHead* aResponseHead,
2286 nsILoadInfo* aLoadInfo) {
2287 if (!StaticPrefs::network_mimesniff_sniff_misconfigured_types()) {
2288 return false;
2289 }
2290
2291 // Only sniff document navigations, not subresources.
2292 // https://mimesniff.spec.whatwg.org/#sniffing-a-mislabeled-binary-resource
2293 auto type = aLoadInfo->GetExternalContentPolicyType();
2294 if (type != ExtContentPolicyType::TYPE_DOCUMENT &&
2295 type != ExtContentPolicyType::TYPE_SUBDOCUMENT) {
2296 return false;
2297 }
2298
2299 // Responses marked as attachments are already going to be downloaded
2300 // regardless of their content type, so there is no need to sniff them.
2301 nsAutoCString contentDisposition;
2302 if (NS_SUCCEEDED(aResponseHead->GetHeader(nsHttp::Content_Disposition,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Content_Disposition, contentDisposition))),
1)))
2303 contentDisposition))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Content_Disposition, contentDisposition))),
1)))
&&
2304 !contentDisposition.IsEmpty() &&
2305 NS_GetContentDispositionFromHeader(contentDisposition) ==
2306 nsIChannel::DISPOSITION_ATTACHMENT) {
2307 return false;
2308 }
2309
2310 nsAutoCString contentTypeOptionsHeader;
2311 if (aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader) &&
2312 contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) {
2313 return false;
2314 }
2315
2316 nsAutoCString contentType;
2317 aResponseHead->ContentType(contentType);
2318
2319 if (contentType.EqualsLiteral("text/plain")) {
2320 return true;
2321 }
2322
2323 if (contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type") ||
2324 contentType.IsEmpty()) {
2325 return true;
2326 }
2327
2328 return false;
2329}
2330
2331nsresult nsHttpChannel::CallOnStartRequest() {
2332 LOG(("nsHttpChannel::CallOnStartRequest [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnStartRequest [this=%p]", this); } } while
(0)
;
2333
2334 MOZ_RELEASE_ASSERT(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()" " ("
"CORS preflight must have been finished by the time we " "call OnStartRequest"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2336); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2336
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2335 "CORS preflight must have been finished by the time we "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()" " ("
"CORS preflight must have been finished by the time we " "call OnStartRequest"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2336); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2336
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2336 "call OnStartRequest")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()" " ("
"CORS preflight must have been finished by the time we " "call OnStartRequest"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2336); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2336
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
2337
2338 MOZ_RELEASE_ASSERT(mCanceled || LoadProcessCrossOriginSecurityHeadersCalled(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCanceled || LoadProcessCrossOriginSecurityHeadersCalled
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mCanceled || LoadProcessCrossOriginSecurityHeadersCalled
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
" (" "Security headers need to have been processed before " "calling CallOnStartRequest"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2340); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2340); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
2339 "Security headers need to have been processed before "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCanceled || LoadProcessCrossOriginSecurityHeadersCalled
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mCanceled || LoadProcessCrossOriginSecurityHeadersCalled
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
" (" "Security headers need to have been processed before " "calling CallOnStartRequest"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2340); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2340); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
2340 "calling CallOnStartRequest")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCanceled || LoadProcessCrossOriginSecurityHeadersCalled
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mCanceled || LoadProcessCrossOriginSecurityHeadersCalled
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
" (" "Security headers need to have been processed before " "calling CallOnStartRequest"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2340); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2340); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
2341
2342 mEarlyHintObserver = nullptr;
2343
2344 if (StaticPrefs::network_http_network_error_logging_enabled() &&
2345 mResponseHead && mResponseHead->HasHeader(nsHttp::NEL) &&
2346 LoadUsedNetwork()) {
2347 // If the policy gets cleared, but this response is still in the cache,
2348 // we probably don't want to reinstall the policy when the entry is
2349 // reloaded. That means it's important to only call RegisterPolicy when
2350 // LoadUsedNetwork() is true.
2351 if (nsCOMPtr<nsINetworkErrorLogging> nel =
2352 components::NetworkErrorLogging::Service()) {
2353 nel->RegisterPolicy(this);
2354 }
2355 }
2356
2357 if (LoadOnStartRequestCalled()) {
2358 // This can only happen when a range request loading rest of the data
2359 // after interrupted concurrent cache read asynchronously failed, e.g.
2360 // the response range bytes are not as expected or this channel has
2361 // been externally canceled.
2362 //
2363 // It's legal to bypass CallOnStartRequest for that case since we've
2364 // already called OnStartRequest on our listener and also added all
2365 // content converters before.
2366 MOZ_ASSERT(LoadConcurrentCacheAccess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadConcurrentCacheAccess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadConcurrentCacheAccess())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("LoadConcurrentCacheAccess()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2366
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { MOZ_CrashSequence(__null, 2366); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2367 LOG(("CallOnStartRequest already invoked before"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "CallOnStartRequest already invoked before"); } } while (0)
;
2368 return mStatus;
2369 }
2370
2371 // Ensure mListener->OnStartRequest will be invoked before exiting
2372 // this function.
2373 auto onStartGuard = MakeScopeExit([&] {
2374 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " calling mListener->OnStartRequest by ScopeExit [this=%p, "
"listener=%p]\n", this, mListener.get()); } } while (0)
2375 (" calling mListener->OnStartRequest by ScopeExit [this=%p, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " calling mListener->OnStartRequest by ScopeExit [this=%p, "
"listener=%p]\n", this, mListener.get()); } } while (0)
2376 "listener=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " calling mListener->OnStartRequest by ScopeExit [this=%p, "
"listener=%p]\n", this, mListener.get()); } } while (0)
2377 this, mListener.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " calling mListener->OnStartRequest by ScopeExit [this=%p, "
"listener=%p]\n", this, mListener.get()); } } while (0)
;
2378 MOZ_ASSERT(!LoadOnStartRequestCalled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2378
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 2378); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2379
2380 if (mListener) {
2381 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
2382 StoreOnStartRequestCalled(true);
2383 deleteProtector->OnStartRequest(this);
2384 }
2385 StoreOnStartRequestCalled(true);
2386 });
2387
2388 nsresult rv = ValidateMIMEType();
2389 // We need to update the channel status before calling
2390 // mListener->OnStartRequest. This is the only way to let child process
2391 // discard the already received ODA messages.
2392 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2393 mStatus = rv;
2394 return mStatus;
2395 }
2396
2397 // EnsureOpaqueResponseIsAllowed and EnsureOpauqeResponseIsAllowedAfterSniff
2398 // are the checks for Opaque Response Blocking to ensure that we block as many
2399 // cross-origin responses with CORS headers as possible that are not either
2400 // Javascript or media to avoid leaking their contents through side channels.
2401 OpaqueResponse opaqueResponse =
2402 PerformOpaqueResponseSafelistCheckBeforeSniff();
2403 if (opaqueResponse == OpaqueResponse::Block) {
2404 SetChannelBlockedByOpaqueResponse();
2405 CancelWithReason(NS_ERROR_DOM_NETWORK_ERR,
2406 "OpaqueResponseBlocker::BlockResponse"_ns);
2407 return NS_BINDING_ABORTED;
2408 }
2409
2410 // We must ensure that any dcb/dcz content is decompressed in the parent
2411 // process, and removed from the Content-Encoding before it's sent down
2412 // to the content process. In most (all?) cases, this should have occurred
2413 // before this.
2414 if (mResponseHead && XRE_IsParentProcess() && !LoadHasAppliedConversion()) {
2415 nsAutoCString contentEncoding;
2416 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
2417 // Note: doesn't handle multiple compressors: "dcb, gzip" or
2418 // "gzip, dcb" (etc)
2419 if (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
2420 contentEncoding.LowerCaseEqualsLiteral("dcz")) {
2421 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Still had %s encoding at CallOnStartRequest, converting"
, contentEncoding.get()); } } while (0)
2422 ("Still had %s encoding at CallOnStartRequest, converting",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Still had %s encoding at CallOnStartRequest, converting"
, contentEncoding.get()); } } while (0)
2423 contentEncoding.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Still had %s encoding at CallOnStartRequest, converting"
, contentEncoding.get()); } } while (0)
;
2424 nsCOMPtr<nsIStreamListener> listener;
2425 MOZ_DIAGNOSTIC_ASSERT(LoadHasAppliedConversion() == false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadHasAppliedConversion() == false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadHasAppliedConversion() ==
false))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("LoadHasAppliedConversion() == false", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2425); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "LoadHasAppliedConversion() == false"
")"); do { MOZ_CrashSequence(__null, 2425); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2426 // Insist we install a converter. This should never be the case, but
2427 // if somehow it is, we need a converter; content can't be allowed
2428 // to see dcb/dcz since it can't convert them
2429 StoreHasAppliedConversion(false);
2430 // IMPORTANT: Must use DoApplyContentConversionsInternal with
2431 // aRemoveEncodings=true to clear Content-Encoding header. Otherwise,
2432 // decompressed data will be cached with dcb/dcz in metadata, causing
2433 // corruption on cache reads.
2434 rv = DoApplyContentConversionsInternal(
2435 mListener, getter_AddRefs(listener), true, nullptr);
2436 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2437 return rv;
2438 }
2439 if (listener) {
2440 mListener = listener;
2441 mCompressListener = listener;
2442
2443 StoreHasAppliedConversion(true);
2444 } else {
2445 // Failed to install decompressor for dcb/dcz - this is a fatal error
2446 // as content cannot handle these encodings
2447 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Failed to install decompressor for %s at "
"CallOnStartRequest", contentEncoding.get()); } } while (0)
2448 ("FATAL: Failed to install decompressor for %s at "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Failed to install decompressor for %s at "
"CallOnStartRequest", contentEncoding.get()); } } while (0)
2449 "CallOnStartRequest",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Failed to install decompressor for %s at "
"CallOnStartRequest", contentEncoding.get()); } } while (0)
2450 contentEncoding.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Failed to install decompressor for %s at "
"CallOnStartRequest", contentEncoding.get()); } } while (0)
;
2451 return NS_ERROR_INVALID_CONTENT_ENCODING;
2452 }
2453 }
2454 }
2455
2456 // Allow consumers to override our content type
2457 if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) {
2458 // NOTE: We can have both a txn pump and a cache pump when the cache
2459 // content is partial. In that case, we need to read from the cache,
2460 // because that's the one that has the initial contents. If that fails
2461 // then give the transaction pump a shot.
2462
2463 nsIChannel* thisChannel = static_cast<nsIChannel*>(this);
2464
2465 bool typeSniffersCalled = false;
2466 if (mCachePump) {
2467 typeSniffersCalled =
2468 NS_SUCCEEDED(mCachePump->PeekStream(CallTypeSniffers, thisChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCachePump->PeekStream
(CallTypeSniffers, thisChannel))), 1)))
;
2469 }
2470
2471 if (!typeSniffersCalled && mTransactionPump) {
2472 RefPtr<nsInputStreamPump> pump = do_QueryObject(mTransactionPump);
2473 if (pump) {
2474 pump->PeekStream(CallTypeSniffers, thisChannel);
2475 }
2476 }
2477 }
2478
2479 bool unknownDecoderStarted = false;
2480 bool shouldSniff = false;
2481 bool hasContentType = mResponseHead && mResponseHead->HasContentType();
2482 if (mResponseHead) {
2483 if (!hasContentType) {
2484 shouldSniff = true;
2485 } else {
2486 shouldSniff =
2487 ShouldSniffMisconfiguredType(mResponseHead.get(), mLoadInfo);
2488 }
2489 }
2490 if (shouldSniff) {
2491 MOZ_ASSERT(mConnectionInfo, "Should have connection info here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mConnectionInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mConnectionInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mConnectionInfo"
" (" "Should have connection info here" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2491); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo"
") (" "Should have connection info here" ")"); do { MOZ_CrashSequence
(__null, 2491); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2492 if (!mContentTypeHint.IsEmpty() && !hasContentType) {
2493 mResponseHead->SetContentType(mContentTypeHint);
2494 } else if (mResponseHead->Version() == HttpVersion::v0_9 &&
2495 mConnectionInfo->OriginPort() !=
2496 mConnectionInfo->DefaultPort()) {
2497 mResponseHead->SetContentType(nsLiteralCString(TEXT_PLAIN"text/plain"));
2498 } else if (!mLoadInfo->GetSkipContentSniffing() ||
2499 opaqueResponse == OpaqueResponse::Sniff) {
2500 // Uh-oh. We had better find out what type we are!
2501 mListener = new nsUnknownDecoder(mListener);
2502 unknownDecoderStarted = true;
2503 }
2504 }
2505
2506 // If unknownDecoder is not going to be launched, call
2507 // EnsureOpaqueResponseIsAllowedAfterSniff immediately.
2508 if (!unknownDecoderStarted) {
2509 if (opaqueResponse == OpaqueResponse::SniffCompressed) {
2510 mListener = new nsCompressedAudioVideoImageDetector(
2511 mListener, &HttpBaseChannel::CallTypeSniffers);
2512 } else if (opaqueResponse == OpaqueResponse::Sniff) {
2513 MOZ_DIAGNOSTIC_ASSERT(mORB)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mORB)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(mORB))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("mORB", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2513); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mORB"
")"); do { MOZ_CrashSequence(__null, 2513); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2514 RefPtr<OpaqueResponseBlocker> orb(mORB);
2515 nsresult rv = orb->EnsureOpaqueResponseIsAllowedAfterSniff(this);
2516
2517 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2518 return rv;
2519 }
2520 }
2521 }
2522
2523 // If the content is multipart/x-mixed-replace, we'll insert a MIME decoder
2524 // in the pipeline to handle the content and pass it along to our
2525 // original listener. nsUnknownDecoder doesn't support detecting this type,
2526 // so we only need to insert this using the response header's mime type.
2527 //
2528 // We only do this for unwrapped document loads, since we might want to send
2529 // parts to the external protocol handler without leaving the parent process.
2530 bool mustRunStreamFilterInParent = false;
2531 nsCOMPtr<nsIParentChannel> parentChannel;
2532 NS_QueryNotificationCallbacks(this, parentChannel);
2533 RefPtr<DocumentLoadListener> docListener = do_QueryObject(parentChannel);
2534 if (mResponseHead && docListener && docListener->GetChannel() == this) {
2535 nsAutoCString contentType;
2536 mResponseHead->ContentType(contentType);
2537
2538 if (contentType.Equals("multipart/x-mixed-replace"_ns)) {
2539 nsCOMPtr<nsIStreamConverterService> convServ(
2540 mozilla::components::StreamConverter::Service(&rv));
2541 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2542 nsCOMPtr<nsIStreamListener> toListener(mListener);
2543 nsCOMPtr<nsIStreamListener> fromListener;
2544
2545 rv = convServ->AsyncConvertData("multipart/x-mixed-replace", "*/*",
2546 toListener, nullptr,
2547 getter_AddRefs(fromListener));
2548 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2549 mListener = fromListener;
2550 mustRunStreamFilterInParent = true;
2551 }
2552 }
2553 }
2554 }
2555
2556 // If we installed a multipart converter, then we need to add StreamFilter
2557 // object before it, so that extensions see the un-parsed original stream.
2558 // We may want to add an option for extensions to opt-in to proper multipart
2559 // handling.
2560 // If not, then pass the StreamFilter promise on to DocumentLoadListener,
2561 // where it'll be added in the content process.
2562 for (StreamFilterRequest& request : mStreamFilterRequests) {
2563 if (mustRunStreamFilterInParent) {
2564 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
2565 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
2566 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
2567 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2568 request.mPromise->Reject(false, __func__);
2569 } else {
2570 extensions::StreamFilterParent::Attach(this, std::move(parent));
2571 request.mPromise->Resolve(std::move(child), __func__);
2572 }
2573 } else {
2574 if (docListener) {
2575 docListener->AttachStreamFilter()->ChainTo(request.mPromise.forget(),
2576 __func__);
2577 } else {
2578 request.mPromise->Reject(false, __func__);
2579 }
2580 }
2581 request.mPromise = nullptr;
2582 }
2583 mStreamFilterRequests.Clear();
2584 StoreTracingEnabled(false);
2585
2586 if (mResponseHead && !mResponseHead->HasContentCharset()) {
2587 mResponseHead->SetContentCharset(mContentCharsetHint);
2588 }
2589
2590 if (mCacheEntry && LoadCacheEntryIsWriteOnly()) {
2591 SetCachedContentType();
2592 }
2593
2594 LOG((" calling mListener->OnStartRequest [this=%p, listener=%p]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " calling mListener->OnStartRequest [this=%p, listener=%p]\n"
, this, mListener.get()); } } while (0)
2595 mListener.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " calling mListener->OnStartRequest [this=%p, listener=%p]\n"
, this, mListener.get()); } } while (0)
;
2596
2597 // About to call OnStartRequest, dismiss the guard object.
2598 onStartGuard.release();
2599
2600 if (mListener) {
2601 MOZ_ASSERT(!LoadOnStartRequestCalled(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
" (" "We should not call OsStartRequest twice" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { MOZ_CrashSequence
(__null, 2602); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2602 "We should not call OsStartRequest twice")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
" (" "We should not call OsStartRequest twice" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2602); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { MOZ_CrashSequence
(__null, 2602); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2603 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
2604 StoreOnStartRequestCalled(true);
2605 rv = deleteProtector->OnStartRequest(this);
2606 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2607 } else {
2608 NS_WARNING("OnStartRequest skipped because of null listener")NS_DebugBreak(NS_DEBUG_WARNING, "OnStartRequest skipped because of null listener"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2608)
;
2609 StoreOnStartRequestCalled(true);
2610 }
2611
2612 // Install stream converter if required.
2613 // Normally, we expect the listener to disable content conversion during
2614 // OnStartRequest if it wants to handle it itself (which is common case with
2615 // HttpChannelParent, disabling so that it can be done in the content
2616 // process). If we've installed an nsUnknownDecoder, then we won't yet have
2617 // called OnStartRequest on the final listener (that happens after we send
2618 // OnDataAvailable to the nsUnknownDecoder), so it can't yet have disabled
2619 // content conversion.
2620 // In that case, assume that the listener will disable content conversion,
2621 // unless it's specifically told us that it won't.
2622 if (!unknownDecoderStarted || LoadListenerRequiresContentConversion()) {
2623 nsCOMPtr<nsIStreamListener> listener;
2624 rv =
2625 DoApplyContentConversions(mListener, getter_AddRefs(listener), nullptr);
2626 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2627 return rv;
2628 }
2629 if (listener) {
2630 mListener = listener;
2631 mCompressListener = std::move(listener);
2632
2633 StoreHasAppliedConversion(true);
2634 }
2635 }
2636
2637 // if this channel is for a download, close off access to the cache.
2638 if (mCacheEntry && LoadChannelIsForDownload()) {
2639 mCacheEntry->AsyncDoom(nullptr);
2640
2641 // We must keep the cache entry in case of partial request.
2642 // Concurrent access is the same, we need the entry in
2643 // OnStopRequest.
2644 if (!LoadCachedContentIsPartial() && !LoadConcurrentCacheAccess()) {
2645 CloseCacheEntry(false);
2646 }
2647 }
2648
2649 return NS_OK;
2650}
2651
2652NS_IMETHODIMPnsresult nsHttpChannel::GetHttpProxyConnectResponseCode(
2653 int32_t* aResponseCode) {
2654 NS_ENSURE_ARG_POINTER(aResponseCode)do { if ((__builtin_expect(!!(!(aResponseCode)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResponseCode" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2654); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2655 if (mProxyConnectResponseHead) {
2656 *aResponseCode = mProxyConnectResponseHead->Head().Status();
2657 } else if (mConnectionInfo && mConnectionInfo->UsingConnect()) {
2658 *aResponseCode = 0;
2659 } else {
2660 *aResponseCode = -1;
2661 }
2662 return NS_OK;
2663}
2664
2665NS_IMETHODIMPnsresult nsHttpChannel::GetHttpProxyResponseHeader(
2666 const nsACString& aHeader, nsACString& aValue) {
2667 if (mProxyConnectResponseHead) {
2668 return mProxyConnectResponseHead->Head().GetHeader(
2669 nsHttp::ResolveAtom(aHeader), aValue);
2670 }
2671 return NS_ERROR_NOT_AVAILABLE;
2672}
2673
2674nsresult nsHttpChannel::ProcessFailedProxyConnect(uint32_t httpStatus) {
2675 // Failure to set up a proxy tunnel via CONNECT means one of the following:
2676 // 1) Proxy wants authorization, or forbids.
2677 // 2) DNS at proxy couldn't resolve target URL.
2678 // 3) Proxy connection to target failed or timed out.
2679 // 4) Eve intercepted our CONNECT, and is replying with malicious HTML.
2680 //
2681 // Our current architecture would parse the proxy's response content with
2682 // the permission of the target URL. Given #4, we must avoid rendering the
2683 // body of the reply, and instead give the user a (hopefully helpful)
2684 // boilerplate error page, based on just the HTTP status of the reply.
2685
2686 MOZ_ASSERT(mConnectionInfo->UsingConnect(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mConnectionInfo->UsingConnect())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mConnectionInfo->UsingConnect
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mConnectionInfo->UsingConnect()" " (" "proxy connect failed but not using CONNECT?"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ MOZ_CrashSequence(__null, 2687); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2687 "proxy connect failed but not using CONNECT?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mConnectionInfo->UsingConnect())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mConnectionInfo->UsingConnect
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mConnectionInfo->UsingConnect()" " (" "proxy connect failed but not using CONNECT?"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ MOZ_CrashSequence(__null, 2687); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2688 nsresult rv = HttpProxyResponseToErrorCode(httpStatus);
2689 LOG(("Cancelling failed proxy CONNECT [this=%p httpStatus=%u]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cancelling failed proxy CONNECT [this=%p httpStatus=%u]\n"
, this, httpStatus); } } while (0)
2690 httpStatus))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cancelling failed proxy CONNECT [this=%p httpStatus=%u]\n"
, this, httpStatus); } } while (0)
;
2691
2692 // Make sure the connection is thrown away as it can be in a bad state
2693 // and the proxy may just hang on the next request.
2694 MOZ_ASSERT(mTransaction)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mTransaction)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mTransaction))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mTransaction", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { MOZ_CrashSequence(__null, 2694); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2695 mTransaction->DontReuseConnection();
2696
2697 Cancel(rv);
2698 {
2699 nsresult rv = CallOnStartRequest();
2700 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2701 LOG(("CallOnStartRequest failed [this=%p httpStatus=%u rv=%08x]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "CallOnStartRequest failed [this=%p httpStatus=%u rv=%08x]\n"
, this, httpStatus, static_cast<uint32_t>(rv)); } } while
(0)
2702 httpStatus, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "CallOnStartRequest failed [this=%p httpStatus=%u rv=%08x]\n"
, this, httpStatus, static_cast<uint32_t>(rv)); } } while
(0)
;
2703 }
2704 }
2705 return rv;
2706}
2707
2708static void GetSTSConsoleErrorTag(uint32_t failureResult,
2709 nsAString& consoleErrorTag) {
2710 switch (failureResult) {
2711 case nsISiteSecurityService::ERROR_COULD_NOT_PARSE_HEADER:
2712 consoleErrorTag = u"STSCouldNotParseHeader"_ns;
2713 break;
2714 case nsISiteSecurityService::ERROR_NO_MAX_AGE:
2715 consoleErrorTag = u"STSNoMaxAge"_ns;
2716 break;
2717 case nsISiteSecurityService::ERROR_MULTIPLE_MAX_AGES:
2718 consoleErrorTag = u"STSMultipleMaxAges"_ns;
2719 break;
2720 case nsISiteSecurityService::ERROR_INVALID_MAX_AGE:
2721 consoleErrorTag = u"STSInvalidMaxAge"_ns;
2722 break;
2723 case nsISiteSecurityService::ERROR_MULTIPLE_INCLUDE_SUBDOMAINS:
2724 consoleErrorTag = u"STSMultipleIncludeSubdomains"_ns;
2725 break;
2726 case nsISiteSecurityService::ERROR_INVALID_INCLUDE_SUBDOMAINS:
2727 consoleErrorTag = u"STSInvalidIncludeSubdomains"_ns;
2728 break;
2729 case nsISiteSecurityService::ERROR_COULD_NOT_SAVE_STATE:
2730 consoleErrorTag = u"STSCouldNotSaveState"_ns;
2731 break;
2732 default:
2733 consoleErrorTag = u"STSUnknownError"_ns;
2734 break;
2735 }
2736}
2737
2738/**
2739 * Process an HTTP Strict Transport Security (HSTS) header.
2740 */
2741nsresult nsHttpChannel::ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo) {
2742 nsHttpAtom atom(nsHttp::ResolveAtom("Strict-Transport-Security"_ns));
2743
2744 nsAutoCString securityHeader;
2745 nsresult rv = mResponseHead->GetHeader(atom, securityHeader);
2746 if (rv == NS_ERROR_NOT_AVAILABLE) {
2747 LOG(("nsHttpChannel: No %s header, continuing load.\n", atom.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: No %s header, continuing load.\n", atom.get
()); } } while (0)
;
2748 return NS_OK;
2749 }
2750 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2750)
) {
2751 return rv;
2752 }
2753
2754 if (!aSecInfo) {
2755 LOG(("nsHttpChannel::ProcessHSTSHeader: no securityInfo?"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessHSTSHeader: no securityInfo?"); } } while
(0)
;
2756 return NS_ERROR_INVALID_ARG;
2757 }
2758 nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
2759 rv = aSecInfo->GetOverridableErrorCategory(&overridableErrorCategory);
2760 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2760)
) {
2761 return rv;
2762 }
2763 if (overridableErrorCategory !=
2764 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
2765 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessHSTSHeader: untrustworthy connection - not "
"processing header"); } } while (0)
2766 ("nsHttpChannel::ProcessHSTSHeader: untrustworthy connection - not "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessHSTSHeader: untrustworthy connection - not "
"processing header"); } } while (0)
2767 "processing header"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessHSTSHeader: untrustworthy connection - not "
"processing header"); } } while (0)
;
2768 return NS_ERROR_FAILURE;
2769 }
2770
2771 nsISiteSecurityService* sss = gHttpHandler->GetSSService();
2772 NS_ENSURE_TRUE(sss, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(sss)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sss" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2772); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2773
2774 OriginAttributes originAttributes;
2775 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2776
)
2776 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2776
)
) {
2777 return NS_ERROR_FAILURE;
2778 }
2779
2780 uint32_t failureResult;
2781 rv = sss->ProcessHeader(mURI, securityHeader, originAttributes, nullptr,
2782 nullptr, &failureResult);
2783 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2784 nsAutoString consoleErrorCategory(u"Invalid HSTS Headers"_ns);
2785 nsAutoString consoleErrorTag;
2786 GetSTSConsoleErrorTag(failureResult, consoleErrorTag);
2787 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2788 LOG(("nsHttpChannel: Failed to parse %s header, continuing load.\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: Failed to parse %s header, continuing load.\n"
, atom.get()); } } while (0)
2789 atom.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: Failed to parse %s header, continuing load.\n"
, atom.get()); } } while (0)
;
2790 }
2791 return NS_OK;
2792}
2793
2794// https://github.com/rozbb/waict-integrity-draft/
2795nsresult nsHttpChannel::ProcessWAICTHeader() {
2796#ifdef NIGHTLY_BUILD1
2797 if (!StaticPrefs::security_waict_downgrade_protection_enable()) {
2798 return NS_OK;
2799 }
2800
2801 // The WAICT header is only relevant for document loads.
2802 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
2803 if (type != ExtContentPolicy::TYPE_DOCUMENT &&
2804 type != ExtContentPolicy::TYPE_SUBDOCUMENT) {
2805 return NS_OK;
2806 }
2807
2808 nsISiteIntegrityService* integrityService =
2809 gHttpHandler->GetSiteIntegrityService();
2810 NS_ENSURE_TRUE(integrityService, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(integrityService)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "integrityService" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2810); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2811
2812 // Unlike HSTS, WAICT is supported for HTTP as well, so we need to use the
2813 // correct helper.
2814 OriginAttributes originAttributes;
2815 if (IsHTTPS()) {
2816 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2817
)
2817 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2817
)
) {
2818 return NS_ERROR_FAILURE;
2819 }
2820 } else {
2821 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2822
)
2822 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2822
)
) {
2823 return NS_ERROR_FAILURE;
2824 }
2825 }
2826
2827 nsAutoCString headerValue;
2828 nsresult rv =
2829 mResponseHead->GetHeader(nsHttp::Integrity_Policy_WAICT, headerValue);
2830 if (rv == NS_ERROR_NOT_AVAILABLE || headerValue.IsEmpty()) {
2831 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: No Integrity-Policy-WAICT header, checking if URI is "
"protected.\n"); } } while (0)
2832 ("nsHttpChannel: No Integrity-Policy-WAICT header, checking if URI is "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: No Integrity-Policy-WAICT header, checking if URI is "
"protected.\n"); } } while (0)
2833 "protected.\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: No Integrity-Policy-WAICT header, checking if URI is "
"protected.\n"); } } while (0)
;
2834
2835 bool isProtected = false;
2836 rv = integrityService->IsProtectedURI(mURI, originAttributes, &isProtected);
2837 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2838 return rv;
2839 }
2840
2841 if (isProtected) {
2842 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: URI is protected but missing WAICT header, "
"aborting load.\n"); } } while (0)
2843 ("nsHttpChannel: URI is protected but missing WAICT header, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: URI is protected but missing WAICT header, "
"aborting load.\n"); } } while (0)
2844 "aborting load.\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: URI is protected but missing WAICT header, "
"aborting load.\n"); } } while (0)
;
2845 Cancel(NS_ERROR_CORRUPTED_CONTENT);
2846 DoNotifyListener();
2847 return NS_ERROR_CORRUPTED_CONTENT;
2848 }
2849
2850 LOG(("nsHttpChannel: URI is not protected, continuing load.\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel: URI is not protected, continuing load.\n");
} } while (0)
;
2851 return NS_OK;
2852 }
2853 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2853)
) {
2854 return rv;
2855 }
2856#endif
2857
2858 return NS_OK;
2859}
2860
2861/**
2862 * Decide whether or not to remember Strict-Transport-Security, and whether
2863 * or not to enforce channel integrity.
2864 *
2865 * @return NS_ERROR_FAILURE if there's security information missing even though
2866 * it's an HTTPS connection.
2867 */
2868nsresult nsHttpChannel::ProcessSecurityHeaders() {
2869 // If this channel is not loading securely, STS or PKP doesn't do anything.
2870 // In the case of HSTS, the upgrade to HTTPS takes place earlier in the
2871 // channel load process.
2872 if (!IsHTTPS()) {
2873 return NS_OK;
2874 }
2875
2876 if (IsBrowsingContextDiscarded()) {
2877 return NS_OK;
2878 }
2879
2880 nsAutoCString asciiHost;
2881 nsresult rv = mURI->GetAsciiHost(asciiHost);
2882 NS_ENSURE_SUCCESS(rv, NS_OK)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_OK", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2882); return NS_OK; } } while (false)
;
2883
2884 // If the channel is not a hostname, but rather an IP, do not process STS
2885 // or PKP headers
2886 if (HostIsIPLiteral(asciiHost)) {
2887 return NS_OK;
2888 }
2889
2890 // mSecurityInfo may not always be present, and if it's not then it is okay
2891 // to just disregard any security headers since we know nothing about the
2892 // security of the connection.
2893 NS_ENSURE_TRUE(mSecurityInfo, NS_OK)do { if ((__builtin_expect(!!(!(mSecurityInfo)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mSecurityInfo" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2893); return NS_OK; } } while (false)
;
2894
2895 // Only process HSTS headers for first-party loads. This prevents a
2896 // proliferation of useless HSTS state for partitioned third parties.
2897 if (!mLoadInfo->GetIsThirdPartyContextToTopWindow()) {
2898 rv = ProcessHSTSHeader(mSecurityInfo);
2899 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2899); return rv; } } while (false)
;
2900 }
2901
2902 return NS_OK;
2903}
2904
2905bool nsHttpChannel::IsHTTPS() { return mURI->SchemeIs("https"); }
2906
2907void nsHttpChannel::ProcessSSLInformation() {
2908 // If this is HTTPS, record any use of RSA so that Key Exchange Algorithm
2909 // can be whitelisted for TLS False Start in future sessions. We could
2910 // do the same for DH but its rarity doesn't justify the lookup.
2911
2912 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) || !mSecurityInfo || !IsHTTPS() ||
2913 mPrivateBrowsing) {
2914 return;
2915 }
2916
2917 if (!mSecurityInfo) {
2918 return;
2919 }
2920
2921 uint32_t state;
2922 if (NS_SUCCEEDED(mSecurityInfo->GetSecurityState(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mSecurityInfo->
GetSecurityState(&state))), 1)))
&&
2923 (state & nsIWebProgressListener::STATE_IS_BROKEN)) {
2924 // Send weak crypto warnings to the web console
2925 if (state & nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
2926 nsString consoleErrorTag = u"WeakCipherSuiteWarning"_ns;
2927 nsString consoleErrorCategory = u"SSL"_ns;
2928 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2929 }
2930 }
2931
2932 uint16_t tlsVersion;
2933 nsresult rv = mSecurityInfo->GetProtocolVersion(&tlsVersion);
2934 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
2935 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_2 &&
2936 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_3) {
2937 nsString consoleErrorTag = u"DeprecatedTLSVersion2"_ns;
2938 nsString consoleErrorCategory = u"TLS"_ns;
2939 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2940 }
2941}
2942
2943void nsHttpChannel::ProcessAltService(nsHttpConnectionInfo* aTransConnInfo) {
2944 // e.g. Alt-Svc: h2=":443"; ma=60
2945 // e.g. Alt-Svc: h2="otherhost:443"
2946 // Alt-Svc = 1#( alternative *( OWS ";" OWS parameter ) )
2947 // alternative = protocol-id "=" alt-authority
2948 // protocol-id = token ; percent-encoded ALPN protocol identifier
2949 // alt-authority = quoted-string ; containing [ uri-host ] ":" port
2950
2951 if (!LoadAllowAltSvc()) { // per channel opt out
2952 return;
2953 }
2954
2955 if (mWebTransportSessionEventListener) {
2956 return;
2957 }
2958
2959 if (!gHttpHandler->AllowAltSvc() || (mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7))) {
2960 return;
2961 }
2962
2963 if (IsBrowsingContextDiscarded()) {
2964 return;
2965 }
2966
2967 nsAutoCString scheme;
2968 mURI->GetScheme(scheme);
2969 bool isHttp = scheme.EqualsLiteral("http");
2970 if (!isHttp && !scheme.EqualsLiteral("https")) {
2971 return;
2972 }
2973
2974 nsAutoCString altSvc;
2975 (void)mResponseHead->GetHeader(nsHttp::Alternate_Service, altSvc);
2976 if (altSvc.IsEmpty()) {
2977 return;
2978 }
2979
2980 if (!nsHttp::IsReasonableHeaderValue(altSvc)) {
2981 LOG(("Alt-Svc Response Header seems unreasonable - skipping\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Alt-Svc Response Header seems unreasonable - skipping\n");
} } while (0)
;
2982 return;
2983 }
2984
2985 nsAutoCString originHost;
2986 int32_t originPort = 80;
2987 mURI->GetPort(&originPort);
2988 if (NS_FAILED(mURI->GetAsciiHost(originHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(mURI->GetAsciiHost
(originHost))), 0)))
) {
2989 return;
2990 }
2991
2992 nsCOMPtr<nsIInterfaceRequestor> callbacks;
2993 nsCOMPtr<nsProxyInfo> proxyInfo;
2994 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
2995 getter_AddRefs(callbacks));
2996
2997 if (mProxyInfo) {
2998 proxyInfo = do_QueryInterface(mProxyInfo);
2999 }
3000
3001 OriginAttributes originAttributes;
3002 StoragePrincipalHelper::GetOriginAttributesForHttpConnection(
3003 this, !!proxyInfo, originAttributes);
3004
3005 AltSvcMapping::ProcessHeader(altSvc, scheme, originHost, originPort,
3006 mUsername, mPrivateBrowsing, callbacks,
3007 proxyInfo, mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7),
3008 originAttributes, aTransConnInfo);
3009}
3010
3011nsresult nsHttpChannel::ProcessResponse(nsHttpConnectionInfo* aConnInfo) {
3012 uint32_t httpStatus = mResponseHead->Status();
3013
3014 LOG(("nsHttpChannel::ProcessResponse [this=%p httpStatus=%u]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessResponse [this=%p httpStatus=%u]\n",
this, httpStatus); } } while (0)
3015 httpStatus))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessResponse [this=%p httpStatus=%u]\n",
this, httpStatus); } } while (0)
;
3016
3017 // Gather data on whether the transaction and page (if this is
3018 // the initial page load) is being loaded with SSL.
3019 glean::http::transaction_is_ssl
3020 .EnumGet(static_cast<glean::http::TransactionIsSslLabel>(
3021 mConnectionInfo->EndToEndSSL()))
3022 .Add();
3023 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
3024 glean::http::pageload_is_ssl
3025 .EnumGet(static_cast<glean::http::PageloadIsSslLabel>(
3026 mConnectionInfo->EndToEndSSL()))
3027 .Add();
3028 }
3029
3030 if (Telemetry::CanRecordPrereleaseData()) {
3031 // Gather data on various response status to monitor any increased frequency
3032 // of auth failures due to Bug 1896350
3033 switch (httpStatus) {
3034 case 200:
3035 mozilla::glean::networking::http_response_status_code.Get("200_ok"_ns)
3036 .Add(1);
3037 break;
3038 case 301:
3039 mozilla::glean::networking::http_response_status_code
3040 .Get("301_moved_permanently"_ns)
3041 .Add(1);
3042 break;
3043 case 302:
3044 mozilla::glean::networking::http_response_status_code
3045 .Get("302_found"_ns)
3046 .Add(1);
3047 break;
3048 case 304:
3049 mozilla::glean::networking::http_response_status_code
3050 .Get("304_not_modified"_ns)
3051 .Add(1);
3052 break;
3053 case 307:
3054 mozilla::glean::networking::http_response_status_code
3055 .Get("307_temporary_redirect"_ns)
3056 .Add(1);
3057 break;
3058 case 308:
3059 mozilla::glean::networking::http_response_status_code
3060 .Get("308_permanent_redirect"_ns)
3061 .Add(1);
3062 break;
3063 case 400:
3064 mozilla::glean::networking::http_response_status_code
3065 .Get("400_bad_request"_ns)
3066 .Add(1);
3067 break;
3068 case 401:
3069 mozilla::glean::networking::http_response_status_code
3070 .Get("401_unauthorized"_ns)
3071 .Add(1);
3072 break;
3073 case 403:
3074 mozilla::glean::networking::http_response_status_code
3075 .Get("403_forbidden"_ns)
3076 .Add(1);
3077 break;
3078 case 404:
3079 mozilla::glean::networking::http_response_status_code
3080 .Get("404_not_found"_ns)
3081 .Add(1);
3082 break;
3083 case 421:
3084 mozilla::glean::networking::http_response_status_code
3085 .Get("421_misdirected_request"_ns)
3086 .Add(1);
3087 break;
3088 case 425:
3089 mozilla::glean::networking::http_response_status_code
3090 .Get("425_too_early"_ns)
3091 .Add(1);
3092 break;
3093 case 429:
3094 mozilla::glean::networking::http_response_status_code
3095 .Get("429_too_many_requests"_ns)
3096 .Add(1);
3097 break;
3098 case 500:
3099 mozilla::glean::networking::http_response_status_code
3100 .Get("other_5xx"_ns)
3101 .Add(1);
3102 break;
3103 default:
3104 if (httpStatus >= 400 && httpStatus < 500) {
3105 mozilla::glean::networking::http_response_status_code
3106 .Get("other_4xx"_ns)
3107 .Add(1);
3108 } else if (httpStatus > 500) {
3109 mozilla::glean::networking::http_response_status_code
3110 .Get("other_5xx"_ns)
3111 .Add(1);
3112 } else {
3113 mozilla::glean::networking::http_response_status_code.Get("other"_ns)
3114 .Add(1);
3115 }
3116 break;
3117 }
3118 }
3119
3120 // We use GetReferringPage because mReferrerInfo may not be set at all(this is
3121 // especially useful in xpcshell tests, where we don't have an actual pageload
3122 // to get a referrer from).
3123 // Only allow 407 (authentication required) to continue
3124 if (mTransaction && mTransaction->ProxyConnectFailed() && httpStatus != 407) {
3125 return ProcessFailedProxyConnect(httpStatus);
3126 }
3127
3128 ProcessSSLInformation();
3129
3130 // notify "http-on-examine-response" observers
3131 gHttpHandler->OnExamineResponse(this);
3132
3133 MaybeSuspendAfterExamineResponse();
3134
3135 return ContinueProcessResponse1(aConnInfo);
3136}
3137
3138void nsHttpChannel::AsyncContinueProcessResponse(
3139 nsHttpConnectionInfo* aConnInfo) {
3140 nsresult rv;
3141 rv = ContinueProcessResponse1(aConnInfo);
3142 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3143 // A synchronous failure here would normally be passed as the return
3144 // value from OnStartRequest, which would in turn cancel the request.
3145 // If we're continuing asynchronously, we need to cancel the request
3146 // ourselves.
3147 (void)Cancel(rv);
3148 }
3149}
3150
3151nsresult nsHttpChannel::ContinueProcessResponse1(
3152 nsHttpConnectionInfo* aConnInfo) {
3153 MOZ_ASSERT(!mCallOnResume, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCallOnResume)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCallOnResume))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mCallOnResume"
" (" "How did that happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 3153); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 3153); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3154 nsresult rv = NS_OK;
3155
3156 if (mSuspendCount) {
3157 LOG(("Waiting until resume to finish processing response [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to finish processing response [this=%p]\n"
, this); } } while (0)
3158 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to finish processing response [this=%p]\n"
, this); } } while (0)
;
3159 mCallOnResume = [connInfo = RefPtr{aConnInfo}](nsHttpChannel* self) {
3160 self->AsyncContinueProcessResponse(connInfo);
3161 return NS_OK;
3162 };
3163 return NS_OK;
3164 }
3165
3166 // Check if request was cancelled during http-on-examine-response.
3167 if (mCanceled) {
3168 return CallOnStartRequest();
3169 }
3170
3171 uint32_t httpStatus = mResponseHead->Status();
3172
3173 // STS, Cookies and Alt-Service should not be handled on proxy failure.
3174 // If proxy CONNECT response needs to complete, wait to process connection
3175 // for Strict-Transport-Security.
3176 if (!(mTransaction && mTransaction->ProxyConnectFailed()) &&
3177 (httpStatus != 407)) {
3178 // This block parses the cookie header, collects any cookie changes,
3179 // and sends them to the parent actor.
3180 {
3181 RefPtr<CookieObserver> cookieObserver;
3182 RefPtr<HttpChannelParent> httpParent;
3183 CookieServiceParent::CookieProcessingGuard cookieProcessingGuard;
3184
3185 // Skip parent channel interaction for background revalidating channels.
3186 if (!LoadOnStartRequestCalled() && !mStaleRevalidation) {
3187 // This can only happen when a range request is created again in
3188 // nsHttpChannel::ContinueOnStopRequest. If OnStartRequest is already
3189 // called, we shouldn't call SetCookieHeaders.
3190
3191 MaybeInitializeCookieProcessingGuard(this, cookieProcessingGuard,
3192 cookieObserver, httpParent,
3193 httpStatus);
3194 }
3195
3196 CookieVisitor cookieVisitor(mResponseHead.get());
3197 SetCookieHeaders(cookieVisitor.CookieHeaders());
3198
3199 if (cookieObserver) {
3200 nsTArray<CookieChange> cookieChanges;
3201 cookieObserver->StealChanges(cookieChanges);
3202
3203 if (!cookieChanges.IsEmpty()) {
3204 MOZ_ASSERT(httpParent)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(httpParent)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(httpParent))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("httpParent", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 3204); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpParent"
")"); do { MOZ_CrashSequence(__null, 3204); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3205 httpParent->SetCookieChanges(std::move(cookieChanges));
3206 }
3207 }
3208 }
3209
3210 rv = ProcessWAICTHeader();
3211 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3212 return rv;
3213 }
3214
3215 // Given a successful connection, process any STS or PKP data that's
3216 // relevant.
3217 if (NS_FAILED(ProcessSecurityHeaders())((bool)(__builtin_expect(!!(NS_FAILED_impl(ProcessSecurityHeaders
())), 0)))
) {
3218 NS_WARNING("ProcessSecurityHeaders failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSecurityHeaders failed, continuing load."
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 3218)
;
3219 }
3220
3221 if ((httpStatus < 500) && (httpStatus != 421)) {
3222 ProcessAltService(aConnInfo);
3223 }
3224 }
3225
3226 if (LoadConcurrentCacheAccess() && LoadCachedContentIsPartial() &&
3227 httpStatus != 206) {
3228 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " only expecting 206 when doing partial request during " "interrupted cache concurrent read"
); } } while (0)
3229 (" only expecting 206 when doing partial request during "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " only expecting 206 when doing partial request during " "interrupted cache concurrent read"
); } } while (0)
3230 "interrupted cache concurrent read"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " only expecting 206 when doing partial request during " "interrupted cache concurrent read"
); } } while (0)
;
3231 return NS_ERROR_CORRUPTED_CONTENT;
3232 }
3233
3234 if (httpStatus != 401 && httpStatus != 407) {
3235 // reset the authentication's current continuation state because ourvr
3236 // last authentication attempt has been completed successfully
3237 MOZ_DIAGNOSTIC_ASSERT(mAuthProvider)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAuthProvider)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAuthProvider))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mAuthProvider",
"./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 3237
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3237); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3238 rv = mAuthProvider ? mAuthProvider->Disconnect(NS_ERROR_ABORT)
3239 : NS_ERROR_UNEXPECTED;
3240 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3241 LOG((" Disconnect failed (%08x)", static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Disconnect failed (%08x)", static_cast<uint32_t>(rv
)); } } while (0)
;
3242 }
3243 mAuthProvider = nullptr;
3244 LOG((" continuation state has been reset"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " continuation state has been reset"); } } while (0)
;
3245 }
3246
3247 gHttpHandler->OnAfterExamineResponse(this);
3248
3249 if (mResponseHead && mResponseHead->HasHeader(nsHttp::Clear_Site_Data)) {
3250 if (nsCOMPtr<nsIObserverService> obsService =
3251 services::GetObserverService()) {
3252 obsService->NotifyObservers(static_cast<nsIHttpChannel*>(this),
3253 "clear-site-data", nullptr);
3254 }
3255 }
3256
3257 // No process switch needed, continue as normal.
3258 return ContinueProcessResponse2(rv);
3259}
3260
3261nsresult nsHttpChannel::ContinueProcessResponse2(nsresult rv) {
3262 if (mSuspendCount) {
3263 LOG(("Waiting until resume to finish processing response [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to finish processing response [this=%p]\n"
, this); } } while (0)
3264 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to finish processing response [this=%p]\n"
, this); } } while (0)
;
3265 mCallOnResume = [rv](nsHttpChannel* self) {
3266 (void)self->ContinueProcessResponse2(rv);
3267 return NS_OK;
3268 };
3269 return NS_OK;
3270 }
3271
3272 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCanceled) {
3273 // The process switch failed, cancel this channel.
3274 Cancel(rv);
3275 return CallOnStartRequest();
3276 }
3277
3278 if (mAPIRedirectTo && !mCanceled) {
3279 MOZ_ASSERT(!LoadOnStartRequestCalled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 3279
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 3279); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3280
3281 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
3282 rv = StartRedirectChannelToURI(
3283 mAPIRedirectTo->first(),
3284 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_TEMPORARY |
3285 nsIChannelEventSink::REDIRECT_TRANSPARENT
3286 : nsIChannelEventSink::REDIRECT_TEMPORARY);
3287 mAPIRedirectTo = Nothing();
3288 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3289 return NS_OK;
3290 }
3291 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
3292 }
3293
3294 // Hack: ContinueProcessResponse3 uses NS_OK to detect successful
3295 // redirects, so we distinguish this codepath (a non-redirect that's
3296 // processing normally) by passing in a bogus error code.
3297 return ContinueProcessResponse3(NS_BINDING_FAILED);
3298}
3299
3300nsresult nsHttpChannel::ContinueProcessResponse3(nsresult rv) {
3301 LOG(("nsHttpChannel::ContinueProcessResponse3 [this=%p, rv=%" PRIx32 "]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponse3 [this=%p, rv=%" "x"
"]", this, static_cast<uint32_t>(rv)); } } while (0)
3302 this, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponse3 [this=%p, rv=%" "x"
"]", this, static_cast<uint32_t>(rv)); } } while (0)
;
3303
3304 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3305 // redirectTo() has passed through, we don't want to go on with
3306 // this channel. It will now be canceled by the redirect handling
3307 // code that called this function.
3308 return NS_OK;
3309 }
3310
3311 rv = NS_OK;
3312
3313 uint32_t httpStatus = mResponseHead->Status();
3314 bool transactionRestarted = mTransaction->TakeRestartedState();
3315
3316 // handle different server response categories. Note that we handle
3317 // caching or not caching of error pages in
3318 // nsHttpResponseHead::MustValidate; if you change this switch, update that
3319 // one
3320 switch (httpStatus) {
3321 case 200:
3322 case 203:
3323 // Per RFC 2616, 14.35.2, "A server MAY ignore the Range header".
3324 // So if a server does that and sends 200 instead of 206 that we
3325 // expect, notify our caller.
3326 // However, if we wanted to start from the beginning, let it go through
3327 if (LoadResuming() && mStartPos != 0) {
3328 LOG(("Server ignored our Range header, cancelling [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Server ignored our Range header, cancelling [this=%p]\n", this
); } } while (0)
;
3329 Cancel(NS_ERROR_NOT_RESUMABLE);
3330 rv = CallOnStartRequest();
3331 break;
3332 }
3333 // these can normally be cached
3334 rv = ProcessNormal();
3335 MaybeInvalidateCacheEntryForSubsequentGet();
3336 break;
3337 case 206:
3338 if (LoadCachedContentIsPartial()) { // an internal byte range request...
3339 auto func = [](auto* self, nsresult aRv) {
3340 return self->ContinueProcessResponseAfterPartialContent(aRv);
3341 };
3342 rv = ProcessPartialContent(func);
3343 // Directly call ContinueProcessResponseAfterPartialContent if channel
3344 // is not suspended or ProcessPartialContent throws.
3345 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3346 return ContinueProcessResponseAfterPartialContent(rv);
3347 }
3348 return NS_OK;
3349 } else {
3350 mCacheInputStream.CloseAndRelease();
3351 rv = ProcessNormal();
3352 }
3353 break;
3354 case 301:
3355 case 302:
3356 case 303:
3357 case 307:
3358 case 308:
3359#if 0
3360 case 305: // disabled as a security measure (see bug 187996).
3361#endif
3362 // RFC 9110: 303 responses are cacheable, but only with explicit
3363 // freshness information (max-age or Expires). Without these directives,
3364 // 303 should not be cached.
3365 if (httpStatus == 303) {
3366 uint32_t freshnessLifetime = 0;
3367 bool hasFreshness =
3368 (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
ComputeFreshnessLifetime(&freshnessLifetime))), 1)))
3369 mResponseHead->ComputeFreshnessLifetime(&freshnessLifetime))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
ComputeFreshnessLifetime(&freshnessLifetime))), 1)))
&&
3370 freshnessLifetime > 0) ||
3371 mResponseHead->HasHeader(nsHttp::Expires);
3372 if (mResponseHead->NoStore() || mResponseHead->NoCache() ||
3373 !hasFreshness) {
3374 CloseCacheEntry(false);
3375 }
3376 }
3377 // don't store the response body for redirects
3378 MaybeInvalidateCacheEntryForSubsequentGet();
3379 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
3380 rv = AsyncProcessRedirection(httpStatus);
3381 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3382 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
3383 LOG(("AsyncProcessRedirection failed [rv=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "AsyncProcessRedirection failed [rv=%" "x" "]\n", static_cast
<uint32_t>(rv)); } } while (0)
3384 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "AsyncProcessRedirection failed [rv=%" "x" "]\n", static_cast
<uint32_t>(rv)); } } while (0)
;
3385 // don't cache failed redirect responses.
3386 if (mCacheEntry) mCacheEntry->AsyncDoom(nullptr);
3387 if (DoNotRender3xxBody(rv)) {
3388 mStatus = rv;
3389 DoNotifyListener();
3390 } else {
3391 rv = ContinueProcessResponse4(rv);
3392 }
3393 }
3394 break;
3395 case 304:
3396 if (!ShouldBypassProcessNotModified()) {
3397 auto func = [](auto* self, nsresult aRv) {
3398 return self->ContinueProcessResponseAfterNotModified(aRv);
3399 };
3400 rv = ProcessNotModified(func);
3401 // Directly call ContinueProcessResponseAfterNotModified if channel
3402 // is not suspended or ProcessNotModified throws.
3403 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3404 return ContinueProcessResponseAfterNotModified(rv);
3405 }
3406 return NS_OK;
3407 }
3408
3409 // Don't cache uninformative 304
3410 if (LoadCustomConditionalRequest()) {
3411 CloseCacheEntry(false);
3412 }
3413
3414 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3415 rv = ProcessNormal();
3416 }
3417 break;
3418 case 401:
3419 case 407:
3420 if (MOZ_UNLIKELY(httpStatus == 407 && transactionRestarted)(__builtin_expect(!!(httpStatus == 407 && transactionRestarted
), 0))
) {
3421 // The transaction has been internally restarted. We want to
3422 // authenticate to the proxy again, so reuse either cached credentials
3423 // or use default credentials for NTLM/Negotiate. This prevents
3424 // considering the previously used credentials as invalid.
3425 MOZ_DIAGNOSTIC_ASSERT(mAuthProvider)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAuthProvider)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAuthProvider))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mAuthProvider",
"./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 3425
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3425); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3426 if (!mAuthProvider) {
3427 mStatus = NS_ERROR_UNEXPECTED;
3428 return ProcessNormal();
3429 }
3430 mAuthProvider->ClearProxyIdent();
3431 }
3432 if (!LoadAuthRedirectedChannel() &&
3433 MOZ_UNLIKELY(LoadCustomAuthHeader())(__builtin_expect(!!(LoadCustomAuthHeader()), 0)) && httpStatus == 401) {
3434 // When a custom auth header fails, we don't want to try
3435 // any cached credentials, nor we want to ask the user.
3436 // It's up to the consumer to re-try w/o setting a custom
3437 // auth header if cached credentials should be attempted.
3438 rv = NS_ERROR_FAILURE;
3439 } else if (httpStatus == 401 && LoadUploadStreamIsStreaming() &&
3440 !(mLoadFlags & LOAD_ANONYMOUS)) {
3441 // A body whose source is null cannot be resubmitted with credentials,
3442 // so this is a network error rather than an auth prompt. Ahead of the
3443 // frame-ancestor check, which would still deliver the 401. Still too
3444 // broad for mode "cors" with credentials "include", which the channel
3445 // cannot tell apart from the cases the spec fails here.
3446 // https://fetch.spec.whatwg.org/#concept-http-network-or-cache-fetch
3447 rv = NS_ERROR_NET_BODY_NOT_REPLAYABLE;
3448 } else if (httpStatus == 401 &&
3449 !nsContentSecurityUtils::CheckCSPFrameAncestorAndXFO(this)) {
3450 // CSP Frame Ancestor and X-Frame-Options check has failed
3451 // Do not prompt http auth - Bug 1629307
3452 rv = NS_ERROR_FAILURE;
3453 } else {
3454 MOZ_DIAGNOSTIC_ASSERT(mAuthProvider)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAuthProvider)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAuthProvider))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mAuthProvider",
"./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 3454
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3454); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3455 rv = mAuthProvider
3456 ? mAuthProvider->ProcessAuthentication(
3457 httpStatus, mConnectionInfo->EndToEndSSL() &&
3458 mTransaction &&
3459 mTransaction->ProxyConnectFailed())
3460 : NS_ERROR_UNEXPECTED;
3461 }
3462 if (rv == NS_ERROR_IN_PROGRESS) {
3463 // authentication prompt has been invoked and result
3464 // is expected asynchronously
3465 mIsAuthChannel = true;
3466 mAuthRetryPending = true;
3467 if (httpStatus == 407 ||
3468 (mTransaction && mTransaction->ProxyConnectFailed())) {
3469 StoreProxyAuthPending(true);
3470 }
3471
3472 // suspend the transaction pump to stop receiving the
3473 // unauthenticated content data. We will throw that data
3474 // away when user provides credentials or resume the pump
3475 // when user refuses to authenticate.
3476 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Suspending the transaction, asynchronously prompting for "
"credentials"); } } while (0)
3477 ("Suspending the transaction, asynchronously prompting for "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Suspending the transaction, asynchronously prompting for "
"credentials"); } } while (0)
3478 "credentials"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Suspending the transaction, asynchronously prompting for "
"credentials"); } } while (0)
;
3479 Suspend();
3480
3481#ifdef DEBUG1
3482 // This is for test purposes only. See bug 1683176 for details.
3483 gHttpHandler->OnTransactionSuspendedDueToAuthentication(this);
3484#endif
3485 rv = NS_OK;
3486 } else if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3487 LOG(("ProcessAuthentication failed [rv=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ProcessAuthentication failed [rv=%" "x" "]\n", static_cast
<uint32_t>(rv)); } } while (0)
3488 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ProcessAuthentication failed [rv=%" "x" "]\n", static_cast
<uint32_t>(rv)); } } while (0)
;
3489 if (mTransaction && mTransaction->ProxyConnectFailed()) {
3490 return ProcessFailedProxyConnect(httpStatus);
3491 }
3492 if (rv == NS_ERROR_BASIC_HTTP_AUTH_DISABLED ||
3493 rv == NS_ERROR_NET_BODY_NOT_REPLAYABLE) {
3494 mStatus = rv;
3495 }
3496 rv = ProcessNormal();
3497 } else {
3498 mIsAuthChannel = true;
3499 mAuthRetryPending = true;
3500 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
3501 if (NS_SUCCEEDED(RedirectToNewChannelForAuthRetry())((bool)(__builtin_expect(!!(!NS_FAILED_impl(RedirectToNewChannelForAuthRetry
())), 1)))
) {
3502 return NS_OK;
3503 }
3504 mAuthRetryPending = false;
3505 rv = ProcessNormal();
3506 }
3507 }
3508 break;
3509
3510 case 408:
3511 case 425:
3512 case 429:
3513 // Do not cache 408, 425 and 429.
3514 CloseCacheEntry(false);
3515 [[fallthrough]]; // process normally
3516 default:
3517 rv = ProcessNormal();
3518 MaybeInvalidateCacheEntryForSubsequentGet();
3519 break;
3520 }
3521
3522 UpdateCacheDisposition(false, false);
3523 return rv;
3524}
3525
3526nsresult nsHttpChannel::ContinueProcessResponseAfterPartialContent(
3527 nsresult aRv) {
3528 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponseAfterPartialContent "
"[this=%p, rv=%" "x" "]", this, static_cast<uint32_t>(
aRv)); } } while (0)
3529 ("nsHttpChannel::ContinueProcessResponseAfterPartialContent "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponseAfterPartialContent "
"[this=%p, rv=%" "x" "]", this, static_cast<uint32_t>(
aRv)); } } while (0)
3530 "[this=%p, rv=%" PRIx32 "]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponseAfterPartialContent "
"[this=%p, rv=%" "x" "]", this, static_cast<uint32_t>(
aRv)); } } while (0)
3531 this, static_cast<uint32_t>(aRv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponseAfterPartialContent "
"[this=%p, rv=%" "x" "]", this, static_cast<uint32_t>(
aRv)); } } while (0)
;
3532
3533 UpdateCacheDisposition(false, NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1))));
3534 return aRv;
3535}
3536
3537nsresult nsHttpChannel::ContinueProcessResponseAfterNotModified(nsresult aRv) {
3538 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponseAfterNotModified " "[this=%p, rv=%"
"x" "]", this, static_cast<uint32_t>(aRv)); } } while (
0)
3539 ("nsHttpChannel::ContinueProcessResponseAfterNotModified "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponseAfterNotModified " "[this=%p, rv=%"
"x" "]", this, static_cast<uint32_t>(aRv)); } } while (
0)
3540 "[this=%p, rv=%" PRIx32 "]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponseAfterNotModified " "[this=%p, rv=%"
"x" "]", this, static_cast<uint32_t>(aRv)); } } while (
0)
3541 this, static_cast<uint32_t>(aRv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessResponseAfterNotModified " "[this=%p, rv=%"
"x" "]", this, static_cast<uint32_t>(aRv)); } } while (
0)
;
3542
3543 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))) {
3544 StoreTransactionReplaced(true);
3545 UpdateCacheDisposition(true, false);
3546 return NS_OK;
3547 }
3548
3549 LOG(("ProcessNotModified failed [rv=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ProcessNotModified failed [rv=%" "x" "]\n", static_cast<
uint32_t>(aRv)); } } while (0)
3550 static_cast<uint32_t>(aRv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ProcessNotModified failed [rv=%" "x" "]\n", static_cast<
uint32_t>(aRv)); } } while (0)
;
3551
3552 // We cannot read from the cache entry, it might be in an
3553 // inconsistent state. Doom it and redirect the channel
3554 // to the same URI to reload from the network.
3555 mCacheInputStream.CloseAndRelease();
3556 if (mCacheEntry) {
3557 mCacheEntry->AsyncDoom(nullptr);
3558 mCacheEntry = nullptr;
3559 }
3560
3561 nsresult rv =
3562 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
3563 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3564 return NS_OK;
3565 }
3566
3567 // Don't cache uninformative 304
3568 if (LoadCustomConditionalRequest()) {
3569 CloseCacheEntry(false);
3570 }
3571
3572 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3573 rv = ProcessNormal();
3574 }
3575
3576 UpdateCacheDisposition(false, false);
3577 return rv;
3578}
3579
3580static void ReportHttpResponseVersion(HttpVersion version) {
3581 if (Telemetry::CanRecordPrereleaseData()) {
3582 glean::http::response_version.AccumulateSingleSample(
3583 static_cast<uint32_t>(version));
3584 }
3585 mozilla::glean::networking::http_response_version
3586 .Get(HttpVersionToTelemetryLabel(version))
3587 .Add(1);
3588}
3589
3590void nsHttpChannel::UpdateCacheDisposition(bool aSuccessfulReval,
3591 bool aPartialContentUsed) {
3592 PROFILER_MARKER_TEXT(do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CacheDisposition", ::geckoprofiler::category::NETWORK, {}, ::
geckoprofiler::markers::TextMarker{}, nsPrintfCString( !mDidReval
? "Missed" : (aSuccessfulReval ? "HitViaReval" : "MissedViaReval"
))); } } while (false); } while (false)
3593 "CacheDisposition", NETWORK, {},do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CacheDisposition", ::geckoprofiler::category::NETWORK, {}, ::
geckoprofiler::markers::TextMarker{}, nsPrintfCString( !mDidReval
? "Missed" : (aSuccessfulReval ? "HitViaReval" : "MissedViaReval"
))); } } while (false); } while (false)
3594 nsPrintfCString(do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CacheDisposition", ::geckoprofiler::category::NETWORK, {}, ::
geckoprofiler::markers::TextMarker{}, nsPrintfCString( !mDidReval
? "Missed" : (aSuccessfulReval ? "HitViaReval" : "MissedViaReval"
))); } } while (false); } while (false)
3595 !mDidReval ? "Missed"do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CacheDisposition", ::geckoprofiler::category::NETWORK, {}, ::
geckoprofiler::markers::TextMarker{}, nsPrintfCString( !mDidReval
? "Missed" : (aSuccessfulReval ? "HitViaReval" : "MissedViaReval"
))); } } while (false); } while (false)
3596 : (aSuccessfulReval ? "HitViaReval" : "MissedViaReval")))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("CacheDisposition", ::geckoprofiler::category::NETWORK, {}, ::
geckoprofiler::markers::TextMarker{}, nsPrintfCString( !mDidReval
? "Missed" : (aSuccessfulReval ? "HitViaReval" : "MissedViaReval"
))); } } while (false); } while (false)
;
3597 CacheDisposition cacheDisposition;
3598 if (!mDidReval) {
3599 cacheDisposition = kCacheMissed;
3600 } else if (aSuccessfulReval) {
3601 cacheDisposition = kCacheHitViaReval;
3602 } else {
3603 cacheDisposition = kCacheMissedViaReval;
3604 }
3605 mCacheDisposition = cacheDisposition;
3606
3607 if (Telemetry::CanRecordPrereleaseData()) {
3608 AccumulateCacheHitTelemetry(cacheDisposition, this);
3609 }
3610
3611 ReportHttpResponseVersion(mResponseHead->Version());
3612}
3613
3614// Only used for redirects (3XX responses)
3615nsresult nsHttpChannel::ContinueProcessResponse4(nsresult rv) {
3616 bool doNotRender = DoNotRender3xxBody(rv);
3617
3618 if (rv == NS_ERROR_DOM_BAD_URI && mRedirectURI &&
3619 !net::SchemeIsHttpOrHttps(mRedirectURI)) {
3620 // This was a blocked attempt to redirect and subvert the system by
3621 // redirecting to another protocol (perhaps javascript:)
3622 // In that case we want to throw an error instead of displaying the
3623 // non-redirected response body.
3624 LOG(("ContinueProcessResponse4 detected rejected Non-HTTP Redirection"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueProcessResponse4 detected rejected Non-HTTP Redirection"
); } } while (0)
;
3625 doNotRender = true;
3626 rv = NS_ERROR_CORRUPTED_CONTENT;
3627 }
3628
3629 if (doNotRender) {
3630 Cancel(rv);
3631 DoNotifyListener();
3632 return rv;
3633 }
3634
3635 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3636 UpdateInhibitPersistentCachingFlag();
3637 (void)MaybeReplaceNoVarySearchAliasEntry();
3638
3639 if (mCacheEntry) {
3640 rv = UpdateExpirationTime();
3641 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3642 LOG(("ContinueProcessResponse4 UpdateExpirationTime failed [rv=%x]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueProcessResponse4 UpdateExpirationTime failed [rv=%x]\n"
, static_cast<uint32_t>(rv)); } } while (0)
3643 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueProcessResponse4 UpdateExpirationTime failed [rv=%x]\n"
, static_cast<uint32_t>(rv)); } } while (0)
;
3644 }
3645 }
3646 rv = InitCacheEntry();
3647 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3648 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueProcessResponse4 " "failed to init cache entry [rv=%x]\n"
, static_cast<uint32_t>(rv)); } } while (0)
3649 ("ContinueProcessResponse4 "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueProcessResponse4 " "failed to init cache entry [rv=%x]\n"
, static_cast<uint32_t>(rv)); } } while (0)
3650 "failed to init cache entry [rv=%x]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueProcessResponse4 " "failed to init cache entry [rv=%x]\n"
, static_cast<uint32_t>(rv)); } } while (0)
3651 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueProcessResponse4 " "failed to init cache entry [rv=%x]\n"
, static_cast<uint32_t>(rv)); } } while (0)
;
3652 }
3653 CloseCacheEntry(false);
3654 return NS_OK;
3655 }
3656
3657 LOG(("ContinueProcessResponse4 got failure result [rv=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueProcessResponse4 got failure result [rv=%" "x" "]\n"
, static_cast<uint32_t>(rv)); } } while (0)
3658 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueProcessResponse4 got failure result [rv=%" "x" "]\n"
, static_cast<uint32_t>(rv)); } } while (0)
;
3659 if (mTransaction && mTransaction->ProxyConnectFailed()) {
3660 return ProcessFailedProxyConnect(mRedirectType);
3661 }
3662 return ProcessNormal();
3663}
3664
3665nsresult nsHttpChannel::ProcessNormal() {
3666 LOG(("nsHttpChannel::ProcessNormal [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessNormal [this=%p]\n", this); } } while
(0)
;
3667
3668 return ContinueProcessNormal(NS_OK);
3669}
3670
3671nsresult nsHttpChannel::ContinueProcessNormal(nsresult rv) {
3672 LOG(("nsHttpChannel::ContinueProcessNormal [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessNormal [this=%p]", this); } }
while (0)
;
3673
3674 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3675 // Fill the failure status here, we have failed to fall back, thus we
3676 // have to report our status as failed.
3677 mStatus = rv;
3678 DoNotifyListener();
3679 return rv;
3680 }
3681
3682 rv = ProcessCrossOriginSecurityHeaders();
3683 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3684 mStatus = rv;
3685 HandleAsyncAbort();
3686 return rv;
3687 }
3688
3689 // if we're here, then any byte-range requests failed to result in a partial
3690 // response. we must clear this flag to prevent BufferPartialContent from
3691 // being called inside our OnDataAvailable (see bug 136678).
3692 StoreCachedContentIsPartial(false);
3693
3694 // The body we are about to deliver comes from the network, so no cached
3695 // alternative data describes it. Normally InitCacheEntry() has already
3696 // dropped it, but not when we no longer hold the entry it came from.
3697 mAvailableCachedAltDataType.Truncate();
3698 StoreDeliveringAltData(false);
3699 mAltDataLength = -1;
3700
3701 UpdateInhibitPersistentCachingFlag();
3702
3703 // We may need to install the cache listener before CallonStartRequest,
3704 // since InstallCacheListener can modify the Content-Encoding to remove
3705 // dcb/dcz (and perhaps others), and CallOnStartRequest() copies
3706 // Content-Encoding to send to the content process. If this doesn't
3707 // install a listener (because this isn't a dictionary or
3708 // dictionary-compressed), call it after CallOnStartRequest so that we
3709 // save the compressed data in the cache, and run the decompressor in the
3710 // content process.
3711 mIsDictionaryCompressed = false;
3712 nsAutoCString contentEncoding;
3713 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
3714 if (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
3715 contentEncoding.LowerCaseEqualsLiteral("dcz")) {
3716 mIsDictionaryCompressed = true;
3717 } else if (contentEncoding.LowerCaseFindASCII("dcb") != -1 ||
3718 contentEncoding.LowerCaseFindASCII("dcz") != -1) {
3719 // Reject responses that combine dcb/dcz with other encodings
3720 // (e.g. "dcb, gzip" or "gzip, dcz"). We don't support chained
3721 // dictionary compression with other compression methods.
3722 LOG_DICTIONARIES(("Rejecting response with unsupported multi-encoding: %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Rejecting response with unsupported multi-encoding: %s"
, contentEncoding.get()); } } while (0)
3723 contentEncoding.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Rejecting response with unsupported multi-encoding: %s"
, contentEncoding.get()); } } while (0)
;
3724 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
3725 return NS_ERROR_INVALID_CONTENT_ENCODING;
3726 }
3727
3728 (void)MaybeReplaceNoVarySearchAliasEntry();
3729
3730 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3731 // Must update expiration time early - ParseDictionary reads it, and
3732 // it's no longer done in InitCacheEntry to avoid double calculation
3733 rv = UpdateExpirationTime();
3734 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3735 LOG(("UpdateExpirationTime failed in ContinueProcessNormal"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "UpdateExpirationTime failed in ContinueProcessNormal"); } }
while (0)
;
3736 }
3737
3738 // XXX We may want to consider recompressing any dcb/dcz files to save space
3739 // and improve hitrate. Downside is CPU use, complexity and perhaps delay,
3740 // maybe.
3741 nsAutoCString dictionary;
3742 if (StaticPrefs::network_http_dictionaries_enable() && IsHTTPS()) {
3743 (void)mResponseHead->GetHeader(nsHttp::Use_As_Dictionary, dictionary);
3744 if (!dictionary.IsEmpty()) {
3745 if (!ParseDictionary(mCacheEntry, mResponseHead.get(), true)) {
3746 LOG_DICTIONARIES(("Failed to parse use-as-dictionary"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Failed to parse use-as-dictionary"
); } } while (0)
;
3747 } else {
3748 MOZ_ASSERT(mDictSaving)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDictSaving)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDictSaving))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mDictSaving", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 3748); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDictSaving"
")"); do { MOZ_CrashSequence(__null, 3748); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3749
3750 // We need to record the hash as we save it
3751 mCacheEntry->SetDictionary(mDictSaving);
3752 }
3753 }
3754 }
3755
3756 // we would call DoInstallCacheListener() here, but it will close the
3757 // cache input stream, which causes problems if we going to be
3758 // suspended because we're replacing a active dictionary. Instead we'll
3759 // call it in ContinueProcessNormal2()
3760 } else {
3761 if (mIsDictionaryCompressed) {
3762 // We still need to decompress in the parent if it's dcb or dcz even if
3763 // not saving to the cache
3764 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Removing Content-Encoding %s for %p"
, contentEncoding.get(), this); } } while (0)
3765 ("Removing Content-Encoding %s for %p", contentEncoding.get(), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Removing Content-Encoding %s for %p"
, contentEncoding.get(), this); } } while (0)
;
3766 nsCOMPtr<nsIStreamListener> listener;
3767 // otherwise we won't convert in the parent process
3768 // XXX may be redundant, but safe
3769 SetApplyConversion(true);
3770 rv = DoApplyContentConversionsInternal(
3771 mListener, getter_AddRefs(listener), true, nullptr);
3772 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3773 return rv;
3774 }
3775 if (listener) {
3776 LOG_DICTIONARIES(("Installed nsHTTPCompressConv %p without cache tee",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Installed nsHTTPCompressConv %p without cache tee"
, listener.get()); } } while (0)
3777 listener.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Installed nsHTTPCompressConv %p without cache tee"
, listener.get()); } } while (0)
;
3778 mListener = listener;
3779 mCompressListener = std::move(listener);
3780 StoreHasAppliedConversion(true);
3781 } else {
3782 LOG_DICTIONARIES(("Didn't install decompressor without cache tee"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Didn't install decompressor without cache tee"
); } } while (0)
;
3783 // This should never happen for dictionary-compressed content (dcb/dcz)
3784 // as it MUST be decompressed in the parent process
3785 if (mIsDictionaryCompressed) {
3786 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Failed to install decompressor for "
"dictionary-compressed content"); } } while (0)
3787 ("FATAL: Failed to install decompressor for "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Failed to install decompressor for "
"dictionary-compressed content"); } } while (0)
3788 "dictionary-compressed content"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Failed to install decompressor for "
"dictionary-compressed content"); } } while (0)
;
3789 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
3790 return NS_ERROR_INVALID_CONTENT_ENCODING;
3791 }
3792 }
3793 }
3794 } // else we'll call InstallCacheListener after CallOnStartRequest
3795
3796 // ParseDictionary may have resulted in our Suspend()ing this request
3797 // until the old dictionary we're replacing has been read from the cache.
3798 // If we continue we'll call InitCacheEntry() and Doom/truncate the entry
3799 // the old one is reading from.
3800 return ContinueProcessNormal2(rv);
3801}
3802
3803nsresult nsHttpChannel::ContinueProcessNormal2(nsresult rv) {
3804 if (mSuspendCount) {
3805 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "*** Suspended %s in ContinueProcessNormal for dictionary "
"replacement! [this=%p]\n", mSpec.get(), this); } } while (
0)
3806 ("*** Suspended %s in ContinueProcessNormal for dictionary "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "*** Suspended %s in ContinueProcessNormal for dictionary "
"replacement! [this=%p]\n", mSpec.get(), this); } } while (
0)
3807 "replacement! [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "*** Suspended %s in ContinueProcessNormal for dictionary "
"replacement! [this=%p]\n", mSpec.get(), this); } } while (
0)
3808 mSpec.get(), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "*** Suspended %s in ContinueProcessNormal for dictionary "
"replacement! [this=%p]\n", mSpec.get(), this); } } while (
0)
;
3809 LOG(("Waiting until resume to finish processing response [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to finish processing response [this=%p]\n"
, this); } } while (0)
3810 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to finish processing response [this=%p]\n"
, this); } } while (0)
;
3811 mCallOnResume = [rv](nsHttpChannel* self) {
3812 (void)self->ContinueProcessNormal2(rv);
3813 return NS_OK;
3814 };
3815 return NS_OK;
3816 }
3817
3818 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCanceled) {
3819 // The process switch failed, cancel this channel.
3820 Cancel(rv);
3821 return CallOnStartRequest();
3822 }
3823
3824 // this must be called before firing OnStartRequest, since http clients,
3825 // such as imagelib, expect our cache entry to already have the correct
3826 // expiration time (bug 87710).
3827 if (mCacheEntry) {
3828 rv = InitCacheEntry();
3829 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CloseCacheEntry(true);
3830 }
3831
3832 // CRITICAL: Check if dictionary is ready BEFORE creating decompressor.
3833 // If we create the decompressor before the dictionary is ready, it will
3834 // be created without the dictionary attached, causing decompression to fail.
3835 // The dictionary prefetch callback (in PrepareToConnect) will call Resume()
3836 // when ready, which will re-invoke ContinueProcessNormal2 via mCallOnResume.
3837 if (mIsDictionaryCompressed && mDictDecompress && mUsingDictionary &&
3838 mShouldSuspendForDictionary && !mDictDecompress->DictionaryReady()) {
3839 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsHttpChannel::ContinueProcessNormal2 [this=%p] Suspending before "
"creating decompressor, waiting for dictionary", this); } } while
(0)
3840 ("nsHttpChannel::ContinueProcessNormal2 [this=%p] Suspending before "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsHttpChannel::ContinueProcessNormal2 [this=%p] Suspending before "
"creating decompressor, waiting for dictionary", this); } } while
(0)
3841 "creating decompressor, waiting for dictionary",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsHttpChannel::ContinueProcessNormal2 [this=%p] Suspending before "
"creating decompressor, waiting for dictionary", this); } } while
(0)
3842 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "nsHttpChannel::ContinueProcessNormal2 [this=%p] Suspending before "
"creating decompressor, waiting for dictionary", this); } } while
(0)
;
3843 Suspend();
3844 mSuspendedForDictionary = true;
3845 // Set up callback to resume processing when dictionary loads
3846 mCallOnResume = [](nsHttpChannel* self) {
3847 return self->ContinueProcessNormal3();
3848 };
3849 return NS_OK;
3850 }
3851
3852 return ContinueProcessNormal3();
3853}
3854
3855nsresult nsHttpChannel::ContinueProcessNormal3() {
3856 if (mCanceled) {
3857 return CallOnStartRequest();
3858 }
3859 nsresult rv = NS_OK;
3860
3861 // Finish post-ParseDictionary work, must be done after waiting if Suspended
3862 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3863 if (mIsDictionaryCompressed || mDictSaving) {
3864 if (MOZ_LOG_TEST(mozilla::net::gDictionaryLog,(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
3865 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
) {
3866 nsAutoCString ceDebug;
3867 if (mResponseHead) {
3868 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, ceDebug);
3869 }
3870 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "ContinueProcessNormal3 [this=%p] dictCompressed=%d "
"dictSaving=%p Content-Encoding='%s' ApplyConversion=%d " "HasApplied=%d"
, this, mIsDictionaryCompressed, mDictSaving.get(), ceDebug.get
(), LoadApplyConversion(), LoadHasAppliedConversion()); } } while
(0)
3871 ("ContinueProcessNormal3 [this=%p] dictCompressed=%d "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "ContinueProcessNormal3 [this=%p] dictCompressed=%d "
"dictSaving=%p Content-Encoding='%s' ApplyConversion=%d " "HasApplied=%d"
, this, mIsDictionaryCompressed, mDictSaving.get(), ceDebug.get
(), LoadApplyConversion(), LoadHasAppliedConversion()); } } while
(0)
3872 "dictSaving=%p Content-Encoding='%s' ApplyConversion=%d "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "ContinueProcessNormal3 [this=%p] dictCompressed=%d "
"dictSaving=%p Content-Encoding='%s' ApplyConversion=%d " "HasApplied=%d"
, this, mIsDictionaryCompressed, mDictSaving.get(), ceDebug.get
(), LoadApplyConversion(), LoadHasAppliedConversion()); } } while
(0)
3873 "HasApplied=%d",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "ContinueProcessNormal3 [this=%p] dictCompressed=%d "
"dictSaving=%p Content-Encoding='%s' ApplyConversion=%d " "HasApplied=%d"
, this, mIsDictionaryCompressed, mDictSaving.get(), ceDebug.get
(), LoadApplyConversion(), LoadHasAppliedConversion()); } } while
(0)
3874 this, mIsDictionaryCompressed, mDictSaving.get(), ceDebug.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "ContinueProcessNormal3 [this=%p] dictCompressed=%d "
"dictSaving=%p Content-Encoding='%s' ApplyConversion=%d " "HasApplied=%d"
, this, mIsDictionaryCompressed, mDictSaving.get(), ceDebug.get
(), LoadApplyConversion(), LoadHasAppliedConversion()); } } while
(0)
3875 LoadApplyConversion(), LoadHasAppliedConversion()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "ContinueProcessNormal3 [this=%p] dictCompressed=%d "
"dictSaving=%p Content-Encoding='%s' ApplyConversion=%d " "HasApplied=%d"
, this, mIsDictionaryCompressed, mDictSaving.get(), ceDebug.get
(), LoadApplyConversion(), LoadHasAppliedConversion()); } } while
(0)
;
3876 }
3877 LOG(("Decompressing before saving into cache [channel=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Decompressing before saving into cache [channel=%p]", this
); } } while (0)
;
3878 rv = DoInstallCacheListener(mIsDictionaryCompressed || mDictSaving, 0);
3879 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3880 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "DoInstallCacheListener FAILED: %x"
, static_cast<uint32_t>(rv)); } } while (0)
3881 ("DoInstallCacheListener FAILED: %x", static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "DoInstallCacheListener FAILED: %x"
, static_cast<uint32_t>(rv)); } } while (0)
;
3882 // Cache entry is now corrupted - we set up headers with dcb/dcz
3883 // Content-Encoding but failed to install the decompressor that would
3884 // clear it. Doom the entry to prevent serving corrupted data.
3885 CloseCacheEntry(true);
3886 }
3887 }
3888 }
3889
3890 // Check that the server sent us what we were asking for
3891 if (LoadResuming()) {
3892 // Create an entity id from the response
3893 nsAutoCString id;
3894 rv = GetEntityID(id);
3895 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3896 // If creating an entity id is not possible -> error
3897 Cancel(NS_ERROR_NOT_RESUMABLE);
3898 } else if (mResponseHead->Status() != 206 &&
3899 mResponseHead->Status() != 200) {
3900 // Probably 404 Not Found, 412 Precondition Failed or
3901 // 416 Invalid Range -> error
3902 LOG(("Unexpected response status while resuming, aborting [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Unexpected response status while resuming, aborting [this=%p]\n"
, this); } } while (0)
3903 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Unexpected response status while resuming, aborting [this=%p]\n"
, this); } } while (0)
;
3904 Cancel(NS_ERROR_ENTITY_CHANGED);
3905 }
3906 // If we were passed an entity id, verify it's equal to the server's
3907 else if (!mEntityID.IsEmpty()) {
3908 if (!mEntityID.Equals(id)) {
3909 LOG(("Entity mismatch, expected '%s', got '%s', aborting [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Entity mismatch, expected '%s', got '%s', aborting [this=%p]"
, mEntityID.get(), id.get(), this); } } while (0)
3910 mEntityID.get(), id.get(), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Entity mismatch, expected '%s', got '%s', aborting [this=%p]"
, mEntityID.get(), id.get(), this); } } while (0)
;
3911 Cancel(NS_ERROR_ENTITY_CHANGED);
3912 }
3913 }
3914 }
3915
3916 rv = CallOnStartRequest();
3917 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3918
3919 // If we didn't install cache listeners to decompress above
3920 // install the cache listener now (so they'll get compressed data)
3921 if (!mIsDictionaryCompressed && !mDictSaving) {
3922 // install cache listener if we still have a cache entry open
3923 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3924 if (MOZ_LOG_TEST(mozilla::net::gDictionaryLog,(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
3925 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
&&
3926 mResponseHead) {
3927 nsAutoCString ceCheck;
3928 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, ceCheck);
3929 if (!ceCheck.IsEmpty()) {
3930 nsAutoCString uadCheck;
3931 (void)mResponseHead->GetHeader(nsHttp::Use_As_Dictionary, uadCheck);
3932 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WARNING: Saving cache entry with Content-Encoding='%s' "
"without decompression (mDictSaving=%p " "Use-As-Dictionary='%s') for %s [this=%p]"
, ceCheck.get(), mDictSaving.get(), uadCheck.get(), mSpec.get
(), this); } } while (0)
3933 ("WARNING: Saving cache entry with Content-Encoding='%s' "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WARNING: Saving cache entry with Content-Encoding='%s' "
"without decompression (mDictSaving=%p " "Use-As-Dictionary='%s') for %s [this=%p]"
, ceCheck.get(), mDictSaving.get(), uadCheck.get(), mSpec.get
(), this); } } while (0)
3934 "without decompression (mDictSaving=%p "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WARNING: Saving cache entry with Content-Encoding='%s' "
"without decompression (mDictSaving=%p " "Use-As-Dictionary='%s') for %s [this=%p]"
, ceCheck.get(), mDictSaving.get(), uadCheck.get(), mSpec.get
(), this); } } while (0)
3935 "Use-As-Dictionary='%s') for %s [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WARNING: Saving cache entry with Content-Encoding='%s' "
"without decompression (mDictSaving=%p " "Use-As-Dictionary='%s') for %s [this=%p]"
, ceCheck.get(), mDictSaving.get(), uadCheck.get(), mSpec.get
(), this); } } while (0)
3936 ceCheck.get(), mDictSaving.get(), uadCheck.get(), mSpec.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WARNING: Saving cache entry with Content-Encoding='%s' "
"without decompression (mDictSaving=%p " "Use-As-Dictionary='%s') for %s [this=%p]"
, ceCheck.get(), mDictSaving.get(), uadCheck.get(), mSpec.get
(), this); } } while (0)
3937 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "WARNING: Saving cache entry with Content-Encoding='%s' "
"without decompression (mDictSaving=%p " "Use-As-Dictionary='%s') for %s [this=%p]"
, ceCheck.get(), mDictSaving.get(), uadCheck.get(), mSpec.get
(), this); } } while (0)
;
3938 }
3939 }
3940 rv = InstallCacheListener();
3941 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3942 }
3943 }
3944 return NS_OK;
3945}
3946
3947nsresult nsHttpChannel::PromptTempRedirect() {
3948 if (!gHttpHandler->PromptTempRedirect()) {
3949 return NS_OK;
3950 }
3951 nsresult rv;
3952 nsCOMPtr<nsIStringBundleService> bundleService;
3953 bundleService = mozilla::components::StringBundle::Service(&rv);
3954 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3955
3956 nsCOMPtr<nsIStringBundle> stringBundle;
3957 rv =
3958 bundleService->CreateBundle(NECKO_MSGS_URL"chrome://necko/locale/necko.properties", getter_AddRefs(stringBundle));
3959 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3960
3961 nsAutoString messageString;
3962 rv = stringBundle->GetStringFromName("RepostFormData", messageString);
3963 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3964 bool repost = false;
3965
3966 nsCOMPtr<nsIPrompt> prompt;
3967 GetCallback(prompt);
3968 if (!prompt) return NS_ERROR_NO_INTERFACE;
3969
3970 prompt->Confirm(nullptr, messageString.get(), &repost);
3971 if (!repost) return NS_ERROR_FAILURE;
3972 }
3973
3974 return rv;
3975}
3976
3977nsresult nsHttpChannel::ProxyFailover() {
3978 LOG(("nsHttpChannel::ProxyFailover [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProxyFailover [this=%p]\n", this); } } while
(0)
;
3979
3980 nsresult rv;
3981
3982 nsCOMPtr<nsIProtocolProxyService> pps;
3983 pps = mozilla::components::ProtocolProxy::Service(&rv);
3984 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3985
3986 nsCOMPtr<nsIProxyInfo> pi;
3987 rv = pps->GetFailoverForProxy(mConnectionInfo->ProxyInfo(), mURI, mStatus,
3988 getter_AddRefs(pi));
3989#ifdef MOZ_PROXY_DIRECT_FAILOVER1
3990 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3991 if (!StaticPrefs::network_proxy_failover_direct()) {
3992 return rv;
3993 }
3994 // If this request used a failed proxy and there is no failover available,
3995 // fallback to DIRECT connections for conservative requests.
3996 if (LoadBeConservative()) {
3997 rv = pps->NewProxyInfo("direct"_ns, ""_ns, 0, ""_ns, ""_ns, 0, UINT32_MAX(4294967295U),
3998 nullptr, getter_AddRefs(pi));
3999 }
4000#endif
4001 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4002 return rv;
4003 }
4004#ifdef MOZ_PROXY_DIRECT_FAILOVER1
4005 }
4006#endif
4007
4008 // XXXbz so where does this codepath remove us from the loadgroup,
4009 // exactly?
4010 return AsyncDoReplaceWithProxy(pi);
4011}
4012
4013void nsHttpChannel::SetHTTPSSVCRecord(
4014 already_AddRefed<nsIDNSHTTPSSVCRecord> aRecord) {
4015 LOG(("nsHttpChannel::SetHTTPSSVCRecord [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetHTTPSSVCRecord [this=%p]\n", this); } } while
(0)
;
4016 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
4017 MOZ_ASSERT(!mHTTPSSVCRecord)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mHTTPSSVCRecord)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mHTTPSSVCRecord))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mHTTPSSVCRecord"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 4017
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mHTTPSSVCRecord"
")"); do { MOZ_CrashSequence(__null, 4017); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4018 mHTTPSSVCRecord.emplace(std::move(record));
4019}
4020
4021void nsHttpChannel::HandleAsyncRedirectChannelToHttps() {
4022 MOZ_ASSERT(!mCallOnResume, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCallOnResume)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCallOnResume))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mCallOnResume"
" (" "How did that happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4022); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4023
4024 if (mSuspendCount) {
4025 LOG(("Waiting until resume to do async redirect to https [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to do async redirect to https [this=%p]\n"
, this); } } while (0)
4026 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to do async redirect to https [this=%p]\n"
, this); } } while (0)
;
4027 mCallOnResume = [](nsHttpChannel* self) {
4028 self->HandleAsyncRedirectChannelToHttps();
4029 return NS_OK;
4030 };
4031 return;
4032 }
4033
4034 nsresult rv = StartRedirectChannelToHttps();
4035 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4036 rv = ContinueAsyncRedirectChannelToURI(rv);
4037 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4038 LOG(("ContinueAsyncRedirectChannelToURI failed (%08x) [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueAsyncRedirectChannelToURI failed (%08x) [this=%p]\n"
, static_cast<uint32_t>(rv), this); } } while (0)
4039 static_cast<uint32_t>(rv), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueAsyncRedirectChannelToURI failed (%08x) [this=%p]\n"
, static_cast<uint32_t>(rv), this); } } while (0)
;
4040 }
4041 }
4042}
4043
4044nsresult nsHttpChannel::StartRedirectChannelToHttps() {
4045 LOG(("nsHttpChannel::HandleAsyncRedirectChannelToHttps() [STS]\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::HandleAsyncRedirectChannelToHttps() [STS]\n"
); } } while (0)
;
4046
4047 nsCOMPtr<nsIURI> upgradedURI;
4048 nsresult rv = NS_GetSecureUpgradedURI(mURI, getter_AddRefs(upgradedURI));
4049 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4049); return rv; } } while (false)
;
4050
4051 return StartRedirectChannelToURI(
4052 upgradedURI, nsIChannelEventSink::REDIRECT_PERMANENT |
4053 nsIChannelEventSink::REDIRECT_STS_UPGRADE);
4054}
4055
4056void nsHttpChannel::HandleAsyncAPIRedirect() {
4057 MOZ_ASSERT(!mCallOnResume, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCallOnResume)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCallOnResume))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mCallOnResume"
" (" "How did that happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4057); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4057); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4058 MOZ_ASSERT(mAPIRedirectTo, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAPIRedirectTo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAPIRedirectTo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mAPIRedirectTo"
" (" "How did that happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4058); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4059 MOZ_ASSERT(mAPIRedirectTo->first(), "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAPIRedirectTo->first())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAPIRedirectTo->first()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("mAPIRedirectTo->first()"
" (" "How did that happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4059); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo->first()"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4059); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4060
4061 if (mSuspendCount) {
4062 LOG(("Waiting until resume to do async API redirect [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to do async API redirect [this=%p]\n"
, this); } } while (0)
;
4063 mCallOnResume = [](nsHttpChannel* self) {
4064 self->HandleAsyncAPIRedirect();
4065 return NS_OK;
4066 };
4067 return;
4068 }
4069
4070 nsresult rv = StartRedirectChannelToURI(
4071 mAPIRedirectTo->first(),
4072 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_PERMANENT |
4073 nsIChannelEventSink::REDIRECT_TRANSPARENT
4074 : nsIChannelEventSink::REDIRECT_PERMANENT);
4075 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4076 rv = ContinueAsyncRedirectChannelToURI(rv);
4077 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4078 LOG(("ContinueAsyncRedirectChannelToURI failed (%08x) [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueAsyncRedirectChannelToURI failed (%08x) [this=%p]\n"
, static_cast<uint32_t>(rv), this); } } while (0)
4079 static_cast<uint32_t>(rv), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueAsyncRedirectChannelToURI failed (%08x) [this=%p]\n"
, static_cast<uint32_t>(rv), this); } } while (0)
;
4080 }
4081 }
4082}
4083
4084void nsHttpChannel::HandleAsyncRedirectToUnstrippedURI() {
4085 MOZ_ASSERT(!mCallOnResume, "How did that happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCallOnResume)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCallOnResume))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mCallOnResume"
" (" "How did that happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4085); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4085); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4086
4087 if (mSuspendCount) {
4088 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to do async redirect to unstripped URI "
"[this=%p]\n", this); } } while (0)
4089 ("Waiting until resume to do async redirect to unstripped URI "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to do async redirect to unstripped URI "
"[this=%p]\n", this); } } while (0)
4090 "[this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to do async redirect to unstripped URI "
"[this=%p]\n", this); } } while (0)
4091 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume to do async redirect to unstripped URI "
"[this=%p]\n", this); } } while (0)
;
4092 mCallOnResume = [](nsHttpChannel* self) {
4093 self->HandleAsyncRedirectToUnstrippedURI();
4094 return NS_OK;
4095 };
4096 return;
4097 }
4098
4099 nsCOMPtr<nsIURI> unstrippedURI;
4100 mLoadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
4101
4102 // Clear the unstripped URI from the loadInfo before starting redirect in case
4103 // endless redirect.
4104 mLoadInfo->SetUnstrippedURI(nullptr);
4105
4106 nsresult rv = StartRedirectChannelToURI(
4107 unstrippedURI, nsIChannelEventSink::REDIRECT_PERMANENT);
4108
4109 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4110 rv = ContinueAsyncRedirectChannelToURI(rv);
4111 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4112 LOG(("ContinueAsyncRedirectChannelToURI failed (%08x) [this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueAsyncRedirectChannelToURI failed (%08x) [this=%p]\n"
, static_cast<uint32_t>(rv), this); } } while (0)
4113 static_cast<uint32_t>(rv), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "ContinueAsyncRedirectChannelToURI failed (%08x) [this=%p]\n"
, static_cast<uint32_t>(rv), this); } } while (0)
;
4114 }
4115 }
4116}
4117nsresult nsHttpChannel::RedirectToNewChannelForAuthRetry() {
4118 LOG(("nsHttpChannel::RedirectToNewChannelForAuthRetry %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::RedirectToNewChannelForAuthRetry %p", this)
; } } while (0)
;
4119 nsresult rv = NS_OK;
4120
4121 nsCOMPtr<nsILoadInfo> redirectLoadInfo = CloneLoadInfoForRedirect(
4122 mURI, nsIChannelEventSink::REDIRECT_INTERNAL |
4123 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4124
4125 nsCOMPtr<nsIIOService> ioService;
4126
4127 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
4128 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4128); return rv; } } while (false)
;
4129
4130 nsCOMPtr<nsIChannel> newChannel;
4131 rv = gHttpHandler->NewProxiedChannel(mURI, mProxyInfo, mProxyResolveFlags,
4132 mProxyURI, mLoadInfo,
4133 getter_AddRefs(newChannel));
4134
4135 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4135); return rv; } } while (false)
;
4136
4137 rv = SetupReplacementChannel(mURI, newChannel, true,
4138 nsIChannelEventSink::REDIRECT_INTERNAL |
4139 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4140 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4140); return rv; } } while (false)
;
4141
4142 // rewind the upload stream
4143 if (mUploadStream) {
4144 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
4145 nsresult rv = NS_ERROR_NO_INTERFACE;
4146 if (seekable) {
4147 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
4148 }
4149
4150 // This should not normally happen, but it's possible that big memory
4151 // blobs originating in the other process can't be rewinded.
4152 // In that case we just fail the request, otherwise the content length
4153 // will not match and this load will never complete.
4154 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4154); return rv; } } while (false)
;
4155 }
4156
4157 RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel);
4158
4159 MOZ_ASSERT(mAuthProvider)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAuthProvider)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAuthProvider))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mAuthProvider",
"./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 4159
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthProvider" ")"
); do { MOZ_CrashSequence(__null, 4159); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4160 httpChannelImpl->mAuthProvider = std::move(mAuthProvider);
4161
4162 httpChannelImpl->mProxyInfo = mProxyInfo;
4163
4164 if ((mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) ||
4165 mTransaction->HasStickyConnection()) {
4166 mConnectionInfo = mTransaction->GetConnInfo();
4167
4168 httpChannelImpl->mTransactionSticky = mTransaction;
4169
4170 if (mTransaction->Http2Disabled()) {
4171 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
4172 }
4173 if (mTransaction->Http3Disabled()) {
4174 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
4175 }
4176 }
4177 // always set sticky connection flag
4178 httpChannelImpl->mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
4179
4180 if (LoadAuthConnectionRestartable()) {
4181 httpChannelImpl->mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
4182 } else {
4183 httpChannelImpl->mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
4184 }
4185
4186 MOZ_ASSERT(mConnectionInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mConnectionInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mConnectionInfo))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mConnectionInfo"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 4186
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo" ")"
); do { MOZ_CrashSequence(__null, 4186); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4187 httpChannelImpl->mConnectionInfo = mConnectionInfo;
4188
4189 // we need to store the state to skip unnecessary checks in the new channel
4190 httpChannelImpl->StoreAuthRedirectedChannel(true);
4191
4192 // We must copy proxy and auth header to the new channel.
4193 // Although the new channel can populate auth headers from auth cache, we
4194 // would still like to use the auth headers generated in this channel. The
4195 // main reason for doing this is that certain connection-based/stateful auth
4196 // schemes like NTLM will fail when we try generate the credentials more than
4197 // the number of times the server has presented us the challenge due to the
4198 // usage of nonce in generating the credentials Copying the auth header will
4199 // bypass generation of the credentials
4200 nsAutoCString authVal;
4201 if (NS_SUCCEEDED(GetRequestHeader("Proxy-Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Proxy-Authorization"_ns, authVal))), 1)))
) {
4202 httpChannelImpl->SetRequestHeader("Proxy-Authorization"_ns, authVal, false);
4203 }
4204 if (NS_SUCCEEDED(GetRequestHeader("Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Authorization"_ns, authVal))), 1)))
) {
4205 httpChannelImpl->SetRequestHeader("Authorization"_ns, authVal, false);
4206 }
4207
4208 httpChannelImpl->SetBlockAuthPrompt(LoadBlockAuthPrompt());
4209 mRedirectChannel = newChannel;
4210
4211 rv = gHttpHandler->AsyncOnChannelRedirect(
4212 this, newChannel,
4213 nsIChannelEventSink::REDIRECT_INTERNAL |
4214 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4215
4216 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4217
4218 // redirected channel will be opened after we receive the OnStopRequest
4219
4220 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4221 AutoRedirectVetoNotifier notifier(this, rv);
4222 mRedirectChannel = nullptr;
4223 }
4224
4225 return rv;
4226}
4227
4228nsresult nsHttpChannel::StartRedirectChannelToURI(nsIURI* upgradedURI,
4229 uint32_t flags) {
4230 return StartRedirectChannelToURI(upgradedURI, flags, [](nsIChannel*) {});
4231}
4232
4233nsresult nsHttpChannel::StartRedirectChannelToURI(
4234 nsIURI* upgradedURI, uint32_t flags,
4235 std::function<void(nsIChannel*)>&& aCallback) {
4236 nsresult rv = NS_OK;
4237 LOG(("nsHttpChannel::StartRedirectChannelToURI()\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::StartRedirectChannelToURI()\n"); } } while (
0)
;
4238
4239 nsCOMPtr<nsIChannel> newChannel;
4240 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
4241 CloneLoadInfoForRedirect(upgradedURI, flags);
4242
4243 nsCOMPtr<nsIIOService> ioService;
4244 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
4245 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4245); return rv; } } while (false)
;
4246
4247 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), upgradedURI,
4248 redirectLoadInfo,
4249 nullptr, // PerformanceStorage
4250 nullptr, // aLoadGroup
4251 nullptr, // aCallbacks
4252 nsIRequest::LOAD_NORMAL, ioService);
4253 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4253); return rv; } } while (false)
;
4254
4255 rv = SetupReplacementChannel(upgradedURI, newChannel, true, flags);
4256 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4256); return rv; } } while (false)
;
4257
4258 if (mHTTPSSVCRecord) {
4259 RefPtr<nsHttpChannel> httpChan = do_QueryObject(newChannel);
4260 nsCOMPtr<nsIDNSHTTPSSVCRecord> rec = mHTTPSSVCRecord.ref();
4261 if (httpChan && rec) {
4262 httpChan->SetHTTPSSVCRecord(rec.forget());
4263 }
4264 }
4265
4266 // Inform consumers about this fake redirect
4267 mRedirectChannel = newChannel;
4268
4269 aCallback(newChannel);
4270
4271 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
4272 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
4273
4274 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4275
4276 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4277 AutoRedirectVetoNotifier notifier(this, rv);
4278
4279 /* Remove the async call to ContinueAsyncRedirectChannelToURI().
4280 * It is called directly by our callers upon return (to clean up
4281 * the failed redirect). */
4282 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
4283 }
4284
4285 return rv;
4286}
4287
4288nsresult nsHttpChannel::ContinueAsyncRedirectChannelToURI(nsresult rv) {
4289 LOG(("nsHttpChannel::ContinueAsyncRedirectChannelToURI [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueAsyncRedirectChannelToURI [this=%p]"
, this); } } while (0)
;
4290
4291 // Since we handle mAPIRedirectTo uri also after on-examine-response handler
4292 // rather drop it here to avoid any redirect loops, even just hypothetical.
4293 mAPIRedirectTo = Nothing();
4294
4295 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4296 rv = OpenRedirectChannel(rv);
4297 }
4298
4299 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4300 // Cancel the channel here, the update to https had been vetoed
4301 // but from the security reasons we have to discard the whole channel
4302 // load.
4303 Cancel(rv);
4304 }
4305
4306 if (mLoadGroup) {
4307 mLoadGroup->RemoveRequest(this, nullptr, mStatus);
4308 }
4309
4310 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCachePump && !mTransactionPump) {
4311 // We have to manually notify the listener because there is not any pump
4312 // that would call our OnStart/StopRequest after resume from waiting for
4313 // the redirect callback.
4314 DoNotifyListener();
4315 }
4316
4317 return rv;
4318}
4319
4320nsresult nsHttpChannel::OpenRedirectChannel(nsresult rv) {
4321 AutoRedirectVetoNotifier notifier(this, rv);
4322
4323 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4324
4325 if (!mRedirectChannel) {
4326 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OpenRedirectChannel unexpected null redirect channel"
); } } while (0)
4327 "nsHttpChannel::OpenRedirectChannel unexpected null redirect channel"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OpenRedirectChannel unexpected null redirect channel"
); } } while (0)
;
4328 return NS_ERROR_FAILURE;
4329 }
4330
4331 // Make sure to do this after we received redirect veto answer,
4332 // i.e. after all sinks had been notified
4333 mRedirectChannel->SetOriginalURI(mOriginalURI);
4334
4335 // open new channel
4336 rv = mRedirectChannel->AsyncOpen(mListener);
4337
4338 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4338); return rv; } } while (false)
;
4339
4340 mStatus = NS_BINDING_REDIRECTED;
4341
4342 notifier.RedirectSucceeded();
4343
4344 // Report timing data if e10s is disabled
4345 MaybeReportTimingDataForRedirect(mRedirectChannel);
4346
4347 ReleaseListeners();
4348
4349 return NS_OK;
4350}
4351
4352nsresult nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi) {
4353 LOG(("nsHttpChannel::AsyncDoReplaceWithProxy [this=%p pi=%p]", this, pi))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::AsyncDoReplaceWithProxy [this=%p pi=%p]", this
, pi); } } while (0)
;
4354 nsresult rv;
4355
4356 nsCOMPtr<nsIChannel> newChannel;
4357 rv = gHttpHandler->NewProxiedChannel(mURI, pi, mProxyResolveFlags, mProxyURI,
4358 mLoadInfo, getter_AddRefs(newChannel));
4359 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4360
4361 uint32_t flags = nsIChannelEventSink::REDIRECT_INTERNAL;
4362
4363 rv = SetupReplacementChannel(mURI, newChannel, true, flags);
4364 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4365
4366 // Inform consumers about this fake redirect
4367 mRedirectChannel = newChannel;
4368
4369 PushRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
4370 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
4371
4372 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4373
4374 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4375 AutoRedirectVetoNotifier notifier(this, rv);
4376 PopRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
4377 }
4378
4379 return rv;
4380}
4381
4382nsresult nsHttpChannel::ResolveProxy() {
4383 LOG(("nsHttpChannel::ResolveProxy [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResolveProxy [this=%p]\n", this); } } while
(0)
;
4384
4385 nsresult rv;
4386
4387 nsCOMPtr<nsIProtocolProxyService> pps;
4388 pps = mozilla::components::ProtocolProxy::Service(&rv);
4389 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4390
4391 // using the nsIProtocolProxyService2 allows a minor performance
4392 // optimization, but if an add-on has only provided the original interface
4393 // then it is ok to use that version.
4394 nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
4395 if (pps2) {
4396 rv = pps2->AsyncResolve2(this, mProxyResolveFlags, this, nullptr,
4397 getter_AddRefs(mProxyRequest));
4398 } else {
4399 rv = pps->AsyncResolve(static_cast<nsIChannel*>(this), mProxyResolveFlags,
4400 this, nullptr, getter_AddRefs(mProxyRequest));
4401 }
4402
4403 return rv;
4404}
4405
4406bool nsHttpChannel::ResponseWouldVary(nsICacheEntry* entry) {
4407 nsresult rv;
4408 nsAutoCString buf, metaKey;
4409 (void)mCachedResponseHead->GetHeader(nsHttp::Vary, buf);
4410
4411 constexpr auto prefix = "request-"_ns;
4412
4413 // enumerate the elements of the Vary header...
4414 for (const nsACString& token :
4415 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4416 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [channel=%p] " "processing %s\n"
, this, nsPromiseFlatCString(token).get()); } } while (0)
4417 ("nsHttpChannel::ResponseWouldVary [channel=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [channel=%p] " "processing %s\n"
, this, nsPromiseFlatCString(token).get()); } } while (0)
4418 "processing %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [channel=%p] " "processing %s\n"
, this, nsPromiseFlatCString(token).get()); } } while (0)
4419 this, nsPromiseFlatCString(token).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [channel=%p] " "processing %s\n"
, this, nsPromiseFlatCString(token).get()); } } while (0)
;
4420 //
4421 // if "*", then assume response would vary. technically speaking,
4422 // "Vary: header, *" is not permitted, but we allow it anyways.
4423 //
4424 // We hash values of cookie-headers for the following reasons:
4425 //
4426 // 1- cookies can be very large in size
4427 //
4428 // 2- cookies may contain sensitive information. (for parity with
4429 // out policy of not storing Set-cookie headers in the cache
4430 // meta data, we likewise do not want to store cookie headers
4431 // here.)
4432 //
4433 if (token.EqualsLiteral("*")) {
4434 return true; // if we encounter this, just get out of here
4435 }
4436
4437 // build cache meta data key...
4438 metaKey = prefix + token;
4439
4440 // check the last value of the given request header to see if it has
4441 // since changed. if so, then indeed the cached response is invalid.
4442 nsCString lastVal;
4443 entry->GetMetaDataElement(metaKey.get(), getter_Copies(lastVal));
4444 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [channel=%p] " "stored value = \"%s\"\n"
, this, lastVal.get()); } } while (0)
4445 ("nsHttpChannel::ResponseWouldVary [channel=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [channel=%p] " "stored value = \"%s\"\n"
, this, lastVal.get()); } } while (0)
4446 "stored value = \"%s\"\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [channel=%p] " "stored value = \"%s\"\n"
, this, lastVal.get()); } } while (0)
4447 this, lastVal.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [channel=%p] " "stored value = \"%s\"\n"
, this, lastVal.get()); } } while (0)
;
4448
4449 // Look for value of "Cookie" in the request headers
4450 nsHttpAtom atom = nsHttp::ResolveAtom(token);
4451 nsAutoCString newVal;
4452 bool hasHeader = NS_SUCCEEDED(mRequestHead.GetHeader(atom, newVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(atom, newVal))), 1)))
;
4453 if (!lastVal.IsEmpty()) {
4454 // value for this header in cache, but no value in request
4455 if (!hasHeader) {
4456 return true; // yes - response would vary
4457 }
4458
4459 // If this is a cookie-header, stored metadata is not
4460 // the value itself but the hash. So we also hash the
4461 // outgoing value here in order to compare the hashes
4462 nsAutoCString hash;
4463 if (atom == nsHttp::Cookie) {
4464 rv = Hash(newVal.get(), hash);
4465 // If hash failed, be conservative (the cached hash
4466 // exists at this point) and claim response would vary
4467 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return true;
4468 newVal = std::move(hash);
4469
4470 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [this=%p] " "set-cookie value hashed to %s\n"
, this, newVal.get()); } } while (0)
4471 ("nsHttpChannel::ResponseWouldVary [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [this=%p] " "set-cookie value hashed to %s\n"
, this, newVal.get()); } } while (0)
4472 "set-cookie value hashed to %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [this=%p] " "set-cookie value hashed to %s\n"
, this, newVal.get()); } } while (0)
4473 this, newVal.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResponseWouldVary [this=%p] " "set-cookie value hashed to %s\n"
, this, newVal.get()); } } while (0)
;
4474 }
4475
4476 if (!newVal.Equals(lastVal)) {
4477 return true; // yes, response would vary
4478 }
4479
4480 } else if (hasHeader) { // old value is empty, but newVal is set
4481 return true;
4482 }
4483 }
4484
4485 return false;
4486}
4487
4488// Remove an entry from Vary header, if it exists
4489void RemoveFromVary(nsHttpResponseHead* aResponseHead,
4490 const nsACString& aRemove) {
4491 nsAutoCString buf;
4492 (void)aResponseHead->GetHeader(nsHttp::Vary, buf);
4493
4494 bool remove = false;
4495 for (const nsACString& token :
4496 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4497 if (token.EqualsIgnoreCase(aRemove)) {
4498 // Need to build a new string without aRemove
4499 remove = true;
4500 break;
4501 }
4502 }
4503 if (!remove) {
4504 return;
4505 }
4506 nsAutoCString newValue;
4507 for (const nsACString& token :
4508 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4509 if (!token.EqualsIgnoreCase(aRemove)) {
4510 if (!newValue.IsEmpty()) {
4511 newValue += ","_ns;
4512 }
4513 newValue += token;
4514 }
4515 }
4516 LOG(("RemoveFromVary %s removed, new value -> %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "RemoveFromVary %s removed, new value -> %s", TPromiseFlatString
<char>(aRemove).get(), newValue.get()); } } while (0)
4517 PromiseFlatCString(aRemove).get(), newValue.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "RemoveFromVary %s removed, new value -> %s", TPromiseFlatString
<char>(aRemove).get(), newValue.get()); } } while (0)
;
4518 (void)aResponseHead->SetHeaderOverride(nsHttp::Vary, newValue);
4519}
4520
4521// We need to have an implementation of this function just so that we can keep
4522// all references to mCallOnResume of type nsHttpChannel: it's not OK in C++
4523// to set a member function ptr to a base class function.
4524void nsHttpChannel::HandleAsyncAbort() {
4525 HttpAsyncAborter<nsHttpChannel>::HandleAsyncAbort();
4526}
4527
4528//-----------------------------------------------------------------------------
4529// nsHttpChannel <byte-range>
4530//-----------------------------------------------------------------------------
4531
4532bool nsHttpChannel::IsResumable(int64_t partialLen, int64_t contentLength,
4533 bool ignoreMissingPartialLen) const {
4534 bool hasContentEncoding =
4535 mCachedResponseHead->HasHeader(nsHttp::Content_Encoding);
4536
4537 nsAutoCString etag;
4538 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, etag);
4539 bool hasWeakEtag = !etag.IsEmpty() && StringBeginsWith(etag, "W/"_ns);
4540
4541 return (partialLen < contentLength) &&
4542 (partialLen > 0 || ignoreMissingPartialLen) && !hasContentEncoding &&
4543 !hasWeakEtag && mCachedResponseHead->IsResumable() &&
4544 !LoadCustomConditionalRequest() && !mCachedResponseHead->NoStore();
4545}
4546
4547nsresult nsHttpChannel::MaybeSetupByteRangeRequest(
4548 int64_t partialLen, int64_t contentLength, bool ignoreMissingPartialLen) {
4549 // Be pesimistic
4550 StoreIsPartialRequest(false);
4551
4552 if (!IsResumable(partialLen, contentLength, ignoreMissingPartialLen)) {
4553 return NS_ERROR_NOT_RESUMABLE;
4554 }
4555
4556 // looks like a partial entry we can reuse; add If-Range
4557 // and Range headers.
4558 nsresult rv = SetupByteRangeRequest(partialLen);
4559 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4560 // Make the request unconditional again.
4561 UntieByteRangeRequest();
4562 }
4563
4564 return rv;
4565}
4566
4567nsresult nsHttpChannel::SetupByteRangeRequest(int64_t partialLen) {
4568 // cached content has been found to be partial, add necessary request
4569 // headers to complete cache entry.
4570
4571 // use strongest validator available...
4572 nsAutoCString val;
4573 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, val);
4574 if (val.IsEmpty()) {
4575 (void)mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
4576 }
4577 if (val.IsEmpty()) {
4578 // if we hit this code it means mCachedResponseHead->IsResumable() is
4579 // either broken or not being called.
4580 MOZ_ASSERT_UNREACHABLE("no cache validator")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"no cache validator" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no cache validator" ")"); do { MOZ_CrashSequence
(__null, 4580); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4581 StoreIsPartialRequest(false);
4582 return NS_ERROR_FAILURE;
4583 }
4584
4585 char buf[64];
4586 SprintfLiteral(buf, "bytes=%" PRId64"l" "d" "-", partialLen);
4587
4588 DebugOnly<nsresult> rv{};
4589 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(buf));
4590 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4590); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4591 rv = mRequestHead.SetHeader(nsHttp::If_Range, val);
4592 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4592); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4592); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4593 StoreIsPartialRequest(true);
4594
4595 return NS_OK;
4596}
4597
4598void nsHttpChannel::UntieByteRangeRequest() {
4599 DebugOnly<nsresult> rv{};
4600 rv = mRequestHead.ClearHeader(nsHttp::Range);
4601 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4601); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4602 rv = mRequestHead.ClearHeader(nsHttp::If_Range);
4603 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4603); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4603); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4604}
4605
4606nsresult nsHttpChannel::ProcessPartialContent(
4607 const std::function<nsresult(nsHttpChannel*, nsresult)>&
4608 aContinueProcessResponseFunc) {
4609 // ok, we've just received a 206
4610 //
4611 // we need to stream whatever data is in the cache out first, and then
4612 // pick up whatever data is on the wire, writing it into the cache.
4613
4614 LOG(("nsHttpChannel::ProcessPartialContent [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p]\n", this); }
} while (0)
;
4615
4616 NS_ENSURE_TRUE(mCachedResponseHead, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(mCachedResponseHead)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mCachedResponseHead"
") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4616); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4617 NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_NOT_INITIALIZED)do { if ((__builtin_expect(!!(!(mCacheEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mCacheEntry" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4617); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4618
4619 // Check if the content-encoding we now got is different from the one we
4620 // got before
4621 nsAutoCString contentEncoding, cachedContentEncoding;
4622 // It is possible that there is not such headers
4623 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
4624 (void)mCachedResponseHead->GetHeader(nsHttp::Content_Encoding,
4625 cachedContentEncoding);
4626 if (nsCRT::strcasecmp(contentEncoding.get(), cachedContentEncoding.get()) !=
4627 0) {
4628 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
4629 return CallOnStartRequest();
4630 }
4631
4632 nsresult rv;
4633
4634 int64_t cachedContentLength = mCachedResponseHead->ContentLength();
4635 int64_t entitySize = mResponseHead->TotalEntitySize();
4636
4637 nsAutoCString contentRange;
4638 (void)mResponseHead->GetHeader(nsHttp::Content_Range, contentRange);
4639 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p trans=%p] " "original content-length %"
"l" "d" ", entity-size %" "l" "d" ", content-range %s\n", this
, mTransaction.get(), cachedContentLength, entitySize, contentRange
.get()); } } while (0)
4640 ("nsHttpChannel::ProcessPartialContent [this=%p trans=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p trans=%p] " "original content-length %"
"l" "d" ", entity-size %" "l" "d" ", content-range %s\n", this
, mTransaction.get(), cachedContentLength, entitySize, contentRange
.get()); } } while (0)
4641 "original content-length %" PRId64 ", entity-size %" PRId64do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p trans=%p] " "original content-length %"
"l" "d" ", entity-size %" "l" "d" ", content-range %s\n", this
, mTransaction.get(), cachedContentLength, entitySize, contentRange
.get()); } } while (0)
4642 ", content-range %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p trans=%p] " "original content-length %"
"l" "d" ", entity-size %" "l" "d" ", content-range %s\n", this
, mTransaction.get(), cachedContentLength, entitySize, contentRange
.get()); } } while (0)
4643 this, mTransaction.get(), cachedContentLength, entitySize,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p trans=%p] " "original content-length %"
"l" "d" ", entity-size %" "l" "d" ", content-range %s\n", this
, mTransaction.get(), cachedContentLength, entitySize, contentRange
.get()); } } while (0)
4644 contentRange.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p trans=%p] " "original content-length %"
"l" "d" ", entity-size %" "l" "d" ", content-range %s\n", this
, mTransaction.get(), cachedContentLength, entitySize, contentRange
.get()); } } while (0)
;
4645
4646 if ((entitySize >= 0) && (cachedContentLength >= 0) &&
4647 (entitySize != cachedContentLength)) {
4648 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p] " "206 has different total entity size than the content length "
"of the original partially cached entity.\n", this); } } while
(0)
4649 ("nsHttpChannel::ProcessPartialContent [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p] " "206 has different total entity size than the content length "
"of the original partially cached entity.\n", this); } } while
(0)
4650 "206 has different total entity size than the content length "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p] " "206 has different total entity size than the content length "
"of the original partially cached entity.\n", this); } } while
(0)
4651 "of the original partially cached entity.\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p] " "206 has different total entity size than the content length "
"of the original partially cached entity.\n", this); } } while
(0)
4652 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessPartialContent [this=%p] " "206 has different total entity size than the content length "
"of the original partially cached entity.\n", this); } } while
(0)
;
4653
4654 mCacheEntry->AsyncDoom(nullptr);
4655 Cancel(NS_ERROR_CORRUPTED_CONTENT);
4656 return CallOnStartRequest();
4657 }
4658
4659 if (LoadConcurrentCacheAccess()) {
4660 // We started to read cached data sooner than its write has been done.
4661 // But the concurrent write has not finished completely, so we had to
4662 // do a range request. Now let the content coming from the network
4663 // be presented to consumers and also stored to the cache entry.
4664
4665 rv = InstallCacheListener(mLogicalOffset);
4666 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4667 } else {
4668 // suspend the current transaction
4669 rv = mTransactionPump->Suspend();
4670 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4671 }
4672
4673 // merge any new headers with the cached response headers
4674 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
4675
4676 // update the cached response head
4677 nsAutoCString head;
4678 mCachedResponseHead->Flatten(head, true);
4679 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
4680 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4681
4682 // make the cached response be the current response
4683 mResponseHead = std::move(mCachedResponseHead);
4684
4685 UpdateInhibitPersistentCachingFlag();
4686
4687 rv = UpdateExpirationTime();
4688 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4689
4690 // notify observers interested in looking at a response that has been
4691 // merged with any cached headers (http-on-examine-merged-response).
4692 gHttpHandler->OnExamineMergedResponse(this);
4693
4694 if (LoadConcurrentCacheAccess()) {
4695 StoreCachedContentIsPartial(false);
4696 // Leave the ConcurrentCacheAccess flag set, we want to use it
4697 // to prevent duplicate OnStartRequest call on the target listener
4698 // in case this channel is canceled before it gets its OnStartRequest
4699 // from the http transaction.
4700 return rv;
4701 }
4702
4703 // Now we continue reading the network response.
4704 // the cached content is valid, although incomplete.
4705 StoreCachedContentIsValid(CachedContentValidity::Valid);
4706 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
4707 nsresult rv = self->ReadFromCache();
4708 return aContinueProcessResponseFunc(self, rv);
4709 });
4710}
4711
4712nsresult nsHttpChannel::OnDoneReadingPartialCacheEntry(bool* streamDone) {
4713 nsresult rv;
4714
4715 LOG(("nsHttpChannel::OnDoneReadingPartialCacheEntry [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnDoneReadingPartialCacheEntry [this=%p]", this
); } } while (0)
;
4716
4717 // by default, assume we would have streamed all data or failed...
4718 *streamDone = true;
4719
4720 // setup cache listener to append to cache entry
4721 int64_t size;
4722 rv = mCacheEntry->GetDataSize(&size);
4723 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4724
4725 rv = InstallCacheListener(size);
4726 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4727
4728 // Entry is valid, do it now, after the output stream has been opened,
4729 // otherwise when done earlier, pending readers would consider the cache
4730 // entry still as partial (CacheEntry::GetDataSize would return the partial
4731 // data size) and consumers would do the conditional request again.
4732 rv = mCacheEntry->SetValid();
4733 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4734
4735 // need to track the logical offset of the data being sent to our listener
4736 mLogicalOffset = size;
4737
4738 // we're now completing the cached content, so we can clear this flag.
4739 // this puts us in the state of a regular download.
4740 StoreCachedContentIsPartial(false);
4741 // The cache input stream pump is finished, we do not need it any more.
4742 // (see bug 1313923)
4743 mCachePump = nullptr;
4744
4745 // resume the transaction if it exists, otherwise the pipe contained the
4746 // remaining part of the document and we've now streamed all of the data.
4747 if (mTransactionPump) {
4748 rv = mTransactionPump->Resume();
4749 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) *streamDone = false;
4750 } else {
4751 MOZ_ASSERT_UNREACHABLE("no transaction")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"no transaction" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4751); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no transaction" ")"); do { MOZ_CrashSequence
(__null, 4751); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4752 }
4753 return rv;
4754}
4755
4756//-----------------------------------------------------------------------------
4757// nsHttpChannel <cache>
4758//-----------------------------------------------------------------------------
4759
4760bool nsHttpChannel::ShouldBypassProcessNotModified() {
4761 if (LoadCustomConditionalRequest()) {
4762 LOG(("Bypassing ProcessNotModified due to custom conditional headers"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Bypassing ProcessNotModified due to custom conditional headers"
); } } while (0)
;
4763 return true;
4764 }
4765
4766 if (!mDidReval) {
4767 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Server returned a 304 response even though we did not send a "
"conditional request"); } } while (0)
4768 ("Server returned a 304 response even though we did not send a "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Server returned a 304 response even though we did not send a "
"conditional request"); } } while (0)
4769 "conditional request"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Server returned a 304 response even though we did not send a "
"conditional request"); } } while (0)
;
4770 return true;
4771 }
4772
4773 return false;
4774}
4775
4776void nsHttpChannel::MaybeGenerateNELReport() {
4777 if (!StaticPrefs::network_http_network_error_logging_enabled()) {
4778 return;
4779 }
4780
4781 nsCOMPtr<nsINetworkErrorReport> report;
4782 if (nsCOMPtr<nsINetworkErrorLogging> nel =
4783 components::NetworkErrorLogging::Service()) {
4784 nel->GenerateNELReport(this, getter_AddRefs(report));
4785 }
4786
4787 mReportedNEL = true;
4788
4789 // https://www.w3.org/TR/2023/WD-network-error-logging-20231005/#deliver-a-network-report
4790 // 4. Generate a network report given these parameters:
4791 // type: network-error
4792 // url
4793 // user_agent
4794 // body
4795
4796 if (!report) {
4797 return;
4798 }
4799
4800 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
4801 if (!ssm) {
4802 return;
4803 }
4804
4805 nsCOMPtr<nsIPrincipal> channelPrincipal;
4806 ssm->GetChannelResultPrincipal(this, getter_AddRefs(channelPrincipal));
4807 if (!channelPrincipal) {
4808 return;
4809 }
4810
4811 nsAutoCString body;
4812 nsAutoString group;
4813 nsAutoString url;
4814
4815 report->GetBody(body);
4816 report->GetGroup(group);
4817 report->GetUrl(url);
4818
4819 nsAutoCString endpointURL;
4820 ReportingHeader::GetEndpointForReportIncludeSubdomains(
4821 NS_ConvertUTF16toUTF8(group), channelPrincipal,
4822 /* includeSubdomains */ true, endpointURL);
4823 if (endpointURL.IsEmpty()) {
4824 return;
4825 }
4826
4827 ReportDeliver::ReportData data;
4828 data.mType = "network-error"_ns;
4829 data.mGroupName = NS_ConvertUTF16toUTF8(group);
4830 data.mURL = NS_ConvertUTF16toUTF8(url);
4831 data.mFailures = 0;
4832 data.mCreationTime = TimeStamp::Now();
4833
4834 data.mPrincipal = std::move(channelPrincipal);
4835 data.mEndpointURL = std::move(endpointURL);
4836 data.mReportBodyJSON = std::move(body);
4837 nsAutoCString userAgent;
4838 // XXX(valentin): Should this be the potentially user set value of the header
4839 // or the current value of user_agent from http handler?
4840 (void)mRequestHead.GetHeader(nsHttp::User_Agent, userAgent);
4841 data.mUserAgent = std::move(userAgent);
4842
4843 // Enqueue the report to be delivered by the reporting API
4844 ReportDeliver::Fetch(data);
4845}
4846
4847nsresult nsHttpChannel::ProcessNotModified(
4848 const std::function<nsresult(nsHttpChannel*, nsresult)>&
4849 aContinueProcessResponseFunc) {
4850 nsresult rv;
4851
4852 LOG(("nsHttpChannel::ProcessNotModified [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessNotModified [this=%p]\n", this); } }
while (0)
;
4853
4854 // Assert ShouldBypassProcessNotModified() has been checked before call to
4855 // ProcessNotModified().
4856 MOZ_ASSERT(!ShouldBypassProcessNotModified())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!ShouldBypassProcessNotModified())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!ShouldBypassProcessNotModified
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!ShouldBypassProcessNotModified()", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4856); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ShouldBypassProcessNotModified()"
")"); do { MOZ_CrashSequence(__null, 4856); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4857
4858 MOZ_ASSERT(mCachedResponseHead)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCachedResponseHead)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCachedResponseHead))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("mCachedResponseHead"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 4858
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedResponseHead"
")"); do { MOZ_CrashSequence(__null, 4858); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4859 MOZ_ASSERT(mCacheEntry)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCacheEntry)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCacheEntry))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mCacheEntry", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 4859); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4860 NS_ENSURE_TRUE(mCachedResponseHead && mCacheEntry, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mCachedResponseHead &&
mCacheEntry)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"mCachedResponseHead && mCacheEntry" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 4860
); return NS_ERROR_UNEXPECTED; } } while (false)
;
4861
4862 // If the 304 response contains a Last-Modified different than the
4863 // one in our cache that is pretty suspicious and is, in at least the
4864 // case of bug 716840, a sign of the server having previously corrupted
4865 // our cache with a bad response. Take the minor step here of just dooming
4866 // that cache entry so there is a fighting chance of getting things on the
4867 // right track.
4868
4869 nsAutoCString lastModifiedCached;
4870 nsAutoCString lastModified304;
4871
4872 rv =
4873 mCachedResponseHead->GetHeader(nsHttp::Last_Modified, lastModifiedCached);
4874 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4875 rv = mResponseHead->GetHeader(nsHttp::Last_Modified, lastModified304);
4876 }
4877
4878 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !lastModified304.Equals(lastModifiedCached)) {
4879 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cache Entry and 304 Last-Modified Headers Do Not Match " "[%s] and [%s]\n"
, lastModifiedCached.get(), lastModified304.get()); } } while
(0)
4880 ("Cache Entry and 304 Last-Modified Headers Do Not Match "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cache Entry and 304 Last-Modified Headers Do Not Match " "[%s] and [%s]\n"
, lastModifiedCached.get(), lastModified304.get()); } } while
(0)
4881 "[%s] and [%s]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cache Entry and 304 Last-Modified Headers Do Not Match " "[%s] and [%s]\n"
, lastModifiedCached.get(), lastModified304.get()); } } while
(0)
4882 lastModifiedCached.get(), lastModified304.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cache Entry and 304 Last-Modified Headers Do Not Match " "[%s] and [%s]\n"
, lastModifiedCached.get(), lastModified304.get()); } } while
(0)
;
4883
4884 mCacheEntry->AsyncDoom(nullptr);
4885 glean::http::cache_lm_inconsistent
4886 .EnumGet(glean::http::CacheLmInconsistentLabel::eTrue)
4887 .Add();
4888 }
4889
4890 // merge any new headers with the cached response headers
4891 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
4892
4893 // update the cached response head
4894 nsAutoCString head;
4895 mCachedResponseHead->Flatten(head, true);
4896 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
4897 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4898
4899 if (LoadUsedNetwork() && !mReportedNEL) {
4900 MaybeGenerateNELReport();
4901 }
4902
4903 // make the cached response be the current response
4904 mResponseHead = std::move(mCachedResponseHead);
4905
4906 UpdateInhibitPersistentCachingFlag();
4907
4908 rv = UpdateExpirationTime();
4909 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4910
4911 rv = AddCacheEntryHeaders(mCacheEntry, false);
4912 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4913
4914 // notify observers interested in looking at a reponse that has been
4915 // merged with any cached headers
4916 gHttpHandler->OnExamineMergedResponse(this);
4917
4918 StoreCachedContentIsValid(CachedContentValidity::Valid);
4919
4920 // Tell other consumers the entry is OK to use
4921 rv = mCacheEntry->SetValid();
4922 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4923
4924 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
4925 nsresult rv = self->ReadFromCache();
4926 return aContinueProcessResponseFunc(self, rv);
4927 });
4928}
4929
4930// Determines if a request is a byte range request for a subrange,
4931// i.e. is a byte range request, but not a 0- byte range request.
4932static bool IsSubRangeRequest(nsHttpRequestHead& aRequestHead) {
4933 nsAutoCString byteRange;
4934 if (NS_FAILED(aRequestHead.GetHeader(nsHttp::Range, byteRange))((bool)(__builtin_expect(!!(NS_FAILED_impl(aRequestHead.GetHeader
(nsHttp::Range, byteRange))), 0)))
) {
4935 return false;
4936 }
4937
4938 if (byteRange.EqualsLiteral("bytes=0-")) {
4939#ifndef ANDROID
4940 glean::network::byte_range_request.Get("cacheable"_ns).Add(1);
4941#endif
4942 return false;
4943 }
4944#ifndef ANDROID
4945 glean::network::byte_range_request.Get("not_cacheable"_ns).Add(1);
4946#endif
4947 return true;
4948}
4949
4950nsresult nsHttpChannel::OpenCacheEntry(bool isHttps) {
4951 // Drop this flag here
4952 StoreConcurrentCacheAccess(0);
4953
4954 LOG(("nsHttpChannel::OpenCacheEntry [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OpenCacheEntry [this=%p]", this); } } while
(0)
;
4955
4956 // make sure we're not abusing this function
4957 MOZ_ASSERT(!mCacheEntry, "cache entry already open")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCacheEntry)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCacheEntry))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mCacheEntry" " ("
"cache entry already open" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 4957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheEntry"
") (" "cache entry already open" ")"); do { MOZ_CrashSequence
(__null, 4957); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4958 if (!mRequestHead.IsGet() && !mRequestHead.IsHead() &&
4959 !mRequestHead.IsPost() && !mRequestHead.IsPatch()) {
4960 // don't use the cache for other types of requests
4961 return NS_OK;
4962 }
4963
4964 MOZ_ASSERT_IF(mRequestHead.IsPost() || mRequestHead.IsPatch(), mPostID > 0)do { if (mRequestHead.IsPost() || mRequestHead.IsPatch()) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(mPostID > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPostID > 0))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mPostID > 0"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 4964
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPostID > 0" ")"
); do { MOZ_CrashSequence(__null, 4964); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
4965
4966 return OpenCacheEntryInternal(isHttps);
4967}
4968
4969nsresult nsHttpChannel::OpenCacheEntryInternal(bool isHttps) {
4970 nsresult rv;
4971
4972 if (LoadResuming()) {
4973 // We don't support caching for requests initiated
4974 // via nsIResumableChannel.
4975 return NS_OK;
4976 }
4977
4978 // Don't cache byte range requests which are subranges, only cache 0-
4979 // byte range requests.
4980 if (IsSubRangeRequest(mRequestHead)) {
4981 return NS_OK;
4982 }
4983
4984 // Handle correctly WaitForCacheEntry
4985 AutoCacheWaitFlags waitFlags(this);
4986
4987 nsAutoCString cacheKey;
4988
4989 nsCOMPtr<nsICacheStorage> cacheStorage;
4990 mCacheEntryURI = mURI;
4991
4992 // A navigation activated from a prefetch record reads the record's own
4993 // entry. A cache-bypassing reload would truncate it, so it doesn't qualify.
4994 bool readPrefetchEntry =
4995 mNavigationalPrefetchCacheURI &&
4996 !BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
;
4997 if (readPrefetchEntry) {
4998 mCacheEntryURI = mNavigationalPrefetchCacheURI;
4999 }
5000
5001 uint32_t cacheEntryOpenFlags;
5002 bool offline = gIOService->IsOffline();
5003
5004 nsAutoCString cacheControlRequestHeader;
5005 (void)mRequestHead.GetHeader(nsHttp::Cache_Control,
5006 cacheControlRequestHeader);
5007 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
5008 if (cacheControlRequest.NoStore()) {
5009 return NS_OK;
5010 }
5011
5012 bool forceOffline = IsForcedOffline();
5013 if (offline || (mLoadFlags & INHIBIT_CACHING) || forceOffline) {
5014 if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
&&
5015 !offline && !forceOffline) {
5016 return NS_OK;
5017 }
5018 cacheEntryOpenFlags = nsICacheStorage::OPEN_READONLY;
5019 StoreCacheEntryIsReadOnly(true);
5020 } else if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
5021 cacheEntryOpenFlags = nsICacheStorage::OPEN_TRUNCATE;
5022 } else if (readPrefetchEntry) {
5023 // Never write to (or replace) the entry the prefetch record holds.
5024 cacheEntryOpenFlags = nsICacheStorage::OPEN_READONLY;
5025 StoreCacheEntryIsReadOnly(true);
5026 } else {
5027 cacheEntryOpenFlags =
5028 nsICacheStorage::OPEN_NORMALLY | nsICacheStorage::CHECK_MULTITHREADED;
5029 }
5030
5031 // Remember the request is a custom conditional request so that we can
5032 // process any 304 response correctly.
5033 StoreCustomConditionalRequest(
5034 mRequestHead.HasHeader(nsHttp::If_Modified_Since) ||
5035 mRequestHead.HasHeader(nsHttp::If_None_Match) ||
5036 mRequestHead.HasHeader(nsHttp::If_Unmodified_Since) ||
5037 mRequestHead.HasHeader(nsHttp::If_Match) ||
5038 mRequestHead.HasHeader(nsHttp::If_Range));
5039
5040 rv = GetCacheStorage(getter_AddRefs(cacheStorage));
5041 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5041); return rv; } } while (false)
;
5042
5043 if ((mClassOfService.Flags() & nsIClassOfService::Leader) ||
5044 (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)) {
5045 cacheEntryOpenFlags |= nsICacheStorage::OPEN_PRIORITY;
5046 }
5047
5048 // Only for backward compatibility with the old cache back end.
5049 // When removed, remove the flags and related code snippets.
5050 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
5051 cacheEntryOpenFlags |= nsICacheStorage::OPEN_BYPASS_IF_BUSY;
5052 }
5053
5054 if (mPostID) {
5055 mCacheIdExtension.AppendInt(mPostID);
5056 }
5057 if (LoadIsTRRServiceChannel()) {
5058 mCacheIdExtension.Append("TRR");
5059 }
5060 if (mRequestHead.IsHead()) {
5061 mCacheIdExtension.Append("HEAD");
5062 }
5063 bool isThirdParty = false;
5064 if (StaticPrefs::network_fetch_cache_partition_cross_origin() &&
5065 (NS_FAILED(mLoadInfo->TriggeringPrincipal()->IsThirdPartyChannel(((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
5066 this, &isThirdParty))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
||
5067 isThirdParty) &&
5068 (mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_FETCH ||
5069 mLoadInfo->InternalContentPolicyType() ==
5070 nsIContentPolicy::TYPE_XMLHTTPREQUEST ||
5071 mLoadInfo->InternalContentPolicyType() ==
5072 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_ASYNC ||
5073 mLoadInfo->InternalContentPolicyType() ==
5074 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_SYNC)) {
5075 mCacheIdExtension.Append("FETCH");
5076 }
5077
5078 mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY;
5079 mCacheQueueSizeWhenOpen =
5080 CacheStorageService::CacheQueueSize(mCacheOpenWithPriority);
5081
5082 MOZ_ASSERT(NS_IsMainThread(), "Should be called on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Should be called on the main thread" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5082); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 5082); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5083 rv = cacheStorage->AsyncOpenURI(mCacheEntryURI, mCacheIdExtension,
5084 cacheEntryOpenFlags, this);
5085 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5085); return rv; } } while (false)
;
5086
5087 waitFlags.Keep(WAIT_FOR_CACHE_ENTRY);
5088
5089 return NS_OK;
5090}
5091
5092// We asked the cache for mCacheEntryURI, but the entry we got back may be
5093// stored under a different URL: on an exact-key miss the cache falls back to a
5094// No-Vary-Search secondary lookup, which can return a sibling entry whose URL
5095// is equivalent to ours under its No-Vary-Search header. Record which of the
5096// two happened, so that later code can tell whether the entry it holds is
5097// really ours to write to.
5098void nsHttpChannel::NoteCacheEntryKeyMatch(nsICacheEntry* aEntry) {
5099 StoreCacheEntryIsNoVarySearchMatch(false);
5100
5101 if (!aEntry || !mCacheEntryURI) {
5102 return;
5103 }
5104
5105 // Normalize the same way CacheStorage::AsyncOpenURI did to build the key.
5106 nsCOMPtr<nsIURI> noRefURI;
5107 nsAutoCString spec;
5108 if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetURIWithoutRef
(mCacheEntryURI, getter_AddRefs(noRefURI)))), 0)))
5109 NS_GetURIWithoutRef(mCacheEntryURI, getter_AddRefs(noRefURI)))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetURIWithoutRef
(mCacheEntryURI, getter_AddRefs(noRefURI)))), 0)))
||
5110 NS_FAILED(noRefURI->GetAsciiSpec(spec))((bool)(__builtin_expect(!!(NS_FAILED_impl(noRefURI->GetAsciiSpec
(spec))), 0)))
) {
5111 return;
5112 }
5113
5114 nsAutoCString key;
5115 if (NS_FAILED(aEntry->GetKey(key))((bool)(__builtin_expect(!!(NS_FAILED_impl(aEntry->GetKey(
key))), 0)))
) {
5116 return;
5117 }
5118
5119 if (!key.Equals(spec)) {
5120 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::NoteCacheEntryKeyMatch [this=%p] No-Vary-Search hit, "
"entry is stored under %s", this, key.get()); } } while (0)
5121 ("nsHttpChannel::NoteCacheEntryKeyMatch [this=%p] No-Vary-Search hit, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::NoteCacheEntryKeyMatch [this=%p] No-Vary-Search hit, "
"entry is stored under %s", this, key.get()); } } while (0)
5122 "entry is stored under %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::NoteCacheEntryKeyMatch [this=%p] No-Vary-Search hit, "
"entry is stored under %s", this, key.get()); } } while (0)
5123 this, key.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::NoteCacheEntryKeyMatch [this=%p] No-Vary-Search hit, "
"entry is stored under %s", this, key.get()); } } while (0)
;
5124 StoreCacheEntryIsNoVarySearchMatch(true);
5125 }
5126}
5127
5128// Picks the storage matching the channel's persistence flags as they stand
5129// right now. Called both when first opening the entry and when replacing an
5130// alias entry later, by which point a no-store response may have set
5131// INHIBIT_PERSISTENT_CACHING and the replacement must be memory-only.
5132nsresult nsHttpChannel::GetCacheStorage(nsICacheStorage** aStorage) {
5133 nsCOMPtr<nsICacheStorageService> service(components::CacheStorage::Service());
5134 if (!service) {
5135 return NS_ERROR_NOT_AVAILABLE;
5136 }
5137
5138 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
5139 if (!info) {
5140 return NS_ERROR_FAILURE;
5141 }
5142
5143 if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
5144 return service->MemoryCacheStorage(info, // ? choose app cache as well...
5145 aStorage);
5146 }
5147 if (LoadPinCacheContent()) {
5148 return service->PinningCacheStorage(info, aStorage);
5149 }
5150 return service->DiskCacheStorage(info, aStorage);
5151}
5152
5153// Called before anything is written to mCacheEntry. When the entry we hold was
5154// found through No-Vary-Search it is stored under a different URL, and this
5155// response describes mCacheEntryURI only, so writing to it would put our
5156// content under someone else's key. Open a fresh entry of our own instead.
5157// Releasing the last handle on the borrowed entry reverts it from REVALIDATING
5158// back to READY, leaving its own representation untouched.
5159nsresult nsHttpChannel::MaybeReplaceNoVarySearchAliasEntry() {
5160 if (!LoadCacheEntryIsNoVarySearchMatch() || !mCacheEntry ||
5161 LoadCacheEntryIsReadOnly()) {
5162 return NS_OK;
5163 }
5164
5165 LOG(("nsHttpChannel::MaybeReplaceNoVarySearchAliasEntry [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeReplaceNoVarySearchAliasEntry [this=%p]"
, this); } } while (0)
;
5166
5167 nsCOMPtr<nsICacheStorage> storage;
5168 nsresult rv = GetCacheStorage(getter_AddRefs(storage));
5169 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5170 rv = storage->OpenTruncate(mCacheEntryURI, mCacheIdExtension,
5171 getter_AddRefs(mCacheEntry));
5172 }
5173
5174 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5175 LOG((" failed to open %s, the response will not be cached",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " failed to open %s, the response will not be cached", mCacheEntryURI
->GetSpecOrDefault().get()); } } while (0)
5176 mCacheEntryURI->GetSpecOrDefault().get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " failed to open %s, the response will not be cached", mCacheEntryURI
->GetSpecOrDefault().get()); } } while (0)
;
5177 mCacheEntry = nullptr;
5178 return rv;
5179 }
5180
5181 // We now hold an entry keyed on mCacheEntryURI, so it is ours to write to.
5182 StoreCacheEntryIsNoVarySearchMatch(false);
5183 StoreCacheEntryIsWriteOnly(true);
5184 // The alt-data belonged to the entry we just let go of.
5185 mAvailableCachedAltDataType.Truncate();
5186 StoreDeliveringAltData(false);
5187
5188 return NS_OK;
5189}
5190
5191nsresult nsHttpChannel::CheckPartial(nsICacheEntry* aEntry, int64_t* aSize,
5192 int64_t* aContentLength) {
5193 return nsHttp::CheckPartial(
5194 aEntry, aSize, aContentLength,
5195 mCachedResponseHead ? mCachedResponseHead.get() : mResponseHead.get());
5196}
5197
5198void nsHttpChannel::UntieValidationRequest() {
5199 DebugOnly<nsresult> rv{};
5200 // Make the request unconditional again.
5201 rv = mRequestHead.ClearHeader(nsHttp::If_Modified_Since);
5202 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5202); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5202); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5203 rv = mRequestHead.ClearHeader(nsHttp::If_None_Match);
5204 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5204); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5204); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5205 rv = mRequestHead.ClearHeader(nsHttp::ETag);
5206 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5206); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5207}
5208
5209void nsHttpChannel::DiscardCacheEntryCheckState() {
5210 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5211
5212 if (mDidReval) {
5213 LOG((" Removing conditional request headers"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Removing conditional request headers"); } } while (0)
;
5214 UntieValidationRequest();
5215 mDidReval = false;
5216 }
5217
5218 if (LoadCachedContentIsPartial()) {
5219 LOG((" Removing byte range request headers"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Removing byte range request headers"); } } while (0)
;
5220 UntieByteRangeRequest();
5221 StoreCachedContentIsPartial(false);
5222 }
5223
5224 mCachedResponseHead = nullptr;
5225 mCacheInputStream.CloseAndRelease();
5226 mAvailableCachedAltDataType.Truncate();
5227 StoreDeliveringAltData(false);
5228 mAltDataLength = -1;
5229}
5230
5231NS_IMETHODIMPnsresult
5232nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, uint32_t* aResult) {
5233 nsresult rv = NS_OK;
5234
5235 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnCacheEntryCheck", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject5236( "nsHttpChannel::OnCacheEntryCheck"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
5236 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject5236( "nsHttpChannel::OnCacheEntryCheck"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
5237 LOG(("nsHttpChannel::OnCacheEntryCheck enter [channel=%p entry=%p]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnCacheEntryCheck enter [channel=%p entry=%p]"
, this, entry); } } while (0)
5238 entry))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnCacheEntryCheck enter [channel=%p entry=%p]"
, this, entry); } } while (0)
;
5239
5240 // Held for the whole check: this may run on the cache I/O thread while the
5241 // backstop timeout or a cancel runs on the main thread, and neither may slip
5242 // in between the tests below and the state we arm from here on.
5243 MutexAutoLock lock(mCacheWaitLock);
5244
5245 if (mCacheWaitTimedOut) {
5246 LOG((" cache entry check arrived after backstop timeout, declining"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache entry check arrived after backstop timeout, declining"
); } } while (0)
;
5247 *aResult = ENTRY_NOT_WANTED;
5248 return NS_OK;
5249 }
5250
5251 if (mCanceled) {
5252 LOG((" cache entry check arrived after cancel, declining"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache entry check arrived after cancel, declining"); } }
while (0)
;
5253 *aResult = ENTRY_NOT_WANTED;
5254 return NS_OK;
5255 }
5256
5257 // Each check starts from a clean slate.
5258 DiscardCacheEntryCheckState();
5259
5260 NoteCacheEntryKeyMatch(entry);
5261
5262 nsAutoCString cacheControlRequestHeader;
5263 (void)mRequestHead.GetHeader(nsHttp::Cache_Control,
5264 cacheControlRequestHeader);
5265 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
5266
5267 if (cacheControlRequest.NoStore()) {
5268 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Not using cached response based on no-store request cache "
"directive\n"); } } while (0)
5269 ("Not using cached response based on no-store request cache "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Not using cached response based on no-store request cache "
"directive\n"); } } while (0)
5270 "directive\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Not using cached response based on no-store request cache "
"directive\n"); } } while (0)
;
5271 *aResult = ENTRY_NOT_WANTED;
5272 return NS_OK;
5273 }
5274
5275 // Be pessimistic: assume the cache entry has no useful data.
5276 *aResult = ENTRY_WANTED;
5277 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5278
5279 nsCString buf;
5280
5281 // Get the method that was used to generate the cached response
5282 rv = entry->GetMetaDataElement("request-method", getter_Copies(buf));
5283 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5283); return rv; } } while (false)
;
5284
5285 bool methodWasHead = buf.EqualsLiteral("HEAD");
5286 bool methodWasGet = buf.EqualsLiteral("GET");
5287
5288 if (methodWasHead) {
5289 // The cached response does not contain an entity. We can only reuse
5290 // the response if the current request is also HEAD.
5291 if (!mRequestHead.IsHead()) {
5292 *aResult = ENTRY_NOT_WANTED;
5293 return NS_OK;
5294 }
5295 }
5296 buf.Adopt(nullptr);
5297
5298 // We'll need this value in later computations...
5299 uint32_t lastModifiedTime;
5300 rv = entry->GetLastModified(&lastModifiedTime);
5301 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5301); return rv; } } while (false)
;
5302
5303 // Determine if this is the first time that this cache entry
5304 // has been accessed during this session.
5305 bool fromPreviousSession =
5306 (gHttpHandler->SessionStartTime() > lastModifiedTime);
5307
5308 // Get the cached HTTP response headers
5309 mCachedResponseHead = std::make_unique<nsHttpResponseHead>();
5310
5311 rv = nsHttp::GetHttpResponseHeadFromCacheEntry(entry,
5312 mCachedResponseHead.get());
5313 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5313); return rv; } } while (false)
;
5314
5315 // Purge stale cache entries that have dcb/dcz Content-Encoding in their
5316 // metadata. These were written by early compression dictionary code that
5317 // failed to clear Content-Encoding before writing cache metadata. The data
5318 // body is decompressed but the header is wrong; serving such entries would
5319 // cause crashes in content processes. Doom and re-fetch from network.
5320 {
5321 nsAutoCString cachedEncoding;
5322 (void)mCachedResponseHead->GetHeader(nsHttp::Content_Encoding,
5323 cachedEncoding);
5324 if (cachedEncoding.LowerCaseFindASCII("dcb") != -1 ||
5325 cachedEncoding.LowerCaseFindASCII("dcz") != -1) {
5326 LOG(("Dooming stale cache entry with dcb/dcz Content-Encoding [%s]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Dooming stale cache entry with dcb/dcz Content-Encoding [%s]\n"
, mSpec.get()); } } while (0)
5327 mSpec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Dooming stale cache entry with dcb/dcz Content-Encoding [%s]\n"
, mSpec.get()); } } while (0)
;
5328 glean::http3::stale_dcb_dcz_cache_entries_purged.Add(1);
5329 entry->AsyncDoom(nullptr);
5330 *aResult = ENTRY_NOT_WANTED;
5331 return NS_OK;
5332 }
5333 }
5334
5335 bool isCachedRedirect = WillRedirect(*mCachedResponseHead);
5336
5337 // Do not return 304 responses from the cache, and also do not return
5338 // any other non-redirect 3xx responses from the cache (see bug 759043).
5339 NS_ENSURE_TRUE((mCachedResponseHead->Status() / 100 != 3) || isCachedRedirect,do { if ((__builtin_expect(!!(!((mCachedResponseHead->Status
() / 100 != 3) || isCachedRedirect)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "(mCachedResponseHead->Status() / 100 != 3) || isCachedRedirect"
") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5340); return NS_ERROR_ABORT; } } while (false)
5340 NS_ERROR_ABORT)do { if ((__builtin_expect(!!(!((mCachedResponseHead->Status
() / 100 != 3) || isCachedRedirect)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "(mCachedResponseHead->Status() / 100 != 3) || isCachedRedirect"
") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5340); return NS_ERROR_ABORT; } } while (false)
;
5341
5342 if (mCachedResponseHead->NoStore() && LoadCacheEntryIsReadOnly()) {
5343 // This prevents loading no-store responses when navigating back
5344 // while the browser is set to work offline.
5345 LOG((" entry loading as read-only but is no-store, set INHIBIT_CACHING"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " entry loading as read-only but is no-store, set INHIBIT_CACHING"
); } } while (0)
;
5346 mLoadFlags |= nsIRequest::INHIBIT_CACHING;
5347 }
5348
5349 // Don't bother to validate items that are read-only,
5350 // unless they are read-only because of INHIBIT_CACHING
5351 if ((LoadCacheEntryIsReadOnly() &&
5352 !(mLoadFlags & nsIRequest::INHIBIT_CACHING))) {
5353 int64_t size, contentLength;
5354 rv = CheckPartial(entry, &size, &contentLength);
5355 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5355); return rv; } } while (false)
;
5356
5357 if (contentLength != int64_t(-1) && contentLength != size) {
5358 *aResult = ENTRY_NOT_WANTED;
5359 return NS_OK;
5360 }
5361
5362 rv = OpenCacheInputStream(entry, true);
5363 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5364 StoreCachedContentIsValid(CachedContentValidity::Valid);
5365 }
5366 return rv;
5367 }
5368
5369 bool wantCompleteEntry = false;
5370
5371 if (!methodWasHead && !isCachedRedirect) {
5372 // If the cached content-length is set and it does not match the data
5373 // size of the cached content, then the cached response is partial...
5374 // either we need to issue a byte range request or we need to refetch
5375 // the entire document.
5376 //
5377 // We exclude redirects from this check because we (usually) strip the
5378 // entity when we store the cache entry, and even if we didn't, we
5379 // always ignore a cached redirect's entity anyway. See bug 759043.
5380 int64_t size, contentLength;
5381 rv = CheckPartial(entry, &size, &contentLength);
5382 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5382); return rv; } } while (false)
;
5383
5384 if (LoadCacheEntryIsNoVarySearchMatch() &&
5385 (size == int64_t(-1) ||
5386 (contentLength != int64_t(-1) && contentLength != size))) {
5387 // Completing this entry means appending our bytes to content stored
5388 // under a different URL, and unlike a full response we cannot divert
5389 // that to an entry of our own: the range request only makes sense
5390 // against what is already there. Refetch from scratch instead.
5391 LOG((" incomplete No-Vary-Search alias entry, not wanted"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " incomplete No-Vary-Search alias entry, not wanted"); } }
while (0)
;
5392 *aResult = ENTRY_NOT_WANTED;
5393 return NS_OK;
5394 }
5395
5396 if (size == int64_t(-1)) {
5397 LOG((" write is in progress"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " write is in progress"); } } while (0)
;
5398 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
5399 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " not interested in the entry, " "LOAD_BYPASS_LOCAL_CACHE_IF_BUSY specified"
); } } while (0)
5400 (" not interested in the entry, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " not interested in the entry, " "LOAD_BYPASS_LOCAL_CACHE_IF_BUSY specified"
); } } while (0)
5401 "LOAD_BYPASS_LOCAL_CACHE_IF_BUSY specified"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " not interested in the entry, " "LOAD_BYPASS_LOCAL_CACHE_IF_BUSY specified"
); } } while (0)
;
5402
5403 *aResult = ENTRY_NOT_WANTED;
5404 return NS_OK;
5405 }
5406
5407 // Ignore !(size > 0) from the resumability condition
5408 if (!IsResumable(size, contentLength, true)) {
5409 if (IsNavigation()) {
5410 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " bypassing wait for the entry, " "this is a navigational load"
); } } while (0)
5411 (" bypassing wait for the entry, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " bypassing wait for the entry, " "this is a navigational load"
); } } while (0)
5412 "this is a navigational load"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " bypassing wait for the entry, " "this is a navigational load"
); } } while (0)
;
5413 *aResult = ENTRY_NOT_WANTED;
5414 return NS_OK;
5415 }
5416
5417 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " wait for entry completion, " "response is not resumable"
); } } while (0)
5418 (" wait for entry completion, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " wait for entry completion, " "response is not resumable"
); } } while (0)
5419 "response is not resumable"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " wait for entry completion, " "response is not resumable"
); } } while (0)
;
5420
5421 wantCompleteEntry = true;
5422 } else {
5423 StoreConcurrentCacheAccess(1);
5424 }
5425 } else if (contentLength != int64_t(-1) && contentLength != size) {
5426 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cached data size does not match the Content-Length header "
"[content-length=%" "l" "d" " size=%" "l" "d" "]\n", contentLength
, size); } } while (0)
5427 ("Cached data size does not match the Content-Length header "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cached data size does not match the Content-Length header "
"[content-length=%" "l" "d" " size=%" "l" "d" "]\n", contentLength
, size); } } while (0)
5428 "[content-length=%" PRId64 " size=%" PRId64 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cached data size does not match the Content-Length header "
"[content-length=%" "l" "d" " size=%" "l" "d" "]\n", contentLength
, size); } } while (0)
5429 contentLength, size))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Cached data size does not match the Content-Length header "
"[content-length=%" "l" "d" " size=%" "l" "d" "]\n", contentLength
, size); } } while (0)
;
5430
5431 rv = MaybeSetupByteRangeRequest(size, contentLength);
5432 StoreCachedContentIsPartial(NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest());
5433 if (LoadCachedContentIsPartial()) {
5434 rv = OpenCacheInputStream(entry, false);
5435 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5436 UntieByteRangeRequest();
5437 return rv;
5438 }
5439
5440 *aResult = ENTRY_NEEDS_REVALIDATION;
5441 return NS_OK;
5442 }
5443
5444 if (size == 0 && LoadCacheOnlyMetadata()) {
5445 // Don't break cache entry load when the entry's data size
5446 // is 0 and CacheOnlyMetadata flag is set. In that case we
5447 // want to proceed since the LOAD_ONLY_IF_MODIFIED flag is
5448 // also set.
5449 MOZ_ASSERT(mLoadFlags & LOAD_ONLY_IF_MODIFIED)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadFlags & LOAD_ONLY_IF_MODIFIED)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mLoadFlags & LOAD_ONLY_IF_MODIFIED))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mLoadFlags & LOAD_ONLY_IF_MODIFIED"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 5449
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadFlags & LOAD_ONLY_IF_MODIFIED"
")"); do { MOZ_CrashSequence(__null, 5449); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5450 } else {
5451 return rv;
5452 }
5453 }
5454 }
5455
5456 bool isHttps = IsHTTPS();
5457
5458 bool doValidation = false;
5459 bool doBackgroundValidation = false;
5460 bool canAddImsHeader = true;
5461
5462 bool isForcedValid = false;
5463 entry->GetIsForcedValid(&isForcedValid);
5464
5465 bool weaklyFramed, isImmutable;
5466 nsHttp::DetermineFramingAndImmutability(entry, mCachedResponseHead.get(),
5467 isHttps, &weaklyFramed, &isImmutable);
5468
5469 // Cached entry is not the entity we request (see bug #633743)
5470 if (ResponseWouldVary(entry)) {
5471 LOG(("Validating based on Vary headers returning TRUE\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Validating based on Vary headers returning TRUE\n"); } } while
(0)
;
5472 canAddImsHeader = false;
5473 doValidation = true;
5474 } else {
5475 if (mCachedResponseHead->ExpiresInPast() ||
5476 mCachedResponseHead->MustValidateIfExpired()) {
5477 }
5478 doValidation = nsHttp::ValidationRequired(
5479 isForcedValid, mCachedResponseHead.get(), mLoadFlags,
5480 LoadAllowStaleCacheContent(), LoadForceValidateCacheContent(),
5481 isImmutable, LoadCustomConditionalRequest(), mRequestHead, entry,
5482 cacheControlRequest, fromPreviousSession, &doBackgroundValidation);
5483
5484 // A navigation activated from a completed speculation-rules prefetch record
5485 // must serve the prefetched response as-is (spec: "create navigation params
5486 // from a prefetch record"), so skip freshness/no-store revalidation of the
5487 // entry we just found.
5488 if (doValidation && mLoadInfo->GetActivatedFromNavigationalPrefetch()) {
5489 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " serving speculation-rules prefetch from cache without " "validation"
); } } while (0)
5490 (" serving speculation-rules prefetch from cache without "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " serving speculation-rules prefetch from cache without " "validation"
); } } while (0)
5491 "validation"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " serving speculation-rules prefetch from cache without " "validation"
); } } while (0)
;
5492 doValidation = false;
5493 }
5494 }
5495
5496 nsAutoCString requestedETag;
5497 if (!doValidation &&
5498 NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::If_Match, requestedETag))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::If_Match, requestedETag))), 1)))
&&
5499 (methodWasGet || methodWasHead)) {
5500 nsAutoCString cachedETag;
5501 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, cachedETag);
5502 if (!cachedETag.IsEmpty() && (StringBeginsWith(cachedETag, "W/"_ns) ||
5503 !requestedETag.Equals(cachedETag))) {
5504 // User has defined If-Match header, if the cached entry is not
5505 // matching the provided header value or the cached ETag is weak,
5506 // force validation.
5507 doValidation = true;
5508 }
5509 }
5510
5511 // Previous error should not be propagated.
5512 rv = NS_OK;
5513
5514 if (!doValidation) {
5515 //
5516 // Check the authorization headers used to generate the cache entry.
5517 // We must validate the cache entry if:
5518 //
5519 // 1) the cache entry was generated prior to this session w/
5520 // credentials (see bug 103402).
5521 // 2) the cache entry was generated w/o credentials, but would now
5522 // require credentials (see bug 96705).
5523 //
5524 // NOTE: this does not apply to proxy authentication.
5525 //
5526 entry->GetMetaDataElement("auth", getter_Copies(buf));
5527 doValidation =
5528 (fromPreviousSession && !buf.IsEmpty()) ||
5529 (buf.IsEmpty() && mRequestHead.HasHeader(nsHttp::Authorization));
5530 }
5531
5532 // Bug #561276: We maintain a chain of cache-keys which returns cached
5533 // 3xx-responses (redirects) in order to detect cycles. If a cycle is
5534 // found, ignore the cached response and hit the net. Otherwise, use
5535 // the cached response and add the cache-key to the chain. Note that
5536 // a limited number of redirects (cached or not) is allowed and is
5537 // enforced independently of this mechanism
5538 if (!doValidation && isCachedRedirect) {
5539 nsAutoCString cacheKey;
5540 rv = GenerateCacheKey(mPostID, cacheKey);
5541 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5541); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5541); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5542
5543 auto redirectedCachekeys = mRedirectedCachekeys.Lock();
5544 auto& ref = redirectedCachekeys.ref();
5545 if (!ref) {
5546 ref = std::make_unique<nsTArray<nsCString>>();
5547 } else if (ref->Contains(cacheKey)) {
5548 doValidation = true;
5549 }
5550
5551 LOG(("Redirection-chain %s key %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Redirection-chain %s key %s\n", doValidation ? "contains" :
"does not contain", cacheKey.get()); } } while (0)
5552 doValidation ? "contains" : "does not contain", cacheKey.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Redirection-chain %s key %s\n", doValidation ? "contains" :
"does not contain", cacheKey.get()); } } while (0)
;
5553
5554 // Append cacheKey if not in the chain already
5555 if (!doValidation) {
5556 ref->AppendElement(cacheKey);
5557 }
5558 }
5559
5560 StoreCachedContentIsValid(!doValidation ? CachedContentValidity::Valid
5561 : CachedContentValidity::Invalid);
5562
5563 if (isForcedValid) {
5564 // Telemetry value is only useful if this was a prefetched item
5565 if (!doValidation) {
5566 // Could have gotten to a funky state with some of the if chain above
5567 // and in nsHttp::ValidationRequired. Make sure we get it right here.
5568 entry->MarkForcedValidUse();
5569 }
5570 }
5571
5572 if (doValidation) {
5573 //
5574 // now, we are definitely going to issue a HTTP request to the server.
5575 // make it conditional if possible.
5576 //
5577 // do not attempt to validate no-store content, since servers will not
5578 // expect it to be cached. (we only keep it in our cache for the
5579 // purposes of back/forward, etc.)
5580 //
5581 // the request method MUST be either GET or HEAD (see bug 175641) and
5582 // the cached response code must be < 400
5583 //
5584 // the cached content must not be weakly framed
5585 //
5586 // do not override conditional headers when consumer has defined its own
5587 if (!mCachedResponseHead->NoStore() &&
5588 (mRequestHead.IsGet() || mRequestHead.IsHead()) &&
5589 !LoadCustomConditionalRequest() && !weaklyFramed &&
5590 (mCachedResponseHead->Status() < 400)) {
5591 if (LoadConcurrentCacheAccess()) {
5592 // In case of concurrent read and also validation request we
5593 // must wait for the current writer to close the output stream
5594 // first. Otherwise, when the writer's job would have been interrupted
5595 // before all the data were downloaded, we'd have to do a range request
5596 // which would be a second request in line during this channel's
5597 // life-time. nsHttpChannel is not designed to do that, so rather
5598 // turn off concurrent read and wait for entry's completion.
5599 // Then only re-validation or range-re-validation request will go out.
5600 StoreConcurrentCacheAccess(0);
5601 // This will cause that OnCacheEntryCheck is called again with the same
5602 // entry after the writer is done.
5603 wantCompleteEntry = true;
5604 } else {
5605 nsAutoCString val;
5606 // Add If-Modified-Since header if a Last-Modified was given
5607 // and we are allowed to do this (see bugs 510359 and 269303)
5608 if (canAddImsHeader) {
5609 (void)mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
5610 if (!val.IsEmpty()) {
5611 rv = mRequestHead.SetHeader(nsHttp::If_Modified_Since, val);
5612 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5613 }
5614 }
5615 // Add If-None-Match header if an ETag was given in the response
5616 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, val);
5617 if (!val.IsEmpty()) {
5618 rv = mRequestHead.SetHeader(nsHttp::If_None_Match, val);
5619 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5619); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5619); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5620 }
5621 mDidReval = true;
5622 }
5623 }
5624 }
5625
5626 bool valid = CachedContentIsValid();
5627 if (valid || mDidReval) {
5628 rv = OpenCacheInputStream(entry, valid);
5629 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5630 // If we can't get the entity then we have to act as though we
5631 // don't have the cache entry.
5632 if (mDidReval) {
5633 UntieValidationRequest();
5634 mDidReval = false;
5635 }
5636 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5637 }
5638 }
5639
5640 if (mDidReval) {
5641 *aResult = ENTRY_NEEDS_REVALIDATION;
5642 } else if (wantCompleteEntry) {
5643 *aResult = RECHECK_AFTER_WRITE_FINISHED;
5644 } else {
5645 *aResult = ENTRY_WANTED;
5646
5647 if (doBackgroundValidation) {
5648 PerformBackgroundCacheRevalidation();
5649 }
5650 }
5651
5652 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHTTPChannel::OnCacheEntryCheck exit [this=%p doValidation=%d "
"result=%d]\n", this, doValidation, *aResult); } } while (0)
5653 ("nsHTTPChannel::OnCacheEntryCheck exit [this=%p doValidation=%d "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHTTPChannel::OnCacheEntryCheck exit [this=%p doValidation=%d "
"result=%d]\n", this, doValidation, *aResult); } } while (0)
5654 "result=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHTTPChannel::OnCacheEntryCheck exit [this=%p doValidation=%d "
"result=%d]\n", this, doValidation, *aResult); } } while (0)
5655 this, doValidation, *aResult))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHTTPChannel::OnCacheEntryCheck exit [this=%p doValidation=%d "
"result=%d]\n", this, doValidation, *aResult); } } while (0)
;
5656 return rv;
5657}
5658
5659NS_IMETHODIMPnsresult
5660nsHttpChannel::OnCacheEntryAvailable(nsICacheEntry* entry, bool aNew,
5661 nsresult status) {
5662 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 5662
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 5662); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5663
5664 nsresult rv;
5665
5666 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnCacheEntryAvailable", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject5667( "nsHttpChannel::OnCacheEntryAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
5667 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject5667( "nsHttpChannel::OnCacheEntryAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
5668 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p " "new=%d status=%"
"x" "] for %s", this, entry, aNew, static_cast<uint32_t>
(status), mSpec.get()); } } while (0)
5669 ("nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p " "new=%d status=%"
"x" "] for %s", this, entry, aNew, static_cast<uint32_t>
(status), mSpec.get()); } } while (0)
5670 "new=%d status=%" PRIx32 "] for %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p " "new=%d status=%"
"x" "] for %s", this, entry, aNew, static_cast<uint32_t>
(status), mSpec.get()); } } while (0)
5671 this, entry, aNew, static_cast<uint32_t>(status), mSpec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnCacheEntryAvailable [this=%p entry=%p " "new=%d status=%"
"x" "] for %s", this, entry, aNew, static_cast<uint32_t>
(status), mSpec.get()); } } while (0)
;
5672
5673 // The cache callback arrived (or we're tearing down); the backstop timer is
5674 // no longer needed.
5675 CancelCacheWaitTimer();
5676
5677 // if the channel's already fired onStopRequest, then we should ignore
5678 // this event.
5679 if (!LoadIsPending()) {
5680 mCacheInputStream.CloseAndRelease();
5681 return NS_OK;
5682 }
5683
5684 // If the backstop already fired we gave up on the cache and raced to the
5685 // network; ignore this late callback so we don't reprocess the entry.
5686 if (mCacheWaitTimedOut) {
5687 LOG((" cache callback arrived after backstop timeout, ignoring [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache callback arrived after backstop timeout, ignoring [this=%p]"
, this); } } while (0)
5688 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache callback arrived after backstop timeout, ignoring [this=%p]"
, this); } } while (0)
;
5689 mCacheInputStream.CloseAndRelease();
5690 return NS_OK;
5691 }
5692
5693 rv = OnCacheEntryAvailableInternal(entry, aNew, status);
5694 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5695 CloseCacheEntry(false);
5696 (void)AsyncAbort(rv);
5697 }
5698
5699 return NS_OK;
5700}
5701
5702nsresult nsHttpChannel::OnCacheEntryAvailableInternal(nsICacheEntry* entry,
5703 bool aNew,
5704 nsresult status) {
5705 nsresult rv;
5706
5707 if (mCanceled) {
5708 LOG(("channel was canceled [this=%p status=%" PRIx32 "]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "channel was canceled [this=%p status=%" "x" "]\n", this, static_cast
<uint32_t>(static_cast<nsresult>(mStatus))); } } while
(0)
5709 static_cast<uint32_t>(static_cast<nsresult>(mStatus))))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "channel was canceled [this=%p status=%" "x" "]\n", this, static_cast
<uint32_t>(static_cast<nsresult>(mStatus))); } } while
(0)
;
5710 return mStatus;
5711 }
5712
5713 rv = OnNormalCacheEntryAvailable(entry, aNew, status);
5714
5715 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
5716 return NS_ERROR_DOCUMENT_NOT_CACHED;
5717 }
5718
5719 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5720 return rv;
5721 }
5722
5723 // We may be waiting for more callbacks...
5724 if (AwaitingCacheCallbacks()) {
5725 return NS_OK;
5726 }
5727
5728 return TriggerNetwork();
5729}
5730
5731nsresult nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntry* aEntry,
5732 bool aNew,
5733 nsresult aEntryStatus) {
5734 StoreWaitForCacheEntry(LoadWaitForCacheEntry() & ~WAIT_FOR_CACHE_ENTRY);
5735
5736 if (NS_FAILED(aEntryStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aEntryStatus)), 0)
))
|| aNew) {
5737 // It may happen the entry is doomed between OnCacheEntryCheck and
5738 // OnCacheEntryAvailable; whatever the check armed from it must go.
5739 DiscardCacheEntryCheckState();
5740
5741 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
5742 // if this channel is only allowed to pull from the cache, then
5743 // we must fail if we were unable to open a cache entry for read.
5744 return NS_ERROR_DOCUMENT_NOT_CACHED;
5745 }
5746 }
5747
5748 if (NS_SUCCEEDED(aEntryStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aEntryStatus)), 1
)))
) {
5749 mCacheEntry = aEntry;
5750 StoreCacheEntryIsWriteOnly(aNew);
5751 NoteCacheEntryKeyMatch(aEntry);
5752 }
5753
5754 return NS_OK;
5755}
5756
5757// Generates the proper cache-key for this instance of nsHttpChannel
5758nsresult nsHttpChannel::GenerateCacheKey(uint32_t postID,
5759 nsACString& cacheKey) {
5760 AssembleCacheKey(mSpec.get(), postID, cacheKey);
5761 return NS_OK;
5762}
5763
5764// Assembles a cache-key from the given pieces of information and |mLoadFlags|
5765void nsHttpChannel::AssembleCacheKey(const char* spec, uint32_t postID,
5766 nsACString& cacheKey) {
5767 cacheKey.Truncate();
5768
5769 if (mLoadFlags & LOAD_ANONYMOUS) {
5770 cacheKey.AssignLiteral("anon&");
5771 }
5772
5773 if (postID) {
5774 char buf[32];
5775 SprintfLiteral(buf, "id=%x&", postID);
5776 cacheKey.Append(buf);
5777 }
5778
5779 if (!cacheKey.IsEmpty()) {
5780 cacheKey.AppendLiteral("uri=");
5781 }
5782
5783 // Strip any trailing #ref from the URL before using it as the key
5784 const char* p = strchr(spec, '#');
5785 if (p) {
5786 cacheKey.Append(spec, p - spec);
5787 } else {
5788 cacheKey.Append(spec);
5789 }
5790}
5791
5792nsresult DoUpdateExpirationTime(nsHttpChannel* aSelf,
5793 nsICacheEntry* aCacheEntry,
5794 nsHttpResponseHead* aResponseHead,
5795 uint32_t& aExpirationTime) {
5796 MOZ_ASSERT(aExpirationTime == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aExpirationTime == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aExpirationTime == 0))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aExpirationTime == 0"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 5796
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aExpirationTime == 0"
")"); do { MOZ_CrashSequence(__null, 5796); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5797 NS_ENSURE_TRUE(aResponseHead, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(aResponseHead)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResponseHead" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5797); return NS_ERROR_FAILURE; } } while (false)
;
5798
5799 nsresult rv;
5800
5801 if (!aResponseHead->MustValidate()) {
5802 // For stale-while-revalidate we use expiration time as the absolute base
5803 // for calculation of the stale window absolute end time. Hence, when the
5804 // entry may be served w/o revalidation, we need a non-zero value for the
5805 // expiration time. Let's set it to |now|, which basicly means "expired",
5806 // same as when set to 0.
5807 uint32_t now = NowInSeconds()PRTimeToSeconds(PR_Now());
5808 aExpirationTime = now;
5809
5810 uint32_t freshnessLifetime = 0;
5811
5812 rv = aResponseHead->ComputeFreshnessLifetime(&freshnessLifetime);
5813 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5814
5815 if (freshnessLifetime > 0) {
5816 uint32_t currentAge = 0;
5817
5818 rv = aResponseHead->ComputeCurrentAge(now, aSelf->GetRequestTime(),
5819 &currentAge);
5820 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5821
5822 LOG(("freshnessLifetime = %u, currentAge = %u\n", freshnessLifetime,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "freshnessLifetime = %u, currentAge = %u\n", freshnessLifetime
, currentAge); } } while (0)
5823 currentAge))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "freshnessLifetime = %u, currentAge = %u\n", freshnessLifetime
, currentAge); } } while (0)
;
5824
5825 if (freshnessLifetime > currentAge) {
5826 uint32_t timeRemaining = freshnessLifetime - currentAge;
5827 // be careful... now + timeRemaining may overflow
5828 if (now + timeRemaining < now) {
5829 aExpirationTime = uint32_t(-1);
5830 } else {
5831 aExpirationTime = now + timeRemaining;
5832 }
5833 }
5834 }
5835 }
5836
5837 rv = aCacheEntry->SetExpirationTime(aExpirationTime);
5838 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5838); return rv; } } while (false)
;
5839
5840 return rv;
5841}
5842
5843// UpdateExpirationTime is called when a new response comes in from the server.
5844// It updates the stored response-time and sets the expiration time on the
5845// cache entry.
5846//
5847// From section 13.2.4 of RFC2616, we compute expiration time as follows:
5848//
5849// timeRemaining = freshnessLifetime - currentAge
5850// expirationTime = now + timeRemaining
5851//
5852nsresult nsHttpChannel::UpdateExpirationTime() {
5853 uint32_t expirationTime = 0;
5854 nsresult rv = DoUpdateExpirationTime(this, mCacheEntry, mResponseHead.get(),
5855 expirationTime);
5856 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5856); return rv; } } while (false)
;
5857
5858 return NS_OK;
5859}
5860
5861nsresult nsHttpChannel::OpenCacheInputStream(nsICacheEntry* cacheEntry,
5862 bool startBuffering) {
5863 nsresult rv;
5864
5865 if (IsHTTPS()) {
5866 rv = cacheEntry->GetSecurityInfo(getter_AddRefs(mCachedSecurityInfo));
5867 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5868 LOG(("failed to parse security-info [channel=%p, entry=%p]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "failed to parse security-info [channel=%p, entry=%p]", this
, cacheEntry); } } while (0)
5869 cacheEntry))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "failed to parse security-info [channel=%p, entry=%p]", this
, cacheEntry); } } while (0)
;
5870 NS_WARNING("failed to parse security-info")NS_DebugBreak(NS_DEBUG_WARNING, "failed to parse security-info"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5870)
;
5871 cacheEntry->AsyncDoom(nullptr);
5872 return rv;
5873 }
5874
5875 MOZ_ASSERT(mCachedSecurityInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCachedSecurityInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCachedSecurityInfo))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("mCachedSecurityInfo"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 5875
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedSecurityInfo"
")"); do { MOZ_CrashSequence(__null, 5875); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5876 if (!mCachedSecurityInfo) {
5877 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "mCacheEntry->GetSecurityInfo returned success but did not "
"return the security info [channel=%p, entry=%p]", this, cacheEntry
); } } while (0)
5878 ("mCacheEntry->GetSecurityInfo returned success but did not "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "mCacheEntry->GetSecurityInfo returned success but did not "
"return the security info [channel=%p, entry=%p]", this, cacheEntry
); } } while (0)
5879 "return the security info [channel=%p, entry=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "mCacheEntry->GetSecurityInfo returned success but did not "
"return the security info [channel=%p, entry=%p]", this, cacheEntry
); } } while (0)
5880 this, cacheEntry))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "mCacheEntry->GetSecurityInfo returned success but did not "
"return the security info [channel=%p, entry=%p]", this, cacheEntry
); } } while (0)
;
5881 cacheEntry->AsyncDoom(nullptr);
5882 return NS_ERROR_UNEXPECTED; // XXX error code
5883 }
5884 }
5885
5886 // Keep the conditions below in sync with the conditions in ReadFromCache.
5887
5888 rv = NS_OK;
Value stored to 'rv' is never read
5889
5890 if (WillRedirect(*mCachedResponseHead)) {
5891 // Do not even try to read the entity for a redirect because we do not
5892 // return an entity to the application when we process redirects.
5893 LOG(("Will skip read of cached redirect entity\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Will skip read of cached redirect entity\n"); } } while (0
)
;
5894 return NS_OK;
5895 }
5896
5897 if ((mLoadFlags & nsICachingChannel::LOAD_ONLY_IF_MODIFIED) &&
5898 !LoadCachedContentIsPartial()) {
5899 // For LOAD_ONLY_IF_MODIFIED, we usually don't have to deal with the
5900 // cached entity.
5901 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Will skip read from cache based on LOAD_ONLY_IF_MODIFIED "
"load flag\n"); } } while (0)
5902 ("Will skip read from cache based on LOAD_ONLY_IF_MODIFIED "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Will skip read from cache based on LOAD_ONLY_IF_MODIFIED "
"load flag\n"); } } while (0)
5903 "load flag\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Will skip read from cache based on LOAD_ONLY_IF_MODIFIED "
"load flag\n"); } } while (0)
;
5904 return NS_OK;
5905 }
5906
5907 // Open an input stream for the entity, so that the call to OpenInputStream
5908 // happens off the main thread.
5909 nsCOMPtr<nsIInputStream> stream;
5910
5911 // If an alternate representation was requested, try to open the alt
5912 // input stream.
5913 // If the entry has "alt-data-from-child" metadata (the remote type of the
5914 // content process that wrote it), then only open the altdata stream if the
5915 // consumer is also from child.
5916 nsCString altDataRemoteType;
5917 rv = cacheEntry->GetMetaDataElement("alt-data-from-child",
5918 getter_Copies(altDataRemoteType));
5919 bool altDataFromChild = !altDataRemoteType.IsEmpty();
5920
5921 nsAutoCString altDataType;
5922 (void)cacheEntry->GetAltDataType(altDataType);
5923
5924 nsAutoCString contentType;
5925 mCachedResponseHead->ContentType(contentType);
5926
5927 // Alt-data written by a content process (bytecode cache) may only be
5928 // consumed by a load from the same remote type, with a principal matching
5929 // the one that produced it. The triggering remote type of a load from a
5930 // content process is that of the process which sent it.
5931 if (altDataFromChild && !altDataType.IsEmpty()) {
5932 nsAutoCString storedOrigin;
5933 cacheEntry->GetMetaDataElement("alt-data-principal",
5934 getter_Copies(storedOrigin));
5935 nsAutoCString currentOrigin;
5936 GetAltDataBindingOrigin(currentOrigin);
5937 dom::RemoteType currentRemoteType;
5938 MOZ_ALWAYS_SUCCEEDS(mLoadInfo->GetTriggeringRemoteType(currentRemoteType))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mLoadInfo->GetTriggeringRemoteType(currentRemoteType))), 1
)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mLoadInfo->GetTriggeringRemoteType(currentRemoteType))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 5938
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mLoadInfo->GetTriggeringRemoteType(currentRemoteType))"
")"); do { MOZ_CrashSequence(__null, 5938); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
5939 nsCString currentRemoteTypeString = currentRemoteType.Stringify();
5940 if (storedOrigin.IsEmpty() || currentOrigin.IsEmpty() ||
5941 !storedOrigin.Equals(currentOrigin) ||
5942 !altDataRemoteType.Equals(currentRemoteTypeString)) {
5943 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal or remote type "
"mismatch [channel=%p, stored='%s' from '%s', current='%s' from "
"'%s']", this, storedOrigin.get(), altDataRemoteType.get(), currentOrigin
.get(), currentRemoteTypeString.get()); } } while (0)
5944 ("Rejecting child-written alt-data due to principal or remote type "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal or remote type "
"mismatch [channel=%p, stored='%s' from '%s', current='%s' from "
"'%s']", this, storedOrigin.get(), altDataRemoteType.get(), currentOrigin
.get(), currentRemoteTypeString.get()); } } while (0)
5945 "mismatch [channel=%p, stored='%s' from '%s', current='%s' from "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal or remote type "
"mismatch [channel=%p, stored='%s' from '%s', current='%s' from "
"'%s']", this, storedOrigin.get(), altDataRemoteType.get(), currentOrigin
.get(), currentRemoteTypeString.get()); } } while (0)
5946 "'%s']",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal or remote type "
"mismatch [channel=%p, stored='%s' from '%s', current='%s' from "
"'%s']", this, storedOrigin.get(), altDataRemoteType.get(), currentOrigin
.get(), currentRemoteTypeString.get()); } } while (0)
5947 this, storedOrigin.get(), altDataRemoteType.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal or remote type "
"mismatch [channel=%p, stored='%s' from '%s', current='%s' from "
"'%s']", this, storedOrigin.get(), altDataRemoteType.get(), currentOrigin
.get(), currentRemoteTypeString.get()); } } while (0)
5948 currentOrigin.get(), currentRemoteTypeString.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Rejecting child-written alt-data due to principal or remote type "
"mismatch [channel=%p, stored='%s' from '%s', current='%s' from "
"'%s']", this, storedOrigin.get(), altDataRemoteType.get(), currentOrigin
.get(), currentRemoteTypeString.get()); } } while (0)
;
5949 altDataType.Truncate();
5950 }
5951 }
5952
5953 bool foundAltData = false;
5954 bool deliverAltData = true;
5955 if (!LoadDisableAltDataCache() && !altDataType.IsEmpty() &&
5956 !mPreferredCachedAltDataTypes.IsEmpty() &&
5957 altDataFromChild == LoadAltDataForChild()) {
5958 for (auto& pref : mPreferredCachedAltDataTypes) {
5959 if (pref.type() == altDataType &&
5960 (pref.contentType().IsEmpty() || pref.contentType() == contentType)) {
5961 foundAltData = true;
5962 deliverAltData =
5963 pref.deliverAltData() ==
5964 nsICacheInfoChannel::PreferredAlternativeDataDeliveryType::ASYNC;
5965 break;
5966 }
5967 }
5968 }
5969
5970 nsCOMPtr<nsIInputStream> altData;
5971 int64_t altDataSize = -1;
5972 if (foundAltData) {
5973 rv = cacheEntry->OpenAlternativeInputStream(altDataType,
5974 getter_AddRefs(altData));
5975 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5976 // We have succeeded.
5977 mAvailableCachedAltDataType = altDataType;
5978 StoreDeliveringAltData(deliverAltData);
5979
5980 // Set the correct data size on the channel.
5981 (void)cacheEntry->GetAltDataSize(&altDataSize);
5982 mAltDataLength = altDataSize;
5983
5984 LOG(("Opened alt-data input stream [type=%s, size=%" PRId64do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened alt-data input stream [type=%s, size=%" "l" "d" ", deliverAltData=%d]"
, altDataType.get(), mAltDataLength, deliverAltData); } } while
(0)
5985 ", deliverAltData=%d]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened alt-data input stream [type=%s, size=%" "l" "d" ", deliverAltData=%d]"
, altDataType.get(), mAltDataLength, deliverAltData); } } while
(0)
5986 altDataType.get(), mAltDataLength, deliverAltData))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened alt-data input stream [type=%s, size=%" "l" "d" ", deliverAltData=%d]"
, altDataType.get(), mAltDataLength, deliverAltData); } } while
(0)
;
5987
5988 if (deliverAltData) {
5989 stream = altData;
5990 }
5991 }
5992 }
5993
5994 if (!stream) {
5995 rv = cacheEntry->OpenInputStream(0, getter_AddRefs(stream));
5996 }
5997
5998 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5999 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Failed to open cache input stream [channel=%p, " "mCacheEntry=%p]"
, this, cacheEntry); } } while (0)
6000 ("Failed to open cache input stream [channel=%p, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Failed to open cache input stream [channel=%p, " "mCacheEntry=%p]"
, this, cacheEntry); } } while (0)
6001 "mCacheEntry=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Failed to open cache input stream [channel=%p, " "mCacheEntry=%p]"
, this, cacheEntry); } } while (0)
6002 this, cacheEntry))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Failed to open cache input stream [channel=%p, " "mCacheEntry=%p]"
, this, cacheEntry); } } while (0)
;
6003 return rv;
6004 }
6005
6006 if (startBuffering) {
6007 bool nonBlocking;
6008 rv = stream->IsNonBlocking(&nonBlocking);
6009 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && nonBlocking) startBuffering = false;
6010 }
6011
6012 if (!startBuffering) {
6013 // Bypass wrapping the input stream for the new cache back-end since
6014 // nsIStreamTransportService expects a blocking stream. Preloading of
6015 // the data must be done on the level of the cache backend, internally.
6016 //
6017 // We do not connect the stream to the stream transport service if we
6018 // have to validate the entry with the server. If we did, we would get
6019 // into a race condition between the stream transport service reading
6020 // the existing contents and the opening of the cache entry's output
6021 // stream to write the new contents in the case where we get a non-304
6022 // response.
6023 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened cache input stream without buffering [channel=%p, "
"mCacheEntry=%p, stream=%p]", this, cacheEntry, stream.get()
); } } while (0)
6024 ("Opened cache input stream without buffering [channel=%p, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened cache input stream without buffering [channel=%p, "
"mCacheEntry=%p, stream=%p]", this, cacheEntry, stream.get()
); } } while (0)
6025 "mCacheEntry=%p, stream=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened cache input stream without buffering [channel=%p, "
"mCacheEntry=%p, stream=%p]", this, cacheEntry, stream.get()
); } } while (0)
6026 this, cacheEntry, stream.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened cache input stream without buffering [channel=%p, "
"mCacheEntry=%p, stream=%p]", this, cacheEntry, stream.get()
); } } while (0)
;
6027 mCacheInputStream.takeOver(stream);
6028 return rv;
6029 }
6030
6031 // Have the stream transport service start reading the entity on one of its
6032 // background threads.
6033
6034 nsCOMPtr<nsITransport> transport;
6035 nsCOMPtr<nsIInputStream> wrapper;
6036
6037 nsCOMPtr<nsIStreamTransportService> sts(
6038 components::StreamTransport::Service());
6039 rv = sts ? NS_OK : NS_ERROR_NOT_AVAILABLE;
6040 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6041 rv = sts->CreateInputTransport(stream, true, getter_AddRefs(transport));
6042 }
6043 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6044 rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(wrapper));
6045 }
6046 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6047 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened cache input stream [channel=%p, wrapper=%p, " "transport=%p, stream=%p]"
, this, wrapper.get(), transport.get(), stream.get()); } } while
(0)
6048 ("Opened cache input stream [channel=%p, wrapper=%p, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened cache input stream [channel=%p, wrapper=%p, " "transport=%p, stream=%p]"
, this, wrapper.get(), transport.get(), stream.get()); } } while
(0)
6049 "transport=%p, stream=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened cache input stream [channel=%p, wrapper=%p, " "transport=%p, stream=%p]"
, this, wrapper.get(), transport.get(), stream.get()); } } while
(0)
6050 this, wrapper.get(), transport.get(), stream.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opened cache input stream [channel=%p, wrapper=%p, " "transport=%p, stream=%p]"
, this, wrapper.get(), transport.get(), stream.get()); } } while
(0)
;
6051 } else {
6052 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Failed to open cache input stream [channel=%p, " "wrapper=%p, transport=%p, stream=%p]"
, this, wrapper.get(), transport.get(), stream.get()); } } while
(0)
6053 ("Failed to open cache input stream [channel=%p, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Failed to open cache input stream [channel=%p, " "wrapper=%p, transport=%p, stream=%p]"
, this, wrapper.get(), transport.get(), stream.get()); } } while
(0)
6054 "wrapper=%p, transport=%p, stream=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Failed to open cache input stream [channel=%p, " "wrapper=%p, transport=%p, stream=%p]"
, this, wrapper.get(), transport.get(), stream.get()); } } while
(0)
6055 this, wrapper.get(), transport.get(), stream.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Failed to open cache input stream [channel=%p, " "wrapper=%p, transport=%p, stream=%p]"
, this, wrapper.get(), transport.get(), stream.get()); } } while
(0)
;
6056
6057 stream->Close();
6058 return rv;
6059 }
6060
6061 mCacheInputStream.takeOver(wrapper);
6062
6063 return NS_OK;
6064}
6065
6066// Actually process the cached response that we started to handle in CheckCache
6067// and/or StartBufferingCachedEntity.
6068nsresult nsHttpChannel::ReadFromCache(void) {
6069 NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mCacheEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mCacheEntry" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6069); return NS_ERROR_FAILURE; } } while (false)
;
6070 NS_ENSURE_TRUE(CachedContentIsValid(), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(CachedContentIsValid())), 0))
) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "CachedContentIsValid()"
") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6070); return NS_ERROR_FAILURE; } } while (false)
;
6071 NS_ENSURE_TRUE(!mCachePump, NS_OK)do { if ((__builtin_expect(!!(!(!mCachePump)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!mCachePump" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6071); return NS_OK; } } while (false)
; // already opened
6072
6073 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ReadFromCache [this=%p] " "Using cached copy of: %s\n"
, this, mSpec.get()); } } while (0)
6074 ("nsHttpChannel::ReadFromCache [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ReadFromCache [this=%p] " "Using cached copy of: %s\n"
, this, mSpec.get()); } } while (0)
6075 "Using cached copy of: %s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ReadFromCache [this=%p] " "Using cached copy of: %s\n"
, this, mSpec.get()); } } while (0)
6076 this, mSpec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ReadFromCache [this=%p] " "Using cached copy of: %s\n"
, this, mSpec.get()); } } while (0)
;
6077
6078 if (mCachedResponseHead) mResponseHead = std::move(mCachedResponseHead);
6079
6080 UpdateInhibitPersistentCachingFlag();
6081
6082 // if we don't already have security info, try to get it from the cache
6083 // entry. there are two cases to consider here: 1) we are just reading
6084 // from the cache, or 2) this may be due to a 304 not modified response,
6085 // in which case we could have security info from a socket transport.
6086 if (!mSecurityInfo) mSecurityInfo = mCachedSecurityInfo;
6087
6088 nsresult rv;
6089
6090 // Keep the conditions below in sync with the conditions in
6091 // StartBufferingCachedEntity.
6092
6093 if (WillRedirect(*mResponseHead)) {
6094 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
6095 // to avoid event dispatching latency.
6096 MOZ_ASSERT(!mCacheInputStream)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCacheInputStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCacheInputStream))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mCacheInputStream"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 6096
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6096); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6097 LOG(("Skipping skip read of cached redirect entity\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Skipping skip read of cached redirect entity\n"); } } while
(0)
;
6098 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
6099 }
6100
6101 if ((mLoadFlags & LOAD_ONLY_IF_MODIFIED) && !LoadCachedContentIsPartial()) {
6102 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Skipping read from cache based on LOAD_ONLY_IF_MODIFIED " "load flag\n"
); } } while (0)
6103 ("Skipping read from cache based on LOAD_ONLY_IF_MODIFIED "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Skipping read from cache based on LOAD_ONLY_IF_MODIFIED " "load flag\n"
); } } while (0)
6104 "load flag\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Skipping read from cache based on LOAD_ONLY_IF_MODIFIED " "load flag\n"
); } } while (0)
;
6105 MOZ_ASSERT(!mCacheInputStream)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCacheInputStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCacheInputStream))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!mCacheInputStream"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 6105
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6105); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6106 // TODO: Bug 759040 - We should call HandleAsyncNotModified directly
6107 // here, to avoid event dispatching latency.
6108 return AsyncCall(&nsHttpChannel::HandleAsyncNotModified);
6109 }
6110
6111 MOZ_ASSERT(mCacheInputStream)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCacheInputStream)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCacheInputStream))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mCacheInputStream"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 6111
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6111); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6112 if (!mCacheInputStream) {
6113 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "mCacheInputStream is null but we're expecting to "
"be able to read from it.", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6115); MOZ_PretendNoReturn(); } while (0)
6114 "mCacheInputStream is null but we're expecting to "do { NS_DebugBreak(NS_DEBUG_ASSERTION, "mCacheInputStream is null but we're expecting to "
"be able to read from it.", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6115); MOZ_PretendNoReturn(); } while (0)
6115 "be able to read from it.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "mCacheInputStream is null but we're expecting to "
"be able to read from it.", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6115); MOZ_PretendNoReturn(); } while (0)
;
6116 return NS_ERROR_UNEXPECTED;
6117 }
6118
6119 nsCOMPtr<nsIInputStream> inputStream = mCacheInputStream.forget();
6120
6121 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), inputStream, 0, 0,
6122 true);
6123 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6124 inputStream->Close();
6125 return rv;
6126 }
6127
6128 rv = mCachePump->AsyncRead(this);
6129 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6130
6131 // Performance timing uses this as responseStart for every cache hit; keep
6132 // an earlier value set by the caller, e.g. when a prefetch completed.
6133 if (mCacheReadStart.IsNull()) {
6134 mCacheReadStart = TimeStamp::Now();
6135 }
6136
6137 uint32_t suspendCount = mSuspendCount;
6138 if (LoadAsyncResumePending()) {
6139 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Suspend()'ing cache pump once because of async resume pending"
", sc=%u, pump=%p, this=%p", suspendCount, mCachePump.get(),
this); } } while (0)
6140 (" Suspend()'ing cache pump once because of async resume pending"do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Suspend()'ing cache pump once because of async resume pending"
", sc=%u, pump=%p, this=%p", suspendCount, mCachePump.get(),
this); } } while (0)
6141 ", sc=%u, pump=%p, this=%p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Suspend()'ing cache pump once because of async resume pending"
", sc=%u, pump=%p, this=%p", suspendCount, mCachePump.get(),
this); } } while (0)
6142 suspendCount, mCachePump.get(), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Suspend()'ing cache pump once because of async resume pending"
", sc=%u, pump=%p, this=%p", suspendCount, mCachePump.get(),
this); } } while (0)
;
6143 ++suspendCount;
6144 }
6145 while (suspendCount--) {
6146 mCachePump->Suspend();
6147 }
6148
6149 return NS_OK;
6150}
6151
6152void nsHttpChannel::CloseCacheEntry(bool doomOnFailure) {
6153 CancelCacheWaitTimer();
6154 mCacheInputStream.CloseAndRelease();
6155
6156 if (!mCacheEntry) return;
6157
6158 LOG(("nsHttpChannel::CloseCacheEntry [this=%p] mStatus=%" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CloseCacheEntry [this=%p] mStatus=%" "x" " CacheEntryIsWriteOnly=%x"
, this, static_cast<uint32_t>(static_cast<nsresult>
(mStatus)), LoadCacheEntryIsWriteOnly()); } } while (0)
6159 " CacheEntryIsWriteOnly=%x",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CloseCacheEntry [this=%p] mStatus=%" "x" " CacheEntryIsWriteOnly=%x"
, this, static_cast<uint32_t>(static_cast<nsresult>
(mStatus)), LoadCacheEntryIsWriteOnly()); } } while (0)
6160 this, static_cast<uint32_t>(static_cast<nsresult>(mStatus)),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CloseCacheEntry [this=%p] mStatus=%" "x" " CacheEntryIsWriteOnly=%x"
, this, static_cast<uint32_t>(static_cast<nsresult>
(mStatus)), LoadCacheEntryIsWriteOnly()); } } while (0)
6161 LoadCacheEntryIsWriteOnly()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CloseCacheEntry [this=%p] mStatus=%" "x" " CacheEntryIsWriteOnly=%x"
, this, static_cast<uint32_t>(static_cast<nsresult>
(mStatus)), LoadCacheEntryIsWriteOnly()); } } while (0)
;
6162
6163 // If we have begun to create or replace a cache entry, and that cache
6164 // entry is not complete and not resumable, then it needs to be doomed.
6165 // Otherwise, CheckCache will make the mistake of thinking that the
6166 // partial cache entry is complete.
6167
6168 bool doom = false;
6169 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref) {
6170 // A response blocked by ORB is fully written to the cache before the block
6171 // decision is made, so it must be doomed here; otherwise it lingers as a
6172 // complete entry that a same-partition request (e.g. a navigation reusing a
6173 // prefetch) could consume.
6174 doom = true;
6175 } else if (LoadInitedCacheEntry()) {
6176 MOZ_ASSERT(mResponseHead, "oops")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mResponseHead)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mResponseHead))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mResponseHead" " ("
"oops" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "oops" ")"); do { MOZ_CrashSequence(__null, 6176); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6177 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) && doomOnFailure && LoadCacheEntryIsWriteOnly() &&
6178 (!mResponseHead || !mResponseHead->IsResumable())) {
6179 doom = true;
6180 }
6181 } else if (LoadCacheEntryIsWriteOnly()) {
6182 doom = true;
6183 }
6184
6185 if (doom) {
6186 LOG((" dooming cache entry!!"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " dooming cache entry!!"); } } while (0)
;
6187 mCacheEntry->AsyncDoom(nullptr);
6188 } else {
6189 // Store updated security info, makes cached EV status race less likely
6190 // (see bug 1040086). On a plain cache hit ReadFromCache() adopted the info
6191 // this very entry handed us in OpenCacheInputStream(), so storing it back
6192 // would only re-serialize the certificate chain and rewrite the entry file.
6193 if (mSecurityInfo && mSecurityInfo != mCachedSecurityInfo) {
6194 mCacheEntry->SetSecurityInfo(mSecurityInfo);
6195 }
6196
6197 // For prefetch requests without cache headers, force the cache entry
6198 // to remain valid so that subsequent navigations reuse the prefetched
6199 // response instead of re-fetching. See bug 1527334.
6200 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && mResponseHead) {
6201 if (StringBeginsWith(GetSecPurpose(), "prefetch"_ns) &&
6202 !mResponseHead->MustValidate()) {
6203 nsAutoCString expires;
6204 (void)mResponseHead->GetHeader(nsHttp::Expires, expires);
6205 nsAutoCString cacheControlHeader;
6206 (void)mResponseHead->GetHeader(nsHttp::Cache_Control,
6207 cacheControlHeader);
6208 CacheControlParser cacheControl(cacheControlHeader);
6209 uint32_t maxAge;
6210 if (!cacheControl.MaxAge(&maxAge) && expires.IsEmpty()) {
6211 uint32_t forceValidFor =
6212 StaticPrefs::network_prefetch_next_force_valid_for();
6213 if (forceValidFor > 0) {
6214 mCacheEntry->ForceValidFor(forceValidFor);
6215 }
6216 }
6217 }
6218 }
6219
6220 // ORB's JavaScript validation finishes asynchronously, after this point,
6221 // so the response may yet be blocked. Keep a reference to the committed
6222 // entry so CancelInternal() can doom it if that happens.
6223 if (mORB && mORB->IsSniffing()) {
6224 mORBValidationCacheEntry = mCacheEntry;
6225 }
6226 }
6227
6228 mCachedResponseHead = nullptr;
6229
6230 mCachePump = nullptr;
6231 // This releases the entry for other consumers to use.
6232 // We call Dismiss() in case someone still keeps a reference
6233 // to this entry handle.
6234 mCacheEntry->Dismiss();
6235 mCacheEntry = nullptr;
6236 StoreCacheEntryIsWriteOnly(false);
6237 StoreInitedCacheEntry(false);
6238}
6239
6240void nsHttpChannel::OnOpaqueResponseAllowed() {
6241 // mORBValidationCacheEntry is only ever touched on the main thread; this
6242 // relies on ORB delivering its validation verdict there.
6243 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 6243
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 6243); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6244 // ORB allowed the response, so the entry we kept in case it had to be doomed
6245 // (see CloseCacheEntry) can stay in the cache; drop our reference to it.
6246 mORBValidationCacheEntry = nullptr;
6247}
6248
6249// Initialize the cache entry for writing.
6250// - finalize storage policy
6251// - store security info
6252// - update expiration time
6253// - store headers and other meta data
6254nsresult nsHttpChannel::InitCacheEntry() {
6255 nsresult rv;
6256
6257 NS_ENSURE_TRUE(mCacheEntry, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mCacheEntry)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mCacheEntry" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6257); return NS_ERROR_UNEXPECTED; } } while (false)
;
6258 // if only reading, nothing to be done here.
6259 if (LoadCacheEntryIsReadOnly()) return NS_OK;
6260
6261 // Don't cache the response again if already cached...
6262 if (CachedContentIsValid()) return NS_OK;
6263
6264 LOG(("nsHttpChannel::InitCacheEntry [this=%p entry=%p]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::InitCacheEntry [this=%p entry=%p]\n", this,
mCacheEntry.get()); } } while (0)
6265 mCacheEntry.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::InitCacheEntry [this=%p entry=%p]\n", this,
mCacheEntry.get()); } } while (0)
;
6266
6267 // Normally already handled before the response was applied to the entry, but
6268 // recreating an alias entry would doom and rewrite another URL's entry, so
6269 // never reach Recreate() below while the flag is still set.
6270 rv = MaybeReplaceNoVarySearchAliasEntry();
6271 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return NS_OK;
6272
6273 bool recreate = !LoadCacheEntryIsWriteOnly();
6274 bool dontPersist = mLoadFlags & INHIBIT_PERSISTENT_CACHING;
6275
6276 if (!recreate && dontPersist) {
6277 // If the current entry is persistent but we inhibit peristence
6278 // then force recreation of the entry as memory/only.
6279 rv = mCacheEntry->GetPersistent(&recreate);
6280 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6281 }
6282
6283 if (recreate) {
6284 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " we have a ready entry, but reading it again from the server -> "
"recreating cache entry\n"); } } while (0)
6285 (" we have a ready entry, but reading it again from the server -> "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " we have a ready entry, but reading it again from the server -> "
"recreating cache entry\n"); } } while (0)
6286 "recreating cache entry\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " we have a ready entry, but reading it again from the server -> "
"recreating cache entry\n"); } } while (0)
;
6287 // clean the altData cache and reset this to avoid wrong content length
6288 mAvailableCachedAltDataType.Truncate();
6289 StoreDeliveringAltData(false);
6290
6291 nsCOMPtr<nsICacheEntry> currentEntry;
6292 currentEntry.swap(mCacheEntry);
6293 rv = currentEntry->Recreate(dontPersist, getter_AddRefs(mCacheEntry));
6294 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6295 LOG((" recreation failed, the response will not be cached"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " recreation failed, the response will not be cached"); } }
while (0)
;
6296 return NS_OK;
6297 }
6298
6299 StoreCacheEntryIsWriteOnly(true);
6300
6301 // Since we recreated, the new entry doesn't have expiration set yet.
6302 // UpdateExpirationTime was called before ParseDictionary on the old entry,
6303 // but we need to set it on this new entry too.
6304 rv = UpdateExpirationTime();
6305 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6306 }
6307
6308 // mark this weakly framed until a response body is seen
6309 mCacheEntry->SetMetaDataElement("strongly-framed", "0");
6310
6311 rv = AddCacheEntryHeaders(mCacheEntry, false);
6312 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6313
6314 StoreInitedCacheEntry(true);
6315
6316 // Don't perform the check when writing (doesn't make sense)
6317 StoreConcurrentCacheAccess(0);
6318
6319 return NS_OK;
6320}
6321
6322void nsHttpChannel::UpdateInhibitPersistentCachingFlag() {
6323 // The no-store directive within the 'Cache-Control:' header indicates
6324 // that we must not store the response in a persistent cache.
6325 if (mResponseHead->NoStore()) {
6326 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6327 return;
6328 }
6329
6330 if (!StaticPrefs::network_cache_persist_permanent_redirects_http() &&
6331 mURI->SchemeIs("http") &&
6332 nsHttp::IsPermanentRedirect(mResponseHead->Status())) {
6333 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6334 return;
6335 }
6336
6337 // Only cache SSL content on disk if the pref is set
6338 if (!gHttpHandler->IsPersistentHttpsCachingEnabled() && IsHTTPS()) {
6339 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6340 }
6341}
6342
6343nsresult DoAddCacheEntryHeaders(nsHttpChannel* self, nsICacheEntry* entry,
6344 nsHttpRequestHead* requestHead,
6345 nsHttpResponseHead* responseHead,
6346 nsITransportSecurityInfo* securityInfo,
6347 bool aModified) {
6348 nsresult rv;
6349
6350 LOG(("nsHttpChannel::AddCacheEntryHeaders [this=%p] begin", self))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::AddCacheEntryHeaders [this=%p] begin", self
); } } while (0)
;
6351 // Store secure data in memory only
6352 if (securityInfo) {
6353 entry->SetSecurityInfo(securityInfo);
6354 }
6355
6356 // Note: if aModified == false, then we're processing a 304 Not Modified,
6357 // and we *shouldn't* have any change to the Dictionary (and won't be
6358 // replacing the DictionaryEntry, though if the Match/Match-dest/Id/Type
6359 // changed, we may need to rewrite it. XXX?
6360
6361 // Store the HTTP request method with the cache entry so we can distinguish
6362 // for example GET and HEAD responses.
6363 nsAutoCString method;
6364 requestHead->Method(method);
6365 rv = entry->SetMetaDataElement("request-method", method.get());
6366 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6367
6368 // Store the HTTP authorization scheme used if any...
6369 rv = StoreAuthorizationMetaData(entry, requestHead);
6370 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6371
6372 rv = self->UpdateCacheEntryHeaders(entry, nullptr);
6373 return rv;
6374}
6375
6376nsresult nsHttpChannel::AddCacheEntryHeaders(nsICacheEntry* entry,
6377 bool aModified) {
6378 return DoAddCacheEntryHeaders(this, entry, &mRequestHead, mResponseHead.get(),
6379 mSecurityInfo, aModified);
6380}
6381
6382nsresult nsHttpChannel::UpdateCacheEntryHeaders(nsICacheEntry* entry,
6383 const nsHttpAtom* aAtom) {
6384 nsresult rv = NS_OK;
6385
6386 // Iterate over the headers listed in the Vary response header, and
6387 // store the value of the corresponding request header so we can verify
6388 // that it has not varied when we try to re-use the cached response at
6389 // a later time. Take care to store "Cookie" headers only as hashes
6390 // due to security considerations and the fact that they can be pretty
6391 // large (bug 468426). We take care of "Vary: cookie" in ResponseWouldVary.
6392 //
6393 // NOTE: if "Vary: accept, cookie", then we will store the "accept" header
6394 // in the cache. we could try to avoid needlessly storing the "accept"
6395 // header in this case, but it doesn't seem worth the extra code to perform
6396 // the check.
6397 {
6398 nsAutoCString buf, metaKey;
6399 (void)mResponseHead->GetHeader(nsHttp::Vary, buf);
6400
6401 constexpr auto prefix = "request-"_ns;
6402
6403 for (const nsACString& token :
6404 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
6405 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "processing %s"
, this, nsPromiseFlatCString(token).get()); } } while (0)
6406 ("nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "processing %s"
, this, nsPromiseFlatCString(token).get()); } } while (0)
6407 "processing %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "processing %s"
, this, nsPromiseFlatCString(token).get()); } } while (0)
6408 this, nsPromiseFlatCString(token).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "processing %s"
, this, nsPromiseFlatCString(token).get()); } } while (0)
;
6409 if (!token.EqualsLiteral("*")) {
6410 nsHttpAtom atom = nsHttp::ResolveAtom(token);
6411 if (!aAtom || atom == *aAtom) {
6412 nsAutoCString val;
6413 nsAutoCString hash;
6414 if (NS_SUCCEEDED(mRequestHead.GetHeader(atom, val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(atom, val))), 1)))
) {
6415 // If cookie-header, store a hash of the value
6416 if (atom == nsHttp::Cookie) {
6417 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "cookie-value %s"
, this, val.get()); } } while (0)
6418 ("nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "cookie-value %s"
, this, val.get()); } } while (0)
6419 "cookie-value %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "cookie-value %s"
, this, val.get()); } } while (0)
6420 this, val.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "cookie-value %s"
, this, val.get()); } } while (0)
;
6421 rv = Hash(val.get(), hash);
6422 // If hash failed, store a string not very likely
6423 // to be the result of subsequent hashes
6424 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6425 val = "<hash failed>"_ns;
6426 } else {
6427 val = std::move(hash);
6428 }
6429
6430 LOG((" hashed to %s\n", val.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " hashed to %s\n", val.get()); } } while (0)
;
6431 }
6432
6433 // build cache meta data key and set meta data element...
6434 metaKey = prefix + token;
6435 entry->SetMetaDataElement(metaKey.get(), val.get());
6436 } else {
6437 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "clearing metadata for %s"
, this, nsPromiseFlatCString(token).get()); } } while (0)
6438 ("nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "clearing metadata for %s"
, this, nsPromiseFlatCString(token).get()); } } while (0)
6439 "clearing metadata for %s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "clearing metadata for %s"
, this, nsPromiseFlatCString(token).get()); } } while (0)
6440 this, nsPromiseFlatCString(token).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ProcessVaryCacheEntryHeaders [this=%p] " "clearing metadata for %s"
, this, nsPromiseFlatCString(token).get()); } } while (0)
;
6441 metaKey = prefix + token;
6442 entry->SetMetaDataElement(metaKey.get(), nullptr);
6443 }
6444 }
6445 }
6446 }
6447 }
6448 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6449 return rv;
6450 }
6451 // Store the received HTTP head with the cache entry as an element of
6452 // the meta data.
6453 nsAutoCString head;
6454 mResponseHead->Flatten(head, true);
6455 rv = entry->SetMetaDataElement("response-head", head.get());
6456 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6457 head.Truncate();
6458 mResponseHead->FlattenNetworkOriginalHeaders(head);
6459 rv = entry->SetMetaDataElement("original-response-headers", head.get());
6460 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6461
6462 // Store No-Vary-Search header in cache metadata and notify the secondary
6463 // index so variant URLs can match this entry on future cache lookups.
6464 nsAutoCString noVarySearch;
6465 if (StaticPrefs::network_cache_no_vary_search() &&
6466 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::No_Vary_Search, noVarySearch))), 1)))
6467 mResponseHead->GetHeader(nsHttp::No_Vary_Search, noVarySearch))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::No_Vary_Search, noVarySearch))), 1)))
&&
6468 !noVarySearch.IsEmpty()) {
6469 glean::network::no_vary_search_header_received.Add(1);
6470 bool parseError = false;
6471 auto data = ParseNoVarySearchHeader(noVarySearch, &parseError);
6472 glean::network::no_vary_search_rule_type
6473 .Get(NoVarySearchRuleLabel(data.paramsRule))
6474 .Add(1);
6475 if (parseError) {
6476 glean::network::no_vary_search_parse_error.Add(1);
6477 }
6478
6479 rv = entry->SetMetaDataElement("no-vary-search", noVarySearch.get());
6480 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6481 return rv;
6482 }
6483
6484 if (mCacheEntryURI) {
6485 if (auto* svc = CacheStorageService::Self()) {
6486 svc->NoteNoVarySearchEntry(entry, mCacheEntryURI);
6487 }
6488 }
6489 }
6490
6491 // Indicate we have successfully finished setting metadata on the cache
6492 // entry.
6493 return entry->MetaDataReady();
6494}
6495
6496bool nsHttpChannel::ParseDictionary(nsICacheEntry* aEntry,
6497 nsHttpResponseHead* aResponseHead,
6498 bool aModified) {
6499 nsAutoCString val;
6500 if (NS_SUCCEEDED(aResponseHead->GetHeader(nsHttp::Use_As_Dictionary, val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Use_As_Dictionary, val))), 1)))
) {
6501 nsAutoCStringN<128> matchVal;
6502 nsAutoCStringN<64> matchIdVal;
6503 nsTArray<nsCString> matchDestItems;
6504 nsAutoCString typeVal;
6505
6506 if (!NS_ParseUseAsDictionary(val, matchVal, matchIdVal, matchDestItems,
6507 typeVal)) {
6508 return false;
6509 }
6510
6511 nsCString key;
6512 nsresult rv;
6513 if (NS_FAILED(rv = aEntry->GetKey(key))((bool)(__builtin_expect(!!(NS_FAILED_impl(rv = aEntry->GetKey
(key))), 0)))
) {
6514 return false;
6515 }
6516
6517 // Verify if the matchVal has regexp groups. If so, reject it
6518 UrlPatternGlue pattern;
6519 UrlPatternOptions options{};
6520 if (!urlpattern_parse_pattern_from_string(&matchVal, &mSpec, options,
6521 &pattern)) {
6522 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Failed to parse dictionary pattern %s"
, matchVal.get()); } } while (0)
6523 ("Failed to parse dictionary pattern %s", matchVal.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Failed to parse dictionary pattern %s"
, matchVal.get()); } } while (0)
;
6524 return false;
6525 }
6526
6527 auto freePattern = MakeScopeExit([&] { urlpattern_pattern_free(pattern); });
6528 if (urlpattern_get_has_regexp_groups(pattern)) {
6529 LOG_DICTIONARIES(("Pattern %s has regexp groups", matchVal.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Pattern %s has regexp groups"
, matchVal.get()); } } while (0)
;
6530 return false;
6531 }
6532
6533 nsCString hash;
6534 // Available now for use
6535 RefPtr<DictionaryCache> dicts(DictionaryCache::GetInstance());
6536 if (!dicts) {
6537 // Shutdown has occurred, cannot add dictionary
6538 return false;
6539 }
6540 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Adding DictionaryCache entry for %s: key %s, matchval %s, id=%s, "
"match-dest[0]=%s, type=%s", mSpec.get(), key.get(), matchVal
.get(), matchIdVal.get(), matchDestItems.Length() > 0 ? matchDestItems
[0].get() : "<none>", typeVal.get()); } } while (0)
6541 ("Adding DictionaryCache entry for %s: key %s, matchval %s, id=%s, "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Adding DictionaryCache entry for %s: key %s, matchval %s, id=%s, "
"match-dest[0]=%s, type=%s", mSpec.get(), key.get(), matchVal
.get(), matchIdVal.get(), matchDestItems.Length() > 0 ? matchDestItems
[0].get() : "<none>", typeVal.get()); } } while (0)
6542 "match-dest[0]=%s, type=%s",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Adding DictionaryCache entry for %s: key %s, matchval %s, id=%s, "
"match-dest[0]=%s, type=%s", mSpec.get(), key.get(), matchVal
.get(), matchIdVal.get(), matchDestItems.Length() > 0 ? matchDestItems
[0].get() : "<none>", typeVal.get()); } } while (0)
6543 mSpec.get(), key.get(), matchVal.get(), matchIdVal.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Adding DictionaryCache entry for %s: key %s, matchval %s, id=%s, "
"match-dest[0]=%s, type=%s", mSpec.get(), key.get(), matchVal
.get(), matchIdVal.get(), matchDestItems.Length() > 0 ? matchDestItems
[0].get() : "<none>", typeVal.get()); } } while (0)
6544 matchDestItems.Length() > 0 ? matchDestItems[0].get() : "<none>",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Adding DictionaryCache entry for %s: key %s, matchval %s, id=%s, "
"match-dest[0]=%s, type=%s", mSpec.get(), key.get(), matchVal
.get(), matchIdVal.get(), matchDestItems.Length() > 0 ? matchDestItems
[0].get() : "<none>", typeVal.get()); } } while (0)
6545 typeVal.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Adding DictionaryCache entry for %s: key %s, matchval %s, id=%s, "
"match-dest[0]=%s, type=%s", mSpec.get(), key.get(), matchVal
.get(), matchIdVal.get(), matchDestItems.Length() > 0 ? matchDestItems
[0].get() : "<none>", typeVal.get()); } } while (0)
;
6546
6547 uint32_t expTime = 0;
6548 (void)GetCacheTokenExpirationTime(&expTime);
6549
6550 RefPtr<LoadContextInfo> lci = GetLoadContextInfo(this);
6551 dicts->AddEntry(mURI, key, matchVal, matchDestItems, matchIdVal, Some(hash),
6552 aModified, expTime, lci, getter_AddRefs(mDictSaving));
6553 // If this was 304 Not Modified, then we don't need the dictionary data
6554 // (though we may update the dictionary entry if the match/id/etc changed).
6555 // If this is 304, mDictSaving will be cleared by AddEntry.
6556 if (mDictSaving) {
6557 if (mDictSaving->ShouldSuspendUntilCacheRead()) {
6558 LOG_DICTIONARIES(("Suspending %p to wait for cache read", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Suspending %p to wait for cache read"
, this); } } while (0)
;
6559 Suspend();
6560 mDictSaving->CallbackOnCacheRead([self = RefPtr(this)](nsresult) {
6561 LOG_DICTIONARIES(("Resuming %p after cache read", self.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Resuming %p after cache read"
, self.get()); } } while (0)
;
6562 self->Resume();
6563 });
6564 }
6565 }
6566 return true;
6567 }
6568 return true; // succeeded, no use-as-dictionary
6569}
6570
6571inline void GetAuthType(const char* challenge, nsCString& authType) {
6572 const char* p;
6573
6574 // get the challenge type
6575 if ((p = strchr(challenge, ' ')) != nullptr) {
6576 authType.Assign(challenge, p - challenge);
6577 } else {
6578 authType.Assign(challenge);
6579 }
6580}
6581
6582nsresult StoreAuthorizationMetaData(nsICacheEntry* entry,
6583 nsHttpRequestHead* requestHead) {
6584 // Not applicable to proxy authorization...
6585 nsAutoCString val;
6586 if (NS_FAILED(requestHead->GetHeader(nsHttp::Authorization, val))((bool)(__builtin_expect(!!(NS_FAILED_impl(requestHead->GetHeader
(nsHttp::Authorization, val))), 0)))
) {
6587 return NS_OK;
6588 }
6589
6590 // eg. [Basic realm="wally world"]
6591 nsAutoCString buf;
6592 GetAuthType(val.get(), buf);
6593 return entry->SetMetaDataElement("auth", buf.get());
6594}
6595
6596// Finalize the cache entry
6597// - may need to rewrite response headers if any headers changed
6598// - may need to recalculate the expiration time if any headers changed
6599// - called only for freshly written cache entries
6600nsresult nsHttpChannel::FinalizeCacheEntry() {
6601 LOG(("nsHttpChannel::FinalizeCacheEntry [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::FinalizeCacheEntry [this=%p]\n", this); } }
while (0)
;
6602
6603 // Don't update this meta-data on 304
6604 if (LoadStronglyFramed() && !CachedContentIsValid() && mCacheEntry) {
6605 LOG(("nsHttpChannel::FinalizeCacheEntry [this=%p] Is Strongly Framed\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::FinalizeCacheEntry [this=%p] Is Strongly Framed\n"
, this); } } while (0)
6606 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::FinalizeCacheEntry [this=%p] Is Strongly Framed\n"
, this); } } while (0)
;
6607 mCacheEntry->SetMetaDataElement("strongly-framed", "1");
6608 }
6609
6610 if (mResponseHead && LoadResponseHeadersModified()) {
6611 // Set the expiration time for this cache entry
6612 nsresult rv = UpdateExpirationTime();
6613 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6614 }
6615 return NS_OK;
6616}
6617
6618nsresult nsHttpChannel::InstallCacheListener(int64_t offset) {
6619 return DoInstallCacheListener(false, offset);
6620}
6621
6622// Open an output stream to the cache entry and insert a listener tee into
6623// the chain of response listeners, so the data will go the cache and the
6624// normal listener chain, which often will eventually include a
6625// decompressor. If the Content-Encoding is dcb or dcz, we'll include a
6626// decompressor *before* the tee, so the cache will see decompressed data
6627// (we can't decompress dcb/dcz when reading from the cache). Also, if an
6628// entry is being used as a dictionary (Use-As-Dictionary), we want the data
6629// to in the cache to be decompressed, so we should install a decompressor
6630// before the tee as well.
6631nsresult nsHttpChannel::DoInstallCacheListener(bool aSaveDecompressed,
6632 int64_t offset) {
6633 nsresult rv;
6634
6635 LOG(("Preparing to write data into the cache [uri=%s]\n", mSpec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Preparing to write data into the cache [uri=%s]\n", mSpec.
get()); } } while (0)
;
6636
6637 MOZ_ASSERT(mCacheEntry)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCacheEntry)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCacheEntry))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mCacheEntry", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 6637); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6638 MOZ_ASSERT(LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 6638
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial()"
")"); do { MOZ_CrashSequence(__null, 6638); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6639 MOZ_ASSERT(mListener)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mListener)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mListener))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mListener", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mListener" ")"
); do { MOZ_CrashSequence(__null, 6639); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6640
6641 LOG(("Trading cache input stream for output stream [channel=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Trading cache input stream for output stream [channel=%p]"
, this); } } while (0)
;
6642
6643 // We must close the input stream first because cache entries do not
6644 // correctly handle having an output stream and input streams open at
6645 // the same time.
6646 mCacheInputStream.CloseAndRelease();
6647
6648 int64_t predictedSize = mResponseHead->TotalEntitySize();
6649 if (predictedSize != -1) {
6650 predictedSize -= offset;
6651 }
6652
6653 nsCOMPtr<nsIOutputStream> out;
6654 rv =
6655 mCacheEntry->OpenOutputStream(offset, predictedSize, getter_AddRefs(out));
6656 if (rv == NS_ERROR_NOT_AVAILABLE) {
6657 LOG((" entry doomed, not writing it [channel=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " entry doomed, not writing it [channel=%p]", this); } } while
(0)
;
6658 // Entry is already doomed.
6659 // This may happen when expiration time is set to past and the entry
6660 // has been removed by the background eviction logic.
6661 return NS_OK;
6662 }
6663 if (rv == NS_ERROR_FILE_TOO_BIG) {
6664 LOG((" entry would exceed max allowed size, not writing it [channel=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " entry would exceed max allowed size, not writing it [channel=%p]"
, this); } } while (0)
6665 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " entry would exceed max allowed size, not writing it [channel=%p]"
, this); } } while (0)
;
6666 mCacheEntry->AsyncDoom(nullptr);
6667 return NS_OK;
6668 }
6669 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6670
6671 if (LoadCacheOnlyMetadata()) {
6672 LOG(("Not storing content, cacheOnlyMetadata set"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Not storing content, cacheOnlyMetadata set"); } } while (0
)
;
6673 // We must open and then close the output stream of the cache entry.
6674 // This way we indicate the content has been written (despite with zero
6675 // length) and the entry is now in the ready state with "having data".
6676
6677 out->Close();
6678 return NS_OK;
6679 }
6680
6681 // XXX disk cache does not support overlapped i/o yet
6682#if 0
6683 // Mark entry valid inorder to allow simultaneous reading...
6684 rv = mCacheEntry->MarkValid();
6685 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6686#endif
6687
6688 nsCOMPtr<nsIStreamListenerTee> tee =
6689 do_CreateInstance(kStreamListenerTeeCID, &rv);
6690 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6691
6692 rv = tee->Init(mListener, out, nullptr);
6693 LOG(("nsHttpChannel::InstallCacheListener sync tee %p rv=%" PRIx32, tee.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::InstallCacheListener sync tee %p rv=%" "x",
tee.get(), static_cast<uint32_t>(rv)); } } while (0)
6694 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::InstallCacheListener sync tee %p rv=%" "x",
tee.get(), static_cast<uint32_t>(rv)); } } while (0)
;
6695 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6696 mListener = tee;
6697
6698 mWritingToCache = true;
6699 // If this is Use-As-Dictionary we need to be able to read it quickly for
6700 // dictionary use, OR if it's encoded in dcb or dcz (using a dictionary),
6701 // we must decompress it before storing since we won't have the dictionary
6702 // when we go to read it out later.
6703 // In this case, we hook an nsHTTPCompressConv instance in before the tee
6704 // since we don't want to have to decompress it here and again in the content
6705 // process (if it's not dcb/dcz); if it is dcb/dcz we must decompress it
6706 // before the content process gets to see it
6707 // XXX We could recompress this with e.g. gzip to save space and improve
6708 // hitrate, at the cost of some CPU.
6709
6710 // Note: this doesn't handle cases like "dcb, gzip" or (worse?) "gzip, dcb".
6711 // We could in theory handle them.
6712 if (aSaveDecompressed) {
6713 nsCOMPtr<nsIStreamListener> listener;
6714 // otherwise we won't convert in the parent process
6715 SetApplyConversion(true);
6716 rv = DoApplyContentConversionsInternal(mListener, getter_AddRefs(listener),
6717 true, nullptr);
6718 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6719 return rv;
6720 }
6721 // Remove Available-Dictionary from Vary header if present. This
6722 // avoids us refusing to match on a future load, for example if this
6723 // dictionary was decoded from an earlier version using a dictionary
6724 // (i.e. the update jquery to new version using the old version as a
6725 // dictionary; no future load will use that old version).
6726
6727 // XXX It would be slightly more efficient to remove all at once
6728 // instead of sequentially by passing an array of strings
6729 RemoveFromVary(mResponseHead.get(), "available-dictionary"_ns);
6730 RemoveFromVary(mResponseHead.get(), "accept-encoding"_ns);
6731
6732 if (listener) {
6733 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Installed nsHTTPCompressConv %p before tee"
, listener.get()); } } while (0)
6734 ("Installed nsHTTPCompressConv %p before tee", listener.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Installed nsHTTPCompressConv %p before tee"
, listener.get()); } } while (0)
;
6735 mListener = listener;
6736 mCompressListener = std::move(listener);
6737 StoreHasAppliedConversion(true);
6738
6739 } else {
6740 nsAutoCString contentEncoding;
6741 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
6742 if (contentEncoding.IsEmpty()) {
6743 // No Content-Encoding — data is already raw. Normal for dictionary
6744 // responses served without transfer encoding.
6745 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "No decompressor needed before tee (no Content-Encoding)"
); } } while (0)
6746 ("No decompressor needed before tee (no Content-Encoding)"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "No decompressor needed before tee (no Content-Encoding)"
); } } while (0)
;
6747 } else if (mIsDictionaryCompressed) {
6748 // dcb/dcz can only be decompressed in the parent process with
6749 // the dictionary. If we can't install the decompressor, this is
6750 // fatal — the content process can't decode it.
6751 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Cannot decompress dcb/dcz content. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]"
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6752 ("FATAL: Cannot decompress dcb/dcz content. "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Cannot decompress dcb/dcz content. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]"
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6753 "Content-Encoding='%s' ApplyConversion=%d HasApplied=%d "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Cannot decompress dcb/dcz content. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]"
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6754 "[this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Cannot decompress dcb/dcz content. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]"
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6755 contentEncoding.get(), LoadApplyConversion(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Cannot decompress dcb/dcz content. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]"
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6756 LoadHasAppliedConversion(), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "FATAL: Cannot decompress dcb/dcz content. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]"
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
;
6757 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
6758 return NS_ERROR_INVALID_CONTENT_ENCODING;
6759 } else if (mDictSaving) {
6760 // Saving a dictionary but can't install a decompressor — we'd store
6761 // compressed data with a hash computed over compressed bytes. Cancel
6762 // the dictionary save but leave Content-Encoding for downstream
6763 // decompression.
6764 LOG_DICTIONARIES(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Cannot save dictionary without decompressor. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]. Canceling dictionary save."
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6765 ("Cannot save dictionary without decompressor. "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Cannot save dictionary without decompressor. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]. Canceling dictionary save."
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6766 "Content-Encoding='%s' ApplyConversion=%d HasApplied=%d "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Cannot save dictionary without decompressor. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]. Canceling dictionary save."
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6767 "[this=%p]. Canceling dictionary save.",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Cannot save dictionary without decompressor. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]. Canceling dictionary save."
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6768 contentEncoding.get(), LoadApplyConversion(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Cannot save dictionary without decompressor. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]. Canceling dictionary save."
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
6769 LoadHasAppliedConversion(), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gDictionaryLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Debug)), 0))) { mozilla::
detail::log_print(moz_real_module, mozilla::LogLevel::Debug, "Cannot save dictionary without decompressor. "
"Content-Encoding='%s' ApplyConversion=%d HasApplied=%d " "[this=%p]. Canceling dictionary save."
, contentEncoding.get(), LoadApplyConversion(), LoadHasAppliedConversion
(), this); } } while (0)
;
6770 MOZ_DIAGNOSTIC_ASSERT(false, "Can't save dictionary uncompressed")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Can't save dictionary uncompressed"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6770); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Can't save dictionary uncompressed" ")"); do { MOZ_CrashSequence
(__null, 6770); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6771 mCacheEntry->SetDictionary(nullptr);
6772 DictionaryCache::RemoveDictionary(nsCString(mDictSaving->GetURI()),
6773 mDictSaving->GetLoadContextInfo());
6774 mDictSaving = nullptr;
6775 }
6776 }
6777 // We may have modified Content-Encoding; make sure cache metadata
6778 // reflects that. Pass nullptr so we pick up the Vary updates above
6779 rv = UpdateCacheEntryHeaders(mCacheEntry, nullptr);
6780 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6781 mCacheEntry->AsyncDoom(nullptr);
6782 return rv;
6783 }
6784 }
6785
6786#ifdef DEBUG1
6787 // Verify that Content-Encoding was properly cleared
6788 nsAutoCString verifyEncoding;
6789 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, verifyEncoding);
6790 MOZ_ASSERT(!verifyEncoding.Equals("dcb") && !verifyEncoding.Equals("dcz"),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!verifyEncoding.Equals("dcb") && !verifyEncoding
.Equals("dcz"))>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(!verifyEncoding.Equals("dcb") &&
!verifyEncoding.Equals("dcz")))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
" (" "Content-Encoding should have been cleared for dcb/dcz"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
") (" "Content-Encoding should have been cleared for dcb/dcz"
")"); do { MOZ_CrashSequence(__null, 6791); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6791 "Content-Encoding should have been cleared for dcb/dcz")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!verifyEncoding.Equals("dcb") && !verifyEncoding
.Equals("dcz"))>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(!verifyEncoding.Equals("dcb") &&
!verifyEncoding.Equals("dcz")))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
" (" "Content-Encoding should have been cleared for dcb/dcz"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
") (" "Content-Encoding should have been cleared for dcb/dcz"
")"); do { MOZ_CrashSequence(__null, 6791); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6792 if (aSaveDecompressed) {
6793 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(verifyEncoding.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(verifyEncoding.IsEmpty()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("verifyEncoding.IsEmpty()"
" (" "Content-Encoding should have been cleared for dictionary resources"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6795); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6794 verifyEncoding.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(verifyEncoding.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(verifyEncoding.IsEmpty()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("verifyEncoding.IsEmpty()"
" (" "Content-Encoding should have been cleared for dictionary resources"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6795); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6795 "Content-Encoding should have been cleared for dictionary resources")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(verifyEncoding.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(verifyEncoding.IsEmpty()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("verifyEncoding.IsEmpty()"
" (" "Content-Encoding should have been cleared for dictionary resources"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6795); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6796 }
6797#endif
6798 return NS_OK;
6799}
6800
6801//-----------------------------------------------------------------------------
6802// nsHttpChannel <redirect>
6803//-----------------------------------------------------------------------------
6804
6805nsresult nsHttpChannel::SetupReplacementChannel(nsIURI* newURI,
6806 nsIChannel* newChannel,
6807 bool preserveMethod,
6808 uint32_t redirectFlags) {
6809 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupReplacementChannel " "[this=%p newChannel=%p preserveMethod=%d]"
, this, newChannel, preserveMethod); } } while (0)
6810 ("nsHttpChannel::SetupReplacementChannel "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupReplacementChannel " "[this=%p newChannel=%p preserveMethod=%d]"
, this, newChannel, preserveMethod); } } while (0)
6811 "[this=%p newChannel=%p preserveMethod=%d]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupReplacementChannel " "[this=%p newChannel=%p preserveMethod=%d]"
, this, newChannel, preserveMethod); } } while (0)
6812 this, newChannel, preserveMethod))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetupReplacementChannel " "[this=%p newChannel=%p preserveMethod=%d]"
, this, newChannel, preserveMethod); } } while (0)
;
6813
6814 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
6815 mEndMarkerAdded = true;
6816
6817 nsAutoCString requestMethod;
6818 GetRequestMethod(requestMethod);
6819
6820 int32_t priority = PRIORITY_NORMAL;
6821 GetPriority(&priority);
6822
6823 TimingStruct timings;
6824 if (mTransaction) {
6825 timings = mTransaction->Timings();
6826 }
6827
6828 uint64_t size = 0;
6829 GetEncodedBodySize(&size);
6830
6831 nsAutoCString contentType;
6832 mozilla::Maybe<mozilla::net::HttpVersion> httpVersion = Nothing();
6833 mozilla::Maybe<uint32_t> responseStatus = Nothing();
6834 if (mResponseHead) {
6835 mResponseHead->ContentType(contentType);
6836 httpVersion = Some(mResponseHead->Version());
6837 responseStatus = Some(mResponseHead->Status());
6838 }
6839
6840 RefPtr<nsIIdentChannel> newIdentChannel = do_QueryObject(newChannel);
6841 uint64_t channelId = 0;
6842 if (newIdentChannel) {
6843 channelId = newIdentChannel->ChannelId();
6844 }
6845 profiler_add_network_marker(
6846 mURI, requestMethod, priority, mChannelId,
6847 NetworkLoadType::LOAD_REDIRECT, mLastStatusReported, TimeStamp::Now(),
6848 size, mCacheDisposition, mLoadInfo->GetInnerWindowID(),
6849 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
6850 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
6851 &timings, std::move(mSource), httpVersion, responseStatus,
6852 Some(nsDependentCString(contentType.get())), newURI, redirectFlags,
6853 channelId);
6854 }
6855
6856 nsresult rv = HttpBaseChannel::SetupReplacementChannel(
6857 newURI, newChannel, preserveMethod, redirectFlags);
6858 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6859
6860 nsAutoCString uriHost;
6861 mURI->GetAsciiHost(uriHost);
6862 // disable https-rr when encountering a downgrade from https to http.
6863 // If the host would have https-rr dns-entries, it would be misconfigured
6864 // due to giving us mixed signals:
6865 // 1. the signal to upgrade all http requests to https,
6866 // 2. but also downgrading to http on https via redirects.
6867 // Add to exclude list for that reason
6868 if (!gHttpHandler->IsHostExcludedForHTTPSRR(uriHost) &&
6869 nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
6870 mURI, newURI, mLoadInfo,
6871 {nsHTTPSOnlyUtils::UpgradeDowngradeEndlessLoopOptions::
6872 EnforceForHTTPSRR})) {
6873 // Add the host to a excluded list because:
6874 // 1. We don't need to do the same check again.
6875 // 2. Other subresources in the same host will be also excluded.
6876 gHttpHandler->ExcludeHTTPSRRHost(uriHost);
6877 LOG(("[%p] skip HTTPS upgrade for host [%s]", this, uriHost.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "[%p] skip HTTPS upgrade for host [%s]", this, uriHost.get(
)); } } while (0)
;
6878 }
6879
6880 rv = CheckRedirectLimit(newURI, redirectFlags);
6881 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6881); return rv; } } while (false)
;
6882
6883 // pass on the early hint observer to be able to process `103 Early Hints`
6884 // responses after cross origin redirects
6885 if (mEarlyHintObserver) {
6886 if (RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel)) {
6887 httpChannelImpl->SetEarlyHintObserver(mEarlyHintObserver);
6888 }
6889 mEarlyHintObserver = nullptr;
6890 }
6891
6892 // We don't support redirection for WebTransport for now.
6893 mWebTransportSessionEventListener = nullptr;
6894
6895 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
6896 if (!httpChannel) return NS_OK; // no other options to set
6897
6898 // convey the ApplyConversion flag (bug 91862)
6899 nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel);
6900 if (encodedChannel) encodedChannel->SetApplyConversion(LoadApplyConversion());
6901
6902 // transfer the resume information
6903 if (LoadResuming()) {
6904 nsCOMPtr<nsIResumableChannel> resumableChannel(
6905 do_QueryInterface(newChannel));
6906 if (!resumableChannel) {
6907 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Got asked to resume, but redirected to non-resumable channel!"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6908)
6908 "Got asked to resume, but redirected to non-resumable channel!")NS_DebugBreak(NS_DEBUG_WARNING, "Got asked to resume, but redirected to non-resumable channel!"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6908)
;
6909 return NS_ERROR_NOT_RESUMABLE;
6910 }
6911 resumableChannel->ResumeAt(mStartPos, mEntityID);
6912 }
6913
6914 nsCOMPtr<nsIHttpChannelInternal> internalChannel =
6915 do_QueryInterface(newChannel, &rv);
6916 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6917 TimeStamp timestamp;
6918 rv = GetNavigationStartTimeStamp(&timestamp);
6919 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6919)
) {
6920 return rv;
6921 }
6922 if (timestamp) {
6923 (void)internalChannel->SetNavigationStartTimeStamp(timestamp);
6924 }
6925 }
6926
6927 return NS_OK;
6928}
6929
6930nsresult nsHttpChannel::AsyncProcessRedirection(uint32_t redirectType) {
6931 LOG(("nsHttpChannel::AsyncProcessRedirection [this=%p type=%u]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::AsyncProcessRedirection [this=%p type=%u]\n"
, this, redirectType); } } while (0)
6932 redirectType))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::AsyncProcessRedirection [this=%p type=%u]\n"
, this, redirectType); } } while (0)
;
6933
6934 nsresult rv = ProcessCrossOriginSecurityHeaders();
6935 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6936 mStatus = rv;
6937 HandleAsyncAbort();
6938 return rv;
6939 }
6940
6941 nsAutoCString location;
6942
6943 // if a location header was not given, then we can't perform the redirect,
6944 // so just carry on as though this were a normal response.
6945 if (NS_FAILED(mResponseHead->GetHeader(nsHttp::Location, location))((bool)(__builtin_expect(!!(NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Location, location))), 0)))
) {
6946 return NS_ERROR_FAILURE;
6947 }
6948
6949 // If we were told to not follow redirects automatically, then again
6950 // carry on as though this were a normal response.
6951 if (mLoadInfo->GetDontFollowRedirects()) {
6952 return NS_ERROR_FAILURE;
6953 }
6954
6955 // make sure non-ASCII characters in the location header are escaped.
6956 nsAutoCString locationBuf;
6957 if (NS_EscapeURL(location.get(), -1, esc_OnlyNonASCII | esc_Spaces,
6958 locationBuf)) {
6959 location = std::move(locationBuf);
6960 }
6961
6962 mRedirectType = redirectType;
6963
6964 LOG(("redirecting to: %s [redirection-limit=%u]\n", location.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "redirecting to: %s [redirection-limit=%u]\n", location.get
(), uint32_t(mRedirectionLimit)); } } while (0)
6965 uint32_t(mRedirectionLimit)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "redirecting to: %s [redirection-limit=%u]\n", location.get
(), uint32_t(mRedirectionLimit)); } } while (0)
;
6966
6967 rv = CreateNewURI(location.get(), getter_AddRefs(mRedirectURI));
6968
6969 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6970 LOG(("Invalid URI for redirect: Location: %s\n", location.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Invalid URI for redirect: Location: %s\n", location.get())
; } } while (0)
;
6971 return NS_ERROR_CORRUPTED_CONTENT;
6972 }
6973
6974 if (!StaticPrefs::network_allow_redirect_to_data() &&
6975 !mLoadInfo->GetAllowInsecureRedirectToDataURI() &&
6976 mRedirectURI->SchemeIs("data")) {
6977 LOG(("Invalid data URI for redirect!"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Invalid data URI for redirect!"); } } while (0)
;
6978 nsContentSecurityManager::ReportBlockedDataURI(mRedirectURI, mLoadInfo,
6979 true);
6980 return NS_ERROR_DOM_BAD_URI;
6981 }
6982
6983 // Perform the URL query string stripping for redirects. We will only strip
6984 // the query string if it is redirecting to a third-party URI in the top
6985 // level.
6986 if (StaticPrefs::privacy_query_stripping_redirect()) {
6987 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
6988 bool isThirdPartyRedirectURI = true;
6989 thirdPartyUtil->IsThirdPartyURI(mURI, mRedirectURI,
6990 &isThirdPartyRedirectURI);
6991 if (isThirdPartyRedirectURI && mLoadInfo->GetExternalContentPolicyType() ==
6992 ExtContentPolicy::TYPE_DOCUMENT) {
6993 glean::contentblocking::query_stripping_count
6994 .EnumGet(glean::contentblocking::QueryStrippingCountLabel::eRedirect)
6995 .Add();
6996
6997 nsCOMPtr<nsIPrincipal> prin;
6998 ContentBlockingAllowList::RecomputePrincipal(
6999 mRedirectURI, mLoadInfo->GetOriginAttributes(), getter_AddRefs(prin));
7000
7001 bool isRedirectURIInAllowList = false;
7002 if (prin) {
7003 ContentBlockingAllowList::Check(prin, mPrivateBrowsing,
7004 isRedirectURIInAllowList);
7005 }
7006
7007 if (!isRedirectURIInAllowList) {
7008 nsCOMPtr<nsIURI> strippedURI;
7009
7010 nsCOMPtr<nsIURLQueryStringStripper> queryStripper;
7011 queryStripper =
7012 mozilla::components::URLQueryStringStripper::Service(&rv);
7013 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7013); return rv; } } while (false)
;
7014
7015 uint32_t numStripped;
7016
7017 rv = queryStripper->Strip(mRedirectURI, mPrivateBrowsing,
7018 getter_AddRefs(strippedURI), &numStripped);
7019 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7019); return rv; } } while (false)
;
7020
7021 if (numStripped) {
7022 mUnstrippedRedirectURI = mRedirectURI;
7023 mRedirectURI = strippedURI;
7024
7025 // Record telemetry, but only if we stripped any query params.
7026 glean::contentblocking::query_stripping_count
7027 .EnumGet(glean::contentblocking::QueryStrippingCountLabel::
7028 eStripforredirect)
7029 .Add();
7030 glean::contentblocking::query_stripping_param_count
7031 .AccumulateSingleSample(numStripped);
7032 }
7033 }
7034 }
7035 }
7036
7037 // if we have a Set-Login header, we should try to handle it here
7038 nsAutoCString setLogin;
7039 if (NS_SUCCEEDED(mResponseHead->GetHeader(nsHttp::Set_Login, setLogin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Set_Login, setLogin))), 1)))
) {
7040 bool isDocument = mLoadInfo->GetExternalContentPolicyType() ==
7041 ExtContentPolicy::TYPE_DOCUMENT;
7042 if (isDocument) {
7043 auto ssm = nsContentUtils::GetSecurityManager();
7044 if (ssm) {
7045 nsCOMPtr<nsIPrincipal> documentPrincipal;
7046 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
7047 this, getter_AddRefs(documentPrincipal));
7048 dom::NavigatorLogin::SetLoginStatus(documentPrincipal, setLogin);
7049 }
7050 } else {
7051 bool inThirdPartyContext = mLoadInfo->GetIsInThirdPartyContext();
7052 nsIPrincipal* loadingPrincipal = mLoadInfo->GetLoadingPrincipal();
7053 if (loadingPrincipal) {
7054 bool isSameOriginToLoadingPrincipal =
7055 loadingPrincipal->IsSameOrigin(mURI);
7056 if (!inThirdPartyContext && isSameOriginToLoadingPrincipal) {
7057 dom::NavigatorLogin::SetLoginStatus(loadingPrincipal, setLogin);
7058 }
7059 }
7060 }
7061 }
7062
7063 if (NS_WARN_IF(!mRedirectURI)NS_warn_if_impl(!mRedirectURI, "!mRedirectURI", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7063)
) {
7064 LOG(("Invalid redirect URI after performaing query string stripping"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Invalid redirect URI after performaing query string stripping"
); } } while (0)
;
7065 return NS_ERROR_FAILURE;
7066 }
7067
7068 return ContinueProcessRedirectionAfterFallback(NS_OK);
7069}
7070
7071nsresult nsHttpChannel::ContinueProcessRedirectionAfterFallback(nsresult rv) {
7072 // Kill the current cache entry if we are redirecting
7073 // back to ourself.
7074 bool redirectingBackToSameURI = false;
7075 if (mCacheEntry && LoadCacheEntryIsWriteOnly() &&
7076 NS_SUCCEEDED(mURI->Equals(mRedirectURI, &redirectingBackToSameURI))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mURI->Equals(mRedirectURI
, &redirectingBackToSameURI))), 1)))
&&
7077 redirectingBackToSameURI) {
7078 mCacheEntry->AsyncDoom(nullptr);
7079 }
7080
7081 // move the reference of the old location to the new one if the new
7082 // one has none.
7083 PropagateReferenceIfNeeded(mURI, mRedirectURI);
7084
7085 bool rewriteToGET =
7086 ShouldRewriteRedirectToGET(mRedirectType, mRequestHead.ParsedMethod());
7087
7088 // prompt if the method is not safe (such as POST, PUT, DELETE, ...)
7089 if (!rewriteToGET && !mRequestHead.IsSafeMethod()) {
7090 rv = PromptTempRedirect();
7091 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7092 }
7093
7094 uint32_t redirectFlags;
7095 if (nsHttp::IsPermanentRedirect(mRedirectType)) {
7096 redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
7097 } else {
7098 redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
7099 }
7100
7101 nsCOMPtr<nsIIOService> ioService;
7102 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
7103 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7104
7105 nsCOMPtr<nsIChannel> newChannel;
7106 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
7107 CloneLoadInfoForRedirect(mRedirectURI, redirectFlags);
7108
7109 // Propagate the unstripped redirect URI.
7110 redirectLoadInfo->SetUnstrippedURI(mUnstrippedRedirectURI);
7111
7112 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), mRedirectURI,
7113 redirectLoadInfo,
7114 nullptr, // PerformanceStorage
7115 nullptr, // aLoadGroup
7116 nullptr, // aCallbacks
7117 nsIRequest::LOAD_NORMAL, ioService);
7118 // If this fails, it usually means that the URI was invalid. Treat this as if
7119 // it were a CreateNewURI failure.
7120 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7120)
) {
7121 return NS_ERROR_CORRUPTED_CONTENT;
7122 }
7123
7124 rv = SetupReplacementChannel(mRedirectURI, newChannel, !rewriteToGET,
7125 redirectFlags);
7126 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7127
7128 // verify that this is a legal redirect
7129 mRedirectChannel = newChannel;
7130
7131 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
7132 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, redirectFlags);
7133
7134 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
7135
7136 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7137 AutoRedirectVetoNotifier notifier(this, rv);
7138 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
7139 }
7140
7141 return rv;
7142}
7143
7144nsresult nsHttpChannel::ContinueProcessRedirection(nsresult rv) {
7145 AutoRedirectVetoNotifier notifier(this, rv);
7146
7147 LOG(("nsHttpChannel::ContinueProcessRedirection [rv=%" PRIx32 ",this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessRedirection [rv=%" "x" ",this=%p]\n"
, static_cast<uint32_t>(rv), this); } } while (0)
7148 static_cast<uint32_t>(rv), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueProcessRedirection [rv=%" "x" ",this=%p]\n"
, static_cast<uint32_t>(rv), this); } } while (0)
;
7149 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7150
7151 MOZ_ASSERT(mRedirectChannel, "No redirect channel?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRedirectChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRedirectChannel))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mRedirectChannel"
" (" "No redirect channel?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7151); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRedirectChannel"
") (" "No redirect channel?" ")"); do { MOZ_CrashSequence(__null
, 7151); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
7152
7153 // Make sure to do this after we received redirect veto answer,
7154 // i.e. after all sinks had been notified
7155 mRedirectChannel->SetOriginalURI(mOriginalURI);
7156
7157 // XXX we used to talk directly with the script security manager, but that
7158 // should really be handled by the event sink implementation.
7159
7160 // begin loading the new channel
7161 rv = mRedirectChannel->AsyncOpen(mListener);
7162 LOG((" new channel AsyncOpen returned %" PRIX32, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " new channel AsyncOpen returned %" "X", static_cast<uint32_t
>(rv)); } } while (0)
;
7163 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7163); return rv; } } while (false)
;
7164
7165 // close down this channel
7166 Cancel(NS_BINDING_REDIRECTED);
7167
7168 notifier.RedirectSucceeded();
7169
7170 ReleaseListeners();
7171
7172 return NS_OK;
7173}
7174
7175//-----------------------------------------------------------------------------
7176// nsHttpChannel <auth>
7177//-----------------------------------------------------------------------------
7178
7179NS_IMETHODIMPnsresult nsHttpChannel::OnAuthAvailable() {
7180 LOG(("nsHttpChannel::OnAuthAvailable [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnAuthAvailable [this=%p]", this); } } while
(0)
;
7181
7182 // setting mAuthRetryPending flag and resuming the transaction
7183 // triggers process of throwing away the unauthenticated data already
7184 // coming from the network
7185 mIsAuthChannel = true;
7186 mAuthRetryPending = true;
7187 StoreProxyAuthPending(false);
7188 LOG(("Resuming the transaction, we got credentials from user"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Resuming the transaction, we got credentials from user"); }
} while (0)
;
7189 if (mTransactionPump) {
7190 Resume();
7191 }
7192
7193 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
7194 return CallOrWaitForResume(
7195 [](auto* self) { return self->RedirectToNewChannelForAuthRetry(); });
7196 }
7197
7198 return NS_OK;
7199}
7200
7201NS_IMETHODIMPnsresult nsHttpChannel::OnAuthCancelled(bool userCancel) {
7202 LOG(("nsHttpChannel::OnAuthCancelled [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnAuthCancelled [this=%p]", this); } } while
(0)
;
7203 MOZ_ASSERT(mAuthRetryPending, "OnAuthCancelled should not be called twice")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAuthRetryPending)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAuthRetryPending))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mAuthRetryPending"
" (" "OnAuthCancelled should not be called twice" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7203); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthRetryPending"
") (" "OnAuthCancelled should not be called twice" ")"); do {
MOZ_CrashSequence(__null, 7203); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7204
7205 if (mTransactionPump) {
7206 // If the channel is trying to authenticate to a proxy and
7207 // that was canceled we cannot show the http response body
7208 // from the 40x as that might mislead the user into thinking
7209 // it was a end host response instead of a proxy reponse.
7210 // This must check explicitly whether a proxy auth was being done
7211 // because we do want to show the content if this is an error from
7212 // the origin server.
7213 if (LoadProxyAuthPending()) Cancel(NS_ERROR_PROXY_CONNECTION_REFUSED);
7214
7215 // Make sure to process security headers before calling CallOnStartRequest.
7216 nsresult rv = ProcessCrossOriginSecurityHeaders();
7217 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7218 mStatus = rv;
7219 HandleAsyncAbort();
7220 return rv;
7221 }
7222
7223 // ensure call of OnStartRequest of the current listener here,
7224 // it would not be called otherwise at all
7225 rv = CallOnStartRequest();
7226
7227 // drop mAuthRetryPending flag and resume the transaction
7228 // this resumes load of the unauthenticated content data (which
7229 // may have been canceled if we don't want to show it)
7230 mAuthRetryPending = false;
7231 LOG(("Resuming the transaction, user cancelled the auth dialog"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Resuming the transaction, user cancelled the auth dialog")
; } } while (0)
;
7232 Resume();
7233
7234 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) mTransactionPump->Cancel(rv);
7235 }
7236
7237 StoreProxyAuthPending(false);
7238 return NS_OK;
7239}
7240
7241NS_IMETHODIMPnsresult nsHttpChannel::CloseStickyConnection() {
7242 LOG(("nsHttpChannel::CloseStickyConnection this=%p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CloseStickyConnection this=%p", this); } } while
(0)
;
7243
7244 // Require we are between OnStartRequest and OnStopRequest, because
7245 // what we do here takes effect in OnStopRequest (not reusing the
7246 // connection for next authentication round).
7247 if (!LoadIsPending()) {
7248 LOG((" channel not pending"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " channel not pending"); } } while (0)
;
7249 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7251); MOZ_PretendNoReturn(); } while (0)
7250 "CloseStickyConnection not called before OnStopRequest, won't have any "do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7251); MOZ_PretendNoReturn(); } while (0)
7251 "effect")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7251); MOZ_PretendNoReturn(); } while (0)
;
7252 return NS_ERROR_UNEXPECTED;
7253 }
7254
7255 MOZ_ASSERT(mTransaction)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mTransaction)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mTransaction))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mTransaction", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { MOZ_CrashSequence(__null, 7255); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7256 if (!mTransaction) {
7257 return NS_ERROR_UNEXPECTED;
7258 }
7259
7260 if (!(mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
7261 mTransaction->HasStickyConnection())) {
7262 LOG((" not sticky"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " not sticky"); } } while (0)
;
7263 return NS_OK;
7264 }
7265
7266 mTransaction->DontReuseConnection();
7267 return NS_OK;
7268}
7269
7270NS_IMETHODIMPnsresult nsHttpChannel::ConnectionRestartable(bool aRestartable) {
7271 LOG(("nsHttpChannel::ConnectionRestartable this=%p, restartable=%d", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ConnectionRestartable this=%p, restartable=%d"
, this, aRestartable); } } while (0)
7272 aRestartable))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ConnectionRestartable this=%p, restartable=%d"
, this, aRestartable); } } while (0)
;
7273 StoreAuthConnectionRestartable(aRestartable);
7274 return NS_OK;
7275}
7276
7277//-----------------------------------------------------------------------------
7278// nsHttpChannel::nsISupports
7279//-----------------------------------------------------------------------------
7280
7281NS_IMPL_ADDREF_INHERITED(nsHttpChannel, HttpBaseChannel)MozExternalRefCountType nsHttpChannel::AddRef(void) { static_assert
(!std::is_destructible_v<nsHttpChannel>, "Reference-counted class "
"nsHttpChannel" " should not have a public destructor. " "Make this class's destructor non-public"
); nsrefcnt r = HttpBaseChannel::AddRef(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<nsHttpChannel>) { NS_LogAddRef
((this), (r), ("nsHttpChannel"), (uint32_t)(sizeof(*this))); }
return r; }
7282bool nsHttpChannel::DispatchRelease() {
7283 if (NS_IsMainThread()) {
7284 return false;
7285 }
7286
7287 NS_DispatchToMainThread(
7288 NewNonOwningRunnableMethod("net::nsHttpChannel::Release", this,
7289 &nsHttpChannel::Release),
7290 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
7291
7292 return true;
7293}
7294
7295NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
7296nsHttpChannel::Release() {
7297 nsrefcnt count = mRefCnt - 1;
7298 if (DispatchRelease()) {
7299 // Redispatched to the main thread.
7300 return count;
7301 }
7302
7303 NS_IMPL_RELEASE_INHERITED_GUTS(nsHttpChannel, HttpBaseChannel)nsrefcnt r = HttpBaseChannel::Release(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<nsHttpChannel>) { NS_LogRelease
((this), (r), ("nsHttpChannel")); } return r
;
7304}
7305
7306NS_INTERFACE_MAP_BEGIN(nsHttpChannel)nsresult nsHttpChannel::QueryInterface(const nsIID& aIID,
void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7306); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
7307 NS_INTERFACE_MAP_ENTRY(nsIRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequest>)) foundInterface = static_cast
<nsIRequest*>(this); else
7308 NS_INTERFACE_MAP_ENTRY(nsIChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIChannel>)) foundInterface = static_cast
<nsIChannel*>(this); else
7309 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestObserver>)) foundInterface
= static_cast<nsIRequestObserver*>(this); else
7310 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIStreamListener>)) foundInterface
= static_cast<nsIStreamListener*>(this); else
7311 NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannel>)) foundInterface =
static_cast<nsIHttpChannel*>(this); else
7312 NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheInfoChannel>)) foundInterface
= static_cast<nsICacheInfoChannel*>(this); else
7313 NS_INTERFACE_MAP_ENTRY(nsICachingChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICachingChannel>)) foundInterface
= static_cast<nsICachingChannel*>(this); else
7314 NS_INTERFACE_MAP_ENTRY(nsIClassOfService)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIClassOfService>)) foundInterface
= static_cast<nsIClassOfService*>(this); else
7315 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel>)) foundInterface
= static_cast<nsIUploadChannel*>(this); else
7316 NS_INTERFACE_MAP_ENTRY(nsIFormPOSTActionChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIFormPOSTActionChannel>)) foundInterface
= static_cast<nsIFormPOSTActionChannel*>(this); else
7317 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel2>)) foundInterface
= static_cast<nsIUploadChannel2*>(this); else
7318 NS_INTERFACE_MAP_ENTRY(nsICacheEntryOpenCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheEntryOpenCallback>)) foundInterface
= static_cast<nsICacheEntryOpenCallback*>(this); else
7319 NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannelInternal>)) foundInterface
= static_cast<nsIHttpChannelInternal*>(this); else
7320 NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIResumableChannel>)) foundInterface
= static_cast<nsIResumableChannel*>(this); else
7321 NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsITransportEventSink>)) foundInterface
= static_cast<nsITransportEventSink*>(this); else
7322 NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsPriority>)) foundInterface
= static_cast<nsISupportsPriority*>(this); else
7323 NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProtocolProxyCallback>)) foundInterface
= static_cast<nsIProtocolProxyCallback*>(this); else
7324 NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProxiedChannel>)) foundInterface
= static_cast<nsIProxiedChannel*>(this); else
7325 NS_INTERFACE_MAP_ENTRY(nsIHttpAuthenticableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpAuthenticableChannel>)) foundInterface
= static_cast<nsIHttpAuthenticableChannel*>(this); else
7326 NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAsyncVerifyRedirectCallback>))
foundInterface = static_cast<nsIAsyncVerifyRedirectCallback
*>(this); else
7327 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableRequest>)) foundInterface
= static_cast<nsIThreadRetargetableRequest*>(this); else
7328 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableStreamListener>
)) foundInterface = static_cast<nsIThreadRetargetableStreamListener
*>(this); else
7329 NS_INTERFACE_MAP_ENTRY(nsIDNSListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDNSListener>)) foundInterface =
static_cast<nsIDNSListener*>(this); else
7330 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
7331 NS_INTERFACE_MAP_ENTRY(nsICorsPreflightCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICorsPreflightCallback>)) foundInterface
= static_cast<nsICorsPreflightCallback*>(this); else
7332 NS_INTERFACE_MAP_ENTRY(nsIRequestTailUnblockCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestTailUnblockCallback>)) foundInterface
= static_cast<nsIRequestTailUnblockCallback*>(this); else
7333 NS_INTERFACE_MAP_ENTRY_CONCRETE(nsHttpChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsHttpChannel>)) { *aInstancePtr =
do_AddRef(static_cast<nsHttpChannel*>(this)).take(); return
NS_OK; } else
7334 NS_INTERFACE_MAP_ENTRY(nsIEarlyHintObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIEarlyHintObserver>)) foundInterface
= static_cast<nsIEarlyHintObserver*>(this); else
7335NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)foundInterface = 0; nsresult status; if (!foundInterface) status
= HttpBaseChannel::QueryInterface(aIID, (void**)&foundInterface
); else { (foundInterface)->AddRef(); status = NS_OK; } *aInstancePtr
= foundInterface; return status; }
7336
7337//-----------------------------------------------------------------------------
7338// nsHttpChannel::nsIRequest
7339//-----------------------------------------------------------------------------
7340
7341NS_IMETHODIMPnsresult nsHttpChannel::SetCanceledReason(const nsACString& aReason) {
7342 return SetCanceledReasonImpl(aReason);
7343}
7344
7345NS_IMETHODIMPnsresult nsHttpChannel::GetCanceledReason(nsACString& aReason) {
7346 return GetCanceledReasonImpl(aReason);
7347}
7348
7349NS_IMETHODIMPnsresult
7350nsHttpChannel::CancelWithReason(nsresult aStatus, const nsACString& aReason) {
7351 return CancelWithReasonImpl(aStatus, aReason);
7352}
7353
7354NS_IMETHODIMPnsresult
7355nsHttpChannel::Cancel(nsresult status) {
7356 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7356
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7356); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7357 // We should never have a pump open while a CORS preflight is in progress.
7358 MOZ_ASSERT_IF(mPreflightChannel, !mCachePump)do { if (mPreflightChannel) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(!mCachePump)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mCachePump))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mCachePump", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7358); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7358); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7359#ifdef DEBUG1
7360 // We want to perform this check only when the chanel is being cancelled the
7361 // first time with a URL classifier blocking error code. If mStatus is
7362 // already set to such an error code then Cancel() may be called for some
7363 // other reason, for example because we've received notification about our
7364 // parent process side channel being canceled, in which case we cannot expect
7365 // that CancelByURLClassifier() would have handled this case.
7366 if (ChannelClassifierUtils::IsClassifierBlockingErrorCode(status) &&
7367 !ChannelClassifierUtils::IsClassifierBlockingErrorCode(mStatus)) {
7368 MOZ_CRASH_UNSAFE_PRINTF("Blocking classifier error %" PRIx32do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7370, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
7369 " need to be handled by CancelByURLClassifier()",do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7370, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
7370 static_cast<uint32_t>(status))do { static_assert(1 > 0, "Did you forget arguments to MOZ_CRASH_UNSAFE_PRINTF? "
"Or maybe you want MOZ_CRASH instead?"); static_assert(1 <=
sPrintfMaxArgs, "Only up to 4 additional arguments are allowed!"
); static_assert(sizeof("Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
) <= sPrintfCrashReasonSize, "The supplied format string is too long!"
); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7370, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
;
7371 }
7372#endif
7373
7374 LOG(("nsHttpChannel::Cancel [this=%p status=%" PRIx32 ", reason=%s]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Cancel [this=%p status=%" "x" ", reason=%s]\n"
, this, static_cast<uint32_t>(status), mCanceledReason.
get()); } } while (0)
7375 static_cast<uint32_t>(status), mCanceledReason.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Cancel [this=%p status=%" "x" ", reason=%s]\n"
, this, static_cast<uint32_t>(status), mCanceledReason.
get()); } } while (0)
;
7376 PROFILER_MARKER("nsHttpChannel::Cancel", NETWORK, {}, FlowMarker,do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("nsHttpChannel::Cancel", ::geckoprofiler::category::NETWORK,
{}, ::geckoprofiler::markers::FlowMarker{}, Flow::FromPointer
(this)); } } while (false); } while (false)
7377 Flow::FromPointer(this))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("nsHttpChannel::Cancel", ::geckoprofiler::category::NETWORK,
{}, ::geckoprofiler::markers::FlowMarker{}, Flow::FromPointer
(this)); } } while (false); } while (false)
;
7378
7379 MOZ_ASSERT_IF(!(mConnectionInfo && mConnectionInfo->UsingConnect()) &&do { if (!(mConnectionInfo && mConnectionInfo->UsingConnect
()) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus
)), 1)))) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!AllowedErrorForTransactionRetry(status))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!AllowedErrorForTransactionRetry(status)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!AllowedErrorForTransactionRetry(status)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7381
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7381); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7380 NS_SUCCEEDED(mStatus),do { if (!(mConnectionInfo && mConnectionInfo->UsingConnect
()) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus
)), 1)))) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!AllowedErrorForTransactionRetry(status))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!AllowedErrorForTransactionRetry(status)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!AllowedErrorForTransactionRetry(status)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7381
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7381); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7381 !AllowedErrorForTransactionRetry(status))do { if (!(mConnectionInfo && mConnectionInfo->UsingConnect
()) && ((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus
)), 1)))) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!AllowedErrorForTransactionRetry(status))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!AllowedErrorForTransactionRetry(status)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!AllowedErrorForTransactionRetry(status)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7381
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7381); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7382
7383 mEarlyHintObserver = nullptr;
7384 mWebTransportSessionEventListener = nullptr;
7385
7386 if (mCanceled) {
7387 LOG((" ignoring; already canceled\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " ignoring; already canceled\n"); } } while (0)
;
7388 return NS_OK;
7389 }
7390
7391 LogCallingScriptLocation(this);
7392
7393 if (LoadWaitingForRedirectCallback()) {
7394 LOG(("channel canceled during wait for redirect callback"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "channel canceled during wait for redirect callback"); } } while
(0)
;
7395 }
7396
7397 return CancelInternal(status);
7398}
7399
7400NS_IMETHODIMPnsresult
7401nsHttpChannel::CancelByURLClassifier(nsresult aErrorCode) {
7402 MOZ_ASSERT(ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ChannelClassifierUtils::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(ChannelClassifierUtils::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7402
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 7402); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7403 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7403
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7403); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7404 // We should never have a pump open while a CORS preflight is in progress.
7405 MOZ_ASSERT_IF(mPreflightChannel, !mCachePump)do { if (mPreflightChannel) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(!mCachePump)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mCachePump))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mCachePump", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7405); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7405); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7406
7407 LOG(("nsHttpChannel::CancelByURLClassifier [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelByURLClassifier [this=%p]\n", this); }
} while (0)
;
7408
7409 if (mCanceled) {
7410 LOG((" ignoring; already canceled\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " ignoring; already canceled\n"); } } while (0)
;
7411 return NS_OK;
7412 }
7413
7414 // We are being canceled by the channel classifier because of tracking
7415 // protection, but we haven't yet had a chance to dispatch the
7416 // "http-on-modify-request" notifications yet (this would normally be
7417 // done in PrepareToConnect()). So do that now, before proceeding to
7418 // cancel.
7419 //
7420 // Note that running these observers can itself result in the channel
7421 // being canceled. In that case, we accept that cancelation code as
7422 // the cause of the cancelation, as if the classification of the channel
7423 // would have occurred past this point!
7424
7425 // notify "http-on-modify-request" observers
7426 CallOnModifyRequestObservers();
7427
7428 // Check if request was cancelled during on-modify-request
7429 if (mCanceled) {
7430 return mStatus;
7431 }
7432
7433 if (mSuspendCount) {
7434 LOG(("Waiting until resume in Cancel [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume in Cancel [this=%p]\n", this); } } while
(0)
;
7435 MOZ_ASSERT(!mCallOnResume)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCallOnResume)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCallOnResume))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mCallOnResume"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7435
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume" ")"
); do { MOZ_CrashSequence(__null, 7435); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7436 StoreChannelClassifierCancellationPending(1);
7437 mCallOnResume = [aErrorCode](nsHttpChannel* self) {
7438 self->HandleContinueCancellingByURLClassifier(aErrorCode);
7439 return NS_OK;
7440 };
7441 return NS_OK;
7442 }
7443
7444 // Check to see if we should redirect this channel elsewhere by
7445 // nsIHttpChannel.redirectTo API request
7446 if (mAPIRedirectTo) {
7447 StoreChannelClassifierCancellationPending(1);
7448 return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
7449 }
7450
7451 return CancelInternal(aErrorCode);
7452}
7453
7454void nsHttpChannel::ContinueCancellingByURLClassifier(nsresult aErrorCode) {
7455 MOZ_ASSERT(ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ChannelClassifierUtils::IsClassifierBlockingErrorCode
(aErrorCode))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(ChannelClassifierUtils::IsClassifierBlockingErrorCode
(aErrorCode)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7455
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 7455); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7456 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7456
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7456); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7457 // We should never have a pump open while a CORS preflight is in progress.
7458 MOZ_ASSERT_IF(mPreflightChannel, !mCachePump)do { if (mPreflightChannel) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(!mCachePump)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!mCachePump))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mCachePump", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7458); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7459
7460 LOG(("nsHttpChannel::ContinueCancellingByURLClassifier [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueCancellingByURLClassifier [this=%p]\n"
, this); } } while (0)
;
7461 if (mCanceled) {
7462 LOG((" ignoring; already canceled\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " ignoring; already canceled\n"); } } while (0)
;
7463 return;
7464 }
7465
7466 // Check to see if we should redirect this channel elsewhere by
7467 // nsIHttpChannel.redirectTo API request
7468 if (mAPIRedirectTo) {
7469 (void)AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
7470 return;
7471 }
7472
7473 (void)CancelInternal(aErrorCode);
7474}
7475
7476nsresult nsHttpChannel::CancelInternal(nsresult status) {
7477 LOG(("nsHttpChannel::CancelInternal [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal [this=%p]\n", this); } } while
(0)
;
7478 bool channelClassifierCancellationPending =
7479 !!LoadChannelClassifierCancellationPending();
7480 if (ChannelClassifierUtils::IsClassifierBlockingErrorCode(status)) {
7481 StoreChannelClassifierCancellationPending(0);
7482 }
7483
7484 mEarlyHintObserver = nullptr;
7485 mWebTransportSessionEventListener = nullptr;
7486 {
7487 // Waits for an OnCacheEntryCheck in flight on the cache I/O thread; once
7488 // we're canceled, the abort path reads the state it would write.
7489 MutexAutoLock lock(mCacheWaitLock);
7490 mCanceled = true;
7491 }
7492 mStatus = NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) ? status : NS_ERROR_ABORT;
7493
7494 // If ORB blocked this response, doom the entry that was committed to the
7495 // cache before the (asynchronous) block decision, so it can't be reused
7496 // later (e.g. a navigation consuming a prefetched, ORB-blocked cross-origin
7497 // document). See bug 2045809.
7498 if (mChannelBlockedByOpaqueResponse && mORBValidationCacheEntry) {
7499 mORBValidationCacheEntry->AsyncDoom(nullptr);
7500 mORBValidationCacheEntry = nullptr;
7501 }
7502
7503 // If we're waiting for LNA permission result and the channel is being
7504 // cancelled, we need to call OnPermissionPromptResult with permission denied
7505 // to resume the channel properly
7506 if (mWaitingForLNAPermission) {
7507 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal [this=%p] cancelling while waiting for "
"LNA permission, denying permission", this); } } while (0)
7508 ("nsHttpChannel::CancelInternal [this=%p] cancelling while waiting for "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal [this=%p] cancelling while waiting for "
"LNA permission, denying permission", this); } } while (0)
7509 "LNA permission, denying permission",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal [this=%p] cancelling while waiting for "
"LNA permission, denying permission", this); } } while (0)
7510 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal [this=%p] cancelling while waiting for "
"LNA permission, denying permission", this); } } while (0)
;
7511 // Determine permission key dynamically from transaction
7512 const nsACString& permissionKey =
7513 (mTransaction && mTransaction->GetTargetIPAddressSpace() ==
7514 nsILoadInfo::IPAddressSpace::Local)
7515 ? LOOPBACK_NETWORK_PERMISSION_KEY
7516 : LOCAL_NETWORK_PERMISSION_KEY;
7517 OnPermissionPromptResult(false, permissionKey);
7518 return NS_OK;
7519 }
7520
7521 if (LoadUsedNetwork() && !mReportedNEL) {
7522 MaybeGenerateNELReport();
7523 }
7524
7525 // We don't want the content process to see any header values
7526 // when the request is blocked by ORB
7527 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref &&
7528 mResponseHead) {
7529 mResponseHead->ClearHeaders();
7530 }
7531
7532 if (mLastStatusReported && !mEndMarkerAdded &&
7533 profiler_thread_is_being_profiled_for_markers()) {
7534 // These do allocations/frees/etc; avoid if not active
7535 // mLastStatusReported can be null if Cancel is called before we added the
7536 // start marker.
7537 mEndMarkerAdded = true;
7538
7539 nsAutoCString requestMethod;
7540 GetRequestMethod(requestMethod);
7541
7542 int32_t priority = PRIORITY_NORMAL;
7543 GetPriority(&priority);
7544
7545 uint64_t size = 0;
7546 GetEncodedBodySize(&size);
7547
7548 profiler_add_network_marker(
7549 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_CANCEL,
7550 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
7551 mLoadInfo->GetInnerWindowID(),
7552 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
7553 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
7554 &mTransactionTimings, std::move(mSource));
7555 }
7556
7557 // If we don't have mTransactionPump and mCachePump, we need to call
7558 // AsyncAbort to make sure this channel's listener got notified.
7559 bool needAsyncAbort = !mTransactionPump && !mCachePump;
7560
7561 if (mProxyRequest) mProxyRequest->Cancel(status);
7562 CancelNetworkRequest(status);
7563 mCacheInputStream.CloseAndRelease();
7564 if (mCachePump) mCachePump->Cancel(status);
7565 if (mAuthProvider) mAuthProvider->Cancel(status);
7566 if (mPreflightChannel) mPreflightChannel->Cancel(status);
7567 if (mRequestContext && mOnTailUnblock) {
7568 mOnTailUnblock = nullptr;
7569 mRequestContext->CancelTailedRequest(this);
7570 CloseCacheEntry(false);
7571 needAsyncAbort = false;
7572 (void)AsyncAbort(status);
7573 } else if (channelClassifierCancellationPending) {
7574 // If mCallOnResume is not null here, it's set in
7575 // nsHttpChannel::CancelByURLClassifier. We can override mCallOnResume since
7576 // mCanceled is true and nsHttpChannel::ContinueCancellingByURLClassifier
7577 // does nothing.
7578 if (mCallOnResume) {
7579 mCallOnResume = nullptr;
7580 }
7581 // If we're coming from an asynchronous path when canceling a channel due
7582 // to safe-browsing protection, we need to AsyncAbort the channel now.
7583 needAsyncAbort = false;
7584 (void)AsyncAbort(status);
7585 }
7586
7587 // If we suspended after examining the response to await asynchronous
7588 // tracking-protection annotation (bug 2030021), a cancel while suspended
7589 // would otherwise defer the terminal teardown below (CloseCacheEntry /
7590 // AsyncAbort) to a Resume() that may never arrive. For a cache writer that
7591 // leaves the entry perpetually "being written" -- its output stream never
7592 // closed and the entry never doomed -- wedging every later same-URL
7593 // revalidating consumer forever (bug 2052908). Undo the annotation
7594 // suspension now so the cancelled pump delivers OnStopRequest and the
7595 // write-only entry is closed/doomed normally. Safe if we only primed but
7596 // never actually suspended.
7597 CancelSuspendOrResumeAfterExamineResponse();
7598
7599 // If suspended waiting for dictionary prefetch, unblock it so the channel
7600 // can proceed to cleanup. The prefetch callback may never fire, so we must
7601 // not rely on it to call Resume().
7602 if (mSuspendedForDictionary) {
7603 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal resuming dictionary-suspended channel "
"[this=%p]\n", this); } } while (0)
7604 ("nsHttpChannel::CancelInternal resuming dictionary-suspended channel "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal resuming dictionary-suspended channel "
"[this=%p]\n", this); } } while (0)
7605 "[this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal resuming dictionary-suspended channel "
"[this=%p]\n", this); } } while (0)
7606 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal resuming dictionary-suspended channel "
"[this=%p]\n", this); } } while (0)
;
7607 mSuspendedForDictionary = false;
7608 mCallOnResume = nullptr;
7609 // Null out the already-cancelled pumps so Resume() won't re-trigger
7610 // their OnStopRequest before AsyncAbort's DoNotifyListener can call
7611 // OnStartRequest on our listener.
7612 mTransactionPump = nullptr;
7613 mCachePump = nullptr;
7614 Resume();
7615 needAsyncAbort = true;
7616 }
7617
7618 // If we already have mCallOnResume, AsyncAbort will be called in
7619 // ResumeInternal.
7620 if (needAsyncAbort && !mCallOnResume && !mSuspendCount) {
7621 LOG(("nsHttpChannel::CancelInternal do AsyncAbort [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CancelInternal do AsyncAbort [this=%p]\n", this
); } } while (0)
;
7622 CloseCacheEntry(false);
7623 (void)AsyncAbort(status);
7624 }
7625 return NS_OK;
7626}
7627
7628void nsHttpChannel::CancelNetworkRequest(nsresult aStatus) {
7629 if (mTransaction) {
7630 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, aStatus);
7631 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7632 LOG(("failed to cancel the transaction\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "failed to cancel the transaction\n"); } } while (0)
;
7633 }
7634 }
7635 if (mTransactionPump) mTransactionPump->Cancel(aStatus);
7636
7637 mEarlyHintObserver = nullptr;
7638 mWebTransportSessionEventListener = nullptr;
7639}
7640
7641NS_IMETHODIMPnsresult
7642nsHttpChannel::Suspend() {
7643 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7643
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7643); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7644 NS_ENSURE_TRUE(LoadIsPending(), NS_ERROR_NOT_AVAILABLE)do { if ((__builtin_expect(!!(!(LoadIsPending())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "LoadIsPending()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7644); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7645
7646 PROFILER_MARKER("nsHttpChannel::Suspend", NETWORK, {MarkerStack::Capture()},do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("nsHttpChannel::Suspend", ::geckoprofiler::category::NETWORK
, {MarkerStack::Capture()}, ::geckoprofiler::markers::FlowMarker
{}, Flow::FromPointer(this)); } } while (false); } while (false
)
7647 FlowMarker, Flow::FromPointer(this))do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("nsHttpChannel::Suspend", ::geckoprofiler::category::NETWORK
, {MarkerStack::Capture()}, ::geckoprofiler::markers::FlowMarker
{}, Flow::FromPointer(this)); } } while (false); } while (false
)
;
7648 LOG(("nsHttpChannel::Suspend [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Suspend [this=%p]\n", this); } } while (0)
;
7649 LogCallingScriptLocation(this);
7650
7651 ++mSuspendCount;
7652
7653 if (mSuspendCount == 1) {
7654 mSuspendTimestamp = TimeStamp::NowLoRes();
7655
7656 // Start timer to detect if we're suspended too long
7657 // This helps unblock waiting cache listeners when a channel is suspended
7658 // for an unreasonably long time.
7659 uint32_t delay = StaticPrefs::network_cache_suspended_writer_delay_ms();
7660 if (!mSuspendTimer && delay) {
7661 mSuspendTimer = NS_NewTimer();
7662 }
7663
7664 if (mSuspendTimer && delay) {
7665 RefPtr<TimerCallback> timerCallback = new TimerCallback(this);
7666 mSuspendTimer->InitWithCallback(timerCallback, delay,
7667 nsITimer::TYPE_ONE_SHOT);
7668 LOG((" started suspend timer, will fire in %dms", delay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " started suspend timer, will fire in %dms", delay); } } while
(0)
;
7669 }
7670 }
7671
7672 nsresult rvTransaction = NS_OK;
7673 if (mTransactionPump) {
7674 rvTransaction = mTransactionPump->Suspend();
7675 }
7676 nsresult rvCache = NS_OK;
7677 if (mCachePump) {
7678 rvCache = mCachePump->Suspend();
7679 }
7680
7681 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
7682}
7683
7684// static
7685void nsHttpChannel::StaticSuspend(nsHttpChannel* aChan) { aChan->Suspend(); }
7686
7687NS_IMETHODIMPnsresult
7688nsHttpChannel::Resume() {
7689 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7689
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7689); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7690 NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(mSuspendCount > 0)), 0))) {
NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "mSuspendCount > 0"
") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7690); return NS_ERROR_UNEXPECTED; } } while (false)
;
7691
7692 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::Resume", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7693( "nsHttpChannel::Resume"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7693 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7693( "nsHttpChannel::Resume"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7694 LOG(("nsHttpChannel::ResumeInternal [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResumeInternal [this=%p]\n", this); } } while
(0)
;
7695 LogCallingScriptLocation(this);
7696
7697 if (--mSuspendCount == 0) {
7698 mSuspendTotalTime += TimeStamp::NowLoRes() - mSuspendTimestamp;
7699
7700 // Cancel suspend timer since we're resuming
7701 if (mSuspendTimer) {
7702 mSuspendTimer->Cancel();
7703 LOG((" cancelled suspend timer"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cancelled suspend timer"); } } while (0)
;
7704 }
7705
7706 // Reset bypass flag since the writer is resuming
7707 if (mBypassCacheWriterSet && mCacheEntry) {
7708 mCacheEntry->SetBypassWriterLock(false);
7709 mBypassCacheWriterSet = false;
7710 LOG((" reset bypass writer lock flag"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " reset bypass writer lock flag"); } } while (0)
;
7711 }
7712
7713 if (mCallOnResume) {
7714 // Resume the interrupted procedure first, then resume
7715 // the pump to continue process the input stream.
7716 // Any newly created pump MUST be suspended to prevent calling
7717 // its OnStartRequest before OnStopRequest of any pre-existing
7718 // pump. AsyncResumePending ensures that.
7719 MOZ_ASSERT(!LoadAsyncResumePending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadAsyncResumePending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadAsyncResumePending())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadAsyncResumePending()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7719
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7719); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7720 StoreAsyncResumePending(1);
7721
7722 std::function<nsresult(nsHttpChannel*)> callOnResume = nullptr;
7723 std::swap(callOnResume, mCallOnResume);
7724
7725 RefPtr<nsHttpChannel> self(this);
7726 nsCOMPtr<nsIRequest> transactionPump = mTransactionPump;
7727 RefPtr<nsInputStreamPump> cachePump = mCachePump;
7728
7729 nsresult rv = NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7730 "nsHttpChannel::CallOnResume",
7731 [callOnResume{std::move(callOnResume)}, self{std::move(self)},
7732 transactionPump{std::move(transactionPump)},
7733 cachePump{std::move(cachePump)}]() {
7734 MOZ_ASSERT(self->LoadAsyncResumePending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(self->LoadAsyncResumePending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(self->LoadAsyncResumePending
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("self->LoadAsyncResumePending()", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7734); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7735 nsresult rv = self->CallOrWaitForResume(callOnResume);
7736 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7737 self->CloseCacheEntry(false);
7738 (void)self->AsyncAbort(rv);
7739 }
7740 MOZ_ASSERT(self->LoadAsyncResumePending())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(self->LoadAsyncResumePending())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(self->LoadAsyncResumePending
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("self->LoadAsyncResumePending()", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7740); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7740); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7741
7742 self->StoreAsyncResumePending(0);
7743
7744 // And now actually resume the previously existing pumps.
7745 if (transactionPump) {
7746 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume resuming previous transaction "
"pump %p, this=%p", transactionPump.get(), self.get()); } } while
(0)
7747 ("nsHttpChannel::CallOnResume resuming previous transaction "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume resuming previous transaction "
"pump %p, this=%p", transactionPump.get(), self.get()); } } while
(0)
7748 "pump %p, this=%p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume resuming previous transaction "
"pump %p, this=%p", transactionPump.get(), self.get()); } } while
(0)
7749 transactionPump.get(), self.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume resuming previous transaction "
"pump %p, this=%p", transactionPump.get(), self.get()); } } while
(0)
;
7750 transactionPump->Resume();
7751 }
7752 if (cachePump) {
7753 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume resuming previous cache pump "
"%p, this=%p", cachePump.get(), self.get()); } } while (0)
7754 ("nsHttpChannel::CallOnResume resuming previous cache pump "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume resuming previous cache pump "
"%p, this=%p", cachePump.get(), self.get()); } } while (0)
7755 "%p, this=%p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume resuming previous cache pump "
"%p, this=%p", cachePump.get(), self.get()); } } while (0)
7756 cachePump.get(), self.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume resuming previous cache pump "
"%p, this=%p", cachePump.get(), self.get()); } } while (0)
;
7757 cachePump->Resume();
7758 }
7759
7760 // Any newly created pumps were suspended once because of
7761 // AsyncResumePending. Problem is that the stream listener
7762 // notification is already pending in the queue right now, because
7763 // AsyncRead doesn't (regardless if called after Suspend) respect
7764 // the suspend coutner and the right order would not be preserved.
7765 // Hence, we do another dispatch round to actually Resume after
7766 // the notification from the original pump.
7767 if (transactionPump != self->mTransactionPump &&
7768 self->mTransactionPump) {
7769 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new " "transaction "
"pump %p, this=%p", self->mTransactionPump.get(), self.get
()); } } while (0)
7770 ("nsHttpChannel::CallOnResume async-resuming new "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new " "transaction "
"pump %p, this=%p", self->mTransactionPump.get(), self.get
()); } } while (0)
7771 "transaction "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new " "transaction "
"pump %p, this=%p", self->mTransactionPump.get(), self.get
()); } } while (0)
7772 "pump %p, this=%p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new " "transaction "
"pump %p, this=%p", self->mTransactionPump.get(), self.get
()); } } while (0)
7773 self->mTransactionPump.get(), self.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new " "transaction "
"pump %p, this=%p", self->mTransactionPump.get(), self.get
()); } } while (0)
;
7774
7775 nsCOMPtr<nsIRequest> pump = self->mTransactionPump;
7776 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7777 "nsHttpChannel::CallOnResume new transaction",
7778 [pump{std::move(pump)}]() { pump->Resume(); }));
7779 }
7780 if (cachePump != self->mCachePump && self->mCachePump) {
7781 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new cache pump "
"%p, this=%p", self->mCachePump.get(), self.get()); } } while
(0)
7782 ("nsHttpChannel::CallOnResume async-resuming new cache pump "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new cache pump "
"%p, this=%p", self->mCachePump.get(), self.get()); } } while
(0)
7783 "%p, this=%p",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new cache pump "
"%p, this=%p", self->mCachePump.get(), self.get()); } } while
(0)
7784 self->mCachePump.get(), self.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new cache pump "
"%p, this=%p", self->mCachePump.get(), self.get()); } } while
(0)
;
7785
7786 RefPtr<nsInputStreamPump> pump = self->mCachePump;
7787 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7788 "nsHttpChannel::CallOnResume new pump",
7789 [pump{std::move(pump)}]() { pump->Resume(); }));
7790 }
7791 }));
7792 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7792); return rv; } } while (false)
;
7793 return rv;
7794 }
7795 }
7796
7797 nsresult rvTransaction = NS_OK;
7798 if (mTransactionPump) {
7799 rvTransaction = mTransactionPump->Resume();
7800 }
7801
7802 nsresult rvCache = NS_OK;
7803 if (mCachePump) {
7804 rvCache = mCachePump->Resume();
7805 }
7806
7807 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
7808}
7809
7810//-----------------------------------------------------------------------------
7811// nsHttpChannel::nsIChannel
7812//-----------------------------------------------------------------------------
7813
7814NS_IMETHODIMPnsresult
7815nsHttpChannel::GetSecurityInfo(nsITransportSecurityInfo** securityInfo) {
7816 NS_ENSURE_ARG_POINTER(securityInfo)do { if ((__builtin_expect(!!(!(securityInfo)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "securityInfo" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7816); return NS_ERROR_INVALID_POINTER; } } while (false)
;
7817 *securityInfo = do_AddRef(mSecurityInfo).take();
7818 return NS_OK;
7819}
7820
7821// If any of the functions that AsyncOpen calls returns immediately an error
7822// AsyncAbort(which calls onStart/onStopRequest) does not need to be call.
7823// To be sure that they are not call ReleaseListeners() is called.
7824// If AsyncOpen returns NS_OK, after that point AsyncAbort must be called on
7825// any error.
7826NS_IMETHODIMPnsresult
7827nsHttpChannel::AsyncOpen(nsIStreamListener* aListener) {
7828 // doContentSecurityCheck and OnOpeningRequest fire observers that may
7829 // spin nested event loops; hold a strong ref to this.
7830 RefPtr<nsHttpChannel> self(this);
7831
7832 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpen", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7833( "nsHttpChannel::AsyncOpen"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7833 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7833( "nsHttpChannel::AsyncOpen"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7834 nsCOMPtr<nsIStreamListener> listener = aListener;
7835 nsresult rv =
7836 nsContentSecurityManager::doContentSecurityCheck(this, listener);
7837 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7837)
) {
7838 ReleaseListeners();
7839 return rv;
7840 }
7841
7842 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->
GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone
() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
" (" "security flags in loadInfo but doContentSecurityCheck() not called"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
") (" "security flags in loadInfo but doContentSecurityCheck() not called"
")"); do { MOZ_CrashSequence(__null, 7849); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7843 mLoadInfo->GetSecurityMode() == 0 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->
GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone
() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
" (" "security flags in loadInfo but doContentSecurityCheck() not called"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
") (" "security flags in loadInfo but doContentSecurityCheck() not called"
")"); do { MOZ_CrashSequence(__null, 7849); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7844 mLoadInfo->GetInitialSecurityCheckDone() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->
GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone
() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
" (" "security flags in loadInfo but doContentSecurityCheck() not called"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
") (" "security flags in loadInfo but doContentSecurityCheck() not called"
")"); do { MOZ_CrashSequence(__null, 7849); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7845 (mLoadInfo->GetSecurityMode() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->
GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone
() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
" (" "security flags in loadInfo but doContentSecurityCheck() not called"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
") (" "security flags in loadInfo but doContentSecurityCheck() not called"
")"); do { MOZ_CrashSequence(__null, 7849); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7846 nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->
GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone
() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
" (" "security flags in loadInfo but doContentSecurityCheck() not called"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
") (" "security flags in loadInfo but doContentSecurityCheck() not called"
")"); do { MOZ_CrashSequence(__null, 7849); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7847 mLoadInfo->GetLoadingPrincipal() &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->
GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone
() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
" (" "security flags in loadInfo but doContentSecurityCheck() not called"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
") (" "security flags in loadInfo but doContentSecurityCheck() not called"
")"); do { MOZ_CrashSequence(__null, 7849); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7848 mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal()),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->
GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone
() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
" (" "security flags in loadInfo but doContentSecurityCheck() not called"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
") (" "security flags in loadInfo but doContentSecurityCheck() not called"
")"); do { MOZ_CrashSequence(__null, 7849); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7849 "security flags in loadInfo but doContentSecurityCheck() not called")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->
GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode
() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone
() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL
&& mLoadInfo->GetLoadingPrincipal() && mLoadInfo
->GetLoadingPrincipal()->IsSystemPrincipal())))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
" (" "security flags in loadInfo but doContentSecurityCheck() not called"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->GetSecurityMode() == 0 || mLoadInfo->GetInitialSecurityCheckDone() || (mLoadInfo->GetSecurityMode() == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL && mLoadInfo->GetLoadingPrincipal() && mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal())"
") (" "security flags in loadInfo but doContentSecurityCheck() not called"
")"); do { MOZ_CrashSequence(__null, 7849); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7850
7851 LOG(("nsHttpChannel::AsyncOpen [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::AsyncOpen [this=%p]\n", this); } } while (0
)
;
7852 mOpenerCallingScriptLocation = CallingScriptLocationString();
7853 LogCallingScriptLocation(this, mOpenerCallingScriptLocation);
7854 NS_CompareLoadInfoAndLoadContext(this);
7855
7856#ifdef DEBUG1
7857 AssertPrivateBrowsingId();
7858#endif
7859
7860 NS_ENSURE_ARG_POINTER(listener)do { if ((__builtin_expect(!!(!(listener)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "listener" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7860
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
7861 NS_ENSURE_TRUE(!LoadIsPending(), NS_ERROR_IN_PROGRESS)do { if ((__builtin_expect(!!(!(!LoadIsPending())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadIsPending()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7861); return NS_ERROR_IN_PROGRESS; } } while (false)
;
7862 NS_ENSURE_TRUE(!LoadWasOpened(), NS_ERROR_ALREADY_OPENED)do { if ((__builtin_expect(!!(!(!LoadWasOpened())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadWasOpened()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7862); return NS_ERROR_ALREADY_OPENED; } } while (false)
;
7863
7864 if (mCanceled) {
7865 ReleaseListeners();
7866 return NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) ? mStatus : NS_ERROR_FAILURE;
7867 }
7868
7869 if (MaybeWaitForUploadStreamNormalization(listener, nullptr)) {
7870 return NS_OK;
7871 }
7872
7873 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7873
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7873); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7874
7875 if (!gHttpHandler->Active()) {
7876 LOG((" after HTTP shutdown..."))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " after HTTP shutdown..."); } } while (0)
;
7877 ReleaseListeners();
7878 return NS_ERROR_NOT_AVAILABLE;
7879 }
7880
7881 rv = NS_CheckPortSafety(mURI);
7882 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7883 ReleaseListeners();
7884 return rv;
7885 }
7886
7887 // If no one called SetLoadGroup or SetNotificationCallbacks, the private
7888 // state has not been updated on PrivateBrowsingChannel (which we derive
7889 // from) Same if the loadinfo has changed since the creation of the channel.
7890 // Hence, we have to call UpdatePrivateBrowsing() here
7891 UpdatePrivateBrowsing();
7892
7893 AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(this);
7894
7895 // Recalculate the default userAgent header after the AntiTrackingInfo gets
7896 // updated because we can only know whether the site is exempted from
7897 // fingerprinting protection after we have the AntiTracking Info.
7898 //
7899 // Note that we don't recalculate the header if it has been modified since the
7900 // channel was created because we want to preserve the modified header.
7901 if (!LoadIsUserAgentHeaderModified()) {
7902 rv = mRequestHead.SetHeader(
7903 nsHttp::User_Agent,
7904 gHttpHandler->UserAgent(nsContentUtils::ShouldResistFingerprinting(
7905 this, RFPTarget::HttpUserAgent)),
7906 false, nsHttpHeaderArray::eVarietyRequestEnforceDefault);
7907 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7907); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 7907); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7908 }
7909
7910 if (WaitingForTailUnblock()) {
7911 // This channel is marked as Tail and is part of a request context
7912 // that has positive number of non-tailed requestst, hence this channel
7913 // has been put to a queue.
7914 // When tail is unblocked, OnTailUnblock on this channel will be called
7915 // to continue AsyncOpen.
7916 mListener = listener;
7917 MOZ_DIAGNOSTIC_ASSERT(!mOnTailUnblock)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mOnTailUnblock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mOnTailUnblock))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mOnTailUnblock"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 7917
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 7917); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7918 mOnTailUnblock = &nsHttpChannel::AsyncOpenOnTailUnblock;
7919
7920 LOG((" put on hold until tail is unblocked"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " put on hold until tail is unblocked"); } } while (0)
;
7921 return NS_OK;
7922 }
7923
7924 // Remember the cookie header that was set, if any
7925 nsAutoCString cookieHeader;
7926 if (NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::Cookie, cookieHeader))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::Cookie, cookieHeader))), 1)))
) {
7927 // if this is a cache revalidaing channel (mIsStaleRevalidation), then this
7928 // represents both user cookies and cookies from cookieService
7929 mUserSetCookieHeader = std::move(cookieHeader);
7930 }
7931
7932 // Set user agent override, do so before OnOpeningRequest notification
7933 // since we want to allow consumers of that notification change or remove
7934 // the User-Agent request header.
7935 HttpBaseChannel::SetDocshellUserAgentOverride();
7936
7937 // After we notify any observers (on-opening-request, loadGroup, etc) we
7938 // must return NS_OK and return any errors asynchronously via
7939 // OnStart/OnStopRequest. Observers may add a reference to the channel
7940 // and expect to get OnStopRequest so they know when to drop the reference,
7941 // etc.
7942
7943 // notify "http-on-opening-request" observers, but not if this is a redirect
7944 if (!(mLoadFlags & LOAD_REPLACE)) {
7945 gHttpHandler->OnOpeningRequest(this);
7946 }
7947
7948 StoreIsPending(true);
7949 StoreWasOpened(true);
7950
7951 mListener = std::move(listener);
7952
7953 AsyncOpenFinal(TimeStamp::Now());
7954
7955 return NS_OK;
7956}
7957
7958void nsHttpChannel::AsyncOpenFinal(TimeStamp aTimeStamp) {
7959 // We save this timestamp from outside of the if block in case we enable the
7960 // profiler after AsyncOpen().
7961 mLastStatusReported = TimeStamp::Now();
7962 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpenFinal", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7963( "nsHttpChannel::AsyncOpenFinal"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7963 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7963( "nsHttpChannel::AsyncOpenFinal"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7964 if (profiler_thread_is_being_profiled_for_markers()) {
7965 nsAutoCString requestMethod;
7966 GetRequestMethod(requestMethod);
7967
7968 profiler_add_network_marker(
7969 mURI, requestMethod, mPriority, mChannelId, NetworkLoadType::LOAD_START,
7970 mChannelCreationTimestamp, mLastStatusReported, 0, mCacheDisposition,
7971 mLoadInfo->GetInnerWindowID(),
7972 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
7973 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch());
7974 }
7975
7976 // Added due to PauseTask/DelayHttpChannel
7977 if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
7978
7979 // record asyncopen time unconditionally and clear it if we
7980 // don't want it after OnModifyRequest() weighs in. But waiting for
7981 // that to complete would mean we don't include proxy resolution in the
7982 // timing.
7983 if (!LoadAsyncOpenTimeOverriden()) {
7984 mAsyncOpenTime = aTimeStamp;
7985 }
7986
7987 // A completed prefetch's response was there before the navigation started.
7988 if (mLoadInfo->GetActivatedFromNavigationalPrefetch() &&
7989 mCacheReadStart.IsNull()) {
7990 mCacheReadStart = mAsyncOpenTime;
7991 }
7992
7993 // Remember we have Authorization header set here. We need to check on it
7994 // just once and early, AsyncOpen is the best place.
7995 StoreCustomAuthHeader(mRequestHead.HasHeader(nsHttp::Authorization));
7996
7997 bool willCallback = false;
7998 // We are about to do an async lookup to check if the URI is a tracker. If
7999 // yes, this channel will be canceled by channel classifier. Chances are the
8000 // lookup is not needed so CheckIsTrackerWithLocalTable() will return an
8001 // error and then we can MaybeResolveProxyAndBeginConnect() right away.
8002 // We skip the check in case this is an internal redirected channel
8003 if (NS_ShouldClassifyChannel(this, ClassifyType::ETP)) {
8004 RefPtr<nsHttpChannel> self = this;
8005 willCallback = NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8006 AsyncUrlChannelClassifier::CheckChannel(this, [self]() -> void {((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8007 nsCOMPtr<nsIURI> uri;((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8008 self->GetURI(getter_AddRefs(uri));((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8009 MOZ_ASSERT(uri);((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8010
8011 // Finish the AntiTracking Heuristic before((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8012 // MaybeResolveProxyAndBeginConnect().((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8013 FinishAntiTrackingRedirectHeuristic(self, uri);((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8014
8015 self->MaybeResolveProxyAndBeginConnect();((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
8016 }))((bool)(__builtin_expect(!!(!NS_FAILED_impl(AsyncUrlChannelClassifier
::CheckChannel(this, [self]() -> void { nsCOMPtr<nsIURI
> uri; self->GetURI(getter_AddRefs(uri)); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(uri)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(uri))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("uri", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 8009); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
;
8017 }
8018
8019 if (!willCallback) {
8020 // We can do MaybeResolveProxyAndBeginConnect immediately if
8021 // CheckIsTrackerWithLocalTable is failed. Note that we don't need to
8022 // handle the failure because BeginConnect() will return synchronously and
8023 // the caller will be responsible for handling it.
8024 MaybeResolveProxyAndBeginConnect();
8025 }
8026}
8027
8028void nsHttpChannel::MaybeResolveProxyAndBeginConnect() {
8029 nsresult rv;
8030
8031 // The common case for HTTP channels is to begin proxy resolution and return
8032 // at this point. The only time we know mProxyInfo already is if we're
8033 // proxying a non-http protocol like ftp. We don't need to discover proxy
8034 // settings if we are never going to make a network connection.
8035 if (!mProxyInfo &&
8036 !(mLoadFlags & (LOAD_ONLY_FROM_CACHE | LOAD_NO_NETWORK_IO)) &&
8037 !BypassProxy()) {
8038 nsCOMPtr<nsIProtocolProxyService> pps =
8039 mozilla::components::ProtocolProxy::Service();
8040 nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
8041 if (pps2 && pps2->IsEffectivelyDirect()) {
8042 mozilla::glean::networking::proxy_fast_path_used.Add(1);
8043 MaybeStartDNSPrefetch();
8044 } else if (NS_SUCCEEDED(ResolveProxy())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ResolveProxy())),
1)))
) {
8045 return;
8046 }
8047 }
8048
8049 if (!gHttpHandler->Active()) {
8050 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeResolveProxyAndBeginConnect [this=%p] "
"Handler no longer active.\n", this); } } while (0)
8051 ("nsHttpChannel::MaybeResolveProxyAndBeginConnect [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeResolveProxyAndBeginConnect [this=%p] "
"Handler no longer active.\n", this); } } while (0)
8052 "Handler no longer active.\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeResolveProxyAndBeginConnect [this=%p] "
"Handler no longer active.\n", this); } } while (0)
8053 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeResolveProxyAndBeginConnect [this=%p] "
"Handler no longer active.\n", this); } } while (0)
;
8054 rv = NS_ERROR_NOT_AVAILABLE;
8055 } else {
8056 rv = BeginConnect();
8057 }
8058 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8059 CloseCacheEntry(false);
8060 (void)AsyncAbort(rv);
8061 }
8062}
8063
8064nsresult nsHttpChannel::AsyncOpenOnTailUnblock() {
8065 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpenOnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject8066( "nsHttpChannel::AsyncOpenOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
8066 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject8066( "nsHttpChannel::AsyncOpenOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
8067 return AsyncOpen(mListener);
8068}
8069
8070already_AddRefed<nsChannelClassifier>
8071nsHttpChannel::GetOrCreateChannelClassifier() {
8072 if (!mChannelClassifier) {
8073 mChannelClassifier = new nsChannelClassifier(this);
8074 LOG(("nsHttpChannel [%p] created nsChannelClassifier [%p]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel [%p] created nsChannelClassifier [%p]\n", this
, mChannelClassifier.get()); } } while (0)
8075 mChannelClassifier.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel [%p] created nsChannelClassifier [%p]\n", this
, mChannelClassifier.get()); } } while (0)
;
8076 }
8077
8078 RefPtr<nsChannelClassifier> classifier = mChannelClassifier;
8079 return classifier.forget();
8080}
8081
8082nsIHttpChannelInternal::ProxyDNSStrategy
8083nsHttpChannel::ComputeProxyDNSStrategy() {
8084 // When network_dns_force_use_https_rr is true, return DNS_PREFETCH_ORIGIN.
8085 // This ensures that we always perform HTTPS RR query.
8086 nsCOMPtr<nsProxyInfo> proxyInfo(static_cast<nsProxyInfo*>(mProxyInfo.get()));
8087 if (!proxyInfo || StaticPrefs::network_dns_force_use_https_rr()) {
8088 return nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN;
8089 }
8090
8091 // If the proxy is not to perform name resolution itself.
8092 return GetProxyDNSStrategyHelper(proxyInfo->Type(), proxyInfo->Flags());
8093}
8094
8095NS_IMETHODIMPnsresult
8096nsHttpChannel::GetProxyDNSStrategy(
8097 nsIHttpChannelInternal::ProxyDNSStrategy* aStrategy) {
8098 NS_ENSURE_ARG_POINTER(aStrategy)do { if ((__builtin_expect(!!(!(aStrategy)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aStrategy" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 8098
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
8099 *aStrategy = ComputeProxyDNSStrategy();
8100 return NS_OK;
8101}
8102
8103// BeginConnect() SHOULD NOT call AsyncAbort(). AsyncAbort will be called by
8104// functions that called BeginConnect if needed. Only
8105// MaybeResolveProxyAndBeginConnect and OnProxyAvailable ever call
8106// BeginConnect.
8107nsresult nsHttpChannel::BeginConnect() {
8108 LOG(("nsHttpChannel::BeginConnect [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::BeginConnect [this=%p]\n", this); } } while
(0)
;
8109
8110 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::BeginConnect", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject8111( "nsHttpChannel::BeginConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
8111 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject8111( "nsHttpChannel::BeginConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
8112 nsresult rv;
8113
8114 // It is the caller's responsibility to not call us late in shutdown.
8115 MOZ_ASSERT(gHttpHandler->Active())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gHttpHandler->Active())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gHttpHandler->Active())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("gHttpHandler->Active()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 8115
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gHttpHandler->Active()"
")"); do { MOZ_CrashSequence(__null, 8115); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8116
8117 // Construct connection info object
8118 nsAutoCString host;
8119 nsAutoCString scheme;
8120 int32_t port = -1;
8121 bool isHttps = IsHTTPS();
8122
8123 rv = mURI->GetScheme(scheme);
8124 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiHost(host);
8125 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetPort(&port);
8126 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiSpec(mSpec);
8127 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8128 return rv;
8129 }
8130
8131 // Just a warning here because some nsIURIs do not implement this method.
8132 (void)NS_WARN_IF(NS_FAILED(mURI->GetUsername(mUsername)))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(mURI
->GetUsername(mUsername))), 0))), "NS_FAILED(mURI->GetUsername(mUsername))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 8132
)
;
8133
8134 // Reject the URL if it doesn't specify a host
8135 if (host.IsEmpty()) {
8136 rv = NS_ERROR_MALFORMED_URI;
8137 return rv;
8138 }
8139 LOG(("host=%s port=%d\n", host.get(), port))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "host=%s port=%d\n", host.get(), port); } } while (0)
;
8140 LOG(("uri=%s\n", mSpec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "uri=%s\n", mSpec.get()); } } while (0)
;
8141
8142 nsCOMPtr<nsProxyInfo> proxyInfo;
8143 if (mProxyInfo) proxyInfo = do_QueryInterface(mProxyInfo);
8144
8145 if (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) {
8146 if (!proxyInfo) {
8147 LOG(("return failure: no proxy for connect-only channel\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "return failure: no proxy for connect-only channel\n"); } }
while (0)
;
8148 return NS_ERROR_FAILURE;
8149 }
8150
8151 if (!proxyInfo->IsHTTP() && !proxyInfo->IsHTTPS()) {
8152 LOG(("return failure: non-http proxy for connect-only channel\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "return failure: non-http proxy for connect-only channel\n"
); } } while (0)
;
8153 return NS_ERROR_FAILURE;
8154 }
8155 }
8156
8157 mRequestHead.SetHTTPS(isHttps);
8158 mRequestHead.SetOrigin(scheme, host, port);
8159
8160 AddStorageAccessHeadersToRequest();
8161 SetOriginHeader();
8162 SetDoNotTrack();
8163 SetGlobalPrivacyControl();
8164
8165 OriginAttributes originAttributes;
8166 StoragePrincipalHelper::GetOriginAttributesForHttpConnection(
8167 this, !!proxyInfo, originAttributes);
8168
8169 // Adjust mCaps according to our request headers:
8170 // - If "Connection: close" is set as a request header, then do not bother
8171 // trying to establish a keep-alive connection.
8172 if (mRequestHead.HasHeaderValue(nsHttp::Connection, "close")) {
8173 mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE(1 << 0));
8174 StoreAllowHttp3(false);
8175 }
8176
8177 gHttpHandler->MaybeAddAltSvcForTesting(mURI, mUsername, mPrivateBrowsing,
8178 mCallbacks, originAttributes);
8179
8180 RefPtr<nsHttpConnectionInfo> connInfo;
8181#ifdef FUZZING
8182 if (StaticPrefs::fuzzing_necko_http3()) {
8183 connInfo =
8184 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8185 originAttributes, host, port, true);
8186 } else {
8187#endif
8188 if (mWebTransportSessionEventListener) {
8189 connInfo =
8190 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8191 originAttributes, isHttps, true, true);
8192 bool dedicated = true;
8193 nsresult rv;
8194 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
8195 do_QueryInterface(mWebTransportSessionEventListener, &rv);
8196 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8196); return rv; } } while (false)
;
8197 nsIWebTransport::HTTPVersion httpVersion;
8198 (void)wtconSettings->GetHttpVersion(&httpVersion);
8199 if (httpVersion == nsIWebTransport::HTTPVersion::h2) {
8200 connInfo =
8201 new nsHttpConnectionInfo(host, port, "h2"_ns, mUsername, proxyInfo,
8202 originAttributes, isHttps, false, true);
8203 } else {
8204 connInfo =
8205 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8206 originAttributes, isHttps, true, true);
8207 }
8208 wtconSettings->GetDedicated(&dedicated);
8209 if (dedicated) {
8210 connInfo = connInfo->Mutate()
8211 .SetWebTransportId(
8212 nsHttpConnectionInfo::GenerateNewWebTransportId())
8213 .Finalize();
8214 }
8215 } else {
8216 connInfo = new nsHttpConnectionInfo(host, port, ""_ns, mUsername,
8217 proxyInfo, originAttributes, isHttps);
8218 }
8219#ifdef FUZZING
8220 }
8221#endif
8222
8223 bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
8224
8225 bool http3Allowed = Http3Allowed();
8226 if (!http3Allowed) {
8227 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
8228 }
8229
8230 RefPtr<AltSvcMapping> mapping;
8231 if (!mConnectionInfo && LoadAllowAltSvc() && // per channel
8232 !mWebTransportSessionEventListener && (http2Allowed || http3Allowed) &&
8233 !(mLoadFlags & LOAD_FRESH_CONNECTION) &&
8234 AltSvcMapping::AcceptableProxy(proxyInfo) &&
8235 (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
8236 (mapping = gHttpHandler->GetAltServiceMapping(
8237 scheme, host, port, mPrivateBrowsing, originAttributes, http2Allowed,
8238 http3Allowed))) {
8239 LOG(("nsHttpChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n"
, this, scheme.get(), mapping->AlternateHost().get(), mapping
->AlternatePort(), mapping->HashKey().get()); } } while
(0)
8240 scheme.get(), mapping->AlternateHost().get(), mapping->AlternatePort(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n"
, this, scheme.get(), mapping->AlternateHost().get(), mapping
->AlternatePort(), mapping->HashKey().get()); } } while
(0)
8241 mapping->HashKey().get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n"
, this, scheme.get(), mapping->AlternateHost().get(), mapping
->AlternatePort(), mapping->HashKey().get()); } } while
(0)
;
8242
8243 if (!(mLoadFlags & LOAD_ANONYMOUS) && !mPrivateBrowsing) {
8244 nsAutoCString altUsedLine(mapping->AlternateHost());
8245 bool defaultPort =
8246 mapping->AlternatePort() ==
8247 (isHttps ? NS_HTTPS_DEFAULT_PORT443 : NS_HTTP_DEFAULT_PORT80);
8248 if (!defaultPort) {
8249 altUsedLine.AppendLiteral(":");
8250 altUsedLine.AppendInt(mapping->AlternatePort());
8251 }
8252 // Like what we did for 'Authorization' header, we need to do the same for
8253 // 'Alt-Used' for avoiding this header being shown in the ServiceWorker
8254 // FetchEvent.
8255 (void)mRequestHead.ClearHeader(nsHttp::Alternate_Service_Used);
8256 rv = mRequestHead.SetHeader(nsHttp::Alternate_Service_Used, altUsedLine,
8257 false,
8258 nsHttpHeaderArray::eVarietyRequestDefault);
8259 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8259); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 8259); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8260 }
8261
8262 nsCOMPtr<nsIConsoleService> consoleService;
8263 consoleService = mozilla::components::Console::Service();
8264 if (consoleService && !host.Equals(mapping->AlternateHost())) {
8265 nsAutoString message(u"Alternate Service Mapping found: "_ns);
8266 AppendASCIItoUTF16(scheme, message);
8267 message.AppendLiteral(u"://");
8268 AppendASCIItoUTF16(host, message);
8269 message.AppendLiteral(u":");
8270 message.AppendInt(port);
8271 message.AppendLiteral(u" to ");
8272 AppendASCIItoUTF16(scheme, message);
8273 message.AppendLiteral(u"://");
8274 AppendASCIItoUTF16(mapping->AlternateHost(), message);
8275 message.AppendLiteral(u":");
8276 message.AppendInt(mapping->AlternatePort());
8277 consoleService->LogStringMessage(message.get());
8278 }
8279
8280 LOG(("nsHttpChannel %p Using connection info from altsvc mapping", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p Using connection info from altsvc mapping"
, this); } } while (0)
;
8281 mapping->GetConnectionInfo(getter_AddRefs(mConnectionInfo), proxyInfo,
8282 originAttributes);
8283 glean::http::transaction_use_altsvc
8284 .EnumGet(glean::http::TransactionUseAltsvcLabel::eTrue)
8285 .Add();
8286 if (mConnectionInfo->IsHttp3() &&
8287 StaticPrefs::
8288 network_http_http3_force_use_alt_svc_mapping_for_testing()) {
8289 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
8290 }
8291 } else if (mConnectionInfo) {
8292 LOG(("nsHttpChannel %p Using channel supplied connection info", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p Using channel supplied connection info", this
); } } while (0)
;
8293 glean::http::transaction_use_altsvc
8294 .EnumGet(glean::http::TransactionUseAltsvcLabel::eFalse)
8295 .Add();
8296 } else {
8297 LOG(("nsHttpChannel %p Using default connection info", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p Using default connection info", this); } }
while (0)
;
8298
8299 mConnectionInfo = connInfo;
8300 glean::http::transaction_use_altsvc
8301 .EnumGet(glean::http::TransactionUseAltsvcLabel::eFalse)
8302 .Add();
8303 }
8304
8305 bool trrEnabled = false;
8306 auto dnsStrategy = ComputeProxyDNSStrategy();
8307 bool httpsRRAllowed =
8308 !LoadBeConservative() && !(mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) &&
8309 !(mLoadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
8310 mLoadInfo->GetExternalContentPolicyType() !=
8311 ExtContentPolicy::TYPE_DOCUMENT) &&
8312 dnsStrategy == nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN &&
8313 !mConnectionInfo->UsingConnect() && canUseHTTPSRRonNetwork(trrEnabled) &&
8314 StaticPrefs::network_dns_use_https_rr_as_altsvc();
8315 if (!httpsRRAllowed) {
8316 DisallowHTTPSRR(mCaps);
8317 } else if (trrEnabled) {
8318 if (nsIRequest::GetTRRMode() != nsIRequest::TRR_DISABLED_MODE) {
8319 mCaps |= NS_HTTP_FORCE_WAIT_HTTP_RR(1 << 22);
8320 }
8321 }
8322
8323 auto canUseHappyEyeballs = [&]() {
8324 if (!StaticPrefs::network_http_happy_eyeballs_enabled()) {
8325 return false;
8326 }
8327
8328 if (LoadBeConservative() || (mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11))) {
8329 return false;
8330 }
8331
8332 if (mProxyInfo &&
8333 !StaticPrefs::network_http_happy_eyeballs_proxy_enabled()) {
8334 return false;
8335 }
8336
8337 // WebSocket and WebTransport upgrades share the same rollout pref.
8338 if ((mUpgradeProtocolCallback || mWebTransportSessionEventListener) &&
8339 !StaticPrefs::network_http_happy_eyeballs_upgrade_enabled()) {
8340 return false;
8341 }
8342
8343 // Connect-only needs the extended-CONNECT tunnel path, which Happy
8344 // Eyeballs does not establish yet.
8345 if (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) {
8346 return false;
8347 }
8348
8349 return true;
8350 };
8351
8352 if (canUseHappyEyeballs()) {
8353 LOG(("%p NS_HTTP_USE_HAPPY_EYEBALLS ", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "%p NS_HTTP_USE_HAPPY_EYEBALLS ", this); } } while (0)
;
8354 mCaps |= NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30);
8355 mCaps &= ~NS_HTTP_FORCE_WAIT_HTTP_RR(1 << 22);
8356 mConnectionInfo =
8357 mConnectionInfo->Mutate().SetHappyEyeballsEnabled(true).Finalize();
8358 }
8359
8360 // No need to lookup HTTPSSVC record if mHTTPSSVCRecord already contains a
8361 // value.
8362 StoreUseHTTPSSVC(StaticPrefs::network_dns_upgrade_with_https_rr() &&
8363 httpsRRAllowed && mHTTPSSVCRecord.isNothing());
8364
8365 // Need to re-ask the handler, since mConnectionInfo may not be the connInfo
8366 // we used earlier
8367 if (!mConnectionInfo->IsHttp3() &&
8368 gHttpHandler->IsHttp2Excluded(mConnectionInfo)) {
8369 StoreAllowSpdy(0);
8370 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
8371 mConnectionInfo = mConnectionInfo->Mutate().SetNoSpdy(true).Finalize();
8372 }
8373
8374 // We can be passed with the auth provider if this channel was
8375 // a result of redirect due to auth retry
8376 if (!mAuthProvider) {
8377 mAuthProvider = new nsHttpChannelAuthProvider();
8378 }
8379
8380 rv = mAuthProvider->Init(this);
8381 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8382 return rv;
8383 }
8384
8385 // check to see if authorization headers should be included
8386 // CustomAuthHeader is set in AsyncOpen if we find Authorization header
8387 rv = mAuthProvider->AddAuthorizationHeaders(LoadCustomAuthHeader());
8388 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8389 LOG(("nsHttpChannel %p AddAuthorizationHeaders failed (%08x)", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p AddAuthorizationHeaders failed (%08x)", this
, static_cast<uint32_t>(rv)); } } while (0)
8390 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p AddAuthorizationHeaders failed (%08x)", this
, static_cast<uint32_t>(rv)); } } while (0)
;
8391 }
8392
8393 // if this somehow fails we can go on without it
8394 (void)gHttpHandler->AddConnectionHeader(&mRequestHead, mCaps);
8395
8396 if (!LoadIsTRRServiceChannel() &&
8397 ((mLoadFlags & LOAD_FRESH_CONNECTION) ||
8398 (!StaticPrefs::network_dns_only_refresh_on_fresh_connection() &&
8399 (mLoadFlags & VALIDATE_ALWAYS ||
8400 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
)))) {
8401 mCaps |= NS_HTTP_REFRESH_DNS(1 << 3);
8402 }
8403
8404 if (gHttpHandler->CriticalRequestPrioritization()) {
8405 if (mClassOfService.Flags() & nsIClassOfService::Leader) {
8406 mCaps |= NS_HTTP_LOAD_AS_BLOCKING(1 << 6);
8407 }
8408 if (mClassOfService.Flags() & nsIClassOfService::Unblocked) {
8409 mCaps |= NS_HTTP_LOAD_UNBLOCKED(1 << 8);
8410 }
8411 if (mClassOfService.Flags() & nsIClassOfService::UrgentStart &&
8412 gHttpHandler->IsUrgentStartEnabled()) {
8413 mCaps |= NS_HTTP_URGENT_START(1 << 12);
8414 SetPriority(nsISupportsPriority::PRIORITY_HIGHEST);
8415 }
8416 }
8417
8418 // Force-Reload should reset the persistent connection pool.
8419 if (mLoadFlags & LOAD_FRESH_CONNECTION) {
8420 // Only the initial document resets the pool, and only for connections
8421 // sharing this channel's origin attributes.
8422 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
8423 gHttpHandler->AltServiceCache()->ClearAltServiceMappingsMatchingOA(
8424 mConnectionInfo->GetOriginAttributes());
8425 rv = gHttpHandler->DoShiftReloadConnectionCleanupWithConnInfo(
8426 mConnectionInfo);
8427 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8428 LOG((do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::BeginConnect " "DoShiftReloadConnectionCleanupWithConnInfo failed: %08x [this=%p]"
, static_cast<uint32_t>(rv), this); } } while (0)
8429 "nsHttpChannel::BeginConnect "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::BeginConnect " "DoShiftReloadConnectionCleanupWithConnInfo failed: %08x [this=%p]"
, static_cast<uint32_t>(rv), this); } } while (0)
8430 "DoShiftReloadConnectionCleanupWithConnInfo failed: %08x [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::BeginConnect " "DoShiftReloadConnectionCleanupWithConnInfo failed: %08x [this=%p]"
, static_cast<uint32_t>(rv), this); } } while (0)
8431 static_cast<uint32_t>(rv), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::BeginConnect " "DoShiftReloadConnectionCleanupWithConnInfo failed: %08x [this=%p]"
, static_cast<uint32_t>(rv), this); } } while (0)
;
8432 }
8433 }
8434 }
8435
8436 // We may have been cancelled already, either by on-modify-request
8437 // listeners or load group observers; in that case, we should not send the
8438 // request to the server
8439 if (mCanceled) {
8440 return mStatus;
8441 }
8442 // skip classifier checks if this channel was the result of internal auth
8443 // redirect
8444 bool shouldBeClassifiedForTracker =
8445 NS_ShouldClassifyChannel(this, ClassifyType::ETP);
8446
8447 if (shouldBeClassifiedForTracker) {
8448 if (LoadChannelClassifierCancellationPending()) {
8449 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting for safe-browsing protection cancellation in BeginConnect "
"[this=%p]\n", this); } } while (0)
8450 ("Waiting for safe-browsing protection cancellation in BeginConnect "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting for safe-browsing protection cancellation in BeginConnect "
"[this=%p]\n", this); } } while (0)
8451 "[this=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting for safe-browsing protection cancellation in BeginConnect "
"[this=%p]\n", this); } } while (0)
8452 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting for safe-browsing protection cancellation in BeginConnect "
"[this=%p]\n", this); } } while (0)
;
8453 return NS_OK;
8454 }
8455
8456 ReEvaluateReferrerAfterTrackingStatusIsKnown();
8457 }
8458
8459 MaybeStartDNSPrefetch();
8460
8461 // Update whether the channel is on the third-party cookie blocking exception
8462 // list.
8463 CookieService::Update3PCBExceptionInfo(this);
8464
8465 rv = CallOrWaitForResume(
8466 [](nsHttpChannel* self) { return self->PrepareToConnect(); });
8467 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8468 return rv;
8469 }
8470
8471 bool shouldBeClassifiedForSafeBrowsing =
8472 NS_ShouldClassifyChannel(this, ClassifyType::SafeBrowsing);
8473
8474 if (shouldBeClassifiedForTracker) {
8475 PrimeSuspendAfterExamineResponse();
8476 RefPtr<nsHttpChannel> self(this);
8477 nsresult rv =
8478 AntiTrackingChannelClassifierUtils::CheckChannelBeforeProcessResponse(
8479 this,
8480 [self]() { self->CancelSuspendOrResumeAfterExamineResponse(); });
8481 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8482 CancelSuspendOrResumeAfterExamineResponse();
8483 }
8484 }
8485
8486 if (shouldBeClassifiedForSafeBrowsing) {
8487 // Start nsChannelClassifier to catch phishing and malware URIs.
8488 RefPtr<nsChannelClassifier> channelClassifier =
8489 GetOrCreateChannelClassifier();
8490 LOG(("nsHttpChannel::Starting nsChannelClassifier %p [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Starting nsChannelClassifier %p [this=%p]",
channelClassifier.get(), this); } } while (0)
8491 channelClassifier.get(), this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::Starting nsChannelClassifier %p [this=%p]",
channelClassifier.get(), this); } } while (0)
;
8492 channelClassifier->Start();
8493 }
8494
8495 return NS_OK;
8496}
8497
8498void nsHttpChannel::MaybeStartDNSPrefetch() {
8499 // Start a DNS lookup very early in case the real open is queued the DNS can
8500 // happen in parallel. Do not do so in the presence of an HTTP proxy as
8501 // all lookups other than for the proxy itself are done by the proxy.
8502 // Also we don't do a lookup if the LOAD_NO_NETWORK_IO or
8503 // LOAD_ONLY_FROM_CACHE flags are set.
8504 //
8505 // We keep the DNS prefetch object around so that we can retrieve
8506 // timing information from it. There is no guarantee that we actually
8507 // use the DNS prefetch data for the real connection, but as we keep
8508 // this data around for 3 minutes by default, this should almost always
8509 // be correct, and even when it isn't, the timing still represents _a_
8510 // valid DNS lookup timing for the site, even if it is not _the_
8511 // timing we used.
8512 if (mDNSPrefetch) {
8513 return;
8514 }
8515 if ((mLoadFlags & (LOAD_NO_NETWORK_IO | LOAD_ONLY_FROM_CACHE)) ||
8516 LoadAuthRedirectedChannel()) {
8517 return;
8518 }
8519
8520 auto dnsStrategy = ComputeProxyDNSStrategy();
8521
8522 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeStartDNSPrefetch [this=%p, strategy=%u] "
"prefetching%s\n", this, static_cast<uint32_t>(dnsStrategy
), mCaps & (1 << 3) ? ", refresh requested" : ""); }
} while (0)
8523 ("nsHttpChannel::MaybeStartDNSPrefetch [this=%p, strategy=%u] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeStartDNSPrefetch [this=%p, strategy=%u] "
"prefetching%s\n", this, static_cast<uint32_t>(dnsStrategy
), mCaps & (1 << 3) ? ", refresh requested" : ""); }
} while (0)
8524 "prefetching%s\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeStartDNSPrefetch [this=%p, strategy=%u] "
"prefetching%s\n", this, static_cast<uint32_t>(dnsStrategy
), mCaps & (1 << 3) ? ", refresh requested" : ""); }
} while (0)
8525 this, static_cast<uint32_t>(dnsStrategy),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeStartDNSPrefetch [this=%p, strategy=%u] "
"prefetching%s\n", this, static_cast<uint32_t>(dnsStrategy
), mCaps & (1 << 3) ? ", refresh requested" : ""); }
} while (0)
8526 mCaps & NS_HTTP_REFRESH_DNS ? ", refresh requested" : ""))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeStartDNSPrefetch [this=%p, strategy=%u] "
"prefetching%s\n", this, static_cast<uint32_t>(dnsStrategy
), mCaps & (1 << 3) ? ", refresh requested" : ""); }
} while (0)
;
8527
8528 if (dnsStrategy == nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN) {
8529 OriginAttributes originAttributes;
8530 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
8531 this, originAttributes);
8532
8533 mDNSPrefetch = new nsDNSPrefetch(mURI, originAttributes,
8534 nsIRequest::GetTRRMode(), this, true);
8535 nsIDNSService::DNSFlags dnsFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS;
8536 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
8537 dnsFlags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
8538 }
8539
8540 bool unused;
8541 if (StaticPrefs::network_dns_use_https_rr_as_altsvc() && !mHTTPSSVCRecord &&
8542 !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) &&
8543 canUseHTTPSRRonNetwork(unused)) {
8544 (void)mDNSPrefetch->FetchHTTPSSVC(mCaps & NS_HTTP_REFRESH_DNS(1 << 3), true,
8545 [](nsIDNSHTTPSSVCRecord*) {
8546 // Do nothing. This is a DNS prefetch.
8547 });
8548 }
8549
8550 if (StaticPrefs::network_http_happy_eyeballs_enabled()) {
8551 // Happy Eyeballs connects per-family, so issue per-family prefetches
8552 // (A and AAAA) that it can reuse instead of starting its own lookups.
8553 // Skip a family that won't be queried; with IPv6 disabled the AAAA
8554 // request collapses to A, so skip it to avoid a duplicate.
8555 bool skipIPv4 = mCaps & NS_HTTP_DISABLE_IPV4(1 << 17);
8556 bool skipIPv6 = (mCaps & NS_HTTP_DISABLE_IPV6(1 << 18)) ||
8557 StaticPrefs::network_dns_disableIPv6();
8558 (void)mDNSPrefetch->PrefetchHighPerFamily(dnsFlags, skipIPv4, skipIPv6);
8559 } else {
8560 if (mCaps & NS_HTTP_DISABLE_IPV4(1 << 17)) {
8561 dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV4;
8562 } else if (mCaps & NS_HTTP_DISABLE_IPV6(1 << 18)) {
8563 dnsFlags |= nsIDNSService::RESOLVE_DISABLE_IPV6;
8564 }
8565 (void)mDNSPrefetch->PrefetchHigh(dnsFlags);
8566 }
8567 }
8568}
8569
8570bool nsHttpChannel::IsForcedOffline() const {
8571 RefPtr<mozilla::dom::BrowsingContext> bc;
8572 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
8573 if (!bc) {
8574 // Loads that are not performed by a window, such as keepalive fetches
8575 // handled by the FetchService and fetches from workers, only record the
8576 // browsing context they are associated with.
8577 mLoadInfo->GetAssociatedBrowsingContext(getter_AddRefs(bc));
8578 }
8579 return bc && bc->Top()->GetForceOffline();
8580}
8581
8582NS_IMETHODIMPnsresult
8583nsHttpChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) {
8584 if (mCacheEntry && !LoadCacheEntryIsWriteOnly()) {
8585 int64_t dataSize = 0;
8586 mCacheEntry->GetDataSize(&dataSize);
8587 *aEncodedBodySize = dataSize;
8588 } else {
8589 *aEncodedBodySize = mLogicalOffset;
8590 }
8591 return NS_OK;
8592}
8593
8594NS_IMETHODIMPnsresult
8595nsHttpChannel::GetDecompressDictionary(DictionaryCacheEntry** aDictionary) {
8596 *aDictionary = do_AddRef(mDictDecompress).take();
8597 return NS_OK;
8598}
8599
8600NS_IMETHODIMPnsresult
8601nsHttpChannel::SetDecompressDictionary(DictionaryCacheEntry* aDictionary) {
8602 if (!aDictionary) {
8603 if (mDictDecompress && mUsingDictionary) {
8604 mDictDecompress->UseCompleted();
8605 }
8606 mUsingDictionary = false;
8607 } else {
8608 MOZ_ASSERT(!mDictDecompress)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mDictDecompress)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mDictDecompress))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mDictDecompress"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 8608
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDictDecompress"
")"); do { MOZ_CrashSequence(__null, 8608); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8609 aDictionary->InUse();
8610 mUsingDictionary = true;
8611 }
8612 mDictDecompress = aDictionary;
8613 return NS_OK;
8614}
8615
8616//-----------------------------------------------------------------------------
8617// nsHttpChannel::nsIHttpChannelInternal
8618//-----------------------------------------------------------------------------
8619
8620NS_IMETHODIMPnsresult
8621nsHttpChannel::GetIsAuthChannel(bool* aIsAuthChannel) {
8622 *aIsAuthChannel = mIsAuthChannel;
8623 return NS_OK;
8624}
8625
8626NS_IMETHODIMPnsresult
8627nsHttpChannel::SetChannelIsForDownload(bool aChannelIsForDownload) {
8628 if (aChannelIsForDownload) {
8629 AddClassFlags(nsIClassOfService::Throttleable);
8630 } else {
8631 ClearClassFlags(nsIClassOfService::Throttleable);
8632 }
8633
8634 return HttpBaseChannel::SetChannelIsForDownload(aChannelIsForDownload);
8635}
8636
8637base::ProcessId nsHttpChannel::ProcessId() {
8638 nsCOMPtr<nsIParentChannel> parentChannel;
8639 NS_QueryNotificationCallbacks(this, parentChannel);
8640 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
8641 return httpParent->OtherPid();
8642 }
8643 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
8644 return docParent->OtherPid();
8645 }
8646 return base::GetCurrentProcId();
8647}
8648
8649auto nsHttpChannel::AttachStreamFilter() -> RefPtr<ChildEndpointPromise> {
8650 LOG(("nsHttpChannel::AttachStreamFilter [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::AttachStreamFilter [this=%p]", this); } } while
(0)
;
8651 MOZ_ASSERT(!LoadOnStartRequestCalled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 8651
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 8651); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8652
8653 if (!ProcessId()) {
8654 return ChildEndpointPromise::CreateAndReject(false, __func__);
8655 }
8656
8657 nsCOMPtr<nsIParentChannel> parentChannel;
8658 NS_QueryNotificationCallbacks(this, parentChannel);
8659
8660 // If our listener is a DocumentLoadListener, then we might handle
8661 // multi-part responses here in the parent process. The current extension
8662 // API doesn't understand the parsed multipart format, so we defer responding
8663 // here until CallOnStartRequest, and attach the StreamFilter before the
8664 // multipart handler (in the parent process!) if applicable.
8665 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
8666 StreamFilterRequest* request = mStreamFilterRequests.AppendElement();
8667 request->mPromise = new ChildEndpointPromise::Private(__func__);
8668 return request->mPromise;
8669 }
8670
8671 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
8672 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
8673 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
8674 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8675 return ChildEndpointPromise::CreateAndReject(false, __func__);
8676 }
8677
8678 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
8679 return httpParent->AttachStreamFilter(std::move(parent), std::move(child));
8680 }
8681
8682 extensions::StreamFilterParent::Attach(this, std::move(parent));
8683 return ChildEndpointPromise::CreateAndResolve(std::move(child), __func__);
8684}
8685
8686NS_IMETHODIMPnsresult
8687nsHttpChannel::GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) {
8688 LOG(("nsHttpChannel::GetNavigationStartTimeStamp [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::GetNavigationStartTimeStamp [this=%p]", this
); } } while (0)
;
8689 MOZ_ASSERT(aTimeStamp)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTimeStamp)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTimeStamp))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aTimeStamp", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 8689); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimeStamp"
")"); do { MOZ_CrashSequence(__null, 8689); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8690 *aTimeStamp = mNavigationStartTimeStamp;
8691 return NS_OK;
8692}
8693
8694NS_IMETHODIMPnsresult
8695nsHttpChannel::SetNavigationStartTimeStamp(TimeStamp aTimeStamp) {
8696 LOG(("nsHttpChannel::SetNavigationStartTimeStamp [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetNavigationStartTimeStamp [this=%p]", this
); } } while (0)
;
8697 mNavigationStartTimeStamp = aTimeStamp;
8698 return NS_OK;
8699}
8700
8701//-----------------------------------------------------------------------------
8702// nsHttpChannel::nsISupportsPriority
8703//-----------------------------------------------------------------------------
8704
8705NS_IMETHODIMPnsresult
8706nsHttpChannel::SetPriority(int32_t value) {
8707 int16_t newValue = std::clamp<int32_t>(value, INT16_MIN(-32767-1), INT16_MAX(32767));
8708 if (mPriority == newValue) return NS_OK;
8709
8710 LOG(("nsHttpChannel::SetPriority %p p=%d", this, newValue))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetPriority %p p=%d", this, newValue); } } while
(0)
;
8711
8712 mPriority = newValue;
8713 if (mTransaction) {
8714 nsresult rv = gHttpHandler->RescheduleTransaction(mTransaction, mPriority);
8715 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8716 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetPriority [this=%p] " "RescheduleTransaction failed (%08x)"
, this, static_cast<uint32_t>(rv)); } } while (0)
8717 ("nsHttpChannel::SetPriority [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetPriority [this=%p] " "RescheduleTransaction failed (%08x)"
, this, static_cast<uint32_t>(rv)); } } while (0)
8718 "RescheduleTransaction failed (%08x)",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetPriority [this=%p] " "RescheduleTransaction failed (%08x)"
, this, static_cast<uint32_t>(rv)); } } while (0)
8719 this, static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetPriority [this=%p] " "RescheduleTransaction failed (%08x)"
, this, static_cast<uint32_t>(rv)); } } while (0)
;
8720 }
8721 }
8722
8723 // If this channel is the real channel for an e10s channel, notify the
8724 // child side about the priority change as well.
8725 nsCOMPtr<nsIParentChannel> parentChannel;
8726 NS_QueryNotificationCallbacks(this, parentChannel);
8727 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
8728 if (httpParent) {
8729 httpParent->DoSendSetPriority(newValue);
8730 }
8731
8732 return NS_OK;
8733}
8734
8735//-----------------------------------------------------------------------------
8736// HttpChannel::nsIClassOfService
8737//-----------------------------------------------------------------------------
8738
8739void nsHttpChannel::OnClassOfServiceUpdated() {
8740 LOG(("nsHttpChannel::OnClassOfServiceUpdated this=%p, cos=%lu, inc=%d", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnClassOfServiceUpdated this=%p, cos=%lu, inc=%d"
, this, mClassOfService.Flags(), mClassOfService.Incremental(
)); } } while (0)
8741 mClassOfService.Flags(), mClassOfService.Incremental()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnClassOfServiceUpdated this=%p, cos=%lu, inc=%d"
, this, mClassOfService.Flags(), mClassOfService.Incremental(
)); } } while (0)
;
8742
8743 if (mTransaction) {
8744 gHttpHandler->UpdateClassOfServiceOnTransaction(mTransaction,
8745 mClassOfService);
8746 }
8747 if (EligibleForTailing()) {
8748 RemoveAsNonTailRequest();
8749 } else {
8750 AddAsNonTailRequest();
8751 }
8752}
8753
8754NS_IMETHODIMPnsresult
8755nsHttpChannel::SetClassFlags(uint32_t inFlags) {
8756 uint32_t previous = mClassOfService.Flags();
8757 mClassOfService.SetFlags(inFlags);
8758 if (previous != mClassOfService.Flags()) {
8759 OnClassOfServiceUpdated();
8760 }
8761 return NS_OK;
8762}
8763
8764NS_IMETHODIMPnsresult
8765nsHttpChannel::AddClassFlags(uint32_t inFlags) {
8766 uint32_t previous = mClassOfService.Flags();
8767 mClassOfService.SetFlags(inFlags | mClassOfService.Flags());
8768 if (previous != mClassOfService.Flags()) {
8769 OnClassOfServiceUpdated();
8770 }
8771 return NS_OK;
8772}
8773
8774NS_IMETHODIMPnsresult
8775nsHttpChannel::ClearClassFlags(uint32_t inFlags) {
8776 uint32_t previous = mClassOfService.Flags();
8777 mClassOfService.SetFlags(~inFlags & mClassOfService.Flags());
8778 if (previous != mClassOfService.Flags()) {
8779 OnClassOfServiceUpdated();
8780 }
8781 return NS_OK;
8782}
8783
8784NS_IMETHODIMPnsresult
8785nsHttpChannel::SetClassOfService(ClassOfService cos) {
8786 ClassOfService previous = mClassOfService;
8787 mClassOfService = cos;
8788 if (previous != mClassOfService) {
8789 OnClassOfServiceUpdated();
8790 }
8791 return NS_OK;
8792}
8793
8794NS_IMETHODIMPnsresult
8795nsHttpChannel::SetIncremental(bool incremental) {
8796 bool previous = mClassOfService.Incremental();
8797 mClassOfService.SetIncremental(incremental);
8798 if (previous != mClassOfService.Incremental()) {
8799 OnClassOfServiceUpdated();
8800 }
8801 return NS_OK;
8802}
8803
8804//-----------------------------------------------------------------------------
8805// nsHttpChannel::nsIProtocolProxyCallback
8806//-----------------------------------------------------------------------------
8807
8808NS_IMETHODIMPnsresult
8809nsHttpChannel::OnProxyAvailable(nsICancelable* request, nsIChannel* channel,
8810 nsIProxyInfo* pi, nsresult status) {
8811 LOG(("nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%" "x"
" mStatus=%" "x" "]\n", this, pi, static_cast<uint32_t>
(status), static_cast<uint32_t>(static_cast<nsresult
>(mStatus))); } } while (0)
8812 " mStatus=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%" "x"
" mStatus=%" "x" "]\n", this, pi, static_cast<uint32_t>
(status), static_cast<uint32_t>(static_cast<nsresult
>(mStatus))); } } while (0)
8813 this, pi, static_cast<uint32_t>(status),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%" "x"
" mStatus=%" "x" "]\n", this, pi, static_cast<uint32_t>
(status), static_cast<uint32_t>(static_cast<nsresult
>(mStatus))); } } while (0)
8814 static_cast<uint32_t>(static_cast<nsresult>(mStatus))))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%" "x"
" mStatus=%" "x" "]\n", this, pi, static_cast<uint32_t>
(status), static_cast<uint32_t>(static_cast<nsresult
>(mStatus))); } } while (0)
;
8815 mProxyRequest = nullptr;
8816
8817 nsresult rv;
8818
8819 // If status is a failure code, then it means that we failed to resolve
8820 // proxy info. That is a non-fatal error assuming it wasn't because the
8821 // request was canceled. We just failover to DIRECT when proxy resolution
8822 // fails (failure can mean that the PAC URL could not be loaded).
8823
8824 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
8825 mProxyInfo = pi;
8826
8827 if (mProxyInfo) {
8828 nsAutoCStringN<8> type;
8829 mProxyInfo->GetType(type);
8830 uint32_t flags = 0;
8831 mProxyInfo->GetFlags(&flags);
8832
8833 if (type.EqualsLiteral("socks")) {
8834 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
8835 glean::networking::proxy_info_type
8836 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5h)
8837 .Add(1);
8838 } else {
8839 glean::networking::proxy_info_type
8840 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5)
8841 .Add(1);
8842 }
8843 } else if (type.EqualsLiteral("socks4")) {
8844 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
8845 glean::networking::proxy_info_type
8846 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4a)
8847 .Add(1);
8848 } else {
8849 glean::networking::proxy_info_type
8850 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4)
8851 .Add(1);
8852 }
8853 } else if (type.EqualsLiteral("http")) {
8854 glean::networking::proxy_info_type
8855 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttp)
8856 .Add(1);
8857 } else if (type.EqualsLiteral("https")) {
8858 glean::networking::proxy_info_type
8859 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttps)
8860 .Add(1);
8861 } else if (type.EqualsLiteral("direct")) {
8862 glean::networking::proxy_info_type
8863 .EnumGet(glean::networking::ProxyInfoTypeLabel::eDirect)
8864 .Add(1);
8865 } else {
8866 glean::networking::proxy_info_type
8867 .EnumGet(glean::networking::ProxyInfoTypeLabel::eUnknown)
8868 .Add(1);
8869 }
8870 }
8871 }
8872
8873 if (!gHttpHandler->Active()) {
8874 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnProxyAvailable [this=%p] " "Handler no longer active.\n"
, this); } } while (0)
8875 ("nsHttpChannel::OnProxyAvailable [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnProxyAvailable [this=%p] " "Handler no longer active.\n"
, this); } } while (0)
8876 "Handler no longer active.\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnProxyAvailable [this=%p] " "Handler no longer active.\n"
, this); } } while (0)
8877 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnProxyAvailable [this=%p] " "Handler no longer active.\n"
, this); } } while (0)
;
8878 rv = NS_ERROR_NOT_AVAILABLE;
8879 } else {
8880 rv = BeginConnect();
8881 }
8882
8883 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8884 CloseCacheEntry(false);
8885 (void)AsyncAbort(rv);
8886 }
8887 return rv;
8888}
8889
8890//-----------------------------------------------------------------------------
8891// nsHttpChannel::nsIProxiedChannel
8892//-----------------------------------------------------------------------------
8893
8894NS_IMETHODIMPnsresult
8895nsHttpChannel::GetProxyInfo(nsIProxyInfo** result) {
8896 if (!mConnectionInfo) {
8897 *result = do_AddRef(mProxyInfo).take();
8898 } else {
8899 *result = do_AddRef(mConnectionInfo->ProxyInfo()).take();
8900 }
8901 return NS_OK;
8902}
8903
8904//-----------------------------------------------------------------------------
8905// nsHttpChannel::nsITimedChannel
8906//-----------------------------------------------------------------------------
8907
8908NS_IMETHODIMPnsresult
8909nsHttpChannel::GetDomainLookupStart(TimeStamp* _retval) {
8910 if (mTransaction) {
8911 *_retval = mTransaction->GetDomainLookupStart();
8912 } else {
8913 *_retval = mTransactionTimings.domainLookupStart;
8914 }
8915 return NS_OK;
8916}
8917
8918NS_IMETHODIMPnsresult
8919nsHttpChannel::GetDomainLookupEnd(TimeStamp* _retval) {
8920 if (mTransaction) {
8921 *_retval = mTransaction->GetDomainLookupEnd();
8922 } else {
8923 *_retval = mTransactionTimings.domainLookupEnd;
8924 }
8925 return NS_OK;
8926}
8927
8928NS_IMETHODIMPnsresult
8929nsHttpChannel::GetConnectStart(TimeStamp* _retval) {
8930 if (mTransaction) {
8931 *_retval = mTransaction->GetConnectStart();
8932 } else {
8933 *_retval = mTransactionTimings.connectStart;
8934 }
8935 return NS_OK;
8936}
8937
8938NS_IMETHODIMPnsresult
8939nsHttpChannel::GetTcpConnectEnd(TimeStamp* _retval) {
8940 if (mTransaction) {
8941 *_retval = mTransaction->GetTcpConnectEnd();
8942 } else {
8943 *_retval = mTransactionTimings.tcpConnectEnd;
8944 }
8945 return NS_OK;
8946}
8947
8948NS_IMETHODIMPnsresult
8949nsHttpChannel::GetSecureConnectionStart(TimeStamp* _retval) {
8950 if (mTransaction) {
8951 *_retval = mTransaction->GetSecureConnectionStart();
8952 } else {
8953 *_retval = mTransactionTimings.secureConnectionStart;
8954 }
8955 return NS_OK;
8956}
8957
8958NS_IMETHODIMPnsresult
8959nsHttpChannel::GetConnectEnd(TimeStamp* _retval) {
8960 if (mTransaction) {
8961 *_retval = mTransaction->GetConnectEnd();
8962 } else {
8963 *_retval = mTransactionTimings.connectEnd;
8964 }
8965 return NS_OK;
8966}
8967
8968NS_IMETHODIMPnsresult
8969nsHttpChannel::GetRequestStart(TimeStamp* _retval) {
8970 if (mTransaction) {
8971 *_retval = mTransaction->GetRequestStart();
8972 } else {
8973 *_retval = mTransactionTimings.requestStart;
8974 }
8975 return NS_OK;
8976}
8977
8978NS_IMETHODIMPnsresult
8979nsHttpChannel::GetResponseStart(TimeStamp* _retval) {
8980 if (mTransaction) {
8981 *_retval = mTransaction->GetResponseStart();
8982 } else {
8983 *_retval = mTransactionTimings.responseStart;
8984 }
8985 return NS_OK;
8986}
8987
8988NS_IMETHODIMPnsresult
8989nsHttpChannel::GetFirstInterimResponseStart(TimeStamp* _retval) {
8990 if (mTransaction) {
8991 *_retval = mTransaction->GetFirstInterimResponseStart();
8992 } else {
8993 *_retval = mTransactionTimings.firstInterimResponseStart;
8994 }
8995 return NS_OK;
8996}
8997
8998NS_IMETHODIMPnsresult
8999nsHttpChannel::GetFinalResponseHeadersStart(TimeStamp* _retval) {
9000 if (mTransaction) {
9001 *_retval = mTransaction->GetFinalResponseHeadersStart();
9002 } else {
9003 *_retval = mTransactionTimings.finalResponseHeadersStart;
9004 }
9005 return NS_OK;
9006}
9007
9008NS_IMETHODIMPnsresult
9009nsHttpChannel::GetResponseEnd(TimeStamp* _retval) {
9010 if (mTransaction) {
9011 *_retval = mTransaction->GetResponseEnd();
9012 } else {
9013 *_retval = mTransactionTimings.responseEnd;
9014 }
9015 return NS_OK;
9016}
9017
9018NS_IMETHODIMPnsresult
9019nsHttpChannel::GetTransactionPending(TimeStamp* _retval) {
9020 if (mTransaction) {
9021 *_retval = mTransaction->GetPendingTime();
9022 } else {
9023 *_retval = mTransactionTimings.transactionPending;
9024 }
9025 return NS_OK;
9026}
9027
9028//-----------------------------------------------------------------------------
9029// nsHttpChannel::nsIHttpAuthenticableChannel
9030//-----------------------------------------------------------------------------
9031
9032NS_IMETHODIMPnsresult
9033nsHttpChannel::GetProxyMethodIsConnect(bool* aProxyMethodIsConnect) {
9034 *aProxyMethodIsConnect = mConnectionInfo->UsingConnect();
9035 return NS_OK;
9036}
9037
9038NS_IMETHODIMPnsresult
9039nsHttpChannel::GetServerResponseHeader(nsACString& value) {
9040 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
9041 return mResponseHead->GetHeader(nsHttp::Server, value);
9042}
9043
9044NS_IMETHODIMPnsresult
9045nsHttpChannel::GetProxyChallenges(nsACString& value) {
9046 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
9047 return mResponseHead->GetHeader(nsHttp::Proxy_Authenticate, value);
9048}
9049
9050NS_IMETHODIMPnsresult
9051nsHttpChannel::GetWWWChallenges(nsACString& value) {
9052 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
9053 return mResponseHead->GetHeader(nsHttp::WWW_Authenticate, value);
9054}
9055
9056NS_IMETHODIMPnsresult
9057nsHttpChannel::SetProxyCredentials(const nsACString& value) {
9058 return mRequestHead.SetHeader(nsHttp::Proxy_Authorization, value);
9059}
9060
9061NS_IMETHODIMPnsresult
9062nsHttpChannel::SetWWWCredentials(const nsACString& value) {
9063 // This method is called when various browser initiated authorization
9064 // code sets the credentials. We need to flag this header as the
9065 // "browser default" so it does not show up in the ServiceWorker
9066 // FetchEvent. This may actually get called more than once, though,
9067 // so we clear the header first since "default" headers are not
9068 // allowed to overwrite normally.
9069 (void)mRequestHead.ClearHeader(nsHttp::Authorization);
9070 return mRequestHead.SetHeader(nsHttp::Authorization, value, false,
9071 nsHttpHeaderArray::eVarietyRequestDefault);
9072}
9073
9074//-----------------------------------------------------------------------------
9075// Methods that nsIHttpAuthenticableChannel dupes from other IDLs, which we
9076// get from HttpBaseChannel, must be explicitly forwarded, because C++ sucks.
9077//-----------------------------------------------------------------------------
9078
9079NS_IMETHODIMPnsresult
9080nsHttpChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
9081 return HttpBaseChannel::GetLoadFlags(aLoadFlags);
9082}
9083
9084NS_IMETHODIMPnsresult
9085nsHttpChannel::GetURI(nsIURI** aURI) { return HttpBaseChannel::GetURI(aURI); }
9086
9087NS_IMETHODIMPnsresult
9088nsHttpChannel::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks) {
9089 return HttpBaseChannel::GetNotificationCallbacks(aCallbacks);
9090}
9091
9092NS_IMETHODIMPnsresult
9093nsHttpChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
9094 return HttpBaseChannel::GetLoadGroup(aLoadGroup);
9095}
9096
9097NS_IMETHODIMPnsresult
9098nsHttpChannel::GetRequestMethod(nsACString& aMethod) {
9099 return HttpBaseChannel::GetRequestMethod(aMethod);
9100}
9101
9102//-----------------------------------------------------------------------------
9103// nsHttpChannel::nsIRequestObserver
9104//-----------------------------------------------------------------------------
9105
9106void nsHttpChannel::RecordOnStartTelemetry(nsresult aStatus,
9107 bool aIsNavigation) {
9108 glean::http::channel_onstart_success
9109 .EnumGet(static_cast<glean::http::ChannelOnstartSuccessLabel>(
9110 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))))
9111 .Add();
9112
9113 mozilla::glean::networking::http_channel_onstart_status
9114 .Get(NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) ? "successful"_ns : "fail"_ns)
9115 .Add(1);
9116
9117 if (mTransaction) {
9118 glean::networking::http3_channel_onstart_success
9119 .Get((mTransaction->IsHttp3Used()) ? "http3"_ns : "no_http3"_ns,
9120 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) ? "true"_ns : "false"_ns)
9121 .Add();
9122 }
9123
9124 enum class HttpOnStartState : uint32_t {
9125 Success = 0,
9126 DNSError = 1,
9127 Others = 2,
9128 };
9129
9130 if (TRRService::Get() && TRRService::Get()->IsConfirmed()) {
9131 HttpOnStartState state = HttpOnStartState::Others;
9132 if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
9133 state = HttpOnStartState::Success;
9134 } else if (aStatus == NS_ERROR_UNKNOWN_HOST ||
9135 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST) {
9136 state = HttpOnStartState::DNSError;
9137 }
9138
9139 if (aIsNavigation) {
9140 glean::http::channel_page_onstart_success_trr
9141 .Get(TRRService::ProviderKey())
9142 .AccumulateSingleSample(static_cast<uint32_t>(state));
9143 } else {
9144 glean::http::channel_sub_onstart_success_trr
9145 .Get(TRRService::ProviderKey())
9146 .AccumulateSingleSample(static_cast<uint32_t>(state));
9147 }
9148 }
9149
9150 mOnStartRequestStartTime = TimeStamp::Now();
9151}
9152
9153static bool hasConnectivity() {
9154 if (RefPtr<NetworkConnectivityService> ncs =
9155 NetworkConnectivityService::GetSingleton()) {
9156 nsINetworkConnectivityService::ConnectivityState state;
9157 if (NS_SUCCEEDED(ncs->GetIPv4(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetIPv4(&
state))), 1)))
&&
9158 state == nsINetworkConnectivityService::OK) {
9159 return true;
9160 }
9161 // We should also check for IPv6 connectivity here, but since
9162 // quite a few mozilla domains don't have IPv6 records yet,
9163 // we might incorrectly fallback to a backup domain on
9164 // IPv6 only networks.
9165 // When bug 1665605 gets fixed we can also return true when only IPv6 is OK.
9166 }
9167
9168 return false;
9169};
9170
9171static already_AddRefed<nsIURI> GetFallbackURI(nsIURI* aURI) {
9172 nsresult rv;
9173 nsAutoCString host;
9174 aURI->GetHost(host);
9175 nsCOMPtr<nsIURI> backupURI;
9176
9177 nsAutoCString fallbackDomain;
9178 if (!gIOService->GetFallbackDomain(host, fallbackDomain)) {
9179 return nullptr;
9180 }
9181
9182 rv = NS_MutateURI(aURI).SetHost(fallbackDomain).Finalize(backupURI);
9183 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9184 return nullptr;
9185 }
9186
9187 return backupURI.forget();
9188}
9189
9190// The essential domain fallback only targets Firefox's own internal requests
9191// Opening a link from browser UI or a priviledged page still carries the
9192// system principal so we need to exclude these regular pageloads.
9193static bool IsInternalSystemLoad(nsILoadInfo* aLoadInfo) {
9194 if (!aLoadInfo->TriggeringPrincipal()->IsSystemPrincipal()) {
9195 return false;
9196 }
9197
9198 ExtContentPolicyType type = aLoadInfo->GetExternalContentPolicyType();
9199 return type != ExtContentPolicy::TYPE_DOCUMENT &&
9200 type != ExtContentPolicy::TYPE_SUBDOCUMENT;
9201}
9202
9203// static
9204nsHttpChannel::EssentialDomainCategory
9205nsHttpChannel::GetEssentialDomainCategory(nsCString& domain) {
9206 if (StringEndsWith(domain, ".addons.mozilla.org"_ns)) {
9207 return EssentialDomainCategory::SubAddonsMozillaOrg;
9208 }
9209 if (domain == "addons.mozilla.org"_ns) {
9210 return EssentialDomainCategory::AddonsMozillaOrg;
9211 }
9212 if (domain == "aus5.mozilla.org"_ns) {
9213 return EssentialDomainCategory::Aus5MozillaOrg;
9214 }
9215 if (domain == "firefox.settings.services.mozilla.com"_ns ||
9216 domain == "firefox-settings-attachments.cdn.mozilla.net"_ns ||
9217 domain == "content-signature-2.cdn.mozilla.net"_ns) {
9218 return EssentialDomainCategory::RemoteSettings;
9219 }
9220 if (domain == "incoming.telemetry.mozilla.com"_ns) {
9221 return EssentialDomainCategory::Telemetry;
9222 }
9223 return EssentialDomainCategory::Other;
9224}
9225
9226// Helper function to send LNA access info to child process for console logging
9227// The child process has access to CallingScriptLocationString() which requires
9228// JS context
9229static void ReportLNAAccessToConsole(nsHttpChannel* aChannel,
9230 const char* aMessageName,
9231 const nsACString& aPromptAction = ""_ns) {
9232 // Send IPC to child process to log to console with script location
9233 nsCOMPtr<nsIParentChannel> parentChannel;
9234 NS_QueryNotificationCallbacks(aChannel, parentChannel);
9235 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
9236 NetAddr peerAddr = aChannel->GetPeerAddr();
9237
9238 // Fetch top-level site URI in parent process and pass via IPC.
9239 // We need to fetch this here because with Fission (site isolation),
9240 // cross-site iframes run in separate content processes and cannot
9241 // access the top-level document in a different process.
9242 nsAutoCString topLevelSite;
9243 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
9244 if (loadInfo) {
9245 RefPtr<mozilla::dom::BrowsingContext> bc;
9246 loadInfo->GetBrowsingContext(getter_AddRefs(bc));
9247 if (bc && bc->Top() && bc->Top()->Canonical()) {
9248 RefPtr<mozilla::dom::WindowGlobalParent> topWindowGlobal =
9249 bc->Top()->Canonical()->GetCurrentWindowGlobal();
9250 if (topWindowGlobal) {
9251 nsIPrincipal* topPrincipal = topWindowGlobal->DocumentPrincipal();
9252 if (topPrincipal) {
9253 nsCOMPtr<nsIURI> topURI = topPrincipal->GetURI();
9254 if (topURI) {
9255 (void)topURI->GetSpec(topLevelSite);
9256 }
9257 }
9258 }
9259 }
9260 }
9261
9262 httpParent->DoSendReportLNAToConsole(peerAddr, nsCString(aMessageName),
9263 nsCString(aPromptAction),
9264 topLevelSite);
9265 }
9266}
9267
9268nsresult nsHttpChannel::ProcessLNAActions() {
9269 if (!mTransaction) {
9270 return NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED;
9271 }
9272
9273 // Suspend to block any notification to the channel.
9274 // This will get resumed in
9275 // nsHttpChannel::OnPermissionPromptResult
9276 UpdateCurrentIpAddressSpace();
9277 mWaitingForLNAPermission = true;
9278 Suspend();
9279 auto targetAddressSpace = mTransaction->GetTargetIPAddressSpace();
9280 auto permissionKey = targetAddressSpace == nsILoadInfo::IPAddressSpace::Local
9281 ? LOOPBACK_NETWORK_PERMISSION_KEY
9282 : LOCAL_NETWORK_PERMISSION_KEY;
9283 LNAPermission permissionUpdateResult =
9284 UpdateLocalNetworkAccessPermissions(permissionKey);
9285
9286 if (LNAPermission::Granted == permissionUpdateResult) {
9287 // permission granted (auto-allow via permanent permission)
9288 mLNAPromptAction.AssignLiteral("auto_allow");
9289 return OnPermissionPromptResult(true, permissionKey);
9290 }
9291
9292 if (LNAPermission::Denied == permissionUpdateResult) {
9293 // permission denied (auto-deny via permanent permission)
9294 mLNAPromptAction.AssignLiteral("auto_deny");
9295 return OnPermissionPromptResult(false, permissionKey);
9296 }
9297
9298 // If we get here, we don't have any permission to access the local
9299 // host/network. We need to prompt the user for action
9300 auto permissionPromptCallback =
9301 [self = RefPtr{this}](bool aPermissionGranted, const nsACString& aType,
9302 bool aPromptShown) -> void {
9303 // Set mLNAPromptAction based on whether prompt was shown and user response
9304 if (aPromptShown) {
9305 if (aPermissionGranted) {
9306 self->mLNAPromptAction.AssignLiteral("prompt_allow");
9307 } else {
9308 self->mLNAPromptAction.AssignLiteral("prompt_deny");
9309 }
9310 } else {
9311 if (aPermissionGranted) {
9312 self->mLNAPromptAction.AssignLiteral("auto_allow");
9313 } else {
9314 self->mLNAPromptAction.AssignLiteral("auto_deny");
9315 }
9316 }
9317 self->OnPermissionPromptResult(aPermissionGranted, aType);
9318 };
9319
9320 RefPtr<LNAPermissionRequest> request = new LNAPermissionRequest(
9321 std::move(permissionPromptCallback), mLoadInfo, permissionKey);
9322
9323 // Log to console before requesting permission
9324 ReportLNAAccessToConsole(this, "LocalNetworkAccessPermissionRequired");
9325
9326 // This invokes callback nsHttpChannel::OnPermissionPromptResult
9327 // synchronously if the permission is already granted or denied
9328 // if permission is not available we prompt the user and in that case
9329 // nsHttpChannel::OnPermissionPromptResult is invoked asynchronously once
9330 // the user responds to the prompt
9331 return request->RequestPermission();
9332}
9333
9334void nsHttpChannel::UpdateCurrentIpAddressSpace() {
9335 if (!mTransaction) {
9336 return;
9337 }
9338
9339 if (mPeerAddr.GetIpAddressSpace() == nsILoadInfo::IPAddressSpace::Unknown) {
9340 // fetch peer address from transaction
9341 bool isTrr;
9342 bool echConfigUsed;
9343 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
9344 mEffectiveTRRMode, mTRRSkipReason,
9345 echConfigUsed);
9346 }
9347
9348 nsILoadInfo::IPAddressSpace docAddressSpace = mPeerAddr.GetIpAddressSpace();
9349 mLoadInfo->SetIpAddressSpace(docAddressSpace);
9350 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
9351 if (type == ExtContentPolicy::TYPE_DOCUMENT ||
9352 type == ExtContentPolicy::TYPE_SUBDOCUMENT) {
9353 RefPtr<mozilla::dom::BrowsingContext> bc;
9354 mLoadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
9355 if (bc) {
9356 bc->SetCurrentIPAddressSpace(docAddressSpace);
9357 }
9358
9359 if (mCacheEntry) {
9360 // store the ipaddr information into the cache metadata entry
9361 if (mPeerAddr.GetIpAddressSpace() !=
9362 nsILoadInfo::IPAddressSpace::Unknown) {
9363 uint16_t port;
9364 mPeerAddr.GetPort(&port);
9365 mCacheEntry->SetMetaDataElement("peer-ip-address",
9366 mPeerAddr.ToString().get());
9367 mCacheEntry->SetMetaDataElement("peer-port", ToString(port).c_str());
9368 }
9369 }
9370 }
9371}
9372
9373NS_IMETHODIMPnsresult
9374nsHttpChannel::OnStartRequest(nsIRequest* request) {
9375 nsresult rv;
9376
9377 MOZ_ASSERT(LoadRequestObserversCalled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadRequestObserversCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadRequestObserversCalled()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"LoadRequestObserversCalled()", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9377); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequestObserversCalled()"
")"); do { MOZ_CrashSequence(__null, 9377); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9378
9379 AUTO_PROFILER_LABEL("nsHttpChannel::OnStartRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject9379( "nsHttpChannel::OnStartRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
9380 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnStartRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject9381( "nsHttpChannel::OnStartRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
9381 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject9381( "nsHttpChannel::OnStartRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
9382
9383 if (!(mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))))) {
9384 // capture the request's status, so our consumers will know ASAP of any
9385 // connection failures, etc - bug 93581
9386 nsresult status;
9387 request->GetStatus(&status);
9388 mStatus = status;
9389 }
9390
9391 if (mStatus == NS_ERROR_NON_LOCAL_CONNECTION_REFUSED) {
9392 MOZ_DUMP_PROFILE_OR_CRASH_UNSAFE(nsPrintfCString(do { const nsCString _profileOrCrashReason(nsPrintfCString( "Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get())); profiler_request_dump_and_quit_for_test
(_profileOrCrashReason); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9398, _profileOrCrashReason.get()); } while (false)
9393 "Attempting to connect to non-local "do { const nsCString _profileOrCrashReason(nsPrintfCString( "Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get())); profiler_request_dump_and_quit_for_test
(_profileOrCrashReason); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9398, _profileOrCrashReason.get()); } while (false)
9394 "address! opener is [%s], uri is "do { const nsCString _profileOrCrashReason(nsPrintfCString( "Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get())); profiler_request_dump_and_quit_for_test
(_profileOrCrashReason); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9398, _profileOrCrashReason.get()); } while (false)
9395 "[%s]",do { const nsCString _profileOrCrashReason(nsPrintfCString( "Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get())); profiler_request_dump_and_quit_for_test
(_profileOrCrashReason); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9398, _profileOrCrashReason.get()); } while (false)
9396 mOpenerCallingScriptLocation ? mOpenerCallingScriptLocation->get()do { const nsCString _profileOrCrashReason(nsPrintfCString( "Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get())); profiler_request_dump_and_quit_for_test
(_profileOrCrashReason); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9398, _profileOrCrashReason.get()); } while (false)
9397 : "unknown",do { const nsCString _profileOrCrashReason(nsPrintfCString( "Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get())); profiler_request_dump_and_quit_for_test
(_profileOrCrashReason); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9398, _profileOrCrashReason.get()); } while (false)
9398 mURI->GetSpecOrDefault().get()))do { const nsCString _profileOrCrashReason(nsPrintfCString( "Attempting to connect to non-local "
"address! opener is [%s], uri is " "[%s]", mOpenerCallingScriptLocation
? mOpenerCallingScriptLocation->get() : "unknown", mURI->
GetSpecOrDefault().get())); profiler_request_dump_and_quit_for_test
(_profileOrCrashReason); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9398, _profileOrCrashReason.get()); } while (false)
;
9399 }
9400
9401 if (mStatus == NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED) {
9402 return ProcessLNAActions();
9403 }
9404
9405 LOG(("nsHttpChannel::OnStartRequest [this=%p request=%p status=%" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnStartRequest [this=%p request=%p status=%"
"x" "]\n", this, request, static_cast<uint32_t>(static_cast
<nsresult>(mStatus))); } } while (0)
9406 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnStartRequest [this=%p request=%p status=%"
"x" "]\n", this, request, static_cast<uint32_t>(static_cast
<nsresult>(mStatus))); } } while (0)
9407 this, request, static_cast<uint32_t>(static_cast<nsresult>(mStatus))))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnStartRequest [this=%p request=%p status=%"
"x" "]\n", this, request, static_cast<uint32_t>(static_cast
<nsresult>(mStatus))); } } while (0)
;
9408
9409 RecordOnStartTelemetry(mStatus, IsNavigation());
9410
9411 // Make sure things are what we expect them to be...
9412 MOZ_ASSERT(request == mCachePump || request == mTransactionPump,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(request == mCachePump || request == mTransactionPump
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(request == mCachePump || request == mTransactionPump
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"request == mCachePump || request == mTransactionPump" " (" "Unexpected request"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9413); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { MOZ_CrashSequence(__null
, 9413); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
9413 "Unexpected request")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(request == mCachePump || request == mTransactionPump
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(request == mCachePump || request == mTransactionPump
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"request == mCachePump || request == mTransactionPump" " (" "Unexpected request"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9413); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { MOZ_CrashSequence(__null
, 9413); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9414
9415 MOZ_ASSERT(!(mTransactionPump && mCachePump) ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial
() || LoadTransactionReplaced())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")"); do { MOZ_CrashSequence
(__null, 9419); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9416 LoadCachedContentIsPartial() || LoadTransactionReplaced(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial
() || LoadTransactionReplaced())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")"); do { MOZ_CrashSequence
(__null, 9419); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9417 "If we have both pumps, the cache content is partial, or the "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial
() || LoadTransactionReplaced())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")"); do { MOZ_CrashSequence
(__null, 9419); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9418 "cache entry was revalidated and OnStopRequest was not called "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial
() || LoadTransactionReplaced())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")"); do { MOZ_CrashSequence
(__null, 9419); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9419 "yet for the transaction pump.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial
() || LoadTransactionReplaced())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(mTransactionPump &&
mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
" (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9419); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mTransactionPump && mCachePump) || LoadCachedContentIsPartial() || LoadTransactionReplaced()"
") (" "If we have both pumps, the cache content is partial, or the "
"cache entry was revalidated and OnStopRequest was not called "
"yet for the transaction pump." ")"); do { MOZ_CrashSequence
(__null, 9419); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9420
9421 StoreAfterOnStartRequestBegun(true);
9422 if (mOnStartRequestTimestamp.IsNull()) {
9423 mOnStartRequestTimestamp = TimeStamp::Now();
9424 }
9425
9426 mozilla::glean::networking::http_onstart_suspend_total_time
9427 .AccumulateRawDuration(mSuspendTotalTime);
9428
9429 if (mTransaction) {
9430 mProxyConnectResponseHead = mTransaction->GetProxyConnectResponseHead();
9431
9432 if (!mSecurityInfo && !mCachePump) {
9433 // grab the security info from the connection object; the transaction
9434 // is guaranteed to own a reference to the connection.
9435 mSecurityInfo = mTransaction->SecurityInfo();
9436 }
9437
9438 uint32_t stage = mTransaction->HTTPSSVCReceivedStage();
9439 if (!LoadHTTPSSVCTelemetryReported() && stage != HTTPSSVC_NOT_USED) {
9440 glean::http::dns_httpssvc_record_receiving_stage.AccumulateSingleSample(
9441 stage);
9442 }
9443
9444 if (HTTPS_RR_IS_USED(stage)(stage > HTTPSSVC_NOT_PRESENT && stage < HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_2
)
) {
9445 nsAutoCString suffix(LoadEchConfigUsed() ? "_ech_used" : "");
9446 // Determine the result string based on the status.
9447 nsAutoCString result(NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) ? "success" : "failure");
9448 result.Append(suffix);
9449
9450 mozilla::glean::networking::http_channel_onstart_success_https_rr
9451 .Get(result)
9452 .Add(1);
9453 StoreHasHTTPSRR(true);
9454 }
9455
9456 bool isTrr;
9457 bool echConfigUsed;
9458 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
9459 mEffectiveTRRMode, mTRRSkipReason,
9460 echConfigUsed);
9461 // update IP AddressSpace for non-proxy connections and tests
9462 // We need to update the browsing context for tests as browser tests
9463 // uses local proxy to connect to
9464 // external domains
9465 if (!mProxyInfo || xpc::IsInAutomation()) {
9466 // If this is main document load or iframe store the IP Address space in
9467 // the browsing context
9468 UpdateCurrentIpAddressSpace();
9469 }
9470
9471 StoreResolvedByTRR(isTrr);
9472 StoreEchConfigUsed(echConfigUsed);
9473 } else { // !mTransaction
9474 MaybeUpdateDocumentIPAddressSpaceFromCache();
9475 }
9476
9477 if (!mCanceled && mTransaction && IsInternalSystemLoad(mLoadInfo)) {
9478 // We have to report telemetry before we actually attempt to redirect to
9479 // the fallback domain because doing so will change mStatus
9480 ReportSystemChannelTelemetry(mStatus);
9481 }
9482
9483 // don't enter this block if we're reading from the cache...
9484 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mCachePump && mTransaction) {
9485 // mTransactionPump doesn't hit OnInputStreamReady and call this until
9486 // all of the response headers have been acquired, so we can take
9487 // ownership of them from the transaction.
9488 RefPtr<nsHttpConnectionInfo> connInfo;
9489 mResponseHead =
9490 mTransaction->TakeResponseHeadAndConnInfo(getter_AddRefs(connInfo));
9491 mSupportsHTTP3 = mTransaction->GetSupportsHTTP3();
9492 // the response head may be null if the transaction was cancelled. in
9493 // which case we just need to call OnStartRequest/OnStopRequest.
9494 if (mResponseHead) {
9495 if (AntiTrackingUtils::ProcessStorageAccessHeadersShouldRetry(this)) {
9496 // force reload. Doom cache to avoid redirect loop
9497 if (mCacheEntry) {
9498 mCacheEntry->AsyncDoom(nullptr);
9499 }
9500
9501 auto storeAllowStorageAccess = [&](nsIChannel* aRedirectedChannel) {
9502 RefPtr<nsHttpChannel> httpChan = do_QueryObject(aRedirectedChannel);
9503 if (httpChan) {
9504 httpChan->StoreStorageAccessReloadChannel(true);
9505 }
9506 };
9507
9508 rv = StartRedirectChannelToURI(mURI,
9509 nsIChannelEventSink::REDIRECT_INTERNAL,
9510 storeAllowStorageAccess);
9511 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9512 Cancel(rv);
9513 return CallOnStartRequest();
9514 }
9515 return NS_OK;
9516 }
9517 return ProcessResponse(connInfo);
9518 }
9519
9520 NS_WARNING("No response head in OnStartRequest")NS_DebugBreak(NS_DEBUG_WARNING, "No response head in OnStartRequest"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9520)
;
9521 }
9522
9523 // cache file could be deleted on our behalf, it could contain errors or
9524 // it failed to allocate memory, reload from network here.
9525 if (mCacheEntry && mCachePump && RECOVER_FROM_CACHE_FILE_ERROR(mStatus)((mStatus) == NS_ERROR_FILE_NOT_FOUND || (mStatus) == NS_ERROR_FILE_CORRUPTED
|| (mStatus) == NS_ERROR_OUT_OF_MEMORY)
) {
9526 LOG((" cache file error, reloading from server"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache file error, reloading from server"); } } while (0)
;
9527 mCacheEntry->AsyncDoom(nullptr);
9528 rv =
9529 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
9530 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) return NS_OK;
9531 }
9532
9533 // If this is a system principal request to an essential domain, we are not
9534 // shutting down and we currently have connectivity, then check if there's a
9535 // fallback domain we can use to retry. If so we redirect to the fallback
9536 // domain.
9537 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) && !mCanceled && IsInternalSystemLoad(mLoadInfo) &&
9538 gHttpHandler->Active()) {
9539 if (StaticPrefs::network_essential_domains_fallback() &&
9540 hasConnectivity()) {
9541 auto passDomainCategory = [&](nsIChannel* aRedirectedChannel) {
9542 RefPtr<nsHttpChannel> httpChan = do_QueryObject(aRedirectedChannel);
9543 if (httpChan) {
9544 nsAutoCString host;
9545 mURI->GetHost(host);
9546 httpChan->mEssentialDomainCategory =
9547 Some(GetEssentialDomainCategory(host));
9548 }
9549 };
9550
9551 if (nsCOMPtr<nsIURI> fallbackURI = GetFallbackURI(mURI)) {
9552 PushRedirectAsyncFunc(
9553 &nsHttpChannel::ContinueOnStartRequestAfterFallback);
9554 rv = StartRedirectChannelToURI(fallbackURI,
9555 nsIChannelEventSink::REDIRECT_INTERNAL,
9556 passDomainCategory);
9557 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9558 nsCOMPtr<nsIObserverService> obsService =
9559 services::GetObserverService();
9560 if (obsService)
9561 obsService->NotifyObservers(static_cast<nsIHttpChannel*>(this),
9562 "httpchannel-fallback", nullptr);
9563 return NS_OK;
9564 }
9565 PopRedirectAsyncFunc(
9566 &nsHttpChannel::ContinueOnStartRequestAfterFallback);
9567 }
9568 }
9569 }
9570
9571 return ContinueOnStartRequestWithoutFallback();
9572}
9573
9574nsresult nsHttpChannel::ContinueOnStartRequestAfterFallback(nsresult aResult) {
9575 if (NS_SUCCEEDED(aResult)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResult)), 1)))) {
9576 // The fallback channel took over; this one is canceled by the redirect
9577 // handling code.
9578 return NS_OK;
9579 }
9580
9581 // The redirect to the fallback domain failed, so report this channel's own
9582 // result to the listener.
9583 return ContinueOnStartRequestWithoutFallback();
9584}
9585
9586nsresult nsHttpChannel::ContinueOnStartRequestWithoutFallback() {
9587 nsresult rv = NS_OK;
9588
9589 // avoid crashing if mListener happens to be null...
9590 if (!mListener) {
9591 MOZ_ASSERT_UNREACHABLE("mListener is null")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"mListener is null" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "mListener is null" ")"); do { MOZ_CrashSequence
(__null, 9591); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9592 return NS_OK;
9593 }
9594
9595 rv = ProcessCrossOriginSecurityHeaders();
9596 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9597 mStatus = rv;
9598 HandleAsyncAbort();
9599 return rv;
9600 }
9601
9602 // No process change is needed, so continue on to ContinueOnStartRequest1.
9603 return ContinueOnStartRequest1(rv);
9604}
9605
9606void nsHttpChannel::MaybeUpdateDocumentIPAddressSpaceFromCache() {
9607 MOZ_ASSERT(mLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mLoadInfo", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9607); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 9607); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9608 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
9609
9610 // Update the IPAddressSpace in the BrowsingContext only for main or sub
9611 // document
9612 if (type != ExtContentPolicy::TYPE_DOCUMENT &&
9613 type != ExtContentPolicy::TYPE_SUBDOCUMENT) {
9614 return;
9615 }
9616
9617 RefPtr<mozilla::dom::BrowsingContext> bc;
9618 mLoadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
9619
9620 if (!bc || !mCacheEntry) {
9621 return;
9622 }
9623
9624 nsAutoCString ipAddrStr, portStr;
9625 mCacheEntry->GetMetaDataElement("peer-ip-address", getter_Copies(ipAddrStr));
9626 mCacheEntry->GetMetaDataElement("peer-port", getter_Copies(portStr));
9627
9628 nsresult rv;
9629 uint32_t port = portStr.ToInteger(&rv);
9630
9631 if (!ipAddrStr.IsEmpty() && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9632 NetAddr ipAddr;
9633 rv = ipAddr.InitFromString(ipAddrStr, port);
9634 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9634); return; } } while (false)
;
9635 mLoadInfo->SetIpAddressSpace(ipAddr.GetIpAddressSpace());
9636 bc->SetCurrentIPAddressSpace(ipAddr.GetIpAddressSpace());
9637 }
9638}
9639
9640nsresult nsHttpChannel::OnPermissionPromptResult(bool aGranted,
9641 const nsACString& aType) {
9642 mWaitingForLNAPermission = false;
9643
9644 if (aGranted) {
9645 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"granted", this); } } while (0)
9646 ("nsHttpChannel::OnPermissionPromptResult [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"granted", this); } } while (0)
9647 "LNAPermissionRequest "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"granted", this); } } while (0)
9648 "granted",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"granted", this); } } while (0)
9649 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"granted", this); } } while (0)
;
9650 // we need to cache this data as permission manager is updated async and
9651 // might not be reflected immediately
9652 if (aType == LOOPBACK_NETWORK_PERMISSION_KEY) {
9653 mLNAPermission.mLocalHostPermission = LNAPermission::Granted;
9654 }
9655
9656 if (aType == LOCAL_NETWORK_PERMISSION_KEY) {
9657 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
9658 }
9659 // reset the transaction
9660 mTransaction = nullptr;
9661
9662 // resets streams and listener. Ensures we dont get any more callbacks to
9663 // nsHttpChannel from the pumps
9664 RefPtr<nsInputStreamPump> pump = do_QueryObject(mTransactionPump);
9665 if (pump) {
9666 pump->Reset();
9667 }
9668 mTransactionPump = nullptr;
9669
9670 // reset the status as we are going to replay the transaction
9671 mStatus = nsresult::NS_OK;
9672
9673 // allow notifications for the channel
9674 Resume();
9675 // replay the transaction with permisions granted
9676 return CallOrWaitForResume(
9677 [](auto* self) -> nsresult { return self->DoConnect(nullptr); });
9678 }
9679
9680 // permission denied
9681 // resume the transaction pump, we should get the OnStopRequest Notification
9682 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"denied", this); } } while (0)
9683 ("nsHttpChannel::OnPermissionPromptResult [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"denied", this); } } while (0)
9684 "LNAPermissionRequest "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"denied", this); } } while (0)
9685 "denied",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"denied", this); } } while (0)
9686 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnPermissionPromptResult [this=%p] " "LNAPermissionRequest "
"denied", this); } } while (0)
;
9687
9688 Resume();
9689
9690 if (aType == LOOPBACK_NETWORK_PERMISSION_KEY) {
9691 mLNAPermission.mLocalHostPermission = LNAPermission::Denied;
9692 }
9693
9694 if (aType == LOCAL_NETWORK_PERMISSION_KEY) {
9695 mLNAPermission.mLocalNetworkPermission = LNAPermission::Denied;
9696 }
9697
9698 if (!mSuspendCount) {
9699 return ContinueOnStartRequest1(
9700 nsresult::NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED);
9701 }
9702 // channel is suspended state. We will continue when the channel is
9703 // resumed
9704 return CallOrWaitForResume([](auto* self) {
9705 return self->ContinueOnStartRequest1(
9706 nsresult::NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED);
9707 });
9708}
9709
9710nsresult nsHttpChannel::ContinueOnStartRequest1(nsresult result) {
9711 nsresult rv;
9712
9713 // if process selection failed, cancel this load.
9714 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
9715 Cancel(result);
9716 return CallOnStartRequest();
9717 }
9718
9719 // before we start any content load, check for redirectTo being called
9720 // this code is executed mainly before we start load from the cache
9721 if (mAPIRedirectTo && !mCanceled) {
9722 nsAutoCString redirectToSpec;
9723 mAPIRedirectTo->first()->GetAsciiSpec(redirectToSpec);
9724 LOG((" redirectTo called with uri=%s", redirectToSpec.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " redirectTo called with uri=%s", redirectToSpec.get()); }
} while (0)
;
9725
9726 MOZ_ASSERT(!LoadOnStartRequestCalled())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 9726
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 9726); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9727 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
9728 rv = StartRedirectChannelToURI(
9729 mAPIRedirectTo->first(),
9730 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_TEMPORARY |
9731 nsIChannelEventSink::REDIRECT_TRANSPARENT
9732 : nsIChannelEventSink::REDIRECT_TEMPORARY);
9733 mAPIRedirectTo = Nothing();
9734 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9735 return NS_OK;
9736 }
9737 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
9738 }
9739
9740 // Hack: ContinueOnStartRequest2 uses NS_OK to detect successful redirects,
9741 // so we distinguish this codepath (a non-redirect that's processing
9742 // normally) by passing in a bogus error code.
9743 return ContinueOnStartRequest2(NS_BINDING_FAILED);
9744}
9745
9746nsresult nsHttpChannel::ContinueOnStartRequest2(nsresult result) {
9747 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
9748 // Redirect has passed through, we don't want to go on with this
9749 // channel. It will now be canceled by the redirect handling code
9750 // that called this function.
9751 return NS_OK;
9752 }
9753
9754 // on proxy errors, try to failover
9755 if (mConnectionInfo->ProxyInfo() &&
9756 (mStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
9757 mStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
9758 mStatus == NS_ERROR_NET_TIMEOUT || mStatus == NS_ERROR_NET_RESET)) {
9759 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
9760 if (NS_SUCCEEDED(ProxyFailover())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ProxyFailover()))
, 1)))
) {
9761 mProxyConnectResponseHead = nullptr;
9762 return NS_OK;
9763 }
9764 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
9765 }
9766
9767 // Hack: ContinueOnStartRequest3 uses NS_OK to detect successful redirects,
9768 // so we distinguish this codepath (a non-redirect that's processing
9769 // normally) by passing in a bogus error code.
9770 return ContinueOnStartRequest3(NS_BINDING_FAILED);
9771}
9772
9773nsresult nsHttpChannel::ContinueOnStartRequest3(nsresult result) {
9774 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
9775 // Redirect has passed through, we don't want to go on with this
9776 // channel. It will now be canceled by the redirect handling code
9777 // that called this function.
9778 return NS_OK;
9779 }
9780
9781 return CallOnStartRequest();
9782}
9783
9784static void ReportHTTPSRRTelemetry(
9785 const Maybe<nsCOMPtr<nsIDNSHTTPSSVCRecord>>& aMaybeRecord) {
9786 bool hasHTTPSRR = aMaybeRecord && (aMaybeRecord.ref() != nullptr);
9787 if (!hasHTTPSRR) {
9788 mozilla::glean::networking::https_rr_presented.Get("none"_ns).Add(1);
9789 return;
9790 }
9791
9792 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& record = aMaybeRecord.ref();
9793 nsCOMPtr<nsISVCBRecord> svcbRecord;
9794 if (NS_SUCCEEDED(record->GetServiceModeRecord(false, false,((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
9795 getter_AddRefs(svcbRecord)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
) {
9796 MOZ_ASSERT(svcbRecord)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(svcbRecord)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(svcbRecord))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("svcbRecord", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "svcbRecord"
")"); do { MOZ_CrashSequence(__null, 9796); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9797
9798 Maybe<std::tuple<nsCString, SupportedAlpnRank>> alpn =
9799 svcbRecord->GetAlpn();
9800 bool isHttp3 = alpn ? IsHttp3(std::get<1>(*alpn)) : false;
9801 mozilla::glean::networking::https_rr_presented
9802 .Get(isHttp3 ? "presented_with_http3"_ns : "presented"_ns)
9803 .Add(1);
9804 }
9805}
9806
9807static void RecordHttpChanDispositionGlean(ChannelDisposition chanDisposition) {
9808 switch (chanDisposition) {
9809 case kHttpCanceled:
9810 mozilla::glean::networking::http_channel_disposition
9811 .Get("http_cancelled"_ns)
9812 .Add(1);
9813 break;
9814 case kHttpDisk:
9815 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
9816 .Add(1);
9817 break;
9818 case kHttpNetOK:
9819 mozilla::glean::networking::http_channel_disposition.Get("http_net_ok"_ns)
9820 .Add(1);
9821 break;
9822 case kHttpNetEarlyFail:
9823 mozilla::glean::networking::http_channel_disposition
9824 .Get("http_net_early_fail"_ns)
9825 .Add(1);
9826 break;
9827 case kHttpNetLateFail:
9828 mozilla::glean::networking::http_channel_disposition
9829 .Get("http_net_late_fail"_ns)
9830 .Add(1);
9831 break;
9832 case kHttpsCanceled:
9833 mozilla::glean::networking::http_channel_disposition
9834 .Get("https_cancelled"_ns)
9835 .Add(1);
9836 break;
9837 case kHttpsDisk:
9838 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
9839 .Add(1);
9840 break;
9841 case kHttpsNetOK:
9842 mozilla::glean::networking::http_channel_disposition
9843 .Get("https_net_ok"_ns)
9844 .Add(1);
9845 break;
9846 case kHttpsNetEarlyFail:
9847 mozilla::glean::networking::http_channel_disposition
9848 .Get("https_net_early_fail"_ns)
9849 .Add(1);
9850 break;
9851 case kHttpsNetLateFail:
9852 mozilla::glean::networking::http_channel_disposition
9853 .Get("https_net_late_fail"_ns)
9854 .Add(1);
9855 break;
9856 default:
9857 MOZ_ASSERT_UNREACHABLE("Unknown value for chanDisposition")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unknown value for chanDisposition" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for chanDisposition"
")"); do { MOZ_CrashSequence(__null, 9857); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9858 }
9859}
9860
9861enum class HttpChannelDispositionUpgrade {
9862 cancel,
9863 disk,
9864 netOk,
9865 netEarlyFail,
9866 netLateFail,
9867};
9868
9869static nsLiteralCString HttpChanDispositionToTelemetryLabel(
9870 HttpChannelDispositionUpgrade upgradeChanDisposition) {
9871 switch (upgradeChanDisposition) {
9872 case HttpChannelDispositionUpgrade::cancel:
9873 return "cancel"_ns;
9874 case HttpChannelDispositionUpgrade::disk:
9875 return "disk"_ns;
9876 case HttpChannelDispositionUpgrade::netOk:
9877 return "net_ok"_ns;
9878 case HttpChannelDispositionUpgrade::netEarlyFail:
9879 return "net_early_fail"_ns;
9880 case HttpChannelDispositionUpgrade::netLateFail:
9881 return "net_late_fail"_ns;
9882 }
9883
9884 MOZ_ASSERT_UNREACHABLE("Unknown value for upgradeChanDecomposition")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unknown value for upgradeChanDecomposition" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9884); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for upgradeChanDecomposition"
")"); do { MOZ_CrashSequence(__null, 9884); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9885 return "other"_ns;
9886}
9887
9888nsresult nsHttpChannel::LogConsoleError(const char* aTag) {
9889 nsCOMPtr<nsIConsoleService> console(mozilla::components::Console::Service());
9890 NS_ENSURE_TRUE(console, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(console)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "console" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 9890
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9891
9892 nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
9893 NS_ENSURE_TRUE(console, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(console)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "console" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 9893
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9894 uint64_t innerWindowID = loadInfo->GetInnerWindowID();
9895
9896 nsAutoString errorText;
9897 nsresult rv = nsContentUtils::GetLocalizedString(
9898 PropertiesFile::NECKO_PROPERTIES, aTag, errorText);
9899 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9899); return rv; } } while (false)
;
9900
9901 nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1"));
9902 NS_ENSURE_TRUE(error, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(error)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "error" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 9902
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9903
9904 rv =
9905 error->InitWithSourceURI(errorText, mURI, 0, 0, nsIScriptError::errorFlag,
9906 "Invalid HTTP Status Lines"_ns, innerWindowID);
9907 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9907); return rv; } } while (false)
;
9908 console->LogMessage(error);
9909 return NS_OK;
9910}
9911
9912static void RecordHTTPSUpgradeTelemetry(nsIURI* aURI, nsILoadInfo* aLoadInfo) {
9913 // we record https telemetry only for top-level loads
9914 if (aLoadInfo->GetExternalContentPolicyType() !=
9915 ExtContentPolicy::TYPE_DOCUMENT) {
9916 return;
9917 }
9918
9919 // exempt loopback addresses because we only want to record telemetry
9920 // for actual web requests
9921 if (nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI)) {
9922 return;
9923 }
9924
9925 // todo: for now we don't record form submissions, only
9926 // top-level document loads. Once Bug 1720500 is fixed, we can
9927 // consider recording form submissions too.
9928 if (aLoadInfo->GetIsFormSubmission()) {
9929 return;
9930 }
9931
9932 bool isHTTPS = aURI->SchemeIs("https");
9933
9934 nsILoadInfo::HTTPSUpgradeTelemetryType httpsTelemetry =
9935 aLoadInfo->GetHttpsUpgradeTelemetry();
9936 switch (httpsTelemetry) {
9937 case nsILoadInfo::NOT_INITIALIZED: {
9938 if (isHTTPS) {
9939 // Bug 1912222: We should never encounter NOT_INITIALIZED values,
9940 // though we still want to know whether those loads are HTTPS
9941 // or not. Eventually we'll want to remove this if-clause
9942 // again and only report "not_initialized".
9943 mozilla::glean::networking::http_to_https_upgrade_reason
9944 .Get("not_initialized_https"_ns)
9945 .Add(1);
9946 return;
9947 }
9948 mozilla::glean::networking::http_to_https_upgrade_reason
9949 .Get("not_initialized"_ns)
9950 .Add(1);
9951 break;
9952 }
9953 case nsILoadInfo::NO_UPGRADE: {
9954 if (isHTTPS) {
9955 // Bug 1912222: We should rearely encounter NO_UPGRADE values, though
9956 // we still want to ensure those are not HTTPS. Eventually we'll want
9957 // to remove this if-clause again and only report "no_upgrade".
9958 mozilla::glean::networking::http_to_https_upgrade_reason
9959 .Get("no_upgrade_https"_ns)
9960 .Add(1);
9961 return;
9962 }
9963 mozilla::glean::networking::http_to_https_upgrade_reason
9964 .Get("no_upgrade"_ns)
9965 .Add(1);
9966 break;
9967 }
9968 case nsILoadInfo::ALREADY_HTTPS:
9969 mozilla::glean::networking::http_to_https_upgrade_reason
9970 .Get("already_https"_ns)
9971 .Add(1);
9972 break;
9973 case nsILoadInfo::HSTS:
9974 mozilla::glean::networking::http_to_https_upgrade_reason.Get("hsts"_ns)
9975 .Add(1);
9976 break;
9977 case nsILoadInfo::HTTPS_ONLY_UPGRADE:
9978 mozilla::glean::networking::http_to_https_upgrade_reason
9979 .Get("https_only_upgrade"_ns)
9980 .Add(1);
9981 break;
9982 case nsILoadInfo::HTTPS_ONLY_UPGRADE_DOWNGRADE:
9983 mozilla::glean::networking::http_to_https_upgrade_reason
9984 .Get("https_only_upgrade_downgrade"_ns)
9985 .Add(1);
9986 break;
9987 case nsILoadInfo::HTTPS_FIRST_UPGRADE:
9988 mozilla::glean::networking::http_to_https_upgrade_reason
9989 .Get("https_first_upgrade"_ns)
9990 .Add(1);
9991 break;
9992 case nsILoadInfo::HTTPS_FIRST_UPGRADE_DOWNGRADE:
9993 mozilla::glean::networking::http_to_https_upgrade_reason
9994 .Get("https_first_upgrade_downgrade"_ns)
9995 .Add(1);
9996 break;
9997 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE:
9998 mozilla::glean::networking::http_to_https_upgrade_reason
9999 .Get("https_first_schemeless_upgrade"_ns)
10000 .Add(1);
10001 break;
10002 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE_DOWNGRADE:
10003 mozilla::glean::networking::http_to_https_upgrade_reason
10004 .Get("https_first_schemeless_upgrade_downgrade"_ns)
10005 .Add(1);
10006 break;
10007 case nsILoadInfo::CSP_UIR:
10008 mozilla::glean::networking::http_to_https_upgrade_reason.Get("csp_uir"_ns)
10009 .Add(1);
10010 break;
10011 case nsILoadInfo::HTTPS_RR:
10012 mozilla::glean::networking::http_to_https_upgrade_reason
10013 .Get("https_rr"_ns)
10014 .Add(1);
10015 break;
10016 case nsILoadInfo::WEB_EXTENSION_UPGRADE:
10017 mozilla::glean::networking::http_to_https_upgrade_reason
10018 .Get("web_extension_upgrade"_ns)
10019 .Add(1);
10020 break;
10021 case nsILoadInfo::UPGRADE_EXCEPTION:
10022 mozilla::glean::networking::http_to_https_upgrade_reason
10023 .Get("upgrade_exception"_ns)
10024 .Add(1);
10025 break;
10026 case nsILoadInfo::SKIP_HTTPS_UPGRADE:
10027 mozilla::glean::networking::http_to_https_upgrade_reason
10028 .Get("skip_upgrade"_ns)
10029 .Add(1);
10030 break;
10031 default:
10032 MOZ_ASSERT(false, "what telemetry flag is set to end up here?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "what telemetry flag is set to end up here?"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"what telemetry flag is set to end up here?" ")"); do { MOZ_CrashSequence
(__null, 10032); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10033 }
10034}
10035
10036static void RecordIPAddressSpaceTelemetry(bool aLoadSuccess, nsIURI* aURI,
10037 nsILoadInfo* aLoadInfo,
10038 NetAddr& aPeerAddr) {
10039 // if the load was not successful, then there is nothing to record here
10040 if (!aLoadSuccess) {
10041 return;
10042 }
10043
10044 // we record https telemetry only for top-level loads
10045 if (aLoadInfo->GetExternalContentPolicyType() !=
10046 ExtContentPolicy::TYPE_DOCUMENT) {
10047 return;
10048 }
10049
10050 if (aURI->SchemeIs("https")) {
10051 mozilla::glean::networking::https_http_or_local.Get("load_is_https"_ns)
10052 .Add(1);
10053 return;
10054 }
10055
10056 if (aURI->SchemeIs("http")) {
10057 if (aPeerAddr.IsIPAddrLocal() || aPeerAddr.IsLoopbackAddr()) {
10058 mozilla::glean::networking::https_http_or_local
10059 .Get("load_is_http_for_local_domain"_ns)
10060 .Add(1);
10061 } else {
10062 mozilla::glean::networking::https_http_or_local.Get("load_is_http"_ns)
10063 .Add(1);
10064 }
10065 return;
10066 }
10067}
10068
10069static void RecordLNATelemetry(nsHttpChannel* aChannel, bool aLoadSuccess) {
10070 // Extract data from channel
10071 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
10072 nsCOMPtr<nsIURI> uri;
10073 aChannel->GetURI(getter_AddRefs(uri));
10074 NetAddr peerAddr = aChannel->GetPeerAddr();
10075 const nsACString& promptAction = aChannel->GetLNAPromptAction();
10076
10077 if (!loadInfo || !uri) {
10078 return;
10079 }
10080
10081 RefPtr<mozilla::dom::BrowsingContext> bc;
10082 loadInfo->GetBrowsingContext(getter_AddRefs(bc));
10083
10084 nsILoadInfo::IPAddressSpace parentAddressSpace =
10085 mozilla::net::GetParentIPAddressSpace(loadInfo);
10086
10087 // Early return if NOT LNA - don't record telemetry or log
10088 if (!mozilla::net::IsLocalOrPrivateNetworkAccess(
10089 parentAddressSpace, loadInfo->GetIpAddressSpace())) {
10090 return;
10091 }
10092
10093 if (aLoadSuccess) {
10094 mozilla::glean::networking::local_network_access.Get("success"_ns).Add(1);
10095 } else {
10096 mozilla::glean::networking::local_network_access.Get("failure"_ns).Add(1);
10097 }
10098
10099 uint16_t port = 0;
10100 peerAddr.GetPort(&port);
10101
10102 // label format is <parentAddressSpace>_to_<targetAddressSpace>_<scheme>
10103 // At this point we are sure that the request is a LNA,
10104 // Hence we can safely assume few conditions to construct the label
10105 nsAutoCString glean_lna_label;
10106 if (parentAddressSpace == nsILoadInfo::IPAddressSpace::Public) {
10107 glean_lna_label.Append("public_to_"_ns);
10108 } else {
10109 glean_lna_label.Append("private_to_"_ns);
10110 }
10111 if (loadInfo->GetIpAddressSpace() == nsILoadInfo::IPAddressSpace::Private) {
10112 glean_lna_label.Append("private_"_ns);
10113 } else {
10114 glean_lna_label.Append("local_"_ns);
10115 }
10116 if (uri->SchemeIs("https")) {
10117 glean_lna_label.Append("https"_ns);
10118 } else {
10119 glean_lna_label.Append("http"_ns);
10120 }
10121
10122 mozilla::glean::networking::local_network_access.Get(glean_lna_label).Add(1);
10123
10124 // Get top-level site (main window principal) - TLD+1
10125 nsAutoCString topLevelSite;
10126 if (bc && bc->Top()) {
10127 if (bc->Top()->Canonical()) {
10128 RefPtr<mozilla::dom::WindowGlobalParent> topWindowGlobal =
10129 bc->Top()->Canonical()->GetCurrentWindowGlobal();
10130 if (topWindowGlobal) {
10131 nsCOMPtr<nsIPrincipal> topPrincipal =
10132 topWindowGlobal->DocumentPrincipal();
10133 if (topPrincipal) {
10134 (void)topPrincipal->GetBaseDomain(topLevelSite);
10135 }
10136 }
10137 }
10138 }
10139
10140 // Get initiator (triggering principal) - TLD+1
10141 nsAutoCString initiator;
10142 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
10143 loadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
10144 if (triggeringPrincipal) {
10145 (void)triggeringPrincipal->GetBaseDomain(initiator);
10146 }
10147
10148 bool isSecureContext =
10149 triggeringPrincipal
10150 ? triggeringPrincipal->GetIsOriginPotentiallyTrustworthy()
10151 : false;
10152
10153 // Get target host - TLD+1
10154 nsCOMPtr<nsIEffectiveTLDService> eTLDService =
10155 mozilla::components::EffectiveTLD::Service();
10156 nsAutoCString targetHost;
10157 if (eTLDService) {
10158 (void)eTLDService->GetBaseDomain(uri, 0, targetHost);
10159 }
10160
10161 // Get target IP address
10162 nsCString targetIp = peerAddr.ToString();
10163
10164 // Determine protocol from LoadInfo
10165 nsAutoCString protocol;
10166 ExtContentPolicyType contentType = loadInfo->GetExternalContentPolicyType();
10167 switch (contentType) {
10168 case ExtContentPolicyType::TYPE_WEBSOCKET:
10169 protocol.AssignLiteral("websocket");
10170 break;
10171 case ExtContentPolicyType::TYPE_WEB_TRANSPORT:
10172 protocol.AssignLiteral("webtransport");
10173 break;
10174 case ExtContentPolicyType::TYPE_FETCH:
10175 protocol.AssignLiteral("fetch");
10176 break;
10177 case ExtContentPolicyType::TYPE_XMLHTTPREQUEST:
10178 protocol.AssignLiteral("xhr");
10179 break;
10180 default:
10181 if (uri->SchemeIs("https")) {
10182 protocol.AssignLiteral("https");
10183 } else {
10184 protocol.AssignLiteral("http");
10185 }
10186 break;
10187 }
10188
10189 // Record the event
10190 glean::networking::LocalNetworkAccessConnectionExtra extra = {
10191 .initiator = initiator.IsEmpty() ? Nothing() : Some(initiator),
10192 .isSecureContext = Some(isSecureContext),
10193 .loadSuccess = Some(aLoadSuccess),
10194 .promptAction =
10195 promptAction.IsEmpty() ? Nothing() : Some(nsCString(promptAction)),
10196 .protocol = Some(protocol),
10197 .targetHost = targetHost.IsEmpty() ? Nothing() : Some(targetHost),
10198 .targetIp = Some(targetIp),
10199 .targetPort = Some(port),
10200 .topLevelSite = topLevelSite.IsEmpty() ? Nothing() : Some(topLevelSite),
10201
10202 };
10203 glean::networking::local_network_access_connection.Record(Some(extra));
10204
10205 ReportLNAAccessToConsole(aChannel, "LocalNetworkAccessDetected",
10206 promptAction);
10207}
10208
10209NS_IMETHODIMPnsresult
10210nsHttpChannel::OnStopRequest(nsIRequest* request, nsresult status) {
10211 MOZ_ASSERT(!mAsyncOpenTime.IsNull())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAsyncOpenTime.IsNull())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAsyncOpenTime.IsNull()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!mAsyncOpenTime.IsNull()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10211
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncOpenTime.IsNull()"
")"); do { MOZ_CrashSequence(__null, 10211); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10212 AUTO_PROFILER_LABEL("nsHttpChannel::OnStopRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject10212( "nsHttpChannel::OnStopRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
10213 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnStopRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10214( "nsHttpChannel::OnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10214 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10214( "nsHttpChannel::OnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10215
10216 LOG(("nsHttpChannel::OnStopRequest [this=%p request=%p status=%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnStopRequest [this=%p request=%p status=%"
"x" "]\n", this, request, static_cast<uint32_t>(status
)); } } while (0)
10217 this, request, static_cast<uint32_t>(status)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnStopRequest [this=%p request=%p status=%"
"x" "]\n", this, request, static_cast<uint32_t>(status
)); } } while (0)
;
10218
10219 LOG(("OnStopRequest %p requestFromCache: %d mFirstResponseSource: %d\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "OnStopRequest %p requestFromCache: %d mFirstResponseSource: %d\n"
, this, request == mCachePump, static_cast<int32_t>(mFirstResponseSource
)); } } while (0)
10220 request == mCachePump, static_cast<int32_t>(mFirstResponseSource)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "OnStopRequest %p requestFromCache: %d mFirstResponseSource: %d\n"
, this, request == mCachePump, static_cast<int32_t>(mFirstResponseSource
)); } } while (0)
;
10221
10222 MOZ_ASSERT(NS_IsMainThread(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "OnStopRequest should only be called from the main thread"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { MOZ_CrashSequence(__null, 10223); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10223 "OnStopRequest should only be called from the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "OnStopRequest should only be called from the main thread"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { MOZ_CrashSequence(__null, 10223); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10224
10225 if (mStatus == NS_ERROR_PARSING_HTTP_STATUS_LINE) {
10226 (void)LogConsoleError("InvalidHTTPResponseStatusLine");
10227 }
10228
10229 // It's possible that LoadUseHTTPSSVC() is false, but we already have
10230 // mHTTPSSVCRecord.
10231 if (LoadUseHTTPSSVC() || mHTTPSSVCRecord) {
10232 ReportHTTPSRRTelemetry(mHTTPSSVCRecord);
10233 }
10234
10235 // If this load failed because of a security error, it may be because we
10236 // are in a captive portal - trigger an async check to make sure.
10237 int32_t nsprError = -1 * NS_ERROR_GET_CODE(status);
10238 if (mozilla::psm::IsNSSErrorCode(nsprError) && IsHTTPS()) {
10239 gIOService->RecheckCaptivePortal();
10240 }
10241
10242 if (request == mCachePump) {
10243 mCacheReadEnd = TimeStamp::Now();
10244 }
10245
10246 // allow content to be cached if it was loaded successfully (bug #482935)
10247 bool contentComplete = NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)));
10248
10249 // honor the cancelation status even if the underlying transaction
10250 // completed.
10251 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) status = mStatus;
10252
10253 if (LoadCachedContentIsPartial()) {
10254 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
10255 // mTransactionPump should be suspended
10256 MOZ_ASSERT(request != mTransactionPump,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(request != mTransactionPump)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(request != mTransactionPump)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("request != mTransactionPump"
" (" "byte-range transaction finished prematurely" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10257); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ MOZ_CrashSequence(__null, 10257); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
10257 "byte-range transaction finished prematurely")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(request != mTransactionPump)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(request != mTransactionPump)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("request != mTransactionPump"
" (" "byte-range transaction finished prematurely" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10257); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ MOZ_CrashSequence(__null, 10257); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
10258
10259 if (request == mCachePump) {
10260 bool streamDone;
10261 status = OnDoneReadingPartialCacheEntry(&streamDone);
10262 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) && !streamDone) return status;
10263 // otherwise, fall through and fire OnStopRequest...
10264 } else if (request == mTransactionPump) {
10265 MOZ_ASSERT(LoadConcurrentCacheAccess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadConcurrentCacheAccess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadConcurrentCacheAccess())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("LoadConcurrentCacheAccess()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10265
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { MOZ_CrashSequence(__null, 10265); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10266 } else {
10267 MOZ_ASSERT_UNREACHABLE("unexpected request")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"unexpected request" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10267); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected request" ")"); do { MOZ_CrashSequence
(__null, 10267); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10268 }
10269 }
10270 // Do not to leave the transaction in a suspended state in error cases.
10271 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) && mTransaction) {
10272 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, status);
10273 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10274 LOG((" CancelTransaction failed (%08x)", static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " CancelTransaction failed (%08x)", static_cast<uint32_t
>(rv)); } } while (0)
;
10275 }
10276 }
10277 }
10278
10279 nsCOMPtr<nsICompressConvStats> conv = do_QueryInterface(mCompressListener);
10280 if (conv) {
10281 uint64_t decodedDataLength = 0;
10282 conv->GetDecodedDataLength(&decodedDataLength);
10283 mDecodedBodySize = decodedDataLength;
10284 }
10285
10286 bool isFromNet = request == mTransactionPump;
10287
10288 if (mTransaction) {
10289 // determine if we should call DoAuthRetry
10290 bool authRetry = (mAuthRetryPending && NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) &&
10291 // we should only auth retry in this channel if are not
10292 // redirecting a new channel for authentication retries
10293 !StaticPrefs::network_auth_use_redirect_for_retries());
10294
10295 StoreStronglyFramed(mTransaction->ResponseIsComplete());
10296 LOG(("nsHttpChannel %p has a strongly framed transaction: %d", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p has a strongly framed transaction: %d", this
, LoadStronglyFramed()); } } while (0)
10297 LoadStronglyFramed()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p has a strongly framed transaction: %d", this
, LoadStronglyFramed()); } } while (0)
;
10298
10299 // Save the reference of |mTransaction| to |transactionWithStickyConn|
10300 // when it has a sticky connection.
10301 // In the case we need to retry an authentication request, we need to
10302 // reuse the connection of |transactionWithStickyConn|.
10303 RefPtr<HttpTransactionShell> transactionWithStickyConn;
10304 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
10305 mTransaction->HasStickyConnection()) {
10306 transactionWithStickyConn = mTransaction;
10307 // Make sure we use the updated caps and connection info from transaction.
10308 // We read these values when the transaction is already closed, so there
10309 // should be no race.
10310 if (mTransaction->Http2Disabled()) {
10311 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
10312 }
10313 if (mTransaction->Http3Disabled()) {
10314 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
10315 }
10316 mConnectionInfo = mTransaction->GetConnInfo();
10317 LOG((" transaction %p has sticky connection",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " transaction %p has sticky connection", transactionWithStickyConn
.get()); } } while (0)
10318 transactionWithStickyConn.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " transaction %p has sticky connection", transactionWithStickyConn
.get()); } } while (0)
;
10319 }
10320
10321 // this code relies on the code in nsHttpTransaction::Close, which
10322 // tests for NS_HTTP_STICKY_CONNECTION to determine whether or not to
10323 // keep the connection around after the transaction is finished.
10324 //
10325 LOG((" mAuthRetryPending=%d, status=%" PRIx32 ", sticky conn cap=%d",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " mAuthRetryPending=%d, status=%" "x" ", sticky conn cap=%d"
, static_cast<bool>(mAuthRetryPending), static_cast<
uint32_t>(status), mCaps & (1 << 2)); } } while (
0)
10326 static_cast<bool>(mAuthRetryPending), static_cast<uint32_t>(status),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " mAuthRetryPending=%d, status=%" "x" ", sticky conn cap=%d"
, static_cast<bool>(mAuthRetryPending), static_cast<
uint32_t>(status), mCaps & (1 << 2)); } } while (
0)
10327 mCaps & NS_HTTP_STICKY_CONNECTION))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " mAuthRetryPending=%d, status=%" "x" ", sticky conn cap=%d"
, static_cast<bool>(mAuthRetryPending), static_cast<
uint32_t>(status), mCaps & (1 << 2)); } } while (
0)
;
10328 // We must check caps for stickinness also on the transaction because it
10329 // might have been updated by the transaction itself during inspection of
10330 // the reposnse headers yet on the socket thread (found connection based
10331 // auth schema).
10332
10333 if ((NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) && transactionWithStickyConn) {
10334 // Close (don't reuse) the sticky connection if this channel has been
10335 // cancelled. There are proxy servers known to get confused when we send
10336 // a new request over such a half-stated connection.
10337 if (!LoadAuthConnectionRestartable()) {
10338 LOG((" not reusing a half-authenticated sticky connection"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " not reusing a half-authenticated sticky connection"); } }
while (0)
;
10339 transactionWithStickyConn->DontReuseConnection();
10340 }
10341 }
10342
10343 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) {
10344 mTransaction->SetH2WSConnRefTaken();
10345 }
10346
10347 mTransferSize = mTransaction->GetTransferSize();
10348 mRequestSize = mTransaction->GetRequestSize();
10349
10350 RecordHTTPSUpgradeTelemetry(mURI, mLoadInfo);
10351
10352 RecordIPAddressSpaceTelemetry(NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))), mURI, mLoadInfo,
10353 mPeerAddr);
10354 RecordLNATelemetry(this, NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))));
10355
10356 uint32_t flags;
10357 if (mStatus == NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED &&
10358 StaticPrefs::network_lna_block_trackers() &&
10359 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
10360 mLoadInfo->GetTriggeringThirdPartyClassificationFlags(&flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
&&
10361 flags != 0) {
10362 mozilla::glean::networking::local_network_blocked_tracker.Add(1);
10363 }
10364
10365 // If we are using the transaction to serve content, we also save the
10366 // time since async open in the cache entry so we can compare telemetry
10367 // between cache and net response.
10368 // Do not store the time of conditional requests because even if we
10369 // fetch the data from the server, the time includes loading of the old
10370 // cache entry which would skew the network load time.
10371 if (request == mTransactionPump && mCacheEntry && !mDidReval &&
10372 !LoadCustomConditionalRequest() && !mAsyncOpenTime.IsNull() &&
10373 !mOnStartRequestTimestamp.IsNull()) {
10374 uint64_t onStartTime =
10375 (mOnStartRequestTimestamp - mAsyncOpenTime).ToMilliseconds();
10376 uint64_t onStopTime =
10377 (TimeStamp::Now() - mAsyncOpenTime).ToMilliseconds();
10378 (void)mCacheEntry->SetNetworkTimes(onStartTime, onStopTime);
10379 }
10380
10381 mResponseTrailers = mTransaction->TakeResponseTrailers();
10382
10383 mOnStopRequestStartTime = TimeStamp::Now();
10384
10385 // at this point, we're done with the transaction
10386 mTransactionTimings = mTransaction->Timings();
10387 mTransaction = nullptr;
10388 mTransactionPump = nullptr;
10389
10390 // We no longer need the dns prefetch object
10391 if (mDNSPrefetch && mDNSPrefetch->TimingsValid() &&
10392 !mTransactionTimings.requestStart.IsNull() &&
10393 !mTransactionTimings.connectStart.IsNull() &&
10394 mDNSPrefetch->EndTimestamp() <= mTransactionTimings.connectStart) {
10395 // We only need the domainLookup timestamps when not using a
10396 // persistent connection, meaning if the endTimestamp < connectStart
10397 mTransactionTimings.domainLookupStart = mDNSPrefetch->StartTimestamp();
10398 mTransactionTimings.domainLookupEnd = mDNSPrefetch->EndTimestamp();
10399 }
10400 mDNSPrefetch = nullptr;
10401
10402 // handle auth retry...
10403 if (authRetry) {
10404 mAuthRetryPending = false;
10405 auto continueOSR = [authRetry, isFromNet, contentComplete,
10406 transactionWithStickyConn](auto* self,
10407 nsresult aStatus) {
10408 return self->ContinueOnStopRequestAfterAuthRetry(
10409 aStatus, authRetry, isFromNet, contentComplete,
10410 transactionWithStickyConn);
10411 };
10412 status = DoAuthRetry(transactionWithStickyConn, continueOSR);
10413 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
10414 return NS_OK;
10415 }
10416 }
10417 return ContinueOnStopRequestAfterAuthRetry(status, authRetry, isFromNet,
10418 contentComplete,
10419 transactionWithStickyConn);
10420 }
10421
10422 return ContinueOnStopRequest(status, isFromNet, contentComplete);
10423}
10424
10425nsresult nsHttpChannel::ContinueOnStopRequestAfterAuthRetry(
10426 nsresult aStatus, bool aAuthRetry, bool aIsFromNet, bool aContentComplete,
10427 HttpTransactionShell* aTransWithStickyConn) {
10428 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequestAfterAuthRetry " "[this=%p, aStatus=%"
"x" " aAuthRetry=%d, aIsFromNet=%d, aTransWithStickyConn=%p]\n"
, this, static_cast<uint32_t>(aStatus), aAuthRetry, aIsFromNet
, aTransWithStickyConn); } } while (0)
10429 ("nsHttpChannel::ContinueOnStopRequestAfterAuthRetry "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequestAfterAuthRetry " "[this=%p, aStatus=%"
"x" " aAuthRetry=%d, aIsFromNet=%d, aTransWithStickyConn=%p]\n"
, this, static_cast<uint32_t>(aStatus), aAuthRetry, aIsFromNet
, aTransWithStickyConn); } } while (0)
10430 "[this=%p, aStatus=%" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequestAfterAuthRetry " "[this=%p, aStatus=%"
"x" " aAuthRetry=%d, aIsFromNet=%d, aTransWithStickyConn=%p]\n"
, this, static_cast<uint32_t>(aStatus), aAuthRetry, aIsFromNet
, aTransWithStickyConn); } } while (0)
10431 " aAuthRetry=%d, aIsFromNet=%d, aTransWithStickyConn=%p]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequestAfterAuthRetry " "[this=%p, aStatus=%"
"x" " aAuthRetry=%d, aIsFromNet=%d, aTransWithStickyConn=%p]\n"
, this, static_cast<uint32_t>(aStatus), aAuthRetry, aIsFromNet
, aTransWithStickyConn); } } while (0)
10432 this, static_cast<uint32_t>(aStatus), aAuthRetry, aIsFromNet,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequestAfterAuthRetry " "[this=%p, aStatus=%"
"x" " aAuthRetry=%d, aIsFromNet=%d, aTransWithStickyConn=%p]\n"
, this, static_cast<uint32_t>(aStatus), aAuthRetry, aIsFromNet
, aTransWithStickyConn); } } while (0)
10433 aTransWithStickyConn))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequestAfterAuthRetry " "[this=%p, aStatus=%"
"x" " aAuthRetry=%d, aIsFromNet=%d, aTransWithStickyConn=%p]\n"
, this, static_cast<uint32_t>(aStatus), aAuthRetry, aIsFromNet
, aTransWithStickyConn); } } while (0)
;
10434
10435 if (aAuthRetry && NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
10436 return NS_OK;
10437 }
10438
10439 // If DoAuthRetry failed, or if we have been cancelled since showing
10440 // the auth. dialog, then we need to send OnStartRequest now
10441 if (aAuthRetry || (mAuthRetryPending && NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0))))) {
10442 MOZ_ASSERT(NS_FAILED(aStatus), "should have a failure code here")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus))
, 0))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus))
, 0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))"
" (" "should have a failure code here" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))"
") (" "should have a failure code here" ")"); do { MOZ_CrashSequence
(__null, 10442); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10443 // NOTE: since we have a failure status, we can ignore the return
10444 // value from onStartRequest.
10445 LOG((" calling mListener->OnStartRequest [this=%p, listener=%p]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " calling mListener->OnStartRequest [this=%p, listener=%p]\n"
, this, mListener.get()); } } while (0)
10446 mListener.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " calling mListener->OnStartRequest [this=%p, listener=%p]\n"
, this, mListener.get()); } } while (0)
;
10447 if (mListener) {
10448 MOZ_ASSERT(!LoadOnStartRequestCalled(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
" (" "We should not call OnStartRequest twice." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10449); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10449 "We should not call OnStartRequest twice.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
" (" "We should not call OnStartRequest twice." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10449); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10450 if (!LoadOnStartRequestCalled()) {
10451 nsCOMPtr<nsIStreamListener> listener(mListener);
10452 StoreOnStartRequestCalled(true);
10453 listener->OnStartRequest(this);
10454 }
10455 } else {
10456 StoreOnStartRequestCalled(true);
10457 NS_WARNING("OnStartRequest skipped because of null listener")NS_DebugBreak(NS_DEBUG_WARNING, "OnStartRequest skipped because of null listener"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10457)
;
10458 }
10459 mAuthRetryPending = false;
10460 }
10461
10462 // if this transaction has been replaced, then bail.
10463 if (LoadTransactionReplaced()) {
10464 LOG(("Transaction replaced\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Transaction replaced\n"); } } while (0)
;
10465 // This was just the network check for a 304 response.
10466 mFirstResponseSource = RESPONSE_PENDING;
10467 return NS_OK;
10468 }
10469
10470 bool upgradeWebsocket = mUpgradeProtocolCallback && aTransWithStickyConn &&
10471 mResponseHead &&
10472 ((mResponseHead->Status() == 101 &&
10473 mResponseHead->Version() == HttpVersion::v1_1) ||
10474 (mResponseHead->Status() == 200 &&
10475 mResponseHead->Version() == HttpVersion::v2_0));
10476
10477 bool upgradeConnect = mUpgradeProtocolCallback && aTransWithStickyConn &&
10478 (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) && mResponseHead &&
10479 mResponseHead->Status() == 200;
10480
10481 if (upgradeWebsocket || upgradeConnect) {
10482 nsresult rv = gHttpHandler->CompleteUpgrade(aTransWithStickyConn,
10483 mUpgradeProtocolCallback);
10484 mUpgradeProtocolCallback = nullptr;
10485 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10486 LOG((" CompleteUpgrade failed with %" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " CompleteUpgrade failed with %" "x", static_cast<uint32_t
>(rv)); } } while (0)
10487 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " CompleteUpgrade failed with %" "x", static_cast<uint32_t
>(rv)); } } while (0)
;
10488
10489 // This ensures that WebSocketChannel::OnStopRequest will be
10490 // called with an error so the session is properly aborted.
10491 aStatus = rv;
10492 }
10493 }
10494
10495 return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
10496}
10497
10498nsresult nsHttpChannel::ContinueOnStopRequest(nsresult aStatus, bool aIsFromNet,
10499 bool aContentComplete) {
10500 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequest " "[this=%p aStatus=%"
"x" ", aIsFromNet=%d]\n", this, static_cast<uint32_t>(
aStatus), aIsFromNet); } } while (0)
10501 ("nsHttpChannel::ContinueOnStopRequest "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequest " "[this=%p aStatus=%"
"x" ", aIsFromNet=%d]\n", this, static_cast<uint32_t>(
aStatus), aIsFromNet); } } while (0)
10502 "[this=%p aStatus=%" PRIx32 ", aIsFromNet=%d]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequest " "[this=%p aStatus=%"
"x" ", aIsFromNet=%d]\n", this, static_cast<uint32_t>(
aStatus), aIsFromNet); } } while (0)
10503 this, static_cast<uint32_t>(aStatus), aIsFromNet))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueOnStopRequest " "[this=%p aStatus=%"
"x" ", aIsFromNet=%d]\n", this, static_cast<uint32_t>(
aStatus), aIsFromNet); } } while (0)
;
10504
10505 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ContinueOnStopRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10506( "nsHttpChannel::ContinueOnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10506 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10506( "nsHttpChannel::ContinueOnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10507 // HTTP_CHANNEL_DISPOSITION TELEMETRY
10508 ChannelDisposition chanDisposition = kHttpCanceled;
10509 // HTTP_CHANNEL_DISPOSITION_UPGRADE TELEMETRY
10510 HttpChannelDispositionUpgrade upgradeChanDisposition =
10511 HttpChannelDispositionUpgrade::cancel;
10512
10513 // HTTP 0.9 is more likely to be an error than really 0.9, so count it that
10514 // way
10515 if (mCanceled) {
10516 chanDisposition = kHttpCanceled;
10517 upgradeChanDisposition = HttpChannelDispositionUpgrade::cancel;
10518 } else if (!LoadUsedNetwork()) {
10519 chanDisposition = kHttpDisk;
10520 upgradeChanDisposition = HttpChannelDispositionUpgrade::disk;
10521 } else if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) && mResponseHead &&
10522 mResponseHead->Version() != HttpVersion::v0_9) {
10523 chanDisposition = kHttpNetOK;
10524 upgradeChanDisposition = HttpChannelDispositionUpgrade::netOk;
10525 } else if (!mTransferSize) {
10526 chanDisposition = kHttpNetEarlyFail;
10527 upgradeChanDisposition = HttpChannelDispositionUpgrade::netEarlyFail;
10528 } else {
10529 chanDisposition = kHttpNetLateFail;
10530 upgradeChanDisposition = HttpChannelDispositionUpgrade::netLateFail;
10531 }
10532 // Browser upgrading only happens on HTTPS pages for mixed passive content
10533 // when upgrading is enabled.
10534 nsCString upgradeKey;
10535 nsLiteralCString upgradeChanDispositionLabel =
10536 HttpChanDispositionToTelemetryLabel(upgradeChanDisposition);
10537 if (IsHTTPS()) {
10538 // Browser upgrading is disabled and the content is already HTTPS
10539 upgradeKey = "disabledNoReason"_ns;
10540 // Checks "security.mixed_content.upgrade_display_content" is true
10541 if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
10542 if (mLoadInfo->GetBrowserUpgradeInsecureRequests()) {
10543 // HTTP content the browser has upgraded to HTTPS
10544 mozilla::glean::networking::http_channel_disposition_enabled_upgrade
10545 .Get(upgradeChanDispositionLabel)
10546 .Add(1);
10547 upgradeKey = "enabledUpgrade"_ns;
10548 } else {
10549 // Content wasn't upgraded but is already HTTPS
10550 mozilla::glean::networking::http_channel_disposition_enabled_no_reason
10551 .Get(upgradeChanDispositionLabel)
10552 .Add(1);
10553 upgradeKey = "enabledNoReason"_ns;
10554 }
10555 } else {
10556 mozilla::glean::networking::http_channel_disposition_disabled_no_reason
10557 .Get(upgradeChanDispositionLabel)
10558 .Add(1);
10559 }
10560 // shift http to https disposition enums
10561 chanDisposition =
10562 static_cast<ChannelDisposition>(chanDisposition + kHttpsCanceled);
10563 } else if (mLoadInfo->GetBrowserWouldUpgradeInsecureRequests()) {
10564 // HTTP content the browser would upgrade to HTTPS if upgrading was
10565 // enabled
10566 mozilla::glean::networking::http_channel_disposition_disabled_upgrade
10567 .Get(upgradeChanDispositionLabel)
10568 .Add(1);
10569 upgradeKey = "disabledUpgrade"_ns;
10570 } else if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
10571 // HTTP content that wouldn't upgrade
10572 mozilla::glean::networking::http_channel_disposition_enabled_wont
10573 .Get(upgradeChanDispositionLabel)
10574 .Add(1);
10575 upgradeKey = "enabledWont"_ns;
10576 } else {
10577 mozilla::glean::networking::http_channel_disposition_disabled_wont
10578 .Get(upgradeChanDispositionLabel)
10579 .Add(1);
10580 upgradeKey = "disabledWont"_ns;
10581 }
10582
10583 glean::networking::http_channel_disposition_upgrade
10584 .Get(upgradeKey, upgradeChanDispositionLabel)
10585 .Add();
10586
10587 LOG((" nsHttpChannel::OnStopRequest ChannelDisposition %d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " nsHttpChannel::OnStopRequest ChannelDisposition %d\n", chanDisposition
); } } while (0)
10588 chanDisposition))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " nsHttpChannel::OnStopRequest ChannelDisposition %d\n", chanDisposition
); } } while (0)
;
10589 glean::http::channel_disposition.AccumulateSingleSample(chanDisposition);
10590 RecordHttpChanDispositionGlean(chanDisposition);
10591
10592 // if needed, check cache entry has all data we expect
10593 if (mCacheEntry && mCachePump && LoadConcurrentCacheAccess() &&
10594 aContentComplete) {
10595 int64_t size, contentLength;
10596 nsresult rv = CheckPartial(mCacheEntry, &size, &contentLength);
10597 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10598 if (size == int64_t(-1)) {
10599 // mayhemer TODO - we have to restart read from cache here at the size
10600 // offset
10601 MOZ_ASSERT(false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10601); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")"
); do { MOZ_CrashSequence(__null, 10601); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10602 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache entry write is still in progress, but we just " "finished reading the cache entry"
); } } while (0)
10603 (" cache entry write is still in progress, but we just "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache entry write is still in progress, but we just " "finished reading the cache entry"
); } } while (0)
10604 "finished reading the cache entry"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache entry write is still in progress, but we just " "finished reading the cache entry"
); } } while (0)
;
10605 } else if (contentLength != int64_t(-1) && contentLength != size) {
10606 LOG((" concurrent cache entry write has been interrupted"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " concurrent cache entry write has been interrupted"); } }
while (0)
;
10607 mCachedResponseHead = std::move(mResponseHead);
10608 // Ignore zero partial length because we also want to resume when
10609 // no data at all has been read from the cache.
10610 rv = MaybeSetupByteRangeRequest(size, contentLength, true);
10611 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest()) {
10612 // Prevent read from cache again
10613 StoreCachedContentIsValid(CachedContentValidity::Invalid);
10614 StoreCachedContentIsPartial(1);
10615
10616 // Perform the range request
10617 rv = ContinueConnect();
10618 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10619 LOG((" performing range request"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " performing range request"); } } while (0)
;
10620 mCachePump = nullptr;
10621 return NS_OK;
10622 }
10623 LOG((" but range request perform failed 0x%08" PRIx32,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " but range request perform failed 0x%08" "x", static_cast
<uint32_t>(rv)); } } while (0)
10624 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " but range request perform failed 0x%08" "x", static_cast
<uint32_t>(rv)); } } while (0)
;
10625 aStatus = NS_ERROR_NET_INTERRUPT;
10626 } else {
10627 LOG((" but range request setup failed rv=0x%08" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " but range request setup failed rv=0x%08" "x" ", failing load"
, static_cast<uint32_t>(rv)); } } while (0)
10628 ", failing load",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " but range request setup failed rv=0x%08" "x" ", failing load"
, static_cast<uint32_t>(rv)); } } while (0)
10629 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " but range request setup failed rv=0x%08" "x" ", failing load"
, static_cast<uint32_t>(rv)); } } while (0)
;
10630 aStatus = NS_ERROR_NET_INTERRUPT;
10631 }
10632
10633 // Range-request recovery failed. Restore mResponseHead so that
10634 // it's available to late callers of Cancel (such as the ORB
10635 // async JS-validation callback)
10636 mResponseHead = std::move(mCachedResponseHead);
10637 }
10638 }
10639 }
10640
10641 StoreIsPending(false);
10642 mStatus = aStatus;
10643
10644 // perform any final cache operations before we close the cache entry.
10645 if (mCacheEntry && LoadRequestTimeInitialized()) {
10646 // New implementation just returns value of the !LoadCacheEntryIsReadOnly()
10647 // flag passed in. Old implementation checks on nsICache::ACCESS_WRITE
10648 // flag.
10649
10650 // Assume that write access is granted
10651 if (!LoadCacheEntryIsReadOnly()) {
10652 nsresult rv = FinalizeCacheEntry();
10653 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10654 LOG(("FinalizeCacheEntry failed (%08x)", static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "FinalizeCacheEntry failed (%08x)", static_cast<uint32_t
>(rv)); } } while (0)
;
10655 }
10656 }
10657 }
10658
10659 // Register entry to the PerformanceStorage resource timing
10660 MaybeReportTimingData();
10661
10662 MaybeFlushConsoleReports();
10663
10664 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
10665 // These do allocations/frees/etc; avoid if not active
10666 mEndMarkerAdded = true;
10667
10668 nsAutoCString requestMethod;
10669 GetRequestMethod(requestMethod);
10670
10671 int32_t priority = PRIORITY_NORMAL;
10672 GetPriority(&priority);
10673
10674 uint64_t size = 0;
10675 GetEncodedBodySize(&size);
10676
10677 nsAutoCString contentType;
10678 mozilla::Maybe<mozilla::net::HttpVersion> httpVersion = Nothing();
10679 mozilla::Maybe<uint32_t> responseStatus = Nothing();
10680 if (mResponseHead) {
10681 mResponseHead->ContentType(contentType);
10682 httpVersion = Some(mResponseHead->Version());
10683 responseStatus = Some(mResponseHead->Status());
10684 }
10685
10686 profiler_add_network_marker(
10687 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_STOP,
10688 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
10689 mLoadInfo->GetInnerWindowID(),
10690 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
10691 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
10692 &mTransactionTimings, std::move(mSource),
10693 // Skip the version for a cached response: it reflects the original
10694 // fetch, not this request's connection.
10695 (mCacheDisposition == kCacheHit ||
10696 mCacheDisposition == kCacheHitViaReval)
10697 ? Nothing()
10698 : httpVersion,
10699 responseStatus, Some(nsDependentCString(contentType.get())));
10700 }
10701
10702 if (mAuthRetryPending &&
10703 StaticPrefs::network_auth_use_redirect_for_retries()) {
10704 nsresult rv = OpenRedirectChannel(aStatus);
10705 LOG(("Opening redirect channel for auth retry %x",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opening redirect channel for auth retry %x", static_cast<
uint32_t>(rv)); } } while (0)
10706 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Opening redirect channel for auth retry %x", static_cast<
uint32_t>(rv)); } } while (0)
;
10707 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10708 if (mListener) {
10709 MOZ_ASSERT(!LoadOnStartRequestCalled(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
" (" "We should not call OnStartRequest twice." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10710); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10710); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10710 "We should not call OnStartRequest twice.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStartRequestCalled())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStartRequestCalled()"
" (" "We should not call OnStartRequest twice." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10710); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10710); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10711 if (!LoadOnStartRequestCalled()) {
10712 nsCOMPtr<nsIStreamListener> listener(mListener);
10713 StoreOnStartRequestCalled(true);
10714 listener->OnStartRequest(this);
10715 }
10716 } else {
10717 StoreOnStartRequestCalled(true);
10718 NS_WARNING("OnStartRequest skipped because of null listener")NS_DebugBreak(NS_DEBUG_WARNING, "OnStartRequest skipped because of null listener"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10718)
;
10719 }
10720 }
10721 mAuthRetryPending = false;
10722 }
10723
10724 if (LoadUsedNetwork() && !mReportedNEL) {
10725 MaybeGenerateNELReport();
10726 }
10727
10728 // notify "http-on-before-stop-request" observers
10729 gHttpHandler->OnBeforeStopRequest(this);
10730
10731 if (mListener) {
10732 LOG(("nsHttpChannel %p calling OnStopRequest\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p calling OnStopRequest\n", this); } } while
(0)
;
10733 MOZ_ASSERT(LoadOnStartRequestCalled(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadOnStartRequestCalled()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("LoadOnStartRequestCalled()"
" (" "OnStartRequest should be called before OnStopRequest" ")"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10734
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { MOZ_CrashSequence(__null, 10734); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10734 "OnStartRequest should be called before OnStopRequest")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadOnStartRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadOnStartRequestCalled()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("LoadOnStartRequestCalled()"
" (" "OnStartRequest should be called before OnStopRequest" ")"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10734
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { MOZ_CrashSequence(__null, 10734); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10735 MOZ_ASSERT(!LoadOnStopRequestCalled(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStopRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStopRequestCalled()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStopRequestCalled()"
" (" "We should not call OnStopRequest twice" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { MOZ_CrashSequence
(__null, 10736); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10736 "We should not call OnStopRequest twice")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadOnStopRequestCalled())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadOnStopRequestCalled()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!LoadOnStopRequestCalled()"
" (" "We should not call OnStopRequest twice" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { MOZ_CrashSequence
(__null, 10736); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10737 StoreOnStopRequestCalled(true);
10738 nsCOMPtr<nsIStreamListener> listener(mListener);
10739 listener->OnStopRequest(this, aStatus);
10740 }
10741 StoreOnStopRequestCalled(true);
10742
10743 // The prefetch needs to be released on the main thread
10744 mDNSPrefetch = nullptr;
10745
10746 mRedirectChannel = nullptr;
10747
10748 // notify "http-on-stop-request" observers
10749 gHttpHandler->OnStopRequest(this);
10750
10751 RemoveAsNonTailRequest();
10752
10753 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref &&
10754 mResponseHead) {
10755 mResponseHead->ClearHeaders();
10756 }
10757 // If a preferred alt-data type was set, this signals the consumer is
10758 // interested in reading and/or writing the alt-data representation.
10759 // We need to hold a reference to the cache entry in case the listener calls
10760 // openAlternativeOutputStream() after CloseCacheEntry() clears mCacheEntry.
10761 if (!mPreferredCachedAltDataTypes.IsEmpty()) {
10762 mAltDataCacheEntry = mCacheEntry;
10763 }
10764
10765 CloseCacheEntry(!aContentComplete);
10766 mWritingToCache = false;
10767
10768 if (mLoadGroup) {
10769 mLoadGroup->RemoveRequest(this, nullptr, aStatus);
10770 }
10771
10772 // We don't need this info anymore
10773 CleanRedirectCacheChainIfNecessary();
10774
10775 ReleaseListeners();
10776
10777 // Release mUploadStream to free some memory sooner.
10778 // We release this in background thread to avoid blocking I/O operations on
10779 // main thread See Bug 1940224
10780 (void)NS_DispatchBackgroundTask(NS_NewRunnableFunction(
10781 "release HttpBaseChannel::mUploadStream",
10782 [uploadStream = std::move(mUploadStream)]() { (void)uploadStream; }));
10783
10784 return NS_OK;
10785}
10786
10787//-----------------------------------------------------------------------------
10788// nsHttpChannel::nsIStreamListener
10789//-----------------------------------------------------------------------------
10790
10791class OnTransportStatusAsyncEvent : public Runnable {
10792 public:
10793 OnTransportStatusAsyncEvent(nsITransportEventSink* aEventSink,
10794 nsresult aTransportStatus, int64_t aProgress,
10795 int64_t aProgressMax)
10796 : Runnable("net::OnTransportStatusAsyncEvent"),
10797 mEventSink(aEventSink),
10798 mTransportStatus(aTransportStatus),
10799 mProgress(aProgress),
10800 mProgressMax(aProgressMax) {
10801 MOZ_ASSERT(!NS_IsMainThread(), "Shouldn't be created on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!NS_IsMainThread()"
" (" "Shouldn't be created on main thread" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "Shouldn't be created on main thread" ")"); do { MOZ_CrashSequence
(__null, 10801); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10802 }
10803
10804 NS_IMETHODvirtual nsresult Run() override {
10805 MOZ_ASSERT(NS_IsMainThread(), "Should run on main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Should run on main thread" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10805); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should run on main thread" ")"); do { MOZ_CrashSequence
(__null, 10805); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10806 if (mEventSink) {
10807 mEventSink->OnTransportStatus(nullptr, mTransportStatus, mProgress,
10808 mProgressMax);
10809 }
10810 return NS_OK;
10811 }
10812
10813 private:
10814 nsCOMPtr<nsITransportEventSink> mEventSink;
10815 nsresult mTransportStatus;
10816 int64_t mProgress;
10817 int64_t mProgressMax;
10818};
10819
10820NS_IMETHODIMPnsresult
10821nsHttpChannel::OnDataAvailable(nsIRequest* request, nsIInputStream* input,
10822 uint64_t offset, uint32_t count) {
10823 nsresult rv;
10824 AUTO_PROFILER_LABEL("nsHttpChannel::OnDataAvailable", NETWORK)mozilla::AutoProfilerLabel raiiObject10824( "nsHttpChannel::OnDataAvailable"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
10825 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnDataAvailable", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10826( "nsHttpChannel::OnDataAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10826 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10826( "nsHttpChannel::OnDataAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10827
10828 LOG(("nsHttpChannel::OnDataAvailable [this=%p request=%p offset=%" PRIu64do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnDataAvailable [this=%p request=%p offset=%"
"l" "u" " count=%" "u" "]\n", this, request, offset, count);
} } while (0)
10829 " count=%" PRIu32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnDataAvailable [this=%p request=%p offset=%"
"l" "u" " count=%" "u" "]\n", this, request, offset, count);
} } while (0)
10830 this, request, offset, count))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnDataAvailable [this=%p request=%p offset=%"
"l" "u" " count=%" "u" "]\n", this, request, offset, count);
} } while (0)
;
10831
10832 LOG((" requestFromCache: %d mFirstResponseSource: %d\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " requestFromCache: %d mFirstResponseSource: %d\n", request
== mCachePump, static_cast<int32_t>(mFirstResponseSource
)); } } while (0)
10833 request == mCachePump, static_cast<int32_t>(mFirstResponseSource)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " requestFromCache: %d mFirstResponseSource: %d\n", request
== mCachePump, static_cast<int32_t>(mFirstResponseSource
)); } } while (0)
;
10834
10835 // don't send out OnDataAvailable notifications if we've been canceled.
10836 if (mCanceled) return mStatus;
10837
10838 if (mAuthRetryPending ||
10839 (request == mTransactionPump && LoadTransactionReplaced())) {
10840 uint32_t n;
10841 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &n);
10842 }
10843
10844 MOZ_ASSERT(mResponseHead, "No response head in ODA!!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mResponseHead)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mResponseHead))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mResponseHead" " ("
"No response head in ODA!!" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10844); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "No response head in ODA!!" ")"); do { MOZ_CrashSequence
(__null, 10844); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10845
10846 MOZ_ASSERT(!(LoadCachedContentIsPartial() && (request == mTransactionPump)),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(LoadCachedContentIsPartial() && (request ==
mTransactionPump)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(LoadCachedContentIsPartial
() && (request == mTransactionPump))))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
" (" "transaction pump not suspended" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { MOZ_CrashSequence
(__null, 10847); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10847 "transaction pump not suspended")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(LoadCachedContentIsPartial() && (request ==
mTransactionPump)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!(LoadCachedContentIsPartial
() && (request == mTransactionPump))))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
" (" "transaction pump not suspended" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10847); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { MOZ_CrashSequence
(__null, 10847); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10848
10849 mIsReadingFromCache = (request == mCachePump);
10850
10851 if (mListener) {
10852 //
10853 // synthesize transport progress event. we do this here since we want
10854 // to delay OnProgress events until we start streaming data. this is
10855 // crucially important since it impacts the lock icon (see bug 240053).
10856 //
10857 nsresult transportStatus;
10858 if (request == mCachePump) {
10859 transportStatus = NS_NET_STATUS_READING;
10860 } else {
10861 transportStatus = NS_NET_STATUS_RECEIVING_FROM;
10862 }
10863
10864 // mResponseHead may reference new or cached headers, but either way it
10865 // holds our best estimate of the total content length. Even in the case
10866 // of a byte range request, the content length stored in the cached
10867 // response headers is what we want to use here.
10868
10869 int64_t progressMax = -1;
10870 rv = GetContentLength(&progressMax);
10871 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10872 NS_WARNING("GetContentLength failed")NS_DebugBreak(NS_DEBUG_WARNING, "GetContentLength failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10872
)
;
10873 }
10874 int64_t progress = mLogicalOffset + count;
10875
10876 if ((progress > progressMax) && (progressMax != -1)) {
10877 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10879)
10878 "unexpected progress values - "NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10879)
10879 "is server exceeding content length?")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10879)
;
10880 }
10881
10882 // make sure params are in range for js
10883 if (!InScriptableRange(progressMax)) {
10884 progressMax = -1;
10885 }
10886
10887 if (!InScriptableRange(progress)) {
10888 progress = -1;
10889 }
10890
10891 if (NS_IsMainThread()) {
10892 OnTransportStatus(nullptr, transportStatus, progress, progressMax);
10893 } else {
10894 rv = NS_DispatchToMainThread(new OnTransportStatusAsyncEvent(
10895 this, transportStatus, progress, progressMax));
10896 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10896); return rv; } } while (false)
;
10897 }
10898
10899 //
10900 // we have to manually keep the logical offset of the stream up-to-date.
10901 // we cannot depend solely on the offset provided, since we may have
10902 // already streamed some data from another source (see, for example,
10903 // OnDoneReadingPartialCacheEntry).
10904 //
10905 int64_t offsetBefore = 0;
10906 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(input);
10907 if (seekable && NS_FAILED(seekable->Tell(&offsetBefore))((bool)(__builtin_expect(!!(NS_FAILED_impl(seekable->Tell(
&offsetBefore))), 0)))
) {
10908 seekable = nullptr;
10909 }
10910
10911 mOnDataAvailableStartTime = TimeStamp::Now();
10912 nsCOMPtr<nsIStreamListener> listener = mListener;
10913 nsresult rv = listener->OnDataAvailable(this, input, mLogicalOffset, count);
10914 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10915 // by contract mListener must read all of "count" bytes, but
10916 // nsInputStreamPump is tolerant to seekable streams that violate that
10917 // and it will redeliver incompletely read data. So we need to do
10918 // the same thing when updating the progress counter to stay in sync.
10919 int64_t offsetAfter, delta;
10920 if (seekable && NS_SUCCEEDED(seekable->Tell(&offsetAfter))((bool)(__builtin_expect(!!(!NS_FAILED_impl(seekable->Tell
(&offsetAfter))), 1)))
) {
10921 delta = offsetAfter - offsetBefore;
10922 if (delta != count) {
10923 count = delta;
10924
10925 NS_WARNING("Listener OnDataAvailable contract violation")NS_DebugBreak(NS_DEBUG_WARNING, "Listener OnDataAvailable contract violation"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10925)
;
10926 nsCOMPtr<nsIConsoleService> consoleService;
10927 consoleService = mozilla::components::Console::Service();
10928 nsAutoString message(nsLiteralString(
10929 u"http channel Listener OnDataAvailable contract violation"));
10930 if (consoleService) {
10931 consoleService->LogStringMessage(message.get());
10932 }
10933 }
10934 }
10935 mLogicalOffset += count;
10936 }
10937
10938 return rv;
10939 }
10940
10941 return NS_ERROR_ABORT;
10942}
10943
10944//-----------------------------------------------------------------------------
10945// nsHttpChannel::nsIThreadRetargetableRequest
10946//-----------------------------------------------------------------------------
10947
10948NS_IMETHODIMPnsresult
10949nsHttpChannel::RetargetDeliveryTo(nsISerialEventTarget* aNewTarget) {
10950 MOZ_ASSERT(NS_IsMainThread(), "Should be called on main thread only")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Should be called on main thread only" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10950); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on main thread only" ")"); do { MOZ_CrashSequence
(__null, 10950); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10951
10952 NS_ENSURE_ARG(aNewTarget)do { if ((__builtin_expect(!!(!(aNewTarget)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aNewTarget" ") failed",
nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10952); return NS_ERROR_INVALID_ARG; } } while (false)
;
10953 if (aNewTarget->IsOnCurrentThread()) {
10954 NS_WARNING("Retargeting delivery to same thread")NS_DebugBreak(NS_DEBUG_WARNING, "Retargeting delivery to same thread"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10954)
;
10955 return NS_OK;
10956 }
10957 // Dictionary operations (saving, decompressing dcb/dcz, or using a
10958 // dictionary for decompression) require the main thread for hash
10959 // accumulation, origin metadata writes, and dictionary data access.
10960 if (mDictSaving || mIsDictionaryCompressed || mDictDecompress) {
10961 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::RetargetDeliveryTo %p refused — dictionary "
"operations active (saving=%p, compressed=%d, decompress=%p)\n"
, this, mDictSaving.get(), mIsDictionaryCompressed, mDictDecompress
.get()); } } while (0)
10962 ("nsHttpChannel::RetargetDeliveryTo %p refused — dictionary "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::RetargetDeliveryTo %p refused — dictionary "
"operations active (saving=%p, compressed=%d, decompress=%p)\n"
, this, mDictSaving.get(), mIsDictionaryCompressed, mDictDecompress
.get()); } } while (0)
10963 "operations active (saving=%p, compressed=%d, decompress=%p)\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::RetargetDeliveryTo %p refused — dictionary "
"operations active (saving=%p, compressed=%d, decompress=%p)\n"
, this, mDictSaving.get(), mIsDictionaryCompressed, mDictDecompress
.get()); } } while (0)
10964 this, mDictSaving.get(), mIsDictionaryCompressed,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::RetargetDeliveryTo %p refused — dictionary "
"operations active (saving=%p, compressed=%d, decompress=%p)\n"
, this, mDictSaving.get(), mIsDictionaryCompressed, mDictDecompress
.get()); } } while (0)
10965 mDictDecompress.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::RetargetDeliveryTo %p refused — dictionary "
"operations active (saving=%p, compressed=%d, decompress=%p)\n"
, this, mDictSaving.get(), mIsDictionaryCompressed, mDictDecompress
.get()); } } while (0)
;
10966 return NS_ERROR_NOT_AVAILABLE;
10967 }
10968 if (!mTransactionPump && !mCachePump) {
10969 LOG(("nsHttpChannel::RetargetDeliveryTo %p %p no pump available\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::RetargetDeliveryTo %p %p no pump available\n"
, this, aNewTarget); } } while (0)
10970 aNewTarget))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::RetargetDeliveryTo %p %p no pump available\n"
, this, aNewTarget); } } while (0)
;
10971 return NS_ERROR_NOT_AVAILABLE;
10972 }
10973
10974 nsresult rv = NS_OK;
10975 // If both cache pump and transaction pump exist, we're probably dealing
10976 // with partially cached content. So, we must be able to retarget both.
10977 nsCOMPtr<nsIThreadRetargetableRequest> retargetableCachePump;
10978 nsCOMPtr<nsIThreadRetargetableRequest> retargetableTransactionPump;
10979 if (mCachePump) {
10980 retargetableCachePump = do_QueryObject(mCachePump);
10981 // nsInputStreamPump should implement this interface.
10982 MOZ_ASSERT(retargetableCachePump)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(retargetableCachePump)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(retargetableCachePump))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("retargetableCachePump"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10982
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableCachePump"
")"); do { MOZ_CrashSequence(__null, 10982); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10983 rv = retargetableCachePump->RetargetDeliveryTo(aNewTarget);
10984 }
10985 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mTransactionPump) {
10986 retargetableTransactionPump = do_QueryObject(mTransactionPump);
10987 // nsInputStreamPump should implement this interface.
10988 MOZ_ASSERT(retargetableTransactionPump)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(retargetableTransactionPump)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(retargetableTransactionPump)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("retargetableTransactionPump"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10988
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableTransactionPump"
")"); do { MOZ_CrashSequence(__null, 10988); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10989 rv = retargetableTransactionPump->RetargetDeliveryTo(aNewTarget);
10990
10991 // If retarget fails for transaction pump, we must restore mCachePump.
10992 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && retargetableCachePump) {
10993 nsCOMPtr<nsISerialEventTarget> main = GetMainThreadSerialEventTarget();
10994 NS_ENSURE_TRUE(main, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(main)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "main" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10994
); return NS_ERROR_UNEXPECTED; } } while (false)
;
10995 rv = retargetableCachePump->RetargetDeliveryTo(main);
10996 }
10997 }
10998 return rv;
10999}
11000
11001NS_IMETHODIMPnsresult
11002nsHttpChannel::GetDeliveryTarget(nsISerialEventTarget** aEventTarget) {
11003 if (mCachePump) {
11004 return mCachePump->GetDeliveryTarget(aEventTarget);
11005 }
11006 if (mTransactionPump) {
11007 nsCOMPtr<nsIThreadRetargetableRequest> request =
11008 do_QueryInterface(mTransactionPump);
11009 return request->GetDeliveryTarget(aEventTarget);
11010 }
11011 return NS_ERROR_NOT_AVAILABLE;
11012}
11013
11014//-----------------------------------------------------------------------------
11015// nsHttpChannel::nsThreadRetargetableStreamListener
11016//-----------------------------------------------------------------------------
11017
11018NS_IMETHODIMPnsresult
11019nsHttpChannel::CheckListenerChain() {
11020 NS_ASSERTION(NS_IsMainThread(), "Should be on main thread!")do { if (!(NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should be on main thread!", "NS_IsMainThread()", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11020); MOZ_PretendNoReturn(); } } while (0)
;
11021 nsresult rv = NS_OK;
11022 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
11023 do_QueryInterface(mListener, &rv);
11024 if (retargetableListener) {
11025 rv = retargetableListener->CheckListenerChain();
11026 }
11027 return rv;
11028}
11029
11030NS_IMETHODIMPnsresult
11031nsHttpChannel::OnDataFinished(nsresult aStatus) {
11032 nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
11033 do_QueryInterface(mListener);
11034
11035 if (listener) {
11036 return listener->OnDataFinished(aStatus);
11037 }
11038
11039 return NS_OK;
11040}
11041
11042//-----------------------------------------------------------------------------
11043// nsHttpChannel::nsITransportEventSink
11044//-----------------------------------------------------------------------------
11045
11046NS_IMETHODIMPnsresult
11047nsHttpChannel::OnTransportStatus(nsITransport* trans, nsresult status,
11048 int64_t progress, int64_t progressMax) {
11049 MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread only")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Should be on main thread only" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11049); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be on main thread only" ")"); do { MOZ_CrashSequence
(__null, 11049); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11050 // cache the progress sink so we don't have to query for it each time.
11051 if (!mProgressSink) GetCallback(mProgressSink);
11052
11053 mLastTransportStatus = status;
11054 if (status == NS_NET_STATUS_CONNECTED_TO ||
11055 status == NS_NET_STATUS_WAITING_FOR) {
11056 bool isTrr = false;
11057 bool echConfigUsed = false;
11058 if (mTransaction) {
11059 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
11060 mEffectiveTRRMode, mTRRSkipReason,
11061 echConfigUsed);
11062
11063 } else {
11064 nsCOMPtr<nsISocketTransport> socketTransport = do_QueryInterface(trans);
11065 if (socketTransport) {
11066 socketTransport->GetPeerAddr(&mPeerAddr);
11067 socketTransport->GetSelfAddr(&mSelfAddr);
11068 socketTransport->ResolvedByTRR(&isTrr);
11069 socketTransport->GetEffectiveTRRMode(&mEffectiveTRRMode);
11070 socketTransport->GetEchConfigUsed(&echConfigUsed);
11071 }
11072 }
11073
11074 StoreResolvedByTRR(isTrr);
11075 StoreEchConfigUsed(echConfigUsed);
11076 }
11077
11078 // block socket status event after Cancel or OnStopRequest has been called.
11079 if (mProgressSink && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && LoadIsPending()) {
11080 LOG(("sending progress%s notification [this=%p status=%" PRIx32do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "sending progress%s notification [this=%p status=%" "x" " progress=%"
"l" "d" "/%" "l" "d" "]\n", (mLoadFlags & LOAD_BACKGROUND
) ? "" : " and status", this, static_cast<uint32_t>(status
), progress, progressMax); } } while (0)
11081 " progress=%" PRId64 "/%" PRId64 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "sending progress%s notification [this=%p status=%" "x" " progress=%"
"l" "d" "/%" "l" "d" "]\n", (mLoadFlags & LOAD_BACKGROUND
) ? "" : " and status", this, static_cast<uint32_t>(status
), progress, progressMax); } } while (0)
11082 (mLoadFlags & LOAD_BACKGROUND) ? "" : " and status", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "sending progress%s notification [this=%p status=%" "x" " progress=%"
"l" "d" "/%" "l" "d" "]\n", (mLoadFlags & LOAD_BACKGROUND
) ? "" : " and status", this, static_cast<uint32_t>(status
), progress, progressMax); } } while (0)
11083 static_cast<uint32_t>(status), progress, progressMax))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "sending progress%s notification [this=%p status=%" "x" " progress=%"
"l" "d" "/%" "l" "d" "]\n", (mLoadFlags & LOAD_BACKGROUND
) ? "" : " and status", this, static_cast<uint32_t>(status
), progress, progressMax); } } while (0)
;
11084
11085 nsAutoCString host;
11086 mURI->GetHost(host);
11087 nsCOMPtr<nsIProgressEventSink> progressSink(mProgressSink);
11088 if (!(mLoadFlags & LOAD_BACKGROUND)) {
11089 progressSink->OnStatus(this, status, NS_ConvertUTF8toUTF16(host).get());
11090 } else {
11091 nsCOMPtr<nsIParentChannel> parentChannel;
11092 NS_QueryNotificationCallbacks(this, parentChannel);
11093 // If the event sink is |HttpChannelParent|, we have to send status
11094 // events to it even if LOAD_BACKGROUND is set. |HttpChannelParent|
11095 // needs to be aware of whether the status is
11096 // |NS_NET_STATUS_RECEIVING_FROM| or |NS_NET_STATUS_READING|.
11097 // LOAD_BACKGROUND is checked again in |HttpChannelChild|, so the final
11098 // consumer won't get this event.
11099 if (SameCOMIdentity(parentChannel, mProgressSink)) {
11100 progressSink->OnStatus(this, status, NS_ConvertUTF8toUTF16(host).get());
11101 }
11102 }
11103
11104 if (progress > 0) {
11105 if ((progress > progressMax) && (progressMax != -1)) {
11106 NS_WARNING("unexpected progress values")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values",
nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11106)
;
11107 }
11108
11109 // Try to get mProgressSink if it was nulled out during OnStatus.
11110 if (!mProgressSink) {
11111 GetCallback(mProgressSink);
11112 progressSink = mProgressSink;
11113 }
11114 if (progressSink) {
11115 progressSink->OnProgress(this, progress, progressMax);
11116 }
11117 }
11118 }
11119
11120 return NS_OK;
11121}
11122
11123//-----------------------------------------------------------------------------
11124// nsHttpChannel::nsICacheInfoChannel
11125//-----------------------------------------------------------------------------
11126
11127NS_IMETHODIMPnsresult
11128nsHttpChannel::IsFromCache(bool* value) {
11129 if (!LoadIsPending()) return NS_ERROR_NOT_AVAILABLE;
11130
11131 // return false if reading a partial cache entry; the data isn't
11132 // entirely from the cache!
11133 *value = (mCachePump || (mLoadFlags & LOAD_ONLY_IF_MODIFIED)) &&
11134 CachedContentIsValid() && !LoadCachedContentIsPartial();
11135 return NS_OK;
11136}
11137
11138NS_IMETHODIMPnsresult
11139nsHttpChannel::HasCacheEntry(bool* value) {
11140 *value = !!mCacheEntry;
11141 return NS_OK;
11142}
11143
11144NS_IMETHODIMPnsresult
11145nsHttpChannel::GetCacheEntryId(uint64_t* aCacheEntryId) {
11146 if (!mCacheEntry || NS_FAILED(mCacheEntry->GetCacheEntryId(aCacheEntryId))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCacheEntry->GetCacheEntryId
(aCacheEntryId))), 0)))
) {
11147 return NS_ERROR_NOT_AVAILABLE;
11148 }
11149
11150 return NS_OK;
11151}
11152
11153NS_IMETHODIMPnsresult
11154nsHttpChannel::GetCacheTokenFetchCount(uint32_t* _retval) {
11155 NS_ENSURE_ARG_POINTER(_retval)do { if ((__builtin_expect(!!(!(_retval)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_retval" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11155
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11156 nsCOMPtr<nsICacheEntry> cacheEntry =
11157 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11158 if (!cacheEntry) {
11159 return NS_ERROR_NOT_AVAILABLE;
11160 }
11161
11162 return cacheEntry->GetFetchCount(_retval);
11163}
11164
11165NS_IMETHODIMPnsresult
11166nsHttpChannel::GetCacheTokenExpirationTime(uint32_t* _retval) {
11167 NS_ENSURE_ARG_POINTER(_retval)do { if ((__builtin_expect(!!(!(_retval)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_retval" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11167
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11168 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
11169
11170 return mCacheEntry->GetExpirationTime(_retval);
11171}
11172
11173NS_IMETHODIMPnsresult
11174nsHttpChannel::SetAllowStaleCacheContent(bool aAllowStaleCacheContent) {
11175 LOG(("nsHttpChannel::SetAllowStaleCacheContent [this=%p, allow=%d]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetAllowStaleCacheContent [this=%p, allow=%d]"
, this, aAllowStaleCacheContent); } } while (0)
11176 aAllowStaleCacheContent))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetAllowStaleCacheContent [this=%p, allow=%d]"
, this, aAllowStaleCacheContent); } } while (0)
;
11177 StoreAllowStaleCacheContent(aAllowStaleCacheContent);
11178 return NS_OK;
11179}
11180NS_IMETHODIMPnsresult
11181nsHttpChannel::GetAllowStaleCacheContent(bool* aAllowStaleCacheContent) {
11182 NS_ENSURE_ARG(aAllowStaleCacheContent)do { if ((__builtin_expect(!!(!(aAllowStaleCacheContent)), 0)
)) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aAllowStaleCacheContent"
") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11182); return NS_ERROR_INVALID_ARG; } } while (false)
;
11183 *aAllowStaleCacheContent = LoadAllowStaleCacheContent();
11184 return NS_OK;
11185}
11186
11187NS_IMETHODIMPnsresult
11188nsHttpChannel::SetForceValidateCacheContent(bool aForceValidateCacheContent) {
11189 LOG(("nsHttpChannel::SetForceValidateCacheContent [this=%p, allow=%d]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetForceValidateCacheContent [this=%p, allow=%d]"
, this, aForceValidateCacheContent); } } while (0)
11190 aForceValidateCacheContent))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetForceValidateCacheContent [this=%p, allow=%d]"
, this, aForceValidateCacheContent); } } while (0)
;
11191 StoreForceValidateCacheContent(aForceValidateCacheContent);
11192 return NS_OK;
11193}
11194NS_IMETHODIMPnsresult
11195nsHttpChannel::GetForceValidateCacheContent(bool* aForceValidateCacheContent) {
11196 NS_ENSURE_ARG(aForceValidateCacheContent)do { if ((__builtin_expect(!!(!(aForceValidateCacheContent)),
0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aForceValidateCacheContent"
") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11196); return NS_ERROR_INVALID_ARG; } } while (false)
;
11197 *aForceValidateCacheContent = LoadForceValidateCacheContent();
11198 return NS_OK;
11199}
11200
11201NS_IMETHODIMPnsresult
11202nsHttpChannel::SetPreferCacheLoadOverBypass(bool aPreferCacheLoadOverBypass) {
11203 StorePreferCacheLoadOverBypass(aPreferCacheLoadOverBypass);
11204 return NS_OK;
11205}
11206NS_IMETHODIMPnsresult
11207nsHttpChannel::GetPreferCacheLoadOverBypass(bool* aPreferCacheLoadOverBypass) {
11208 NS_ENSURE_ARG(aPreferCacheLoadOverBypass)do { if ((__builtin_expect(!!(!(aPreferCacheLoadOverBypass)),
0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPreferCacheLoadOverBypass"
") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11208); return NS_ERROR_INVALID_ARG; } } while (false)
;
11209 *aPreferCacheLoadOverBypass = LoadPreferCacheLoadOverBypass();
11210 return NS_OK;
11211}
11212
11213nsresult nsHttpChannel::SetNavigationalPrefetchCacheURI(nsIURI* aURI) {
11214 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11214); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11214, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11214); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11214); return NS_ERROR_IN_PROGRESS; } } while (false); do {
if ((__builtin_expect(!!(!(!LoadWasOpened())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadWasOpened()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11214); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
11215 mNavigationalPrefetchCacheURI = aURI;
11216 return NS_OK;
11217}
11218
11219NS_IMETHODIMPnsresult
11220nsHttpChannel::PreferAlternativeDataType(
11221 const nsACString& aType, const nsACString& aContentType,
11222 PreferredAlternativeDataDeliveryType aDeliverAltData) {
11223 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11223); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11223, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11223); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11223); return NS_ERROR_IN_PROGRESS; } } while (false); do {
if ((__builtin_expect(!!(!(!LoadWasOpened())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadWasOpened()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11223); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
11224 mPreferredCachedAltDataTypes.AppendElement(PreferredAlternativeDataTypeParams(
11225 nsCString(aType), nsCString(aContentType), aDeliverAltData));
11226 return NS_OK;
11227}
11228
11229const nsTArray<PreferredAlternativeDataTypeParams>&
11230nsHttpChannel::PreferredAlternativeDataTypes() {
11231 return mPreferredCachedAltDataTypes;
11232}
11233
11234NS_IMETHODIMPnsresult
11235nsHttpChannel::GetAlternativeDataType(nsACString& aType) {
11236 // must be called during or after OnStartRequest
11237 if (!LoadAfterOnStartRequestBegun()) {
11238 return NS_ERROR_NOT_AVAILABLE;
11239 }
11240 aType = mAvailableCachedAltDataType;
11241 return NS_OK;
11242}
11243
11244class CacheEntryWriteHandle : public nsICacheEntryWriteHandle {
11245 virtual ~CacheEntryWriteHandle() = default;
11246
11247 public:
11248 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
11249 NS_DECL_NSICACHEENTRYWRITEHANDLEvirtual nsresult OpenAlternativeOutputStream(const nsACString
& type, int64_t predictedSize, nsIAsyncOutputStream **_retval
) override;
11250
11251 explicit CacheEntryWriteHandle(nsICacheEntry* aCacheEntry)
11252 : mCacheEntry(aCacheEntry) {
11253 MOZ_ASSERT(mCacheEntry)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCacheEntry)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCacheEntry))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mCacheEntry", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 11253); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11254 }
11255
11256 private:
11257 nsCOMPtr<nsICacheEntry> mCacheEntry;
11258};
11259
11260NS_IMPL_ADDREF(CacheEntryWriteHandle)MozExternalRefCountType CacheEntryWriteHandle::AddRef(void) {
static_assert(!std::is_destructible_v<CacheEntryWriteHandle
>, "Reference-counted class " "CacheEntryWriteHandle" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 11260
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CacheEntryWriteHandle" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CacheEntryWriteHandle" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CacheEntryWriteHandle\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11260); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CacheEntryWriteHandle\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11260); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CacheEntryWriteHandle" " not thread-safe");
nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), ("CacheEntryWriteHandle"
), (uint32_t)(sizeof(*this))); return count; }
11261NS_IMPL_RELEASE(CacheEntryWriteHandle)MozExternalRefCountType CacheEntryWriteHandle::Release(void) {
do { static_assert( mozilla::detail::AssertionConditionType<
decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11261); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 11261
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CacheEntryWriteHandle" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CacheEntryWriteHandle" != nullptr))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("\"CacheEntryWriteHandle\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11261); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CacheEntryWriteHandle\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11261); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CacheEntryWriteHandle" " not thread-safe");
const char* const nametmp = "CacheEntryWriteHandle"; nsrefcnt
count = --mRefCnt; NS_LogRelease((this), (count), (nametmp))
; if (count == 0) { mRefCnt = 1; delete (this); return 0; } return
count; }
11262NS_INTERFACE_MAP_BEGIN(CacheEntryWriteHandle)nsresult CacheEntryWriteHandle::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11262); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
11263 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
11264 NS_INTERFACE_MAP_ENTRY(nsICacheEntryWriteHandle)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheEntryWriteHandle>)) foundInterface
= static_cast<nsICacheEntryWriteHandle*>(this); else
11265NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::kIID
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::kIID))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11265); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 11265); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); status
= NS_NOINTERFACE; } else { (foundInterface)->AddRef(); status
= NS_OK; } *aInstancePtr = foundInterface; return status; }
11266
11267NS_IMETHODIMPnsresult
11268CacheEntryWriteHandle::OpenAlternativeOutputStream(
11269 const nsACString& type, int64_t predictedSize,
11270 nsIAsyncOutputStream** _retval) {
11271 nsresult rv =
11272 mCacheEntry->OpenAlternativeOutputStream(type, predictedSize, _retval);
11273 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11274 mCacheEntry->SetMetaDataElement("alt-data-from-child", nullptr);
11275 }
11276 return rv;
11277}
11278
11279NS_IMETHODIMPnsresult
11280nsHttpChannel::GetCacheEntryWriteHandle(nsICacheEntryWriteHandle** _retval) {
11281 nsCOMPtr<nsICacheEntry> cacheEntry =
11282 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11283 if (!cacheEntry) {
11284 return NS_ERROR_NOT_AVAILABLE;
11285 }
11286
11287 nsCOMPtr<nsICacheEntryWriteHandle> handle =
11288 new CacheEntryWriteHandle(cacheEntry);
11289 handle.forget(_retval);
11290 return NS_OK;
11291}
11292
11293NS_IMETHODIMPnsresult
11294nsHttpChannel::OpenAlternativeOutputStream(const nsACString& type,
11295 int64_t predictedSize,
11296 nsIAsyncOutputStream** _retval) {
11297 // OnStopRequest will clear mCacheEntry, but we may use mAltDataCacheEntry
11298 // if the consumer called PreferAlternativeDataType()
11299 nsCOMPtr<nsICacheEntry> cacheEntry =
11300 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11301 if (!cacheEntry) {
11302 return NS_ERROR_NOT_AVAILABLE;
11303 }
11304 nsresult rv =
11305 cacheEntry->OpenAlternativeOutputStream(type, predictedSize, _retval);
11306 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11307 // Clear this metadata flag in case it exists.
11308 // The caller of this method may set it again.
11309 cacheEntry->SetMetaDataElement("alt-data-from-child", nullptr);
11310 }
11311 return rv;
11312}
11313
11314NS_IMETHODIMPnsresult
11315nsHttpChannel::GetOriginalInputStream(nsIInputStreamReceiver* aReceiver) {
11316 if (aReceiver == nullptr) {
11317 return NS_ERROR_INVALID_ARG;
11318 }
11319 nsCOMPtr<nsIInputStream> inputStream;
11320
11321 nsCOMPtr<nsICacheEntry> cacheEntry =
11322 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11323 if (cacheEntry) {
11324 cacheEntry->OpenInputStream(0, getter_AddRefs(inputStream));
11325 }
11326 aReceiver->OnInputStreamReady(inputStream);
11327 return NS_OK;
11328}
11329
11330NS_IMETHODIMPnsresult
11331nsHttpChannel::GetAlternativeDataInputStream(nsIInputStream** aInputStream) {
11332 NS_ENSURE_ARG_POINTER(aInputStream)do { if ((__builtin_expect(!!(!(aInputStream)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aInputStream" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11332); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11333
11334 *aInputStream = nullptr;
11335
11336 nsCOMPtr<nsICacheEntry> cacheEntry =
11337 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11338 if (!mAvailableCachedAltDataType.IsEmpty() && cacheEntry) {
11339 nsresult rv = cacheEntry->OpenAlternativeInputStream(
11340 mAvailableCachedAltDataType, aInputStream);
11341 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11341); return rv; } } while (false)
;
11342 }
11343 return NS_OK;
11344}
11345
11346//-----------------------------------------------------------------------------
11347// nsHttpChannel::nsICachingChannel
11348//-----------------------------------------------------------------------------
11349
11350NS_IMETHODIMPnsresult
11351nsHttpChannel::GetCacheToken(nsISupports** token) {
11352 NS_ENSURE_ARG_POINTER(token)do { if ((__builtin_expect(!!(!(token)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "token" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11352
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11353 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
11354 return CallQueryInterface(mCacheEntry, token);
11355}
11356
11357NS_IMETHODIMPnsresult
11358nsHttpChannel::SetCacheToken(nsISupports* token) {
11359 return NS_ERROR_NOT_IMPLEMENTED;
11360}
11361
11362NS_IMETHODIMPnsresult
11363nsHttpChannel::GetCacheKey(uint32_t* key) {
11364 NS_ENSURE_ARG_POINTER(key)do { if ((__builtin_expect(!!(!(key)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "key" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11364); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11365
11366 LOG(("nsHttpChannel::GetCacheKey [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::GetCacheKey [this=%p]\n", this); } } while (
0)
;
11367
11368 *key = mPostID;
11369 return NS_OK;
11370}
11371
11372NS_IMETHODIMPnsresult
11373nsHttpChannel::SetCacheKey(uint32_t key) {
11374 LOG(("nsHttpChannel::SetCacheKey [this=%p key=%u]\n", this, key))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetCacheKey [this=%p key=%u]\n", this, key)
; } } while (0)
;
11375
11376 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11376); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11376, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11376); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11376
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 11376); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
11377
11378 mPostID = key;
11379 return NS_OK;
11380}
11381
11382NS_IMETHODIMPnsresult
11383nsHttpChannel::GetCacheOnlyMetadata(bool* aOnlyMetadata) {
11384 NS_ENSURE_ARG(aOnlyMetadata)do { if ((__builtin_expect(!!(!(aOnlyMetadata)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aOnlyMetadata" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11384); return NS_ERROR_INVALID_ARG; } } while (false)
;
11385 *aOnlyMetadata = LoadCacheOnlyMetadata();
11386 return NS_OK;
11387}
11388
11389NS_IMETHODIMPnsresult
11390nsHttpChannel::SetCacheOnlyMetadata(bool aOnlyMetadata) {
11391 LOG(("nsHttpChannel::SetCacheOnlyMetadata [this=%p only-metadata=%d]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetCacheOnlyMetadata [this=%p only-metadata=%d]\n"
, this, aOnlyMetadata); } } while (0)
11392 aOnlyMetadata))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetCacheOnlyMetadata [this=%p only-metadata=%d]\n"
, this, aOnlyMetadata); } } while (0)
;
11393
11394 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11394); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11394, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11394); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11394); return NS_ERROR_IN_PROGRESS; } } while (false); do {
if ((__builtin_expect(!!(!(!LoadWasOpened())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "!LoadWasOpened()" ") failed"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11394); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
11395
11396 StoreCacheOnlyMetadata(aOnlyMetadata);
11397 if (aOnlyMetadata) {
11398 mLoadFlags |= LOAD_ONLY_IF_MODIFIED;
11399 }
11400
11401 return NS_OK;
11402}
11403
11404NS_IMETHODIMPnsresult
11405nsHttpChannel::GetPin(bool* aPin) {
11406 NS_ENSURE_ARG(aPin)do { if ((__builtin_expect(!!(!(aPin)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aPin" ") failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11406
); return NS_ERROR_INVALID_ARG; } } while (false)
;
11407 *aPin = LoadPinCacheContent();
11408 return NS_OK;
11409}
11410
11411NS_IMETHODIMPnsresult
11412nsHttpChannel::SetPin(bool aPin) {
11413 LOG(("nsHttpChannel::SetPin [this=%p pin=%d]\n", this, aPin))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetPin [this=%p pin=%d]\n", this, aPin); } }
while (0)
;
11414
11415 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11415); do { bool abort = true; const char* e = PR_GetEnv("NECKO_ERRORS_ARE_FATAL"
); if (e) abort = (*e == '0') ? false : true; if (abort) { msg
.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=0 in your environment "
"to convert this error into a warning.)"); MOZ_Crash("./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11415, msg.get()); } else { msg.AppendLiteral( " (set NECKO_ERRORS_ARE_FATAL=1 in your environment "
"to convert this warning into a fatal error.)"); NS_DebugBreak
(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11415); } } while (0); if (LoadIsPending()) return NS_ERROR_IN_PROGRESS
; do { static_assert( mozilla::detail::AssertionConditionType
<decltype(LoadWasOpened())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWasOpened()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("LoadWasOpened()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11415
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 11415); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
11416
11417 StorePinCacheContent(aPin);
11418 return NS_OK;
11419}
11420
11421NS_IMETHODIMPnsresult
11422nsHttpChannel::ForceCacheEntryValidFor(uint32_t aSecondsToTheFuture) {
11423 if (!mCacheEntry) {
11424 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ForceCacheEntryValidFor found no cache entry "
"for this channel [this=%p].", this); } } while (0)
11425 ("nsHttpChannel::ForceCacheEntryValidFor found no cache entry "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ForceCacheEntryValidFor found no cache entry "
"for this channel [this=%p].", this); } } while (0)
11426 "for this channel [this=%p].",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ForceCacheEntryValidFor found no cache entry "
"for this channel [this=%p].", this); } } while (0)
11427 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ForceCacheEntryValidFor found no cache entry "
"for this channel [this=%p].", this); } } while (0)
;
11428 } else {
11429 mCacheEntry->ForceValidFor(aSecondsToTheFuture);
11430
11431 nsAutoCString key;
11432 mCacheEntry->GetKey(key);
11433
11434 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ForceCacheEntryValidFor successfully forced valid "
"entry with key %s for %d seconds. [this=%p]", key.get(), aSecondsToTheFuture
, this); } } while (0)
11435 ("nsHttpChannel::ForceCacheEntryValidFor successfully forced valid "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ForceCacheEntryValidFor successfully forced valid "
"entry with key %s for %d seconds. [this=%p]", key.get(), aSecondsToTheFuture
, this); } } while (0)
11436 "entry with key %s for %d seconds. [this=%p]",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ForceCacheEntryValidFor successfully forced valid "
"entry with key %s for %d seconds. [this=%p]", key.get(), aSecondsToTheFuture
, this); } } while (0)
11437 key.get(), aSecondsToTheFuture, this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ForceCacheEntryValidFor successfully forced valid "
"entry with key %s for %d seconds. [this=%p]", key.get(), aSecondsToTheFuture
, this); } } while (0)
;
11438 }
11439
11440 return NS_OK;
11441}
11442
11443//-----------------------------------------------------------------------------
11444// nsHttpChannel::nsIResumableChannel
11445//-----------------------------------------------------------------------------
11446
11447NS_IMETHODIMPnsresult
11448nsHttpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) {
11449 LOG(("nsHttpChannel::ResumeAt [this=%p startPos=%" PRIu64 " id='%s']\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResumeAt [this=%p startPos=%" "l" "u" " id='%s']\n"
, this, aStartPos, TPromiseFlatString<char>(aEntityID).
get()); } } while (0)
11450 aStartPos, PromiseFlatCString(aEntityID).get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ResumeAt [this=%p startPos=%" "l" "u" " id='%s']\n"
, this, aStartPos, TPromiseFlatString<char>(aEntityID).
get()); } } while (0)
;
11451 mEntityID = aEntityID;
11452 mStartPos = aStartPos;
11453 StoreResuming(true);
11454 return NS_OK;
11455}
11456
11457nsresult nsHttpChannel::DoAuthRetry(
11458 HttpTransactionShell* aTransWithStickyConn,
11459 const std::function<nsresult(nsHttpChannel*, nsresult)>&
11460 aContinueOnStopRequestFunc) {
11461 LOG(("nsHttpChannel::DoAuthRetry [this=%p, aTransWithStickyConn=%p]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::DoAuthRetry [this=%p, aTransWithStickyConn=%p]\n"
, this, aTransWithStickyConn); } } while (0)
11462 aTransWithStickyConn))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::DoAuthRetry [this=%p, aTransWithStickyConn=%p]\n"
, this, aTransWithStickyConn); } } while (0)
;
11463
11464 MOZ_ASSERT(!mTransaction, "should not have a transaction")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mTransaction)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mTransaction))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mTransaction" " ("
"should not have a transaction" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11464); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mTransaction"
") (" "should not have a transaction" ")"); do { MOZ_CrashSequence
(__null, 11464); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11465
11466 // Clear security info so it can be repopulated by the retried connection.
11467 mSecurityInfo = nullptr;
11468
11469 // Note that we don't have to toggle |IsPending| anymore. See the reasons
11470 // below.
11471 // 1. We can't suspend the channel during "http-on-modify-request"
11472 // when |IsPending| is false.
11473 // 2. We don't check |IsPending| in SetRequestHeader now.
11474
11475 // Reset RequestObserversCalled because we've probably called the request
11476 // observers once already.
11477 StoreRequestObserversCalled(false);
11478
11479 // fetch cookies, and add them to the request header.
11480 // the server response could have included cookies that must be sent with
11481 // this authentication attempt (bug 84794).
11482 // TODO: save cookies from auth response and send them here (bug 572151).
11483 AddCookiesToRequest();
11484
11485 // notify "http-on-modify-request" observers
11486 CallOnModifyRequestObservers();
11487
11488 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
11489 return CallOrWaitForResume(
11490 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
11491 return self->ContinueDoAuthRetry(trans, aContinueOnStopRequestFunc);
11492 });
11493}
11494
11495nsresult nsHttpChannel::ContinueDoAuthRetry(
11496 HttpTransactionShell* aTransWithStickyConn,
11497 const std::function<nsresult(nsHttpChannel*, nsresult)>&
11498 aContinueOnStopRequestFunc) {
11499 LOG(("nsHttpChannel::ContinueDoAuthRetry [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::ContinueDoAuthRetry [this=%p]\n", this); } }
while (0)
;
11500 StoreIsPending(true);
11501
11502 // get rid of the old response headers
11503 mResponseHead = nullptr;
11504
11505 // rewind the upload stream
11506 if (mUploadStream) {
11507 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
11508 nsresult rv = NS_ERROR_NO_INTERFACE;
11509 if (seekable) {
11510 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
11511 }
11512
11513 // This should not normally happen, but it's possible that big memory
11514 // blobs originating in the other process can't be rewinded.
11515 // In that case we just fail the request, otherwise the content length
11516 // will not match and this load will never complete.
11517 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11517); return rv; } } while (false)
;
11518 }
11519
11520 // always set sticky connection flag
11521 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
11522 // and when needed, allow restart regardless the sticky flag
11523 if (LoadAuthConnectionRestartable()) {
11524 LOG((" connection made restartable"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " connection made restartable"); } } while (0)
;
11525 mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
11526 StoreAuthConnectionRestartable(false);
11527 } else {
11528 LOG((" connection made non-restartable"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " connection made non-restartable"); } } while (0)
;
11529 mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
11530 }
11531
11532 // notify "http-on-before-connect" observers
11533 gHttpHandler->OnBeforeConnect(this);
11534
11535 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
11536 return CallOrWaitForResume(
11537 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
11538 nsresult rv = self->DoConnect(trans);
11539 return aContinueOnStopRequestFunc(self, rv);
11540 });
11541}
11542
11543//-----------------------------------------------------------------------------
11544// nsHttpChannel::nsIAsyncVerifyRedirectCallback
11545//-----------------------------------------------------------------------------
11546
11547nsresult nsHttpChannel::WaitForRedirectCallback() {
11548 nsresult rv;
11549 LOG(("nsHttpChannel::WaitForRedirectCallback [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::WaitForRedirectCallback [this=%p]\n", this)
; } } while (0)
;
11550
11551 if (mTransactionPump) {
11552 rv = mTransactionPump->Suspend();
11553 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11553); return rv; } } while (false)
;
11554 }
11555 if (mCachePump) {
11556 rv = mCachePump->Suspend();
11557 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && mTransactionPump) {
11558#ifdef DEBUG1
11559 nsresult resume =
11560#endif
11561 mTransactionPump->Resume();
11562 MOZ_ASSERT(NS_SUCCEEDED(resume), "Failed to resume transaction pump")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(resume))
, 1))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(resume))
, 1)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(resume)), 1)))"
" (" "Failed to resume transaction pump" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(resume)), 1)))"
") (" "Failed to resume transaction pump" ")"); do { MOZ_CrashSequence
(__null, 11562); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11563 }
11564 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11564); return rv; } } while (false)
;
11565 }
11566
11567 StoreWaitingForRedirectCallback(true);
11568 return NS_OK;
11569}
11570
11571NS_IMETHODIMPnsresult
11572nsHttpChannel::OnRedirectVerifyCallback(nsresult result) {
11573 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnRedirectVerifyCallback [this=%p] " "result=%"
"x" " stack=%zu WaitingForRedirectCallback=%u\n", this, static_cast
<uint32_t>(result), mRedirectFuncStack.Length(), LoadWaitingForRedirectCallback
()); } } while (0)
11574 ("nsHttpChannel::OnRedirectVerifyCallback [this=%p] "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnRedirectVerifyCallback [this=%p] " "result=%"
"x" " stack=%zu WaitingForRedirectCallback=%u\n", this, static_cast
<uint32_t>(result), mRedirectFuncStack.Length(), LoadWaitingForRedirectCallback
()); } } while (0)
11575 "result=%" PRIx32 " stack=%zu WaitingForRedirectCallback=%u\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnRedirectVerifyCallback [this=%p] " "result=%"
"x" " stack=%zu WaitingForRedirectCallback=%u\n", this, static_cast
<uint32_t>(result), mRedirectFuncStack.Length(), LoadWaitingForRedirectCallback
()); } } while (0)
11576 this, static_cast<uint32_t>(result), mRedirectFuncStack.Length(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnRedirectVerifyCallback [this=%p] " "result=%"
"x" " stack=%zu WaitingForRedirectCallback=%u\n", this, static_cast
<uint32_t>(result), mRedirectFuncStack.Length(), LoadWaitingForRedirectCallback
()); } } while (0)
11577 LoadWaitingForRedirectCallback()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnRedirectVerifyCallback [this=%p] " "result=%"
"x" " stack=%zu WaitingForRedirectCallback=%u\n", this, static_cast
<uint32_t>(result), mRedirectFuncStack.Length(), LoadWaitingForRedirectCallback
()); } } while (0)
;
11578 MOZ_ASSERT(LoadWaitingForRedirectCallback(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadWaitingForRedirectCallback())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWaitingForRedirectCallback
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("LoadWaitingForRedirectCallback()" " (" "Someone forgot to call WaitForRedirectCallback() ?!"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { MOZ_CrashSequence(__null, 11579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11579 "Someone forgot to call WaitForRedirectCallback() ?!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadWaitingForRedirectCallback())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadWaitingForRedirectCallback
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("LoadWaitingForRedirectCallback()" " (" "Someone forgot to call WaitForRedirectCallback() ?!"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { MOZ_CrashSequence(__null, 11579); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11580 StoreWaitingForRedirectCallback(false);
11581
11582 if (mCanceled && NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) result = NS_BINDING_ABORTED;
11583
11584 for (uint32_t i = mRedirectFuncStack.Length(); i > 0;) {
11585 --i;
11586 // Pop the last function pushed to the stack
11587 nsContinueRedirectionFunc func = mRedirectFuncStack.PopLastElement();
11588
11589 // Call it with the result we got from the callback or the deeper
11590 // function call.
11591 result = (this->*func)(result);
11592
11593 // If a new function has been pushed to the stack and placed us in the
11594 // waiting state, we need to break the chain and wait for the callback
11595 // again.
11596 if (LoadWaitingForRedirectCallback()) break;
11597 }
11598
11599 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
11600 // First, cancel this channel if we are in failure state to set mStatus
11601 // and let it be propagated to pumps.
11602 Cancel(result);
11603 }
11604
11605 if (!LoadWaitingForRedirectCallback()) {
11606 // We are not waiting for the callback. At this moment we must release
11607 // reference to the redirect target channel, otherwise we may leak.
11608 // However, if we are redirecting due to auth retries, we open the
11609 // redirected channel after OnStopRequest. In that case we should not
11610 // release the reference
11611 if (!StaticPrefs::network_auth_use_redirect_for_retries() ||
11612 !mAuthRetryPending) {
11613 mRedirectChannel = nullptr;
11614 }
11615 }
11616
11617 // We always resume the pumps here. If all functions on stack have been
11618 // called we need OnStopRequest to be triggered, and if we broke out of the
11619 // loop above (and are thus waiting for a new callback) the suspension
11620 // count must be balanced in the pumps.
11621 if (mTransactionPump) mTransactionPump->Resume();
11622 if (mCachePump) mCachePump->Resume();
11623
11624 return result;
11625}
11626
11627void nsHttpChannel::PushRedirectAsyncFunc(nsContinueRedirectionFunc func) {
11628 mRedirectFuncStack.AppendElement(func);
11629}
11630
11631void nsHttpChannel::PopRedirectAsyncFunc(nsContinueRedirectionFunc func) {
11632 MOZ_ASSERT(func == mRedirectFuncStack.LastElement(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(func == mRedirectFuncStack.LastElement())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(func == mRedirectFuncStack.LastElement()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("func == mRedirectFuncStack.LastElement()"
" (" "Trying to pop wrong method from redirect async stack!"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { MOZ_CrashSequence(__null, 11633); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11633 "Trying to pop wrong method from redirect async stack!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(func == mRedirectFuncStack.LastElement())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(func == mRedirectFuncStack.LastElement()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("func == mRedirectFuncStack.LastElement()"
" (" "Trying to pop wrong method from redirect async stack!"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { MOZ_CrashSequence(__null, 11633); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11634
11635 mRedirectFuncStack.RemoveLastElement();
11636}
11637
11638//-----------------------------------------------------------------------------
11639// nsIDNSListener functions
11640//-----------------------------------------------------------------------------
11641
11642NS_IMETHODIMPnsresult
11643nsHttpChannel::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
11644 nsresult status) {
11645 MOZ_ASSERT(NS_IsMainThread(), "Expecting DNS callback on main thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Expecting DNS callback on main thread." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11645); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { MOZ_CrashSequence
(__null, 11645); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11646
11647 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnLookupComplete [this=%p] prefetch complete%s: "
"%s status[0x%" "x" "]\n", this, mCaps & (1 << 3) ?
", refresh requested" : "", ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(status)), 1))) ? "success" : "failure", static_cast<uint32_t
>(status)); } } while (0)
11648 ("nsHttpChannel::OnLookupComplete [this=%p] prefetch complete%s: "do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnLookupComplete [this=%p] prefetch complete%s: "
"%s status[0x%" "x" "]\n", this, mCaps & (1 << 3) ?
", refresh requested" : "", ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(status)), 1))) ? "success" : "failure", static_cast<uint32_t
>(status)); } } while (0)
11649 "%s status[0x%" PRIx32 "]\n",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnLookupComplete [this=%p] prefetch complete%s: "
"%s status[0x%" "x" "]\n", this, mCaps & (1 << 3) ?
", refresh requested" : "", ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(status)), 1))) ? "success" : "failure", static_cast<uint32_t
>(status)); } } while (0)
11650 this, mCaps & NS_HTTP_REFRESH_DNS ? ", refresh requested" : "",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnLookupComplete [this=%p] prefetch complete%s: "
"%s status[0x%" "x" "]\n", this, mCaps & (1 << 3) ?
", refresh requested" : "", ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(status)), 1))) ? "success" : "failure", static_cast<uint32_t
>(status)); } } while (0)
11651 NS_SUCCEEDED(status) ? "success" : "failure",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnLookupComplete [this=%p] prefetch complete%s: "
"%s status[0x%" "x" "]\n", this, mCaps & (1 << 3) ?
", refresh requested" : "", ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(status)), 1))) ? "success" : "failure", static_cast<uint32_t
>(status)); } } while (0)
11652 static_cast<uint32_t>(status)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnLookupComplete [this=%p] prefetch complete%s: "
"%s status[0x%" "x" "]\n", this, mCaps & (1 << 3) ?
", refresh requested" : "", ((bool)(__builtin_expect(!!(!NS_FAILED_impl
(status)), 1))) ? "success" : "failure", static_cast<uint32_t
>(status)); } } while (0)
;
11653
11654 // Unset DNS cache refresh if it was requested,
11655 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
11656 mCaps &= ~NS_HTTP_REFRESH_DNS(1 << 3);
11657 if (mTransaction) {
11658 mTransaction->SetDNSWasRefreshed();
11659 }
11660 }
11661
11662 return NS_OK;
11663}
11664
11665void nsHttpChannel::OnHTTPSRRAvailable(nsIDNSHTTPSSVCRecord* aRecord) {
11666 MOZ_ASSERT(NS_IsMainThread(), "Expecting DNS callback on main thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Expecting DNS callback on main thread." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { MOZ_CrashSequence
(__null, 11666); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11667
11668 LOG(("nsHttpChannel::OnHTTPSRRAvailable [this=%p, aRecord=%p]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnHTTPSRRAvailable [this=%p, aRecord=%p]\n"
, this, aRecord); } } while (0)
11669 aRecord))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnHTTPSRRAvailable [this=%p, aRecord=%p]\n"
, this, aRecord); } } while (0)
;
11670
11671 if (mHTTPSSVCRecord) {
11672 MOZ_ASSERT(false, "OnHTTPSRRAvailable called twice!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "OnHTTPSRRAvailable called twice!"
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11672); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"OnHTTPSRRAvailable called twice!" ")"); do { MOZ_CrashSequence
(__null, 11672); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11673 return;
11674 }
11675
11676 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
11677 mHTTPSSVCRecord.emplace(std::move(record));
11678 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& httprr = mHTTPSSVCRecord.ref();
11679
11680 if (LoadWaitHTTPSSVCRecord()) {
11681 MOZ_ASSERT(mURI->SchemeIs("http"))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mURI->SchemeIs("http"))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mURI->SchemeIs("http"))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("mURI->SchemeIs(\"http\")"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11681
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mURI->SchemeIs(\"http\")"
")"); do { MOZ_CrashSequence(__null, 11681); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11682
11683 StoreWaitHTTPSSVCRecord(false);
11684 nsresult rv = ContinueOnBeforeConnect(!!httprr, mStatus, !!httprr);
11685 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11686 CloseCacheEntry(false);
11687 (void)AsyncAbort(rv);
11688 }
11689 } else {
11690 // This channel is not canceled and the transaction is not created.
11691 if (httprr && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mTransaction &&
11692 (mFirstResponseSource != RESPONSE_FROM_CACHE)) {
11693 bool hasIPAddress = false;
11694 (void)httprr->GetHasIPAddresses(&hasIPAddress);
11695 glean::http::dns_httpssvc_record_receiving_stage.AccumulateSingleSample(
11696 hasIPAddress ? HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_0
11697 : HTTPSSVC_WITHOUT_IPHINT_RECEIVED_STAGE_0);
11698 StoreHTTPSSVCTelemetryReported(true);
11699 }
11700 }
11701}
11702
11703//-----------------------------------------------------------------------------
11704// nsHttpChannel internal functions
11705//-----------------------------------------------------------------------------
11706
11707// Creates an URI to the given location using current URI for base and charset
11708nsresult nsHttpChannel::CreateNewURI(const char* loc, nsIURI** newURI) {
11709 nsCOMPtr<nsIIOService> ioService;
11710 nsresult rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
11711 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
11712
11713 return ioService->NewURI(nsDependentCString(loc), nullptr, mURI, newURI);
11714}
11715
11716void nsHttpChannel::MaybeInvalidateCacheEntryForSubsequentGet() {
11717 // See RFC 2616 section 5.1.1. These are considered valid
11718 // methods which DO NOT invalidate cache-entries for the
11719 // referred resource. POST, PUT and DELETE as well as any
11720 // other method not listed here will potentially invalidate
11721 // any cached copy of the resource
11722 if (mRequestHead.IsGet() || mRequestHead.IsOptions() ||
11723 mRequestHead.IsHead() || mRequestHead.IsTrace() ||
11724 mRequestHead.IsConnect()) {
11725 return;
11726 }
11727
11728 // Invalidate the request-uri.
11729 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
11730 nsAutoCString key;
11731 mURI->GetAsciiSpec(key);
11732 LOG(("MaybeInvalidateCacheEntryForSubsequentGet [this=%p uri=%s]\n", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "MaybeInvalidateCacheEntryForSubsequentGet [this=%p uri=%s]\n"
, this, key.get()); } } while (0)
11733 key.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "MaybeInvalidateCacheEntryForSubsequentGet [this=%p uri=%s]\n"
, this, key.get()); } } while (0)
;
11734 }
11735
11736 DoInvalidateCacheEntry(mURI);
11737
11738 // Invalidate Location-header if set
11739 nsAutoCString location;
11740 (void)mResponseHead->GetHeader(nsHttp::Location, location);
11741 if (!location.IsEmpty()) {
11742 LOG((" Location-header=%s\n", location.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Location-header=%s\n", location.get()); } } while (0)
;
11743 InvalidateCacheEntryForLocation(location.get());
11744 }
11745
11746 // Invalidate Content-Location-header if set
11747 (void)mResponseHead->GetHeader(nsHttp::Content_Location, location);
11748 if (!location.IsEmpty()) {
11749 LOG((" Content-Location-header=%s\n", location.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " Content-Location-header=%s\n", location.get()); } } while
(0)
;
11750 InvalidateCacheEntryForLocation(location.get());
11751 }
11752}
11753
11754void nsHttpChannel::InvalidateCacheEntryForLocation(const char* location) {
11755 nsAutoCString tmpCacheKey, tmpSpec;
11756 nsCOMPtr<nsIURI> resultingURI;
11757 nsresult rv = CreateNewURI(location, getter_AddRefs(resultingURI));
11758 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && HostPartIsTheSame(resultingURI)) {
11759 DoInvalidateCacheEntry(resultingURI);
11760 } else {
11761 LOG((" hosts not matching\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " hosts not matching\n"); } } while (0)
;
11762 }
11763}
11764
11765void nsHttpChannel::DoInvalidateCacheEntry(nsIURI* aURI) {
11766 // NOTE:
11767 // Following comments 24,32 and 33 in bug #327765, we only care about
11768 // the cache in the protocol-handler.
11769 // The logic below deviates from the original logic in OpenCacheEntry on
11770 // one point by using only READ_ONLY access-policy. I think this is safe.
11771
11772 nsresult rv;
11773
11774 nsAutoCString key;
11775 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
11776 aURI->GetAsciiSpec(key);
11777 }
11778
11779 LOG(("DoInvalidateCacheEntry [channel=%p key=%s]", this, key.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "DoInvalidateCacheEntry [channel=%p key=%s]", this, key.get
()); } } while (0)
;
11780
11781 nsCOMPtr<nsICacheStorageService> cacheStorageService(
11782 components::CacheStorage::Service());
11783 rv = cacheStorageService ? NS_OK : NS_ERROR_FAILURE;
11784
11785 nsCOMPtr<nsICacheStorage> cacheStorage;
11786 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11787 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
11788 rv = cacheStorageService->DiskCacheStorage(info,
11789 getter_AddRefs(cacheStorage));
11790 }
11791
11792 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11793 rv = cacheStorage->AsyncDoomURI(aURI, ""_ns, nullptr);
11794 }
11795
11796 LOG(("DoInvalidateCacheEntry [channel=%p key=%s rv=%d]", this, key.get(),do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "DoInvalidateCacheEntry [channel=%p key=%s rv=%d]", this, key
.get(), int(rv)); } } while (0)
11797 int(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "DoInvalidateCacheEntry [channel=%p key=%s rv=%d]", this, key
.get(), int(rv)); } } while (0)
;
11798}
11799
11800void nsHttpChannel::AsyncOnExamineCachedResponse() {
11801 gHttpHandler->OnExamineCachedResponse(this);
11802}
11803
11804void nsHttpChannel::UpdateAggregateCallbacks() {
11805 if (!mTransaction) {
11806 return;
11807 }
11808 nsCOMPtr<nsIInterfaceRequestor> callbacks;
11809 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
11810 GetCurrentSerialEventTarget(),
11811 getter_AddRefs(callbacks));
11812 mTransaction->SetSecurityCallbacks(callbacks);
11813}
11814
11815NS_IMETHODIMPnsresult
11816nsHttpChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
11817 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Wrong thread." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11817); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { MOZ_CrashSequence(__null, 11817
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
11818
11819 nsresult rv = HttpBaseChannel::SetLoadGroup(aLoadGroup);
11820 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11821 UpdateAggregateCallbacks();
11822 }
11823 return rv;
11824}
11825
11826NS_IMETHODIMPnsresult
11827nsHttpChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
11828 MOZ_ASSERT(NS_IsMainThread(), "Wrong thread.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Wrong thread." ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11828); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { MOZ_CrashSequence(__null, 11828
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
11829
11830 nsresult rv = HttpBaseChannel::SetNotificationCallbacks(aCallbacks);
11831 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11832 UpdateAggregateCallbacks();
11833 }
11834 return rv;
11835}
11836
11837bool nsHttpChannel::AwaitingCacheCallbacks() {
11838 return LoadWaitForCacheEntry() != 0;
11839}
11840
11841// static
11842bool nsHttpChannel::IsRedirectStatus(uint32_t status) {
11843 // 305 disabled as a security measure (see bug 187996).
11844 return status == 301 || status == 302 || status == 303 || status == 307 ||
11845 status == 308;
11846}
11847
11848void nsHttpChannel::SetCouldBeSynthesized() {
11849 MOZ_ASSERT(!BypassServiceWorker())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!BypassServiceWorker())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!BypassServiceWorker()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!BypassServiceWorker()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11849
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
")"); do { MOZ_CrashSequence(__null, 11849); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11850 StoreResponseCouldBeSynthesized(true);
11851}
11852
11853NS_IMETHODIMPnsresult
11854nsHttpChannel::OnPreflightSucceeded() {
11855 MOZ_ASSERT(LoadRequireCORSPreflight(), "Why did a preflight happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadRequireCORSPreflight())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadRequireCORSPreflight()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("LoadRequireCORSPreflight()"
" (" "Why did a preflight happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11855); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { MOZ_CrashSequence
(__null, 11855); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11856 StoreIsCorsPreflightDone(1);
11857 mPreflightChannel = nullptr;
11858
11859 return ContinueConnect();
11860}
11861
11862NS_IMETHODIMPnsresult
11863nsHttpChannel::OnPreflightFailed(nsresult aError) {
11864 MOZ_ASSERT(LoadRequireCORSPreflight(), "Why did a preflight happen?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(LoadRequireCORSPreflight())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(LoadRequireCORSPreflight()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("LoadRequireCORSPreflight()"
" (" "Why did a preflight happen?" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { MOZ_CrashSequence
(__null, 11864); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11865 StoreIsCorsPreflightDone(1);
11866 mPreflightChannel = nullptr;
11867
11868 CloseCacheEntry(false);
11869 (void)AsyncAbort(aError);
11870 return NS_OK;
11871}
11872
11873nsresult nsHttpChannel::CallOrWaitForResume(
11874 const std::function<nsresult(nsHttpChannel*)>& aFunc) {
11875 if (mCanceled) {
11876 MOZ_ASSERT(NS_FAILED(mStatus))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus))
, 0))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus))
, 0)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11876
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))"
")"); do { MOZ_CrashSequence(__null, 11876); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11877 return mStatus;
11878 }
11879
11880 if (mSuspendCount) {
11881 LOG(("Waiting until resume [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "Waiting until resume [this=%p]\n", this); } } while (0)
;
11882 MOZ_ASSERT(!mCallOnResume)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mCallOnResume)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mCallOnResume))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!mCallOnResume"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11882
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume" ")"
); do { MOZ_CrashSequence(__null, 11882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11883 mCallOnResume = aFunc;
11884 return NS_OK;
11885 }
11886
11887 return aFunc(this);
11888}
11889
11890// This is loosely based on:
11891// https://fetch.spec.whatwg.org/#serializing-a-request-origin
11892static bool HasNullRequestOrigin(nsHttpChannel* aChannel, nsIURI* aURI,
11893 bool isAddonRequest) {
11894 // Step 1. If request has a redirect-tainted origin, then return "null".
11895 if (aChannel->HasRedirectTaintedOrigin()) {
11896 return true;
11897 }
11898
11899 // Non-standard: Only allow HTTP and HTTPS origins.
11900 if (!ReferrerInfo::IsReferrerSchemeAllowed(aURI)) {
11901 // And moz-extension: for add-on initiated requests.
11902 if (!aURI->SchemeIs("moz-extension") || !isAddonRequest) {
11903 return true;
11904 }
11905 }
11906
11907 // Non-standard: Hide onion URLs.
11908 if (StaticPrefs::network_http_referer_hideOnionSource()) {
11909 nsAutoCString host;
11910 if (NS_SUCCEEDED(aURI->GetAsciiHost(host))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aURI->GetAsciiHost
(host))), 1)))
&&
11911 StringEndsWith(host, ".onion"_ns)) {
11912 return ReferrerInfo::IsCrossOriginRequest(aChannel);
11913 }
11914 }
11915
11916 // Step 2. Return request’s origin, serialized.
11917 return false;
11918}
11919
11920// Step 8.12. of HTTP-network-or-cache fetch
11921//
11922// https://fetch.spec.whatwg.org/#append-a-request-origin-header
11923void nsHttpChannel::SetOriginHeader() {
11924 auto* triggeringPrincipal =
11925 BasePrincipal::Cast(mLoadInfo->TriggeringPrincipal());
11926
11927 if (triggeringPrincipal->IsSystemPrincipal()) {
11928 // We can't infer an Origin header from the system principal,
11929 // this means system requests use whatever Origin header was specified.
11930 return;
11931 }
11932 bool isAddonRequest = triggeringPrincipal->AddonPolicy() ||
11933 triggeringPrincipal->ContentScriptAddonPolicy();
11934
11935 // Non-standard: Handle already existing Origin header.
11936 nsAutoCString existingHeader;
11937 (void)mRequestHead.GetHeader(nsHttp::Origin, existingHeader);
11938 if (!existingHeader.IsEmpty()) {
11939 LOG(("nsHttpChannel::SetOriginHeader Origin header already present"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetOriginHeader Origin header already present"
); } } while (0)
;
11940 auto const shouldNullifyOriginHeader =
11941 [&existingHeader, isAddonRequest](nsHttpChannel* aChannel) {
11942 nsCOMPtr<nsIURI> uri;
11943 nsresult rv = NS_NewURI(getter_AddRefs(uri), existingHeader);
11944 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11945 return false;
11946 }
11947
11948 if (HasNullRequestOrigin(aChannel, uri, isAddonRequest)) {
11949 return true;
11950 }
11951
11952 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
11953 if (info->GetTainting() == mozilla::LoadTainting::CORS) {
11954 return false;
11955 }
11956
11957 return ReferrerInfo::ShouldSetNullOriginHeader(aChannel, uri);
11958 };
11959
11960 if (!existingHeader.EqualsLiteral("null") &&
11961 shouldNullifyOriginHeader(this)) {
11962 LOG(("nsHttpChannel::SetOriginHeader null Origin by Referrer-Policy"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::SetOriginHeader null Origin by Referrer-Policy"
); } } while (0)
;
11963 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Origin, "null"_ns, false ))),
1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11964
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { MOZ_CrashSequence(__null, 11964); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
11964 mRequestHead.SetHeader(nsHttp::Origin, "null"_ns, false /* merge */))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Origin, "null"_ns, false ))),
1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 11964
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { MOZ_CrashSequence(__null, 11964); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
11965 }
11966 return;
11967 }
11968
11969 if (StaticPrefs::network_http_sendOriginHeader() == 0) {
11970 // Custom user setting: 0 means never send Origin header.
11971 return;
11972 }
11973
11974 // Step 2. Let serializedOrigin be the result of byte-serializing a request
11975 // origin with request.
11976 nsAutoCString serializedOrigin;
11977 nsCOMPtr<nsIURI> uri;
11978 {
11979 if (NS_FAILED(triggeringPrincipal->GetURI(getter_AddRefs(uri)))((bool)(__builtin_expect(!!(NS_FAILED_impl(triggeringPrincipal
->GetURI(getter_AddRefs(uri)))), 0)))
) {
11980 return;
11981 }
11982
11983 if (!uri) {
11984 if (isAddonRequest) {
11985 // For add-on compatibility prefer sending no header at all
11986 // instead of `Origin: null`.
11987 return;
11988 }
11989
11990 // Otherwise use "null" when the triggeringPrincipal's URI is nullptr.
11991 serializedOrigin.AssignLiteral("null");
11992 } else if (HasNullRequestOrigin(this, uri, isAddonRequest)) {
11993 serializedOrigin.AssignLiteral("null");
11994 } else {
11995 nsContentUtils::GetWebExposedOriginSerialization(uri, serializedOrigin);
11996 }
11997 }
11998
11999 // Step 3. If request’s response tainting is "cors" or request’s mode is
12000 // "websocket", then append (`Origin`, serializedOrigin) to request’s header
12001 // list.
12002 //
12003 // Note: We don't handle "websocket" here (yet?).
12004 if (mLoadInfo->GetTainting() == mozilla::LoadTainting::CORS) {
12005 MOZ_ALWAYS_SUCCEEDS(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin,do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false
))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12006
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12006); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
12006 false /* merge */))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false
))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12006
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12006); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12007 return;
12008 }
12009
12010 // Step 4. Otherwise, if request’s method is neither `GET` nor `HEAD`, then:
12011 if (mRequestHead.IsGet() || mRequestHead.IsHead()) {
12012 // Modified Step 4 in case storage-access-headers are enabled
12013 if (!StaticPrefs::dom_storage_access_enabled() ||
12014 !StaticPrefs::dom_storage_access_headers_enabled()) {
12015 // proceed with unmodified fetch spec
12016 return;
12017 } else {
12018 // the result of getting `Sec-Fetch-Storage-Access` from request’s header
12019 // list is "inactive"
12020 nsAutoCString storageAccess;
12021 nsresult rv =
12022 GetRequestHeader("Sec-Fetch-Storage-Access"_ns, storageAccess);
12023 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !storageAccess.EqualsLiteral("inactive")) {
12024 return;
12025 }
12026 }
12027 }
12028
12029 if (!serializedOrigin.EqualsLiteral("null")) {
12030 // Step 4.1. (Implemented by ReferrerInfo::ShouldSetNullOriginHeader)
12031 if (ReferrerInfo::ShouldSetNullOriginHeader(this, uri)) {
12032 serializedOrigin.AssignLiteral("null");
12033 } else if (StaticPrefs::network_http_sendOriginHeader() == 1) {
12034 // Non-standard: Restrict Origin to same-origin loads if requested by user
12035 nsAutoCString currentOrigin;
12036 nsContentUtils::GetWebExposedOriginSerialization(mURI, currentOrigin);
12037 if (!serializedOrigin.EqualsIgnoreCase(currentOrigin.get())) {
12038 // Origin header suppressed by user setting.
12039 serializedOrigin.AssignLiteral("null");
12040 }
12041 }
12042 }
12043
12044 // Step 4.2. Append (`Origin`, serializedOrigin) to request’s header list.
12045 MOZ_ALWAYS_SUCCEEDS(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin,do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false
))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12046
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12046); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
12046 false /* merge */))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false
))), 1)))), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12046
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12046); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12047}
12048
12049void nsHttpChannel::SetDoNotTrack() {
12050 /**
12051 * 'DoNotTrack' header should be added if 'privacy.donottrackheader.enabled'
12052 * is true.
12053 */
12054 if (StaticPrefs::privacy_donottrackheader_enabled()) {
12055 DebugOnly<nsresult> rv =
12056 mRequestHead.SetHeader(nsHttp::DoNotTrack, "1"_ns, false);
12057 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12057); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 12057); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12058 }
12059}
12060
12061void nsHttpChannel::SetGlobalPrivacyControl() {
12062 MOZ_ASSERT(NS_IsMainThread(), "Must be called on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Must be called on the main thread" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12062); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12062); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12063
12064 if (StaticPrefs::privacy_globalprivacycontrol_enabled() ||
12065 (StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled() &&
12066 NS_UsePrivateBrowsing(this))) {
12067 // Send the header with a value of 1 to indicate opting-out
12068 DebugOnly<nsresult> rv =
12069 mRequestHead.SetHeader(nsHttp::GlobalPrivacyControl, "1"_ns, false);
12070 }
12071}
12072
12073void nsHttpChannel::ReportSystemChannelTelemetry(nsresult status) {
12074 // Use status and httpStatus to determine
12075 // if it was successful, and if we had connectivity / offline in this time
12076 nsAutoCString domain;
12077 mOriginalURI->GetHost(domain);
12078
12079 if (!LoadUsedNetwork()) {
12080 // We're not really interested in any cached requests.
12081 return;
12082 }
12083
12084 if (!StringEndsWith(domain, ".mozilla.org"_ns) &&
12085 !StringEndsWith(domain, ".mozilla.com"_ns) &&
12086 mEssentialDomainCategory.isNothing()) {
12087 return;
12088 }
12089
12090 nsAutoCString label("ok"_ns);
12091 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
12092 if (mCanceled) {
12093 // The request was cancelled.
12094 label = "cancel"_ns;
12095 } else if (NS_IsOffline()) {
12096 // The error occured while all interfaces are offline
12097 label = "offline"_ns;
12098 } else if (!hasConnectivity()) {
12099 // The error occured while the browser didn't have connectivity
12100 label = "connectivity"_ns;
12101 } else if (status == NS_ERROR_UNKNOWN_HOST) {
12102 // The failure was a DNS error
12103 label = "dns"_ns;
12104 } else if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY21) {
12105 // The error was due to TLS
12106 label = "tls_fail"_ns;
12107 } else if (status == NS_ERROR_NET_RESET) {
12108 label = "reset"_ns;
12109 } else if (status == NS_ERROR_NET_TIMEOUT) {
12110 label = "timeout"_ns;
12111 } else if (status == NS_ERROR_CONNECTION_REFUSED) {
12112 label = "refused"_ns;
12113 } else if (status == NS_ERROR_NET_PARTIAL_TRANSFER) {
12114 label = "partial"_ns;
12115 } else {
12116 // Unspecified error. If this bucket is too big we might add other labels.
12117 label = "other"_ns;
12118 }
12119 } else if (mResponseHead && mResponseHead->Status() / 100 != 2) {
12120 // There was no channel error, but the server responded with a non-2XX
12121 // status code.
12122 label = "http_status";
12123 }
12124
12125 // This is the first time failure channel
12126 if (mEssentialDomainCategory.isNothing()) {
12127 auto category = GetEssentialDomainCategory(domain);
12128 switch (category) {
12129 case EssentialDomainCategory::SubAddonsMozillaOrg: {
12130 mozilla::glean::network::system_channel_addonversion_status.Get(label)
12131 .Add(1);
12132 return;
12133 }
12134 case EssentialDomainCategory::AddonsMozillaOrg: {
12135 mozilla::glean::network::system_channel_addon_status.Get(label).Add(1);
12136 return;
12137 }
12138 case EssentialDomainCategory::Aus5MozillaOrg: {
12139 mozilla::glean::network::system_channel_update_status.Get(label).Add(1);
12140 return;
12141 }
12142 case EssentialDomainCategory::RemoteSettings: {
12143 mozilla::glean::network::system_channel_remote_settings_status
12144 .Get(label)
12145 .Add(1);
12146 return;
12147 }
12148 case EssentialDomainCategory::Telemetry: {
12149 mozilla::glean::network::system_channel_telemetry_status.Get(label).Add(
12150 1);
12151 return;
12152 }
12153 default: {
12154 // Not one of the probes we recorded earlier.
12155 mozilla::glean::network::system_channel_other_status.Get(label).Add(1);
12156 return;
12157 }
12158 }
12159 }
12160
12161 // This is a retry.
12162 switch (mEssentialDomainCategory.ref()) {
12163 case EssentialDomainCategory::SubAddonsMozillaOrg: {
12164 mozilla::glean::network::retried_system_channel_addonversion_status
12165 .Get(label)
12166 .Add(1);
12167 return;
12168 }
12169 case EssentialDomainCategory::AddonsMozillaOrg: {
12170 mozilla::glean::network::retried_system_channel_addon_status.Get(label)
12171 .Add(1);
12172 return;
12173 }
12174 case EssentialDomainCategory::Aus5MozillaOrg: {
12175 mozilla::glean::network::retried_system_channel_update_status.Get(label)
12176 .Add(1);
12177 return;
12178 }
12179 case EssentialDomainCategory::RemoteSettings: {
12180 mozilla::glean::network::retried_system_channel_remote_settings_status
12181 .Get(label)
12182 .Add(1);
12183 return;
12184 }
12185 case EssentialDomainCategory::Telemetry: {
12186 mozilla::glean::network::retried_system_channel_telemetry_status
12187 .Get(label)
12188 .Add(1);
12189 return;
12190 }
12191 default: {
12192 // Not one of the probes we recorded earlier.
12193 mozilla::glean::network::retried_system_channel_other_status.Get(label)
12194 .Add(1);
12195 return;
12196 }
12197 }
12198}
12199
12200nsresult nsHttpChannel::TriggerNetwork() {
12201 MOZ_ASSERT(NS_IsMainThread(), "Must be called on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Must be called on the main thread" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12201); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12202
12203 LOG(("nsHttpChannel::TriggerNetwork [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::TriggerNetwork [this=%p]\n", this); } } while
(0)
;
12204
12205 if (mCanceled) {
12206 LOG((" channel was canceled.\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " channel was canceled.\n"); } } while (0)
;
12207 return mStatus;
12208 }
12209
12210 // If a network request has already gone out, there is no point in
12211 // doing this again.
12212 if (mNetworkTriggered) {
12213 LOG((" network already triggered. Returning.\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " network already triggered. Returning.\n"); } } while (0)
;
12214 return NS_OK;
12215 }
12216
12217 mNetworkTriggered = true;
12218
12219 // If we are waiting for a proxy request, that means we can't trigger
12220 // the next step just yet. We need for mConnectionInfo to be non-null
12221 // before we call ContinueConnect. OnProxyAvailable will trigger
12222 // BeginConnect, and Connect will call ContinueConnect even if it's
12223 // for the cache callbacks.
12224 if (mProxyRequest) {
12225 LOG((" proxy request in progress. Delaying network trigger.\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " proxy request in progress. Delaying network trigger.\n")
; } } while (0)
;
12226 mWaitingForProxy = true;
12227 return NS_OK;
12228 }
12229
12230 return ContinueConnect();
12231}
12232
12233nsresult nsHttpChannel::OnSuspendTimeout() {
12234 MOZ_ASSERT(NS_IsMainThread(), "Must be called on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
" (" "Must be called on the main thread" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12234); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12235
12236 LOG(("nsHttpChannel::OnSuspendTimeout [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnSuspendTimeout [this=%p]\n", this); } } while
(0)
;
12237
12238 // If we're still suspended and have a cache entry, enable bypass mode
12239 // This allows any waiting or future listeners to continue
12240 if (mSuspendCount > 0 && mCacheEntry) {
12241 LOG((" suspend timeout: bypassing writer lock"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " suspend timeout: bypassing writer lock"); } } while (0)
;
12242 mCacheEntry->SetBypassWriterLock(true);
12243 mBypassCacheWriterSet = true;
12244 }
12245
12246 return NS_OK;
12247}
12248
12249nsHttpChannel::TimerCallback::TimerCallback(nsHttpChannel* aChannel)
12250 : mChannel(aChannel) {}
12251
12252NS_IMPL_ISUPPORTS(nsHttpChannel::TimerCallback, nsITimerCallback, nsINamed)MozExternalRefCountType nsHttpChannel::TimerCallback::AddRef(
void) { static_assert(!std::is_destructible_v<nsHttpChannel
::TimerCallback>, "Reference-counted class " "nsHttpChannel::TimerCallback"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12252); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12252
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsHttpChannel::TimerCallback" != nullptr)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsHttpChannel::TimerCallback" != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("\"nsHttpChannel::TimerCallback\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12252); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12252); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsHttpChannel::TimerCallback" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"nsHttpChannel::TimerCallback"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType nsHttpChannel::TimerCallback
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12252); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12252
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsHttpChannel::TimerCallback" != nullptr)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("nsHttpChannel::TimerCallback" != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("\"nsHttpChannel::TimerCallback\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12252); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12252); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsHttpChannel::TimerCallback" " not thread-safe"
); const char* const nametmp = "nsHttpChannel::TimerCallback"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult nsHttpChannel::TimerCallback::
QueryInterface(const nsIID& aIID, void** aInstancePtr) { do
{ if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12252); MOZ_PretendNoReturn(); } } while (0); nsresult rv =
NS_ERROR_FAILURE; static_assert(2 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsHttpChannel::TimerCallback, nsITimerCallback
>, int32_t( reinterpret_cast<char*>(static_cast<nsITimerCallback
*>((nsHttpChannel::TimerCallback*)0x1000)) - reinterpret_cast
<char*>((nsHttpChannel::TimerCallback*)0x1000))}, {&
mozilla::detail::kImplementedIID<nsHttpChannel::TimerCallback
, nsINamed>, int32_t( reinterpret_cast<char*>(static_cast
<nsINamed*>((nsHttpChannel::TimerCallback*)0x1000)) - reinterpret_cast
<char*>((nsHttpChannel::TimerCallback*)0x1000))}, {&
mozilla::detail::kImplementedIID<nsHttpChannel::TimerCallback
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsITimerCallback*>((nsHttpChannel
::TimerCallback*)0x1000))) - reinterpret_cast<char*>((nsHttpChannel
::TimerCallback*)0x1000))}, { nullptr, 0 } } ; static_assert(
std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
12253
12254NS_IMETHODIMPnsresult
12255nsHttpChannel::TimerCallback::GetName(nsACString& aName) {
12256 aName.AssignLiteral("nsHttpChannel");
12257 return NS_OK;
12258}
12259
12260NS_IMETHODIMPnsresult
12261nsHttpChannel::TimerCallback::Notify(nsITimer* aTimer) {
12262 if (aTimer == mChannel->mSuspendTimer) {
12263 return mChannel->OnSuspendTimeout();
12264 }
12265 if (aTimer == mChannel->mCacheWaitTimer) {
12266 return mChannel->OnCacheWaitTimeout();
12267 }
12268 MOZ_CRASH("Unknown timer")do { do { } while (false); MOZ_ReportCrash("" "Unknown timer"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12268
); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown timer" ")"); do
{ MOZ_CrashSequence(__null, 12268); __attribute__((nomerge))
::abort(); } while (false); } while (false)
;
12269
12270 return NS_OK;
12271}
12272
12273void nsHttpChannel::MaybeStartCacheWaitTimer() {
12274 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12274
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12274); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12275
12276 uint32_t delay = StaticPrefs::network_cache_entry_wait_timeout_ms();
12277 if (!delay || mCacheWaitTimer || mCacheWaitTimedOut || mNetworkTriggered) {
12278 return;
12279 }
12280
12281 mCacheWaitTimer = NS_NewTimer();
12282 if (mCacheWaitTimer) {
12283 RefPtr<TimerCallback> timerCallback = new TimerCallback(this);
12284 mCacheWaitTimer->InitWithCallback(timerCallback, delay,
12285 nsITimer::TYPE_ONE_SHOT);
12286 LOG(("nsHttpChannel::MaybeStartCacheWaitTimer [this=%p] fires in %ums",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeStartCacheWaitTimer [this=%p] fires in %ums"
, this, delay); } } while (0)
12287 this, delay))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::MaybeStartCacheWaitTimer [this=%p] fires in %ums"
, this, delay); } } while (0)
;
12288 }
12289}
12290
12291void nsHttpChannel::CancelCacheWaitTimer() {
12292 if (mCacheWaitTimer) {
12293 mCacheWaitTimer->Cancel();
12294 mCacheWaitTimer = nullptr;
12295 }
12296}
12297
12298nsresult nsHttpChannel::OnCacheWaitTimeout() {
12299 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12299
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12299); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12300
12301 LOG(("nsHttpChannel::OnCacheWaitTimeout [this=%p]\n", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnCacheWaitTimeout [this=%p]\n", this); } }
while (0)
;
12302 mCacheWaitTimer = nullptr;
12303
12304 // Backstop for a wedged cache entry: if we're still parked waiting for a
12305 // cache entry callback that never arrived (e.g. a writer that was suspended
12306 // or cancelled without ever closing its output stream, so the entry stays
12307 // perpetually "being written"), stop waiting and race to the network so the
12308 // load can make progress instead of hanging forever.
12309 if (!LoadIsPending() || !AwaitingCacheCallbacks()) {
12310 return NS_OK;
12311 }
12312
12313 LOG((" cache entry wait timed out, forcing network [this=%p]", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache entry wait timed out, forcing network [this=%p]", this
); } } while (0)
;
12314 {
12315 // Waits for an OnCacheEntryCheck in flight on the cache I/O thread.
12316 MutexAutoLock lock(mCacheWaitLock);
12317 mCacheWaitTimedOut = true;
12318 }
12319
12320 // Stop treating the outstanding cache open as blocking. We stay registered
12321 // as a callback on the entry, but a late OnCacheEntryCheck or
12322 // OnCacheEntryAvailable will be declined/ignored (see mCacheWaitTimedOut).
12323 StoreWaitForCacheEntry(LoadWaitForCacheEntry() & ~WAIT_FOR_CACHE_ENTRY);
12324
12325 // OnCacheEntryCheck may already have run for an entry we now won't get
12326 // (e.g. it asked to be rechecked once a wedged writer finishes); the network
12327 // response must not carry its conditional headers or alt-data.
12328 DiscardCacheEntryCheckState();
12329
12330 nsresult rv = TriggerNetwork();
12331 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12332 CloseCacheEntry(false);
12333 (void)AsyncAbort(rv);
12334 }
12335 return rv;
12336}
12337
12338bool nsHttpChannel::EligibleForTailing() {
12339 if (!(mClassOfService.Flags() & nsIClassOfService::Tail)) {
12340 return false;
12341 }
12342
12343 if (mClassOfService.Flags() &
12344 (nsIClassOfService::UrgentStart | nsIClassOfService::Leader |
12345 nsIClassOfService::TailForbidden)) {
12346 return false;
12347 }
12348
12349 if (mClassOfService.Flags() & nsIClassOfService::Unblocked &&
12350 !(mClassOfService.Flags() & nsIClassOfService::TailAllowed)) {
12351 return false;
12352 }
12353
12354 if (IsNavigation()) {
12355 return false;
12356 }
12357
12358 return true;
12359}
12360
12361bool nsHttpChannel::WaitingForTailUnblock() {
12362 nsresult rv;
12363
12364 if (!gHttpHandler->IsTailBlockingEnabled()) {
12365 LOG(("nsHttpChannel %p tail-blocking disabled", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p tail-blocking disabled", this); } } while
(0)
;
12366 return false;
12367 }
12368
12369 if (!EligibleForTailing()) {
12370 LOG(("nsHttpChannel %p not eligible for tail-blocking", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p not eligible for tail-blocking", this); }
} while (0)
;
12371 AddAsNonTailRequest();
12372 return false;
12373 }
12374
12375 if (!EnsureRequestContext()) {
12376 LOG(("nsHttpChannel %p no request context", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel %p no request context", this); } } while (0)
;
12377 return false;
12378 }
12379
12380 LOG(("nsHttpChannel::WaitingForTailUnblock this=%p, rc=%p", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::WaitingForTailUnblock this=%p, rc=%p", this
, mRequestContext.get()); } } while (0)
12381 mRequestContext.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::WaitingForTailUnblock this=%p, rc=%p", this
, mRequestContext.get()); } } while (0)
;
12382
12383 bool blocked;
12384 rv = mRequestContext->IsContextTailBlocked(this, &blocked);
12385 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12386 return false;
12387 }
12388
12389 LOG((" blocked=%d", blocked))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " blocked=%d", blocked); } } while (0)
;
12390
12391 return blocked;
12392}
12393
12394//-----------------------------------------------------------------------------
12395// nsHttpChannel::nsIRequestTailUnblockCallback
12396//-----------------------------------------------------------------------------
12397
12398// Must be implemented in the leaf class because we don't have
12399// AsyncAbort in HttpBaseChannel.
12400NS_IMETHODIMPnsresult
12401nsHttpChannel::OnTailUnblock(nsresult rv) {
12402 LOG(("nsHttpChannel::OnTailUnblock this=%p rv=%" PRIx32 " rc=%p", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnTailUnblock this=%p rv=%" "x" " rc=%p", this
, static_cast<uint32_t>(rv), mRequestContext.get()); } }
while (0)
12403 static_cast<uint32_t>(rv), mRequestContext.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::OnTailUnblock this=%p rv=%" "x" " rc=%p", this
, static_cast<uint32_t>(rv), mRequestContext.get()); } }
while (0)
;
12404 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject12405( "nsHttpChannel::OnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
12405 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject12405( "nsHttpChannel::OnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
12406 MOZ_RELEASE_ASSERT(mOnTailUnblock)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOnTailUnblock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mOnTailUnblock))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mOnTailUnblock"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12406
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 12406); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12407
12408 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
12409 rv = mStatus;
12410 }
12411
12412 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12413 auto callback = mOnTailUnblock;
12414 mOnTailUnblock = nullptr;
12415 rv = (this->*callback)();
12416 }
12417
12418 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12419 CloseCacheEntry(false);
12420 return AsyncAbort(rv);
12421 }
12422
12423 return NS_OK;
12424}
12425
12426void nsHttpChannel::SetWarningReporter(
12427 HttpChannelSecurityWarningReporter* aReporter) {
12428 LOG(("nsHttpChannel [this=%p] SetWarningReporter [%p]", this, aReporter))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel [this=%p] SetWarningReporter [%p]", this, aReporter
); } } while (0)
;
12429 mWarningReporter = aReporter;
12430}
12431
12432HttpChannelSecurityWarningReporter* nsHttpChannel::GetWarningReporter() {
12433 LOG(("nsHttpChannel [this=%p] GetWarningReporter [%p]", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel [this=%p] GetWarningReporter [%p]", this, mWarningReporter
.get()); } } while (0)
12434 mWarningReporter.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel [this=%p] GetWarningReporter [%p]", this, mWarningReporter
.get()); } } while (0)
;
12435 return mWarningReporter.get();
12436}
12437
12438// The specification for ORB is currently being written:
12439// https://whatpr.org/fetch/1442.html#orb-algorithm
12440// The `opaque-response-safelist check` is implemented in:
12441// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff`
12442// * `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
12443// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff`
12444// * `OpaqueResponseBlocker::ValidateJavaScript`
12445//
12446// Should only be called by nsMediaSniffer::GetMIMETypeFromContent and
12447// imageLoader::GetMIMETypeFromContent when the content type can be
12448// recognized by these sniffers.
12449void nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck(
12450 SnifferType aType) {
12451 // https://whatpr.org/fetch/1442.html#orb-algorithm
12452 // This method covers steps, 8 and 10.
12453 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12453
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 12453); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12454
12455 if (NeedOpaqueResponseAllowedCheckAfterSniff()) {
12456 MOZ_ASSERT(mCachedOpaqueResponseBlockingPref)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mCachedOpaqueResponseBlockingPref)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mCachedOpaqueResponseBlockingPref
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mCachedOpaqueResponseBlockingPref", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedOpaqueResponseBlockingPref"
")"); do { MOZ_CrashSequence(__null, 12456); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12457
12458 // If the sniffer type is media and the request comes from a media element,
12459 // we would like to check:
12460 // - Whether the information provided by the media element shows it's an
12461 // initial request.
12462 // - Whether the response's status is either 200 or 206.
12463 //
12464 // If any of the results is false, then we set
12465 // mBlockOpaqueResponseAfterSniff to true and block the response later.
12466 if (aType == SnifferType::Media) {
12467 // Step 8
12468 MOZ_ASSERT(mLoadInfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mLoadInfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mLoadInfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mLoadInfo", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12468); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo"
")"); do { MOZ_CrashSequence(__null, 12468); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12469
12470 auto noCorsMediaRequestState = NoCorsMediaRequestState();
12471 if (noCorsMediaRequestState !=
12472 dom::NoCorsMediaRequestState::NotAvailable) {
12473 if (noCorsMediaRequestState != dom::NoCorsMediaRequestState::Initial) {
12474 // Step 8.1
12475 BlockOpaqueResponseAfterSniff(
12476 u"media request after sniffing, but not initial request"_ns,
12477 OpaqueResponseBlockedTelemetryReason::eMediaNotInitial);
12478 return;
12479 }
12480
12481 if (mResponseHead->Status() != 200 && mResponseHead->Status() != 206) {
12482 // Step 8.2
12483 BlockOpaqueResponseAfterSniff(
12484 u"media request's response status is neither 200 nor 206"_ns,
12485 OpaqueResponseBlockedTelemetryReason::eMediaIncorrectResp);
12486 return;
12487 }
12488
12489 // At this point we've checked that the requested resource is media and
12490 // that the sniff passes. Any following requests for this resource
12491 // should be considered to be subsequent.
12492 RecordSubsequentNoCorsRequestState();
12493 }
12494 }
12495
12496 // Step 8.3 if `aType == SnifferType::Media`
12497 // Step 9 can be skipped, only `HTMLMediaElement` ever sets isMediaRequest.
12498 // Step 10 if `aType == SnifferType::Image`
12499 AllowOpaqueResponseAfterSniff();
12500 }
12501}
12502
12503namespace {
12504
12505class CopyNonDefaultHeaderVisitor final : public nsIHttpHeaderVisitor {
12506 nsCOMPtr<nsIHttpChannel> mTarget;
12507
12508 ~CopyNonDefaultHeaderVisitor() = default;
12509
12510 NS_IMETHODvirtual nsresult
12511 VisitHeader(const nsACString& aHeader, const nsACString& aValue) override {
12512 if (aValue.IsEmpty()) {
12513 return mTarget->SetEmptyRequestHeader(aHeader);
12514 }
12515 return mTarget->SetRequestHeader(aHeader, aValue, false /* merge */);
12516 }
12517
12518 public:
12519 explicit CopyNonDefaultHeaderVisitor(nsIHttpChannel* aTarget)
12520 : mTarget(aTarget) {
12521 MOZ_DIAGNOSTIC_ASSERT(mTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mTarget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mTarget", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12521); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mTarget"
")"); do { MOZ_CrashSequence(__null, 12521); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12522 }
12523
12524 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
12525};
12526
12527NS_IMPL_ISUPPORTS(CopyNonDefaultHeaderVisitor, nsIHttpHeaderVisitor)MozExternalRefCountType CopyNonDefaultHeaderVisitor::AddRef(void
) { static_assert(!std::is_destructible_v<CopyNonDefaultHeaderVisitor
>, "Reference-counted class " "CopyNonDefaultHeaderVisitor"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12527); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12527
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CopyNonDefaultHeaderVisitor" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CopyNonDefaultHeaderVisitor" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"CopyNonDefaultHeaderVisitor\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12527); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12527); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CopyNonDefaultHeaderVisitor" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"CopyNonDefaultHeaderVisitor"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType CopyNonDefaultHeaderVisitor
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12527); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12527
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CopyNonDefaultHeaderVisitor" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("CopyNonDefaultHeaderVisitor" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"CopyNonDefaultHeaderVisitor\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12527); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12527); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CopyNonDefaultHeaderVisitor" " not thread-safe"
); const char* const nametmp = "CopyNonDefaultHeaderVisitor";
nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult CopyNonDefaultHeaderVisitor::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12527); MOZ_PretendNoReturn(); } } while (0); nsresult rv =
NS_ERROR_FAILURE; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<CopyNonDefaultHeaderVisitor, nsIHttpHeaderVisitor
>, int32_t( reinterpret_cast<char*>(static_cast<nsIHttpHeaderVisitor
*>((CopyNonDefaultHeaderVisitor*)0x1000)) - reinterpret_cast
<char*>((CopyNonDefaultHeaderVisitor*)0x1000))}, {&
mozilla::detail::kImplementedIID<CopyNonDefaultHeaderVisitor
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIHttpHeaderVisitor*>
((CopyNonDefaultHeaderVisitor*)0x1000))) - reinterpret_cast<
char*>((CopyNonDefaultHeaderVisitor*)0x1000))}, { nullptr,
0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
12528
12529} // anonymous namespace
12530
12531nsresult nsHttpChannel::RedirectToInterceptedChannel() {
12532 nsCOMPtr<nsINetworkInterceptController> controller;
12533 GetCallback(controller);
12534
12535 RefPtr<InterceptedHttpChannel> intercepted =
12536 InterceptedHttpChannel::CreateForInterception(
12537 mChannelCreationTime, mChannelCreationTimestamp, mAsyncOpenTime);
12538
12539 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
12540 CloneLoadInfoForRedirect(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
12541
12542 nsresult rv = intercepted->Init(
12543 mURI, mCaps, static_cast<nsProxyInfo*>(mProxyInfo.get()),
12544 mProxyResolveFlags, mProxyURI, mChannelId, redirectLoadInfo);
12545
12546 rv = SetupReplacementChannel(mURI, intercepted, true,
12547 nsIChannelEventSink::REDIRECT_INTERNAL);
12548 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12548); return rv; } } while (false)
;
12549
12550 // Some APIs, like fetch(), allow content to set non-standard headers.
12551 // Normally these APIs are responsible for copying these headers across
12552 // redirects. In the e10s parent-side intercept case, though, we currently
12553 // "hide" the internal redirect to the InterceptedHttpChannel. So the
12554 // fetch() API does not have the opportunity to move headers over.
12555 // Therefore, we do it automatically here.
12556 //
12557 // Once child-side interception is removed and the internal redirect no
12558 // longer needs to be "hidden", then this header copying code can be
12559 // removed.
12560 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
12561 new CopyNonDefaultHeaderVisitor(intercepted);
12562 rv = VisitNonDefaultRequestHeaders(visitor);
12563 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12563); return rv; } } while (false)
;
12564
12565 mRedirectChannel = intercepted;
12566
12567 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
12568
12569 rv = gHttpHandler->AsyncOnChannelRedirect(
12570 this, intercepted, nsIChannelEventSink::REDIRECT_INTERNAL);
12571
12572 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12573 rv = WaitForRedirectCallback();
12574 }
12575
12576 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12577 AutoRedirectVetoNotifier notifier(this, rv);
12578
12579 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
12580 }
12581
12582 return rv;
12583}
12584
12585void nsHttpChannel::ReEvaluateReferrerAfterTrackingStatusIsKnown() {
12586 nsCOMPtr<nsICookieJarSettings> cjs;
12587 if (mLoadInfo) {
12588 (void)mLoadInfo->GetCookieJarSettings(getter_AddRefs(cjs));
12589 }
12590 if (!cjs) {
12591 cjs = net::CookieJarSettings::Create(mLoadInfo->GetLoadingPrincipal());
12592 }
12593 if (cjs->GetRejectThirdPartyContexts()) {
12594 bool isPrivate = mLoadInfo->GetOriginAttributes().IsPrivateBrowsing();
12595 // If our referrer has been set before, and our referrer policy is unset
12596 // (default policy) if we thought the channel wasn't a third-party
12597 // tracking channel, we may need to set our referrer with referrer policy
12598 // once again to ensure our defaults properly take effect now.
12599 if (mReferrerInfo) {
12600 ReferrerInfo* referrerInfo =
12601 static_cast<ReferrerInfo*>(mReferrerInfo.get());
12602
12603 if (referrerInfo->IsPolicyOverrided() &&
12604 referrerInfo->ReferrerPolicy() ==
12605 ReferrerInfo::GetDefaultReferrerPolicy(nullptr, nullptr,
12606 isPrivate)) {
12607 nsCOMPtr<nsIReferrerInfo> newReferrerInfo =
12608 referrerInfo->CloneWithNewPolicy(
12609 ReferrerInfo::GetDefaultReferrerPolicy(this, mURI, isPrivate));
12610 // The arguments passed to SetReferrerInfoInternal here should mirror
12611 // the arguments passed in
12612 // HttpChannelChild::RecvOverrideReferrerInfoDuringBeginConnect().
12613 SetReferrerInfoInternal(newReferrerInfo, false, true, true);
12614
12615 nsCOMPtr<nsIParentChannel> parentChannel;
12616 NS_QueryNotificationCallbacks(this, parentChannel);
12617 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
12618 if (httpParent) {
12619 httpParent->OverrideReferrerInfoDuringBeginConnect(newReferrerInfo);
12620 }
12621 }
12622 }
12623 }
12624}
12625
12626namespace {
12627
12628// Also acts as the only notification callbacks of the revalidating channel, so
12629// that none of its notifications reach the consumer of the original channel.
12630class BackgroundRevalidatingListener : public nsIStreamListener,
12631 public nsIInterfaceRequestor,
12632 public nsIChannelEventSink {
12633 public:
12634 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
12635 NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream
*aInputStream, uint64_t aOffset, uint32_t aCount) override;
12636 NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override
; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult
aStatusCode) override;
12637 NS_DECL_NSIINTERFACEREQUESTORvirtual nsresult GetInterface(const nsIID & uuid, void * *
result) override;
12638 NS_DECL_NSICHANNELEVENTSINKvirtual nsresult AsyncOnChannelRedirect(nsIChannel *oldChannel
, nsIChannel *newChannel, uint32_t flags, nsIAsyncVerifyRedirectCallback
*callback) override;
12639
12640 private:
12641 virtual ~BackgroundRevalidatingListener() = default;
12642};
12643
12644NS_IMETHODIMPnsresult
12645BackgroundRevalidatingListener::OnStartRequest(nsIRequest* request) {
12646 return NS_OK;
12647}
12648
12649NS_IMETHODIMPnsresult
12650BackgroundRevalidatingListener::OnDataAvailable(nsIRequest* request,
12651 nsIInputStream* input,
12652 uint64_t offset,
12653 uint32_t count) {
12654 uint32_t bytesRead = 0;
12655 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &bytesRead);
12656}
12657
12658NS_IMETHODIMPnsresult
12659BackgroundRevalidatingListener::OnStopRequest(nsIRequest* request,
12660 nsresult status) {
12661 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
12662 return status;
12663 }
12664
12665 nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(request));
12666 if (gHttpHandler) {
12667 gHttpHandler->OnBackgroundRevalidation(channel);
12668 }
12669 return NS_OK;
12670}
12671
12672NS_IMETHODIMPnsresult
12673BackgroundRevalidatingListener::GetInterface(const nsIID& aIID,
12674 void** aResult) {
12675 if (aIID.Equals(NS_GET_IID(nsIChannelEventSink)(nsIChannelEventSink::kIID))) {
12676 return QueryInterface(aIID, aResult);
12677 }
12678 return NS_ERROR_NO_INTERFACE;
12679}
12680
12681// The redirect response itself revalidates the cache entry, there is no need
12682// to follow it.
12683NS_IMETHODIMPnsresult
12684BackgroundRevalidatingListener::AsyncOnChannelRedirect(
12685 nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
12686 nsIAsyncVerifyRedirectCallback* aCallback) {
12687 LOG(("BackgroundRevalidatingListener::AsyncOnChannelRedirect %p vetoing",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "BackgroundRevalidatingListener::AsyncOnChannelRedirect %p vetoing"
, aOldChannel); } } while (0)
12688 aOldChannel))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "BackgroundRevalidatingListener::AsyncOnChannelRedirect %p vetoing"
, aOldChannel); } } while (0)
;
12689 return NS_BINDING_ABORTED;
12690}
12691
12692NS_IMPL_ISUPPORTS(BackgroundRevalidatingListener, nsIStreamListener,MozExternalRefCountType BackgroundRevalidatingListener::AddRef
(void) { static_assert(!std::is_destructible_v<BackgroundRevalidatingListener
>, "Reference-counted class " "BackgroundRevalidatingListener"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12694
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("BackgroundRevalidatingListener" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("BackgroundRevalidatingListener" != nullptr))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("\"BackgroundRevalidatingListener\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12694); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("BackgroundRevalidatingListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"BackgroundRevalidatingListener"), (uint32_t)(sizeof(*this)))
; return count; } MozExternalRefCountType BackgroundRevalidatingListener
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12694
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("BackgroundRevalidatingListener" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("BackgroundRevalidatingListener" != nullptr))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("\"BackgroundRevalidatingListener\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12694); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("BackgroundRevalidatingListener" " not thread-safe"
); const char* const nametmp = "BackgroundRevalidatingListener"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult BackgroundRevalidatingListener
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12694
); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<BackgroundRevalidatingListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((BackgroundRevalidatingListener*)0x1000)) - reinterpret_cast
<char*>((BackgroundRevalidatingListener*)0x1000))}, {&
mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIStreamListener*>((
BackgroundRevalidatingListener*)0x1000))) - reinterpret_cast<
char*>((BackgroundRevalidatingListener*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
12693 nsIRequestObserver, nsIInterfaceRequestor,MozExternalRefCountType BackgroundRevalidatingListener::AddRef
(void) { static_assert(!std::is_destructible_v<BackgroundRevalidatingListener
>, "Reference-counted class " "BackgroundRevalidatingListener"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12694
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("BackgroundRevalidatingListener" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("BackgroundRevalidatingListener" != nullptr))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("\"BackgroundRevalidatingListener\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12694); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("BackgroundRevalidatingListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"BackgroundRevalidatingListener"), (uint32_t)(sizeof(*this)))
; return count; } MozExternalRefCountType BackgroundRevalidatingListener
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12694
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("BackgroundRevalidatingListener" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("BackgroundRevalidatingListener" != nullptr))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("\"BackgroundRevalidatingListener\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12694); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("BackgroundRevalidatingListener" " not thread-safe"
); const char* const nametmp = "BackgroundRevalidatingListener"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult BackgroundRevalidatingListener
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12694
); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<BackgroundRevalidatingListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((BackgroundRevalidatingListener*)0x1000)) - reinterpret_cast
<char*>((BackgroundRevalidatingListener*)0x1000))}, {&
mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIStreamListener*>((
BackgroundRevalidatingListener*)0x1000))) - reinterpret_cast<
char*>((BackgroundRevalidatingListener*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
12694 nsIChannelEventSink)MozExternalRefCountType BackgroundRevalidatingListener::AddRef
(void) { static_assert(!std::is_destructible_v<BackgroundRevalidatingListener
>, "Reference-counted class " "BackgroundRevalidatingListener"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12694
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("BackgroundRevalidatingListener" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("BackgroundRevalidatingListener" != nullptr))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("\"BackgroundRevalidatingListener\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12694); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("BackgroundRevalidatingListener" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"BackgroundRevalidatingListener"), (uint32_t)(sizeof(*this)))
; return count; } MozExternalRefCountType BackgroundRevalidatingListener
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12694
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("BackgroundRevalidatingListener" != nullptr)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("BackgroundRevalidatingListener" != nullptr))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("\"BackgroundRevalidatingListener\" != nullptr"
" (" "Must specify a name" ")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12694); __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("BackgroundRevalidatingListener" " not thread-safe"
); const char* const nametmp = "BackgroundRevalidatingListener"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult BackgroundRevalidatingListener
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12694
); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(4 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<BackgroundRevalidatingListener, nsIStreamListener
>, int32_t( reinterpret_cast<char*>(static_cast<nsIStreamListener
*>((BackgroundRevalidatingListener*)0x1000)) - reinterpret_cast
<char*>((BackgroundRevalidatingListener*)0x1000))}, {&
mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIRequestObserver>, int32_t( reinterpret_cast<char*>
(static_cast<nsIRequestObserver*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIInterfaceRequestor>, int32_t( reinterpret_cast<char
*>(static_cast<nsIInterfaceRequestor*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsIChannelEventSink>, int32_t( reinterpret_cast<char*
>(static_cast<nsIChannelEventSink*>((BackgroundRevalidatingListener
*)0x1000)) - reinterpret_cast<char*>((BackgroundRevalidatingListener
*)0x1000))}, {&mozilla::detail::kImplementedIID<BackgroundRevalidatingListener
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIStreamListener*>((
BackgroundRevalidatingListener*)0x1000))) - reinterpret_cast<
char*>((BackgroundRevalidatingListener*)0x1000))}, { nullptr
, 0 } } ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
12695
12696} // namespace
12697
12698void nsHttpChannel::PerformBackgroundCacheRevalidation() {
12699 if (!StaticPrefs::network_http_stale_while_revalidate_enabled()) {
12700 return;
12701 }
12702
12703 // This is a channel doing a revalidation. It shouldn't do it again.
12704 if (mStaleRevalidation) {
12705 return;
12706 }
12707
12708 LOG(("nsHttpChannel::PerformBackgroundCacheRevalidation %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::PerformBackgroundCacheRevalidation %p", this
); } } while (0)
;
12709
12710 (void)NS_DispatchToMainThreadQueue(
12711 NewIdleRunnableMethod(
12712 "nsHttpChannel::PerformBackgroundCacheRevalidation", this,
12713 &nsHttpChannel::PerformBackgroundCacheRevalidationNow),
12714 EventQueuePriority::Idle);
12715}
12716
12717void nsHttpChannel::PerformBackgroundCacheRevalidationNow() {
12718 LOG(("nsHttpChannel::PerformBackgroundCacheRevalidationNow %p", this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::PerformBackgroundCacheRevalidationNow %p", this
); } } while (0)
;
12719
12720 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12720
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12720); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12721
12722 nsresult rv;
12723
12724 nsLoadFlags loadFlags = mLoadFlags | LOAD_ONLY_IF_MODIFIED | VALIDATE_ALWAYS |
12725 LOAD_BACKGROUND | LOAD_BYPASS_SERVICE_WORKER;
12726
12727 RefPtr<BackgroundRevalidatingListener> listener =
12728 new BackgroundRevalidatingListener();
12729
12730 nsCOMPtr<nsIPrincipal> principal;
12731 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
12732 this, getter_AddRefs(principal));
12733 nsCOMPtr<nsILoadGroup> loadGroup;
12734 rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), principal);
12735 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12736 LOG((" failed to create the load group, rv=0x%08x",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " failed to create the load group, rv=0x%08x", static_cast
<uint32_t>(rv)); } } while (0)
12737 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " failed to create the load group, rv=0x%08x", static_cast
<uint32_t>(rv)); } } while (0)
;
12738 return;
12739 }
12740
12741 // XXX(valentin): Preserving the old load info means mInitialSecurityCheckDone
12742 // will be true. Using CloneForNewRequest would be closer to the spec, but
12743 // it would mean redoing previous checks.
12744 nsCOMPtr<nsILoadInfo> loadInfo =
12745 static_cast<mozilla::net::LoadInfo*>(mLoadInfo.get())->Clone();
12746
12747 nsCOMPtr<nsIChannel> validatingChannel;
12748 rv = NS_NewChannelInternal(getter_AddRefs(validatingChannel), mURI, loadInfo,
12749 nullptr /* performance storage */, loadGroup,
12750 listener, loadFlags);
12751 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12752 LOG((" failed to created the channel, rv=0x%08x",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " failed to created the channel, rv=0x%08x", static_cast<
uint32_t>(rv)); } } while (0)
12753 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " failed to created the channel, rv=0x%08x", static_cast<
uint32_t>(rv)); } } while (0)
;
12754 return;
12755 }
12756
12757 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(validatingChannel));
12758 MOZ_ASSERT(httpChannel)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(httpChannel)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(httpChannel))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("httpChannel", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 12758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpChannel"
")"); do { MOZ_CrashSequence(__null, 12758); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12759
12760 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
12761 new CopyNonDefaultHeaderVisitor(httpChannel);
12762 rv = VisitNonDefaultRequestHeaders(visitor);
12763 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12764 LOG(("failed to copy headers to the validating channel, rv=0x%08x",do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "failed to copy headers to the validating channel, rv=0x%08x"
, static_cast<uint32_t>(rv)); } } while (0)
12765 static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "failed to copy headers to the validating channel, rv=0x%08x"
, static_cast<uint32_t>(rv)); } } while (0)
;
12766 return;
12767 }
12768
12769 nsCOMPtr<nsISupportsPriority> priority(do_QueryInterface(validatingChannel));
12770 if (priority) {
12771 priority->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
12772 }
12773
12774 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(validatingChannel));
12775 if (cos) {
12776 cos->AddClassFlags(nsIClassOfService::Tail);
12777 }
12778
12779 RefPtr<nsHttpChannel> httpChan = do_QueryObject(validatingChannel);
12780 if (httpChan) {
12781 httpChan->mStaleRevalidation = true;
12782 }
12783
12784 rv = validatingChannel->AsyncOpen(listener);
12785 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12786 LOG((" failed to open the channel, rv=0x%08x", static_cast<uint32_t>(rv)))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " failed to open the channel, rv=0x%08x", static_cast<uint32_t
>(rv)); } } while (0)
;
12787 return;
12788 }
12789
12790 LOG((" %p is re-validating with a new channel %p", this,do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " %p is re-validating with a new channel %p", this, validatingChannel
.get()); } } while (0)
12791 validatingChannel.get()))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " %p is re-validating with a new channel %p", this, validatingChannel
.get()); } } while (0)
;
12792}
12793
12794NS_IMETHODIMPnsresult
12795nsHttpChannel::SetEarlyHintObserver(nsIEarlyHintObserver* aObserver) {
12796 mEarlyHintObserver = aObserver;
12797 return NS_OK;
12798}
12799
12800NS_IMETHODIMPnsresult
12801nsHttpChannel::EarlyHint(const nsACString& aLinkHeader,
12802 const nsACString& aReferrerPolicy,
12803 const nsACString& aCspHeader,
12804 const nsACString& aConnectionAllowlistHeader) {
12805 LOG(("nsHttpChannel::EarlyHint.\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::EarlyHint.\n"); } } while (0)
;
12806
12807 if (nsCOMPtr<nsIEarlyHintObserver> obs = mEarlyHintObserver) {
12808 if (nsContentUtils::ComputeIsSecureContext(this)) {
12809 LOG(("nsHttpChannel::EarlyHint propagated.\n"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::EarlyHint propagated.\n"); } } while (0)
;
12810 obs->EarlyHint(aLinkHeader, aReferrerPolicy, aCspHeader,
12811 aConnectionAllowlistHeader);
12812 }
12813 }
12814 return NS_OK;
12815}
12816
12817NS_IMETHODIMPnsresult nsHttpChannel::SetResponseOverride(
12818 nsIReplacedHttpResponse* aReplacedHttpResponse) {
12819 mOverrideResponse = new nsMainThreadPtrHolder<nsIReplacedHttpResponse>(
12820 "nsIReplacedHttpResponse", aReplacedHttpResponse);
12821
12822 if (LoadRequireCORSPreflight()) {
12823 // Bug 1986615, Bug 1940738, responses provided via setResponseOverride will
12824 // be handled before the preflight can be sent, flag it as done.
12825 StoreIsCorsPreflightDone(true);
12826 }
12827
12828 return NS_OK;
12829}
12830
12831NS_IMETHODIMPnsresult nsHttpChannel::SetResponseStatus(uint32_t aStatus,
12832 const nsACString& aStatusText) {
12833 if (!mResponseHead) {
12834 return NS_ERROR_NOT_AVAILABLE;
12835 }
12836
12837 nsAutoCString statusText(aStatusText);
12838 nsAutoCString protocolVersion(
12839 nsHttp::GetProtocolVersion(mResponseHead->Version()));
12840 ToUpperCase(protocolVersion);
12841
12842 nsPrintfCString line("%s %u %s", protocolVersion.get(), aStatus,
12843 statusText.get());
12844
12845 return mResponseHead->ParseStatusLine(line);
12846}
12847
12848NS_IMETHODIMPnsresult nsHttpChannel::SetWebTransportSessionEventListener(
12849 WebTransportSessionEventListener* aListener) {
12850 mWebTransportSessionEventListener = aListener;
12851 return NS_OK;
12852}
12853
12854already_AddRefed<WebTransportSessionEventListener>
12855nsHttpChannel::GetWebTransportSessionEventListener() {
12856 RefPtr<WebTransportSessionEventListener> wt =
12857 mWebTransportSessionEventListener;
12858 return wt.forget();
12859}
12860
12861NS_IMETHODIMPnsresult nsHttpChannel::GetLastTransportStatus(
12862 nsresult* aLastTransportStatus) {
12863 *aLastTransportStatus = mLastTransportStatus;
12864 return NS_OK;
12865}
12866
12867NS_IMETHODIMPnsresult
12868nsHttpChannel::GetCacheDisposition(CacheDisposition* aDisposition) {
12869 if (!aDisposition) {
12870 return NS_ERROR_INVALID_ARG;
12871 }
12872 *aDisposition = mCacheDisposition;
12873 return NS_OK;
12874}
12875
12876} // namespace net
12877} // namespace mozilla