Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http/./../../../../netwerk/protocol/http/nsHttpChannel.cpp
Warning:line 5896, 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_http5.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/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -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-09-01-224014-2642839-1 -x c++ Unified_cpp_protocol_http5.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 "HttpTransactionParent.h"
18#include "InterceptedHttpChannel.h"
19#include "LNAPermissionRequest.h"
20#include "LoadContextInfo.h"
21#include "NetworkMarker.h"
22#include "ThirdPartyUtil.h"
23#include "mozilla/AntiTrackingRedirectHeuristic.h"
24#include "mozilla/AntiTrackingUtils.h"
25#include "mozilla/Attributes.h"
26#include "mozilla/BasePrincipal.h"
27#include "mozilla/Components.h"
28#include "mozilla/ContentBlockingAllowList.h"
29#include "mozilla/DebugOnly.h"
30#include "mozilla/FlowMarkers.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/SecFetch.h"
53#include "mozilla/dom/ServiceWorkerUtils.h"
54#include "mozilla/dom/WindowGlobalParent.h"
55#include "mozilla/dom/nsCSPContext.h"
56#include "mozilla/dom/nsHTTPSOnlyStreamListener.h"
57#include "mozilla/dom/nsHTTPSOnlyUtils.h"
58#include "mozilla/extensions/StreamFilterParent.h"
59#include "mozilla/glean/AntitrackingMetrics.h"
60#include "mozilla/glean/DomSecurityMetrics.h"
61#include "mozilla/glean/NetwerkMetrics.h"
62#include "mozilla/glean/NetwerkProtocolHttpMetrics.h"
63#include "mozilla/net/AsyncUrlChannelClassifier.h"
64#include "mozilla/net/CaptivePortalService.h"
65#include "mozilla/net/ChannelClassifierUtils.h"
66#include "mozilla/net/CookieJarSettings.h"
67#include "mozilla/net/CookieServiceParent.h"
68#include "mozilla/net/NeckoChannelParams.h"
69#include "mozilla/net/NoVarySearchUtils.h"
70#include "mozilla/net/OpaqueResponseUtils.h"
71#include "mozilla/net/SFVService.h"
72#include "mozilla/net/SocketProcessParent.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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 ("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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 "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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 "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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 }((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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 }))((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; } 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"
, 688); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->mDictDecompress->DictionaryReady()"
")"); do { MOZ_CrashSequence(__null, 688); __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 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)
700 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)
701 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)
;
702 return true;
703 }
704 // Need to undo these if we're not going to be able to use the dict
705 self->mDictDecompress->UseCompleted();
706 self->mDictDecompress = nullptr;
707 self->mUsingDictionary = false;
708 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)
;
709 return false;
710 });
711 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
712
713 // notify "http-on-modify-request-before-cookies" observers
714 gHttpHandler->OnModifyRequestBeforeCookies(this);
715
716 if (mStaleRevalidation) {
717 // This is a revalidating channel.
718 // The cookies (user set cookies + cookies from the cookeservice) are
719 // already copied to the request headers when opening this channel in
720 // PerformBackgroundCacheRevalidationNow().
721 } else {
722 AddCookiesToRequest();
723 }
724
725#if defined(XP_WIN) || defined(XP_MACOSX)
726
727 auto prefEnabledForCurrentContainer = [&]() {
728 uint32_t containerId = mLoadInfo->GetOriginAttributes().mUserContextId;
729 // Make sure that the default container ID is 0
730 static_assert(nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID == 0);
731
732 nsAutoCString prefName;
733# ifdef XP_WIN
734 prefName = nsPrintfCString("network.http.windows-sso.container-enabled.%u",
735 containerId);
736# endif
737
738# ifdef XP_MACOSX
739 prefName = nsPrintfCString(
740 "network.http.microsoft-entra-sso.container-enabled.%u", containerId);
741# endif
742
743 bool enabled = false;
744 Preferences::GetBool(prefName.get(), &enabled);
745
746 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)
;
747
748 return enabled;
749 };
750
751#endif // defined(XP_WIN) || defined(XP_MACOSX)
752
753#ifdef XP_WIN
754
755 // If Windows 10 SSO is enabled, we potentially add auth
756 // information to secure top level loads (DOCUMENTs) and iframes
757 // (SUBDOCUMENTs) that aren't anonymous or private browsing.
758 if (StaticPrefs::network_http_windows_sso_enabled() &&
759 mURI->SchemeIs("https") && !(mLoadFlags & LOAD_ANONYMOUS) &&
760 !mPrivateBrowsing) {
761 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
762 if ((type == ExtContentPolicy::TYPE_DOCUMENT ||
763 type == ExtContentPolicy::TYPE_SUBDOCUMENT) &&
764 prefEnabledForCurrentContainer()) {
765 AddWindowsSSO(this);
766 }
767 }
768#endif
769
770#ifdef XP_MACOSX
771
772 auto isUriMSAuthority = [&]() {
773 nsAutoCString endPoint;
774 nsresult rv = mURI->GetHost(endPoint);
775 if (!NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
776 return false;
777 }
778 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)
;
779
780 return gHttpHandler->IsHostMSAuthority(endPoint);
781 };
782
783 // If macOS SSO is enabled, we potentially add auth
784 // information to secure top level loads (DOCUMENTs) and iframes
785 // (SUBDOCUMENTs) that aren't anonymous or private browsing.
786 if (StaticPrefs::network_http_microsoft_entra_sso_enabled() &&
787 mURI->SchemeIs("https") && !(mLoadFlags & LOAD_ANONYMOUS) &&
788 !mPrivateBrowsing) {
789 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
790 if ((type == ExtContentPolicy::TYPE_DOCUMENT ||
791 type == ExtContentPolicy::TYPE_SUBDOCUMENT) &&
792 prefEnabledForCurrentContainer() && isUriMSAuthority()) {
793 nsMainThreadPtrHandle<nsHttpChannel> self(
794 new nsMainThreadPtrHolder<nsHttpChannel>(
795 "nsHttpChannel::PrepareToConnect::self", this));
796 auto resultCallback = [self(self)]() {
797 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", 797
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 797); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
798 nsresult rv = self->ContinuePrepareToConnect();
799 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
800 self->CloseCacheEntry(false);
801 (void)self->AsyncAbort(rv);
802 }
803 };
804
805 nsresult rv = AddMicrosoftEntraSSO(this, std::move(resultCallback));
806
807 // Returns NS_OK if performRequests is called in MicrosoftEntraSSOUtils
808 // This temporarily stops the channel setup for the delegate.
809 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
810 return rv;
811 }
812 }
813 }
814
815#endif
816
817 return ContinuePrepareToConnect();
818}
819
820nsresult nsHttpChannel::ContinuePrepareToConnect() {
821 // notify "http-on-modify-request" observers
822 CallOnModifyRequestObservers();
823
824 return CallOrWaitForResume(
825 [](auto* self) { return self->OnBeforeConnect(); });
826}
827
828void nsHttpChannel::HandleContinueCancellingByURLClassifier(
829 nsresult aErrorCode) {
830 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", 830
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 830); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
831 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"
, 831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 831); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false)
;
832
833 if (mSuspendCount) {
834 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)
835 ("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)
836 "[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)
837 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)
;
838 mCallOnResume = [aErrorCode](nsHttpChannel* self) {
839 self->HandleContinueCancellingByURLClassifier(aErrorCode);
840 return NS_OK;
841 };
842 return;
843 }
844
845 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)
846 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)
;
847 ContinueCancellingByURLClassifier(aErrorCode);
848}
849
850void nsHttpChannel::SetPriorityHeader() {
851 nsAutoCString userSetPriority;
852 (void)GetRequestHeader("Priority"_ns, userSetPriority);
853 if (!userSetPriority.IsEmpty()) {
854 // If the Priority header is set by the user, do not override it.
855 return;
856 }
857
858 uint8_t urgency =
859 nsHttpHandler::UrgencyFromCoSFlags(mClassOfService.Flags(), mPriority);
860 bool incremental = mClassOfService.Incremental();
861
862 nsPrintfCString value(
863 "%s", urgency != 3 ? nsPrintfCString("u=%d", urgency).get() : "");
864
865 if (incremental) {
866 if (!value.IsEmpty()) {
867 value.Append(", ");
868 }
869 value.Append("i");
870 }
871
872 if (!value.IsEmpty()) {
873 SetRequestHeader("Priority"_ns, value, false);
874 }
875}
876
877nsresult nsHttpChannel::OnBeforeConnect() {
878 nsresult rv = NS_OK;
879
880 // Check if request was cancelled during suspend AFTER on-modify-request
881 if (mCanceled) {
882 return mStatus;
883 }
884
885 // Check to see if we should redirect this channel elsewhere by
886 // nsIHttpChannel.redirectTo API request
887 if (mAPIRedirectTo) {
888 return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
889 }
890
891 // Note that we are only setting the "Upgrade-Insecure-Requests" request
892 // header for *all* navigational requests instead of all requests as
893 // defined in the spec, see:
894 // https://www.w3.org/TR/upgrade-insecure-requests/#preference
895 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
896
897 if (type == ExtContentPolicy::TYPE_DOCUMENT ||
898 type == ExtContentPolicy::TYPE_SUBDOCUMENT) {
899 rv = SetRequestHeader("Upgrade-Insecure-Requests"_ns, "1"_ns, false);
900 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"
, 900); return rv; } } while (false)
;
901 }
902
903 if (LoadAuthRedirectedChannel()) {
904 // This channel is a result of a redirect due to auth retry
905 // We have already checked for HSTS upgarde in the redirecting channel.
906 // We can safely skip those checks
907 return ContinueOnBeforeConnect(false, rv);
908 }
909
910 SecFetch::AddSecFetchHeader(this);
911
912 // Check to see if we should redirect this channel to the unstripped URI. To
913 // revert the query stripping if the loading channel is in the content
914 // blocking allow list.
915 if (ContentBlockingAllowList::Check(this)) {
916 nsCOMPtr<nsIURI> unstrippedURI;
917 mLoadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
918
919 if (unstrippedURI) {
920 return AsyncCall(&nsHttpChannel::HandleAsyncRedirectToUnstrippedURI);
921 }
922 }
923
924 nsCOMPtr<nsIPrincipal> resultPrincipal;
925 if (!mURI->SchemeIs("https")) {
926 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
927 this, getter_AddRefs(resultPrincipal));
928 }
929
930 // Check if we already know about the HSTS status of the host
931 nsISiteSecurityService* sss = gHttpHandler->GetSSService();
932 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"
, 932); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
933 bool isSecureURI;
934 OriginAttributes originAttributes;
935 if (!StoragePrincipalHelper::GetOriginAttributesForHSTS(this,
936 originAttributes)) {
937 return NS_ERROR_FAILURE;
938 }
939 rv = sss->IsSecureURI(mURI, originAttributes, &isSecureURI);
940 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"
, 940); return rv; } } while (false)
;
941 // Save that on the loadInfo so it can later be consumed by
942 // SecurityInfo.sys.mjs
943 mLoadInfo->SetHstsStatus(isSecureURI);
944
945 RefPtr<mozilla::dom::BrowsingContext> bc;
946 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
947 // If bypassing the cache and we're forced offline
948 // we can just return the error here.
949 if (bc && bc->Top()->GetForceOffline() &&
950 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
951 return NS_ERROR_OFFLINE;
952 }
953
954 // At this point it is no longer possible to call
955 // HttpBaseChannel::UpgradeToSecure.
956 StoreUpgradableToSecure(false);
957 bool shouldUpgrade = LoadUpgradeToSecure();
958 if (mURI->SchemeIs("http")) {
959 OriginAttributes originAttributes;
960 if (!StoragePrincipalHelper::GetOriginAttributesForHSTS(this,
961 originAttributes)) {
962 return NS_ERROR_FAILURE;
963 }
964
965 if (!shouldUpgrade) {
966 // Make sure http channel is released on main thread.
967 // See bug 1539148 for details.
968 nsMainThreadPtrHandle<nsHttpChannel> self(
969 new nsMainThreadPtrHolder<nsHttpChannel>(
970 "nsHttpChannel::OnBeforeConnect::self", this));
971 auto resultCallback = [self(self)](bool aResult, nsresult aStatus) {
972 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", 972
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 972); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
973
974 nsresult rv = self->MaybeUseHTTPSRRForUpgrade(aResult, aStatus);
975 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
976 self->CloseCacheEntry(false);
977 (void)self->AsyncAbort(rv);
978 }
979 };
980
981 bool willCallback = false;
982 rv = NS_ShouldSecureUpgrade(
983 mURI, mLoadInfo, resultPrincipal, LoadAllowSTS(), originAttributes,
984 shouldUpgrade, std::move(resultCallback), willCallback);
985 // If the request gets upgraded because of the HTTPS-Only mode, but no
986 // event listener has been registered so far, we want to do that here.
987 uint32_t httpOnlyStatus = mLoadInfo->GetHttpsOnlyStatus();
988 if (httpOnlyStatus &
989 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED) {
990 RefPtr<nsHTTPSOnlyStreamListener> httpsOnlyListener =
991 new nsHTTPSOnlyStreamListener(mListener, mLoadInfo);
992 mListener = httpsOnlyListener;
993
994 httpOnlyStatus ^=
995 nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_NOT_REGISTERED;
996 httpOnlyStatus |= nsILoadInfo::HTTPS_ONLY_UPGRADED_LISTENER_REGISTERED;
997 mLoadInfo->SetHttpsOnlyStatus(httpOnlyStatus);
998 }
999 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)
1000 ("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)
1001 "[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)
1002 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)
;
1003
1004 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || MOZ_UNLIKELY(willCallback)(__builtin_expect(!!(willCallback), 0))) {
1005 return rv;
1006 }
1007 }
1008 }
1009
1010 return MaybeUseHTTPSRRForUpgrade(shouldUpgrade, NS_OK);
1011}
1012
1013// Returns true if the network connectivity checker indicated
1014// that HTTPS records can be resolved on this network - false otherwise.
1015// When TRR is enabled, we always return true, as resolving HTTPS
1016// records don't depend on the network.
1017static bool canUseHTTPSRRonNetwork(bool& aTRREnabled) {
1018 // Respect the pref.
1019 if (StaticPrefs::network_dns_force_use_https_rr()) {
1020 aTRREnabled = true;
1021 return true;
1022 }
1023
1024 aTRREnabled = false;
1025
1026 if (nsCOMPtr<nsIDNSService> dns = mozilla::components::DNS::Service()) {
1027 nsIDNSService::ResolverMode mode;
1028 // If the browser is currently using TRR/DoH, then it can
1029 // definitely resolve HTTPS records.
1030 if (NS_SUCCEEDED(dns->GetCurrentTrrMode(&mode))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dns->GetCurrentTrrMode
(&mode))), 1)))
) {
1031 if (mode == nsIDNSService::MODE_TRRFIRST) {
1032 RefPtr<TRRService> trr = TRRService::Get();
1033 if (trr && trr->IsConfirmed()) {
1034 aTRREnabled = true;
1035 }
1036 } else if (mode == nsIDNSService::MODE_TRRONLY) {
1037 aTRREnabled = true;
1038 }
1039 if (aTRREnabled) {
1040 return true;
1041 }
1042 }
1043 }
1044
1045 // With Happy Eyeballs enabled we can allow native HTTPS RR queries: HE's
1046 // resolution-delay timer lets connection attempts proceed using the A/AAAA
1047 // results even when the native HTTPS RR lookup is slow or blocked.
1048 if (StaticPrefs::network_http_happy_eyeballs_enabled()) {
1049 return true;
1050 }
1051
1052 if (RefPtr<NetworkConnectivityService> ncs =
1053 NetworkConnectivityService::GetSingleton()) {
1054 nsINetworkConnectivityService::ConnectivityState state;
1055 if (NS_SUCCEEDED(ncs->GetDNS_HTTPS(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetDNS_HTTPS
(&state))), 1)))
&&
1056 state == nsINetworkConnectivityService::NOT_AVAILABLE) {
1057 return false;
1058 }
1059 }
1060 return true;
1061}
1062
1063nsresult nsHttpChannel::MaybeUseHTTPSRRForUpgrade(bool aShouldUpgrade,
1064 nsresult aStatus) {
1065 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
1066 return aStatus;
1067 }
1068
1069 RefPtr<mozilla::dom::BrowsingContext> bc;
1070 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
1071 bool forceOffline = bc && bc->Top()->GetForceOffline();
1072
1073 if (mURI->SchemeIs("https") || aShouldUpgrade || !LoadUseHTTPSSVC() ||
1074 forceOffline) {
1075 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
1076 }
1077
1078 auto shouldSkipUpgradeWithHTTPSRR = [&]() -> bool {
1079 if (mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) {
1080 return true;
1081 }
1082
1083 // Skip using HTTPS RR to upgrade when this is not a top-level load and the
1084 // loading principal is http.
1085 if ((mLoadInfo->GetExternalContentPolicyType() !=
1086 ExtContentPolicy::TYPE_DOCUMENT) &&
1087 (mLoadInfo->GetLoadingPrincipal() &&
1088 mLoadInfo->GetLoadingPrincipal()->SchemeIs("http"))) {
1089 return true;
1090 }
1091
1092 // If the network connectivity checker indicates the network is
1093 // blocking HTTPS requests, then we should skip them so we don't
1094 // needlessly wait for a timeout.
1095 bool trrEnabled = false;
1096 if (!canUseHTTPSRRonNetwork(trrEnabled)) {
1097 return true;
1098 }
1099
1100 // Don't block the channel when TRR is not used.
1101 if (!trrEnabled) {
1102 return true;
1103 }
1104
1105 auto dnsStrategy = ComputeProxyDNSStrategy();
1106 if (dnsStrategy != nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN) {
1107 return true;
1108 }
1109
1110 nsAutoCString uriHost;
1111 mURI->GetAsciiHost(uriHost);
1112
1113 return gHttpHandler->IsHostExcludedForHTTPSRR(uriHost);
1114 };
1115
1116 if (shouldSkipUpgradeWithHTTPSRR()) {
1117 StoreUseHTTPSSVC(false);
1118 // If the website does not want to use HTTPS RR, we should set
1119 // NS_HTTP_DISALLOW_HTTPS_RR. This is for avoiding HTTPS RR being used by
1120 // the transaction.
1121 DisallowHTTPSRR(mCaps);
1122 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
1123 }
1124
1125 if (mHTTPSSVCRecord.isSome()) {
1126 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)
1127 "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)
1128 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)
;
1129 StoreWaitHTTPSSVCRecord(false);
1130 bool hasHTTPSRR = (mHTTPSSVCRecord.ref() != nullptr);
1131 return ContinueOnBeforeConnect(hasHTTPSRR, aStatus, hasHTTPSRR);
1132 }
1133
1134 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)
1135 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)
;
1136
1137 OriginAttributes originAttributes;
1138 StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(this, originAttributes);
1139
1140 RefPtr<nsDNSPrefetch> resolver =
1141 new nsDNSPrefetch(mURI, originAttributes, nsIRequest::GetTRRMode());
1142 nsWeakPtr weakPtrThis(
1143 do_GetWeakReference(static_cast<nsIHttpChannel*>(this)));
1144 nsresult rv = resolver->FetchHTTPSSVC(
1145 mCaps & NS_HTTP_REFRESH_DNS(1 << 3), !LoadUseHTTPSSVC(),
1146 [weakPtrThis](nsIDNSHTTPSSVCRecord* aRecord) {
1147 nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(weakPtrThis);
1148 RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(channel);
1149 if (httpChannelImpl) {
1150 httpChannelImpl->OnHTTPSRRAvailable(aRecord);
1151 }
1152 });
1153 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1154 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)
1155 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)
;
1156 return ContinueOnBeforeConnect(aShouldUpgrade, aStatus);
1157 }
1158
1159 StoreWaitHTTPSSVCRecord(true);
1160 return NS_OK;
1161}
1162
1163nsresult nsHttpChannel::ContinueOnBeforeConnect(bool aShouldUpgrade,
1164 nsresult aStatus,
1165 bool aUpgradeWithHTTPSRR) {
1166 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)
1167 ("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)
1168 "[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)
1169 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)
;
1170
1171 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", 1171
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadWaitHTTPSSVCRecord()"
")"); do { MOZ_CrashSequence(__null, 1171); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1172
1173 if (NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))) {
1174 return aStatus;
1175 }
1176
1177 if (aShouldUpgrade && !mURI->SchemeIs("https")) {
1178 // only set HTTPS_RR to be responsbile for the upgrade in the loadinfo
1179 // if it actually was responsible, otherwise the correct flag is
1180 // already present in the loadinfo.
1181 if (aUpgradeWithHTTPSRR) {
1182 mLoadInfo->SetHttpsUpgradeTelemetry(nsILoadInfo::HTTPS_RR);
1183 }
1184 return AsyncCall(&nsHttpChannel::HandleAsyncRedirectChannelToHttps);
1185 }
1186
1187 // ensure that we are using a valid hostname
1188 if (!net_IsValidDNSHost(nsDependentCString(mConnectionInfo->Origin()))) {
1189 return NS_ERROR_UNKNOWN_HOST;
1190 }
1191
1192 if (mUpgradeProtocolCallback) {
1193 // Websockets can run over HTTP/2, but other upgrades can't.
1194 if (mUpgradeProtocol.EqualsLiteral("websocket") &&
1195 StaticPrefs::network_http_http2_websockets()) {
1196 // Need to tell the conn manager that we're ok with http/2 even with
1197 // the allow keepalive bit not set. That bit needs to stay off,
1198 // though, in case we end up having to fallback to http/1.1 (where
1199 // we absolutely do want to disable keepalive).
1200 mCaps |= NS_HTTP_ALLOW_SPDY_WITHOUT_KEEPALIVE(1 << 15);
1201 } else {
1202 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
1203 }
1204 // Upgrades cannot use HTTP/3.
1205 // TODO: When mUpgradeProtocolCallback is not null, we should allow HTTP/3
1206 // for connect-udp.
1207 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
1208 // NS_HTTP_STICKY_CONNECTION breaks the (non-Happy-Eyeballs) HTTPS RR
1209 // fallback mechanism, which restarts the transaction to fall back. Happy
1210 // Eyeballs instead races endpoints (honoring the HTTPS RR port, hints and
1211 // ALPN) and dispatches the sticky upgrade onto the winner with no restart,
1212 // so it can safely use HTTPS RR. Only disallow HTTPS RR for upgrades that
1213 // are not handled by Happy Eyeballs.
1214 if (!(mCaps & NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30))) {
1215 DisallowHTTPSRR(mCaps);
1216 }
1217 }
1218
1219 if (LoadIsTRRServiceChannel()) {
1220 mCaps |= NS_HTTP_LARGE_KEEPALIVE(1 << 1);
1221 DisallowHTTPSRR(mCaps);
1222 }
1223
1224 if (mTransactionSticky) {
1225 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", 1225
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadAuthRedirectedChannel()"
")"); do { MOZ_CrashSequence(__null, 1225); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1226 // this means this is a redirected channel channel due to auth retry and a
1227 // connection based auth scheme was used
1228 // we have a reference to the old-transaction with sticky connection which
1229 // we need to use
1230 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
1231 }
1232
1233 mCaps |= NS_HTTP_TRR_FLAGS_FROM_MODE(nsIRequest::GetTRRMode())((static_cast<uint32_t>(nsIRequest::GetTRRMode()) &
3) << 19)
;
1234
1235 // Finalize ConnectionInfo flags before SpeculativeConnect
1236 mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0);
1237 mConnectionInfo->SetPrivate(mPrivateBrowsing);
1238 mConnectionInfo->SetNoSpdy(mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7));
1239 mConnectionInfo->SetBeConservative((mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) ||
1240 LoadBeConservative());
1241 mConnectionInfo->SetTlsFlags(mTlsFlags);
1242 mConnectionInfo->SetIsTrrServiceChannel(LoadIsTRRServiceChannel());
1243 mConnectionInfo->SetTRRMode(nsIRequest::GetTRRMode());
1244 mConnectionInfo->SetIPv4Disabled(mCaps & NS_HTTP_DISABLE_IPV4(1 << 17));
1245 mConnectionInfo->SetIPv6Disabled(mCaps & NS_HTTP_DISABLE_IPV6(1 << 18));
1246 mConnectionInfo->SetHttp3Disabled(mCaps & NS_HTTP_DISALLOW_HTTP3(1 << 21));
1247 mConnectionInfo->SetAnonymousAllowClientCert(
1248 (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) != 0);
1249
1250 if (mWebTransportSessionEventListener) {
1251 nsTArray<RefPtr<nsIWebTransportHash>> aServerCertHashes;
1252 nsresult rv;
1253 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
1254 do_QueryInterface(mWebTransportSessionEventListener, &rv);
1255 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"
, 1255); return rv; } } while (false)
;
1256
1257 wtconSettings->GetServerCertificateHashes(aServerCertHashes);
1258 gHttpHandler->ConnMgr()->StoreServerCertHashes(
1259 mConnectionInfo, gHttpHandler->IsHttp2Excluded(mConnectionInfo),
1260 !Http3Allowed(), std::move(aServerCertHashes));
1261 }
1262
1263 if (ShouldIntercept()) {
1264 return RedirectToInterceptedChannel();
1265 }
1266
1267 // notify "http-on-before-connect" observers
1268 gHttpHandler->OnBeforeConnect(this);
1269
1270 return CallOrWaitForResume([](auto* self) { return self->Connect(); });
1271}
1272
1273class MOZ_STACK_CLASS AddResponseHeadersToResponseHead final
1274 : public nsIHttpHeaderVisitor {
1275 public:
1276 explicit AddResponseHeadersToResponseHead(nsHttpResponseHead* aResponseHead)
1277 : mResponseHead(aResponseHead) {}
1278
1279 NS_IMETHODvirtual nsresult VisitHeader(const nsACString& aHeader,
1280 const nsACString& aValue) override {
1281 nsAutoCString headerLine = aHeader + ": "_ns + aValue;
1282 DebugOnly<nsresult> rv = mResponseHead->ParseHeaderLine(headerLine);
1283 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"
, 1283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1283); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1284
1285 return NS_OK;
1286 }
1287
1288 NS_IMETHODvirtual nsresult QueryInterface(REFNSIIDconst nsIID& aIID, void** aInstancePtr) override;
1289
1290 // Stub AddRef/Release since this is a stack class.
1291 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType AddRef(void) override {
1292 return ++mRefCnt;
1293 }
1294
1295 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType Release(void) override {
1296 return --mRefCnt;
1297 }
1298
1299 virtual ~AddResponseHeadersToResponseHead() {
1300 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"
, 1300); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mRefCnt == 0"
")"); do { MOZ_CrashSequence(__null, 1300); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1301 }
1302
1303 private:
1304 nsHttpResponseHead* mResponseHead;
1305
1306 nsrefcnt mRefCnt = 0;
1307};
1308
1309NS_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"
, 1309); 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; }
1310
1311nsresult nsHttpChannel::HandleOverrideResponse() {
1312 // Start building a response with the data from mOverrideResponse.
1313 mResponseHead = MakeUnique<nsHttpResponseHead>();
1314
1315 // Apply override response status code and status text.
1316 uint32_t statusCode;
1317 nsresult rv = mOverrideResponse->GetResponseStatus(&statusCode);
1318 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"
, 1318); return rv; } } while (false)
;
1319
1320 nsAutoCString statusText;
1321 rv = mOverrideResponse->GetResponseStatusText(statusText);
1322 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"
, 1322); return rv; } } while (false)
;
1323
1324 // Hardcoding protocol HTTP/1.1
1325 nsPrintfCString line("HTTP/1.1 %u %s", statusCode, statusText.get());
1326 rv = mResponseHead->ParseStatusLine(line);
1327 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"
, 1327); return rv; } } while (false)
;
1328
1329 // Apply override response headers.
1330 AddResponseHeadersToResponseHead visitor(mResponseHead.get());
1331 rv = mOverrideResponse->VisitResponseHeaders(&visitor);
1332 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"
, 1332); return rv; } } while (false)
;
1333
1334 if (WillRedirect(*mResponseHead)) {
1335 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
1336 // to avoid event dispatching latency.
1337 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)
;
1338 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
1339 }
1340
1341 // This block parses the cookie header, collects any cookie changes,
1342 // and sends them to the parent actor.
1343 {
1344 RefPtr<HttpChannelParent> httpParent;
1345 RefPtr<CookieObserver> cookieObserver;
1346
1347 CookieServiceParent::CookieProcessingGuard cookieProcessingGuard;
1348 MaybeInitializeCookieProcessingGuard(
1349 this, cookieProcessingGuard, cookieObserver, httpParent, statusCode);
1350
1351 // Handle Set-Cookie headers as if the response was from networking.
1352 CookieVisitor cookieVisitor(mResponseHead.get());
1353 SetCookieHeaders(cookieVisitor.CookieHeaders());
1354
1355 if (cookieObserver) {
1356 nsTArray<CookieChange> cookieChanges;
1357 cookieObserver->StealChanges(cookieChanges);
1358
1359 if (!cookieChanges.IsEmpty()) {
1360 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"
, 1360); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpParent"
")"); do { MOZ_CrashSequence(__null, 1360); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1361 httpParent->SetCookieChanges(std::move(cookieChanges));
1362 }
1363 }
1364 }
1365
1366 rv = ProcessWAICTHeader();
1367 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1368 return rv;
1369 }
1370
1371 if (NS_FAILED(ProcessSecurityHeaders())((bool)(__builtin_expect(!!(NS_FAILED_impl(ProcessSecurityHeaders
())), 0)))
) {
1372 NS_WARNING("ProcessSecurityHeaders failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSecurityHeaders failed, continuing load."
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1372)
;
1373 }
1374
1375 if ((statusCode < 500) && (statusCode != 421)) {
1376 ProcessAltService();
1377 }
1378
1379 nsAutoCString body;
1380 rv = mOverrideResponse->GetResponseBody(body);
1381 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"
, 1381); return rv; } } while (false)
;
1382
1383 nsCOMPtr<nsIInputStream> stringStream;
1384 rv = NS_NewCStringInputStream(getter_AddRefs(stringStream), body);
1385 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"
, 1385); return rv; } } while (false)
;
1386 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), stringStream, 0, 0,
1387 true);
1388 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1389 stringStream->Close();
1390 return rv;
1391 }
1392
1393 rv = mCachePump->AsyncRead(this);
1394 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1395
1396 return NS_OK;
1397}
1398
1399nsresult nsHttpChannel::Connect() {
1400 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)
;
1401
1402 if (mAPIRedirectTo) {
1403 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)
1404 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)
;
1405
1406 nsresult rv = StartRedirectChannelToURI(
1407 mAPIRedirectTo->first(),
1408 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_PERMANENT |
1409 nsIChannelEventSink::REDIRECT_TRANSPARENT
1410 : nsIChannelEventSink::REDIRECT_PERMANENT);
1411 mAPIRedirectTo = Nothing();
1412 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1413 return NS_OK;
1414 }
1415 return NS_ERROR_FAILURE;
1416 }
1417
1418 // If mOverrideResponse is set, bypass the rest of the connection and reply
1419 // immediately with a response built using the data from mOverrideResponse.
1420 if (mOverrideResponse) {
1421 return HandleOverrideResponse();
1422 }
1423
1424 // Don't allow resuming when cache must be used
1425 if (LoadResuming() && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
1426 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)
;
1427 return NS_ERROR_DOCUMENT_NOT_CACHED;
1428 }
1429
1430 // Step 8.18 of HTTP-network-or-cache fetch
1431 // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
1432 nsAutoCString rangeVal;
1433 if (NS_SUCCEEDED(GetRequestHeader("Range"_ns, rangeVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Range"_ns, rangeVal))), 1)))
) {
1434 SetRequestHeader("Accept-Encoding"_ns, "identity"_ns, false);
1435 }
1436
1437 if (mRequestHead.IsPost() || mRequestHead.IsPatch()) {
1438 // If the post id is already set then this is an attempt to replay
1439 // a post/patch transaction via the cache. Otherwise, we need a unique
1440 // post id for this transaction.
1441 if (mPostID == 0) {
1442 mPostID = gHttpHandler->GenerateUniqueID();
1443 }
1444
1445 if (StaticPrefs::network_http_idempotencyKey_enabled() &&
1446 !mRequestHead.HasHeader(nsHttp::Idempotency_Key)) {
1447 // check if we need to add
1448 // idempotency-key header
1449 // See Bug 1830022 for more details
1450 nsAutoCString key;
1451 gHttpHandler->GenerateIdempotencyKeyForPost(mPostID, mLoadInfo, key);
1452 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", 1453
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
")"); do { MOZ_CrashSequence(__null, 1453); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1453 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", 1453
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
")"); do { MOZ_CrashSequence(__null, 1453); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1454 }
1455 }
1456
1457#ifdef MOZ_WIDGET_ANDROID
1458 bool val = false;
1459 if (nsIOService::ShouldAddAdditionalSearchHeaders(mURI, &val)) {
1460 SetRequestHeader("X-Search-Subdivision"_ns, val ? "1"_ns : "0"_ns, false);
1461 }
1462#endif
1463
1464 bool isTrackingResource = IsThirdPartyTrackingResource();
1465 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)
1466 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)
1467 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)
;
1468
1469 if (isTrackingResource) {
1470 AddClassFlags(nsIClassOfService::Tail);
1471 }
1472
1473 if (WaitingForTailUnblock()) {
1474 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", 1474
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 1474); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1475 mOnTailUnblock = &nsHttpChannel::ConnectOnTailUnblock;
1476 return NS_OK;
1477 }
1478
1479 return ConnectOnTailUnblock();
1480}
1481
1482nsresult nsHttpChannel::ConnectOnTailUnblock() {
1483 nsresult rv;
1484
1485 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)
;
1486 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ConnectOnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject1487( "nsHttpChannel::ConnectOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
1487 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject1487( "nsHttpChannel::ConnectOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
1488
1489 // Consider opening a TCP connection right away.
1490 SpeculativeConnect();
1491
1492 // open a cache entry for this channel...
1493 rv = OpenCacheEntry(mURI->SchemeIs("https"));
1494
1495 // do not continue if asyncOpenCacheEntry is in progress
1496 if (AwaitingCacheCallbacks()) {
1497 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)
1498 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)
;
1499 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"
, 1499); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Unexpected state" ")"); do { MOZ_CrashSequence(__null
, 1499); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1500
1501 // Backstop against a wedged cache entry that never delivers its callback.
1502 MaybeStartCacheWaitTimer();
1503
1504 if (mNetworkTriggered && mWaitingForProxy) {
1505 // Someone has called TriggerNetwork(), meaning we are racing the
1506 // network with the cache.
1507 mWaitingForProxy = false;
1508 return ContinueConnect();
1509 }
1510
1511 return NS_OK;
1512 }
1513
1514 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1515 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)
1516 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)
;
1517 // if this channel is only allowed to pull from the cache, then
1518 // we must fail if we were unable to open a cache entry.
1519 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1520 return NS_ERROR_DOCUMENT_NOT_CACHED;
1521 }
1522 // otherwise, let's just proceed without using the cache.
1523 }
1524
1525 return TriggerNetwork();
1526}
1527
1528nsresult nsHttpChannel::ContinueConnect() {
1529 // If we need to start a CORS preflight, do it now!
1530 // Note that it is important to do this before the early returns below.
1531 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ContinueConnect", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject1532( "nsHttpChannel::ContinueConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
1532 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject1532( "nsHttpChannel::ContinueConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
1533 if (!LoadIsCorsPreflightDone() && LoadRequireCORSPreflight()) {
1534 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", 1534
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPreflightChannel"
")"); do { MOZ_CrashSequence(__null, 1534); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1535 nsresult rv = nsCORSListenerProxy::StartCORSPreflight(
1536 this, this, mUnsafeHeaders, getter_AddRefs(mPreflightChannel));
1537 return rv;
1538 }
1539
1540 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"
, 1542); 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, 1542); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1541 "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"
, 1542); 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, 1542); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1542 "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"
, 1542); 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, 1542); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1543
1544 RefPtr<mozilla::dom::BrowsingContext> bc;
1545 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
1546
1547 // we may or may not have a cache entry at this point
1548 if (mCacheEntry) {
1549 // read straight from the cache if possible...
1550 if (CachedContentIsValid()) {
1551 // If we're forced offline, and set to bypass the cache, return offline.
1552 if (bc && bc->Top()->GetForceOffline() &&
1553 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
1554 return NS_ERROR_OFFLINE;
1555 }
1556
1557 nsRunnableMethod<nsHttpChannel>* event = nullptr;
1558 nsresult rv;
1559 if (!LoadCachedContentIsPartial()) {
1560 rv = AsyncCall(&nsHttpChannel::AsyncOnExamineCachedResponse, &event);
1561 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1562 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)
;
1563 }
1564 }
1565 rv = ReadFromCache();
1566 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && event) {
1567 event->Revoke();
1568 }
1569
1570 AccumulateCacheHitTelemetry(kCacheHit, this);
1571 mCacheDisposition = kCacheHit;
1572
1573 return rv;
1574 }
1575 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1576 // the cache contains the requested resource, but it must be
1577 // validated before we can reuse it. since we are not allowed
1578 // to hit the net, there's nothing more to do. the document
1579 // is effectively not in the cache.
1580 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)
;
1581 return NS_ERROR_DOCUMENT_NOT_CACHED;
1582 }
1583 } else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1584 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)
;
1585 return NS_ERROR_DOCUMENT_NOT_CACHED;
1586 }
1587
1588 if (mLoadFlags & LOAD_NO_NETWORK_IO) {
1589 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)
;
1590 return NS_ERROR_DOCUMENT_NOT_CACHED;
1591 }
1592
1593 // We're about to hit the network. Don't if we're forced offline.
1594 if (bc && bc->Top()->GetForceOffline()) {
1595 return NS_ERROR_OFFLINE;
1596 }
1597
1598 // hit the net...
1599 nsresult rv = DoConnect(mTransactionSticky);
1600 mTransactionSticky = nullptr;
1601 return rv;
1602}
1603
1604nsresult nsHttpChannel::DoConnect(HttpTransactionShell* aTransWithStickyConn) {
1605 LOG(("nsHttpChannel::DoConnect [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::DoConnect [this=%p]\n", this); } } while (0
)
;
1606
1607 if (!mDNSBlockingPromise.IsEmpty()) {
1608 LOG((" waiting for DNS prefetch"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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 DNS prefetch"); } } while (0)
;
1609
1610 // Transaction is passed only from auth retry for which we will definitely
1611 // not block on DNS to alter the origin server name for IP; it has already
1612 // been done.
1613 MOZ_ASSERT(!aTransWithStickyConn)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTransWithStickyConn)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aTransWithStickyConn))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!aTransWithStickyConn"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 1613
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTransWithStickyConn"
")"); do { MOZ_CrashSequence(__null, 1613); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1614 MOZ_ASSERT(mDNSBlockingThenable)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDNSBlockingThenable)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDNSBlockingThenable))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("mDNSBlockingThenable"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 1614
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDNSBlockingThenable"
")"); do { MOZ_CrashSequence(__null, 1614); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1615
1616 nsCOMPtr<nsISerialEventTarget> target(do_GetMainThread());
1617 RefPtr<nsHttpChannel> self(this);
1618 mDNSBlockingThenable->Then(
1619 target, __func__,
1620 [self](const nsCOMPtr<nsIDNSRecord>& aRec) {
1621 nsresult rv = self->DoConnectActual(nullptr);
1622 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1623 self->CloseCacheEntry(false);
1624 (void)self->AsyncAbort(rv);
1625 }
1626 },
1627 [self](nsresult err) {
1628 self->CloseCacheEntry(false);
1629 (void)self->AsyncAbort(err);
1630 });
1631
1632 // The connection will continue when the promise is resolved in
1633 // OnLookupComplete.
1634 return NS_OK;
1635 }
1636
1637 return DoConnectActual(aTransWithStickyConn);
1638}
1639
1640nsresult nsHttpChannel::DoConnectActual(
1641 HttpTransactionShell* aTransWithStickyConn) {
1642 LOG(("nsHttpChannel::DoConnectActual [this=%p, 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::DoConnectActual [this=%p, aTransWithStickyConn=%p]\n"
, this, aTransWithStickyConn); } } while (0)
1643 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::DoConnectActual [this=%p, aTransWithStickyConn=%p]\n"
, this, aTransWithStickyConn); } } while (0)
;
1644
1645 nsresult rv = SetupChannelForTransaction();
1646 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1647 return rv;
1648 }
1649
1650 return CallOrWaitForResume(
1651 [trans = RefPtr(aTransWithStickyConn)](auto* self) {
1652 return self->DispatchTransaction(trans);
1653 });
1654}
1655
1656nsresult nsHttpChannel::DispatchTransaction(
1657 HttpTransactionShell* aTransWithStickyConn) {
1658 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)
1659 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)
;
1660 nsresult rv = InitTransaction();
1661 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1662 return rv;
1663 }
1664 if (aTransWithStickyConn) {
1665 rv = gHttpHandler->InitiateTransactionWithStickyConn(
1666 mTransaction, mPriority, aTransWithStickyConn);
1667 } else {
1668 rv = gHttpHandler->InitiateTransaction(mTransaction, mPriority);
1669 }
1670
1671 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1672 return rv;
1673 }
1674
1675 rv = mTransaction->AsyncRead(this, getter_AddRefs(mTransactionPump));
1676 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1677 return rv;
1678 }
1679
1680 uint32_t suspendCount = mSuspendCount;
1681 if (LoadAsyncResumePending()) {
1682 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)
1683 (" 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)
1684 ", 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)
1685 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)
;
1686 ++suspendCount;
1687 }
1688 while (suspendCount--) {
1689 mTransactionPump->Suspend();
1690 }
1691
1692 return NS_OK;
1693}
1694
1695void nsHttpChannel::SpeculativeConnect() {
1696 // Before we take the latency hit of dealing with the cache, try and
1697 // get the TCP (and SSL) handshakes going so they can overlap.
1698
1699 // don't speculate if we are offline, when doing http upgrade (i.e.
1700 // websockets bootstrap), or if we can't do keep-alive (because then we
1701 // couldn't reuse the speculative connection anyhow).
1702 RefPtr<mozilla::dom::BrowsingContext> bc;
1703 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
1704
1705 if (gIOService->IsOffline() || mUpgradeProtocolCallback ||
1706 !(mCaps & NS_HTTP_ALLOW_KEEPALIVE(1 << 0)) ||
1707 (bc && bc->Top()->GetForceOffline())) {
1708 return;
1709 }
1710
1711 // LOAD_ONLY_FROM_CACHE and LOAD_NO_NETWORK_IO must not hit network.
1712 // LOAD_FROM_CACHE is unlikely to hit network, so skip preconnects for it.
1713 if (mLoadFlags &
1714 (LOAD_ONLY_FROM_CACHE | LOAD_FROM_CACHE | LOAD_NO_NETWORK_IO)) {
1715 return;
1716 }
1717
1718 if (LoadAllowStaleCacheContent()) {
1719 return;
1720 }
1721
1722 nsCOMPtr<nsIInterfaceRequestor> callbacks;
1723 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
1724 getter_AddRefs(callbacks));
1725 if (!callbacks) return;
1726 // Disable HTTPS RR, since the new HappyEyeballs implementation will handle
1727 // it.
1728 bool httpsRRAllowed = !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) &&
1729 !(mCaps & NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30));
1730 (void)gHttpHandler->MaybeSpeculativeConnectWithHTTPSRR(
1731 mConnectionInfo, callbacks,
1732 mCaps & (NS_HTTP_DISALLOW_SPDY(1 << 7) | NS_HTTP_TRR_MODE_MASK((1 << 19) | (1 << 20)) |
1733 NS_HTTP_DISABLE_IPV4(1 << 17) | NS_HTTP_DISABLE_IPV6(1 << 18) |
1734 NS_HTTP_DISALLOW_HTTP3(1 << 21) | NS_HTTP_REFRESH_DNS(1 << 3)),
1735 nsHttpHandler::EchConfigEnabled() && httpsRRAllowed);
1736}
1737
1738void nsHttpChannel::DoNotifyListenerCleanup() {
1739 // We don't need this info anymore
1740 CleanRedirectCacheChainIfNecessary();
1741}
1742
1743void nsHttpChannel::ReleaseListeners() {
1744 HttpBaseChannel::ReleaseListeners();
1745
1746 mChannelClassifier = nullptr;
1747 mWarningReporter = nullptr;
1748 mEarlyHintObserver = nullptr;
1749 mWebTransportSessionEventListener = nullptr;
1750
1751 for (StreamFilterRequest& request : mStreamFilterRequests) {
1752 request.mPromise->Reject(false, __func__);
1753 }
1754 mStreamFilterRequests.Clear();
1755}
1756
1757void nsHttpChannel::DoAsyncAbort(nsresult aStatus) {
1758 (void)AsyncAbort(aStatus);
1759}
1760
1761void nsHttpChannel::HandleAsyncRedirect() {
1762 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"
, 1762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 1762); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1763
1764 if (mSuspendCount) {
1765 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)
;
1766 mCallOnResume = [](nsHttpChannel* self) {
1767 self->HandleAsyncRedirect();
1768 return NS_OK;
1769 };
1770 return;
1771 }
1772
1773 nsresult rv = NS_OK;
1774
1775 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)
;
1776
1777 // since this event is handled asynchronously, it is possible that this
1778 // channel could have been canceled, in which case there would be no point
1779 // in processing the redirect.
1780 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) {
1781 PushRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1782 rv = AsyncProcessRedirection(mResponseHead->Status());
1783 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1784 PopRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1785 // TODO: if !DoNotRender3xxBody(), render redirect body instead.
1786 // But first we need to cache 3xx bodies (bug 748510)
1787 rv = ContinueHandleAsyncRedirect(rv);
1788 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"
, 1788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1788); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1789 }
1790 } else {
1791 rv = ContinueHandleAsyncRedirect(mStatus);
1792 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"
, 1792); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1792); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1793 }
1794}
1795
1796nsresult nsHttpChannel::ContinueHandleAsyncRedirect(nsresult rv) {
1797 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1798 // If AsyncProcessRedirection fails, then we have to send out the
1799 // OnStart/OnStop notifications.
1800 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)
1801 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)
;
1802
1803 bool redirectsEnabled = !mLoadInfo->GetDontFollowRedirects();
1804
1805 if (redirectsEnabled) {
1806 // TODO: stop failing original channel if redirect vetoed?
1807 mStatus = rv;
1808
1809 DoNotifyListener();
1810
1811 // Blow away cache entry if we couldn't process the redirect
1812 // for some reason (the cache entry might be corrupt).
1813 if (mCacheEntry) {
1814 mCacheEntry->AsyncDoom(nullptr);
1815 }
1816 } else {
1817 DoNotifyListener();
1818 }
1819 }
1820
1821 CloseCacheEntry(true);
1822
1823 StoreIsPending(false);
1824
1825 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1826
1827 return NS_OK;
1828}
1829
1830void nsHttpChannel::HandleAsyncNotModified() {
1831 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"
, 1831); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 1831); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1832
1833 if (mSuspendCount) {
1834 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)
;
1835 mCallOnResume = [](nsHttpChannel* self) {
1836 self->HandleAsyncNotModified();
1837 return NS_OK;
1838 };
1839 return;
1840 }
1841
1842 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)
;
1843
1844 DoNotifyListener();
1845
1846 CloseCacheEntry(false);
1847
1848 StoreIsPending(false);
1849
1850 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1851}
1852
1853nsresult nsHttpChannel::SetupChannelForTransaction() {
1854 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)
1855 "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)
1856 "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)
1857 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)
;
1858
1859 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"
, 1859); return NS_ERROR_ALREADY_INITIALIZED; } } while (false
)
;
1860
1861 nsresult rv;
1862
1863 if (StaticPrefs::network_http_priority_header_enabled()) {
1864 SetPriorityHeader();
1865 }
1866
1867 StoreUsedNetwork(1);
1868
1869 if (!LoadAllowSpdy()) {
1870 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
1871 }
1872 if (!LoadAllowHttp3()) {
1873 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
1874 }
1875 if (LoadBeConservative()) {
1876 mCaps |= NS_HTTP_BE_CONSERVATIVE(1 << 11);
1877 }
1878
1879 if (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) {
1880 mCaps |= NS_HTTP_LOAD_ANONYMOUS_CONNECT_ALLOW_CLIENT_CERT(1 << 23);
1881 }
1882
1883 if (nsContentUtils::ShouldResistFingerprinting(this,
1884 RFPTarget::HttpUserAgent)) {
1885 mCaps |= NS_HTTP_USE_RFP(1 << 26);
1886 }
1887
1888 // Use the URI path if not proxying (transparent proxying such as proxy
1889 // CONNECT does not count here). Also figure out what HTTP version to use.
1890 nsAutoCString buf, path;
1891 nsCString* requestURI;
1892
1893 // This is the normal e2e H1 path syntax "/index.html"
1894 rv = mURI->GetPathQueryRef(path);
1895 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1896 return rv;
1897 }
1898
1899 // path may contain UTF-8 characters, so ensure that they're escaped.
1900 if (NS_EscapeURL(path.get(), path.Length(), esc_OnlyNonASCII | esc_Spaces,
1901 buf)) {
1902 requestURI = &buf;
1903 } else {
1904 requestURI = &path;
1905 }
1906
1907 // trim off the #ref portion if any...
1908 int32_t ref1 = requestURI->FindChar('#');
1909 if (ref1 != kNotFound) {
1910 requestURI->SetLength(ref1);
1911 }
1912
1913 if (mConnectionInfo->UsingConnect() || !mConnectionInfo->UsingHttpProxy()) {
1914 mRequestHead.SetVersion(gHttpHandler->HttpVersion());
1915 } else {
1916 mRequestHead.SetPath(*requestURI);
1917
1918 // RequestURI should be the absolute uri H1 proxy syntax
1919 // "http://foo/index.html" so we will overwrite the relative version in
1920 // requestURI
1921 rv = mURI->GetUserPass(buf);
1922 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1923 if (!buf.IsEmpty() && ((strncmp(mSpec.get(), "http:", 5) == 0) ||
1924 strncmp(mSpec.get(), "https:", 6) == 0)) {
1925 nsCOMPtr<nsIURI> tempURI = nsIOService::CreateExposableURI(mURI);
1926 rv = tempURI->GetAsciiSpec(path);
1927 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1928 requestURI = &path;
1929 } else {
1930 requestURI = &mSpec;
1931 }
1932
1933 // trim off the #ref portion if any...
1934 int32_t ref2 = requestURI->FindChar('#');
1935 if (ref2 != kNotFound) {
1936 requestURI->SetLength(ref2);
1937 }
1938
1939 mRequestHead.SetVersion(gHttpHandler->ProxyHttpVersion());
1940 }
1941
1942 mRequestHead.SetRequestURI(*requestURI);
1943
1944 // set the request time for cache expiration calculations
1945 mRequestTime = NowInSeconds()PRTimeToSeconds(PR_Now());
1946 StoreRequestTimeInitialized(true);
1947
1948 // if doing a reload, force end-to-end
1949 if (mLoadFlags & LOAD_BYPASS_CACHE) {
1950 // We need to send 'Pragma:no-cache' to inhibit proxy caching even if
1951 // no proxy is configured since we might be talking with a transparent
1952 // proxy, i.e. one that operates at the network level. See bug #14772.
1953 // But we should not touch Pragma if Cache-Control is already set
1954 // (https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A3)
1955 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1956 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
1957 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"
, 1957); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1957); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1958 }
1959 // If we're configured to speak HTTP/1.1 then also send 'Cache-control:
1960 // no-cache'. But likewise don't touch Cache-Control if it's already set.
1961 if (mRequestHead.Version() >= HttpVersion::v1_1 &&
1962 !mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1963 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "no-cache", true);
1964 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"
, 1964); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1964); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1965 }
1966 } else if (mLoadFlags & VALIDATE_ALWAYS) {
1967 // We need to send 'Cache-Control: max-age=0' to force each cache along
1968 // the path to the origin server to revalidate its own entry, if any,
1969 // with the next cache or server. See bug #84847.
1970 //
1971 // If we're configured to speak HTTP/1.0 then just send 'Pragma: no-cache'
1972 //
1973 // But don't send the headers if they're already set:
1974 // https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A2
1975 if (mRequestHead.Version() >= HttpVersion::v1_1) {
1976 if (!mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1977 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "max-age=0",
1978 true);
1979 }
1980 } else {
1981 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1982 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
1983 }
1984 }
1985 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"
, 1985); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1985); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1986 }
1987
1988 if (LoadResuming()) {
1989 char byteRange[32];
1990 SprintfLiteral(byteRange, "bytes=%" PRIu64"l" "u" "-", mStartPos);
1991 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(byteRange));
1992 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"
, 1992); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1992); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1993
1994 if (!mEntityID.IsEmpty()) {
1995 // Also, we want an error if this resource changed in the meantime
1996 // Format of the entity id is: escaped_etag/size/lastmod
1997 nsCString::const_iterator start, end, slash;
1998 mEntityID.BeginReading(start);
1999 mEntityID.EndReading(end);
2000 mEntityID.BeginReading(slash);
2001
2002 if (FindCharInReadable('/', slash, end)) {
2003 nsAutoCString ifMatch;
2004 rv = mRequestHead.SetHeader(
2005 nsHttp::If_Match,
2006 NS_UnescapeURL(Substring(start, slash), 0, ifMatch));
2007 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"
, 2007); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2007); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2008
2009 ++slash; // Incrementing, so that searching for '/' won't find
2010 // the same slash again
2011 }
2012
2013 if (FindCharInReadable('/', slash, end)) {
2014 rv = mRequestHead.SetHeader(nsHttp::If_Unmodified_Since,
2015 Substring(++slash, end));
2016 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"
, 2016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2016); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2017 }
2018 }
2019 }
2020
2021 // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
2022 if (mLoadFlags & LOAD_ANONYMOUS) mCaps |= NS_HTTP_LOAD_ANONYMOUS(1 << 4);
2023
2024 if (mUpgradeProtocolCallback) {
2025 rv = mRequestHead.SetHeader(nsHttp::Upgrade, mUpgradeProtocol, 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 rv = mRequestHead.SetHeaderOnce(nsHttp::Connection, nsHttp::Upgrade.get(),
2028 false);
2029 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"
, 2029); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2029); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2030 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
2031 mCaps &= ~NS_HTTP_ALLOW_KEEPALIVE(1 << 0);
2032 }
2033
2034 if (mWebTransportSessionEventListener) {
2035 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
2036 }
2037
2038 return NS_OK;
2039}
2040
2041// Updates mLNAPermission members based on existing permission and tracking
2042// flags in load info
2043LNAPermission nsHttpChannel::UpdateLocalNetworkAccessPermissions(
2044 const nsACString& aPermissionType) {
2045 // We should arrive at this point after LNA has been detected at the
2046 // transaction layer and has errored
2047
2048 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", 2049
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
")"); do { MOZ_CrashSequence(__null, 2049); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2049 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", 2049
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
")"); do { MOZ_CrashSequence(__null, 2049); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2050 LNAPermission userPerms = aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY
2051 ? mLNAPermission.mLocalHostPermission
2052 : mLNAPermission.mLocalNetworkPermission;
2053
2054 if (NS_WARN_IF(userPerms != LNAPermission::Pending)NS_warn_if_impl(userPerms != LNAPermission::Pending, "userPerms != LNAPermission::Pending"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2054
)
) {
2055 // Unexpected condition, we should not hit this case
2056 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"
, 2058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2058); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2057 "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"
, 2058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2058); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2058 "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"
, 2058); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2058); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
2059 return userPerms;
2060 }
2061
2062 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"
, 2062); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->TriggeringPrincipal()"
") (" "need triggering principal" ")"); do { MOZ_CrashSequence
(__null, 2062); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2063
2064 // Skip LNA checks if the triggering principal and target are same origin.
2065 // Note: This could be a case where there is a network change or device
2066 // migration to a private or corporate network.
2067 //
2068 // This only holds when we connect directly to the origin's own endpoint. If
2069 // the connection was rerouted via Alt-Svc to a different host/port, a
2070 // same-origin URL no longer implies we are talking to the origin itself: a
2071 // public origin could steer same-origin traffic to an attacker-selected
2072 // private address. Don't grant the exemption in that case.
2073 bool reroutedElsewhere =
2074 mConnectionInfo && !mConnectionInfo->GetRoutedHost().IsEmpty() &&
2075 (!mConnectionInfo->GetRoutedHost().Equals(mConnectionInfo->GetOrigin()) ||
2076 mConnectionInfo->RoutedPort() != mConnectionInfo->OriginPort());
2077 // This exemption (same origin) should apply only to secure contexts.
2078 const bool triggeringPrincipalIsPotentiallyTrustworthy =
2079 mLoadInfo->TriggeringPrincipal()->GetIsOriginPotentiallyTrustworthy();
2080 bool isSameOrigin = false;
2081 nsresult rv =
2082 mLoadInfo->TriggeringPrincipal()->IsSameOrigin(mURI, &isSameOrigin);
2083 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && isSameOrigin && !reroutedElsewhere &&
2084 triggeringPrincipalIsPotentiallyTrustworthy) {
2085 userPerms = LNAPermission::Granted;
2086 return userPerms;
2087 }
2088
2089 // Skip LNA checks if captive portal is active
2090 nsCOMPtr<nsICaptivePortalService> cps = CaptivePortalService::GetSingleton();
2091 if (cps) {
2092 int32_t state = cps->State();
2093 if (state == nsICaptivePortalService::LOCKED_PORTAL &&
2094 aPermissionType == LOCAL_NETWORK_PERMISSION_KEY) {
2095 userPerms = LNAPermission::Granted;
2096 return userPerms;
2097 }
2098 }
2099
2100 // Step 1. Check for Existing Allow or Deny permission
2101 if (nsContentUtils::IsExactSitePermAllow(mLoadInfo->TriggeringPrincipal(),
2102 aPermissionType)) {
2103 userPerms = LNAPermission::Granted;
2104 return userPerms;
2105 }
2106
2107 if (nsContentUtils::IsExactSitePermDeny(mLoadInfo->TriggeringPrincipal(),
2108 aPermissionType)) {
2109 userPerms = LNAPermission::Denied;
2110 return userPerms;
2111 }
2112
2113 // Step 2.If this is from third Party Tracker, just block
2114 uint32_t flags = 0;
2115 using CF = nsIClassifiedChannel::ClassificationFlags;
2116 if (StaticPrefs::network_lna_block_trackers() &&
2117 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
2118 mLoadInfo->GetTriggeringThirdPartyClassificationFlags(&flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
&&
2119 (flags & (CF::CLASSIFIED_ANY_BASIC_TRACKING |
2120 CF::CLASSIFIED_ANY_SOCIAL_TRACKING)) != 0) {
2121 userPerms = LNAPermission::Denied;
2122 return userPerms;
2123 }
2124
2125 // Check if we should block LNA requests from insecure contexts
2126 if (StaticPrefs::network_lna_block_insecure_contexts() &&
2127 !triggeringPrincipalIsPotentiallyTrustworthy) {
2128 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)
2129 ("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)
2130 "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)
2131 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)
;
2132 userPerms = LNAPermission::Denied;
2133 return userPerms;
2134 }
2135
2136 // Step 3
2137 // could not determine the permission, lets prompt user
2138 // for permission if lna blocking is enabled
2139 if (StaticPrefs::network_lna_blocking()) {
2140 return userPerms;
2141 }
2142
2143 // we dont have reasons to block the request so we allow this LNA request
2144 // Ideally we should not hit this case once the feature is fully shipped
2145 userPerms = LNAPermission::Granted;
2146 return userPerms;
2147}
2148
2149nsresult nsHttpChannel::InitTransaction() {
2150 nsresult rv;
2151 // create wrapper for this channel's notification callbacks
2152 nsCOMPtr<nsIInterfaceRequestor> callbacks;
2153 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
2154 getter_AddRefs(callbacks));
2155
2156 // create the transaction object
2157 if (nsIOService::UseSocketProcess()) {
2158 if (NS_WARN_IF(!gIOService->SocketProcessReady())NS_warn_if_impl(!gIOService->SocketProcessReady(), "!gIOService->SocketProcessReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2158
)
) {
2159 return NS_ERROR_NOT_AVAILABLE;
2160 }
2161 RefPtr<SocketProcessParent> socketProcess =
2162 SocketProcessParent::GetSingleton();
2163 if (!socketProcess->CanSend()) {
2164 return NS_ERROR_NOT_AVAILABLE;
2165 }
2166
2167 nsCOMPtr<nsIParentChannel> parentChannel;
2168 NS_QueryNotificationCallbacks(this, parentChannel);
2169 RefPtr<DocumentLoadListener> documentChannelParent =
2170 do_QueryObject(parentChannel);
2171 // See HttpTransactionChild::CanSendODAToContentProcessDirectly() and
2172 // nsHttpChannel::CallOnStartRequest() for the reason why we need to know if
2173 // this is a document load. We only send ODA directly to child process for
2174 // non document loads.
2175 RefPtr<HttpTransactionParent> transParent =
2176 new HttpTransactionParent(!!documentChannelParent);
2177 LOG1(("nsHttpChannel %p created HttpTransactionParent %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 HttpTransactionParent %p\n"
, this, transParent.get()); } } while (0)
2178 transParent.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 HttpTransactionParent %p\n"
, this, transParent.get()); } } while (0)
;
2179
2180 // Since OnStopRequest could be sent to child process from socket process
2181 // directly, we need to store these two values in HttpTransactionChild and
2182 // forward to child process until HttpTransactionChild::OnStopRequest is
2183 // called.
2184 transParent->SetRedirectTimestamp(mRedirectStartTimeStamp,
2185 mRedirectEndTimeStamp);
2186
2187 if (socketProcess) {
2188 MOZ_ALWAYS_TRUE(do { if ((__builtin_expect(!!(socketProcess->SendPHttpTransactionConstructor
(transParent)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "socketProcess->SendPHttpTransactionConstructor(transParent)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2189
); AnnotateMozCrashReason("MOZ_CRASH(" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")"); do { MOZ_CrashSequence(__null, 2189); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
2189 socketProcess->SendPHttpTransactionConstructor(transParent))do { if ((__builtin_expect(!!(socketProcess->SendPHttpTransactionConstructor
(transParent)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "socketProcess->SendPHttpTransactionConstructor(transParent)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2189
); AnnotateMozCrashReason("MOZ_CRASH(" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")"); do { MOZ_CrashSequence(__null, 2189); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2190 }
2191 mTransaction = transParent;
2192 } else {
2193 mTransaction = new nsHttpTransaction();
2194 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)
2195 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)
;
2196 }
2197
2198 // Save the mapping of channel id and the channel. We need this mapping for
2199 // nsIHttpActivityObserver.
2200 gHttpHandler->AddHttpChannel(mChannelId, ToSupports(this));
2201
2202 EnsureBrowserId();
2203 EnsureRequestContext();
2204
2205 HttpTrafficCategory category = CreateTrafficCategory();
2206 mTransaction->SetIsForWebTransport(!!mWebTransportSessionEventListener);
2207
2208 RefPtr<mozilla::dom::BrowsingContext> bc;
2209 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
2210
2211 nsILoadInfo::IPAddressSpace parentAddressSpace =
2212 nsILoadInfo::IPAddressSpace::Unknown;
2213 // For worker-initiated requests, read IP address space from the policy
2214 // container which carries the parent document's address space.
2215 Maybe<dom::ClientInfo> clientInfo = mLoadInfo->GetClientInfo();
2216 if (clientInfo.isSome() && clientInfo->Type() != dom::ClientType::Window) {
2217 nsCOMPtr<nsIPolicyContainer> policyContainer =
2218 mLoadInfo->GetPolicyContainer();
2219 if (policyContainer) {
2220 parentAddressSpace =
2221 PolicyContainer::Cast(policyContainer)->GetIPAddressSpace();
2222 }
2223 } else if (!bc) {
2224 parentAddressSpace = mLoadInfo->GetParentIpAddressSpace();
2225 } else {
2226 parentAddressSpace = bc->GetCurrentIPAddressSpace();
2227 }
2228
2229 // Check if this is a top-level navigation load and grant LNA permissions
2230 // to skip local network access verification for navigational loads
2231 if (mLoadInfo && StaticPrefs::network_lna_allow_top_level_navigation()) {
2232 ExtContentPolicyType contentPolicyType =
2233 mLoadInfo->GetExternalContentPolicyType();
2234 if (contentPolicyType == ExtContentPolicy::TYPE_DOCUMENT) {
2235 // Grant permissions for top-level navigation loads
2236 mLNAPermission.mLocalHostPermission = LNAPermission::Granted;
2237 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
2238 }
2239 }
2240
2241 // Grant LNA permissions for captive portal tabs to allow them to access
2242 // local network resources without prompting the user
2243 if (bc && bc->GetIsCaptivePortalTab()) {
2244 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
2245 }
2246
2247 rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead, mUploadStream,
2248 mReqContentLength, GetCurrentSerialEventTarget(),
2249 callbacks, this, mBrowserId, category,
2250 mRequestContext, mClassOfService, mInitialRwin,
2251 LoadResponseTimeoutEnabled(), mChannelId, nullptr,
2252 parentAddressSpace, mLNAPermission);
2253 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2254 mTransaction = nullptr;
2255 return rv;
2256 }
2257
2258 return rv;
2259}
2260
2261HttpTrafficCategory nsHttpChannel::CreateTrafficCategory() {
2262 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", 2263
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 2263); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2263 !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", 2263
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 2263); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2264
2265 if (!StaticPrefs::network_traffic_analyzer_enabled()) {
2266 return HttpTrafficCategory::eInvalid;
2267 }
2268
2269 HttpTrafficAnalyzer::ClassOfService cos;
2270 {
2271 if ((mClassOfService.Flags() & nsIClassOfService::Leader) &&
2272 mLoadInfo->GetExternalContentPolicyType() ==
2273 ExtContentPolicy::TYPE_SCRIPT) {
2274 cos = HttpTrafficAnalyzer::ClassOfService::eLeader;
2275 } else if (mLoadFlags & nsIRequest::LOAD_BACKGROUND) {
2276 cos = HttpTrafficAnalyzer::ClassOfService::eBackground;
2277 } else {
2278 cos = HttpTrafficAnalyzer::ClassOfService::eOther;
2279 }
2280 }
2281
2282 bool isThirdParty = AntiTrackingUtils::IsThirdPartyChannel(this);
2283
2284 HttpTrafficAnalyzer::TrackingClassification tc;
2285 {
2286 uint32_t flags = isThirdParty ? mThirdPartyClassificationFlags
2287 : mFirstPartyClassificationFlags;
2288
2289 using CF = nsIClassifiedChannel::ClassificationFlags;
2290 using TC = HttpTrafficAnalyzer::TrackingClassification;
2291
2292 if (flags & CF::CLASSIFIED_TRACKING_CONTENT) {
2293 tc = TC::eContent;
2294 } else if (flags & CF::CLASSIFIED_FINGERPRINTING_CONTENT) {
2295 tc = TC::eFingerprinting;
2296 } else if (flags & CF::CLASSIFIED_ANY_BASIC_TRACKING) {
2297 tc = TC::eBasic;
2298 } else {
2299 tc = TC::eNone;
2300 }
2301 }
2302
2303 bool isSystemPrincipal =
2304 mLoadInfo->GetLoadingPrincipal() &&
2305 mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal();
2306 return HttpTrafficAnalyzer::CreateTrafficCategory(
2307 NS_UsePrivateBrowsing(this), isSystemPrincipal, isThirdParty, cos, tc);
2308}
2309
2310void nsHttpChannel::SetCachedContentType() {
2311 if (!mResponseHead) {
2312 return;
2313 }
2314
2315 nsAutoCString contentTypeStr;
2316 mResponseHead->ContentType(contentTypeStr);
2317
2318 uint8_t contentType = nsICacheEntry::CONTENT_TYPE_OTHER;
2319 if (nsContentUtils::IsJavascriptMIMEType(
2320 NS_ConvertUTF8toUTF16(contentTypeStr))) {
2321 contentType = nsICacheEntry::CONTENT_TYPE_JAVASCRIPT;
2322 } else if (StringBeginsWith(contentTypeStr, "text/css"_ns) ||
2323 (mLoadInfo->GetExternalContentPolicyType() ==
2324 ExtContentPolicy::TYPE_STYLESHEET)) {
2325 contentType = nsICacheEntry::CONTENT_TYPE_STYLESHEET;
2326 } else if (StringBeginsWith(contentTypeStr, "application/wasm"_ns)) {
2327 contentType = nsICacheEntry::CONTENT_TYPE_WASM;
2328 } else if (StringBeginsWith(contentTypeStr, "image/"_ns)) {
2329 contentType = nsICacheEntry::CONTENT_TYPE_IMAGE;
2330 } else if (StringBeginsWith(contentTypeStr, "video/"_ns)) {
2331 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
2332 } else if (StringBeginsWith(contentTypeStr, "audio/"_ns)) {
2333 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
2334 }
2335
2336 mCacheEntry->SetContentType(contentType);
2337}
2338
2339static bool ShouldSniffMisconfiguredType(nsHttpResponseHead* aResponseHead,
2340 nsILoadInfo* aLoadInfo) {
2341 if (!StaticPrefs::network_mimesniff_sniff_misconfigured_types()) {
2342 return false;
2343 }
2344
2345 // Only sniff document navigations, not subresources.
2346 // https://mimesniff.spec.whatwg.org/#sniffing-a-mislabeled-binary-resource
2347 auto type = aLoadInfo->GetExternalContentPolicyType();
2348 if (type != ExtContentPolicyType::TYPE_DOCUMENT &&
2349 type != ExtContentPolicyType::TYPE_SUBDOCUMENT) {
2350 return false;
2351 }
2352
2353 // Responses marked as attachments are already going to be downloaded
2354 // regardless of their content type, so there is no need to sniff them.
2355 nsAutoCString contentDisposition;
2356 if (NS_SUCCEEDED(aResponseHead->GetHeader(nsHttp::Content_Disposition,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Content_Disposition, contentDisposition))),
1)))
2357 contentDisposition))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Content_Disposition, contentDisposition))),
1)))
&&
2358 !contentDisposition.IsEmpty() &&
2359 NS_GetContentDispositionFromHeader(contentDisposition) ==
2360 nsIChannel::DISPOSITION_ATTACHMENT) {
2361 return false;
2362 }
2363
2364 nsAutoCString contentTypeOptionsHeader;
2365 if (aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader) &&
2366 contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) {
2367 return false;
2368 }
2369
2370 nsAutoCString contentType;
2371 aResponseHead->ContentType(contentType);
2372
2373 if (contentType.EqualsLiteral("text/plain")) {
2374 return true;
2375 }
2376
2377 if (contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type") ||
2378 contentType.IsEmpty()) {
2379 return true;
2380 }
2381
2382 return false;
2383}
2384
2385nsresult nsHttpChannel::CallOnStartRequest() {
2386 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)
;
2387
2388 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"
, 2390); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2390
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2389 "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"
, 2390); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2390
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2390 "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"
, 2390); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2390
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
2391
2392 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"
, 2394); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2394); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
2393 "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"
, 2394); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2394); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
2394 "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"
, 2394); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2394); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
2395
2396 mEarlyHintObserver = nullptr;
2397
2398 if (StaticPrefs::network_http_network_error_logging_enabled() &&
2399 mResponseHead && mResponseHead->HasHeader(nsHttp::NEL) &&
2400 LoadUsedNetwork()) {
2401 // If the policy gets cleared, but this response is still in the cache,
2402 // we probably don't want to reinstall the policy when the entry is
2403 // reloaded. That means it's important to only call RegisterPolicy when
2404 // LoadUsedNetwork() is true.
2405 if (nsCOMPtr<nsINetworkErrorLogging> nel =
2406 components::NetworkErrorLogging::Service()) {
2407 nel->RegisterPolicy(this);
2408 }
2409 }
2410
2411 if (LoadOnStartRequestCalled()) {
2412 // This can only happen when a range request loading rest of the data
2413 // after interrupted concurrent cache read asynchronously failed, e.g.
2414 // the response range bytes are not as expected or this channel has
2415 // been externally canceled.
2416 //
2417 // It's legal to bypass CallOnStartRequest for that case since we've
2418 // already called OnStartRequest on our listener and also added all
2419 // content converters before.
2420 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", 2420
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { MOZ_CrashSequence(__null, 2420); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2421 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)
;
2422 return mStatus;
2423 }
2424
2425 // Ensure mListener->OnStartRequest will be invoked before exiting
2426 // this function.
2427 auto onStartGuard = MakeScopeExit([&] {
2428 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)
2429 (" 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)
2430 "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)
2431 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)
;
2432 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", 2432
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 2432); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2433
2434 if (mListener) {
2435 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
2436 StoreOnStartRequestCalled(true);
2437 deleteProtector->OnStartRequest(this);
2438 }
2439 StoreOnStartRequestCalled(true);
2440 });
2441
2442 nsresult rv = ValidateMIMEType();
2443 // Since ODA and OnStopRequest could be sent from socket process directly, we
2444 // need to update the channel status before calling mListener->OnStartRequest.
2445 // This is the only way to let child process discard the already received ODA
2446 // messages.
2447 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2448 mStatus = rv;
2449 return mStatus;
2450 }
2451
2452 // EnsureOpaqueResponseIsAllowed and EnsureOpauqeResponseIsAllowedAfterSniff
2453 // are the checks for Opaque Response Blocking to ensure that we block as many
2454 // cross-origin responses with CORS headers as possible that are not either
2455 // Javascript or media to avoid leaking their contents through side channels.
2456 OpaqueResponse opaqueResponse =
2457 PerformOpaqueResponseSafelistCheckBeforeSniff();
2458 if (opaqueResponse == OpaqueResponse::Block) {
2459 SetChannelBlockedByOpaqueResponse();
2460 CancelWithReason(NS_ERROR_DOM_NETWORK_ERR,
2461 "OpaqueResponseBlocker::BlockResponse"_ns);
2462 return NS_BINDING_ABORTED;
2463 }
2464
2465 // We must ensure that any dcb/dcz content is decompressed in the parent
2466 // process, and removed from the Content-Encoding before it's sent down
2467 // to the content process. In most (all?) cases, this should have occurred
2468 // before this.
2469 if (mResponseHead && XRE_IsParentProcess() && !LoadHasAppliedConversion()) {
2470 nsAutoCString contentEncoding;
2471 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
2472 // Note: doesn't handle multiple compressors: "dcb, gzip" or
2473 // "gzip, dcb" (etc)
2474 if (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
2475 contentEncoding.LowerCaseEqualsLiteral("dcz")) {
2476 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)
2477 ("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)
2478 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)
;
2479 nsCOMPtr<nsIStreamListener> listener;
2480 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"
, 2480); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "LoadHasAppliedConversion() == false"
")"); do { MOZ_CrashSequence(__null, 2480); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2481 // Insist we install a converter. This should never be the case, but
2482 // if somehow it is, we need a converter; content can't be allowed
2483 // to see dcb/dcz since it can't convert them
2484 StoreHasAppliedConversion(false);
2485 // IMPORTANT: Must use DoApplyContentConversionsInternal with
2486 // aRemoveEncodings=true to clear Content-Encoding header. Otherwise,
2487 // decompressed data will be cached with dcb/dcz in metadata, causing
2488 // corruption on cache reads.
2489 rv = DoApplyContentConversionsInternal(
2490 mListener, getter_AddRefs(listener), true, nullptr);
2491 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2492 return rv;
2493 }
2494 if (listener) {
2495 MOZ_ASSERT(!LoadDataSentToChildProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadDataSentToChildProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadDataSentToChildProcess(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadDataSentToChildProcess()" " (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadDataSentToChildProcess()"
") (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")"); do { MOZ_CrashSequence(__null, 2498); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2496 "DataSentToChildProcess being true means ODAs are sent to "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadDataSentToChildProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadDataSentToChildProcess(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadDataSentToChildProcess()" " (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadDataSentToChildProcess()"
") (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")"); do { MOZ_CrashSequence(__null, 2498); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2497 "the child process directly. We MUST NOT apply content "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadDataSentToChildProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadDataSentToChildProcess(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadDataSentToChildProcess()" " (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadDataSentToChildProcess()"
") (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")"); do { MOZ_CrashSequence(__null, 2498); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2498 "converter in this case.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadDataSentToChildProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadDataSentToChildProcess(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadDataSentToChildProcess()" " (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2498); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadDataSentToChildProcess()"
") (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")"); do { MOZ_CrashSequence(__null, 2498); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2499 mListener = listener;
2500 mCompressListener = listener;
2501
2502 StoreHasAppliedConversion(true);
2503 } else {
2504 // Failed to install decompressor for dcb/dcz - this is a fatal error
2505 // as content cannot handle these encodings
2506 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)
2507 ("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)
2508 "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)
2509 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)
;
2510 return NS_ERROR_INVALID_CONTENT_ENCODING;
2511 }
2512 }
2513 }
2514
2515 // Allow consumers to override our content type
2516 if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) {
2517 // NOTE: We can have both a txn pump and a cache pump when the cache
2518 // content is partial. In that case, we need to read from the cache,
2519 // because that's the one that has the initial contents. If that fails
2520 // then give the transaction pump a shot.
2521
2522 nsIChannel* thisChannel = static_cast<nsIChannel*>(this);
2523
2524 bool typeSniffersCalled = false;
2525 if (mCachePump) {
2526 typeSniffersCalled =
2527 NS_SUCCEEDED(mCachePump->PeekStream(CallTypeSniffers, thisChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCachePump->PeekStream
(CallTypeSniffers, thisChannel))), 1)))
;
2528 }
2529
2530 if (!typeSniffersCalled && mTransactionPump) {
2531 RefPtr<nsInputStreamPump> pump = do_QueryObject(mTransactionPump);
2532 if (pump) {
2533 pump->PeekStream(CallTypeSniffers, thisChannel);
2534 } else {
2535 MOZ_ASSERT(nsIOService::UseSocketProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(nsIOService::UseSocketProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(nsIOService::UseSocketProcess
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("nsIOService::UseSocketProcess()", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsIOService::UseSocketProcess()"
")"); do { MOZ_CrashSequence(__null, 2535); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2536 RefPtr<HttpTransactionParent> trans = do_QueryObject(mTransactionPump);
2537 MOZ_ASSERT(trans)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(trans)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(trans))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("trans", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "trans" ")")
; do { MOZ_CrashSequence(__null, 2537); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2538 trans->SetSniffedTypeToChannel(CallTypeSniffers, thisChannel);
2539 }
2540 }
2541 }
2542
2543 // Note that the code below should be synced with the code in
2544 // HttpTransactionChild::CanSendODAToContentProcessDirectly(). We MUST make
2545 // sure HttpTransactionChild::CanSendODAToContentProcessDirectly() returns
2546 // false when a stream converter is applied.
2547 bool unknownDecoderStarted = false;
2548 bool shouldSniff = false;
2549 if (mResponseHead) {
2550 if (!mResponseHead->HasContentType()) {
2551 shouldSniff = true;
2552 } else {
2553 shouldSniff =
2554 ShouldSniffMisconfiguredType(mResponseHead.get(), mLoadInfo);
2555 }
2556 }
2557 if (shouldSniff) {
2558 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"
, 2558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo"
") (" "Should have connection info here" ")"); do { MOZ_CrashSequence
(__null, 2558); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2559 if (!mContentTypeHint.IsEmpty()) {
2560 mResponseHead->SetContentType(mContentTypeHint);
2561 } else if (mResponseHead->Version() == HttpVersion::v0_9 &&
2562 mConnectionInfo->OriginPort() !=
2563 mConnectionInfo->DefaultPort()) {
2564 mResponseHead->SetContentType(nsLiteralCString(TEXT_PLAIN"text/plain"));
2565 } else if (!mLoadInfo->GetSkipContentSniffing() ||
2566 opaqueResponse == OpaqueResponse::Sniff) {
2567 // Uh-oh. We had better find out what type we are!
2568 mListener = new nsUnknownDecoder(mListener);
2569 unknownDecoderStarted = true;
2570 }
2571 }
2572
2573 // If unknownDecoder is not going to be launched, call
2574 // EnsureOpaqueResponseIsAllowedAfterSniff immediately.
2575 if (!unknownDecoderStarted) {
2576 if (opaqueResponse == OpaqueResponse::SniffCompressed) {
2577 mListener = new nsCompressedAudioVideoImageDetector(
2578 mListener, &HttpBaseChannel::CallTypeSniffers);
2579 } else if (opaqueResponse == OpaqueResponse::Sniff) {
2580 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"
, 2580); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mORB"
")"); do { MOZ_CrashSequence(__null, 2580); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2581 RefPtr<OpaqueResponseBlocker> orb(mORB);
2582 nsresult rv = orb->EnsureOpaqueResponseIsAllowedAfterSniff(this);
2583
2584 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2585 return rv;
2586 }
2587 }
2588 }
2589
2590 // If the content is multipart/x-mixed-replace, we'll insert a MIME decoder
2591 // in the pipeline to handle the content and pass it along to our
2592 // original listener. nsUnknownDecoder doesn't support detecting this type,
2593 // so we only need to insert this using the response header's mime type.
2594 //
2595 // We only do this for unwrapped document loads, since we might want to send
2596 // parts to the external protocol handler without leaving the parent process.
2597 bool mustRunStreamFilterInParent = false;
2598 nsCOMPtr<nsIParentChannel> parentChannel;
2599 NS_QueryNotificationCallbacks(this, parentChannel);
2600 RefPtr<DocumentLoadListener> docListener = do_QueryObject(parentChannel);
2601 if (mResponseHead && docListener && docListener->GetChannel() == this) {
2602 nsAutoCString contentType;
2603 mResponseHead->ContentType(contentType);
2604
2605 if (contentType.Equals("multipart/x-mixed-replace"_ns)) {
2606 nsCOMPtr<nsIStreamConverterService> convServ(
2607 mozilla::components::StreamConverter::Service(&rv));
2608 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2609 nsCOMPtr<nsIStreamListener> toListener(mListener);
2610 nsCOMPtr<nsIStreamListener> fromListener;
2611
2612 rv = convServ->AsyncConvertData("multipart/x-mixed-replace", "*/*",
2613 toListener, nullptr,
2614 getter_AddRefs(fromListener));
2615 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2616 mListener = fromListener;
2617 mustRunStreamFilterInParent = true;
2618 }
2619 }
2620 }
2621 }
2622
2623 // If we installed a multipart converter, then we need to add StreamFilter
2624 // object before it, so that extensions see the un-parsed original stream.
2625 // We may want to add an option for extensions to opt-in to proper multipart
2626 // handling.
2627 // If not, then pass the StreamFilter promise on to DocumentLoadListener,
2628 // where it'll be added in the content process.
2629 for (StreamFilterRequest& request : mStreamFilterRequests) {
2630 if (mustRunStreamFilterInParent) {
2631 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
2632 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
2633 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
2634 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2635 request.mPromise->Reject(false, __func__);
2636 } else {
2637 extensions::StreamFilterParent::Attach(this, std::move(parent));
2638 request.mPromise->Resolve(std::move(child), __func__);
2639 }
2640 } else {
2641 if (docListener) {
2642 docListener->AttachStreamFilter()->ChainTo(request.mPromise.forget(),
2643 __func__);
2644 } else {
2645 request.mPromise->Reject(false, __func__);
2646 }
2647 }
2648 request.mPromise = nullptr;
2649 }
2650 mStreamFilterRequests.Clear();
2651 StoreTracingEnabled(false);
2652
2653 if (mResponseHead && !mResponseHead->HasContentCharset()) {
2654 mResponseHead->SetContentCharset(mContentCharsetHint);
2655 }
2656
2657 if (mCacheEntry && LoadCacheEntryIsWriteOnly()) {
2658 SetCachedContentType();
2659 }
2660
2661 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)
2662 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)
;
2663
2664 // About to call OnStartRequest, dismiss the guard object.
2665 onStartGuard.release();
2666
2667 if (mListener) {
2668 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"
, 2669); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { MOZ_CrashSequence
(__null, 2669); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2669 "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"
, 2669); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { MOZ_CrashSequence
(__null, 2669); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2670 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
2671 StoreOnStartRequestCalled(true);
2672 rv = deleteProtector->OnStartRequest(this);
2673 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2674 } else {
2675 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"
, 2675)
;
2676 StoreOnStartRequestCalled(true);
2677 }
2678
2679 // Install stream converter if required.
2680 // Normally, we expect the listener to disable content conversion during
2681 // OnStartRequest if it wants to handle it itself (which is common case with
2682 // HttpChannelParent, disabling so that it can be done in the content
2683 // process). If we've installed an nsUnknownDecoder, then we won't yet have
2684 // called OnStartRequest on the final listener (that happens after we send
2685 // OnDataAvailable to the nsUnknownDecoder), so it can't yet have disabled
2686 // content conversion.
2687 // In that case, assume that the listener will disable content conversion,
2688 // unless it's specifically told us that it won't.
2689 if (!unknownDecoderStarted || LoadListenerRequiresContentConversion()) {
2690 nsCOMPtr<nsIStreamListener> listener;
2691 rv =
2692 DoApplyContentConversions(mListener, getter_AddRefs(listener), nullptr);
2693 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2694 return rv;
2695 }
2696 if (listener) {
2697 MOZ_ASSERT(!LoadDataSentToChildProcess(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadDataSentToChildProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadDataSentToChildProcess(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadDataSentToChildProcess()" " (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2700); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadDataSentToChildProcess()"
") (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")"); do { MOZ_CrashSequence(__null, 2700); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2698 "DataSentToChildProcess being true means ODAs are sent to "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadDataSentToChildProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadDataSentToChildProcess(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadDataSentToChildProcess()" " (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2700); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadDataSentToChildProcess()"
") (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")"); do { MOZ_CrashSequence(__null, 2700); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2699 "the child process directly. We MUST NOT apply content "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadDataSentToChildProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadDataSentToChildProcess(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadDataSentToChildProcess()" " (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2700); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadDataSentToChildProcess()"
") (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")"); do { MOZ_CrashSequence(__null, 2700); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2700 "converter in this case.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!LoadDataSentToChildProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!LoadDataSentToChildProcess(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!LoadDataSentToChildProcess()" " (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 2700); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadDataSentToChildProcess()"
") (" "DataSentToChildProcess being true means ODAs are sent to "
"the child process directly. We MUST NOT apply content " "converter in this case."
")"); do { MOZ_CrashSequence(__null, 2700); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2701 mListener = listener;
2702 mCompressListener = std::move(listener);
2703
2704 StoreHasAppliedConversion(true);
2705 }
2706 }
2707
2708 // if this channel is for a download, close off access to the cache.
2709 if (mCacheEntry && LoadChannelIsForDownload()) {
2710 mCacheEntry->AsyncDoom(nullptr);
2711
2712 // We must keep the cache entry in case of partial request.
2713 // Concurrent access is the same, we need the entry in
2714 // OnStopRequest.
2715 if (!LoadCachedContentIsPartial() && !LoadConcurrentCacheAccess()) {
2716 CloseCacheEntry(false);
2717 }
2718 }
2719
2720 return NS_OK;
2721}
2722
2723NS_IMETHODIMPnsresult nsHttpChannel::GetHttpProxyConnectResponseCode(
2724 int32_t* aResponseCode) {
2725 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"
, 2725); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2726 if (mProxyConnectResponseHead) {
2727 *aResponseCode = mProxyConnectResponseHead->Head().Status();
2728 } else if (mConnectionInfo && mConnectionInfo->UsingConnect()) {
2729 *aResponseCode = 0;
2730 } else {
2731 *aResponseCode = -1;
2732 }
2733 return NS_OK;
2734}
2735
2736NS_IMETHODIMPnsresult nsHttpChannel::GetHttpProxyResponseHeader(
2737 const nsACString& aHeader, nsACString& aValue) {
2738 if (mProxyConnectResponseHead) {
2739 return mProxyConnectResponseHead->Head().GetHeader(
2740 nsHttp::ResolveAtom(aHeader), aValue);
2741 }
2742 return NS_ERROR_NOT_AVAILABLE;
2743}
2744
2745nsresult nsHttpChannel::ProcessFailedProxyConnect(uint32_t httpStatus) {
2746 // Failure to set up a proxy tunnel via CONNECT means one of the following:
2747 // 1) Proxy wants authorization, or forbids.
2748 // 2) DNS at proxy couldn't resolve target URL.
2749 // 3) Proxy connection to target failed or timed out.
2750 // 4) Eve intercepted our CONNECT, and is replying with malicious HTML.
2751 //
2752 // Our current architecture would parse the proxy's response content with
2753 // the permission of the target URL. Given #4, we must avoid rendering the
2754 // body of the reply, and instead give the user a (hopefully helpful)
2755 // boilerplate error page, based on just the HTTP status of the reply.
2756
2757 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"
, 2758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ MOZ_CrashSequence(__null, 2758); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2758 "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"
, 2758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ MOZ_CrashSequence(__null, 2758); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2759 nsresult rv = HttpProxyResponseToErrorCode(httpStatus);
2760 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)
2761 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)
;
2762
2763 // Make sure the connection is thrown away as it can be in a bad state
2764 // and the proxy may just hang on the next request.
2765 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"
, 2765); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { MOZ_CrashSequence(__null, 2765); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2766 mTransaction->DontReuseConnection();
2767
2768 Cancel(rv);
2769 {
2770 nsresult rv = CallOnStartRequest();
2771 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2772 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)
2773 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)
;
2774 }
2775 }
2776 return rv;
2777}
2778
2779static void GetSTSConsoleErrorTag(uint32_t failureResult,
2780 nsAString& consoleErrorTag) {
2781 switch (failureResult) {
2782 case nsISiteSecurityService::ERROR_COULD_NOT_PARSE_HEADER:
2783 consoleErrorTag = u"STSCouldNotParseHeader"_ns;
2784 break;
2785 case nsISiteSecurityService::ERROR_NO_MAX_AGE:
2786 consoleErrorTag = u"STSNoMaxAge"_ns;
2787 break;
2788 case nsISiteSecurityService::ERROR_MULTIPLE_MAX_AGES:
2789 consoleErrorTag = u"STSMultipleMaxAges"_ns;
2790 break;
2791 case nsISiteSecurityService::ERROR_INVALID_MAX_AGE:
2792 consoleErrorTag = u"STSInvalidMaxAge"_ns;
2793 break;
2794 case nsISiteSecurityService::ERROR_MULTIPLE_INCLUDE_SUBDOMAINS:
2795 consoleErrorTag = u"STSMultipleIncludeSubdomains"_ns;
2796 break;
2797 case nsISiteSecurityService::ERROR_INVALID_INCLUDE_SUBDOMAINS:
2798 consoleErrorTag = u"STSInvalidIncludeSubdomains"_ns;
2799 break;
2800 case nsISiteSecurityService::ERROR_COULD_NOT_SAVE_STATE:
2801 consoleErrorTag = u"STSCouldNotSaveState"_ns;
2802 break;
2803 default:
2804 consoleErrorTag = u"STSUnknownError"_ns;
2805 break;
2806 }
2807}
2808
2809/**
2810 * Process an HTTP Strict Transport Security (HSTS) header.
2811 */
2812nsresult nsHttpChannel::ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo) {
2813 nsHttpAtom atom(nsHttp::ResolveAtom("Strict-Transport-Security"_ns));
2814
2815 nsAutoCString securityHeader;
2816 nsresult rv = mResponseHead->GetHeader(atom, securityHeader);
2817 if (rv == NS_ERROR_NOT_AVAILABLE) {
2818 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)
;
2819 return NS_OK;
2820 }
2821 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"
, 2821)
) {
2822 return rv;
2823 }
2824
2825 if (!aSecInfo) {
2826 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)
;
2827 return NS_ERROR_INVALID_ARG;
2828 }
2829 nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
2830 rv = aSecInfo->GetOverridableErrorCategory(&overridableErrorCategory);
2831 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"
, 2831)
) {
2832 return rv;
2833 }
2834 if (overridableErrorCategory !=
2835 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
2836 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)
2837 ("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)
2838 "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)
;
2839 return NS_ERROR_FAILURE;
2840 }
2841
2842 nsISiteSecurityService* sss = gHttpHandler->GetSSService();
2843 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"
, 2843); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2844
2845 OriginAttributes originAttributes;
2846 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2847
)
2847 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2847
)
) {
2848 return NS_ERROR_FAILURE;
2849 }
2850
2851 uint32_t failureResult;
2852 rv = sss->ProcessHeader(mURI, securityHeader, originAttributes, nullptr,
2853 nullptr, &failureResult);
2854 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2855 nsAutoString consoleErrorCategory(u"Invalid HSTS Headers"_ns);
2856 nsAutoString consoleErrorTag;
2857 GetSTSConsoleErrorTag(failureResult, consoleErrorTag);
2858 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2859 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)
2860 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)
;
2861 }
2862 return NS_OK;
2863}
2864
2865// https://github.com/rozbb/waict-integrity-draft/
2866nsresult nsHttpChannel::ProcessWAICTHeader() {
2867#ifdef NIGHTLY_BUILD1
2868 if (!StaticPrefs::security_waict_downgrade_protection_enable()) {
2869 return NS_OK;
2870 }
2871
2872 // The WAICT header is only relevant for document loads.
2873 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
2874 if (type != ExtContentPolicy::TYPE_DOCUMENT &&
2875 type != ExtContentPolicy::TYPE_SUBDOCUMENT) {
2876 return NS_OK;
2877 }
2878
2879 nsISiteIntegrityService* integrityService =
2880 gHttpHandler->GetSiteIntegrityService();
2881 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"
, 2881); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2882
2883 // Unlike HSTS, WAICT is supported for HTTP as well, so we need to use the
2884 // correct helper.
2885 OriginAttributes originAttributes;
2886 if (mURI->SchemeIs("https")) {
2887 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2888
)
2888 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2888
)
) {
2889 return NS_ERROR_FAILURE;
2890 }
2891 } else {
2892 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2893
)
2893 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2893
)
) {
2894 return NS_ERROR_FAILURE;
2895 }
2896 }
2897
2898 nsAutoCString headerValue;
2899 nsresult rv =
2900 mResponseHead->GetHeader(nsHttp::Integrity_Policy_WAICT, headerValue);
2901 if (rv == NS_ERROR_NOT_AVAILABLE || headerValue.IsEmpty()) {
2902 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)
2903 ("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)
2904 "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)
;
2905
2906 bool isProtected = false;
2907 rv = integrityService->IsProtectedURI(mURI, originAttributes, &isProtected);
2908 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2909 return rv;
2910 }
2911
2912 if (isProtected) {
2913 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)
2914 ("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)
2915 "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)
;
2916 Cancel(NS_ERROR_CORRUPTED_CONTENT);
2917 DoNotifyListener();
2918 return NS_ERROR_CORRUPTED_CONTENT;
2919 }
2920
2921 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)
;
2922 return NS_OK;
2923 }
2924 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"
, 2924)
) {
2925 return rv;
2926 }
2927#endif
2928
2929 return NS_OK;
2930}
2931
2932/**
2933 * Decide whether or not to remember Strict-Transport-Security, and whether
2934 * or not to enforce channel integrity.
2935 *
2936 * @return NS_ERROR_FAILURE if there's security information missing even though
2937 * it's an HTTPS connection.
2938 */
2939nsresult nsHttpChannel::ProcessSecurityHeaders() {
2940 // If this channel is not loading securely, STS or PKP doesn't do anything.
2941 // In the case of HSTS, the upgrade to HTTPS takes place earlier in the
2942 // channel load process.
2943 if (!mURI->SchemeIs("https")) {
2944 return NS_OK;
2945 }
2946
2947 if (IsBrowsingContextDiscarded()) {
2948 return NS_OK;
2949 }
2950
2951 nsAutoCString asciiHost;
2952 nsresult rv = mURI->GetAsciiHost(asciiHost);
2953 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"
, 2953); return NS_OK; } } while (false)
;
2954
2955 // If the channel is not a hostname, but rather an IP, do not process STS
2956 // or PKP headers
2957 if (HostIsIPLiteral(asciiHost)) {
2958 return NS_OK;
2959 }
2960
2961 // mSecurityInfo may not always be present, and if it's not then it is okay
2962 // to just disregard any security headers since we know nothing about the
2963 // security of the connection.
2964 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"
, 2964); return NS_OK; } } while (false)
;
2965
2966 // Only process HSTS headers for first-party loads. This prevents a
2967 // proliferation of useless HSTS state for partitioned third parties.
2968 if (!mLoadInfo->GetIsThirdPartyContextToTopWindow()) {
2969 rv = ProcessHSTSHeader(mSecurityInfo);
2970 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"
, 2970); return rv; } } while (false)
;
2971 }
2972
2973 return NS_OK;
2974}
2975
2976bool nsHttpChannel::IsHTTPS() { return mURI->SchemeIs("https"); }
2977
2978void nsHttpChannel::ProcessSSLInformation() {
2979 // If this is HTTPS, record any use of RSA so that Key Exchange Algorithm
2980 // can be whitelisted for TLS False Start in future sessions. We could
2981 // do the same for DH but its rarity doesn't justify the lookup.
2982
2983 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) || !mSecurityInfo || !IsHTTPS() ||
2984 mPrivateBrowsing) {
2985 return;
2986 }
2987
2988 if (!mSecurityInfo) {
2989 return;
2990 }
2991
2992 uint32_t state;
2993 if (NS_SUCCEEDED(mSecurityInfo->GetSecurityState(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mSecurityInfo->
GetSecurityState(&state))), 1)))
&&
2994 (state & nsIWebProgressListener::STATE_IS_BROKEN)) {
2995 // Send weak crypto warnings to the web console
2996 if (state & nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
2997 nsString consoleErrorTag = u"WeakCipherSuiteWarning"_ns;
2998 nsString consoleErrorCategory = u"SSL"_ns;
2999 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
3000 }
3001 }
3002
3003 uint16_t tlsVersion;
3004 nsresult rv = mSecurityInfo->GetProtocolVersion(&tlsVersion);
3005 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
3006 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_2 &&
3007 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_3) {
3008 nsString consoleErrorTag = u"DeprecatedTLSVersion2"_ns;
3009 nsString consoleErrorCategory = u"TLS"_ns;
3010 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
3011 }
3012}
3013
3014void nsHttpChannel::ProcessAltService(nsHttpConnectionInfo* aTransConnInfo) {
3015 // e.g. Alt-Svc: h2=":443"; ma=60
3016 // e.g. Alt-Svc: h2="otherhost:443"
3017 // Alt-Svc = 1#( alternative *( OWS ";" OWS parameter ) )
3018 // alternative = protocol-id "=" alt-authority
3019 // protocol-id = token ; percent-encoded ALPN protocol identifier
3020 // alt-authority = quoted-string ; containing [ uri-host ] ":" port
3021
3022 if (!LoadAllowAltSvc()) { // per channel opt out
3023 return;
3024 }
3025
3026 if (mWebTransportSessionEventListener) {
3027 return;
3028 }
3029
3030 if (!gHttpHandler->AllowAltSvc() || (mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7))) {
3031 return;
3032 }
3033
3034 if (IsBrowsingContextDiscarded()) {
3035 return;
3036 }
3037
3038 nsAutoCString scheme;
3039 mURI->GetScheme(scheme);
3040 bool isHttp = scheme.EqualsLiteral("http");
3041 if (!isHttp && !scheme.EqualsLiteral("https")) {
3042 return;
3043 }
3044
3045 nsAutoCString altSvc;
3046 (void)mResponseHead->GetHeader(nsHttp::Alternate_Service, altSvc);
3047 if (altSvc.IsEmpty()) {
3048 return;
3049 }
3050
3051 if (!nsHttp::IsReasonableHeaderValue(altSvc)) {
3052 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)
;
3053 return;
3054 }
3055
3056 nsAutoCString originHost;
3057 int32_t originPort = 80;
3058 mURI->GetPort(&originPort);
3059 if (NS_FAILED(mURI->GetAsciiHost(originHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(mURI->GetAsciiHost
(originHost))), 0)))
) {
3060 return;
3061 }
3062
3063 nsCOMPtr<nsIInterfaceRequestor> callbacks;
3064 nsCOMPtr<nsProxyInfo> proxyInfo;
3065 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
3066 getter_AddRefs(callbacks));
3067
3068 if (mProxyInfo) {
3069 proxyInfo = do_QueryInterface(mProxyInfo);
3070 }
3071
3072 OriginAttributes originAttributes;
3073 // Regular principal in case we have a proxy.
3074 if (proxyInfo &&
3075 !StaticPrefs::privacy_partition_network_state_connection_with_proxy()) {
3076 StoragePrincipalHelper::GetOriginAttributes(
3077 this, originAttributes, StoragePrincipalHelper::eRegularPrincipal);
3078 } else {
3079 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
3080 this, originAttributes);
3081 }
3082
3083 AltSvcMapping::ProcessHeader(altSvc, scheme, originHost, originPort,
3084 mUsername, mPrivateBrowsing, callbacks,
3085 proxyInfo, mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7),
3086 originAttributes, aTransConnInfo);
3087}
3088
3089nsresult nsHttpChannel::ProcessResponse(nsHttpConnectionInfo* aConnInfo) {
3090 uint32_t httpStatus = mResponseHead->Status();
3091
3092 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)
3093 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)
;
3094
3095 // Gather data on whether the transaction and page (if this is
3096 // the initial page load) is being loaded with SSL.
3097 glean::http::transaction_is_ssl
3098 .EnumGet(static_cast<glean::http::TransactionIsSslLabel>(
3099 mConnectionInfo->EndToEndSSL()))
3100 .Add();
3101 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
3102 glean::http::pageload_is_ssl
3103 .EnumGet(static_cast<glean::http::PageloadIsSslLabel>(
3104 mConnectionInfo->EndToEndSSL()))
3105 .Add();
3106 }
3107
3108 if (Telemetry::CanRecordPrereleaseData()) {
3109 // Gather data on various response status to monitor any increased frequency
3110 // of auth failures due to Bug 1896350
3111 switch (httpStatus) {
3112 case 200:
3113 mozilla::glean::networking::http_response_status_code.Get("200_ok"_ns)
3114 .Add(1);
3115 break;
3116 case 301:
3117 mozilla::glean::networking::http_response_status_code
3118 .Get("301_moved_permanently"_ns)
3119 .Add(1);
3120 break;
3121 case 302:
3122 mozilla::glean::networking::http_response_status_code
3123 .Get("302_found"_ns)
3124 .Add(1);
3125 break;
3126 case 304:
3127 mozilla::glean::networking::http_response_status_code
3128 .Get("304_not_modified"_ns)
3129 .Add(1);
3130 break;
3131 case 307:
3132 mozilla::glean::networking::http_response_status_code
3133 .Get("307_temporary_redirect"_ns)
3134 .Add(1);
3135 break;
3136 case 308:
3137 mozilla::glean::networking::http_response_status_code
3138 .Get("308_permanent_redirect"_ns)
3139 .Add(1);
3140 break;
3141 case 400:
3142 mozilla::glean::networking::http_response_status_code
3143 .Get("400_bad_request"_ns)
3144 .Add(1);
3145 break;
3146 case 401:
3147 mozilla::glean::networking::http_response_status_code
3148 .Get("401_unauthorized"_ns)
3149 .Add(1);
3150 break;
3151 case 403:
3152 mozilla::glean::networking::http_response_status_code
3153 .Get("403_forbidden"_ns)
3154 .Add(1);
3155 break;
3156 case 404:
3157 mozilla::glean::networking::http_response_status_code
3158 .Get("404_not_found"_ns)
3159 .Add(1);
3160 break;
3161 case 421:
3162 mozilla::glean::networking::http_response_status_code
3163 .Get("421_misdirected_request"_ns)
3164 .Add(1);
3165 break;
3166 case 425:
3167 mozilla::glean::networking::http_response_status_code
3168 .Get("425_too_early"_ns)
3169 .Add(1);
3170 break;
3171 case 429:
3172 mozilla::glean::networking::http_response_status_code
3173 .Get("429_too_many_requests"_ns)
3174 .Add(1);
3175 break;
3176 case 500:
3177 mozilla::glean::networking::http_response_status_code
3178 .Get("other_5xx"_ns)
3179 .Add(1);
3180 break;
3181 default:
3182 if (httpStatus >= 400 && httpStatus < 500) {
3183 mozilla::glean::networking::http_response_status_code
3184 .Get("other_4xx"_ns)
3185 .Add(1);
3186 } else if (httpStatus > 500) {
3187 mozilla::glean::networking::http_response_status_code
3188 .Get("other_5xx"_ns)
3189 .Add(1);
3190 } else {
3191 mozilla::glean::networking::http_response_status_code.Get("other"_ns)
3192 .Add(1);
3193 }
3194 break;
3195 }
3196 }
3197
3198 // We use GetReferringPage because mReferrerInfo may not be set at all(this is
3199 // especially useful in xpcshell tests, where we don't have an actual pageload
3200 // to get a referrer from).
3201 // Only allow 407 (authentication required) to continue
3202 if (mTransaction && mTransaction->ProxyConnectFailed() && httpStatus != 407) {
3203 return ProcessFailedProxyConnect(httpStatus);
3204 }
3205
3206 ProcessSSLInformation();
3207
3208 // notify "http-on-examine-response" observers
3209 gHttpHandler->OnExamineResponse(this);
3210
3211 MaybeSuspendAfterExamineResponse();
3212
3213 return ContinueProcessResponse1(aConnInfo);
3214}
3215
3216void nsHttpChannel::AsyncContinueProcessResponse(
3217 nsHttpConnectionInfo* aConnInfo) {
3218 nsresult rv;
3219 rv = ContinueProcessResponse1(aConnInfo);
3220 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3221 // A synchronous failure here would normally be passed as the return
3222 // value from OnStartRequest, which would in turn cancel the request.
3223 // If we're continuing asynchronously, we need to cancel the request
3224 // ourselves.
3225 (void)Cancel(rv);
3226 }
3227}
3228
3229nsresult nsHttpChannel::ContinueProcessResponse1(
3230 nsHttpConnectionInfo* aConnInfo) {
3231 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"
, 3231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 3231); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3232 nsresult rv = NS_OK;
3233
3234 if (mSuspendCount) {
3235 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)
3236 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)
;
3237 mCallOnResume = [connInfo = RefPtr{aConnInfo}](nsHttpChannel* self) {
3238 self->AsyncContinueProcessResponse(connInfo);
3239 return NS_OK;
3240 };
3241 return NS_OK;
3242 }
3243
3244 // Check if request was cancelled during http-on-examine-response.
3245 if (mCanceled) {
3246 return CallOnStartRequest();
3247 }
3248
3249 uint32_t httpStatus = mResponseHead->Status();
3250
3251 // STS, Cookies and Alt-Service should not be handled on proxy failure.
3252 // If proxy CONNECT response needs to complete, wait to process connection
3253 // for Strict-Transport-Security.
3254 if (!(mTransaction && mTransaction->ProxyConnectFailed()) &&
3255 (httpStatus != 407)) {
3256 // This block parses the cookie header, collects any cookie changes,
3257 // and sends them to the parent actor.
3258 {
3259 RefPtr<CookieObserver> cookieObserver;
3260 RefPtr<HttpChannelParent> httpParent;
3261 CookieServiceParent::CookieProcessingGuard cookieProcessingGuard;
3262
3263 // Skip parent channel interaction for background revalidating channels.
3264 if (!LoadOnStartRequestCalled() && !mStaleRevalidation) {
3265 // This can only happen when a range request is created again in
3266 // nsHttpChannel::ContinueOnStopRequest. If OnStartRequest is already
3267 // called, we shouldn't call SetCookieHeaders.
3268
3269 MaybeInitializeCookieProcessingGuard(this, cookieProcessingGuard,
3270 cookieObserver, httpParent,
3271 httpStatus);
3272 }
3273
3274 CookieVisitor cookieVisitor(mResponseHead.get());
3275 SetCookieHeaders(cookieVisitor.CookieHeaders());
3276
3277 if (cookieObserver) {
3278 nsTArray<CookieChange> cookieChanges;
3279 cookieObserver->StealChanges(cookieChanges);
3280
3281 if (!cookieChanges.IsEmpty()) {
3282 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"
, 3282); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpParent"
")"); do { MOZ_CrashSequence(__null, 3282); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3283 httpParent->SetCookieChanges(std::move(cookieChanges));
3284 }
3285 }
3286 }
3287
3288 rv = ProcessWAICTHeader();
3289 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3290 return rv;
3291 }
3292
3293 // Given a successful connection, process any STS or PKP data that's
3294 // relevant.
3295 if (NS_FAILED(ProcessSecurityHeaders())((bool)(__builtin_expect(!!(NS_FAILED_impl(ProcessSecurityHeaders
())), 0)))
) {
3296 NS_WARNING("ProcessSecurityHeaders failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSecurityHeaders failed, continuing load."
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 3296)
;
3297 }
3298
3299 if ((httpStatus < 500) && (httpStatus != 421)) {
3300 ProcessAltService(aConnInfo);
3301 }
3302 }
3303
3304 if (LoadConcurrentCacheAccess() && LoadCachedContentIsPartial() &&
3305 httpStatus != 206) {
3306 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)
3307 (" 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)
3308 "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)
;
3309 return NS_ERROR_CORRUPTED_CONTENT;
3310 }
3311
3312 if (httpStatus != 401 && httpStatus != 407) {
3313 // reset the authentication's current continuation state because ourvr
3314 // last authentication attempt has been completed successfully
3315 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", 3315
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3315); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3316 rv = mAuthProvider ? mAuthProvider->Disconnect(NS_ERROR_ABORT)
3317 : NS_ERROR_UNEXPECTED;
3318 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3319 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)
;
3320 }
3321 mAuthProvider = nullptr;
3322 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)
;
3323 }
3324
3325 gHttpHandler->OnAfterExamineResponse(this);
3326
3327 if (mResponseHead && mResponseHead->HasHeader(nsHttp::Clear_Site_Data)) {
3328 if (nsCOMPtr<nsIObserverService> obsService =
3329 services::GetObserverService()) {
3330 obsService->NotifyObservers(static_cast<nsIHttpChannel*>(this),
3331 "clear-site-data", nullptr);
3332 }
3333 }
3334
3335 // No process switch needed, continue as normal.
3336 return ContinueProcessResponse2(rv);
3337}
3338
3339nsresult nsHttpChannel::ContinueProcessResponse2(nsresult rv) {
3340 if (mSuspendCount) {
3341 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)
3342 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)
;
3343 mCallOnResume = [rv](nsHttpChannel* self) {
3344 (void)self->ContinueProcessResponse2(rv);
3345 return NS_OK;
3346 };
3347 return NS_OK;
3348 }
3349
3350 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCanceled) {
3351 // The process switch failed, cancel this channel.
3352 Cancel(rv);
3353 return CallOnStartRequest();
3354 }
3355
3356 if (mAPIRedirectTo && !mCanceled) {
3357 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", 3357
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 3357); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3358
3359 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
3360 rv = StartRedirectChannelToURI(
3361 mAPIRedirectTo->first(),
3362 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_TEMPORARY |
3363 nsIChannelEventSink::REDIRECT_TRANSPARENT
3364 : nsIChannelEventSink::REDIRECT_TEMPORARY);
3365 mAPIRedirectTo = Nothing();
3366 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3367 return NS_OK;
3368 }
3369 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
3370 }
3371
3372 // Hack: ContinueProcessResponse3 uses NS_OK to detect successful
3373 // redirects, so we distinguish this codepath (a non-redirect that's
3374 // processing normally) by passing in a bogus error code.
3375 return ContinueProcessResponse3(NS_BINDING_FAILED);
3376}
3377
3378nsresult nsHttpChannel::ContinueProcessResponse3(nsresult rv) {
3379 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)
3380 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)
;
3381
3382 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3383 // redirectTo() has passed through, we don't want to go on with
3384 // this channel. It will now be canceled by the redirect handling
3385 // code that called this function.
3386 return NS_OK;
3387 }
3388
3389 rv = NS_OK;
3390
3391 uint32_t httpStatus = mResponseHead->Status();
3392 bool transactionRestarted = mTransaction->TakeRestartedState();
3393
3394 // handle different server response categories. Note that we handle
3395 // caching or not caching of error pages in
3396 // nsHttpResponseHead::MustValidate; if you change this switch, update that
3397 // one
3398 switch (httpStatus) {
3399 case 200:
3400 case 203:
3401 // Per RFC 2616, 14.35.2, "A server MAY ignore the Range header".
3402 // So if a server does that and sends 200 instead of 206 that we
3403 // expect, notify our caller.
3404 // However, if we wanted to start from the beginning, let it go through
3405 if (LoadResuming() && mStartPos != 0) {
3406 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)
;
3407 Cancel(NS_ERROR_NOT_RESUMABLE);
3408 rv = CallOnStartRequest();
3409 break;
3410 }
3411 // these can normally be cached
3412 rv = ProcessNormal();
3413 MaybeInvalidateCacheEntryForSubsequentGet();
3414 break;
3415 case 206:
3416 if (LoadCachedContentIsPartial()) { // an internal byte range request...
3417 auto func = [](auto* self, nsresult aRv) {
3418 return self->ContinueProcessResponseAfterPartialContent(aRv);
3419 };
3420 rv = ProcessPartialContent(func);
3421 // Directly call ContinueProcessResponseAfterPartialContent if channel
3422 // is not suspended or ProcessPartialContent throws.
3423 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3424 return ContinueProcessResponseAfterPartialContent(rv);
3425 }
3426 return NS_OK;
3427 } else {
3428 mCacheInputStream.CloseAndRelease();
3429 rv = ProcessNormal();
3430 }
3431 break;
3432 case 301:
3433 case 302:
3434 case 303:
3435 case 307:
3436 case 308:
3437#if 0
3438 case 305: // disabled as a security measure (see bug 187996).
3439#endif
3440 // RFC 9110: 303 responses are cacheable, but only with explicit
3441 // freshness information (max-age or Expires). Without these directives,
3442 // 303 should not be cached.
3443 if (httpStatus == 303) {
3444 uint32_t freshnessLifetime = 0;
3445 bool hasFreshness =
3446 (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
ComputeFreshnessLifetime(&freshnessLifetime))), 1)))
3447 mResponseHead->ComputeFreshnessLifetime(&freshnessLifetime))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
ComputeFreshnessLifetime(&freshnessLifetime))), 1)))
&&
3448 freshnessLifetime > 0) ||
3449 mResponseHead->HasHeader(nsHttp::Expires);
3450 if (mResponseHead->NoStore() || mResponseHead->NoCache() ||
3451 !hasFreshness) {
3452 CloseCacheEntry(false);
3453 }
3454 }
3455 // don't store the response body for redirects
3456 MaybeInvalidateCacheEntryForSubsequentGet();
3457 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
3458 rv = AsyncProcessRedirection(httpStatus);
3459 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3460 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
3461 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)
3462 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)
;
3463 // don't cache failed redirect responses.
3464 if (mCacheEntry) mCacheEntry->AsyncDoom(nullptr);
3465 if (DoNotRender3xxBody(rv)) {
3466 mStatus = rv;
3467 DoNotifyListener();
3468 } else {
3469 rv = ContinueProcessResponse4(rv);
3470 }
3471 }
3472 break;
3473 case 304:
3474 if (!ShouldBypassProcessNotModified()) {
3475 auto func = [](auto* self, nsresult aRv) {
3476 return self->ContinueProcessResponseAfterNotModified(aRv);
3477 };
3478 rv = ProcessNotModified(func);
3479 // Directly call ContinueProcessResponseAfterNotModified if channel
3480 // is not suspended or ProcessNotModified throws.
3481 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3482 return ContinueProcessResponseAfterNotModified(rv);
3483 }
3484 return NS_OK;
3485 }
3486
3487 // Don't cache uninformative 304
3488 if (LoadCustomConditionalRequest()) {
3489 CloseCacheEntry(false);
3490 }
3491
3492 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3493 rv = ProcessNormal();
3494 }
3495 break;
3496 case 401:
3497 case 407:
3498 if (MOZ_UNLIKELY(httpStatus == 407 && transactionRestarted)(__builtin_expect(!!(httpStatus == 407 && transactionRestarted
), 0))
) {
3499 // The transaction has been internally restarted. We want to
3500 // authenticate to the proxy again, so reuse either cached credentials
3501 // or use default credentials for NTLM/Negotiate. This prevents
3502 // considering the previously used credentials as invalid.
3503 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", 3503
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3503); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3504 if (!mAuthProvider) {
3505 mStatus = NS_ERROR_UNEXPECTED;
3506 return ProcessNormal();
3507 }
3508 mAuthProvider->ClearProxyIdent();
3509 }
3510 if (!LoadAuthRedirectedChannel() &&
3511 MOZ_UNLIKELY(LoadCustomAuthHeader())(__builtin_expect(!!(LoadCustomAuthHeader()), 0)) && httpStatus == 401) {
3512 // When a custom auth header fails, we don't want to try
3513 // any cached credentials, nor we want to ask the user.
3514 // It's up to the consumer to re-try w/o setting a custom
3515 // auth header if cached credentials should be attempted.
3516 rv = NS_ERROR_FAILURE;
3517 } else if (httpStatus == 401 &&
3518 !nsContentSecurityUtils::CheckCSPFrameAncestorAndXFO(this)) {
3519 // CSP Frame Ancestor and X-Frame-Options check has failed
3520 // Do not prompt http auth - Bug 1629307
3521 rv = NS_ERROR_FAILURE;
3522 } else {
3523 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", 3523
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3523); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3524 rv = mAuthProvider
3525 ? mAuthProvider->ProcessAuthentication(
3526 httpStatus, mConnectionInfo->EndToEndSSL() &&
3527 mTransaction &&
3528 mTransaction->ProxyConnectFailed())
3529 : NS_ERROR_UNEXPECTED;
3530 }
3531 if (rv == NS_ERROR_IN_PROGRESS) {
3532 // authentication prompt has been invoked and result
3533 // is expected asynchronously
3534 mIsAuthChannel = true;
3535 mAuthRetryPending = true;
3536 if (httpStatus == 407 ||
3537 (mTransaction && mTransaction->ProxyConnectFailed())) {
3538 StoreProxyAuthPending(true);
3539 }
3540
3541 // suspend the transaction pump to stop receiving the
3542 // unauthenticated content data. We will throw that data
3543 // away when user provides credentials or resume the pump
3544 // when user refuses to authenticate.
3545 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)
3546 ("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)
3547 "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)
;
3548 Suspend();
3549
3550#ifdef DEBUG1
3551 // This is for test purposes only. See bug 1683176 for details.
3552 gHttpHandler->OnTransactionSuspendedDueToAuthentication(this);
3553#endif
3554 rv = NS_OK;
3555 } else if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3556 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)
3557 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)
;
3558 if (mTransaction && mTransaction->ProxyConnectFailed()) {
3559 return ProcessFailedProxyConnect(httpStatus);
3560 }
3561 if (rv == NS_ERROR_BASIC_HTTP_AUTH_DISABLED) {
3562 mStatus = rv;
3563 }
3564 rv = ProcessNormal();
3565 } else {
3566 mIsAuthChannel = true;
3567 mAuthRetryPending = true;
3568 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
3569 if (NS_SUCCEEDED(RedirectToNewChannelForAuthRetry())((bool)(__builtin_expect(!!(!NS_FAILED_impl(RedirectToNewChannelForAuthRetry
())), 1)))
) {
3570 return NS_OK;
3571 }
3572 mAuthRetryPending = false;
3573 rv = ProcessNormal();
3574 }
3575 }
3576 break;
3577
3578 case 408:
3579 case 425:
3580 case 429:
3581 // Do not cache 408, 425 and 429.
3582 CloseCacheEntry(false);
3583 [[fallthrough]]; // process normally
3584 default:
3585 rv = ProcessNormal();
3586 MaybeInvalidateCacheEntryForSubsequentGet();
3587 break;
3588 }
3589
3590 UpdateCacheDisposition(false, false);
3591 return rv;
3592}
3593
3594nsresult nsHttpChannel::ContinueProcessResponseAfterPartialContent(
3595 nsresult aRv) {
3596 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)
3597 ("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)
3598 "[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)
3599 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)
;
3600
3601 UpdateCacheDisposition(false, NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1))));
3602 return aRv;
3603}
3604
3605nsresult nsHttpChannel::ContinueProcessResponseAfterNotModified(nsresult aRv) {
3606 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)
3607 ("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)
3608 "[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)
3609 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)
;
3610
3611 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))) {
3612 StoreTransactionReplaced(true);
3613 UpdateCacheDisposition(true, false);
3614 return NS_OK;
3615 }
3616
3617 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)
3618 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)
;
3619
3620 // We cannot read from the cache entry, it might be in an
3621 // inconsistent state. Doom it and redirect the channel
3622 // to the same URI to reload from the network.
3623 mCacheInputStream.CloseAndRelease();
3624 if (mCacheEntry) {
3625 mCacheEntry->AsyncDoom(nullptr);
3626 mCacheEntry = nullptr;
3627 }
3628
3629 nsresult rv =
3630 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
3631 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3632 return NS_OK;
3633 }
3634
3635 // Don't cache uninformative 304
3636 if (LoadCustomConditionalRequest()) {
3637 CloseCacheEntry(false);
3638 }
3639
3640 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3641 rv = ProcessNormal();
3642 }
3643
3644 UpdateCacheDisposition(false, false);
3645 return rv;
3646}
3647
3648static void ReportHttpResponseVersion(HttpVersion version) {
3649 if (Telemetry::CanRecordPrereleaseData()) {
3650 glean::http::response_version.AccumulateSingleSample(
3651 static_cast<uint32_t>(version));
3652 }
3653 mozilla::glean::networking::http_response_version
3654 .Get(HttpVersionToTelemetryLabel(version))
3655 .Add(1);
3656}
3657
3658void nsHttpChannel::UpdateCacheDisposition(bool aSuccessfulReval,
3659 bool aPartialContentUsed) {
3660 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)
3661 "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)
3662 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)
3663 !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)
3664 : (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)
;
3665 CacheDisposition cacheDisposition;
3666 if (!mDidReval) {
3667 cacheDisposition = kCacheMissed;
3668 } else if (aSuccessfulReval) {
3669 cacheDisposition = kCacheHitViaReval;
3670 } else {
3671 cacheDisposition = kCacheMissedViaReval;
3672 }
3673 mCacheDisposition = cacheDisposition;
3674
3675 if (Telemetry::CanRecordPrereleaseData()) {
3676 AccumulateCacheHitTelemetry(cacheDisposition, this);
3677 }
3678
3679 ReportHttpResponseVersion(mResponseHead->Version());
3680}
3681
3682// Only used for redirects (3XX responses)
3683nsresult nsHttpChannel::ContinueProcessResponse4(nsresult rv) {
3684 bool doNotRender = DoNotRender3xxBody(rv);
3685
3686 if (rv == NS_ERROR_DOM_BAD_URI && mRedirectURI &&
3687 !net::SchemeIsHttpOrHttps(mRedirectURI)) {
3688 // This was a blocked attempt to redirect and subvert the system by
3689 // redirecting to another protocol (perhaps javascript:)
3690 // In that case we want to throw an error instead of displaying the
3691 // non-redirected response body.
3692 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)
;
3693 doNotRender = true;
3694 rv = NS_ERROR_CORRUPTED_CONTENT;
3695 }
3696
3697 if (doNotRender) {
3698 Cancel(rv);
3699 DoNotifyListener();
3700 return rv;
3701 }
3702
3703 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3704 UpdateInhibitPersistentCachingFlag();
3705 (void)MaybeReplaceNoVarySearchAliasEntry();
3706
3707 if (mCacheEntry) {
3708 rv = UpdateExpirationTime();
3709 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3710 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)
3711 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)
;
3712 }
3713 }
3714 rv = InitCacheEntry();
3715 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3716 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)
3717 ("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)
3718 "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)
3719 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)
;
3720 }
3721 CloseCacheEntry(false);
3722 return NS_OK;
3723 }
3724
3725 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)
3726 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)
;
3727 if (mTransaction && mTransaction->ProxyConnectFailed()) {
3728 return ProcessFailedProxyConnect(mRedirectType);
3729 }
3730 return ProcessNormal();
3731}
3732
3733nsresult nsHttpChannel::ProcessNormal() {
3734 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)
;
3735
3736 return ContinueProcessNormal(NS_OK);
3737}
3738
3739nsresult nsHttpChannel::ContinueProcessNormal(nsresult rv) {
3740 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)
;
3741
3742 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3743 // Fill the failure status here, we have failed to fall back, thus we
3744 // have to report our status as failed.
3745 mStatus = rv;
3746 DoNotifyListener();
3747 return rv;
3748 }
3749
3750 rv = ProcessCrossOriginSecurityHeaders();
3751 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3752 mStatus = rv;
3753 HandleAsyncAbort();
3754 return rv;
3755 }
3756
3757 // if we're here, then any byte-range requests failed to result in a partial
3758 // response. we must clear this flag to prevent BufferPartialContent from
3759 // being called inside our OnDataAvailable (see bug 136678).
3760 StoreCachedContentIsPartial(false);
3761
3762 UpdateInhibitPersistentCachingFlag();
3763
3764 // We may need to install the cache listener before CallonStartRequest,
3765 // since InstallCacheListener can modify the Content-Encoding to remove
3766 // dcb/dcz (and perhaps others), and CallOnStartRequest() copies
3767 // Content-Encoding to send to the content process. If this doesn't
3768 // install a listener (because this isn't a dictionary or
3769 // dictionary-compressed), call it after CallOnStartRequest so that we
3770 // save the compressed data in the cache, and run the decompressor in the
3771 // content process.
3772 mIsDictionaryCompressed = false;
3773 nsAutoCString contentEncoding;
3774 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
3775 if (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
3776 contentEncoding.LowerCaseEqualsLiteral("dcz")) {
3777 mIsDictionaryCompressed = true;
3778 } else if (contentEncoding.LowerCaseFindASCII("dcb") != -1 ||
3779 contentEncoding.LowerCaseFindASCII("dcz") != -1) {
3780 // Reject responses that combine dcb/dcz with other encodings
3781 // (e.g. "dcb, gzip" or "gzip, dcz"). We don't support chained
3782 // dictionary compression with other compression methods.
3783 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)
3784 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)
;
3785 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
3786 return NS_ERROR_INVALID_CONTENT_ENCODING;
3787 }
3788
3789 (void)MaybeReplaceNoVarySearchAliasEntry();
3790
3791 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3792 // Must update expiration time early - ParseDictionary reads it, and
3793 // it's no longer done in InitCacheEntry to avoid double calculation
3794 rv = UpdateExpirationTime();
3795 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3796 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)
;
3797 }
3798
3799 // XXX We may want to consider recompressing any dcb/dcz files to save space
3800 // and improve hitrate. Downside is CPU use, complexity and perhaps delay,
3801 // maybe.
3802 nsAutoCString dictionary;
3803 if (StaticPrefs::network_http_dictionaries_enable() && IsHTTPS()) {
3804 (void)mResponseHead->GetHeader(nsHttp::Use_As_Dictionary, dictionary);
3805 if (!dictionary.IsEmpty()) {
3806 if (!ParseDictionary(mCacheEntry, mResponseHead.get(), true)) {
3807 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)
;
3808 } else {
3809 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"
, 3809); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDictSaving"
")"); do { MOZ_CrashSequence(__null, 3809); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3810
3811 // We need to record the hash as we save it
3812 mCacheEntry->SetDictionary(mDictSaving);
3813 }
3814 }
3815 }
3816
3817 // we would call DoInstallCacheListener() here, but it will close the
3818 // cache input stream, which causes problems if we going to be
3819 // suspended because we're replacing a active dictionary. Instead we'll
3820 // call it in ContinueProcessNormal2()
3821 } else {
3822 if (mIsDictionaryCompressed) {
3823 // We still need to decompress in the parent if it's dcb or dcz even if
3824 // not saving to the cache
3825 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)
3826 ("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)
;
3827 nsCOMPtr<nsIStreamListener> listener;
3828 // otherwise we won't convert in the parent process
3829 // XXX may be redundant, but safe
3830 SetApplyConversion(true);
3831 rv = DoApplyContentConversionsInternal(
3832 mListener, getter_AddRefs(listener), true, nullptr);
3833 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3834 return rv;
3835 }
3836 if (listener) {
3837 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)
3838 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)
;
3839 mListener = listener;
3840 mCompressListener = std::move(listener);
3841 StoreHasAppliedConversion(true);
3842 } else {
3843 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)
;
3844 // This should never happen for dictionary-compressed content (dcb/dcz)
3845 // as it MUST be decompressed in the parent process
3846 if (mIsDictionaryCompressed) {
3847 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)
3848 ("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)
3849 "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)
;
3850 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
3851 return NS_ERROR_INVALID_CONTENT_ENCODING;
3852 }
3853 }
3854 }
3855 } // else we'll call InstallCacheListener after CallOnStartRequest
3856
3857 // ParseDictionary may have resulted in our Suspend()ing this request
3858 // until the old dictionary we're replacing has been read from the cache.
3859 // If we continue we'll call InitCacheEntry() and Doom/truncate the entry
3860 // the old one is reading from.
3861 return ContinueProcessNormal2(rv);
3862}
3863
3864nsresult nsHttpChannel::ContinueProcessNormal2(nsresult rv) {
3865 if (mSuspendCount) {
3866 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)
3867 ("*** 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)
3868 "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)
3869 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)
;
3870 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)
3871 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)
;
3872 mCallOnResume = [rv](nsHttpChannel* self) {
3873 (void)self->ContinueProcessNormal2(rv);
3874 return NS_OK;
3875 };
3876 return NS_OK;
3877 }
3878
3879 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCanceled) {
3880 // The process switch failed, cancel this channel.
3881 Cancel(rv);
3882 return CallOnStartRequest();
3883 }
3884
3885 // this must be called before firing OnStartRequest, since http clients,
3886 // such as imagelib, expect our cache entry to already have the correct
3887 // expiration time (bug 87710).
3888 if (mCacheEntry) {
3889 rv = InitCacheEntry();
3890 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CloseCacheEntry(true);
3891 }
3892
3893 // CRITICAL: Check if dictionary is ready BEFORE creating decompressor.
3894 // If we create the decompressor before the dictionary is ready, it will
3895 // be created without the dictionary attached, causing decompression to fail.
3896 // The dictionary prefetch callback (in PrepareToConnect) will call Resume()
3897 // when ready, which will re-invoke ContinueProcessNormal2 via mCallOnResume.
3898 if (mIsDictionaryCompressed && mDictDecompress && mUsingDictionary &&
3899 mShouldSuspendForDictionary && !mDictDecompress->DictionaryReady()) {
3900 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)
3901 ("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)
3902 "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)
3903 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)
;
3904 Suspend();
3905 mSuspendedForDictionary = true;
3906 // Set up callback to resume processing when dictionary loads
3907 mCallOnResume = [](nsHttpChannel* self) {
3908 return self->ContinueProcessNormal3();
3909 };
3910 return NS_OK;
3911 }
3912
3913 return ContinueProcessNormal3();
3914}
3915
3916nsresult nsHttpChannel::ContinueProcessNormal3() {
3917 if (mCanceled) {
3918 return CallOnStartRequest();
3919 }
3920 nsresult rv = NS_OK;
3921
3922 // Finish post-ParseDictionary work, must be done after waiting if Suspended
3923 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3924 if (mIsDictionaryCompressed || mDictSaving) {
3925 if (MOZ_LOG_TEST(mozilla::net::gDictionaryLog,(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
3926 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
) {
3927 nsAutoCString ceDebug;
3928 if (mResponseHead) {
3929 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, ceDebug);
3930 }
3931 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)
3932 ("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)
3933 "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)
3934 "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)
3935 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)
3936 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)
;
3937 }
3938 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)
;
3939 rv = DoInstallCacheListener(mIsDictionaryCompressed || mDictSaving, 0);
3940 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3941 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)
3942 ("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)
;
3943 // Cache entry is now corrupted - we set up headers with dcb/dcz
3944 // Content-Encoding but failed to install the decompressor that would
3945 // clear it. Doom the entry to prevent serving corrupted data.
3946 CloseCacheEntry(true);
3947 }
3948 }
3949 }
3950
3951 // Check that the server sent us what we were asking for
3952 if (LoadResuming()) {
3953 // Create an entity id from the response
3954 nsAutoCString id;
3955 rv = GetEntityID(id);
3956 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3957 // If creating an entity id is not possible -> error
3958 Cancel(NS_ERROR_NOT_RESUMABLE);
3959 } else if (mResponseHead->Status() != 206 &&
3960 mResponseHead->Status() != 200) {
3961 // Probably 404 Not Found, 412 Precondition Failed or
3962 // 416 Invalid Range -> error
3963 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)
3964 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)
;
3965 Cancel(NS_ERROR_ENTITY_CHANGED);
3966 }
3967 // If we were passed an entity id, verify it's equal to the server's
3968 else if (!mEntityID.IsEmpty()) {
3969 if (!mEntityID.Equals(id)) {
3970 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)
3971 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)
;
3972 Cancel(NS_ERROR_ENTITY_CHANGED);
3973 }
3974 }
3975 }
3976
3977 rv = CallOnStartRequest();
3978 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3979
3980 // If we didn't install cache listeners to decompress above
3981 // install the cache listener now (so they'll get compressed data)
3982 if (!mIsDictionaryCompressed && !mDictSaving) {
3983 // install cache listener if we still have a cache entry open
3984 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3985 if (MOZ_LOG_TEST(mozilla::net::gDictionaryLog,(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
3986 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
&&
3987 mResponseHead) {
3988 nsAutoCString ceCheck;
3989 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, ceCheck);
3990 if (!ceCheck.IsEmpty()) {
3991 nsAutoCString uadCheck;
3992 (void)mResponseHead->GetHeader(nsHttp::Use_As_Dictionary, uadCheck);
3993 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)
3994 ("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)
3995 "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)
3996 "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)
3997 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)
3998 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)
;
3999 }
4000 }
4001 rv = InstallCacheListener();
4002 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4003 }
4004 }
4005 return NS_OK;
4006}
4007
4008nsresult nsHttpChannel::PromptTempRedirect() {
4009 if (!gHttpHandler->PromptTempRedirect()) {
4010 return NS_OK;
4011 }
4012 nsresult rv;
4013 nsCOMPtr<nsIStringBundleService> bundleService;
4014 bundleService = mozilla::components::StringBundle::Service(&rv);
4015 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4016
4017 nsCOMPtr<nsIStringBundle> stringBundle;
4018 rv =
4019 bundleService->CreateBundle(NECKO_MSGS_URL"chrome://necko/locale/necko.properties", getter_AddRefs(stringBundle));
4020 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4021
4022 nsAutoString messageString;
4023 rv = stringBundle->GetStringFromName("RepostFormData", messageString);
4024 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4025 bool repost = false;
4026
4027 nsCOMPtr<nsIPrompt> prompt;
4028 GetCallback(prompt);
4029 if (!prompt) return NS_ERROR_NO_INTERFACE;
4030
4031 prompt->Confirm(nullptr, messageString.get(), &repost);
4032 if (!repost) return NS_ERROR_FAILURE;
4033 }
4034
4035 return rv;
4036}
4037
4038nsresult nsHttpChannel::ProxyFailover() {
4039 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)
;
4040
4041 nsresult rv;
4042
4043 nsCOMPtr<nsIProtocolProxyService> pps;
4044 pps = mozilla::components::ProtocolProxy::Service(&rv);
4045 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4046
4047 nsCOMPtr<nsIProxyInfo> pi;
4048 rv = pps->GetFailoverForProxy(mConnectionInfo->ProxyInfo(), mURI, mStatus,
4049 getter_AddRefs(pi));
4050#ifdef MOZ_PROXY_DIRECT_FAILOVER1
4051 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4052 if (!StaticPrefs::network_proxy_failover_direct()) {
4053 return rv;
4054 }
4055 // If this request used a failed proxy and there is no failover available,
4056 // fallback to DIRECT connections for conservative requests.
4057 if (LoadBeConservative()) {
4058 rv = pps->NewProxyInfo("direct"_ns, ""_ns, 0, ""_ns, ""_ns, 0, UINT32_MAX(4294967295U),
4059 nullptr, getter_AddRefs(pi));
4060 }
4061#endif
4062 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4063 return rv;
4064 }
4065#ifdef MOZ_PROXY_DIRECT_FAILOVER1
4066 }
4067#endif
4068
4069 // XXXbz so where does this codepath remove us from the loadgroup,
4070 // exactly?
4071 return AsyncDoReplaceWithProxy(pi);
4072}
4073
4074void nsHttpChannel::SetHTTPSSVCRecord(
4075 already_AddRefed<nsIDNSHTTPSSVCRecord> aRecord) {
4076 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)
;
4077 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
4078 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", 4078
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mHTTPSSVCRecord"
")"); do { MOZ_CrashSequence(__null, 4078); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4079 mHTTPSSVCRecord.emplace(std::move(record));
4080}
4081
4082void nsHttpChannel::HandleAsyncRedirectChannelToHttps() {
4083 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"
, 4083); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4083); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4084
4085 if (mSuspendCount) {
4086 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)
4087 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)
;
4088 mCallOnResume = [](nsHttpChannel* self) {
4089 self->HandleAsyncRedirectChannelToHttps();
4090 return NS_OK;
4091 };
4092 return;
4093 }
4094
4095 nsresult rv = StartRedirectChannelToHttps();
4096 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4097 rv = ContinueAsyncRedirectChannelToURI(rv);
4098 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4099 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)
4100 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)
;
4101 }
4102 }
4103}
4104
4105nsresult nsHttpChannel::StartRedirectChannelToHttps() {
4106 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)
;
4107
4108 nsCOMPtr<nsIURI> upgradedURI;
4109 nsresult rv = NS_GetSecureUpgradedURI(mURI, getter_AddRefs(upgradedURI));
4110 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"
, 4110); return rv; } } while (false)
;
4111
4112 return StartRedirectChannelToURI(
4113 upgradedURI, nsIChannelEventSink::REDIRECT_PERMANENT |
4114 nsIChannelEventSink::REDIRECT_STS_UPGRADE);
4115}
4116
4117void nsHttpChannel::HandleAsyncAPIRedirect() {
4118 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"
, 4118); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4118); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4119 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"
, 4119); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4119); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4120 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"
, 4120); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo->first()"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4120); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4121
4122 if (mSuspendCount) {
4123 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)
;
4124 mCallOnResume = [](nsHttpChannel* self) {
4125 self->HandleAsyncAPIRedirect();
4126 return NS_OK;
4127 };
4128 return;
4129 }
4130
4131 nsresult rv = StartRedirectChannelToURI(
4132 mAPIRedirectTo->first(),
4133 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_PERMANENT |
4134 nsIChannelEventSink::REDIRECT_TRANSPARENT
4135 : nsIChannelEventSink::REDIRECT_PERMANENT);
4136 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4137 rv = ContinueAsyncRedirectChannelToURI(rv);
4138 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4139 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)
4140 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)
;
4141 }
4142 }
4143}
4144
4145void nsHttpChannel::HandleAsyncRedirectToUnstrippedURI() {
4146 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"
, 4146); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4146); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4147
4148 if (mSuspendCount) {
4149 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)
4150 ("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)
4151 "[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)
4152 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)
;
4153 mCallOnResume = [](nsHttpChannel* self) {
4154 self->HandleAsyncRedirectToUnstrippedURI();
4155 return NS_OK;
4156 };
4157 return;
4158 }
4159
4160 nsCOMPtr<nsIURI> unstrippedURI;
4161 mLoadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
4162
4163 // Clear the unstripped URI from the loadInfo before starting redirect in case
4164 // endless redirect.
4165 mLoadInfo->SetUnstrippedURI(nullptr);
4166
4167 nsresult rv = StartRedirectChannelToURI(
4168 unstrippedURI, nsIChannelEventSink::REDIRECT_PERMANENT);
4169
4170 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4171 rv = ContinueAsyncRedirectChannelToURI(rv);
4172 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4173 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)
4174 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)
;
4175 }
4176 }
4177}
4178nsresult nsHttpChannel::RedirectToNewChannelForAuthRetry() {
4179 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)
;
4180 nsresult rv = NS_OK;
4181
4182 nsCOMPtr<nsILoadInfo> redirectLoadInfo = CloneLoadInfoForRedirect(
4183 mURI, nsIChannelEventSink::REDIRECT_INTERNAL |
4184 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4185
4186 nsCOMPtr<nsIIOService> ioService;
4187
4188 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
4189 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"
, 4189); return rv; } } while (false)
;
4190
4191 nsCOMPtr<nsIChannel> newChannel;
4192 rv = gHttpHandler->NewProxiedChannel(mURI, mProxyInfo, mProxyResolveFlags,
4193 mProxyURI, mLoadInfo,
4194 getter_AddRefs(newChannel));
4195
4196 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"
, 4196); return rv; } } while (false)
;
4197
4198 rv = SetupReplacementChannel(mURI, newChannel, true,
4199 nsIChannelEventSink::REDIRECT_INTERNAL |
4200 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4201 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"
, 4201); return rv; } } while (false)
;
4202
4203 // rewind the upload stream
4204 if (mUploadStream) {
4205 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
4206 nsresult rv = NS_ERROR_NO_INTERFACE;
4207 if (seekable) {
4208 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
4209 }
4210
4211 // This should not normally happen, but it's possible that big memory
4212 // blobs originating in the other process can't be rewinded.
4213 // In that case we just fail the request, otherwise the content length
4214 // will not match and this load will never complete.
4215 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"
, 4215); return rv; } } while (false)
;
4216 }
4217
4218 RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel);
4219
4220 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", 4220
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthProvider" ")"
); do { MOZ_CrashSequence(__null, 4220); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4221 httpChannelImpl->mAuthProvider = std::move(mAuthProvider);
4222
4223 httpChannelImpl->mProxyInfo = mProxyInfo;
4224
4225 if ((mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) ||
4226 mTransaction->HasStickyConnection()) {
4227 mConnectionInfo = mTransaction->GetConnInfo();
4228
4229 httpChannelImpl->mTransactionSticky = mTransaction;
4230
4231 if (mTransaction->Http2Disabled()) {
4232 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
4233 }
4234 if (mTransaction->Http3Disabled()) {
4235 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
4236 }
4237 }
4238 // always set sticky connection flag
4239 httpChannelImpl->mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
4240
4241 if (LoadAuthConnectionRestartable()) {
4242 httpChannelImpl->mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
4243 } else {
4244 httpChannelImpl->mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
4245 }
4246
4247 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", 4247
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo" ")"
); do { MOZ_CrashSequence(__null, 4247); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4248 httpChannelImpl->mConnectionInfo = mConnectionInfo->Clone();
4249
4250 // we need to store the state to skip unnecessary checks in the new channel
4251 httpChannelImpl->StoreAuthRedirectedChannel(true);
4252
4253 // We must copy proxy and auth header to the new channel.
4254 // Although the new channel can populate auth headers from auth cache, we
4255 // would still like to use the auth headers generated in this channel. The
4256 // main reason for doing this is that certain connection-based/stateful auth
4257 // schemes like NTLM will fail when we try generate the credentials more than
4258 // the number of times the server has presented us the challenge due to the
4259 // usage of nonce in generating the credentials Copying the auth header will
4260 // bypass generation of the credentials
4261 nsAutoCString authVal;
4262 if (NS_SUCCEEDED(GetRequestHeader("Proxy-Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Proxy-Authorization"_ns, authVal))), 1)))
) {
4263 httpChannelImpl->SetRequestHeader("Proxy-Authorization"_ns, authVal, false);
4264 }
4265 if (NS_SUCCEEDED(GetRequestHeader("Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Authorization"_ns, authVal))), 1)))
) {
4266 httpChannelImpl->SetRequestHeader("Authorization"_ns, authVal, false);
4267 }
4268
4269 httpChannelImpl->SetBlockAuthPrompt(LoadBlockAuthPrompt());
4270 mRedirectChannel = newChannel;
4271
4272 rv = gHttpHandler->AsyncOnChannelRedirect(
4273 this, newChannel,
4274 nsIChannelEventSink::REDIRECT_INTERNAL |
4275 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4276
4277 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4278
4279 // redirected channel will be opened after we receive the OnStopRequest
4280
4281 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4282 AutoRedirectVetoNotifier notifier(this, rv);
4283 mRedirectChannel = nullptr;
4284 }
4285
4286 return rv;
4287}
4288
4289nsresult nsHttpChannel::StartRedirectChannelToURI(nsIURI* upgradedURI,
4290 uint32_t flags) {
4291 return StartRedirectChannelToURI(upgradedURI, flags, [](nsIChannel*) {});
4292}
4293
4294nsresult nsHttpChannel::StartRedirectChannelToURI(
4295 nsIURI* upgradedURI, uint32_t flags,
4296 std::function<void(nsIChannel*)>&& aCallback) {
4297 nsresult rv = NS_OK;
4298 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)
;
4299
4300 nsCOMPtr<nsIChannel> newChannel;
4301 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
4302 CloneLoadInfoForRedirect(upgradedURI, flags);
4303
4304 nsCOMPtr<nsIIOService> ioService;
4305 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
4306 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"
, 4306); return rv; } } while (false)
;
4307
4308 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), upgradedURI,
4309 redirectLoadInfo,
4310 nullptr, // PerformanceStorage
4311 nullptr, // aLoadGroup
4312 nullptr, // aCallbacks
4313 nsIRequest::LOAD_NORMAL, ioService);
4314 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"
, 4314); return rv; } } while (false)
;
4315
4316 rv = SetupReplacementChannel(upgradedURI, newChannel, true, flags);
4317 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"
, 4317); return rv; } } while (false)
;
4318
4319 if (mHTTPSSVCRecord) {
4320 RefPtr<nsHttpChannel> httpChan = do_QueryObject(newChannel);
4321 nsCOMPtr<nsIDNSHTTPSSVCRecord> rec = mHTTPSSVCRecord.ref();
4322 if (httpChan && rec) {
4323 httpChan->SetHTTPSSVCRecord(rec.forget());
4324 }
4325 }
4326
4327 // Inform consumers about this fake redirect
4328 mRedirectChannel = newChannel;
4329
4330 aCallback(newChannel);
4331
4332 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
4333 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
4334
4335 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4336
4337 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4338 AutoRedirectVetoNotifier notifier(this, rv);
4339
4340 /* Remove the async call to ContinueAsyncRedirectChannelToURI().
4341 * It is called directly by our callers upon return (to clean up
4342 * the failed redirect). */
4343 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
4344 }
4345
4346 return rv;
4347}
4348
4349nsresult nsHttpChannel::ContinueAsyncRedirectChannelToURI(nsresult rv) {
4350 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)
;
4351
4352 // Since we handle mAPIRedirectTo uri also after on-examine-response handler
4353 // rather drop it here to avoid any redirect loops, even just hypothetical.
4354 mAPIRedirectTo = Nothing();
4355
4356 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4357 rv = OpenRedirectChannel(rv);
4358 }
4359
4360 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4361 // Cancel the channel here, the update to https had been vetoed
4362 // but from the security reasons we have to discard the whole channel
4363 // load.
4364 Cancel(rv);
4365 }
4366
4367 if (mLoadGroup) {
4368 mLoadGroup->RemoveRequest(this, nullptr, mStatus);
4369 }
4370
4371 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCachePump && !mTransactionPump) {
4372 // We have to manually notify the listener because there is not any pump
4373 // that would call our OnStart/StopRequest after resume from waiting for
4374 // the redirect callback.
4375 DoNotifyListener();
4376 }
4377
4378 return rv;
4379}
4380
4381nsresult nsHttpChannel::OpenRedirectChannel(nsresult rv) {
4382 AutoRedirectVetoNotifier notifier(this, rv);
4383
4384 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4385
4386 if (!mRedirectChannel) {
4387 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)
4388 "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)
;
4389 return NS_ERROR_FAILURE;
4390 }
4391
4392 // Make sure to do this after we received redirect veto answer,
4393 // i.e. after all sinks had been notified
4394 mRedirectChannel->SetOriginalURI(mOriginalURI);
4395
4396 // open new channel
4397 rv = mRedirectChannel->AsyncOpen(mListener);
4398
4399 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"
, 4399); return rv; } } while (false)
;
4400
4401 mStatus = NS_BINDING_REDIRECTED;
4402
4403 notifier.RedirectSucceeded();
4404
4405 ReleaseListeners();
4406
4407 return NS_OK;
4408}
4409
4410nsresult nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi) {
4411 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)
;
4412 nsresult rv;
4413
4414 nsCOMPtr<nsIChannel> newChannel;
4415 rv = gHttpHandler->NewProxiedChannel(mURI, pi, mProxyResolveFlags, mProxyURI,
4416 mLoadInfo, getter_AddRefs(newChannel));
4417 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4418
4419 uint32_t flags = nsIChannelEventSink::REDIRECT_INTERNAL;
4420
4421 rv = SetupReplacementChannel(mURI, newChannel, true, flags);
4422 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4423
4424 // Inform consumers about this fake redirect
4425 mRedirectChannel = newChannel;
4426
4427 PushRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
4428 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
4429
4430 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4431
4432 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4433 AutoRedirectVetoNotifier notifier(this, rv);
4434 PopRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
4435 }
4436
4437 return rv;
4438}
4439
4440nsresult nsHttpChannel::ResolveProxy() {
4441 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)
;
4442
4443 nsresult rv;
4444
4445 nsCOMPtr<nsIProtocolProxyService> pps;
4446 pps = mozilla::components::ProtocolProxy::Service(&rv);
4447 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4448
4449 // using the nsIProtocolProxyService2 allows a minor performance
4450 // optimization, but if an add-on has only provided the original interface
4451 // then it is ok to use that version.
4452 nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
4453 if (pps2) {
4454 rv = pps2->AsyncResolve2(this, mProxyResolveFlags, this, nullptr,
4455 getter_AddRefs(mProxyRequest));
4456 } else {
4457 rv = pps->AsyncResolve(static_cast<nsIChannel*>(this), mProxyResolveFlags,
4458 this, nullptr, getter_AddRefs(mProxyRequest));
4459 }
4460
4461 return rv;
4462}
4463
4464bool nsHttpChannel::ResponseWouldVary(nsICacheEntry* entry) {
4465 nsresult rv;
4466 nsAutoCString buf, metaKey;
4467 (void)mCachedResponseHead->GetHeader(nsHttp::Vary, buf);
4468
4469 constexpr auto prefix = "request-"_ns;
4470
4471 // enumerate the elements of the Vary header...
4472 for (const nsACString& token :
4473 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4474 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)
4475 ("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)
4476 "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)
4477 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)
;
4478 //
4479 // if "*", then assume response would vary. technically speaking,
4480 // "Vary: header, *" is not permitted, but we allow it anyways.
4481 //
4482 // We hash values of cookie-headers for the following reasons:
4483 //
4484 // 1- cookies can be very large in size
4485 //
4486 // 2- cookies may contain sensitive information. (for parity with
4487 // out policy of not storing Set-cookie headers in the cache
4488 // meta data, we likewise do not want to store cookie headers
4489 // here.)
4490 //
4491 if (token.EqualsLiteral("*")) {
4492 return true; // if we encounter this, just get out of here
4493 }
4494
4495 // build cache meta data key...
4496 metaKey = prefix + token;
4497
4498 // check the last value of the given request header to see if it has
4499 // since changed. if so, then indeed the cached response is invalid.
4500 nsCString lastVal;
4501 entry->GetMetaDataElement(metaKey.get(), getter_Copies(lastVal));
4502 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)
4503 ("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)
4504 "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)
4505 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)
;
4506
4507 // Look for value of "Cookie" in the request headers
4508 nsHttpAtom atom = nsHttp::ResolveAtom(token);
4509 nsAutoCString newVal;
4510 bool hasHeader = NS_SUCCEEDED(mRequestHead.GetHeader(atom, newVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(atom, newVal))), 1)))
;
4511 if (!lastVal.IsEmpty()) {
4512 // value for this header in cache, but no value in request
4513 if (!hasHeader) {
4514 return true; // yes - response would vary
4515 }
4516
4517 // If this is a cookie-header, stored metadata is not
4518 // the value itself but the hash. So we also hash the
4519 // outgoing value here in order to compare the hashes
4520 nsAutoCString hash;
4521 if (atom == nsHttp::Cookie) {
4522 rv = Hash(newVal.get(), hash);
4523 // If hash failed, be conservative (the cached hash
4524 // exists at this point) and claim response would vary
4525 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return true;
4526 newVal = std::move(hash);
4527
4528 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)
4529 ("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)
4530 "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)
4531 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)
;
4532 }
4533
4534 if (!newVal.Equals(lastVal)) {
4535 return true; // yes, response would vary
4536 }
4537
4538 } else if (hasHeader) { // old value is empty, but newVal is set
4539 return true;
4540 }
4541 }
4542
4543 return false;
4544}
4545
4546// Remove an entry from Vary header, if it exists
4547void RemoveFromVary(nsHttpResponseHead* aResponseHead,
4548 const nsACString& aRemove) {
4549 nsAutoCString buf;
4550 (void)aResponseHead->GetHeader(nsHttp::Vary, buf);
4551
4552 bool remove = false;
4553 for (const nsACString& token :
4554 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4555 if (token.EqualsIgnoreCase(aRemove)) {
4556 // Need to build a new string without aRemove
4557 remove = true;
4558 break;
4559 }
4560 }
4561 if (!remove) {
4562 return;
4563 }
4564 nsAutoCString newValue;
4565 for (const nsACString& token :
4566 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4567 if (!token.EqualsIgnoreCase(aRemove)) {
4568 if (!newValue.IsEmpty()) {
4569 newValue += ","_ns;
4570 }
4571 newValue += token;
4572 }
4573 }
4574 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)
4575 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)
;
4576 (void)aResponseHead->SetHeaderOverride(nsHttp::Vary, newValue);
4577}
4578
4579// We need to have an implementation of this function just so that we can keep
4580// all references to mCallOnResume of type nsHttpChannel: it's not OK in C++
4581// to set a member function ptr to a base class function.
4582void nsHttpChannel::HandleAsyncAbort() {
4583 HttpAsyncAborter<nsHttpChannel>::HandleAsyncAbort();
4584}
4585
4586//-----------------------------------------------------------------------------
4587// nsHttpChannel <byte-range>
4588//-----------------------------------------------------------------------------
4589
4590bool nsHttpChannel::IsResumable(int64_t partialLen, int64_t contentLength,
4591 bool ignoreMissingPartialLen) const {
4592 bool hasContentEncoding =
4593 mCachedResponseHead->HasHeader(nsHttp::Content_Encoding);
4594
4595 nsAutoCString etag;
4596 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, etag);
4597 bool hasWeakEtag = !etag.IsEmpty() && StringBeginsWith(etag, "W/"_ns);
4598
4599 return (partialLen < contentLength) &&
4600 (partialLen > 0 || ignoreMissingPartialLen) && !hasContentEncoding &&
4601 !hasWeakEtag && mCachedResponseHead->IsResumable() &&
4602 !LoadCustomConditionalRequest() && !mCachedResponseHead->NoStore();
4603}
4604
4605nsresult nsHttpChannel::MaybeSetupByteRangeRequest(
4606 int64_t partialLen, int64_t contentLength, bool ignoreMissingPartialLen) {
4607 // Be pesimistic
4608 StoreIsPartialRequest(false);
4609
4610 if (!IsResumable(partialLen, contentLength, ignoreMissingPartialLen)) {
4611 return NS_ERROR_NOT_RESUMABLE;
4612 }
4613
4614 // looks like a partial entry we can reuse; add If-Range
4615 // and Range headers.
4616 nsresult rv = SetupByteRangeRequest(partialLen);
4617 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4618 // Make the request unconditional again.
4619 UntieByteRangeRequest();
4620 }
4621
4622 return rv;
4623}
4624
4625nsresult nsHttpChannel::SetupByteRangeRequest(int64_t partialLen) {
4626 // cached content has been found to be partial, add necessary request
4627 // headers to complete cache entry.
4628
4629 // use strongest validator available...
4630 nsAutoCString val;
4631 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, val);
4632 if (val.IsEmpty()) {
4633 (void)mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
4634 }
4635 if (val.IsEmpty()) {
4636 // if we hit this code it means mCachedResponseHead->IsResumable() is
4637 // either broken or not being called.
4638 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"
, 4638); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no cache validator" ")"); do { MOZ_CrashSequence
(__null, 4638); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4639 StoreIsPartialRequest(false);
4640 return NS_ERROR_FAILURE;
4641 }
4642
4643 char buf[64];
4644 SprintfLiteral(buf, "bytes=%" PRId64"l" "d" "-", partialLen);
4645
4646 DebugOnly<nsresult> rv{};
4647 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(buf));
4648 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"
, 4648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4648); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4649 rv = mRequestHead.SetHeader(nsHttp::If_Range, val);
4650 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"
, 4650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4650); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4651 StoreIsPartialRequest(true);
4652
4653 return NS_OK;
4654}
4655
4656void nsHttpChannel::UntieByteRangeRequest() {
4657 DebugOnly<nsresult> rv{};
4658 rv = mRequestHead.ClearHeader(nsHttp::Range);
4659 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"
, 4659); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4660 rv = mRequestHead.ClearHeader(nsHttp::If_Range);
4661 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"
, 4661); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4661); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4662}
4663
4664nsresult nsHttpChannel::ProcessPartialContent(
4665 const std::function<nsresult(nsHttpChannel*, nsresult)>&
4666 aContinueProcessResponseFunc) {
4667 // ok, we've just received a 206
4668 //
4669 // we need to stream whatever data is in the cache out first, and then
4670 // pick up whatever data is on the wire, writing it into the cache.
4671
4672 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)
;
4673
4674 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"
, 4674); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4675 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"
, 4675); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4676
4677 // Check if the content-encoding we now got is different from the one we
4678 // got before
4679 nsAutoCString contentEncoding, cachedContentEncoding;
4680 // It is possible that there is not such headers
4681 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
4682 (void)mCachedResponseHead->GetHeader(nsHttp::Content_Encoding,
4683 cachedContentEncoding);
4684 if (nsCRT::strcasecmp(contentEncoding.get(), cachedContentEncoding.get()) !=
4685 0) {
4686 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
4687 return CallOnStartRequest();
4688 }
4689
4690 nsresult rv;
4691
4692 int64_t cachedContentLength = mCachedResponseHead->ContentLength();
4693 int64_t entitySize = mResponseHead->TotalEntitySize();
4694
4695 nsAutoCString contentRange;
4696 (void)mResponseHead->GetHeader(nsHttp::Content_Range, contentRange);
4697 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)
4698 ("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)
4699 "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)
4700 ", 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)
4701 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)
4702 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)
;
4703
4704 if ((entitySize >= 0) && (cachedContentLength >= 0) &&
4705 (entitySize != cachedContentLength)) {
4706 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)
4707 ("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)
4708 "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)
4709 "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)
4710 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)
;
4711
4712 mCacheEntry->AsyncDoom(nullptr);
4713 Cancel(NS_ERROR_CORRUPTED_CONTENT);
4714 return CallOnStartRequest();
4715 }
4716
4717 if (LoadConcurrentCacheAccess()) {
4718 // We started to read cached data sooner than its write has been done.
4719 // But the concurrent write has not finished completely, so we had to
4720 // do a range request. Now let the content coming from the network
4721 // be presented to consumers and also stored to the cache entry.
4722
4723 rv = InstallCacheListener(mLogicalOffset);
4724 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4725 } else {
4726 // suspend the current transaction
4727 rv = mTransactionPump->Suspend();
4728 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4729 }
4730
4731 // merge any new headers with the cached response headers
4732 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
4733
4734 // update the cached response head
4735 nsAutoCString head;
4736 mCachedResponseHead->Flatten(head, true);
4737 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
4738 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4739
4740 // make the cached response be the current response
4741 mResponseHead = std::move(mCachedResponseHead);
4742
4743 UpdateInhibitPersistentCachingFlag();
4744
4745 rv = UpdateExpirationTime();
4746 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4747
4748 // notify observers interested in looking at a response that has been
4749 // merged with any cached headers (http-on-examine-merged-response).
4750 gHttpHandler->OnExamineMergedResponse(this);
4751
4752 if (LoadConcurrentCacheAccess()) {
4753 StoreCachedContentIsPartial(false);
4754 // Leave the ConcurrentCacheAccess flag set, we want to use it
4755 // to prevent duplicate OnStartRequest call on the target listener
4756 // in case this channel is canceled before it gets its OnStartRequest
4757 // from the http transaction.
4758 return rv;
4759 }
4760
4761 // Now we continue reading the network response.
4762 // the cached content is valid, although incomplete.
4763 StoreCachedContentIsValid(CachedContentValidity::Valid);
4764 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
4765 nsresult rv = self->ReadFromCache();
4766 return aContinueProcessResponseFunc(self, rv);
4767 });
4768}
4769
4770nsresult nsHttpChannel::OnDoneReadingPartialCacheEntry(bool* streamDone) {
4771 nsresult rv;
4772
4773 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)
;
4774
4775 // by default, assume we would have streamed all data or failed...
4776 *streamDone = true;
4777
4778 // setup cache listener to append to cache entry
4779 int64_t size;
4780 rv = mCacheEntry->GetDataSize(&size);
4781 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4782
4783 rv = InstallCacheListener(size);
4784 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4785
4786 // Entry is valid, do it now, after the output stream has been opened,
4787 // otherwise when done earlier, pending readers would consider the cache
4788 // entry still as partial (CacheEntry::GetDataSize would return the partial
4789 // data size) and consumers would do the conditional request again.
4790 rv = mCacheEntry->SetValid();
4791 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4792
4793 // need to track the logical offset of the data being sent to our listener
4794 mLogicalOffset = size;
4795
4796 // we're now completing the cached content, so we can clear this flag.
4797 // this puts us in the state of a regular download.
4798 StoreCachedContentIsPartial(false);
4799 // The cache input stream pump is finished, we do not need it any more.
4800 // (see bug 1313923)
4801 mCachePump = nullptr;
4802
4803 // resume the transaction if it exists, otherwise the pipe contained the
4804 // remaining part of the document and we've now streamed all of the data.
4805 if (mTransactionPump) {
4806 rv = mTransactionPump->Resume();
4807 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) *streamDone = false;
4808 } else {
4809 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"
, 4809); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no transaction" ")"); do { MOZ_CrashSequence
(__null, 4809); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4810 }
4811 return rv;
4812}
4813
4814//-----------------------------------------------------------------------------
4815// nsHttpChannel <cache>
4816//-----------------------------------------------------------------------------
4817
4818bool nsHttpChannel::ShouldBypassProcessNotModified() {
4819 if (LoadCustomConditionalRequest()) {
4820 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)
;
4821 return true;
4822 }
4823
4824 if (!mDidReval) {
4825 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)
4826 ("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)
4827 "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)
;
4828 return true;
4829 }
4830
4831 return false;
4832}
4833
4834void nsHttpChannel::MaybeGenerateNELReport() {
4835 if (!StaticPrefs::network_http_network_error_logging_enabled()) {
4836 return;
4837 }
4838
4839 nsCOMPtr<nsINetworkErrorReport> report;
4840 if (nsCOMPtr<nsINetworkErrorLogging> nel =
4841 components::NetworkErrorLogging::Service()) {
4842 nel->GenerateNELReport(this, getter_AddRefs(report));
4843 }
4844
4845 mReportedNEL = true;
4846
4847 // https://www.w3.org/TR/2023/WD-network-error-logging-20231005/#deliver-a-network-report
4848 // 4. Generate a network report given these parameters:
4849 // type: network-error
4850 // url
4851 // user_agent
4852 // body
4853
4854 if (!report) {
4855 return;
4856 }
4857
4858 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
4859 if (!ssm) {
4860 return;
4861 }
4862
4863 nsCOMPtr<nsIPrincipal> channelPrincipal;
4864 ssm->GetChannelResultPrincipal(this, getter_AddRefs(channelPrincipal));
4865 if (!channelPrincipal) {
4866 return;
4867 }
4868
4869 nsAutoCString body;
4870 nsAutoString group;
4871 nsAutoString url;
4872
4873 report->GetBody(body);
4874 report->GetGroup(group);
4875 report->GetUrl(url);
4876
4877 nsAutoCString endpointURL;
4878 ReportingHeader::GetEndpointForReportIncludeSubdomains(
4879 group, channelPrincipal, /* includeSubdomains */ true, endpointURL);
4880 if (endpointURL.IsEmpty()) {
4881 return;
4882 }
4883
4884 ReportDeliver::ReportData data;
4885 data.mType = u"network-error"_ns;
4886 data.mGroupName = std::move(group);
4887 data.mURL = std::move(url);
4888 data.mFailures = 0;
4889 data.mCreationTime = TimeStamp::Now();
4890
4891 data.mPrincipal = std::move(channelPrincipal);
4892 data.mEndpointURL = std::move(endpointURL);
4893 data.mReportBodyJSON = std::move(body);
4894 nsAutoCString userAgent;
4895 // XXX(valentin): Should this be the potentially user set value of the header
4896 // or the current value of user_agent from http handler?
4897 (void)mRequestHead.GetHeader(nsHttp::User_Agent, userAgent);
4898 data.mUserAgent = NS_ConvertUTF8toUTF16(userAgent);
4899
4900 // Enqueue the report to be delivered by the reporting API
4901 ReportDeliver::Fetch(data);
4902}
4903
4904nsresult nsHttpChannel::ProcessNotModified(
4905 const std::function<nsresult(nsHttpChannel*, nsresult)>&
4906 aContinueProcessResponseFunc) {
4907 nsresult rv;
4908
4909 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)
;
4910
4911 // Assert ShouldBypassProcessNotModified() has been checked before call to
4912 // ProcessNotModified().
4913 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"
, 4913); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ShouldBypassProcessNotModified()"
")"); do { MOZ_CrashSequence(__null, 4913); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4914
4915 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", 4915
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedResponseHead"
")"); do { MOZ_CrashSequence(__null, 4915); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4916 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"
, 4916); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 4916); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4917 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", 4917
); return NS_ERROR_UNEXPECTED; } } while (false)
;
4918
4919 // If the 304 response contains a Last-Modified different than the
4920 // one in our cache that is pretty suspicious and is, in at least the
4921 // case of bug 716840, a sign of the server having previously corrupted
4922 // our cache with a bad response. Take the minor step here of just dooming
4923 // that cache entry so there is a fighting chance of getting things on the
4924 // right track.
4925
4926 nsAutoCString lastModifiedCached;
4927 nsAutoCString lastModified304;
4928
4929 rv =
4930 mCachedResponseHead->GetHeader(nsHttp::Last_Modified, lastModifiedCached);
4931 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4932 rv = mResponseHead->GetHeader(nsHttp::Last_Modified, lastModified304);
4933 }
4934
4935 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !lastModified304.Equals(lastModifiedCached)) {
4936 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)
4937 ("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)
4938 "[%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)
4939 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)
;
4940
4941 mCacheEntry->AsyncDoom(nullptr);
4942 glean::http::cache_lm_inconsistent
4943 .EnumGet(glean::http::CacheLmInconsistentLabel::eTrue)
4944 .Add();
4945 }
4946
4947 // merge any new headers with the cached response headers
4948 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
4949
4950 // update the cached response head
4951 nsAutoCString head;
4952 mCachedResponseHead->Flatten(head, true);
4953 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
4954 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4955
4956 if (LoadUsedNetwork() && !mReportedNEL) {
4957 MaybeGenerateNELReport();
4958 }
4959
4960 // make the cached response be the current response
4961 mResponseHead = std::move(mCachedResponseHead);
4962
4963 UpdateInhibitPersistentCachingFlag();
4964
4965 rv = UpdateExpirationTime();
4966 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4967
4968 rv = AddCacheEntryHeaders(mCacheEntry, false);
4969 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4970
4971 // notify observers interested in looking at a reponse that has been
4972 // merged with any cached headers
4973 gHttpHandler->OnExamineMergedResponse(this);
4974
4975 StoreCachedContentIsValid(CachedContentValidity::Valid);
4976
4977 // Tell other consumers the entry is OK to use
4978 rv = mCacheEntry->SetValid();
4979 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4980
4981 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
4982 nsresult rv = self->ReadFromCache();
4983 return aContinueProcessResponseFunc(self, rv);
4984 });
4985}
4986
4987// Determines if a request is a byte range request for a subrange,
4988// i.e. is a byte range request, but not a 0- byte range request.
4989static bool IsSubRangeRequest(nsHttpRequestHead& aRequestHead) {
4990 nsAutoCString byteRange;
4991 if (NS_FAILED(aRequestHead.GetHeader(nsHttp::Range, byteRange))((bool)(__builtin_expect(!!(NS_FAILED_impl(aRequestHead.GetHeader
(nsHttp::Range, byteRange))), 0)))
) {
4992 return false;
4993 }
4994
4995 if (byteRange.EqualsLiteral("bytes=0-")) {
4996#ifndef ANDROID
4997 glean::network::byte_range_request.Get("cacheable"_ns).Add(1);
4998#endif
4999 return false;
5000 }
5001#ifndef ANDROID
5002 glean::network::byte_range_request.Get("not_cacheable"_ns).Add(1);
5003#endif
5004 return true;
5005}
5006
5007nsresult nsHttpChannel::OpenCacheEntry(bool isHttps) {
5008 // Drop this flag here
5009 StoreConcurrentCacheAccess(0);
5010
5011 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)
;
5012
5013 // make sure we're not abusing this function
5014 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"
, 5014); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheEntry"
") (" "cache entry already open" ")"); do { MOZ_CrashSequence
(__null, 5014); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5015 if (!mRequestHead.IsGet() && !mRequestHead.IsHead() &&
5016 !mRequestHead.IsPost() && !mRequestHead.IsPatch()) {
5017 // don't use the cache for other types of requests
5018 return NS_OK;
5019 }
5020
5021 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", 5021
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPostID > 0" ")"
); do { MOZ_CrashSequence(__null, 5021); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5022
5023 return OpenCacheEntryInternal(isHttps);
5024}
5025
5026nsresult nsHttpChannel::OpenCacheEntryInternal(bool isHttps) {
5027 nsresult rv;
5028
5029 if (LoadResuming()) {
5030 // We don't support caching for requests initiated
5031 // via nsIResumableChannel.
5032 return NS_OK;
5033 }
5034
5035 // Don't cache byte range requests which are subranges, only cache 0-
5036 // byte range requests.
5037 if (IsSubRangeRequest(mRequestHead)) {
5038 return NS_OK;
5039 }
5040
5041 // Handle correctly WaitForCacheEntry
5042 AutoCacheWaitFlags waitFlags(this);
5043
5044 nsAutoCString cacheKey;
5045
5046 nsCOMPtr<nsICacheStorage> cacheStorage;
5047 mCacheEntryURI = mURI;
5048
5049 uint32_t cacheEntryOpenFlags;
5050 bool offline = gIOService->IsOffline();
5051
5052 RefPtr<mozilla::dom::BrowsingContext> bc;
5053 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
5054
5055 nsAutoCString cacheControlRequestHeader;
5056 (void)mRequestHead.GetHeader(nsHttp::Cache_Control,
5057 cacheControlRequestHeader);
5058 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
5059 if (cacheControlRequest.NoStore()) {
5060 return NS_OK;
5061 }
5062
5063 bool forceOffline = bc && bc->Top()->GetForceOffline();
5064 if (offline || (mLoadFlags & INHIBIT_CACHING) || forceOffline) {
5065 if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
&&
5066 !offline && !forceOffline) {
5067 return NS_OK;
5068 }
5069 cacheEntryOpenFlags = nsICacheStorage::OPEN_READONLY;
5070 StoreCacheEntryIsReadOnly(true);
5071 } else if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
5072 cacheEntryOpenFlags = nsICacheStorage::OPEN_TRUNCATE;
5073 } else {
5074 cacheEntryOpenFlags =
5075 nsICacheStorage::OPEN_NORMALLY | nsICacheStorage::CHECK_MULTITHREADED;
5076 }
5077
5078 // Remember the request is a custom conditional request so that we can
5079 // process any 304 response correctly.
5080 StoreCustomConditionalRequest(
5081 mRequestHead.HasHeader(nsHttp::If_Modified_Since) ||
5082 mRequestHead.HasHeader(nsHttp::If_None_Match) ||
5083 mRequestHead.HasHeader(nsHttp::If_Unmodified_Since) ||
5084 mRequestHead.HasHeader(nsHttp::If_Match) ||
5085 mRequestHead.HasHeader(nsHttp::If_Range));
5086
5087 rv = GetCacheStorage(getter_AddRefs(cacheStorage));
5088 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"
, 5088); return rv; } } while (false)
;
5089
5090 if ((mClassOfService.Flags() & nsIClassOfService::Leader) ||
5091 (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)) {
5092 cacheEntryOpenFlags |= nsICacheStorage::OPEN_PRIORITY;
5093 }
5094
5095 // Only for backward compatibility with the old cache back end.
5096 // When removed, remove the flags and related code snippets.
5097 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
5098 cacheEntryOpenFlags |= nsICacheStorage::OPEN_BYPASS_IF_BUSY;
5099 }
5100
5101 if (mPostID) {
5102 mCacheIdExtension.AppendInt(mPostID);
5103 }
5104 if (LoadIsTRRServiceChannel()) {
5105 mCacheIdExtension.Append("TRR");
5106 }
5107 if (mRequestHead.IsHead()) {
5108 mCacheIdExtension.Append("HEAD");
5109 }
5110 bool isThirdParty = false;
5111 if (StaticPrefs::network_fetch_cache_partition_cross_origin() &&
5112 (NS_FAILED(mLoadInfo->TriggeringPrincipal()->IsThirdPartyChannel(((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
5113 this, &isThirdParty))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
||
5114 isThirdParty) &&
5115 (mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_FETCH ||
5116 mLoadInfo->InternalContentPolicyType() ==
5117 nsIContentPolicy::TYPE_XMLHTTPREQUEST ||
5118 mLoadInfo->InternalContentPolicyType() ==
5119 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_ASYNC ||
5120 mLoadInfo->InternalContentPolicyType() ==
5121 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_SYNC)) {
5122 mCacheIdExtension.Append("FETCH");
5123 }
5124
5125 mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY;
5126 mCacheQueueSizeWhenOpen =
5127 CacheStorageService::CacheQueueSize(mCacheOpenWithPriority);
5128
5129 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"
, 5129); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 5129); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5130 rv = cacheStorage->AsyncOpenURI(mCacheEntryURI, mCacheIdExtension,
5131 cacheEntryOpenFlags, this);
5132 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"
, 5132); return rv; } } while (false)
;
5133
5134 waitFlags.Keep(WAIT_FOR_CACHE_ENTRY);
5135
5136 return NS_OK;
5137}
5138
5139// We asked the cache for mCacheEntryURI, but the entry we got back may be
5140// stored under a different URL: on an exact-key miss the cache falls back to a
5141// No-Vary-Search secondary lookup, which can return a sibling entry whose URL
5142// is equivalent to ours under its No-Vary-Search header. Record which of the
5143// two happened, so that later code can tell whether the entry it holds is
5144// really ours to write to.
5145void nsHttpChannel::NoteCacheEntryKeyMatch(nsICacheEntry* aEntry) {
5146 StoreCacheEntryIsNoVarySearchMatch(false);
5147
5148 if (!aEntry || !mCacheEntryURI) {
5149 return;
5150 }
5151
5152 // Normalize the same way CacheStorage::AsyncOpenURI did to build the key.
5153 nsCOMPtr<nsIURI> noRefURI;
5154 nsAutoCString spec;
5155 if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetURIWithoutRef
(mCacheEntryURI, getter_AddRefs(noRefURI)))), 0)))
5156 NS_GetURIWithoutRef(mCacheEntryURI, getter_AddRefs(noRefURI)))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetURIWithoutRef
(mCacheEntryURI, getter_AddRefs(noRefURI)))), 0)))
||
5157 NS_FAILED(noRefURI->GetAsciiSpec(spec))((bool)(__builtin_expect(!!(NS_FAILED_impl(noRefURI->GetAsciiSpec
(spec))), 0)))
) {
5158 return;
5159 }
5160
5161 nsAutoCString key;
5162 if (NS_FAILED(aEntry->GetKey(key))((bool)(__builtin_expect(!!(NS_FAILED_impl(aEntry->GetKey(
key))), 0)))
) {
5163 return;
5164 }
5165
5166 if (!key.Equals(spec)) {
5167 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)
5168 ("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)
5169 "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)
5170 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)
;
5171 StoreCacheEntryIsNoVarySearchMatch(true);
5172 }
5173}
5174
5175// Picks the storage matching the channel's persistence flags as they stand
5176// right now. Called both when first opening the entry and when replacing an
5177// alias entry later, by which point a no-store response may have set
5178// INHIBIT_PERSISTENT_CACHING and the replacement must be memory-only.
5179nsresult nsHttpChannel::GetCacheStorage(nsICacheStorage** aStorage) {
5180 nsCOMPtr<nsICacheStorageService> service(components::CacheStorage::Service());
5181 if (!service) {
5182 return NS_ERROR_NOT_AVAILABLE;
5183 }
5184
5185 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
5186 if (!info) {
5187 return NS_ERROR_FAILURE;
5188 }
5189
5190 if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
5191 return service->MemoryCacheStorage(info, // ? choose app cache as well...
5192 aStorage);
5193 }
5194 if (LoadPinCacheContent()) {
5195 return service->PinningCacheStorage(info, aStorage);
5196 }
5197 return service->DiskCacheStorage(info, aStorage);
5198}
5199
5200// Called before anything is written to mCacheEntry. When the entry we hold was
5201// found through No-Vary-Search it is stored under a different URL, and this
5202// response describes mCacheEntryURI only, so writing to it would put our
5203// content under someone else's key. Open a fresh entry of our own instead.
5204// Releasing the last handle on the borrowed entry reverts it from REVALIDATING
5205// back to READY, leaving its own representation untouched.
5206nsresult nsHttpChannel::MaybeReplaceNoVarySearchAliasEntry() {
5207 if (!LoadCacheEntryIsNoVarySearchMatch() || !mCacheEntry ||
5208 LoadCacheEntryIsReadOnly()) {
5209 return NS_OK;
5210 }
5211
5212 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)
;
5213
5214 nsCOMPtr<nsICacheStorage> storage;
5215 nsresult rv = GetCacheStorage(getter_AddRefs(storage));
5216 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5217 rv = storage->OpenTruncate(mCacheEntryURI, mCacheIdExtension,
5218 getter_AddRefs(mCacheEntry));
5219 }
5220
5221 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5222 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)
5223 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)
;
5224 mCacheEntry = nullptr;
5225 return rv;
5226 }
5227
5228 // We now hold an entry keyed on mCacheEntryURI, so it is ours to write to.
5229 StoreCacheEntryIsNoVarySearchMatch(false);
5230 StoreCacheEntryIsWriteOnly(true);
5231 // The alt-data belonged to the entry we just let go of.
5232 mAvailableCachedAltDataType.Truncate();
5233 StoreDeliveringAltData(false);
5234
5235 return NS_OK;
5236}
5237
5238nsresult nsHttpChannel::CheckPartial(nsICacheEntry* aEntry, int64_t* aSize,
5239 int64_t* aContentLength) {
5240 return nsHttp::CheckPartial(
5241 aEntry, aSize, aContentLength,
5242 mCachedResponseHead ? mCachedResponseHead.get() : mResponseHead.get());
5243}
5244
5245void nsHttpChannel::UntieValidationRequest() {
5246 DebugOnly<nsresult> rv{};
5247 // Make the request unconditional again.
5248 rv = mRequestHead.ClearHeader(nsHttp::If_Modified_Since);
5249 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"
, 5249); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5249); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5250 rv = mRequestHead.ClearHeader(nsHttp::If_None_Match);
5251 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"
, 5251); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5251); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5252 rv = mRequestHead.ClearHeader(nsHttp::ETag);
5253 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"
, 5253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5253); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5254}
5255
5256NS_IMETHODIMPnsresult
5257nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, uint32_t* aResult) {
5258 nsresult rv = NS_OK;
5259
5260 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnCacheEntryCheck", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject5261( "nsHttpChannel::OnCacheEntryCheck"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
5261 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject5261( "nsHttpChannel::OnCacheEntryCheck"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
5262 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)
5263 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)
;
5264
5265 NoteCacheEntryKeyMatch(entry);
5266
5267 nsAutoCString cacheControlRequestHeader;
5268 (void)mRequestHead.GetHeader(nsHttp::Cache_Control,
5269 cacheControlRequestHeader);
5270 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
5271
5272 if (cacheControlRequest.NoStore()) {
5273 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)
5274 ("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)
5275 "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)
;
5276 *aResult = ENTRY_NOT_WANTED;
5277 return NS_OK;
5278 }
5279
5280 // Be pessimistic: assume the cache entry has no useful data.
5281 *aResult = ENTRY_WANTED;
5282 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5283
5284 nsCString buf;
5285
5286 // Get the method that was used to generate the cached response
5287 rv = entry->GetMetaDataElement("request-method", getter_Copies(buf));
5288 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"
, 5288); return rv; } } while (false)
;
5289
5290 bool methodWasHead = buf.EqualsLiteral("HEAD");
5291 bool methodWasGet = buf.EqualsLiteral("GET");
5292
5293 if (methodWasHead) {
5294 // The cached response does not contain an entity. We can only reuse
5295 // the response if the current request is also HEAD.
5296 if (!mRequestHead.IsHead()) {
5297 *aResult = ENTRY_NOT_WANTED;
5298 return NS_OK;
5299 }
5300 }
5301 buf.Adopt(nullptr);
5302
5303 // We'll need this value in later computations...
5304 uint32_t lastModifiedTime;
5305 rv = entry->GetLastModified(&lastModifiedTime);
5306 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"
, 5306); return rv; } } while (false)
;
5307
5308 // Determine if this is the first time that this cache entry
5309 // has been accessed during this session.
5310 bool fromPreviousSession =
5311 (gHttpHandler->SessionStartTime() > lastModifiedTime);
5312
5313 // Get the cached HTTP response headers
5314 mCachedResponseHead = MakeUnique<nsHttpResponseHead>();
5315
5316 rv = nsHttp::GetHttpResponseHeadFromCacheEntry(entry,
5317 mCachedResponseHead.get());
5318 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"
, 5318); return rv; } } while (false)
;
5319
5320 // Purge stale cache entries that have dcb/dcz Content-Encoding in their
5321 // metadata. These were written by early compression dictionary code that
5322 // failed to clear Content-Encoding before writing cache metadata. The data
5323 // body is decompressed but the header is wrong; serving such entries would
5324 // cause crashes in content processes. Doom and re-fetch from network.
5325 {
5326 nsAutoCString cachedEncoding;
5327 (void)mCachedResponseHead->GetHeader(nsHttp::Content_Encoding,
5328 cachedEncoding);
5329 if (cachedEncoding.LowerCaseFindASCII("dcb") != -1 ||
5330 cachedEncoding.LowerCaseFindASCII("dcz") != -1) {
5331 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)
5332 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)
;
5333 glean::http3::stale_dcb_dcz_cache_entries_purged.Add(1);
5334 entry->AsyncDoom(nullptr);
5335 *aResult = ENTRY_NOT_WANTED;
5336 return NS_OK;
5337 }
5338 }
5339
5340 bool isCachedRedirect = WillRedirect(*mCachedResponseHead);
5341
5342 // Do not return 304 responses from the cache, and also do not return
5343 // any other non-redirect 3xx responses from the cache (see bug 759043).
5344 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"
, 5345); return NS_ERROR_ABORT; } } while (false)
5345 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"
, 5345); return NS_ERROR_ABORT; } } while (false)
;
5346
5347 if (mCachedResponseHead->NoStore() && LoadCacheEntryIsReadOnly()) {
5348 // This prevents loading no-store responses when navigating back
5349 // while the browser is set to work offline.
5350 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)
;
5351 mLoadFlags |= nsIRequest::INHIBIT_CACHING;
5352 }
5353
5354 // Don't bother to validate items that are read-only,
5355 // unless they are read-only because of INHIBIT_CACHING
5356 if ((LoadCacheEntryIsReadOnly() &&
5357 !(mLoadFlags & nsIRequest::INHIBIT_CACHING))) {
5358 int64_t size, contentLength;
5359 rv = CheckPartial(entry, &size, &contentLength);
5360 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"
, 5360); return rv; } } while (false)
;
5361
5362 if (contentLength != int64_t(-1) && contentLength != size) {
5363 *aResult = ENTRY_NOT_WANTED;
5364 return NS_OK;
5365 }
5366
5367 rv = OpenCacheInputStream(entry, true);
5368 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5369 StoreCachedContentIsValid(CachedContentValidity::Valid);
5370 }
5371 return rv;
5372 }
5373
5374 bool wantCompleteEntry = false;
5375
5376 if (!methodWasHead && !isCachedRedirect) {
5377 // If the cached content-length is set and it does not match the data
5378 // size of the cached content, then the cached response is partial...
5379 // either we need to issue a byte range request or we need to refetch
5380 // the entire document.
5381 //
5382 // We exclude redirects from this check because we (usually) strip the
5383 // entity when we store the cache entry, and even if we didn't, we
5384 // always ignore a cached redirect's entity anyway. See bug 759043.
5385 int64_t size, contentLength;
5386 rv = CheckPartial(entry, &size, &contentLength);
5387 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"
, 5387); return rv; } } while (false)
;
5388
5389 if (LoadCacheEntryIsNoVarySearchMatch() &&
5390 (size == int64_t(-1) ||
5391 (contentLength != int64_t(-1) && contentLength != size))) {
5392 // Completing this entry means appending our bytes to content stored
5393 // under a different URL, and unlike a full response we cannot divert
5394 // that to an entry of our own: the range request only makes sense
5395 // against what is already there. Refetch from scratch instead.
5396 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)
;
5397 *aResult = ENTRY_NOT_WANTED;
5398 return NS_OK;
5399 }
5400
5401 if (size == int64_t(-1)) {
5402 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)
;
5403 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
5404 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)
5405 (" 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)
5406 "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)
;
5407
5408 *aResult = ENTRY_NOT_WANTED;
5409 return NS_OK;
5410 }
5411
5412 // Ignore !(size > 0) from the resumability condition
5413 if (!IsResumable(size, contentLength, true)) {
5414 if (IsNavigation()) {
5415 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)
5416 (" 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)
5417 "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)
;
5418 *aResult = ENTRY_NOT_WANTED;
5419 return NS_OK;
5420 }
5421
5422 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)
5423 (" 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)
5424 "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)
;
5425
5426 wantCompleteEntry = true;
5427 } else {
5428 StoreConcurrentCacheAccess(1);
5429 }
5430 } else if (contentLength != int64_t(-1) && contentLength != size) {
5431 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)
5432 ("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)
5433 "[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)
5434 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)
;
5435
5436 rv = MaybeSetupByteRangeRequest(size, contentLength);
5437 StoreCachedContentIsPartial(NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest());
5438 if (LoadCachedContentIsPartial()) {
5439 rv = OpenCacheInputStream(entry, false);
5440 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5441 UntieByteRangeRequest();
5442 return rv;
5443 }
5444
5445 *aResult = ENTRY_NEEDS_REVALIDATION;
5446 return NS_OK;
5447 }
5448
5449 if (size == 0 && LoadCacheOnlyMetadata()) {
5450 // Don't break cache entry load when the entry's data size
5451 // is 0 and CacheOnlyMetadata flag is set. In that case we
5452 // want to proceed since the LOAD_ONLY_IF_MODIFIED flag is
5453 // also set.
5454 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", 5454
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadFlags & LOAD_ONLY_IF_MODIFIED"
")"); do { MOZ_CrashSequence(__null, 5454); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5455 } else {
5456 return rv;
5457 }
5458 }
5459 }
5460
5461 bool isHttps = mURI->SchemeIs("https");
5462
5463 bool doValidation = false;
5464 bool doBackgroundValidation = false;
5465 bool canAddImsHeader = true;
5466
5467 bool isForcedValid = false;
5468 entry->GetIsForcedValid(&isForcedValid);
5469
5470 bool weaklyFramed, isImmutable;
5471 nsHttp::DetermineFramingAndImmutability(entry, mCachedResponseHead.get(),
5472 isHttps, &weaklyFramed, &isImmutable);
5473
5474 // Cached entry is not the entity we request (see bug #633743)
5475 if (ResponseWouldVary(entry)) {
5476 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)
;
5477 canAddImsHeader = false;
5478 doValidation = true;
5479 } else {
5480 if (mCachedResponseHead->ExpiresInPast() ||
5481 mCachedResponseHead->MustValidateIfExpired()) {
5482 }
5483 doValidation = nsHttp::ValidationRequired(
5484 isForcedValid, mCachedResponseHead.get(), mLoadFlags,
5485 LoadAllowStaleCacheContent(), LoadForceValidateCacheContent(),
5486 isImmutable, LoadCustomConditionalRequest(), mRequestHead, entry,
5487 cacheControlRequest, fromPreviousSession, &doBackgroundValidation);
5488 }
5489
5490 nsAutoCString requestedETag;
5491 if (!doValidation &&
5492 NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::If_Match, requestedETag))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::If_Match, requestedETag))), 1)))
&&
5493 (methodWasGet || methodWasHead)) {
5494 nsAutoCString cachedETag;
5495 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, cachedETag);
5496 if (!cachedETag.IsEmpty() && (StringBeginsWith(cachedETag, "W/"_ns) ||
5497 !requestedETag.Equals(cachedETag))) {
5498 // User has defined If-Match header, if the cached entry is not
5499 // matching the provided header value or the cached ETag is weak,
5500 // force validation.
5501 doValidation = true;
5502 }
5503 }
5504
5505 // Previous error should not be propagated.
5506 rv = NS_OK;
5507
5508 if (!doValidation) {
5509 //
5510 // Check the authorization headers used to generate the cache entry.
5511 // We must validate the cache entry if:
5512 //
5513 // 1) the cache entry was generated prior to this session w/
5514 // credentials (see bug 103402).
5515 // 2) the cache entry was generated w/o credentials, but would now
5516 // require credentials (see bug 96705).
5517 //
5518 // NOTE: this does not apply to proxy authentication.
5519 //
5520 entry->GetMetaDataElement("auth", getter_Copies(buf));
5521 doValidation =
5522 (fromPreviousSession && !buf.IsEmpty()) ||
5523 (buf.IsEmpty() && mRequestHead.HasHeader(nsHttp::Authorization));
5524 }
5525
5526 // Bug #561276: We maintain a chain of cache-keys which returns cached
5527 // 3xx-responses (redirects) in order to detect cycles. If a cycle is
5528 // found, ignore the cached response and hit the net. Otherwise, use
5529 // the cached response and add the cache-key to the chain. Note that
5530 // a limited number of redirects (cached or not) is allowed and is
5531 // enforced independently of this mechanism
5532 if (!doValidation && isCachedRedirect) {
5533 nsAutoCString cacheKey;
5534 rv = GenerateCacheKey(mPostID, cacheKey);
5535 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"
, 5535); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5535); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5536
5537 auto redirectedCachekeys = mRedirectedCachekeys.Lock();
5538 auto& ref = redirectedCachekeys.ref();
5539 if (!ref) {
5540 ref = MakeUnique<nsTArray<nsCString>>();
5541 } else if (ref->Contains(cacheKey)) {
5542 doValidation = true;
5543 }
5544
5545 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)
5546 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)
;
5547
5548 // Append cacheKey if not in the chain already
5549 if (!doValidation) {
5550 ref->AppendElement(cacheKey);
5551 }
5552 }
5553
5554 StoreCachedContentIsValid(!doValidation ? CachedContentValidity::Valid
5555 : CachedContentValidity::Invalid);
5556
5557 if (isForcedValid) {
5558 // Telemetry value is only useful if this was a prefetched item
5559 if (!doValidation) {
5560 // Could have gotten to a funky state with some of the if chain above
5561 // and in nsHttp::ValidationRequired. Make sure we get it right here.
5562 entry->MarkForcedValidUse();
5563 }
5564 }
5565
5566 if (doValidation) {
5567 //
5568 // now, we are definitely going to issue a HTTP request to the server.
5569 // make it conditional if possible.
5570 //
5571 // do not attempt to validate no-store content, since servers will not
5572 // expect it to be cached. (we only keep it in our cache for the
5573 // purposes of back/forward, etc.)
5574 //
5575 // the request method MUST be either GET or HEAD (see bug 175641) and
5576 // the cached response code must be < 400
5577 //
5578 // the cached content must not be weakly framed
5579 //
5580 // do not override conditional headers when consumer has defined its own
5581 if (!mCachedResponseHead->NoStore() &&
5582 (mRequestHead.IsGet() || mRequestHead.IsHead()) &&
5583 !LoadCustomConditionalRequest() && !weaklyFramed &&
5584 (mCachedResponseHead->Status() < 400)) {
5585 if (LoadConcurrentCacheAccess()) {
5586 // In case of concurrent read and also validation request we
5587 // must wait for the current writer to close the output stream
5588 // first. Otherwise, when the writer's job would have been interrupted
5589 // before all the data were downloaded, we'd have to do a range request
5590 // which would be a second request in line during this channel's
5591 // life-time. nsHttpChannel is not designed to do that, so rather
5592 // turn off concurrent read and wait for entry's completion.
5593 // Then only re-validation or range-re-validation request will go out.
5594 StoreConcurrentCacheAccess(0);
5595 // This will cause that OnCacheEntryCheck is called again with the same
5596 // entry after the writer is done.
5597 wantCompleteEntry = true;
5598 } else {
5599 nsAutoCString val;
5600 // Add If-Modified-Since header if a Last-Modified was given
5601 // and we are allowed to do this (see bugs 510359 and 269303)
5602 if (canAddImsHeader) {
5603 (void)mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
5604 if (!val.IsEmpty()) {
5605 rv = mRequestHead.SetHeader(nsHttp::If_Modified_Since, val);
5606 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"
, 5606); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5606); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5607 }
5608 }
5609 // Add If-None-Match header if an ETag was given in the response
5610 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, val);
5611 if (!val.IsEmpty()) {
5612 rv = mRequestHead.SetHeader(nsHttp::If_None_Match, val);
5613 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"
, 5613); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5613); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5614 }
5615 mDidReval = true;
5616 }
5617 }
5618 }
5619
5620 bool valid = CachedContentIsValid();
5621 if (valid || mDidReval) {
5622 rv = OpenCacheInputStream(entry, valid);
5623 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5624 // If we can't get the entity then we have to act as though we
5625 // don't have the cache entry.
5626 if (mDidReval) {
5627 UntieValidationRequest();
5628 mDidReval = false;
5629 }
5630 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5631 }
5632 }
5633
5634 if (mDidReval) {
5635 *aResult = ENTRY_NEEDS_REVALIDATION;
5636 } else if (wantCompleteEntry) {
5637 *aResult = RECHECK_AFTER_WRITE_FINISHED;
5638 } else {
5639 *aResult = ENTRY_WANTED;
5640
5641 if (doBackgroundValidation) {
5642 PerformBackgroundCacheRevalidation();
5643 }
5644 }
5645
5646 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)
5647 ("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)
5648 "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)
5649 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)
;
5650 return rv;
5651}
5652
5653NS_IMETHODIMPnsresult
5654nsHttpChannel::OnCacheEntryAvailable(nsICacheEntry* entry, bool aNew,
5655 nsresult status) {
5656 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", 5656
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 5656); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5657
5658 nsresult rv;
5659
5660 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnCacheEntryAvailable", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject5661( "nsHttpChannel::OnCacheEntryAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
5661 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject5661( "nsHttpChannel::OnCacheEntryAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
5662 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)
5663 ("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)
5664 "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)
5665 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)
;
5666
5667 // The cache callback arrived (or we're tearing down); the backstop timer is
5668 // no longer needed.
5669 CancelCacheWaitTimer();
5670
5671 // if the channel's already fired onStopRequest, then we should ignore
5672 // this event.
5673 if (!LoadIsPending()) {
5674 mCacheInputStream.CloseAndRelease();
5675 return NS_OK;
5676 }
5677
5678 // If the backstop already fired we gave up on the cache and raced to the
5679 // network; ignore this late callback so we don't reprocess the entry.
5680 if (mCacheWaitTimedOut) {
5681 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)
5682 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)
;
5683 mCacheInputStream.CloseAndRelease();
5684 return NS_OK;
5685 }
5686
5687 rv = OnCacheEntryAvailableInternal(entry, aNew, status);
5688 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5689 CloseCacheEntry(false);
5690 (void)AsyncAbort(rv);
5691 }
5692
5693 return NS_OK;
5694}
5695
5696nsresult nsHttpChannel::OnCacheEntryAvailableInternal(nsICacheEntry* entry,
5697 bool aNew,
5698 nsresult status) {
5699 nsresult rv;
5700
5701 if (mCanceled) {
5702 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)
5703 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)
;
5704 return mStatus;
5705 }
5706
5707 rv = OnNormalCacheEntryAvailable(entry, aNew, status);
5708
5709 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
5710 return NS_ERROR_DOCUMENT_NOT_CACHED;
5711 }
5712
5713 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5714 return rv;
5715 }
5716
5717 // We may be waiting for more callbacks...
5718 if (AwaitingCacheCallbacks()) {
5719 return NS_OK;
5720 }
5721
5722 return TriggerNetwork();
5723}
5724
5725nsresult nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntry* aEntry,
5726 bool aNew,
5727 nsresult aEntryStatus) {
5728 StoreWaitForCacheEntry(LoadWaitForCacheEntry() & ~WAIT_FOR_CACHE_ENTRY);
5729
5730 if (NS_FAILED(aEntryStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aEntryStatus)), 0)
))
|| aNew) {
5731 // Make sure this flag is dropped. It may happen the entry is doomed
5732 // between OnCacheEntryCheck and OnCacheEntryAvailable.
5733 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5734
5735 // From the same reason remove any conditional headers added
5736 // in OnCacheEntryCheck.
5737 if (mDidReval) {
5738 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)
;
5739 UntieValidationRequest();
5740 mDidReval = false;
5741 }
5742
5743 if (LoadCachedContentIsPartial()) {
5744 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)
;
5745 UntieByteRangeRequest();
5746 StoreCachedContentIsPartial(false);
5747 }
5748
5749 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
5750 // if this channel is only allowed to pull from the cache, then
5751 // we must fail if we were unable to open a cache entry for read.
5752 return NS_ERROR_DOCUMENT_NOT_CACHED;
5753 }
5754 }
5755
5756 if (NS_SUCCEEDED(aEntryStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aEntryStatus)), 1
)))
) {
5757 mCacheEntry = aEntry;
5758 StoreCacheEntryIsWriteOnly(aNew);
5759 NoteCacheEntryKeyMatch(aEntry);
5760 }
5761
5762 return NS_OK;
5763}
5764
5765// Generates the proper cache-key for this instance of nsHttpChannel
5766nsresult nsHttpChannel::GenerateCacheKey(uint32_t postID,
5767 nsACString& cacheKey) {
5768 AssembleCacheKey(mSpec.get(), postID, cacheKey);
5769 return NS_OK;
5770}
5771
5772// Assembles a cache-key from the given pieces of information and |mLoadFlags|
5773void nsHttpChannel::AssembleCacheKey(const char* spec, uint32_t postID,
5774 nsACString& cacheKey) {
5775 cacheKey.Truncate();
5776
5777 if (mLoadFlags & LOAD_ANONYMOUS) {
5778 cacheKey.AssignLiteral("anon&");
5779 }
5780
5781 if (postID) {
5782 char buf[32];
5783 SprintfLiteral(buf, "id=%x&", postID);
5784 cacheKey.Append(buf);
5785 }
5786
5787 if (!cacheKey.IsEmpty()) {
5788 cacheKey.AppendLiteral("uri=");
5789 }
5790
5791 // Strip any trailing #ref from the URL before using it as the key
5792 const char* p = strchr(spec, '#');
5793 if (p) {
5794 cacheKey.Append(spec, p - spec);
5795 } else {
5796 cacheKey.Append(spec);
5797 }
5798}
5799
5800nsresult DoUpdateExpirationTime(nsHttpChannel* aSelf,
5801 nsICacheEntry* aCacheEntry,
5802 nsHttpResponseHead* aResponseHead,
5803 uint32_t& aExpirationTime) {
5804 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", 5804
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aExpirationTime == 0"
")"); do { MOZ_CrashSequence(__null, 5804); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5805 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"
, 5805); return NS_ERROR_FAILURE; } } while (false)
;
5806
5807 nsresult rv;
5808
5809 if (!aResponseHead->MustValidate()) {
5810 // For stale-while-revalidate we use expiration time as the absolute base
5811 // for calculation of the stale window absolute end time. Hence, when the
5812 // entry may be served w/o revalidation, we need a non-zero value for the
5813 // expiration time. Let's set it to |now|, which basicly means "expired",
5814 // same as when set to 0.
5815 uint32_t now = NowInSeconds()PRTimeToSeconds(PR_Now());
5816 aExpirationTime = now;
5817
5818 uint32_t freshnessLifetime = 0;
5819
5820 rv = aResponseHead->ComputeFreshnessLifetime(&freshnessLifetime);
5821 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5822
5823 if (freshnessLifetime > 0) {
5824 uint32_t currentAge = 0;
5825
5826 rv = aResponseHead->ComputeCurrentAge(now, aSelf->GetRequestTime(),
5827 &currentAge);
5828 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5829
5830 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)
5831 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)
;
5832
5833 if (freshnessLifetime > currentAge) {
5834 uint32_t timeRemaining = freshnessLifetime - currentAge;
5835 // be careful... now + timeRemaining may overflow
5836 if (now + timeRemaining < now) {
5837 aExpirationTime = uint32_t(-1);
5838 } else {
5839 aExpirationTime = now + timeRemaining;
5840 }
5841 }
5842 }
5843 }
5844
5845 rv = aCacheEntry->SetExpirationTime(aExpirationTime);
5846 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"
, 5846); return rv; } } while (false)
;
5847
5848 return rv;
5849}
5850
5851// UpdateExpirationTime is called when a new response comes in from the server.
5852// It updates the stored response-time and sets the expiration time on the
5853// cache entry.
5854//
5855// From section 13.2.4 of RFC2616, we compute expiration time as follows:
5856//
5857// timeRemaining = freshnessLifetime - currentAge
5858// expirationTime = now + timeRemaining
5859//
5860nsresult nsHttpChannel::UpdateExpirationTime() {
5861 uint32_t expirationTime = 0;
5862 nsresult rv = DoUpdateExpirationTime(this, mCacheEntry, mResponseHead.get(),
5863 expirationTime);
5864 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"
, 5864); return rv; } } while (false)
;
5865
5866 return NS_OK;
5867}
5868
5869nsresult nsHttpChannel::OpenCacheInputStream(nsICacheEntry* cacheEntry,
5870 bool startBuffering) {
5871 nsresult rv;
5872
5873 if (mURI->SchemeIs("https")) {
5874 rv = cacheEntry->GetSecurityInfo(getter_AddRefs(mCachedSecurityInfo));
5875 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5876 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)
5877 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)
;
5878 NS_WARNING("failed to parse security-info")NS_DebugBreak(NS_DEBUG_WARNING, "failed to parse security-info"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5878)
;
5879 cacheEntry->AsyncDoom(nullptr);
5880 return rv;
5881 }
5882
5883 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", 5883
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedSecurityInfo"
")"); do { MOZ_CrashSequence(__null, 5883); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5884 if (!mCachedSecurityInfo) {
5885 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)
5886 ("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)
5887 "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)
5888 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)
;
5889 cacheEntry->AsyncDoom(nullptr);
5890 return NS_ERROR_UNEXPECTED; // XXX error code
5891 }
5892 }
5893
5894 // Keep the conditions below in sync with the conditions in ReadFromCache.
5895
5896 rv = NS_OK;
Value stored to 'rv' is never read
5897
5898 if (WillRedirect(*mCachedResponseHead)) {
5899 // Do not even try to read the entity for a redirect because we do not
5900 // return an entity to the application when we process redirects.
5901 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
)
;
5902 return NS_OK;
5903 }
5904
5905 if ((mLoadFlags & nsICachingChannel::LOAD_ONLY_IF_MODIFIED) &&
5906 !LoadCachedContentIsPartial()) {
5907 // For LOAD_ONLY_IF_MODIFIED, we usually don't have to deal with the
5908 // cached entity.
5909 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)
5910 ("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)
5911 "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)
;
5912 return NS_OK;
5913 }
5914
5915 // Open an input stream for the entity, so that the call to OpenInputStream
5916 // happens off the main thread.
5917 nsCOMPtr<nsIInputStream> stream;
5918
5919 // If an alternate representation was requested, try to open the alt
5920 // input stream.
5921 // If the entry has a "is-from-child" metadata, then only open the altdata
5922 // stream if the consumer is also from child.
5923 bool altDataFromChild = false;
5924 {
5925 nsCString value;
5926 rv = cacheEntry->GetMetaDataElement("alt-data-from-child",
5927 getter_Copies(value));
5928 altDataFromChild = !value.IsEmpty();
5929 }
5930
5931 nsAutoCString altDataType;
5932 (void)cacheEntry->GetAltDataType(altDataType);
5933
5934 nsAutoCString contentType;
5935 mCachedResponseHead->ContentType(contentType);
5936
5937 bool foundAltData = false;
5938 bool deliverAltData = true;
5939 if (!LoadDisableAltDataCache() && !altDataType.IsEmpty() &&
5940 !mPreferredCachedAltDataTypes.IsEmpty() &&
5941 altDataFromChild == LoadAltDataForChild()) {
5942 for (auto& pref : mPreferredCachedAltDataTypes) {
5943 if (pref.type() == altDataType &&
5944 (pref.contentType().IsEmpty() || pref.contentType() == contentType)) {
5945 foundAltData = true;
5946 deliverAltData =
5947 pref.deliverAltData() ==
5948 nsICacheInfoChannel::PreferredAlternativeDataDeliveryType::ASYNC;
5949 break;
5950 }
5951 }
5952 }
5953
5954 nsCOMPtr<nsIInputStream> altData;
5955 int64_t altDataSize = -1;
5956 if (foundAltData) {
5957 rv = cacheEntry->OpenAlternativeInputStream(altDataType,
5958 getter_AddRefs(altData));
5959 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5960 // We have succeeded.
5961 mAvailableCachedAltDataType = altDataType;
5962 StoreDeliveringAltData(deliverAltData);
5963
5964 // Set the correct data size on the channel.
5965 (void)cacheEntry->GetAltDataSize(&altDataSize);
5966 mAltDataLength = altDataSize;
5967
5968 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)
5969 ", 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)
5970 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)
;
5971
5972 if (deliverAltData) {
5973 stream = altData;
5974 }
5975 }
5976 }
5977
5978 if (!stream) {
5979 rv = cacheEntry->OpenInputStream(0, getter_AddRefs(stream));
5980 }
5981
5982 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5983 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)
5984 ("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)
5985 "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)
5986 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)
;
5987 return rv;
5988 }
5989
5990 if (startBuffering) {
5991 bool nonBlocking;
5992 rv = stream->IsNonBlocking(&nonBlocking);
5993 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && nonBlocking) startBuffering = false;
5994 }
5995
5996 if (!startBuffering) {
5997 // Bypass wrapping the input stream for the new cache back-end since
5998 // nsIStreamTransportService expects a blocking stream. Preloading of
5999 // the data must be done on the level of the cache backend, internally.
6000 //
6001 // We do not connect the stream to the stream transport service if we
6002 // have to validate the entry with the server. If we did, we would get
6003 // into a race condition between the stream transport service reading
6004 // the existing contents and the opening of the cache entry's output
6005 // stream to write the new contents in the case where we get a non-304
6006 // response.
6007 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)
6008 ("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)
6009 "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)
6010 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)
;
6011 mCacheInputStream.takeOver(stream);
6012 return rv;
6013 }
6014
6015 // Have the stream transport service start reading the entity on one of its
6016 // background threads.
6017
6018 nsCOMPtr<nsITransport> transport;
6019 nsCOMPtr<nsIInputStream> wrapper;
6020
6021 nsCOMPtr<nsIStreamTransportService> sts(
6022 components::StreamTransport::Service());
6023 rv = sts ? NS_OK : NS_ERROR_NOT_AVAILABLE;
6024 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6025 rv = sts->CreateInputTransport(stream, true, getter_AddRefs(transport));
6026 }
6027 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6028 rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(wrapper));
6029 }
6030 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6031 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)
6032 ("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)
6033 "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)
6034 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)
;
6035 } else {
6036 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)
6037 ("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)
6038 "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)
6039 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)
;
6040
6041 stream->Close();
6042 return rv;
6043 }
6044
6045 mCacheInputStream.takeOver(wrapper);
6046
6047 return NS_OK;
6048}
6049
6050// Actually process the cached response that we started to handle in CheckCache
6051// and/or StartBufferingCachedEntity.
6052nsresult nsHttpChannel::ReadFromCache(void) {
6053 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"
, 6053); return NS_ERROR_FAILURE; } } while (false)
;
6054 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"
, 6054); return NS_ERROR_FAILURE; } } while (false)
;
6055 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"
, 6055); return NS_OK; } } while (false)
; // already opened
6056
6057 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)
6058 ("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)
6059 "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)
6060 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)
;
6061
6062 if (mCachedResponseHead) mResponseHead = std::move(mCachedResponseHead);
6063
6064 UpdateInhibitPersistentCachingFlag();
6065
6066 // if we don't already have security info, try to get it from the cache
6067 // entry. there are two cases to consider here: 1) we are just reading
6068 // from the cache, or 2) this may be due to a 304 not modified response,
6069 // in which case we could have security info from a socket transport.
6070 if (!mSecurityInfo) mSecurityInfo = mCachedSecurityInfo;
6071
6072 nsresult rv;
6073
6074 // Keep the conditions below in sync with the conditions in
6075 // StartBufferingCachedEntity.
6076
6077 if (WillRedirect(*mResponseHead)) {
6078 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
6079 // to avoid event dispatching latency.
6080 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", 6080
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6080); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6081 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)
;
6082 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
6083 }
6084
6085 if ((mLoadFlags & LOAD_ONLY_IF_MODIFIED) && !LoadCachedContentIsPartial()) {
6086 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)
6087 ("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)
6088 "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)
;
6089 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", 6089
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6089); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6090 // TODO: Bug 759040 - We should call HandleAsyncNotModified directly
6091 // here, to avoid event dispatching latency.
6092 return AsyncCall(&nsHttpChannel::HandleAsyncNotModified);
6093 }
6094
6095 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", 6095
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6095); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6096 if (!mCacheInputStream) {
6097 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"
, 6099); MOZ_PretendNoReturn(); } while (0)
6098 "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"
, 6099); MOZ_PretendNoReturn(); } while (0)
6099 "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"
, 6099); MOZ_PretendNoReturn(); } while (0)
;
6100 return NS_ERROR_UNEXPECTED;
6101 }
6102
6103 nsCOMPtr<nsIInputStream> inputStream = mCacheInputStream.forget();
6104
6105 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), inputStream, 0, 0,
6106 true);
6107 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6108 inputStream->Close();
6109 return rv;
6110 }
6111
6112 rv = mCachePump->AsyncRead(this);
6113 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6114
6115 uint32_t suspendCount = mSuspendCount;
6116 if (LoadAsyncResumePending()) {
6117 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)
6118 (" 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)
6119 ", 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)
6120 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)
;
6121 ++suspendCount;
6122 }
6123 while (suspendCount--) {
6124 mCachePump->Suspend();
6125 }
6126
6127 return NS_OK;
6128}
6129
6130void nsHttpChannel::CloseCacheEntry(bool doomOnFailure) {
6131 CancelCacheWaitTimer();
6132 mCacheInputStream.CloseAndRelease();
6133
6134 if (!mCacheEntry) return;
6135
6136 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)
6137 " 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)
6138 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)
6139 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)
;
6140
6141 // If we have begun to create or replace a cache entry, and that cache
6142 // entry is not complete and not resumable, then it needs to be doomed.
6143 // Otherwise, CheckCache will make the mistake of thinking that the
6144 // partial cache entry is complete.
6145
6146 bool doom = false;
6147 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref) {
6148 // A response blocked by ORB is fully written to the cache before the block
6149 // decision is made, so it must be doomed here; otherwise it lingers as a
6150 // complete entry that a same-partition request (e.g. a navigation reusing a
6151 // prefetch) could consume.
6152 doom = true;
6153 } else if (LoadInitedCacheEntry()) {
6154 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"
, 6154); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "oops" ")"); do { MOZ_CrashSequence(__null, 6154); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6155 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) && doomOnFailure && LoadCacheEntryIsWriteOnly() &&
6156 (!mResponseHead || !mResponseHead->IsResumable())) {
6157 doom = true;
6158 }
6159 } else if (LoadCacheEntryIsWriteOnly()) {
6160 doom = true;
6161 }
6162
6163 if (doom) {
6164 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)
;
6165 mCacheEntry->AsyncDoom(nullptr);
6166 } else {
6167 // Store updated security info, makes cached EV status race less likely
6168 // (see bug 1040086)
6169 if (mSecurityInfo) {
6170 mCacheEntry->SetSecurityInfo(mSecurityInfo);
6171 }
6172
6173 // For prefetch requests without cache headers, force the cache entry
6174 // to remain valid so that subsequent navigations reuse the prefetched
6175 // response instead of re-fetching. See bug 1527334.
6176 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && mResponseHead) {
6177 if (StringBeginsWith(GetSecPurpose(), "prefetch"_ns) &&
6178 !mResponseHead->MustValidate()) {
6179 nsAutoCString expires;
6180 (void)mResponseHead->GetHeader(nsHttp::Expires, expires);
6181 nsAutoCString cacheControlHeader;
6182 (void)mResponseHead->GetHeader(nsHttp::Cache_Control,
6183 cacheControlHeader);
6184 CacheControlParser cacheControl(cacheControlHeader);
6185 uint32_t maxAge;
6186 if (!cacheControl.MaxAge(&maxAge) && expires.IsEmpty()) {
6187 uint32_t forceValidFor =
6188 StaticPrefs::network_prefetch_next_force_valid_for();
6189 if (forceValidFor > 0) {
6190 mCacheEntry->ForceValidFor(forceValidFor);
6191 }
6192 }
6193 }
6194 }
6195
6196 // ORB's JavaScript validation finishes asynchronously, after this point,
6197 // so the response may yet be blocked. Keep a reference to the committed
6198 // entry so CancelInternal() can doom it if that happens.
6199 if (mORB && mORB->IsSniffing()) {
6200 mORBValidationCacheEntry = mCacheEntry;
6201 }
6202 }
6203
6204 mCachedResponseHead = nullptr;
6205
6206 mCachePump = nullptr;
6207 // This releases the entry for other consumers to use.
6208 // We call Dismiss() in case someone still keeps a reference
6209 // to this entry handle.
6210 mCacheEntry->Dismiss();
6211 mCacheEntry = nullptr;
6212 StoreCacheEntryIsWriteOnly(false);
6213 StoreInitedCacheEntry(false);
6214}
6215
6216void nsHttpChannel::OnOpaqueResponseAllowed() {
6217 // mORBValidationCacheEntry is only ever touched on the main thread; this
6218 // relies on ORB delivering its validation verdict there.
6219 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", 6219
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 6219); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6220 // ORB allowed the response, so the entry we kept in case it had to be doomed
6221 // (see CloseCacheEntry) can stay in the cache; drop our reference to it.
6222 mORBValidationCacheEntry = nullptr;
6223}
6224
6225// Initialize the cache entry for writing.
6226// - finalize storage policy
6227// - store security info
6228// - update expiration time
6229// - store headers and other meta data
6230nsresult nsHttpChannel::InitCacheEntry() {
6231 nsresult rv;
6232
6233 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"
, 6233); return NS_ERROR_UNEXPECTED; } } while (false)
;
6234 // if only reading, nothing to be done here.
6235 if (LoadCacheEntryIsReadOnly()) return NS_OK;
6236
6237 // Don't cache the response again if already cached...
6238 if (CachedContentIsValid()) return NS_OK;
6239
6240 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)
6241 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)
;
6242
6243 // Normally already handled before the response was applied to the entry, but
6244 // recreating an alias entry would doom and rewrite another URL's entry, so
6245 // never reach Recreate() below while the flag is still set.
6246 rv = MaybeReplaceNoVarySearchAliasEntry();
6247 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return NS_OK;
6248
6249 bool recreate = !LoadCacheEntryIsWriteOnly();
6250 bool dontPersist = mLoadFlags & INHIBIT_PERSISTENT_CACHING;
6251
6252 if (!recreate && dontPersist) {
6253 // If the current entry is persistent but we inhibit peristence
6254 // then force recreation of the entry as memory/only.
6255 rv = mCacheEntry->GetPersistent(&recreate);
6256 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6257 }
6258
6259 if (recreate) {
6260 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)
6261 (" 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)
6262 "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)
;
6263 // clean the altData cache and reset this to avoid wrong content length
6264 mAvailableCachedAltDataType.Truncate();
6265 StoreDeliveringAltData(false);
6266
6267 nsCOMPtr<nsICacheEntry> currentEntry;
6268 currentEntry.swap(mCacheEntry);
6269 rv = currentEntry->Recreate(dontPersist, getter_AddRefs(mCacheEntry));
6270 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6271 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)
;
6272 return NS_OK;
6273 }
6274
6275 StoreCacheEntryIsWriteOnly(true);
6276
6277 // Since we recreated, the new entry doesn't have expiration set yet.
6278 // UpdateExpirationTime was called before ParseDictionary on the old entry,
6279 // but we need to set it on this new entry too.
6280 rv = UpdateExpirationTime();
6281 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6282 }
6283
6284 // mark this weakly framed until a response body is seen
6285 mCacheEntry->SetMetaDataElement("strongly-framed", "0");
6286
6287 rv = AddCacheEntryHeaders(mCacheEntry, false);
6288 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6289
6290 StoreInitedCacheEntry(true);
6291
6292 // Don't perform the check when writing (doesn't make sense)
6293 StoreConcurrentCacheAccess(0);
6294
6295 return NS_OK;
6296}
6297
6298void nsHttpChannel::UpdateInhibitPersistentCachingFlag() {
6299 // The no-store directive within the 'Cache-Control:' header indicates
6300 // that we must not store the response in a persistent cache.
6301 if (mResponseHead->NoStore()) {
6302 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6303 return;
6304 }
6305
6306 if (!StaticPrefs::network_cache_persist_permanent_redirects_http() &&
6307 mURI->SchemeIs("http") &&
6308 nsHttp::IsPermanentRedirect(mResponseHead->Status())) {
6309 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6310 return;
6311 }
6312
6313 // Only cache SSL content on disk if the pref is set
6314 if (!gHttpHandler->IsPersistentHttpsCachingEnabled() &&
6315 mURI->SchemeIs("https")) {
6316 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6317 }
6318}
6319
6320nsresult DoAddCacheEntryHeaders(nsHttpChannel* self, nsICacheEntry* entry,
6321 nsHttpRequestHead* requestHead,
6322 nsHttpResponseHead* responseHead,
6323 nsITransportSecurityInfo* securityInfo,
6324 bool aModified) {
6325 nsresult rv;
6326
6327 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)
;
6328 // Store secure data in memory only
6329 if (securityInfo) {
6330 entry->SetSecurityInfo(securityInfo);
6331 }
6332
6333 // Note: if aModified == false, then we're processing a 304 Not Modified,
6334 // and we *shouldn't* have any change to the Dictionary (and won't be
6335 // replacing the DictionaryEntry, though if the Match/Match-dest/Id/Type
6336 // changed, we may need to rewrite it. XXX?
6337
6338 // Store the HTTP request method with the cache entry so we can distinguish
6339 // for example GET and HEAD responses.
6340 nsAutoCString method;
6341 requestHead->Method(method);
6342 rv = entry->SetMetaDataElement("request-method", method.get());
6343 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6344
6345 // Store the HTTP authorization scheme used if any...
6346 rv = StoreAuthorizationMetaData(entry, requestHead);
6347 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6348
6349 rv = self->UpdateCacheEntryHeaders(entry, nullptr);
6350 return rv;
6351}
6352
6353nsresult nsHttpChannel::AddCacheEntryHeaders(nsICacheEntry* entry,
6354 bool aModified) {
6355 return DoAddCacheEntryHeaders(this, entry, &mRequestHead, mResponseHead.get(),
6356 mSecurityInfo, aModified);
6357}
6358
6359nsresult nsHttpChannel::UpdateCacheEntryHeaders(nsICacheEntry* entry,
6360 const nsHttpAtom* aAtom) {
6361 nsresult rv = NS_OK;
6362
6363 // Iterate over the headers listed in the Vary response header, and
6364 // store the value of the corresponding request header so we can verify
6365 // that it has not varied when we try to re-use the cached response at
6366 // a later time. Take care to store "Cookie" headers only as hashes
6367 // due to security considerations and the fact that they can be pretty
6368 // large (bug 468426). We take care of "Vary: cookie" in ResponseWouldVary.
6369 //
6370 // NOTE: if "Vary: accept, cookie", then we will store the "accept" header
6371 // in the cache. we could try to avoid needlessly storing the "accept"
6372 // header in this case, but it doesn't seem worth the extra code to perform
6373 // the check.
6374 {
6375 nsAutoCString buf, metaKey;
6376 (void)mResponseHead->GetHeader(nsHttp::Vary, buf);
6377
6378 constexpr auto prefix = "request-"_ns;
6379
6380 for (const nsACString& token :
6381 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
6382 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)
6383 ("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)
6384 "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)
6385 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)
;
6386 if (!token.EqualsLiteral("*")) {
6387 nsHttpAtom atom = nsHttp::ResolveAtom(token);
6388 if (!aAtom || atom == *aAtom) {
6389 nsAutoCString val;
6390 nsAutoCString hash;
6391 if (NS_SUCCEEDED(mRequestHead.GetHeader(atom, val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(atom, val))), 1)))
) {
6392 // If cookie-header, store a hash of the value
6393 if (atom == nsHttp::Cookie) {
6394 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)
6395 ("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)
6396 "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)
6397 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)
;
6398 rv = Hash(val.get(), hash);
6399 // If hash failed, store a string not very likely
6400 // to be the result of subsequent hashes
6401 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6402 val = "<hash failed>"_ns;
6403 } else {
6404 val = std::move(hash);
6405 }
6406
6407 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)
;
6408 }
6409
6410 // build cache meta data key and set meta data element...
6411 metaKey = prefix + token;
6412 entry->SetMetaDataElement(metaKey.get(), val.get());
6413 } else {
6414 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)
6415 ("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)
6416 "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)
6417 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)
;
6418 metaKey = prefix + token;
6419 entry->SetMetaDataElement(metaKey.get(), nullptr);
6420 }
6421 }
6422 }
6423 }
6424 }
6425 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6426 return rv;
6427 }
6428 // Store the received HTTP head with the cache entry as an element of
6429 // the meta data.
6430 nsAutoCString head;
6431 mResponseHead->Flatten(head, true);
6432 rv = entry->SetMetaDataElement("response-head", head.get());
6433 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6434 head.Truncate();
6435 mResponseHead->FlattenNetworkOriginalHeaders(head);
6436 rv = entry->SetMetaDataElement("original-response-headers", head.get());
6437 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6438
6439 // Store No-Vary-Search header in cache metadata and notify the secondary
6440 // index so variant URLs can match this entry on future cache lookups.
6441 nsAutoCString noVarySearch;
6442 if (StaticPrefs::network_cache_no_vary_search() &&
6443 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::No_Vary_Search, noVarySearch))), 1)))
6444 mResponseHead->GetHeader(nsHttp::No_Vary_Search, noVarySearch))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::No_Vary_Search, noVarySearch))), 1)))
&&
6445 !noVarySearch.IsEmpty()) {
6446 glean::network::no_vary_search_header_received.Add(1);
6447 bool parseError = false;
6448 auto data = ParseNoVarySearchHeader(noVarySearch, &parseError);
6449 glean::network::no_vary_search_rule_type
6450 .Get(NoVarySearchRuleLabel(data.paramsRule))
6451 .Add(1);
6452 if (parseError) {
6453 glean::network::no_vary_search_parse_error.Add(1);
6454 }
6455
6456 rv = entry->SetMetaDataElement("no-vary-search", noVarySearch.get());
6457 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6458 return rv;
6459 }
6460
6461 if (mCacheEntryURI) {
6462 if (auto* svc = CacheStorageService::Self()) {
6463 svc->NoteNoVarySearchEntry(entry, mCacheEntryURI);
6464 }
6465 }
6466 }
6467
6468 // Indicate we have successfully finished setting metadata on the cache
6469 // entry.
6470 return entry->MetaDataReady();
6471}
6472
6473bool nsHttpChannel::ParseDictionary(nsICacheEntry* aEntry,
6474 nsHttpResponseHead* aResponseHead,
6475 bool aModified) {
6476 nsAutoCString val;
6477 if (NS_SUCCEEDED(aResponseHead->GetHeader(nsHttp::Use_As_Dictionary, val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Use_As_Dictionary, val))), 1)))
) {
6478 nsAutoCStringN<128> matchVal;
6479 nsAutoCStringN<64> matchIdVal;
6480 nsTArray<nsCString> matchDestItems;
6481 nsAutoCString typeVal;
6482
6483 if (!NS_ParseUseAsDictionary(val, matchVal, matchIdVal, matchDestItems,
6484 typeVal)) {
6485 return false;
6486 }
6487
6488 nsCString key;
6489 nsresult rv;
6490 if (NS_FAILED(rv = aEntry->GetKey(key))((bool)(__builtin_expect(!!(NS_FAILED_impl(rv = aEntry->GetKey
(key))), 0)))
) {
6491 return false;
6492 }
6493
6494 // Verify if the matchVal has regexp groups. If so, reject it
6495 UrlPatternGlue pattern;
6496 UrlPatternOptions options{};
6497 if (!urlpattern_parse_pattern_from_string(&matchVal, &mSpec, options,
6498 &pattern)) {
6499 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)
6500 ("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)
;
6501 return false;
6502 }
6503
6504 auto freePattern = MakeScopeExit([&] { urlpattern_pattern_free(pattern); });
6505 if (urlpattern_get_has_regexp_groups(pattern)) {
6506 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)
;
6507 return false;
6508 }
6509
6510 nsCString hash;
6511 // Available now for use
6512 RefPtr<DictionaryCache> dicts(DictionaryCache::GetInstance());
6513 if (!dicts) {
6514 // Shutdown has occurred, cannot add dictionary
6515 return false;
6516 }
6517 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)
6518 ("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)
6519 "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)
6520 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)
6521 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)
6522 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)
;
6523
6524 uint32_t expTime = 0;
6525 (void)GetCacheTokenExpirationTime(&expTime);
6526
6527 dicts->AddEntry(mURI, key, matchVal, matchDestItems, matchIdVal, Some(hash),
6528 aModified, expTime, getter_AddRefs(mDictSaving));
6529 // If this was 304 Not Modified, then we don't need the dictionary data
6530 // (though we may update the dictionary entry if the match/id/etc changed).
6531 // If this is 304, mDictSaving will be cleared by AddEntry.
6532 if (mDictSaving) {
6533 if (mDictSaving->ShouldSuspendUntilCacheRead()) {
6534 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)
;
6535 Suspend();
6536 mDictSaving->CallbackOnCacheRead([self = RefPtr(this)](nsresult) {
6537 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)
;
6538 self->Resume();
6539 });
6540 }
6541 }
6542 return true;
6543 }
6544 return true; // succeeded, no use-as-dictionary
6545}
6546
6547inline void GetAuthType(const char* challenge, nsCString& authType) {
6548 const char* p;
6549
6550 // get the challenge type
6551 if ((p = strchr(challenge, ' ')) != nullptr) {
6552 authType.Assign(challenge, p - challenge);
6553 } else {
6554 authType.Assign(challenge);
6555 }
6556}
6557
6558nsresult StoreAuthorizationMetaData(nsICacheEntry* entry,
6559 nsHttpRequestHead* requestHead) {
6560 // Not applicable to proxy authorization...
6561 nsAutoCString val;
6562 if (NS_FAILED(requestHead->GetHeader(nsHttp::Authorization, val))((bool)(__builtin_expect(!!(NS_FAILED_impl(requestHead->GetHeader
(nsHttp::Authorization, val))), 0)))
) {
6563 return NS_OK;
6564 }
6565
6566 // eg. [Basic realm="wally world"]
6567 nsAutoCString buf;
6568 GetAuthType(val.get(), buf);
6569 return entry->SetMetaDataElement("auth", buf.get());
6570}
6571
6572// Finalize the cache entry
6573// - may need to rewrite response headers if any headers changed
6574// - may need to recalculate the expiration time if any headers changed
6575// - called only for freshly written cache entries
6576nsresult nsHttpChannel::FinalizeCacheEntry() {
6577 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)
;
6578
6579 // Don't update this meta-data on 304
6580 if (LoadStronglyFramed() && !CachedContentIsValid() && mCacheEntry) {
6581 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)
6582 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)
;
6583 mCacheEntry->SetMetaDataElement("strongly-framed", "1");
6584 }
6585
6586 if (mResponseHead && LoadResponseHeadersModified()) {
6587 // Set the expiration time for this cache entry
6588 nsresult rv = UpdateExpirationTime();
6589 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6590 }
6591 return NS_OK;
6592}
6593
6594nsresult nsHttpChannel::InstallCacheListener(int64_t offset) {
6595 return DoInstallCacheListener(false, offset);
6596}
6597
6598// Open an output stream to the cache entry and insert a listener tee into
6599// the chain of response listeners, so the data will go the cache and the
6600// normal listener chain, which often will eventually include a
6601// decompressor. If the Content-Encoding is dcb or dcz, we'll include a
6602// decompressor *before* the tee, so the cache will see decompressed data
6603// (we can't decompress dcb/dcz when reading from the cache). Also, if an
6604// entry is being used as a dictionary (Use-As-Dictionary), we want the data
6605// to in the cache to be decompressed, so we should install a decompressor
6606// before the tee as well.
6607nsresult nsHttpChannel::DoInstallCacheListener(bool aSaveDecompressed,
6608 int64_t offset) {
6609 nsresult rv;
6610
6611 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)
;
6612
6613 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"
, 6613); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 6613); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6614 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", 6614
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial()"
")"); do { MOZ_CrashSequence(__null, 6614); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6615 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"
, 6615); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mListener" ")"
); do { MOZ_CrashSequence(__null, 6615); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6616
6617 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)
;
6618
6619 // We must close the input stream first because cache entries do not
6620 // correctly handle having an output stream and input streams open at
6621 // the same time.
6622 mCacheInputStream.CloseAndRelease();
6623
6624 int64_t predictedSize = mResponseHead->TotalEntitySize();
6625 if (predictedSize != -1) {
6626 predictedSize -= offset;
6627 }
6628
6629 nsCOMPtr<nsIOutputStream> out;
6630 rv =
6631 mCacheEntry->OpenOutputStream(offset, predictedSize, getter_AddRefs(out));
6632 if (rv == NS_ERROR_NOT_AVAILABLE) {
6633 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)
;
6634 // Entry is already doomed.
6635 // This may happen when expiration time is set to past and the entry
6636 // has been removed by the background eviction logic.
6637 return NS_OK;
6638 }
6639 if (rv == NS_ERROR_FILE_TOO_BIG) {
6640 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)
6641 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)
;
6642 mCacheEntry->AsyncDoom(nullptr);
6643 return NS_OK;
6644 }
6645 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6646
6647 if (LoadCacheOnlyMetadata()) {
6648 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
)
;
6649 // We must open and then close the output stream of the cache entry.
6650 // This way we indicate the content has been written (despite with zero
6651 // length) and the entry is now in the ready state with "having data".
6652
6653 out->Close();
6654 return NS_OK;
6655 }
6656
6657 // XXX disk cache does not support overlapped i/o yet
6658#if 0
6659 // Mark entry valid inorder to allow simultaneous reading...
6660 rv = mCacheEntry->MarkValid();
6661 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6662#endif
6663
6664 nsCOMPtr<nsIStreamListenerTee> tee =
6665 do_CreateInstance(kStreamListenerTeeCID, &rv);
6666 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6667
6668 rv = tee->Init(mListener, out, nullptr);
6669 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)
6670 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)
;
6671 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6672 mListener = tee;
6673
6674 mWritingToCache = true;
6675 // If this is Use-As-Dictionary we need to be able to read it quickly for
6676 // dictionary use, OR if it's encoded in dcb or dcz (using a dictionary),
6677 // we must decompress it before storing since we won't have the dictionary
6678 // when we go to read it out later.
6679 // In this case, we hook an nsHTTPCompressConv instance in before the tee
6680 // since we don't want to have to decompress it here and again in the content
6681 // process (if it's not dcb/dcz); if it is dcb/dcz we must decompress it
6682 // before the content process gets to see it
6683 // XXX We could recompress this with e.g. gzip to save space and improve
6684 // hitrate, at the cost of some CPU.
6685
6686 // Note: this doesn't handle cases like "dcb, gzip" or (worse?) "gzip, dcb".
6687 // We could in theory handle them.
6688 if (aSaveDecompressed) {
6689 nsCOMPtr<nsIStreamListener> listener;
6690 // otherwise we won't convert in the parent process
6691 SetApplyConversion(true);
6692 rv = DoApplyContentConversionsInternal(mListener, getter_AddRefs(listener),
6693 true, nullptr);
6694 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6695 return rv;
6696 }
6697 // Remove Available-Dictionary from Vary header if present. This
6698 // avoids us refusing to match on a future load, for example if this
6699 // dictionary was decoded from an earlier version using a dictionary
6700 // (i.e. the update jquery to new version using the old version as a
6701 // dictionary; no future load will use that old version).
6702
6703 // XXX It would be slightly more efficient to remove all at once
6704 // instead of sequentially by passing an array of strings
6705 RemoveFromVary(mResponseHead.get(), "available-dictionary"_ns);
6706 RemoveFromVary(mResponseHead.get(), "accept-encoding"_ns);
6707
6708 if (listener) {
6709 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)
6710 ("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)
;
6711 mListener = listener;
6712 mCompressListener = std::move(listener);
6713 StoreHasAppliedConversion(true);
6714
6715 } else {
6716 nsAutoCString contentEncoding;
6717 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
6718 if (contentEncoding.IsEmpty()) {
6719 // No Content-Encoding — data is already raw. Normal for dictionary
6720 // responses served without transfer encoding.
6721 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)
6722 ("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)
;
6723 } else if (mIsDictionaryCompressed) {
6724 // dcb/dcz can only be decompressed in the parent process with
6725 // the dictionary. If we can't install the decompressor, this is
6726 // fatal — the content process can't decode it.
6727 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)
6728 ("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)
6729 "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)
6730 "[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)
6731 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)
6732 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)
;
6733 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
6734 return NS_ERROR_INVALID_CONTENT_ENCODING;
6735 } else if (mDictSaving) {
6736 // Saving a dictionary but can't install a decompressor — we'd store
6737 // compressed data with a hash computed over compressed bytes. Cancel
6738 // the dictionary save but leave Content-Encoding for downstream
6739 // decompression.
6740 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)
6741 ("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)
6742 "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)
6743 "[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)
6744 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)
6745 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)
;
6746 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"
, 6746); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Can't save dictionary uncompressed" ")"); do { MOZ_CrashSequence
(__null, 6746); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6747 mCacheEntry->SetDictionary(nullptr);
6748 DictionaryCache::RemoveDictionary(nsCString(mDictSaving->GetURI()));
6749 mDictSaving = nullptr;
6750 }
6751 }
6752 // We may have modified Content-Encoding; make sure cache metadata
6753 // reflects that. Pass nullptr so we pick up the Vary updates above
6754 rv = UpdateCacheEntryHeaders(mCacheEntry, nullptr);
6755 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6756 mCacheEntry->AsyncDoom(nullptr);
6757 return rv;
6758 }
6759 }
6760
6761#ifdef DEBUG1
6762 // Verify that Content-Encoding was properly cleared
6763 nsAutoCString verifyEncoding;
6764 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, verifyEncoding);
6765 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"
, 6766); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
") (" "Content-Encoding should have been cleared for dcb/dcz"
")"); do { MOZ_CrashSequence(__null, 6766); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6766 "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"
, 6766); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
") (" "Content-Encoding should have been cleared for dcb/dcz"
")"); do { MOZ_CrashSequence(__null, 6766); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6767 if (aSaveDecompressed) {
6768 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"
, 6770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6770); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6769 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"
, 6770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6770); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6770 "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"
, 6770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6770); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6771 }
6772#endif
6773 return NS_OK;
6774}
6775
6776//-----------------------------------------------------------------------------
6777// nsHttpChannel <redirect>
6778//-----------------------------------------------------------------------------
6779
6780nsresult nsHttpChannel::SetupReplacementChannel(nsIURI* newURI,
6781 nsIChannel* newChannel,
6782 bool preserveMethod,
6783 uint32_t redirectFlags) {
6784 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)
6785 ("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)
6786 "[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)
6787 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)
;
6788
6789 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
6790 mEndMarkerAdded = true;
6791
6792 nsAutoCString requestMethod;
6793 GetRequestMethod(requestMethod);
6794
6795 int32_t priority = PRIORITY_NORMAL;
6796 GetPriority(&priority);
6797
6798 TimingStruct timings;
6799 if (mTransaction) {
6800 timings = mTransaction->Timings();
6801 }
6802
6803 uint64_t size = 0;
6804 GetEncodedBodySize(&size);
6805
6806 nsAutoCString contentType;
6807 mozilla::Maybe<mozilla::net::HttpVersion> httpVersion = Nothing();
6808 mozilla::Maybe<uint32_t> responseStatus = Nothing();
6809 if (mResponseHead) {
6810 mResponseHead->ContentType(contentType);
6811 httpVersion = Some(mResponseHead->Version());
6812 responseStatus = Some(mResponseHead->Status());
6813 }
6814
6815 RefPtr<nsIIdentChannel> newIdentChannel = do_QueryObject(newChannel);
6816 uint64_t channelId = 0;
6817 if (newIdentChannel) {
6818 channelId = newIdentChannel->ChannelId();
6819 }
6820 profiler_add_network_marker(
6821 mURI, requestMethod, priority, mChannelId,
6822 NetworkLoadType::LOAD_REDIRECT, mLastStatusReported, TimeStamp::Now(),
6823 size, mCacheDisposition, mLoadInfo->GetInnerWindowID(),
6824 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
6825 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
6826 &timings, std::move(mSource), httpVersion, responseStatus,
6827 Some(nsDependentCString(contentType.get())), newURI, redirectFlags,
6828 channelId);
6829 }
6830
6831 nsresult rv = HttpBaseChannel::SetupReplacementChannel(
6832 newURI, newChannel, preserveMethod, redirectFlags);
6833 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6834
6835 nsAutoCString uriHost;
6836 mURI->GetAsciiHost(uriHost);
6837 // disable https-rr when encountering a downgrade from https to http.
6838 // If the host would have https-rr dns-entries, it would be misconfigured
6839 // due to giving us mixed signals:
6840 // 1. the signal to upgrade all http requests to https,
6841 // 2. but also downgrading to http on https via redirects.
6842 // Add to exclude list for that reason
6843 if (!gHttpHandler->IsHostExcludedForHTTPSRR(uriHost) &&
6844 nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
6845 mURI, newURI, mLoadInfo,
6846 {nsHTTPSOnlyUtils::UpgradeDowngradeEndlessLoopOptions::
6847 EnforceForHTTPSRR})) {
6848 // Add the host to a excluded list because:
6849 // 1. We don't need to do the same check again.
6850 // 2. Other subresources in the same host will be also excluded.
6851 gHttpHandler->ExcludeHTTPSRRHost(uriHost);
6852 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)
;
6853 }
6854
6855 rv = CheckRedirectLimit(newURI, redirectFlags);
6856 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"
, 6856); return rv; } } while (false)
;
6857
6858 // pass on the early hint observer to be able to process `103 Early Hints`
6859 // responses after cross origin redirects
6860 if (mEarlyHintObserver) {
6861 if (RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel)) {
6862 httpChannelImpl->SetEarlyHintObserver(mEarlyHintObserver);
6863 }
6864 mEarlyHintObserver = nullptr;
6865 }
6866
6867 // We don't support redirection for WebTransport for now.
6868 mWebTransportSessionEventListener = nullptr;
6869
6870 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
6871 if (!httpChannel) return NS_OK; // no other options to set
6872
6873 // convey the ApplyConversion flag (bug 91862)
6874 nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel);
6875 if (encodedChannel) encodedChannel->SetApplyConversion(LoadApplyConversion());
6876
6877 // transfer the resume information
6878 if (LoadResuming()) {
6879 nsCOMPtr<nsIResumableChannel> resumableChannel(
6880 do_QueryInterface(newChannel));
6881 if (!resumableChannel) {
6882 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Got asked to resume, but redirected to non-resumable channel!"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6883)
6883 "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"
, 6883)
;
6884 return NS_ERROR_NOT_RESUMABLE;
6885 }
6886 resumableChannel->ResumeAt(mStartPos, mEntityID);
6887 }
6888
6889 nsCOMPtr<nsIHttpChannelInternal> internalChannel =
6890 do_QueryInterface(newChannel, &rv);
6891 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6892 TimeStamp timestamp;
6893 rv = GetNavigationStartTimeStamp(&timestamp);
6894 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"
, 6894)
) {
6895 return rv;
6896 }
6897 if (timestamp) {
6898 (void)internalChannel->SetNavigationStartTimeStamp(timestamp);
6899 }
6900 }
6901
6902 return NS_OK;
6903}
6904
6905nsresult nsHttpChannel::AsyncProcessRedirection(uint32_t redirectType) {
6906 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)
6907 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)
;
6908
6909 nsresult rv = ProcessCrossOriginSecurityHeaders();
6910 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6911 mStatus = rv;
6912 HandleAsyncAbort();
6913 return rv;
6914 }
6915
6916 nsAutoCString location;
6917
6918 // if a location header was not given, then we can't perform the redirect,
6919 // so just carry on as though this were a normal response.
6920 if (NS_FAILED(mResponseHead->GetHeader(nsHttp::Location, location))((bool)(__builtin_expect(!!(NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Location, location))), 0)))
) {
6921 return NS_ERROR_FAILURE;
6922 }
6923
6924 // If we were told to not follow redirects automatically, then again
6925 // carry on as though this were a normal response.
6926 if (mLoadInfo->GetDontFollowRedirects()) {
6927 return NS_ERROR_FAILURE;
6928 }
6929
6930 // make sure non-ASCII characters in the location header are escaped.
6931 nsAutoCString locationBuf;
6932 if (NS_EscapeURL(location.get(), -1, esc_OnlyNonASCII | esc_Spaces,
6933 locationBuf)) {
6934 location = std::move(locationBuf);
6935 }
6936
6937 mRedirectType = redirectType;
6938
6939 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)
6940 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)
;
6941
6942 rv = CreateNewURI(location.get(), getter_AddRefs(mRedirectURI));
6943
6944 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6945 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)
;
6946 return NS_ERROR_CORRUPTED_CONTENT;
6947 }
6948
6949 if (!StaticPrefs::network_allow_redirect_to_data() &&
6950 !mLoadInfo->GetAllowInsecureRedirectToDataURI() &&
6951 mRedirectURI->SchemeIs("data")) {
6952 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)
;
6953 nsContentSecurityManager::ReportBlockedDataURI(mRedirectURI, mLoadInfo,
6954 true);
6955 return NS_ERROR_DOM_BAD_URI;
6956 }
6957
6958 // Perform the URL query string stripping for redirects. We will only strip
6959 // the query string if it is redirecting to a third-party URI in the top
6960 // level.
6961 if (StaticPrefs::privacy_query_stripping_redirect()) {
6962 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
6963 bool isThirdPartyRedirectURI = true;
6964 thirdPartyUtil->IsThirdPartyURI(mURI, mRedirectURI,
6965 &isThirdPartyRedirectURI);
6966 if (isThirdPartyRedirectURI && mLoadInfo->GetExternalContentPolicyType() ==
6967 ExtContentPolicy::TYPE_DOCUMENT) {
6968 glean::contentblocking::query_stripping_count
6969 .EnumGet(glean::contentblocking::QueryStrippingCountLabel::eRedirect)
6970 .Add();
6971
6972 nsCOMPtr<nsIPrincipal> prin;
6973 ContentBlockingAllowList::RecomputePrincipal(
6974 mRedirectURI, mLoadInfo->GetOriginAttributes(), getter_AddRefs(prin));
6975
6976 bool isRedirectURIInAllowList = false;
6977 if (prin) {
6978 ContentBlockingAllowList::Check(prin, mPrivateBrowsing,
6979 isRedirectURIInAllowList);
6980 }
6981
6982 if (!isRedirectURIInAllowList) {
6983 nsCOMPtr<nsIURI> strippedURI;
6984
6985 nsCOMPtr<nsIURLQueryStringStripper> queryStripper;
6986 queryStripper =
6987 mozilla::components::URLQueryStringStripper::Service(&rv);
6988 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"
, 6988); return rv; } } while (false)
;
6989
6990 uint32_t numStripped;
6991
6992 rv = queryStripper->Strip(mRedirectURI, mPrivateBrowsing,
6993 getter_AddRefs(strippedURI), &numStripped);
6994 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"
, 6994); return rv; } } while (false)
;
6995
6996 if (numStripped) {
6997 mUnstrippedRedirectURI = mRedirectURI;
6998 mRedirectURI = strippedURI;
6999
7000 // Record telemetry, but only if we stripped any query params.
7001 glean::contentblocking::query_stripping_count
7002 .EnumGet(glean::contentblocking::QueryStrippingCountLabel::
7003 eStripforredirect)
7004 .Add();
7005 glean::contentblocking::query_stripping_param_count
7006 .AccumulateSingleSample(numStripped);
7007 }
7008 }
7009 }
7010 }
7011
7012 // if we have a Set-Login header, we should try to handle it here
7013 nsAutoCString setLogin;
7014 if (NS_SUCCEEDED(mResponseHead->GetHeader(nsHttp::Set_Login, setLogin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Set_Login, setLogin))), 1)))
) {
7015 bool isDocument = mLoadInfo->GetExternalContentPolicyType() ==
7016 ExtContentPolicy::TYPE_DOCUMENT;
7017 if (isDocument) {
7018 auto ssm = nsContentUtils::GetSecurityManager();
7019 if (ssm) {
7020 nsCOMPtr<nsIPrincipal> documentPrincipal;
7021 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
7022 this, getter_AddRefs(documentPrincipal));
7023 dom::NavigatorLogin::SetLoginStatus(documentPrincipal, setLogin);
7024 }
7025 } else {
7026 bool inThirdPartyContext = mLoadInfo->GetIsInThirdPartyContext();
7027 nsIPrincipal* loadingPrincipal = mLoadInfo->GetLoadingPrincipal();
7028 if (loadingPrincipal) {
7029 bool isSameOriginToLoadingPrincipal =
7030 loadingPrincipal->IsSameOrigin(mURI);
7031 if (!inThirdPartyContext && isSameOriginToLoadingPrincipal) {
7032 dom::NavigatorLogin::SetLoginStatus(loadingPrincipal, setLogin);
7033 }
7034 }
7035 }
7036 }
7037
7038 if (NS_WARN_IF(!mRedirectURI)NS_warn_if_impl(!mRedirectURI, "!mRedirectURI", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7038)
) {
7039 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)
;
7040 return NS_ERROR_FAILURE;
7041 }
7042
7043 return ContinueProcessRedirectionAfterFallback(NS_OK);
7044}
7045
7046nsresult nsHttpChannel::ContinueProcessRedirectionAfterFallback(nsresult rv) {
7047 // Kill the current cache entry if we are redirecting
7048 // back to ourself.
7049 bool redirectingBackToSameURI = false;
7050 if (mCacheEntry && LoadCacheEntryIsWriteOnly() &&
7051 NS_SUCCEEDED(mURI->Equals(mRedirectURI, &redirectingBackToSameURI))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mURI->Equals(mRedirectURI
, &redirectingBackToSameURI))), 1)))
&&
7052 redirectingBackToSameURI) {
7053 mCacheEntry->AsyncDoom(nullptr);
7054 }
7055
7056 // move the reference of the old location to the new one if the new
7057 // one has none.
7058 PropagateReferenceIfNeeded(mURI, mRedirectURI);
7059
7060 bool rewriteToGET =
7061 ShouldRewriteRedirectToGET(mRedirectType, mRequestHead.ParsedMethod());
7062
7063 // prompt if the method is not safe (such as POST, PUT, DELETE, ...)
7064 if (!rewriteToGET && !mRequestHead.IsSafeMethod()) {
7065 rv = PromptTempRedirect();
7066 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7067 }
7068
7069 uint32_t redirectFlags;
7070 if (nsHttp::IsPermanentRedirect(mRedirectType)) {
7071 redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
7072 } else {
7073 redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
7074 }
7075
7076 nsCOMPtr<nsIIOService> ioService;
7077 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
7078 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7079
7080 nsCOMPtr<nsIChannel> newChannel;
7081 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
7082 CloneLoadInfoForRedirect(mRedirectURI, redirectFlags);
7083
7084 // Propagate the unstripped redirect URI.
7085 redirectLoadInfo->SetUnstrippedURI(mUnstrippedRedirectURI);
7086
7087 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), mRedirectURI,
7088 redirectLoadInfo,
7089 nullptr, // PerformanceStorage
7090 nullptr, // aLoadGroup
7091 nullptr, // aCallbacks
7092 nsIRequest::LOAD_NORMAL, ioService);
7093 // If this fails, it usually means that the URI was invalid. Treat this as if
7094 // it were a CreateNewURI failure.
7095 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"
, 7095)
) {
7096 return NS_ERROR_CORRUPTED_CONTENT;
7097 }
7098
7099 rv = SetupReplacementChannel(mRedirectURI, newChannel, !rewriteToGET,
7100 redirectFlags);
7101 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7102
7103 // verify that this is a legal redirect
7104 mRedirectChannel = newChannel;
7105
7106 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
7107 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, redirectFlags);
7108
7109 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
7110
7111 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7112 AutoRedirectVetoNotifier notifier(this, rv);
7113 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
7114 }
7115
7116 return rv;
7117}
7118
7119nsresult nsHttpChannel::ContinueProcessRedirection(nsresult rv) {
7120 AutoRedirectVetoNotifier notifier(this, rv);
7121
7122 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)
7123 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)
;
7124 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7125
7126 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"
, 7126); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRedirectChannel"
") (" "No redirect channel?" ")"); do { MOZ_CrashSequence(__null
, 7126); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
7127
7128 // Make sure to do this after we received redirect veto answer,
7129 // i.e. after all sinks had been notified
7130 mRedirectChannel->SetOriginalURI(mOriginalURI);
7131
7132 // XXX we used to talk directly with the script security manager, but that
7133 // should really be handled by the event sink implementation.
7134
7135 // begin loading the new channel
7136 rv = mRedirectChannel->AsyncOpen(mListener);
7137 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)
;
7138 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"
, 7138); return rv; } } while (false)
;
7139
7140 // close down this channel
7141 Cancel(NS_BINDING_REDIRECTED);
7142
7143 notifier.RedirectSucceeded();
7144
7145 ReleaseListeners();
7146
7147 return NS_OK;
7148}
7149
7150//-----------------------------------------------------------------------------
7151// nsHttpChannel <auth>
7152//-----------------------------------------------------------------------------
7153
7154NS_IMETHODIMPnsresult nsHttpChannel::OnAuthAvailable() {
7155 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)
;
7156
7157 // setting mAuthRetryPending flag and resuming the transaction
7158 // triggers process of throwing away the unauthenticated data already
7159 // coming from the network
7160 mIsAuthChannel = true;
7161 mAuthRetryPending = true;
7162 StoreProxyAuthPending(false);
7163 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)
;
7164 if (mTransactionPump) {
7165 Resume();
7166 }
7167
7168 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
7169 return CallOrWaitForResume(
7170 [](auto* self) { return self->RedirectToNewChannelForAuthRetry(); });
7171 }
7172
7173 return NS_OK;
7174}
7175
7176NS_IMETHODIMPnsresult nsHttpChannel::OnAuthCancelled(bool userCancel) {
7177 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)
;
7178 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"
, 7178); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthRetryPending"
") (" "OnAuthCancelled should not be called twice" ")"); do {
MOZ_CrashSequence(__null, 7178); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7179
7180 if (mTransactionPump) {
7181 // If the channel is trying to authenticate to a proxy and
7182 // that was canceled we cannot show the http response body
7183 // from the 40x as that might mislead the user into thinking
7184 // it was a end host response instead of a proxy reponse.
7185 // This must check explicitly whether a proxy auth was being done
7186 // because we do want to show the content if this is an error from
7187 // the origin server.
7188 if (LoadProxyAuthPending()) Cancel(NS_ERROR_PROXY_CONNECTION_REFUSED);
7189
7190 // Make sure to process security headers before calling CallOnStartRequest.
7191 nsresult rv = ProcessCrossOriginSecurityHeaders();
7192 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7193 mStatus = rv;
7194 HandleAsyncAbort();
7195 return rv;
7196 }
7197
7198 // ensure call of OnStartRequest of the current listener here,
7199 // it would not be called otherwise at all
7200 rv = CallOnStartRequest();
7201
7202 // drop mAuthRetryPending flag and resume the transaction
7203 // this resumes load of the unauthenticated content data (which
7204 // may have been canceled if we don't want to show it)
7205 mAuthRetryPending = false;
7206 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)
;
7207 Resume();
7208
7209 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) mTransactionPump->Cancel(rv);
7210 }
7211
7212 StoreProxyAuthPending(false);
7213 return NS_OK;
7214}
7215
7216NS_IMETHODIMPnsresult nsHttpChannel::CloseStickyConnection() {
7217 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)
;
7218
7219 // Require we are between OnStartRequest and OnStopRequest, because
7220 // what we do here takes effect in OnStopRequest (not reusing the
7221 // connection for next authentication round).
7222 if (!LoadIsPending()) {
7223 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)
;
7224 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7226); MOZ_PretendNoReturn(); } while (0)
7225 "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"
, 7226); MOZ_PretendNoReturn(); } while (0)
7226 "effect")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7226); MOZ_PretendNoReturn(); } while (0)
;
7227 return NS_ERROR_UNEXPECTED;
7228 }
7229
7230 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"
, 7230); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { MOZ_CrashSequence(__null, 7230); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7231 if (!mTransaction) {
7232 return NS_ERROR_UNEXPECTED;
7233 }
7234
7235 if (!(mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
7236 mTransaction->HasStickyConnection())) {
7237 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)
;
7238 return NS_OK;
7239 }
7240
7241 mTransaction->DontReuseConnection();
7242 return NS_OK;
7243}
7244
7245NS_IMETHODIMPnsresult nsHttpChannel::ConnectionRestartable(bool aRestartable) {
7246 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)
7247 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)
;
7248 StoreAuthConnectionRestartable(aRestartable);
7249 return NS_OK;
7250}
7251
7252//-----------------------------------------------------------------------------
7253// nsHttpChannel::nsISupports
7254//-----------------------------------------------------------------------------
7255
7256NS_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; }
7257bool nsHttpChannel::DispatchRelease() {
7258 if (NS_IsMainThread()) {
7259 return false;
7260 }
7261
7262 NS_DispatchToMainThread(
7263 NewNonOwningRunnableMethod("net::nsHttpChannel::Release", this,
7264 &nsHttpChannel::Release),
7265 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
7266
7267 return true;
7268}
7269
7270NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
7271nsHttpChannel::Release() {
7272 nsrefcnt count = mRefCnt - 1;
7273 if (DispatchRelease()) {
7274 // Redispatched to the main thread.
7275 return count;
7276 }
7277
7278 NS_IMPL_RELEASE_INHERITED_GUTS(nsHttpChannel, HttpBaseChannel)nsrefcnt r = HttpBaseChannel::Release(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<nsHttpChannel>) { NS_LogRelease
((this), (r), ("nsHttpChannel")); } return r
;
7279}
7280
7281NS_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"
, 7281); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
7282 NS_INTERFACE_MAP_ENTRY(nsIRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequest>)) foundInterface = static_cast
<nsIRequest*>(this); else
7283 NS_INTERFACE_MAP_ENTRY(nsIChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIChannel>)) foundInterface = static_cast
<nsIChannel*>(this); else
7284 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestObserver>)) foundInterface
= static_cast<nsIRequestObserver*>(this); else
7285 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIStreamListener>)) foundInterface
= static_cast<nsIStreamListener*>(this); else
7286 NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannel>)) foundInterface =
static_cast<nsIHttpChannel*>(this); else
7287 NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheInfoChannel>)) foundInterface
= static_cast<nsICacheInfoChannel*>(this); else
7288 NS_INTERFACE_MAP_ENTRY(nsICachingChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICachingChannel>)) foundInterface
= static_cast<nsICachingChannel*>(this); else
7289 NS_INTERFACE_MAP_ENTRY(nsIClassOfService)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIClassOfService>)) foundInterface
= static_cast<nsIClassOfService*>(this); else
7290 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel>)) foundInterface
= static_cast<nsIUploadChannel*>(this); else
7291 NS_INTERFACE_MAP_ENTRY(nsIFormPOSTActionChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIFormPOSTActionChannel>)) foundInterface
= static_cast<nsIFormPOSTActionChannel*>(this); else
7292 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel2>)) foundInterface
= static_cast<nsIUploadChannel2*>(this); else
7293 NS_INTERFACE_MAP_ENTRY(nsICacheEntryOpenCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheEntryOpenCallback>)) foundInterface
= static_cast<nsICacheEntryOpenCallback*>(this); else
7294 NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannelInternal>)) foundInterface
= static_cast<nsIHttpChannelInternal*>(this); else
7295 NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIResumableChannel>)) foundInterface
= static_cast<nsIResumableChannel*>(this); else
7296 NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsITransportEventSink>)) foundInterface
= static_cast<nsITransportEventSink*>(this); else
7297 NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsPriority>)) foundInterface
= static_cast<nsISupportsPriority*>(this); else
7298 NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProtocolProxyCallback>)) foundInterface
= static_cast<nsIProtocolProxyCallback*>(this); else
7299 NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProxiedChannel>)) foundInterface
= static_cast<nsIProxiedChannel*>(this); else
7300 NS_INTERFACE_MAP_ENTRY(nsIHttpAuthenticableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpAuthenticableChannel>)) foundInterface
= static_cast<nsIHttpAuthenticableChannel*>(this); else
7301 NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAsyncVerifyRedirectCallback>))
foundInterface = static_cast<nsIAsyncVerifyRedirectCallback
*>(this); else
7302 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableRequest>)) foundInterface
= static_cast<nsIThreadRetargetableRequest*>(this); else
7303 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableStreamListener>
)) foundInterface = static_cast<nsIThreadRetargetableStreamListener
*>(this); else
7304 NS_INTERFACE_MAP_ENTRY(nsIDNSListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDNSListener>)) foundInterface =
static_cast<nsIDNSListener*>(this); else
7305 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
7306 NS_INTERFACE_MAP_ENTRY(nsICorsPreflightCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICorsPreflightCallback>)) foundInterface
= static_cast<nsICorsPreflightCallback*>(this); else
7307 NS_INTERFACE_MAP_ENTRY(nsIRequestTailUnblockCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestTailUnblockCallback>)) foundInterface
= static_cast<nsIRequestTailUnblockCallback*>(this); else
7308 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
7309 NS_INTERFACE_MAP_ENTRY(nsIEarlyHintObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIEarlyHintObserver>)) foundInterface
= static_cast<nsIEarlyHintObserver*>(this); else
7310NS_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; }
7311
7312//-----------------------------------------------------------------------------
7313// nsHttpChannel::nsIRequest
7314//-----------------------------------------------------------------------------
7315
7316NS_IMETHODIMPnsresult nsHttpChannel::SetCanceledReason(const nsACString& aReason) {
7317 return SetCanceledReasonImpl(aReason);
7318}
7319
7320NS_IMETHODIMPnsresult nsHttpChannel::GetCanceledReason(nsACString& aReason) {
7321 return GetCanceledReasonImpl(aReason);
7322}
7323
7324NS_IMETHODIMPnsresult
7325nsHttpChannel::CancelWithReason(nsresult aStatus, const nsACString& aReason) {
7326 return CancelWithReasonImpl(aStatus, aReason);
7327}
7328
7329NS_IMETHODIMPnsresult
7330nsHttpChannel::Cancel(nsresult status) {
7331 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", 7331
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7331); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7332 // We should never have a pump open while a CORS preflight is in progress.
7333 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"
, 7333); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7333); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7334#ifdef DEBUG1
7335 // We want to perform this check only when the chanel is being cancelled the
7336 // first time with a URL classifier blocking error code. If mStatus is
7337 // already set to such an error code then Cancel() may be called for some
7338 // other reason, for example because we've received notification about our
7339 // parent process side channel being canceled, in which case we cannot expect
7340 // that CancelByURLClassifier() would have handled this case.
7341 if (ChannelClassifierUtils::IsClassifierBlockingErrorCode(status) &&
7342 !ChannelClassifierUtils::IsClassifierBlockingErrorCode(mStatus)) {
7343 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"
, 7345, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
7344 " 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"
, 7345, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
7345 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"
, 7345, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
;
7346 }
7347#endif
7348
7349 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)
7350 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)
;
7351 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)
7352 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)
;
7353
7354 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", 7356
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7356); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7355 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", 7356
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7356); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7356 !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", 7356
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7356); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7357
7358 mEarlyHintObserver = nullptr;
7359 mWebTransportSessionEventListener = nullptr;
7360
7361 if (mCanceled) {
7362 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)
;
7363 return NS_OK;
7364 }
7365
7366 LogCallingScriptLocation(this);
7367
7368 if (LoadWaitingForRedirectCallback()) {
7369 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)
;
7370 }
7371
7372 return CancelInternal(status);
7373}
7374
7375NS_IMETHODIMPnsresult
7376nsHttpChannel::CancelByURLClassifier(nsresult aErrorCode) {
7377 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", 7377
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 7377); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7378 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", 7378
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7378); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7379 // We should never have a pump open while a CORS preflight is in progress.
7380 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"
, 7380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7380); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7381
7382 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)
;
7383
7384 if (mCanceled) {
7385 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)
;
7386 return NS_OK;
7387 }
7388
7389 // We are being canceled by the channel classifier because of tracking
7390 // protection, but we haven't yet had a chance to dispatch the
7391 // "http-on-modify-request" notifications yet (this would normally be
7392 // done in PrepareToConnect()). So do that now, before proceeding to
7393 // cancel.
7394 //
7395 // Note that running these observers can itself result in the channel
7396 // being canceled. In that case, we accept that cancelation code as
7397 // the cause of the cancelation, as if the classification of the channel
7398 // would have occurred past this point!
7399
7400 // notify "http-on-modify-request" observers
7401 CallOnModifyRequestObservers();
7402
7403 // Check if request was cancelled during on-modify-request
7404 if (mCanceled) {
7405 return mStatus;
7406 }
7407
7408 if (mSuspendCount) {
7409 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)
;
7410 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", 7410
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume" ")"
); do { MOZ_CrashSequence(__null, 7410); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7411 StoreChannelClassifierCancellationPending(1);
7412 mCallOnResume = [aErrorCode](nsHttpChannel* self) {
7413 self->HandleContinueCancellingByURLClassifier(aErrorCode);
7414 return NS_OK;
7415 };
7416 return NS_OK;
7417 }
7418
7419 // Check to see if we should redirect this channel elsewhere by
7420 // nsIHttpChannel.redirectTo API request
7421 if (mAPIRedirectTo) {
7422 StoreChannelClassifierCancellationPending(1);
7423 return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
7424 }
7425
7426 return CancelInternal(aErrorCode);
7427}
7428
7429void nsHttpChannel::ContinueCancellingByURLClassifier(nsresult aErrorCode) {
7430 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", 7430
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 7430); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7431 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", 7431
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7431); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7432 // We should never have a pump open while a CORS preflight is in progress.
7433 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"
, 7433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7433); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7434
7435 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)
;
7436 if (mCanceled) {
7437 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)
;
7438 return;
7439 }
7440
7441 // Check to see if we should redirect this channel elsewhere by
7442 // nsIHttpChannel.redirectTo API request
7443 if (mAPIRedirectTo) {
7444 (void)AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
7445 return;
7446 }
7447
7448 (void)CancelInternal(aErrorCode);
7449}
7450
7451nsresult nsHttpChannel::CancelInternal(nsresult status) {
7452 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)
;
7453 bool channelClassifierCancellationPending =
7454 !!LoadChannelClassifierCancellationPending();
7455 if (ChannelClassifierUtils::IsClassifierBlockingErrorCode(status)) {
7456 StoreChannelClassifierCancellationPending(0);
7457 }
7458
7459 mEarlyHintObserver = nullptr;
7460 mWebTransportSessionEventListener = nullptr;
7461 mCanceled = true;
7462 mStatus = NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) ? status : NS_ERROR_ABORT;
7463
7464 // If ORB blocked this response, doom the entry that was committed to the
7465 // cache before the (asynchronous) block decision, so it can't be reused
7466 // later (e.g. a navigation consuming a prefetched, ORB-blocked cross-origin
7467 // document). See bug 2045809.
7468 if (mChannelBlockedByOpaqueResponse && mORBValidationCacheEntry) {
7469 mORBValidationCacheEntry->AsyncDoom(nullptr);
7470 mORBValidationCacheEntry = nullptr;
7471 }
7472
7473 // If we're waiting for LNA permission result and the channel is being
7474 // cancelled, we need to call OnPermissionPromptResult with permission denied
7475 // to resume the channel properly
7476 if (mWaitingForLNAPermission) {
7477 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)
7478 ("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)
7479 "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)
7480 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)
;
7481 // Determine permission key dynamically from transaction
7482 const nsACString& permissionKey =
7483 (mTransaction && mTransaction->GetTargetIPAddressSpace() ==
7484 nsILoadInfo::IPAddressSpace::Local)
7485 ? LOOPBACK_NETWORK_PERMISSION_KEY
7486 : LOCAL_NETWORK_PERMISSION_KEY;
7487 OnPermissionPromptResult(false, permissionKey);
7488 return NS_OK;
7489 }
7490
7491 if (LoadUsedNetwork() && !mReportedNEL) {
7492 MaybeGenerateNELReport();
7493 }
7494
7495 // We don't want the content process to see any header values
7496 // when the request is blocked by ORB
7497 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref &&
7498 mResponseHead) {
7499 mResponseHead->ClearHeaders();
7500 }
7501
7502 if (mLastStatusReported && !mEndMarkerAdded &&
7503 profiler_thread_is_being_profiled_for_markers()) {
7504 // These do allocations/frees/etc; avoid if not active
7505 // mLastStatusReported can be null if Cancel is called before we added the
7506 // start marker.
7507 mEndMarkerAdded = true;
7508
7509 nsAutoCString requestMethod;
7510 GetRequestMethod(requestMethod);
7511
7512 int32_t priority = PRIORITY_NORMAL;
7513 GetPriority(&priority);
7514
7515 uint64_t size = 0;
7516 GetEncodedBodySize(&size);
7517
7518 profiler_add_network_marker(
7519 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_CANCEL,
7520 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
7521 mLoadInfo->GetInnerWindowID(),
7522 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
7523 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
7524 &mTransactionTimings, std::move(mSource));
7525 }
7526
7527 // If we don't have mTransactionPump and mCachePump, we need to call
7528 // AsyncAbort to make sure this channel's listener got notified.
7529 bool needAsyncAbort = !mTransactionPump && !mCachePump;
7530
7531 if (mProxyRequest) mProxyRequest->Cancel(status);
7532 CancelNetworkRequest(status);
7533 mCacheInputStream.CloseAndRelease();
7534 if (mCachePump) mCachePump->Cancel(status);
7535 if (mAuthProvider) mAuthProvider->Cancel(status);
7536 if (mPreflightChannel) mPreflightChannel->Cancel(status);
7537 if (mRequestContext && mOnTailUnblock) {
7538 mOnTailUnblock = nullptr;
7539 mRequestContext->CancelTailedRequest(this);
7540 CloseCacheEntry(false);
7541 needAsyncAbort = false;
7542 (void)AsyncAbort(status);
7543 } else if (channelClassifierCancellationPending) {
7544 // If mCallOnResume is not null here, it's set in
7545 // nsHttpChannel::CancelByURLClassifier. We can override mCallOnResume since
7546 // mCanceled is true and nsHttpChannel::ContinueCancellingByURLClassifier
7547 // does nothing.
7548 if (mCallOnResume) {
7549 mCallOnResume = nullptr;
7550 }
7551 // If we're coming from an asynchronous path when canceling a channel due
7552 // to safe-browsing protection, we need to AsyncAbort the channel now.
7553 needAsyncAbort = false;
7554 (void)AsyncAbort(status);
7555 }
7556
7557 // If we suspended after examining the response to await asynchronous
7558 // tracking-protection annotation (bug 2030021), a cancel while suspended
7559 // would otherwise defer the terminal teardown below (CloseCacheEntry /
7560 // AsyncAbort) to a Resume() that may never arrive. For a cache writer that
7561 // leaves the entry perpetually "being written" -- its output stream never
7562 // closed and the entry never doomed -- wedging every later same-URL
7563 // revalidating consumer forever (bug 2052908). Undo the annotation
7564 // suspension now so the cancelled pump delivers OnStopRequest and the
7565 // write-only entry is closed/doomed normally. Safe if we only primed but
7566 // never actually suspended.
7567 CancelSuspendOrResumeAfterExamineResponse();
7568
7569 // If suspended waiting for dictionary prefetch, unblock it so the channel
7570 // can proceed to cleanup. The prefetch callback may never fire, so we must
7571 // not rely on it to call Resume().
7572 if (mSuspendedForDictionary) {
7573 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)
7574 ("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)
7575 "[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)
7576 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)
;
7577 mSuspendedForDictionary = false;
7578 mCallOnResume = nullptr;
7579 // Null out the already-cancelled pumps so Resume() won't re-trigger
7580 // their OnStopRequest before AsyncAbort's DoNotifyListener can call
7581 // OnStartRequest on our listener.
7582 mTransactionPump = nullptr;
7583 mCachePump = nullptr;
7584 Resume();
7585 needAsyncAbort = true;
7586 }
7587
7588 // If we already have mCallOnResume, AsyncAbort will be called in
7589 // ResumeInternal.
7590 if (needAsyncAbort && !mCallOnResume && !mSuspendCount) {
7591 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)
;
7592 CloseCacheEntry(false);
7593 (void)AsyncAbort(status);
7594 }
7595 return NS_OK;
7596}
7597
7598void nsHttpChannel::CancelNetworkRequest(nsresult aStatus) {
7599 if (mTransaction) {
7600 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, aStatus);
7601 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7602 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)
;
7603 }
7604 }
7605 if (mTransactionPump) mTransactionPump->Cancel(aStatus);
7606
7607 mEarlyHintObserver = nullptr;
7608 mWebTransportSessionEventListener = nullptr;
7609}
7610
7611NS_IMETHODIMPnsresult
7612nsHttpChannel::Suspend() {
7613 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", 7613
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7613); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7614 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"
, 7614); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7615
7616 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
)
7617 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
)
;
7618 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)
;
7619 LogCallingScriptLocation(this);
7620
7621 ++mSuspendCount;
7622
7623 if (mSuspendCount == 1) {
7624 mSuspendTimestamp = TimeStamp::NowLoRes();
7625
7626 // Start timer to detect if we're suspended too long
7627 // This helps unblock waiting cache listeners when a channel is suspended
7628 // for an unreasonably long time.
7629 uint32_t delay = StaticPrefs::network_cache_suspended_writer_delay_ms();
7630 if (!mSuspendTimer && delay) {
7631 mSuspendTimer = NS_NewTimer();
7632 }
7633
7634 if (mSuspendTimer && delay) {
7635 RefPtr<TimerCallback> timerCallback = new TimerCallback(this);
7636 mSuspendTimer->InitWithCallback(timerCallback, delay,
7637 nsITimer::TYPE_ONE_SHOT);
7638 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)
;
7639 }
7640 }
7641
7642 nsresult rvTransaction = NS_OK;
7643 if (mTransactionPump) {
7644 rvTransaction = mTransactionPump->Suspend();
7645 }
7646 nsresult rvCache = NS_OK;
7647 if (mCachePump) {
7648 rvCache = mCachePump->Suspend();
7649 }
7650
7651 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
7652}
7653
7654// static
7655void nsHttpChannel::StaticSuspend(nsHttpChannel* aChan) { aChan->Suspend(); }
7656
7657NS_IMETHODIMPnsresult
7658nsHttpChannel::Resume() {
7659 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", 7659
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7659); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7660 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"
, 7660); return NS_ERROR_UNEXPECTED; } } while (false)
;
7661
7662 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::Resume", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7663( "nsHttpChannel::Resume"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7663 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7663( "nsHttpChannel::Resume"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7664 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)
;
7665 LogCallingScriptLocation(this);
7666
7667 if (--mSuspendCount == 0) {
7668 mSuspendTotalTime += TimeStamp::NowLoRes() - mSuspendTimestamp;
7669
7670 // Cancel suspend timer since we're resuming
7671 if (mSuspendTimer) {
7672 mSuspendTimer->Cancel();
7673 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)
;
7674 }
7675
7676 // Reset bypass flag since the writer is resuming
7677 if (mBypassCacheWriterSet && mCacheEntry) {
7678 mCacheEntry->SetBypassWriterLock(false);
7679 mBypassCacheWriterSet = false;
7680 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)
;
7681 }
7682
7683 if (mCallOnResume) {
7684 // Resume the interrupted procedure first, then resume
7685 // the pump to continue process the input stream.
7686 // Any newly created pump MUST be suspended to prevent calling
7687 // its OnStartRequest before OnStopRequest of any pre-existing
7688 // pump. AsyncResumePending ensures that.
7689 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", 7689
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7689); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7690 StoreAsyncResumePending(1);
7691
7692 std::function<nsresult(nsHttpChannel*)> callOnResume = nullptr;
7693 std::swap(callOnResume, mCallOnResume);
7694
7695 RefPtr<nsHttpChannel> self(this);
7696 nsCOMPtr<nsIRequest> transactionPump = mTransactionPump;
7697 RefPtr<nsInputStreamPump> cachePump = mCachePump;
7698
7699 nsresult rv = NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7700 "nsHttpChannel::CallOnResume",
7701 [callOnResume{std::move(callOnResume)}, self{std::move(self)},
7702 transactionPump{std::move(transactionPump)},
7703 cachePump{std::move(cachePump)}]() {
7704 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"
, 7704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7704); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7705 nsresult rv = self->CallOrWaitForResume(callOnResume);
7706 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7707 self->CloseCacheEntry(false);
7708 (void)self->AsyncAbort(rv);
7709 }
7710 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"
, 7710); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7710); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7711
7712 self->StoreAsyncResumePending(0);
7713
7714 // And now actually resume the previously existing pumps.
7715 if (transactionPump) {
7716 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)
7717 ("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)
7718 "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)
7719 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)
;
7720 transactionPump->Resume();
7721 }
7722 if (cachePump) {
7723 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)
7724 ("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)
7725 "%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)
7726 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)
;
7727 cachePump->Resume();
7728 }
7729
7730 // Any newly created pumps were suspended once because of
7731 // AsyncResumePending. Problem is that the stream listener
7732 // notification is already pending in the queue right now, because
7733 // AsyncRead doesn't (regardless if called after Suspend) respect
7734 // the suspend coutner and the right order would not be preserved.
7735 // Hence, we do another dispatch round to actually Resume after
7736 // the notification from the original pump.
7737 if (transactionPump != self->mTransactionPump &&
7738 self->mTransactionPump) {
7739 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)
7740 ("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)
7741 "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)
7742 "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)
7743 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)
;
7744
7745 nsCOMPtr<nsIRequest> pump = self->mTransactionPump;
7746 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7747 "nsHttpChannel::CallOnResume new transaction",
7748 [pump{std::move(pump)}]() { pump->Resume(); }));
7749 }
7750 if (cachePump != self->mCachePump && self->mCachePump) {
7751 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)
7752 ("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)
7753 "%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)
7754 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)
;
7755
7756 RefPtr<nsInputStreamPump> pump = self->mCachePump;
7757 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7758 "nsHttpChannel::CallOnResume new pump",
7759 [pump{std::move(pump)}]() { pump->Resume(); }));
7760 }
7761 }));
7762 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"
, 7762); return rv; } } while (false)
;
7763 return rv;
7764 }
7765 }
7766
7767 nsresult rvTransaction = NS_OK;
7768 if (mTransactionPump) {
7769 rvTransaction = mTransactionPump->Resume();
7770 }
7771
7772 nsresult rvCache = NS_OK;
7773 if (mCachePump) {
7774 rvCache = mCachePump->Resume();
7775 }
7776
7777 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
7778}
7779
7780//-----------------------------------------------------------------------------
7781// nsHttpChannel::nsIChannel
7782//-----------------------------------------------------------------------------
7783
7784NS_IMETHODIMPnsresult
7785nsHttpChannel::GetSecurityInfo(nsITransportSecurityInfo** securityInfo) {
7786 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"
, 7786); return NS_ERROR_INVALID_POINTER; } } while (false)
;
7787 *securityInfo = do_AddRef(mSecurityInfo).take();
7788 return NS_OK;
7789}
7790
7791// If any of the functions that AsyncOpen calls returns immediately an error
7792// AsyncAbort(which calls onStart/onStopRequest) does not need to be call.
7793// To be sure that they are not call ReleaseListeners() is called.
7794// If AsyncOpen returns NS_OK, after that point AsyncAbort must be called on
7795// any error.
7796NS_IMETHODIMPnsresult
7797nsHttpChannel::AsyncOpen(nsIStreamListener* aListener) {
7798 // doContentSecurityCheck and OnOpeningRequest fire observers that may
7799 // spin nested event loops; hold a strong ref to this.
7800 RefPtr<nsHttpChannel> self(this);
7801
7802 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpen", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7803( "nsHttpChannel::AsyncOpen"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7803 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7803( "nsHttpChannel::AsyncOpen"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7804 nsCOMPtr<nsIStreamListener> listener = aListener;
7805 nsresult rv =
7806 nsContentSecurityManager::doContentSecurityCheck(this, listener);
7807 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"
, 7807)
) {
7808 ReleaseListeners();
7809 return rv;
7810 }
7811
7812 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"
, 7819); 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, 7819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7813 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"
, 7819); 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, 7819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7814 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"
, 7819); 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, 7819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7815 (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"
, 7819); 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, 7819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7816 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"
, 7819); 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, 7819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7817 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"
, 7819); 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, 7819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7818 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"
, 7819); 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, 7819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7819 "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"
, 7819); 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, 7819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7820
7821 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
)
;
7822 mOpenerCallingScriptLocation = CallingScriptLocationString();
7823 LogCallingScriptLocation(this, mOpenerCallingScriptLocation);
7824 NS_CompareLoadInfoAndLoadContext(this);
7825
7826#ifdef DEBUG1
7827 AssertPrivateBrowsingId();
7828#endif
7829
7830 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", 7830
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
7831 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"
, 7831); return NS_ERROR_IN_PROGRESS; } } while (false)
;
7832 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"
, 7832); return NS_ERROR_ALREADY_OPENED; } } while (false)
;
7833
7834 if (mCanceled) {
7835 ReleaseListeners();
7836 return NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) ? mStatus : NS_ERROR_FAILURE;
7837 }
7838
7839 if (MaybeWaitForUploadStreamNormalization(listener, nullptr)) {
7840 return NS_OK;
7841 }
7842
7843 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", 7843
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7843); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7844
7845 if (!gHttpHandler->Active()) {
7846 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)
;
7847 ReleaseListeners();
7848 return NS_ERROR_NOT_AVAILABLE;
7849 }
7850
7851 rv = NS_CheckPortSafety(mURI);
7852 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7853 ReleaseListeners();
7854 return rv;
7855 }
7856
7857 // If no one called SetLoadGroup or SetNotificationCallbacks, the private
7858 // state has not been updated on PrivateBrowsingChannel (which we derive
7859 // from) Same if the loadinfo has changed since the creation of the channel.
7860 // Hence, we have to call UpdatePrivateBrowsing() here
7861 UpdatePrivateBrowsing();
7862
7863 AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(this);
7864
7865 // Recalculate the default userAgent header after the AntiTrackingInfo gets
7866 // updated because we can only know whether the site is exempted from
7867 // fingerprinting protection after we have the AntiTracking Info.
7868 //
7869 // Note that we don't recalculate the header if it has been modified since the
7870 // channel was created because we want to preserve the modified header.
7871 if (!LoadIsUserAgentHeaderModified()) {
7872 rv = mRequestHead.SetHeader(
7873 nsHttp::User_Agent,
7874 gHttpHandler->UserAgent(nsContentUtils::ShouldResistFingerprinting(
7875 this, RFPTarget::HttpUserAgent)),
7876 false, nsHttpHeaderArray::eVarietyRequestEnforceDefault);
7877 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"
, 7877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 7877); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7878 }
7879
7880 if (WaitingForTailUnblock()) {
7881 // This channel is marked as Tail and is part of a request context
7882 // that has positive number of non-tailed requestst, hence this channel
7883 // has been put to a queue.
7884 // When tail is unblocked, OnTailUnblock on this channel will be called
7885 // to continue AsyncOpen.
7886 mListener = listener;
7887 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", 7887
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 7887); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7888 mOnTailUnblock = &nsHttpChannel::AsyncOpenOnTailUnblock;
7889
7890 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)
;
7891 return NS_OK;
7892 }
7893
7894 // Remember the cookie header that was set, if any
7895 nsAutoCString cookieHeader;
7896 if (NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::Cookie, cookieHeader))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::Cookie, cookieHeader))), 1)))
) {
7897 // if this is a cache revalidaing channel (mIsStaleRevalidation), then this
7898 // represents both user cookies and cookies from cookieService
7899 mUserSetCookieHeader = std::move(cookieHeader);
7900 }
7901
7902 // Set user agent override, do so before OnOpeningRequest notification
7903 // since we want to allow consumers of that notification change or remove
7904 // the User-Agent request header.
7905 HttpBaseChannel::SetDocshellUserAgentOverride();
7906
7907 // After we notify any observers (on-opening-request, loadGroup, etc) we
7908 // must return NS_OK and return any errors asynchronously via
7909 // OnStart/OnStopRequest. Observers may add a reference to the channel
7910 // and expect to get OnStopRequest so they know when to drop the reference,
7911 // etc.
7912
7913 // notify "http-on-opening-request" observers, but not if this is a redirect
7914 if (!(mLoadFlags & LOAD_REPLACE)) {
7915 gHttpHandler->OnOpeningRequest(this);
7916 }
7917
7918 StoreIsPending(true);
7919 StoreWasOpened(true);
7920
7921 mListener = std::move(listener);
7922
7923 if (nsIOService::UseSocketProcess() &&
7924 !gIOService->IsSocketProcessLaunchComplete()) {
7925 RefPtr<nsHttpChannel> self = this;
7926 gIOService->CallOrWaitForSocketProcess(
7927 [self]() { self->AsyncOpenFinal(TimeStamp::Now()); });
7928 return NS_OK;
7929 }
7930
7931 AsyncOpenFinal(TimeStamp::Now());
7932
7933 return NS_OK;
7934}
7935
7936void nsHttpChannel::AsyncOpenFinal(TimeStamp aTimeStamp) {
7937 // We save this timestamp from outside of the if block in case we enable the
7938 // profiler after AsyncOpen().
7939 mLastStatusReported = TimeStamp::Now();
7940 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpenFinal", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7941( "nsHttpChannel::AsyncOpenFinal"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7941 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7941( "nsHttpChannel::AsyncOpenFinal"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7942 if (profiler_thread_is_being_profiled_for_markers()) {
7943 nsAutoCString requestMethod;
7944 GetRequestMethod(requestMethod);
7945
7946 profiler_add_network_marker(
7947 mURI, requestMethod, mPriority, mChannelId, NetworkLoadType::LOAD_START,
7948 mChannelCreationTimestamp, mLastStatusReported, 0, mCacheDisposition,
7949 mLoadInfo->GetInnerWindowID(),
7950 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
7951 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch());
7952 }
7953
7954 // Added due to PauseTask/DelayHttpChannel
7955 if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
7956
7957 // record asyncopen time unconditionally and clear it if we
7958 // don't want it after OnModifyRequest() weighs in. But waiting for
7959 // that to complete would mean we don't include proxy resolution in the
7960 // timing.
7961 if (!LoadAsyncOpenTimeOverriden()) {
7962 mAsyncOpenTime = aTimeStamp;
7963 }
7964
7965 // Remember we have Authorization header set here. We need to check on it
7966 // just once and early, AsyncOpen is the best place.
7967 StoreCustomAuthHeader(mRequestHead.HasHeader(nsHttp::Authorization));
7968
7969 bool willCallback = false;
7970 // We are about to do an async lookup to check if the URI is a tracker. If
7971 // yes, this channel will be canceled by channel classifier. Chances are the
7972 // lookup is not needed so CheckIsTrackerWithLocalTable() will return an
7973 // error and then we can MaybeResolveProxyAndBeginConnect() right away.
7974 // We skip the check in case this is an internal redirected channel
7975 if (NS_ShouldClassifyChannel(this, ClassifyType::ETP)) {
7976 RefPtr<nsHttpChannel> self = this;
7977 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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7978 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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7979 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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7980 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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7981 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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7982
7983 // 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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7984 // 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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7985 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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7986
7987 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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7988 }))((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"
, 7981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7981); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
;
7989 }
7990
7991 if (!willCallback) {
7992 // We can do MaybeResolveProxyAndBeginConnect immediately if
7993 // CheckIsTrackerWithLocalTable is failed. Note that we don't need to
7994 // handle the failure because BeginConnect() will return synchronously and
7995 // the caller will be responsible for handling it.
7996 MaybeResolveProxyAndBeginConnect();
7997 }
7998}
7999
8000void nsHttpChannel::MaybeResolveProxyAndBeginConnect() {
8001 nsresult rv;
8002
8003 // The common case for HTTP channels is to begin proxy resolution and return
8004 // at this point. The only time we know mProxyInfo already is if we're
8005 // proxying a non-http protocol like ftp. We don't need to discover proxy
8006 // settings if we are never going to make a network connection.
8007 if (!mProxyInfo &&
8008 !(mLoadFlags & (LOAD_ONLY_FROM_CACHE | LOAD_NO_NETWORK_IO)) &&
8009 !BypassProxy()) {
8010 nsCOMPtr<nsIProtocolProxyService> pps =
8011 mozilla::components::ProtocolProxy::Service();
8012 nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
8013 if (pps2 && pps2->IsEffectivelyDirect()) {
8014 mozilla::glean::networking::proxy_fast_path_used.Add(1);
8015 MaybeStartDNSPrefetch();
8016 } else if (NS_SUCCEEDED(ResolveProxy())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ResolveProxy())),
1)))
) {
8017 return;
8018 }
8019 }
8020
8021 if (!gHttpHandler->Active()) {
8022 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)
8023 ("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)
8024 "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)
8025 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)
;
8026 rv = NS_ERROR_NOT_AVAILABLE;
8027 } else {
8028 rv = BeginConnect();
8029 }
8030 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8031 CloseCacheEntry(false);
8032 (void)AsyncAbort(rv);
8033 }
8034}
8035
8036nsresult nsHttpChannel::AsyncOpenOnTailUnblock() {
8037 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpenOnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject8038( "nsHttpChannel::AsyncOpenOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
8038 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject8038( "nsHttpChannel::AsyncOpenOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
8039 return AsyncOpen(mListener);
8040}
8041
8042already_AddRefed<nsChannelClassifier>
8043nsHttpChannel::GetOrCreateChannelClassifier() {
8044 if (!mChannelClassifier) {
8045 mChannelClassifier = new nsChannelClassifier(this);
8046 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)
8047 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)
;
8048 }
8049
8050 RefPtr<nsChannelClassifier> classifier = mChannelClassifier;
8051 return classifier.forget();
8052}
8053
8054nsIHttpChannelInternal::ProxyDNSStrategy
8055nsHttpChannel::ComputeProxyDNSStrategy() {
8056 // When network_dns_force_use_https_rr is true, return DNS_PREFETCH_ORIGIN.
8057 // This ensures that we always perform HTTPS RR query.
8058 nsCOMPtr<nsProxyInfo> proxyInfo(static_cast<nsProxyInfo*>(mProxyInfo.get()));
8059 if (!proxyInfo || StaticPrefs::network_dns_force_use_https_rr()) {
8060 return nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN;
8061 }
8062
8063 // If the proxy is not to perform name resolution itself.
8064 return GetProxyDNSStrategyHelper(proxyInfo->Type(), proxyInfo->Flags());
8065}
8066
8067NS_IMETHODIMPnsresult
8068nsHttpChannel::GetProxyDNSStrategy(
8069 nsIHttpChannelInternal::ProxyDNSStrategy* aStrategy) {
8070 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", 8070
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
8071 *aStrategy = ComputeProxyDNSStrategy();
8072 return NS_OK;
8073}
8074
8075// BeginConnect() SHOULD NOT call AsyncAbort(). AsyncAbort will be called by
8076// functions that called BeginConnect if needed. Only
8077// MaybeResolveProxyAndBeginConnect and OnProxyAvailable ever call
8078// BeginConnect.
8079nsresult nsHttpChannel::BeginConnect() {
8080 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)
;
8081
8082 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::BeginConnect", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject8083( "nsHttpChannel::BeginConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
8083 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject8083( "nsHttpChannel::BeginConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
8084 nsresult rv;
8085
8086 // It is the caller's responsibility to not call us late in shutdown.
8087 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", 8087
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gHttpHandler->Active()"
")"); do { MOZ_CrashSequence(__null, 8087); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8088
8089 // Construct connection info object
8090 nsAutoCString host;
8091 nsAutoCString scheme;
8092 int32_t port = -1;
8093 bool isHttps = mURI->SchemeIs("https");
8094
8095 rv = mURI->GetScheme(scheme);
8096 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiHost(host);
8097 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetPort(&port);
8098 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiSpec(mSpec);
8099 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8100 return rv;
8101 }
8102
8103 // Just a warning here because some nsIURIs do not implement this method.
8104 (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", 8104
)
;
8105
8106 // Reject the URL if it doesn't specify a host
8107 if (host.IsEmpty()) {
8108 rv = NS_ERROR_MALFORMED_URI;
8109 return rv;
8110 }
8111 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)
;
8112 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)
;
8113
8114 nsCOMPtr<nsProxyInfo> proxyInfo;
8115 if (mProxyInfo) proxyInfo = do_QueryInterface(mProxyInfo);
8116
8117 if (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) {
8118 if (!proxyInfo) {
8119 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)
;
8120 return NS_ERROR_FAILURE;
8121 }
8122
8123 if (!proxyInfo->IsHTTP() && !proxyInfo->IsHTTPS()) {
8124 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)
;
8125 return NS_ERROR_FAILURE;
8126 }
8127 }
8128
8129 mRequestHead.SetHTTPS(isHttps);
8130 mRequestHead.SetOrigin(scheme, host, port);
8131
8132 AddStorageAccessHeadersToRequest();
8133 SetOriginHeader();
8134 SetDoNotTrack();
8135 SetGlobalPrivacyControl();
8136
8137 OriginAttributes originAttributes;
8138 // Regular principal in case we have a proxy.
8139 if (proxyInfo &&
8140 !StaticPrefs::privacy_partition_network_state_connection_with_proxy()) {
8141 StoragePrincipalHelper::GetOriginAttributes(
8142 this, originAttributes, StoragePrincipalHelper::eRegularPrincipal);
8143 } else {
8144 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
8145 this, originAttributes);
8146 }
8147
8148 // Adjust mCaps according to our request headers:
8149 // - If "Connection: close" is set as a request header, then do not bother
8150 // trying to establish a keep-alive connection.
8151 if (mRequestHead.HasHeaderValue(nsHttp::Connection, "close")) {
8152 mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE(1 << 0));
8153 StoreAllowHttp3(false);
8154 }
8155
8156 gHttpHandler->MaybeAddAltSvcForTesting(mURI, mUsername, mPrivateBrowsing,
8157 mCallbacks, originAttributes);
8158
8159 RefPtr<nsHttpConnectionInfo> connInfo;
8160#ifdef FUZZING
8161 if (StaticPrefs::fuzzing_necko_http3()) {
8162 connInfo =
8163 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8164 originAttributes, host, port, true);
8165 } else {
8166#endif
8167 if (mWebTransportSessionEventListener) {
8168 connInfo =
8169 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8170 originAttributes, isHttps, true, true);
8171 bool dedicated = true;
8172 nsresult rv;
8173 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
8174 do_QueryInterface(mWebTransportSessionEventListener, &rv);
8175 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"
, 8175); return rv; } } while (false)
;
8176 nsIWebTransport::HTTPVersion httpVersion;
8177 (void)wtconSettings->GetHttpVersion(&httpVersion);
8178 if (httpVersion == nsIWebTransport::HTTPVersion::h2) {
8179 connInfo =
8180 new nsHttpConnectionInfo(host, port, "h2"_ns, mUsername, proxyInfo,
8181 originAttributes, isHttps, false, true);
8182 } else {
8183 connInfo =
8184 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8185 originAttributes, isHttps, true, true);
8186 }
8187 wtconSettings->GetDedicated(&dedicated);
8188 if (dedicated) {
8189 connInfo->SetWebTransportId(
8190 nsHttpConnectionInfo::GenerateNewWebTransportId());
8191 }
8192 } else {
8193 connInfo = new nsHttpConnectionInfo(host, port, ""_ns, mUsername,
8194 proxyInfo, originAttributes, isHttps);
8195 }
8196#ifdef FUZZING
8197 }
8198#endif
8199
8200 bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
8201
8202 bool http3Allowed = Http3Allowed();
8203 if (!http3Allowed) {
8204 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
8205 }
8206
8207 RefPtr<AltSvcMapping> mapping;
8208 if (!mConnectionInfo && LoadAllowAltSvc() && // per channel
8209 !mWebTransportSessionEventListener && (http2Allowed || http3Allowed) &&
8210 !(mLoadFlags & LOAD_FRESH_CONNECTION) &&
8211 AltSvcMapping::AcceptableProxy(proxyInfo) &&
8212 (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
8213 (mapping = gHttpHandler->GetAltServiceMapping(
8214 scheme, host, port, mPrivateBrowsing, originAttributes, http2Allowed,
8215 http3Allowed))) {
8216 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)
8217 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)
8218 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)
;
8219
8220 if (!(mLoadFlags & LOAD_ANONYMOUS) && !mPrivateBrowsing) {
8221 nsAutoCString altUsedLine(mapping->AlternateHost());
8222 bool defaultPort =
8223 mapping->AlternatePort() ==
8224 (isHttps ? NS_HTTPS_DEFAULT_PORT443 : NS_HTTP_DEFAULT_PORT80);
8225 if (!defaultPort) {
8226 altUsedLine.AppendLiteral(":");
8227 altUsedLine.AppendInt(mapping->AlternatePort());
8228 }
8229 // Like what we did for 'Authorization' header, we need to do the same for
8230 // 'Alt-Used' for avoiding this header being shown in the ServiceWorker
8231 // FetchEvent.
8232 (void)mRequestHead.ClearHeader(nsHttp::Alternate_Service_Used);
8233 rv = mRequestHead.SetHeader(nsHttp::Alternate_Service_Used, altUsedLine,
8234 false,
8235 nsHttpHeaderArray::eVarietyRequestDefault);
8236 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"
, 8236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 8236); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8237 }
8238
8239 nsCOMPtr<nsIConsoleService> consoleService;
8240 consoleService = mozilla::components::Console::Service();
8241 if (consoleService && !host.Equals(mapping->AlternateHost())) {
8242 nsAutoString message(u"Alternate Service Mapping found: "_ns);
8243 AppendASCIItoUTF16(scheme, message);
8244 message.AppendLiteral(u"://");
8245 AppendASCIItoUTF16(host, message);
8246 message.AppendLiteral(u":");
8247 message.AppendInt(port);
8248 message.AppendLiteral(u" to ");
8249 AppendASCIItoUTF16(scheme, message);
8250 message.AppendLiteral(u"://");
8251 AppendASCIItoUTF16(mapping->AlternateHost(), message);
8252 message.AppendLiteral(u":");
8253 message.AppendInt(mapping->AlternatePort());
8254 consoleService->LogStringMessage(message.get());
8255 }
8256
8257 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)
;
8258 mapping->GetConnectionInfo(getter_AddRefs(mConnectionInfo), proxyInfo,
8259 originAttributes);
8260 glean::http::transaction_use_altsvc
8261 .EnumGet(glean::http::TransactionUseAltsvcLabel::eTrue)
8262 .Add();
8263 if (mConnectionInfo->IsHttp3() &&
8264 StaticPrefs::
8265 network_http_http3_force_use_alt_svc_mapping_for_testing()) {
8266 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
8267 }
8268 } else if (mConnectionInfo) {
8269 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)
;
8270 glean::http::transaction_use_altsvc
8271 .EnumGet(glean::http::TransactionUseAltsvcLabel::eFalse)
8272 .Add();
8273 } else {
8274 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)
;
8275
8276 mConnectionInfo = connInfo;
8277 glean::http::transaction_use_altsvc
8278 .EnumGet(glean::http::TransactionUseAltsvcLabel::eFalse)
8279 .Add();
8280 }
8281
8282 bool trrEnabled = false;
8283 auto dnsStrategy = ComputeProxyDNSStrategy();
8284 bool httpsRRAllowed =
8285 !LoadBeConservative() && !(mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) &&
8286 !(mLoadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
8287 mLoadInfo->GetExternalContentPolicyType() !=
8288 ExtContentPolicy::TYPE_DOCUMENT) &&
8289 dnsStrategy == nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN &&
8290 !mConnectionInfo->UsingConnect() && canUseHTTPSRRonNetwork(trrEnabled) &&
8291 StaticPrefs::network_dns_use_https_rr_as_altsvc();
8292 if (!httpsRRAllowed) {
8293 DisallowHTTPSRR(mCaps);
8294 } else if (trrEnabled) {
8295 if (nsIRequest::GetTRRMode() != nsIRequest::TRR_DISABLED_MODE) {
8296 mCaps |= NS_HTTP_FORCE_WAIT_HTTP_RR(1 << 22);
8297 }
8298 }
8299
8300 auto canUseHappyEyeballs = [&]() {
8301 if (!StaticPrefs::network_http_happy_eyeballs_enabled()) {
8302 return false;
8303 }
8304
8305 if (LoadBeConservative() || (mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11))) {
8306 return false;
8307 }
8308
8309 if (mProxyInfo) {
8310 return false;
8311 }
8312
8313 // WebSocket and WebTransport upgrades share the same rollout pref.
8314 if ((mUpgradeProtocolCallback || mWebTransportSessionEventListener) &&
8315 !StaticPrefs::network_http_happy_eyeballs_upgrade_enabled()) {
8316 return false;
8317 }
8318
8319 // Connect-only requests need the extended-CONNECT tunnel path, which is
8320 // untested with Happy Eyeballs. These only reach us via a proxy today
8321 // (already excluded above), but guard explicitly against a future
8322 // non-proxied consumer.
8323 if (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) {
8324 return false;
8325 }
8326
8327 return true;
8328 };
8329
8330 if (canUseHappyEyeballs()) {
8331 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)
;
8332 mCaps |= NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30);
8333 mCaps &= ~NS_HTTP_FORCE_WAIT_HTTP_RR(1 << 22);
8334 mConnectionInfo->SetHappyEyeballsEnabled(true);
8335 }
8336
8337 // No need to lookup HTTPSSVC record if mHTTPSSVCRecord already contains a
8338 // value.
8339 StoreUseHTTPSSVC(StaticPrefs::network_dns_upgrade_with_https_rr() &&
8340 httpsRRAllowed && mHTTPSSVCRecord.isNothing());
8341
8342 // Need to re-ask the handler, since mConnectionInfo may not be the connInfo
8343 // we used earlier
8344 if (!mConnectionInfo->IsHttp3() &&
8345 gHttpHandler->IsHttp2Excluded(mConnectionInfo)) {
8346 StoreAllowSpdy(0);
8347 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
8348 mConnectionInfo->SetNoSpdy(true);
8349 }
8350
8351 // We can be passed with the auth provider if this channel was
8352 // a result of redirect due to auth retry
8353 if (!mAuthProvider) {
8354 mAuthProvider = new nsHttpChannelAuthProvider();
8355 }
8356
8357 rv = mAuthProvider->Init(this);
8358 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8359 return rv;
8360 }
8361
8362 // check to see if authorization headers should be included
8363 // CustomAuthHeader is set in AsyncOpen if we find Authorization header
8364 rv = mAuthProvider->AddAuthorizationHeaders(LoadCustomAuthHeader());
8365 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8366 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)
8367 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)
;
8368 }
8369
8370 // if this somehow fails we can go on without it
8371 (void)gHttpHandler->AddConnectionHeader(&mRequestHead, mCaps);
8372
8373 if (!LoadIsTRRServiceChannel() &&
8374 ((mLoadFlags & LOAD_FRESH_CONNECTION) ||
8375 (!StaticPrefs::network_dns_only_refresh_on_fresh_connection() &&
8376 (mLoadFlags & VALIDATE_ALWAYS ||
8377 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
)))) {
8378 mCaps |= NS_HTTP_REFRESH_DNS(1 << 3);
8379 }
8380
8381 if (gHttpHandler->CriticalRequestPrioritization()) {
8382 if (mClassOfService.Flags() & nsIClassOfService::Leader) {
8383 mCaps |= NS_HTTP_LOAD_AS_BLOCKING(1 << 6);
8384 }
8385 if (mClassOfService.Flags() & nsIClassOfService::Unblocked) {
8386 mCaps |= NS_HTTP_LOAD_UNBLOCKED(1 << 8);
8387 }
8388 if (mClassOfService.Flags() & nsIClassOfService::UrgentStart &&
8389 gHttpHandler->IsUrgentStartEnabled()) {
8390 mCaps |= NS_HTTP_URGENT_START(1 << 12);
8391 SetPriority(nsISupportsPriority::PRIORITY_HIGHEST);
8392 }
8393 }
8394
8395 // Force-Reload should reset the persistent connection pool for this host
8396 if (mLoadFlags & LOAD_FRESH_CONNECTION) {
8397 // just the initial document resets the whole pool
8398 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
8399 gHttpHandler->AltServiceCache()->ClearAltServiceMappings();
8400 rv = gHttpHandler->DoShiftReloadConnectionCleanupWithConnInfo(
8401 mConnectionInfo);
8402 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8403 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)
8404 "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)
8405 "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)
8406 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)
;
8407 }
8408 }
8409 }
8410
8411 // We may have been cancelled already, either by on-modify-request
8412 // listeners or load group observers; in that case, we should not send the
8413 // request to the server
8414 if (mCanceled) {
8415 return mStatus;
8416 }
8417 // skip classifier checks if this channel was the result of internal auth
8418 // redirect
8419 bool shouldBeClassifiedForTracker =
8420 NS_ShouldClassifyChannel(this, ClassifyType::ETP);
8421
8422 if (shouldBeClassifiedForTracker) {
8423 if (LoadChannelClassifierCancellationPending()) {
8424 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)
8425 ("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)
8426 "[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)
8427 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)
;
8428 return NS_OK;
8429 }
8430
8431 ReEvaluateReferrerAfterTrackingStatusIsKnown();
8432 }
8433
8434 MaybeStartDNSPrefetch();
8435
8436 // Update whether the channel is on the third-party cookie blocking exception
8437 // list.
8438 CookieService::Update3PCBExceptionInfo(this);
8439
8440 rv = CallOrWaitForResume(
8441 [](nsHttpChannel* self) { return self->PrepareToConnect(); });
8442 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8443 return rv;
8444 }
8445
8446 bool shouldBeClassifiedForSafeBrowsing =
8447 NS_ShouldClassifyChannel(this, ClassifyType::SafeBrowsing);
8448
8449 if (shouldBeClassifiedForTracker) {
8450 PrimeSuspendAfterExamineResponse();
8451 RefPtr<nsHttpChannel> self(this);
8452 nsresult rv =
8453 AntiTrackingChannelClassifierUtils::CheckChannelBeforeProcessResponse(
8454 this,
8455 [self]() { self->CancelSuspendOrResumeAfterExamineResponse(); });
8456 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8457 CancelSuspendOrResumeAfterExamineResponse();
8458 }
8459 }
8460
8461 if (shouldBeClassifiedForSafeBrowsing) {
8462 // Start nsChannelClassifier to catch phishing and malware URIs.
8463 RefPtr<nsChannelClassifier> channelClassifier =
8464 GetOrCreateChannelClassifier();
8465 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)
8466 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)
;
8467 channelClassifier->Start();
8468 }
8469
8470 return NS_OK;
8471}
8472
8473void nsHttpChannel::MaybeStartDNSPrefetch() {
8474 // Start a DNS lookup very early in case the real open is queued the DNS can
8475 // happen in parallel. Do not do so in the presence of an HTTP proxy as
8476 // all lookups other than for the proxy itself are done by the proxy.
8477 // Also we don't do a lookup if the LOAD_NO_NETWORK_IO or
8478 // LOAD_ONLY_FROM_CACHE flags are set.
8479 //
8480 // We keep the DNS prefetch object around so that we can retrieve
8481 // timing information from it. There is no guarantee that we actually
8482 // use the DNS prefetch data for the real connection, but as we keep
8483 // this data around for 3 minutes by default, this should almost always
8484 // be correct, and even when it isn't, the timing still represents _a_
8485 // valid DNS lookup timing for the site, even if it is not _the_
8486 // timing we used.
8487 if (mDNSPrefetch) {
8488 return;
8489 }
8490 if ((mLoadFlags & (LOAD_NO_NETWORK_IO | LOAD_ONLY_FROM_CACHE)) ||
8491 LoadAuthRedirectedChannel()) {
8492 return;
8493 }
8494
8495 auto dnsStrategy = ComputeProxyDNSStrategy();
8496
8497 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)
8498 ("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)
8499 "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)
8500 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)
8501 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)
;
8502
8503 if (dnsStrategy == nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN) {
8504 OriginAttributes originAttributes;
8505 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
8506 this, originAttributes);
8507
8508 mDNSPrefetch = new nsDNSPrefetch(mURI, originAttributes,
8509 nsIRequest::GetTRRMode(), this, true);
8510 nsIDNSService::DNSFlags dnsFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS;
8511 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
8512 dnsFlags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
8513 }
8514
8515 bool unused;
8516 if (StaticPrefs::network_dns_use_https_rr_as_altsvc() && !mHTTPSSVCRecord &&
8517 !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) &&
8518 canUseHTTPSRRonNetwork(unused)) {
8519 (void)mDNSPrefetch->FetchHTTPSSVC(mCaps & NS_HTTP_REFRESH_DNS(1 << 3), true,
8520 [](nsIDNSHTTPSSVCRecord*) {
8521 // Do nothing. This is a DNS prefetch.
8522 });
8523 }
8524
8525 // Issue per-family prefetches (A and AAAA) so Happy Eyeballs can reuse
8526 // them instead of starting its own lookups. Skip a family that won't be
8527 // queried; with IPv6 disabled the AAAA request collapses to A, so skip it
8528 // to avoid a duplicate.
8529 bool skipIPv4 = mCaps & NS_HTTP_DISABLE_IPV4(1 << 17);
8530 bool skipIPv6 = (mCaps & NS_HTTP_DISABLE_IPV6(1 << 18)) ||
8531 StaticPrefs::network_dns_disableIPv6();
8532 (void)mDNSPrefetch->PrefetchHighPerFamily(dnsFlags, skipIPv4, skipIPv6);
8533 }
8534}
8535
8536NS_IMETHODIMPnsresult
8537nsHttpChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) {
8538 if (mCacheEntry && !LoadCacheEntryIsWriteOnly()) {
8539 int64_t dataSize = 0;
8540 mCacheEntry->GetDataSize(&dataSize);
8541 *aEncodedBodySize = dataSize;
8542 } else {
8543 *aEncodedBodySize = mLogicalOffset;
8544 }
8545 return NS_OK;
8546}
8547
8548NS_IMETHODIMPnsresult
8549nsHttpChannel::GetDecompressDictionary(DictionaryCacheEntry** aDictionary) {
8550 *aDictionary = do_AddRef(mDictDecompress).take();
8551 return NS_OK;
8552}
8553
8554NS_IMETHODIMPnsresult
8555nsHttpChannel::SetDecompressDictionary(DictionaryCacheEntry* aDictionary) {
8556 if (!aDictionary) {
8557 if (mDictDecompress && mUsingDictionary) {
8558 mDictDecompress->UseCompleted();
8559 }
8560 mUsingDictionary = false;
8561 } else {
8562 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", 8562
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDictDecompress"
")"); do { MOZ_CrashSequence(__null, 8562); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8563 aDictionary->InUse();
8564 mUsingDictionary = true;
8565 }
8566 mDictDecompress = aDictionary;
8567 return NS_OK;
8568}
8569
8570//-----------------------------------------------------------------------------
8571// nsHttpChannel::nsIHttpChannelInternal
8572//-----------------------------------------------------------------------------
8573
8574NS_IMETHODIMPnsresult
8575nsHttpChannel::GetIsAuthChannel(bool* aIsAuthChannel) {
8576 *aIsAuthChannel = mIsAuthChannel;
8577 return NS_OK;
8578}
8579
8580NS_IMETHODIMPnsresult
8581nsHttpChannel::SetChannelIsForDownload(bool aChannelIsForDownload) {
8582 if (aChannelIsForDownload) {
8583 AddClassFlags(nsIClassOfService::Throttleable);
8584 } else {
8585 ClearClassFlags(nsIClassOfService::Throttleable);
8586 }
8587
8588 return HttpBaseChannel::SetChannelIsForDownload(aChannelIsForDownload);
8589}
8590
8591base::ProcessId nsHttpChannel::ProcessId() {
8592 nsCOMPtr<nsIParentChannel> parentChannel;
8593 NS_QueryNotificationCallbacks(this, parentChannel);
8594 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
8595 return httpParent->OtherPid();
8596 }
8597 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
8598 return docParent->OtherPid();
8599 }
8600 return base::GetCurrentProcId();
8601}
8602
8603auto nsHttpChannel::AttachStreamFilter() -> RefPtr<ChildEndpointPromise> {
8604 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)
;
8605 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", 8605
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 8605); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8606
8607 if (!ProcessId()) {
8608 return ChildEndpointPromise::CreateAndReject(false, __func__);
8609 }
8610
8611 nsCOMPtr<nsIParentChannel> parentChannel;
8612 NS_QueryNotificationCallbacks(this, parentChannel);
8613
8614 // If our listener is a DocumentLoadListener, then we might handle
8615 // multi-part responses here in the parent process. The current extension
8616 // API doesn't understand the parsed multipart format, so we defer responding
8617 // here until CallOnStartRequest, and attach the StreamFilter before the
8618 // multipart handler (in the parent process!) if applicable.
8619 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
8620 StreamFilterRequest* request = mStreamFilterRequests.AppendElement();
8621 request->mPromise = new ChildEndpointPromise::Private(__func__);
8622 return request->mPromise;
8623 }
8624
8625 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
8626 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
8627 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
8628 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8629 return ChildEndpointPromise::CreateAndReject(false, __func__);
8630 }
8631
8632 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
8633 return httpParent->AttachStreamFilter(std::move(parent), std::move(child));
8634 }
8635
8636 extensions::StreamFilterParent::Attach(this, std::move(parent));
8637 return ChildEndpointPromise::CreateAndResolve(std::move(child), __func__);
8638}
8639
8640NS_IMETHODIMPnsresult
8641nsHttpChannel::GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) {
8642 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)
;
8643 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"
, 8643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimeStamp"
")"); do { MOZ_CrashSequence(__null, 8643); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8644 *aTimeStamp = mNavigationStartTimeStamp;
8645 return NS_OK;
8646}
8647
8648NS_IMETHODIMPnsresult
8649nsHttpChannel::SetNavigationStartTimeStamp(TimeStamp aTimeStamp) {
8650 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)
;
8651 mNavigationStartTimeStamp = aTimeStamp;
8652 return NS_OK;
8653}
8654
8655//-----------------------------------------------------------------------------
8656// nsHttpChannel::nsISupportsPriority
8657//-----------------------------------------------------------------------------
8658
8659NS_IMETHODIMPnsresult
8660nsHttpChannel::SetPriority(int32_t value) {
8661 int16_t newValue = std::clamp<int32_t>(value, INT16_MIN(-32767-1), INT16_MAX(32767));
8662 if (mPriority == newValue) return NS_OK;
8663
8664 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)
;
8665
8666 mPriority = newValue;
8667 if (mTransaction) {
8668 nsresult rv = gHttpHandler->RescheduleTransaction(mTransaction, mPriority);
8669 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8670 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)
8671 ("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)
8672 "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)
8673 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)
;
8674 }
8675 }
8676
8677 // If this channel is the real channel for an e10s channel, notify the
8678 // child side about the priority change as well.
8679 nsCOMPtr<nsIParentChannel> parentChannel;
8680 NS_QueryNotificationCallbacks(this, parentChannel);
8681 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
8682 if (httpParent) {
8683 httpParent->DoSendSetPriority(newValue);
8684 }
8685
8686 return NS_OK;
8687}
8688
8689//-----------------------------------------------------------------------------
8690// HttpChannel::nsIClassOfService
8691//-----------------------------------------------------------------------------
8692
8693void nsHttpChannel::OnClassOfServiceUpdated() {
8694 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)
8695 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)
;
8696
8697 if (mTransaction) {
8698 gHttpHandler->UpdateClassOfServiceOnTransaction(mTransaction,
8699 mClassOfService);
8700 }
8701 if (EligibleForTailing()) {
8702 RemoveAsNonTailRequest();
8703 } else {
8704 AddAsNonTailRequest();
8705 }
8706}
8707
8708NS_IMETHODIMPnsresult
8709nsHttpChannel::SetClassFlags(uint32_t inFlags) {
8710 uint32_t previous = mClassOfService.Flags();
8711 mClassOfService.SetFlags(inFlags);
8712 if (previous != mClassOfService.Flags()) {
8713 OnClassOfServiceUpdated();
8714 }
8715 return NS_OK;
8716}
8717
8718NS_IMETHODIMPnsresult
8719nsHttpChannel::AddClassFlags(uint32_t inFlags) {
8720 uint32_t previous = mClassOfService.Flags();
8721 mClassOfService.SetFlags(inFlags | mClassOfService.Flags());
8722 if (previous != mClassOfService.Flags()) {
8723 OnClassOfServiceUpdated();
8724 }
8725 return NS_OK;
8726}
8727
8728NS_IMETHODIMPnsresult
8729nsHttpChannel::ClearClassFlags(uint32_t inFlags) {
8730 uint32_t previous = mClassOfService.Flags();
8731 mClassOfService.SetFlags(~inFlags & mClassOfService.Flags());
8732 if (previous != mClassOfService.Flags()) {
8733 OnClassOfServiceUpdated();
8734 }
8735 return NS_OK;
8736}
8737
8738NS_IMETHODIMPnsresult
8739nsHttpChannel::SetClassOfService(ClassOfService cos) {
8740 ClassOfService previous = mClassOfService;
8741 mClassOfService = cos;
8742 if (previous != mClassOfService) {
8743 OnClassOfServiceUpdated();
8744 }
8745 return NS_OK;
8746}
8747
8748NS_IMETHODIMPnsresult
8749nsHttpChannel::SetIncremental(bool incremental) {
8750 bool previous = mClassOfService.Incremental();
8751 mClassOfService.SetIncremental(incremental);
8752 if (previous != mClassOfService.Incremental()) {
8753 OnClassOfServiceUpdated();
8754 }
8755 return NS_OK;
8756}
8757
8758//-----------------------------------------------------------------------------
8759// nsHttpChannel::nsIProtocolProxyCallback
8760//-----------------------------------------------------------------------------
8761
8762NS_IMETHODIMPnsresult
8763nsHttpChannel::OnProxyAvailable(nsICancelable* request, nsIChannel* channel,
8764 nsIProxyInfo* pi, nsresult status) {
8765 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)
8766 " 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)
8767 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)
8768 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)
;
8769 mProxyRequest = nullptr;
8770
8771 nsresult rv;
8772
8773 // If status is a failure code, then it means that we failed to resolve
8774 // proxy info. That is a non-fatal error assuming it wasn't because the
8775 // request was canceled. We just failover to DIRECT when proxy resolution
8776 // fails (failure can mean that the PAC URL could not be loaded).
8777
8778 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
8779 mProxyInfo = pi;
8780
8781 if (mProxyInfo) {
8782 nsAutoCStringN<8> type;
8783 mProxyInfo->GetType(type);
8784 uint32_t flags = 0;
8785 mProxyInfo->GetFlags(&flags);
8786
8787 if (type.EqualsLiteral("socks")) {
8788 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
8789 glean::networking::proxy_info_type
8790 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5h)
8791 .Add(1);
8792 } else {
8793 glean::networking::proxy_info_type
8794 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5)
8795 .Add(1);
8796 }
8797 } else if (type.EqualsLiteral("socks4")) {
8798 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
8799 glean::networking::proxy_info_type
8800 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4a)
8801 .Add(1);
8802 } else {
8803 glean::networking::proxy_info_type
8804 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4)
8805 .Add(1);
8806 }
8807 } else if (type.EqualsLiteral("http")) {
8808 glean::networking::proxy_info_type
8809 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttp)
8810 .Add(1);
8811 } else if (type.EqualsLiteral("https")) {
8812 glean::networking::proxy_info_type
8813 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttps)
8814 .Add(1);
8815 } else if (type.EqualsLiteral("direct")) {
8816 glean::networking::proxy_info_type
8817 .EnumGet(glean::networking::ProxyInfoTypeLabel::eDirect)
8818 .Add(1);
8819 } else {
8820 glean::networking::proxy_info_type
8821 .EnumGet(glean::networking::ProxyInfoTypeLabel::eUnknown)
8822 .Add(1);
8823 }
8824 }
8825 }
8826
8827 if (!gHttpHandler->Active()) {
8828 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)
8829 ("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)
8830 "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)
8831 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)
;
8832 rv = NS_ERROR_NOT_AVAILABLE;
8833 } else {
8834 rv = BeginConnect();
8835 }
8836
8837 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8838 CloseCacheEntry(false);
8839 (void)AsyncAbort(rv);
8840 }
8841 return rv;
8842}
8843
8844//-----------------------------------------------------------------------------
8845// nsHttpChannel::nsIProxiedChannel
8846//-----------------------------------------------------------------------------
8847
8848NS_IMETHODIMPnsresult
8849nsHttpChannel::GetProxyInfo(nsIProxyInfo** result) {
8850 if (!mConnectionInfo) {
8851 *result = do_AddRef(mProxyInfo).take();
8852 } else {
8853 *result = do_AddRef(mConnectionInfo->ProxyInfo()).take();
8854 }
8855 return NS_OK;
8856}
8857
8858//-----------------------------------------------------------------------------
8859// nsHttpChannel::nsITimedChannel
8860//-----------------------------------------------------------------------------
8861
8862NS_IMETHODIMPnsresult
8863nsHttpChannel::GetDomainLookupStart(TimeStamp* _retval) {
8864 if (mTransaction) {
8865 *_retval = mTransaction->GetDomainLookupStart();
8866 } else {
8867 *_retval = mTransactionTimings.domainLookupStart;
8868 }
8869 return NS_OK;
8870}
8871
8872NS_IMETHODIMPnsresult
8873nsHttpChannel::GetDomainLookupEnd(TimeStamp* _retval) {
8874 if (mTransaction) {
8875 *_retval = mTransaction->GetDomainLookupEnd();
8876 } else {
8877 *_retval = mTransactionTimings.domainLookupEnd;
8878 }
8879 return NS_OK;
8880}
8881
8882NS_IMETHODIMPnsresult
8883nsHttpChannel::GetConnectStart(TimeStamp* _retval) {
8884 if (mTransaction) {
8885 *_retval = mTransaction->GetConnectStart();
8886 } else {
8887 *_retval = mTransactionTimings.connectStart;
8888 }
8889 return NS_OK;
8890}
8891
8892NS_IMETHODIMPnsresult
8893nsHttpChannel::GetTcpConnectEnd(TimeStamp* _retval) {
8894 if (mTransaction) {
8895 *_retval = mTransaction->GetTcpConnectEnd();
8896 } else {
8897 *_retval = mTransactionTimings.tcpConnectEnd;
8898 }
8899 return NS_OK;
8900}
8901
8902NS_IMETHODIMPnsresult
8903nsHttpChannel::GetSecureConnectionStart(TimeStamp* _retval) {
8904 if (mTransaction) {
8905 *_retval = mTransaction->GetSecureConnectionStart();
8906 } else {
8907 *_retval = mTransactionTimings.secureConnectionStart;
8908 }
8909 return NS_OK;
8910}
8911
8912NS_IMETHODIMPnsresult
8913nsHttpChannel::GetConnectEnd(TimeStamp* _retval) {
8914 if (mTransaction) {
8915 *_retval = mTransaction->GetConnectEnd();
8916 } else {
8917 *_retval = mTransactionTimings.connectEnd;
8918 }
8919 return NS_OK;
8920}
8921
8922NS_IMETHODIMPnsresult
8923nsHttpChannel::GetRequestStart(TimeStamp* _retval) {
8924 if (mTransaction) {
8925 *_retval = mTransaction->GetRequestStart();
8926 } else {
8927 *_retval = mTransactionTimings.requestStart;
8928 }
8929 return NS_OK;
8930}
8931
8932NS_IMETHODIMPnsresult
8933nsHttpChannel::GetResponseStart(TimeStamp* _retval) {
8934 if (mTransaction) {
8935 *_retval = mTransaction->GetResponseStart();
8936 } else {
8937 *_retval = mTransactionTimings.responseStart;
8938 }
8939 return NS_OK;
8940}
8941
8942NS_IMETHODIMPnsresult
8943nsHttpChannel::GetFirstInterimResponseStart(TimeStamp* _retval) {
8944 if (mTransaction) {
8945 *_retval = mTransaction->GetFirstInterimResponseStart();
8946 } else {
8947 *_retval = mTransactionTimings.firstInterimResponseStart;
8948 }
8949 return NS_OK;
8950}
8951
8952NS_IMETHODIMPnsresult
8953nsHttpChannel::GetFinalResponseHeadersStart(TimeStamp* _retval) {
8954 if (mTransaction) {
8955 *_retval = mTransaction->GetFinalResponseHeadersStart();
8956 } else {
8957 *_retval = mTransactionTimings.finalResponseHeadersStart;
8958 }
8959 return NS_OK;
8960}
8961
8962NS_IMETHODIMPnsresult
8963nsHttpChannel::GetResponseEnd(TimeStamp* _retval) {
8964 if (mTransaction) {
8965 *_retval = mTransaction->GetResponseEnd();
8966 } else {
8967 *_retval = mTransactionTimings.responseEnd;
8968 }
8969 return NS_OK;
8970}
8971
8972NS_IMETHODIMPnsresult
8973nsHttpChannel::GetTransactionPending(TimeStamp* _retval) {
8974 if (mTransaction) {
8975 *_retval = mTransaction->GetPendingTime();
8976 } else {
8977 *_retval = mTransactionTimings.transactionPending;
8978 }
8979 return NS_OK;
8980}
8981
8982//-----------------------------------------------------------------------------
8983// nsHttpChannel::nsIHttpAuthenticableChannel
8984//-----------------------------------------------------------------------------
8985
8986NS_IMETHODIMPnsresult
8987nsHttpChannel::GetIsSSL(bool* aIsSSL) {
8988 // this attribute is really misnamed - it wants to know if
8989 // https:// is being used. SSL might be used to cover http://
8990 // in some circumstances (proxies, http/2, etc..)
8991 return mURI->SchemeIs("https", aIsSSL);
8992}
8993
8994NS_IMETHODIMPnsresult
8995nsHttpChannel::GetProxyMethodIsConnect(bool* aProxyMethodIsConnect) {
8996 *aProxyMethodIsConnect = mConnectionInfo->UsingConnect();
8997 return NS_OK;
8998}
8999
9000NS_IMETHODIMPnsresult
9001nsHttpChannel::GetServerResponseHeader(nsACString& value) {
9002 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
9003 return mResponseHead->GetHeader(nsHttp::Server, value);
9004}
9005
9006NS_IMETHODIMPnsresult
9007nsHttpChannel::GetProxyChallenges(nsACString& value) {
9008 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
9009 return mResponseHead->GetHeader(nsHttp::Proxy_Authenticate, value);
9010}
9011
9012NS_IMETHODIMPnsresult
9013nsHttpChannel::GetWWWChallenges(nsACString& value) {
9014 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
9015 return mResponseHead->GetHeader(nsHttp::WWW_Authenticate, value);
9016}
9017
9018NS_IMETHODIMPnsresult
9019nsHttpChannel::SetProxyCredentials(const nsACString& value) {
9020 return mRequestHead.SetHeader(nsHttp::Proxy_Authorization, value);
9021}
9022
9023NS_IMETHODIMPnsresult
9024nsHttpChannel::SetWWWCredentials(const nsACString& value) {
9025 // This method is called when various browser initiated authorization
9026 // code sets the credentials. We need to flag this header as the
9027 // "browser default" so it does not show up in the ServiceWorker
9028 // FetchEvent. This may actually get called more than once, though,
9029 // so we clear the header first since "default" headers are not
9030 // allowed to overwrite normally.
9031 (void)mRequestHead.ClearHeader(nsHttp::Authorization);
9032 return mRequestHead.SetHeader(nsHttp::Authorization, value, false,
9033 nsHttpHeaderArray::eVarietyRequestDefault);
9034}
9035
9036//-----------------------------------------------------------------------------
9037// Methods that nsIHttpAuthenticableChannel dupes from other IDLs, which we
9038// get from HttpBaseChannel, must be explicitly forwarded, because C++ sucks.
9039//-----------------------------------------------------------------------------
9040
9041NS_IMETHODIMPnsresult
9042nsHttpChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
9043 return HttpBaseChannel::GetLoadFlags(aLoadFlags);
9044}
9045
9046NS_IMETHODIMPnsresult
9047nsHttpChannel::GetURI(nsIURI** aURI) { return HttpBaseChannel::GetURI(aURI); }
9048
9049NS_IMETHODIMPnsresult
9050nsHttpChannel::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks) {
9051 return HttpBaseChannel::GetNotificationCallbacks(aCallbacks);
9052}
9053
9054NS_IMETHODIMPnsresult
9055nsHttpChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
9056 return HttpBaseChannel::GetLoadGroup(aLoadGroup);
9057}
9058
9059NS_IMETHODIMPnsresult
9060nsHttpChannel::GetRequestMethod(nsACString& aMethod) {
9061 return HttpBaseChannel::GetRequestMethod(aMethod);
9062}
9063
9064//-----------------------------------------------------------------------------
9065// nsHttpChannel::nsIRequestObserver
9066//-----------------------------------------------------------------------------
9067
9068void nsHttpChannel::RecordOnStartTelemetry(nsresult aStatus,
9069 bool aIsNavigation) {
9070 glean::http::channel_onstart_success
9071 .EnumGet(static_cast<glean::http::ChannelOnstartSuccessLabel>(
9072 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))))
9073 .Add();
9074
9075 mozilla::glean::networking::http_channel_onstart_status
9076 .Get(NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) ? "successful"_ns : "fail"_ns)
9077 .Add(1);
9078
9079 if (mTransaction) {
9080 glean::networking::http3_channel_onstart_success
9081 .Get((mTransaction->IsHttp3Used()) ? "http3"_ns : "no_http3"_ns,
9082 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) ? "true"_ns : "false"_ns)
9083 .Add();
9084 }
9085
9086 enum class HttpOnStartState : uint32_t {
9087 Success = 0,
9088 DNSError = 1,
9089 Others = 2,
9090 };
9091
9092 if (TRRService::Get() && TRRService::Get()->IsConfirmed()) {
9093 // Note this telemetry probe is not working when DNS resolution is done in
9094 // the socket process.
9095 HttpOnStartState state = HttpOnStartState::Others;
9096 if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
9097 state = HttpOnStartState::Success;
9098 } else if (aStatus == NS_ERROR_UNKNOWN_HOST ||
9099 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST) {
9100 state = HttpOnStartState::DNSError;
9101 }
9102
9103 if (aIsNavigation) {
9104 glean::http::channel_page_onstart_success_trr
9105 .Get(TRRService::ProviderKey())
9106 .AccumulateSingleSample(static_cast<uint32_t>(state));
9107 } else {
9108 glean::http::channel_sub_onstart_success_trr
9109 .Get(TRRService::ProviderKey())
9110 .AccumulateSingleSample(static_cast<uint32_t>(state));
9111 }
9112 }
9113
9114 if (nsIOService::UseSocketProcess() && mTransaction) {
9115 const TimeStamp now = TimeStamp::Now();
9116 TimeStamp responseEnd = mTransaction->GetResponseEnd();
9117 if (!responseEnd.IsNull()) {
9118 PerfStats::RecordMeasurement(PerfStats::Metric::ResponseEndSocketToParent,
9119 now - responseEnd);
9120 }
9121
9122 mOnStartRequestStartTime = mTransaction->GetOnStartRequestStartTime();
9123 if (!mOnStartRequestStartTime.IsNull()) {
9124 PerfStats::RecordMeasurement(
9125 PerfStats::Metric::OnStartRequestSocketToParent,
9126 now - mOnStartRequestStartTime);
9127 }
9128 } else {
9129 mOnStartRequestStartTime = TimeStamp::Now();
9130 }
9131}
9132
9133static bool hasConnectivity() {
9134 if (RefPtr<NetworkConnectivityService> ncs =
9135 NetworkConnectivityService::GetSingleton()) {
9136 nsINetworkConnectivityService::ConnectivityState state;
9137 if (NS_SUCCEEDED(ncs->GetIPv4(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetIPv4(&
state))), 1)))
&&
9138 state == nsINetworkConnectivityService::OK) {
9139 return true;
9140 }
9141 // We should also check for IPv6 connectivity here, but since
9142 // quite a few mozilla domains don't have IPv6 records yet,
9143 // we might incorrectly fallback to a backup domain on
9144 // IPv6 only networks.
9145 // When bug 1665605 gets fixed we can also return true when only IPv6 is OK.
9146 }
9147
9148 return false;
9149};
9150
9151static already_AddRefed<nsIURI> GetFallbackURI(nsIURI* aURI) {
9152 nsresult rv;
9153 nsAutoCString host;
9154 aURI->GetHost(host);
9155 nsCOMPtr<nsIURI> backupURI;
9156
9157 nsAutoCString fallbackDomain;
9158 if (!gIOService->GetFallbackDomain(host, fallbackDomain)) {
9159 return nullptr;
9160 }
9161
9162 rv = NS_MutateURI(aURI).SetHost(fallbackDomain).Finalize(backupURI);
9163 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9164 return nullptr;
9165 }
9166
9167 return backupURI.forget();
9168}
9169
9170// The essential domain fallback only targets Firefox's own internal requests
9171// Opening a link from browser UI or a priviledged page still carries the
9172// system principal so we need to exclude these regular pageloads.
9173static bool IsInternalSystemLoad(nsILoadInfo* aLoadInfo) {
9174 if (!aLoadInfo->TriggeringPrincipal()->IsSystemPrincipal()) {
9175 return false;
9176 }
9177
9178 ExtContentPolicyType type = aLoadInfo->GetExternalContentPolicyType();
9179 return type != ExtContentPolicy::TYPE_DOCUMENT &&
9180 type != ExtContentPolicy::TYPE_SUBDOCUMENT;
9181}
9182
9183// static
9184nsHttpChannel::EssentialDomainCategory
9185nsHttpChannel::GetEssentialDomainCategory(nsCString& domain) {
9186 if (StringEndsWith(domain, ".addons.mozilla.org"_ns)) {
9187 return EssentialDomainCategory::SubAddonsMozillaOrg;
9188 }
9189 if (domain == "addons.mozilla.org"_ns) {
9190 return EssentialDomainCategory::AddonsMozillaOrg;
9191 }
9192 if (domain == "aus5.mozilla.org"_ns) {
9193 return EssentialDomainCategory::Aus5MozillaOrg;
9194 }
9195 if (domain == "firefox.settings.services.mozilla.com"_ns ||
9196 domain == "firefox-settings-attachments.cdn.mozilla.net"_ns ||
9197 domain == "content-signature-2.cdn.mozilla.net"_ns) {
9198 return EssentialDomainCategory::RemoteSettings;
9199 }
9200 if (domain == "incoming.telemetry.mozilla.com"_ns) {
9201 return EssentialDomainCategory::Telemetry;
9202 }
9203 return EssentialDomainCategory::Other;
9204}
9205
9206// Helper function to send LNA access info to child process for console logging
9207// The child process has access to CallingScriptLocationString() which requires
9208// JS context
9209static void ReportLNAAccessToConsole(nsHttpChannel* aChannel,
9210 const char* aMessageName,
9211 const nsACString& aPromptAction = ""_ns) {
9212 // Send IPC to child process to log to console with script location
9213 nsCOMPtr<nsIParentChannel> parentChannel;
9214 NS_QueryNotificationCallbacks(aChannel, parentChannel);
9215 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
9216 NetAddr peerAddr = aChannel->GetPeerAddr();
9217
9218 // Fetch top-level site URI in parent process and pass via IPC.
9219 // We need to fetch this here because with Fission (site isolation),
9220 // cross-site iframes run in separate content processes and cannot
9221 // access the top-level document in a different process.
9222 nsAutoCString topLevelSite;
9223 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
9224 if (loadInfo) {
9225 RefPtr<mozilla::dom::BrowsingContext> bc;
9226 loadInfo->GetBrowsingContext(getter_AddRefs(bc));
9227 if (bc && bc->Top() && bc->Top()->Canonical()) {
9228 RefPtr<mozilla::dom::WindowGlobalParent> topWindowGlobal =
9229 bc->Top()->Canonical()->GetCurrentWindowGlobal();
9230 if (topWindowGlobal) {
9231 nsIPrincipal* topPrincipal = topWindowGlobal->DocumentPrincipal();
9232 if (topPrincipal) {
9233 nsCOMPtr<nsIURI> topURI = topPrincipal->GetURI();
9234 if (topURI) {
9235 (void)topURI->GetSpec(topLevelSite);
9236 }
9237 }
9238 }
9239 }
9240 }
9241
9242 httpParent->DoSendReportLNAToConsole(peerAddr, nsCString(aMessageName),
9243 nsCString(aPromptAction),
9244 topLevelSite);
9245 }
9246}
9247
9248nsresult nsHttpChannel::ProcessLNAActions() {
9249 if (!mTransaction) {
9250 return NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED;
9251 }
9252
9253 // Suspend to block any notification to the channel.
9254 // This will get resumed in
9255 // nsHttpChannel::OnPermissionPromptResult
9256 UpdateCurrentIpAddressSpace();
9257 mWaitingForLNAPermission = true;
9258 Suspend();
9259 auto targetAddressSpace = mTransaction->GetTargetIPAddressSpace();
9260 auto permissionKey = targetAddressSpace == nsILoadInfo::IPAddressSpace::Local
9261 ? LOOPBACK_NETWORK_PERMISSION_KEY
9262 : LOCAL_NETWORK_PERMISSION_KEY;
9263 LNAPermission permissionUpdateResult =
9264 UpdateLocalNetworkAccessPermissions(permissionKey);
9265
9266 if (LNAPermission::Granted == permissionUpdateResult) {
9267 // permission granted (auto-allow via permanent permission)
9268 mLNAPromptAction.AssignLiteral("auto_allow");
9269 return OnPermissionPromptResult(true, permissionKey);
9270 }
9271
9272 if (LNAPermission::Denied == permissionUpdateResult) {
9273 // permission denied (auto-deny via permanent permission)
9274 mLNAPromptAction.AssignLiteral("auto_deny");
9275 return OnPermissionPromptResult(false, permissionKey);
9276 }
9277
9278 // If we get here, we don't have any permission to access the local
9279 // host/network. We need to prompt the user for action
9280 auto permissionPromptCallback =
9281 [self = RefPtr{this}](bool aPermissionGranted, const nsACString& aType,
9282 bool aPromptShown) -> void {
9283 // Set mLNAPromptAction based on whether prompt was shown and user response
9284 if (aPromptShown) {
9285 if (aPermissionGranted) {
9286 self->mLNAPromptAction.AssignLiteral("prompt_allow");
9287 } else {
9288 self->mLNAPromptAction.AssignLiteral("prompt_deny");
9289 }
9290 } else {
9291 if (aPermissionGranted) {
9292 self->mLNAPromptAction.AssignLiteral("auto_allow");
9293 } else {
9294 self->mLNAPromptAction.AssignLiteral("auto_deny");
9295 }
9296 }
9297 self->OnPermissionPromptResult(aPermissionGranted, aType);
9298 };
9299
9300 RefPtr<LNAPermissionRequest> request = new LNAPermissionRequest(
9301 std::move(permissionPromptCallback), mLoadInfo, permissionKey);
9302
9303 // Log to console before requesting permission
9304 ReportLNAAccessToConsole(this, "LocalNetworkAccessPermissionRequired");
9305
9306 // This invokes callback nsHttpChannel::OnPermissionPromptResult
9307 // synchronously if the permission is already granted or denied
9308 // if permission is not available we prompt the user and in that case
9309 // nsHttpChannel::OnPermissionPromptResult is invoked asynchronously once
9310 // the user responds to the prompt
9311 return request->RequestPermission();
9312}
9313
9314void nsHttpChannel::UpdateCurrentIpAddressSpace() {
9315 if (!mTransaction) {
9316 return;
9317 }
9318
9319 if (mPeerAddr.GetIpAddressSpace() == nsILoadInfo::IPAddressSpace::Unknown) {
9320 // fetch peer address from transaction
9321 bool isTrr;
9322 bool echConfigUsed;
9323 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
9324 mEffectiveTRRMode, mTRRSkipReason,
9325 echConfigUsed);
9326 }
9327
9328 nsILoadInfo::IPAddressSpace docAddressSpace = mPeerAddr.GetIpAddressSpace();
9329 mLoadInfo->SetIpAddressSpace(docAddressSpace);
9330 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
9331 if (type == ExtContentPolicy::TYPE_DOCUMENT ||
9332 type == ExtContentPolicy::TYPE_SUBDOCUMENT) {
9333 RefPtr<mozilla::dom::BrowsingContext> bc;
9334 mLoadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
9335 if (bc) {
9336 bc->SetCurrentIPAddressSpace(docAddressSpace);
9337 }
9338
9339 if (mCacheEntry) {
9340 // store the ipaddr information into the cache metadata entry
9341 if (mPeerAddr.GetIpAddressSpace() !=
9342 nsILoadInfo::IPAddressSpace::Unknown) {
9343 uint16_t port;
9344 mPeerAddr.GetPort(&port);
9345 mCacheEntry->SetMetaDataElement("peer-ip-address",
9346 mPeerAddr.ToString().get());
9347 mCacheEntry->SetMetaDataElement("peer-port", ToString(port).c_str());
9348 }
9349 }
9350 }
9351}
9352
9353NS_IMETHODIMPnsresult
9354nsHttpChannel::OnStartRequest(nsIRequest* request) {
9355 nsresult rv;
9356
9357 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"
, 9357); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequestObserversCalled()"
")"); do { MOZ_CrashSequence(__null, 9357); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9358
9359 AUTO_PROFILER_LABEL("nsHttpChannel::OnStartRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject9359( "nsHttpChannel::OnStartRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
9360 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnStartRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject9361( "nsHttpChannel::OnStartRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
9361 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject9361( "nsHttpChannel::OnStartRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
9362
9363 if (!(mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))))) {
9364 // capture the request's status, so our consumers will know ASAP of any
9365 // connection failures, etc - bug 93581
9366 nsresult status;
9367 request->GetStatus(&status);
9368 mStatus = status;
9369 }
9370
9371 if (mStatus == NS_ERROR_NON_LOCAL_CONNECTION_REFUSED) {
9372 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"
, 9378, _profileOrCrashReason.get()); } while (false)
9373 "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"
, 9378, _profileOrCrashReason.get()); } while (false)
9374 "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"
, 9378, _profileOrCrashReason.get()); } while (false)
9375 "[%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"
, 9378, _profileOrCrashReason.get()); } while (false)
9376 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"
, 9378, _profileOrCrashReason.get()); } while (false)
9377 : "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"
, 9378, _profileOrCrashReason.get()); } while (false)
9378 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"
, 9378, _profileOrCrashReason.get()); } while (false)
;
9379 }
9380
9381 if (mStatus == NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED) {
9382 return ProcessLNAActions();
9383 }
9384
9385 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)
9386 "]\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)
9387 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)
;
9388
9389 RecordOnStartTelemetry(mStatus, IsNavigation());
9390
9391 // Make sure things are what we expect them to be...
9392 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"
, 9393); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { MOZ_CrashSequence(__null
, 9393); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
9393 "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"
, 9393); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { MOZ_CrashSequence(__null
, 9393); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9394
9395 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"
, 9399); 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, 9399); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9396 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"
, 9399); 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, 9399); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9397 "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"
, 9399); 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, 9399); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9398 "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"
, 9399); 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, 9399); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9399 "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"
, 9399); 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, 9399); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9400
9401 StoreAfterOnStartRequestBegun(true);
9402 if (mOnStartRequestTimestamp.IsNull()) {
9403 mOnStartRequestTimestamp = TimeStamp::Now();
9404 }
9405
9406 mozilla::glean::networking::http_onstart_suspend_total_time
9407 .AccumulateRawDuration(mSuspendTotalTime);
9408
9409 if (mTransaction) {
9410 mProxyConnectResponseHead = mTransaction->GetProxyConnectResponseHead();
9411 if (request == mTransactionPump) {
9412 StoreDataSentToChildProcess(mTransaction->DataSentToChildProcess());
9413 }
9414
9415 if (!mSecurityInfo && !mCachePump) {
9416 // grab the security info from the connection object; the transaction
9417 // is guaranteed to own a reference to the connection.
9418 mSecurityInfo = mTransaction->SecurityInfo();
9419 }
9420
9421 uint32_t stage = mTransaction->HTTPSSVCReceivedStage();
9422 if (!LoadHTTPSSVCTelemetryReported() && stage != HTTPSSVC_NOT_USED) {
9423 glean::http::dns_httpssvc_record_receiving_stage.AccumulateSingleSample(
9424 stage);
9425 }
9426
9427 if (HTTPS_RR_IS_USED(stage)(stage > HTTPSSVC_NOT_PRESENT && stage < HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_2
)
) {
9428 nsAutoCString suffix(LoadEchConfigUsed() ? "_ech_used" : "");
9429 // Determine the result string based on the status.
9430 nsAutoCString result(NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) ? "success" : "failure");
9431 result.Append(suffix);
9432
9433 mozilla::glean::networking::http_channel_onstart_success_https_rr
9434 .Get(result)
9435 .Add(1);
9436 StoreHasHTTPSRR(true);
9437 }
9438
9439 StoreLoadedBySocketProcess(mTransaction->AsHttpTransactionParent() !=
9440 nullptr);
9441
9442 bool isTrr;
9443 bool echConfigUsed;
9444 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
9445 mEffectiveTRRMode, mTRRSkipReason,
9446 echConfigUsed);
9447 // update IP AddressSpace for non-proxy connections and tests
9448 // We need to update the browsing context for tests as browser tests
9449 // uses local proxy to connect to
9450 // external domains
9451 if (!mProxyInfo || xpc::IsInAutomation()) {
9452 // If this is main document load or iframe store the IP Address space in
9453 // the browsing context
9454 UpdateCurrentIpAddressSpace();
9455 }
9456
9457 StoreResolvedByTRR(isTrr);
9458 StoreEchConfigUsed(echConfigUsed);
9459 } else { // !mTransaction
9460 MaybeUpdateDocumentIPAddressSpaceFromCache();
9461 }
9462
9463 if (!mCanceled && mTransaction && IsInternalSystemLoad(mLoadInfo)) {
9464 // We have to report telemetry before we actually attempt to redirect to
9465 // the fallback domain because doing so will change mStatus
9466 ReportSystemChannelTelemetry(mStatus);
9467 }
9468
9469 // don't enter this block if we're reading from the cache...
9470 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mCachePump && mTransaction) {
9471 // mTransactionPump doesn't hit OnInputStreamReady and call this until
9472 // all of the response headers have been acquired, so we can take
9473 // ownership of them from the transaction.
9474 RefPtr<nsHttpConnectionInfo> connInfo;
9475 mResponseHead =
9476 mTransaction->TakeResponseHeadAndConnInfo(getter_AddRefs(connInfo));
9477 mSupportsHTTP3 = mTransaction->GetSupportsHTTP3();
9478 // the response head may be null if the transaction was cancelled. in
9479 // which case we just need to call OnStartRequest/OnStopRequest.
9480 if (mResponseHead) {
9481 if (AntiTrackingUtils::ProcessStorageAccessHeadersShouldRetry(this)) {
9482 // force reload. Doom cache to avoid redirect loop
9483 if (mCacheEntry) {
9484 mCacheEntry->AsyncDoom(nullptr);
9485 }
9486
9487 auto storeAllowStorageAccess = [&](nsIChannel* aRedirectedChannel) {
9488 RefPtr<nsHttpChannel> httpChan = do_QueryObject(aRedirectedChannel);
9489 if (httpChan) {
9490 httpChan->StoreStorageAccessReloadChannel(true);
9491 }
9492 };
9493
9494 rv = StartRedirectChannelToURI(mURI,
9495 nsIChannelEventSink::REDIRECT_INTERNAL,
9496 storeAllowStorageAccess);
9497 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9498 Cancel(rv);
9499 return CallOnStartRequest();
9500 }
9501 return NS_OK;
9502 }
9503 return ProcessResponse(connInfo);
9504 }
9505
9506 NS_WARNING("No response head in OnStartRequest")NS_DebugBreak(NS_DEBUG_WARNING, "No response head in OnStartRequest"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9506)
;
9507 }
9508
9509 // cache file could be deleted on our behalf, it could contain errors or
9510 // it failed to allocate memory, reload from network here.
9511 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)
) {
9512 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)
;
9513 mCacheEntry->AsyncDoom(nullptr);
9514 rv =
9515 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
9516 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) return NS_OK;
9517 }
9518
9519 // If this is a system principal request to an essential domain and we
9520 // currently have connectivity, then check if there's a fallback domain we
9521 // can use to retry. If so we redirect to the fallback domain.
9522 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) && !mCanceled && IsInternalSystemLoad(mLoadInfo)) {
9523 if (StaticPrefs::network_essential_domains_fallback() &&
9524 hasConnectivity()) {
9525 auto passDomainCategory = [&](nsIChannel* aRedirectedChannel) {
9526 RefPtr<nsHttpChannel> httpChan = do_QueryObject(aRedirectedChannel);
9527 if (httpChan) {
9528 nsAutoCString host;
9529 mURI->GetHost(host);
9530 httpChan->mEssentialDomainCategory =
9531 Some(GetEssentialDomainCategory(host));
9532 }
9533 };
9534
9535 if (nsCOMPtr<nsIURI> fallbackURI = GetFallbackURI(mURI)) {
9536 rv = StartRedirectChannelToURI(fallbackURI,
9537 nsIChannelEventSink::REDIRECT_INTERNAL,
9538 passDomainCategory);
9539 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9540 nsCOMPtr<nsIObserverService> obsService =
9541 services::GetObserverService();
9542 if (obsService)
9543 obsService->NotifyObservers(static_cast<nsIHttpChannel*>(this),
9544 "httpchannel-fallback", nullptr);
9545 return NS_OK;
9546 }
9547 }
9548 }
9549 }
9550
9551 // avoid crashing if mListener happens to be null...
9552 if (!mListener) {
9553 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"
, 9553); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "mListener is null" ")"); do { MOZ_CrashSequence
(__null, 9553); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9554 return NS_OK;
9555 }
9556
9557 rv = ProcessCrossOriginSecurityHeaders();
9558 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9559 mStatus = rv;
9560 HandleAsyncAbort();
9561 return rv;
9562 }
9563
9564 // No process change is needed, so continue on to ContinueOnStartRequest1.
9565 return ContinueOnStartRequest1(rv);
9566}
9567
9568void nsHttpChannel::MaybeUpdateDocumentIPAddressSpaceFromCache() {
9569 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"
, 9569); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 9569); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9570 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
9571
9572 // Update the IPAddressSpace in the BrowsingContext only for main or sub
9573 // document
9574 if (type != ExtContentPolicy::TYPE_DOCUMENT &&
9575 type != ExtContentPolicy::TYPE_SUBDOCUMENT) {
9576 return;
9577 }
9578
9579 RefPtr<mozilla::dom::BrowsingContext> bc;
9580 mLoadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
9581
9582 if (!bc || !mCacheEntry) {
9583 return;
9584 }
9585
9586 nsAutoCString ipAddrStr, portStr;
9587 mCacheEntry->GetMetaDataElement("peer-ip-address", getter_Copies(ipAddrStr));
9588 mCacheEntry->GetMetaDataElement("peer-port", getter_Copies(portStr));
9589
9590 nsresult rv;
9591 uint32_t port = portStr.ToInteger(&rv);
9592
9593 if (!ipAddrStr.IsEmpty() && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9594 NetAddr ipAddr;
9595 rv = ipAddr.InitFromString(ipAddrStr, port);
9596 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"
, 9596); return; } } while (false)
;
9597 mLoadInfo->SetIpAddressSpace(ipAddr.GetIpAddressSpace());
9598 bc->SetCurrentIPAddressSpace(ipAddr.GetIpAddressSpace());
9599 }
9600}
9601
9602nsresult nsHttpChannel::OnPermissionPromptResult(bool aGranted,
9603 const nsACString& aType) {
9604 mWaitingForLNAPermission = false;
9605
9606 if (aGranted) {
9607 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)
9608 ("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)
9609 "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)
9610 "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)
9611 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)
;
9612 // we need to cache this data as permission manager is updated async and
9613 // might not be reflected immediately
9614 if (aType == LOOPBACK_NETWORK_PERMISSION_KEY) {
9615 mLNAPermission.mLocalHostPermission = LNAPermission::Granted;
9616 }
9617
9618 if (aType == LOCAL_NETWORK_PERMISSION_KEY) {
9619 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
9620 }
9621 // reset the transaction
9622 mTransaction = nullptr;
9623
9624 // resets streams and listener. Ensures we dont get any more callbacks to
9625 // nsHttpChannel from the pumps
9626 RefPtr<nsInputStreamPump> pump = do_QueryObject(mTransactionPump);
9627 if (pump) {
9628 pump->Reset();
9629 }
9630 mTransactionPump = nullptr;
9631
9632 // reset the status as we are going to replay the transaction
9633 mStatus = nsresult::NS_OK;
9634
9635 // allow notifications for the channel
9636 Resume();
9637 // replay the transaction with permisions granted
9638 return CallOrWaitForResume(
9639 [](auto* self) -> nsresult { return self->DoConnect(nullptr); });
9640 }
9641
9642 // permission denied
9643 // resume the transaction pump, we should get the OnStopRequest Notification
9644 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)
9645 ("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)
9646 "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)
9647 "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)
9648 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)
;
9649
9650 Resume();
9651
9652 if (aType == LOOPBACK_NETWORK_PERMISSION_KEY) {
9653 mLNAPermission.mLocalHostPermission = LNAPermission::Denied;
9654 }
9655
9656 if (aType == LOCAL_NETWORK_PERMISSION_KEY) {
9657 mLNAPermission.mLocalNetworkPermission = LNAPermission::Denied;
9658 }
9659
9660 if (!mSuspendCount) {
9661 return ContinueOnStartRequest1(
9662 nsresult::NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED);
9663 }
9664 // channel is suspended state. We will continue when the channel is
9665 // resumed
9666 return CallOrWaitForResume([](auto* self) {
9667 return self->ContinueOnStartRequest1(
9668 nsresult::NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED);
9669 });
9670}
9671
9672nsresult nsHttpChannel::ContinueOnStartRequest1(nsresult result) {
9673 nsresult rv;
9674
9675 // if process selection failed, cancel this load.
9676 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
9677 Cancel(result);
9678 return CallOnStartRequest();
9679 }
9680
9681 // before we start any content load, check for redirectTo being called
9682 // this code is executed mainly before we start load from the cache
9683 if (mAPIRedirectTo && !mCanceled) {
9684 nsAutoCString redirectToSpec;
9685 mAPIRedirectTo->first()->GetAsciiSpec(redirectToSpec);
9686 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)
;
9687
9688 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", 9688
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 9688); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9689 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
9690 rv = StartRedirectChannelToURI(
9691 mAPIRedirectTo->first(),
9692 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_TEMPORARY |
9693 nsIChannelEventSink::REDIRECT_TRANSPARENT
9694 : nsIChannelEventSink::REDIRECT_TEMPORARY);
9695 mAPIRedirectTo = Nothing();
9696 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9697 return NS_OK;
9698 }
9699 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
9700 }
9701
9702 // Hack: ContinueOnStartRequest2 uses NS_OK to detect successful redirects,
9703 // so we distinguish this codepath (a non-redirect that's processing
9704 // normally) by passing in a bogus error code.
9705 return ContinueOnStartRequest2(NS_BINDING_FAILED);
9706}
9707
9708nsresult nsHttpChannel::ContinueOnStartRequest2(nsresult result) {
9709 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
9710 // Redirect has passed through, we don't want to go on with this
9711 // channel. It will now be canceled by the redirect handling code
9712 // that called this function.
9713 return NS_OK;
9714 }
9715
9716 // on proxy errors, try to failover
9717 if (mConnectionInfo->ProxyInfo() &&
9718 (mStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
9719 mStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
9720 mStatus == NS_ERROR_NET_TIMEOUT || mStatus == NS_ERROR_NET_RESET)) {
9721 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
9722 if (NS_SUCCEEDED(ProxyFailover())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ProxyFailover()))
, 1)))
) {
9723 mProxyConnectResponseHead = nullptr;
9724 return NS_OK;
9725 }
9726 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
9727 }
9728
9729 // Hack: ContinueOnStartRequest3 uses NS_OK to detect successful redirects,
9730 // so we distinguish this codepath (a non-redirect that's processing
9731 // normally) by passing in a bogus error code.
9732 return ContinueOnStartRequest3(NS_BINDING_FAILED);
9733}
9734
9735nsresult nsHttpChannel::ContinueOnStartRequest3(nsresult result) {
9736 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
9737 // Redirect has passed through, we don't want to go on with this
9738 // channel. It will now be canceled by the redirect handling code
9739 // that called this function.
9740 return NS_OK;
9741 }
9742
9743 return CallOnStartRequest();
9744}
9745
9746static void ReportHTTPSRRTelemetry(
9747 const Maybe<nsCOMPtr<nsIDNSHTTPSSVCRecord>>& aMaybeRecord) {
9748 bool hasHTTPSRR = aMaybeRecord && (aMaybeRecord.ref() != nullptr);
9749 if (!hasHTTPSRR) {
9750 mozilla::glean::networking::https_rr_presented.Get("none"_ns).Add(1);
9751 return;
9752 }
9753
9754 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& record = aMaybeRecord.ref();
9755 nsCOMPtr<nsISVCBRecord> svcbRecord;
9756 if (NS_SUCCEEDED(record->GetServiceModeRecord(false, false,((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
9757 getter_AddRefs(svcbRecord)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
) {
9758 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"
, 9758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "svcbRecord"
")"); do { MOZ_CrashSequence(__null, 9758); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9759
9760 Maybe<std::tuple<nsCString, SupportedAlpnRank>> alpn =
9761 svcbRecord->GetAlpn();
9762 bool isHttp3 = alpn ? IsHttp3(std::get<1>(*alpn)) : false;
9763 mozilla::glean::networking::https_rr_presented
9764 .Get(isHttp3 ? "presented_with_http3"_ns : "presented"_ns)
9765 .Add(1);
9766 }
9767}
9768
9769static void RecordHttpChanDispositionGlean(ChannelDisposition chanDisposition) {
9770 switch (chanDisposition) {
9771 case kHttpCanceled:
9772 mozilla::glean::networking::http_channel_disposition
9773 .Get("http_cancelled"_ns)
9774 .Add(1);
9775 break;
9776 case kHttpDisk:
9777 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
9778 .Add(1);
9779 break;
9780 case kHttpNetOK:
9781 mozilla::glean::networking::http_channel_disposition.Get("http_net_ok"_ns)
9782 .Add(1);
9783 break;
9784 case kHttpNetEarlyFail:
9785 mozilla::glean::networking::http_channel_disposition
9786 .Get("http_net_early_fail"_ns)
9787 .Add(1);
9788 break;
9789 case kHttpNetLateFail:
9790 mozilla::glean::networking::http_channel_disposition
9791 .Get("http_net_late_fail"_ns)
9792 .Add(1);
9793 break;
9794 case kHttpsCanceled:
9795 mozilla::glean::networking::http_channel_disposition
9796 .Get("https_cancelled"_ns)
9797 .Add(1);
9798 break;
9799 case kHttpsDisk:
9800 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
9801 .Add(1);
9802 break;
9803 case kHttpsNetOK:
9804 mozilla::glean::networking::http_channel_disposition
9805 .Get("https_net_ok"_ns)
9806 .Add(1);
9807 break;
9808 case kHttpsNetEarlyFail:
9809 mozilla::glean::networking::http_channel_disposition
9810 .Get("https_net_early_fail"_ns)
9811 .Add(1);
9812 break;
9813 case kHttpsNetLateFail:
9814 mozilla::glean::networking::http_channel_disposition
9815 .Get("https_net_late_fail"_ns)
9816 .Add(1);
9817 break;
9818 default:
9819 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"
, 9819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for chanDisposition"
")"); do { MOZ_CrashSequence(__null, 9819); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9820 }
9821}
9822
9823enum class HttpChannelDispositionUpgrade {
9824 cancel,
9825 disk,
9826 netOk,
9827 netEarlyFail,
9828 netLateFail,
9829};
9830
9831static nsLiteralCString HttpChanDispositionToTelemetryLabel(
9832 HttpChannelDispositionUpgrade upgradeChanDisposition) {
9833 switch (upgradeChanDisposition) {
9834 case HttpChannelDispositionUpgrade::cancel:
9835 return "cancel"_ns;
9836 case HttpChannelDispositionUpgrade::disk:
9837 return "disk"_ns;
9838 case HttpChannelDispositionUpgrade::netOk:
9839 return "net_ok"_ns;
9840 case HttpChannelDispositionUpgrade::netEarlyFail:
9841 return "net_early_fail"_ns;
9842 case HttpChannelDispositionUpgrade::netLateFail:
9843 return "net_late_fail"_ns;
9844 }
9845
9846 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"
, 9846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for upgradeChanDecomposition"
")"); do { MOZ_CrashSequence(__null, 9846); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9847 return "other"_ns;
9848}
9849
9850nsresult nsHttpChannel::LogConsoleError(const char* aTag) {
9851 nsCOMPtr<nsIConsoleService> console(mozilla::components::Console::Service());
9852 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", 9852
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9853
9854 nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
9855 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", 9855
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9856 uint64_t innerWindowID = loadInfo->GetInnerWindowID();
9857
9858 nsAutoString errorText;
9859 nsresult rv = nsContentUtils::GetLocalizedString(
9860 PropertiesFile::NECKO_PROPERTIES, aTag, errorText);
9861 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"
, 9861); return rv; } } while (false)
;
9862
9863 nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1"));
9864 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", 9864
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9865
9866 rv =
9867 error->InitWithSourceURI(errorText, mURI, 0, 0, nsIScriptError::errorFlag,
9868 "Invalid HTTP Status Lines"_ns, innerWindowID);
9869 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"
, 9869); return rv; } } while (false)
;
9870 console->LogMessage(error);
9871 return NS_OK;
9872}
9873
9874static void RecordHTTPSUpgradeTelemetry(nsIURI* aURI, nsILoadInfo* aLoadInfo) {
9875 // we record https telemetry only for top-level loads
9876 if (aLoadInfo->GetExternalContentPolicyType() !=
9877 ExtContentPolicy::TYPE_DOCUMENT) {
9878 return;
9879 }
9880
9881 // exempt loopback addresses because we only want to record telemetry
9882 // for actual web requests
9883 if (nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI)) {
9884 return;
9885 }
9886
9887 // todo: for now we don't record form submissions, only
9888 // top-level document loads. Once Bug 1720500 is fixed, we can
9889 // consider recording form submissions too.
9890 if (aLoadInfo->GetIsFormSubmission()) {
9891 return;
9892 }
9893
9894 bool isHTTPS = aURI->SchemeIs("https");
9895
9896 nsILoadInfo::HTTPSUpgradeTelemetryType httpsTelemetry =
9897 aLoadInfo->GetHttpsUpgradeTelemetry();
9898 switch (httpsTelemetry) {
9899 case nsILoadInfo::NOT_INITIALIZED: {
9900 if (isHTTPS) {
9901 // Bug 1912222: We should never encounter NOT_INITIALIZED values,
9902 // though we still want to know whether those loads are HTTPS
9903 // or not. Eventually we'll want to remove this if-clause
9904 // again and only report "not_initialized".
9905 mozilla::glean::networking::http_to_https_upgrade_reason
9906 .Get("not_initialized_https"_ns)
9907 .Add(1);
9908 return;
9909 }
9910 mozilla::glean::networking::http_to_https_upgrade_reason
9911 .Get("not_initialized"_ns)
9912 .Add(1);
9913 break;
9914 }
9915 case nsILoadInfo::NO_UPGRADE: {
9916 if (isHTTPS) {
9917 // Bug 1912222: We should rearely encounter NO_UPGRADE values, though
9918 // we still want to ensure those are not HTTPS. Eventually we'll want
9919 // to remove this if-clause again and only report "no_upgrade".
9920 mozilla::glean::networking::http_to_https_upgrade_reason
9921 .Get("no_upgrade_https"_ns)
9922 .Add(1);
9923 return;
9924 }
9925 mozilla::glean::networking::http_to_https_upgrade_reason
9926 .Get("no_upgrade"_ns)
9927 .Add(1);
9928 break;
9929 }
9930 case nsILoadInfo::ALREADY_HTTPS:
9931 mozilla::glean::networking::http_to_https_upgrade_reason
9932 .Get("already_https"_ns)
9933 .Add(1);
9934 break;
9935 case nsILoadInfo::HSTS:
9936 mozilla::glean::networking::http_to_https_upgrade_reason.Get("hsts"_ns)
9937 .Add(1);
9938 break;
9939 case nsILoadInfo::HTTPS_ONLY_UPGRADE:
9940 mozilla::glean::networking::http_to_https_upgrade_reason
9941 .Get("https_only_upgrade"_ns)
9942 .Add(1);
9943 break;
9944 case nsILoadInfo::HTTPS_ONLY_UPGRADE_DOWNGRADE:
9945 mozilla::glean::networking::http_to_https_upgrade_reason
9946 .Get("https_only_upgrade_downgrade"_ns)
9947 .Add(1);
9948 break;
9949 case nsILoadInfo::HTTPS_FIRST_UPGRADE:
9950 mozilla::glean::networking::http_to_https_upgrade_reason
9951 .Get("https_first_upgrade"_ns)
9952 .Add(1);
9953 break;
9954 case nsILoadInfo::HTTPS_FIRST_UPGRADE_DOWNGRADE:
9955 mozilla::glean::networking::http_to_https_upgrade_reason
9956 .Get("https_first_upgrade_downgrade"_ns)
9957 .Add(1);
9958 break;
9959 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE:
9960 mozilla::glean::networking::http_to_https_upgrade_reason
9961 .Get("https_first_schemeless_upgrade"_ns)
9962 .Add(1);
9963 break;
9964 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE_DOWNGRADE:
9965 mozilla::glean::networking::http_to_https_upgrade_reason
9966 .Get("https_first_schemeless_upgrade_downgrade"_ns)
9967 .Add(1);
9968 break;
9969 case nsILoadInfo::CSP_UIR:
9970 mozilla::glean::networking::http_to_https_upgrade_reason.Get("csp_uir"_ns)
9971 .Add(1);
9972 break;
9973 case nsILoadInfo::HTTPS_RR:
9974 mozilla::glean::networking::http_to_https_upgrade_reason
9975 .Get("https_rr"_ns)
9976 .Add(1);
9977 break;
9978 case nsILoadInfo::WEB_EXTENSION_UPGRADE:
9979 mozilla::glean::networking::http_to_https_upgrade_reason
9980 .Get("web_extension_upgrade"_ns)
9981 .Add(1);
9982 break;
9983 case nsILoadInfo::UPGRADE_EXCEPTION:
9984 mozilla::glean::networking::http_to_https_upgrade_reason
9985 .Get("upgrade_exception"_ns)
9986 .Add(1);
9987 break;
9988 case nsILoadInfo::SKIP_HTTPS_UPGRADE:
9989 mozilla::glean::networking::http_to_https_upgrade_reason
9990 .Get("skip_upgrade"_ns)
9991 .Add(1);
9992 break;
9993 default:
9994 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"
, 9994); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"what telemetry flag is set to end up here?" ")"); do { MOZ_CrashSequence
(__null, 9994); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9995 }
9996}
9997
9998static void RecordIPAddressSpaceTelemetry(bool aLoadSuccess, nsIURI* aURI,
9999 nsILoadInfo* aLoadInfo,
10000 NetAddr& aPeerAddr) {
10001 // if the load was not successful, then there is nothing to record here
10002 if (!aLoadSuccess) {
10003 return;
10004 }
10005
10006 // we record https telemetry only for top-level loads
10007 if (aLoadInfo->GetExternalContentPolicyType() !=
10008 ExtContentPolicy::TYPE_DOCUMENT) {
10009 return;
10010 }
10011
10012 if (aURI->SchemeIs("https")) {
10013 mozilla::glean::networking::https_http_or_local.Get("load_is_https"_ns)
10014 .Add(1);
10015 return;
10016 }
10017
10018 if (aURI->SchemeIs("http")) {
10019 if (aPeerAddr.IsIPAddrLocal() || aPeerAddr.IsLoopbackAddr()) {
10020 mozilla::glean::networking::https_http_or_local
10021 .Get("load_is_http_for_local_domain"_ns)
10022 .Add(1);
10023 } else {
10024 mozilla::glean::networking::https_http_or_local.Get("load_is_http"_ns)
10025 .Add(1);
10026 }
10027 return;
10028 }
10029}
10030
10031static void RecordLNATelemetry(nsHttpChannel* aChannel, bool aLoadSuccess) {
10032 // Extract data from channel
10033 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
10034 nsCOMPtr<nsIURI> uri;
10035 aChannel->GetURI(getter_AddRefs(uri));
10036 NetAddr peerAddr = aChannel->GetPeerAddr();
10037 const nsACString& promptAction = aChannel->GetLNAPromptAction();
10038
10039 if (!loadInfo || !uri) {
10040 return;
10041 }
10042
10043 RefPtr<mozilla::dom::BrowsingContext> bc;
10044 loadInfo->GetBrowsingContext(getter_AddRefs(bc));
10045
10046 nsILoadInfo::IPAddressSpace parentAddressSpace =
10047 nsILoadInfo::IPAddressSpace::Unknown;
10048 Maybe<dom::ClientInfo> clientInfo = loadInfo->GetClientInfo();
10049 if (clientInfo.isSome() && clientInfo->Type() != dom::ClientType::Window) {
10050 nsCOMPtr<nsIPolicyContainer> policyContainer =
10051 loadInfo->GetPolicyContainer();
10052 if (policyContainer) {
10053 parentAddressSpace =
10054 PolicyContainer::Cast(policyContainer)->GetIPAddressSpace();
10055 }
10056 } else if (!bc) {
10057 parentAddressSpace = loadInfo->GetParentIpAddressSpace();
10058 } else {
10059 parentAddressSpace = bc->GetCurrentIPAddressSpace();
10060 }
10061
10062 // Early return if NOT LNA - don't record telemetry or log
10063 if (!mozilla::net::IsLocalOrPrivateNetworkAccess(
10064 parentAddressSpace, loadInfo->GetIpAddressSpace())) {
10065 return;
10066 }
10067
10068 if (aLoadSuccess) {
10069 mozilla::glean::networking::local_network_access.Get("success"_ns).Add(1);
10070 } else {
10071 mozilla::glean::networking::local_network_access.Get("failure"_ns).Add(1);
10072 }
10073
10074 uint16_t port = 0;
10075 peerAddr.GetPort(&port);
10076
10077 // label format is <parentAddressSpace>_to_<targetAddressSpace>_<scheme>
10078 // At this point we are sure that the request is a LNA,
10079 // Hence we can safely assume few conditions to construct the label
10080 nsAutoCString glean_lna_label;
10081 if (parentAddressSpace == nsILoadInfo::IPAddressSpace::Public) {
10082 glean_lna_label.Append("public_to_"_ns);
10083 } else {
10084 glean_lna_label.Append("private_to_"_ns);
10085 }
10086 if (loadInfo->GetIpAddressSpace() == nsILoadInfo::IPAddressSpace::Private) {
10087 glean_lna_label.Append("private_"_ns);
10088 } else {
10089 glean_lna_label.Append("local_"_ns);
10090 }
10091 if (uri->SchemeIs("https")) {
10092 glean_lna_label.Append("https"_ns);
10093 } else {
10094 glean_lna_label.Append("http"_ns);
10095 }
10096
10097 mozilla::glean::networking::local_network_access.Get(glean_lna_label).Add(1);
10098
10099 // Get top-level site (main window principal) - TLD+1
10100 nsAutoCString topLevelSite;
10101 if (bc && bc->Top()) {
10102 if (bc->Top()->Canonical()) {
10103 RefPtr<mozilla::dom::WindowGlobalParent> topWindowGlobal =
10104 bc->Top()->Canonical()->GetCurrentWindowGlobal();
10105 if (topWindowGlobal) {
10106 nsCOMPtr<nsIPrincipal> topPrincipal =
10107 topWindowGlobal->DocumentPrincipal();
10108 if (topPrincipal) {
10109 (void)topPrincipal->GetBaseDomain(topLevelSite);
10110 }
10111 }
10112 }
10113 }
10114
10115 // Get initiator (triggering principal) - TLD+1
10116 nsAutoCString initiator;
10117 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
10118 loadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
10119 if (triggeringPrincipal) {
10120 (void)triggeringPrincipal->GetBaseDomain(initiator);
10121 }
10122
10123 bool isSecureContext =
10124 triggeringPrincipal
10125 ? triggeringPrincipal->GetIsOriginPotentiallyTrustworthy()
10126 : false;
10127
10128 // Get target host - TLD+1
10129 nsCOMPtr<nsIEffectiveTLDService> eTLDService =
10130 mozilla::components::EffectiveTLD::Service();
10131 nsAutoCString targetHost;
10132 if (eTLDService) {
10133 (void)eTLDService->GetBaseDomain(uri, 0, targetHost);
10134 }
10135
10136 // Get target IP address
10137 nsCString targetIp = peerAddr.ToString();
10138
10139 // Determine protocol from LoadInfo
10140 nsAutoCString protocol;
10141 ExtContentPolicyType contentType = loadInfo->GetExternalContentPolicyType();
10142 switch (contentType) {
10143 case ExtContentPolicyType::TYPE_WEBSOCKET:
10144 protocol.AssignLiteral("websocket");
10145 break;
10146 case ExtContentPolicyType::TYPE_WEB_TRANSPORT:
10147 protocol.AssignLiteral("webtransport");
10148 break;
10149 case ExtContentPolicyType::TYPE_FETCH:
10150 protocol.AssignLiteral("fetch");
10151 break;
10152 case ExtContentPolicyType::TYPE_XMLHTTPREQUEST:
10153 protocol.AssignLiteral("xhr");
10154 break;
10155 default:
10156 if (uri->SchemeIs("https")) {
10157 protocol.AssignLiteral("https");
10158 } else {
10159 protocol.AssignLiteral("http");
10160 }
10161 break;
10162 }
10163
10164 // Record the event
10165 glean::networking::LocalNetworkAccessConnectionExtra extra = {
10166 .initiator = initiator.IsEmpty() ? Nothing() : Some(initiator),
10167 .isSecureContext = Some(isSecureContext),
10168 .loadSuccess = Some(aLoadSuccess),
10169 .promptAction =
10170 promptAction.IsEmpty() ? Nothing() : Some(nsCString(promptAction)),
10171 .protocol = Some(protocol),
10172 .targetHost = targetHost.IsEmpty() ? Nothing() : Some(targetHost),
10173 .targetIp = Some(targetIp),
10174 .targetPort = Some(port),
10175 .topLevelSite = topLevelSite.IsEmpty() ? Nothing() : Some(topLevelSite),
10176
10177 };
10178 glean::networking::local_network_access_connection.Record(Some(extra));
10179
10180 ReportLNAAccessToConsole(aChannel, "LocalNetworkAccessDetected",
10181 promptAction);
10182}
10183
10184NS_IMETHODIMPnsresult
10185nsHttpChannel::OnStopRequest(nsIRequest* request, nsresult status) {
10186 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", 10186
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncOpenTime.IsNull()"
")"); do { MOZ_CrashSequence(__null, 10186); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10187 AUTO_PROFILER_LABEL("nsHttpChannel::OnStopRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject10187( "nsHttpChannel::OnStopRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
10188 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnStopRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10189( "nsHttpChannel::OnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10189 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10189( "nsHttpChannel::OnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10190
10191 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)
10192 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)
;
10193
10194 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)
10195 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)
;
10196
10197 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"
, 10198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { MOZ_CrashSequence(__null, 10198); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10198 "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"
, 10198); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { MOZ_CrashSequence(__null, 10198); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10199
10200 if (mStatus == NS_ERROR_PARSING_HTTP_STATUS_LINE) {
10201 (void)LogConsoleError("InvalidHTTPResponseStatusLine");
10202 }
10203
10204 // It's possible that LoadUseHTTPSSVC() is false, but we already have
10205 // mHTTPSSVCRecord.
10206 if (LoadUseHTTPSSVC() || mHTTPSSVCRecord) {
10207 ReportHTTPSRRTelemetry(mHTTPSSVCRecord);
10208 }
10209
10210 // If this load failed because of a security error, it may be because we
10211 // are in a captive portal - trigger an async check to make sure.
10212 int32_t nsprError = -1 * NS_ERROR_GET_CODE(status);
10213 if (mozilla::psm::IsNSSErrorCode(nsprError) && IsHTTPS()) {
10214 gIOService->RecheckCaptivePortal();
10215 }
10216
10217 if (request == mCachePump) {
10218 mCacheReadEnd = TimeStamp::Now();
10219 }
10220
10221 // allow content to be cached if it was loaded successfully (bug #482935)
10222 bool contentComplete = NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)));
10223
10224 // honor the cancelation status even if the underlying transaction
10225 // completed.
10226 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) status = mStatus;
10227
10228 if (LoadCachedContentIsPartial()) {
10229 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
10230 // mTransactionPump should be suspended
10231 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"
, 10232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ MOZ_CrashSequence(__null, 10232); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
10232 "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"
, 10232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ MOZ_CrashSequence(__null, 10232); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
10233
10234 if (request == mCachePump) {
10235 bool streamDone;
10236 status = OnDoneReadingPartialCacheEntry(&streamDone);
10237 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) && !streamDone) return status;
10238 // otherwise, fall through and fire OnStopRequest...
10239 } else if (request == mTransactionPump) {
10240 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", 10240
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { MOZ_CrashSequence(__null, 10240); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10241 } else {
10242 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"
, 10242); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected request" ")"); do { MOZ_CrashSequence
(__null, 10242); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10243 }
10244 }
10245 // Do not to leave the transaction in a suspended state in error cases.
10246 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) && mTransaction) {
10247 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, status);
10248 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10249 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)
;
10250 }
10251 }
10252 }
10253
10254 nsCOMPtr<nsICompressConvStats> conv = do_QueryInterface(mCompressListener);
10255 if (conv) {
10256 uint64_t decodedDataLength = 0;
10257 conv->GetDecodedDataLength(&decodedDataLength);
10258 mDecodedBodySize = decodedDataLength;
10259 }
10260
10261 bool isFromNet = request == mTransactionPump;
10262
10263 if (mTransaction) {
10264 // determine if we should call DoAuthRetry
10265 bool authRetry = (mAuthRetryPending && NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) &&
10266 // we should only auth retry in this channel if are not
10267 // redirecting a new channel for authentication retries
10268 !StaticPrefs::network_auth_use_redirect_for_retries());
10269
10270 StoreStronglyFramed(mTransaction->ResponseIsComplete());
10271 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)
10272 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)
;
10273
10274 // Save the reference of |mTransaction| to |transactionWithStickyConn|
10275 // when it has a sticky connection.
10276 // In the case we need to retry an authentication request, we need to
10277 // reuse the connection of |transactionWithStickyConn|.
10278 RefPtr<HttpTransactionShell> transactionWithStickyConn;
10279 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
10280 mTransaction->HasStickyConnection()) {
10281 transactionWithStickyConn = mTransaction;
10282 // Make sure we use the updated caps and connection info from transaction.
10283 // We read these values when the transaction is already closed, so there
10284 // should be no race.
10285 if (mTransaction->Http2Disabled()) {
10286 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
10287 }
10288 if (mTransaction->Http3Disabled()) {
10289 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
10290 }
10291 mConnectionInfo = mTransaction->GetConnInfo();
10292 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)
10293 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)
;
10294 }
10295
10296 // this code relies on the code in nsHttpTransaction::Close, which
10297 // tests for NS_HTTP_STICKY_CONNECTION to determine whether or not to
10298 // keep the connection around after the transaction is finished.
10299 //
10300 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)
10301 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)
10302 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)
;
10303 // We must check caps for stickinness also on the transaction because it
10304 // might have been updated by the transaction itself during inspection of
10305 // the reposnse headers yet on the socket thread (found connection based
10306 // auth schema).
10307
10308 if ((NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) && transactionWithStickyConn) {
10309 // Close (don't reuse) the sticky connection if this channel has been
10310 // cancelled. There are proxy servers known to get confused when we send
10311 // a new request over such a half-stated connection.
10312 if (!LoadAuthConnectionRestartable()) {
10313 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)
;
10314 transactionWithStickyConn->DontReuseConnection();
10315 }
10316 }
10317
10318 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) {
10319 mTransaction->SetH2WSConnRefTaken();
10320 }
10321
10322 mTransferSize = mTransaction->GetTransferSize();
10323 mRequestSize = mTransaction->GetRequestSize();
10324
10325 RecordHTTPSUpgradeTelemetry(mURI, mLoadInfo);
10326
10327 RecordIPAddressSpaceTelemetry(NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))), mURI, mLoadInfo,
10328 mPeerAddr);
10329 RecordLNATelemetry(this, NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))));
10330
10331 uint32_t flags;
10332 if (mStatus == NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED &&
10333 StaticPrefs::network_lna_block_trackers() &&
10334 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
10335 mLoadInfo->GetTriggeringThirdPartyClassificationFlags(&flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
&&
10336 flags != 0) {
10337 mozilla::glean::networking::local_network_blocked_tracker.Add(1);
10338 }
10339
10340 // If we are using the transaction to serve content, we also save the
10341 // time since async open in the cache entry so we can compare telemetry
10342 // between cache and net response.
10343 // Do not store the time of conditional requests because even if we
10344 // fetch the data from the server, the time includes loading of the old
10345 // cache entry which would skew the network load time.
10346 if (request == mTransactionPump && mCacheEntry && !mDidReval &&
10347 !LoadCustomConditionalRequest() && !mAsyncOpenTime.IsNull() &&
10348 !mOnStartRequestTimestamp.IsNull()) {
10349 uint64_t onStartTime =
10350 (mOnStartRequestTimestamp - mAsyncOpenTime).ToMilliseconds();
10351 uint64_t onStopTime =
10352 (TimeStamp::Now() - mAsyncOpenTime).ToMilliseconds();
10353 (void)mCacheEntry->SetNetworkTimes(onStartTime, onStopTime);
10354 }
10355
10356 mResponseTrailers = mTransaction->TakeResponseTrailers();
10357
10358 if (nsIOService::UseSocketProcess() && mTransaction) {
10359 mOnStopRequestStartTime = mTransaction->GetOnStopRequestStartTime();
10360 if (!mOnStopRequestStartTime.IsNull()) {
10361 PerfStats::RecordMeasurement(
10362 PerfStats::Metric::OnStopRequestSocketToParent,
10363 TimeStamp::Now() - mOnStopRequestStartTime);
10364 }
10365 } else {
10366 mOnStopRequestStartTime = TimeStamp::Now();
10367 }
10368
10369 // at this point, we're done with the transaction
10370 mTransactionTimings = mTransaction->Timings();
10371 mTransaction = nullptr;
10372 mTransactionPump = nullptr;
10373
10374 // We no longer need the dns prefetch object
10375 if (mDNSPrefetch && mDNSPrefetch->TimingsValid() &&
10376 !mTransactionTimings.requestStart.IsNull() &&
10377 !mTransactionTimings.connectStart.IsNull() &&
10378 mDNSPrefetch->EndTimestamp() <= mTransactionTimings.connectStart) {
10379 // We only need the domainLookup timestamps when not using a
10380 // persistent connection, meaning if the endTimestamp < connectStart
10381 mTransactionTimings.domainLookupStart = mDNSPrefetch->StartTimestamp();
10382 mTransactionTimings.domainLookupEnd = mDNSPrefetch->EndTimestamp();
10383 }
10384 mDNSPrefetch = nullptr;
10385
10386 // handle auth retry...
10387 if (authRetry) {
10388 mAuthRetryPending = false;
10389 auto continueOSR = [authRetry, isFromNet, contentComplete,
10390 transactionWithStickyConn](auto* self,
10391 nsresult aStatus) {
10392 return self->ContinueOnStopRequestAfterAuthRetry(
10393 aStatus, authRetry, isFromNet, contentComplete,
10394 transactionWithStickyConn);
10395 };
10396 status = DoAuthRetry(transactionWithStickyConn, continueOSR);
10397 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
10398 return NS_OK;
10399 }
10400 }
10401 return ContinueOnStopRequestAfterAuthRetry(status, authRetry, isFromNet,
10402 contentComplete,
10403 transactionWithStickyConn);
10404 }
10405
10406 return ContinueOnStopRequest(status, isFromNet, contentComplete);
10407}
10408
10409nsresult nsHttpChannel::ContinueOnStopRequestAfterAuthRetry(
10410 nsresult aStatus, bool aAuthRetry, bool aIsFromNet, bool aContentComplete,
10411 HttpTransactionShell* aTransWithStickyConn) {
10412 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)
10413 ("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)
10414 "[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)
10415 " 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)
10416 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)
10417 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)
;
10418
10419 if (aAuthRetry && NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
10420 return NS_OK;
10421 }
10422
10423 // If DoAuthRetry failed, or if we have been cancelled since showing
10424 // the auth. dialog, then we need to send OnStartRequest now
10425 if (aAuthRetry || (mAuthRetryPending && NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0))))) {
10426 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"
, 10426); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))"
") (" "should have a failure code here" ")"); do { MOZ_CrashSequence
(__null, 10426); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10427 // NOTE: since we have a failure status, we can ignore the return
10428 // value from onStartRequest.
10429 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)
10430 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)
;
10431 if (mListener) {
10432 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"
, 10433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10433); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10433 "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"
, 10433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10433); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10434 if (!LoadOnStartRequestCalled()) {
10435 nsCOMPtr<nsIStreamListener> listener(mListener);
10436 StoreOnStartRequestCalled(true);
10437 listener->OnStartRequest(this);
10438 }
10439 } else {
10440 StoreOnStartRequestCalled(true);
10441 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"
, 10441)
;
10442 }
10443 mAuthRetryPending = false;
10444 }
10445
10446 // if this transaction has been replaced, then bail.
10447 if (LoadTransactionReplaced()) {
10448 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)
;
10449 // This was just the network check for a 304 response.
10450 mFirstResponseSource = RESPONSE_PENDING;
10451 return NS_OK;
10452 }
10453
10454 bool upgradeWebsocket = mUpgradeProtocolCallback && aTransWithStickyConn &&
10455 mResponseHead &&
10456 ((mResponseHead->Status() == 101 &&
10457 mResponseHead->Version() == HttpVersion::v1_1) ||
10458 (mResponseHead->Status() == 200 &&
10459 mResponseHead->Version() == HttpVersion::v2_0));
10460
10461 bool upgradeConnect = mUpgradeProtocolCallback && aTransWithStickyConn &&
10462 (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) && mResponseHead &&
10463 mResponseHead->Status() == 200;
10464
10465 if (upgradeWebsocket || upgradeConnect) {
10466 if (nsIOService::UseSocketProcess() && upgradeConnect) {
10467 // TODO: Support connection upgrade for socket process in bug 1632809.
10468 (void)mUpgradeProtocolCallback->OnUpgradeFailed(NS_ERROR_NOT_IMPLEMENTED);
10469 return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
10470 }
10471
10472 nsresult rv = gHttpHandler->CompleteUpgrade(aTransWithStickyConn,
10473 mUpgradeProtocolCallback);
10474 mUpgradeProtocolCallback = nullptr;
10475 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10476 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)
10477 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)
;
10478
10479 // This ensures that WebSocketChannel::OnStopRequest will be
10480 // called with an error so the session is properly aborted.
10481 aStatus = rv;
10482 }
10483 }
10484
10485 return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
10486}
10487
10488nsresult nsHttpChannel::ContinueOnStopRequest(nsresult aStatus, bool aIsFromNet,
10489 bool aContentComplete) {
10490 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)
10491 ("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)
10492 "[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)
10493 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)
;
10494
10495 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ContinueOnStopRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10496( "nsHttpChannel::ContinueOnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10496 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10496( "nsHttpChannel::ContinueOnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10497 // HTTP_CHANNEL_DISPOSITION TELEMETRY
10498 ChannelDisposition chanDisposition = kHttpCanceled;
10499 // HTTP_CHANNEL_DISPOSITION_UPGRADE TELEMETRY
10500 HttpChannelDispositionUpgrade upgradeChanDisposition =
10501 HttpChannelDispositionUpgrade::cancel;
10502
10503 // HTTP 0.9 is more likely to be an error than really 0.9, so count it that
10504 // way
10505 if (mCanceled) {
10506 chanDisposition = kHttpCanceled;
10507 upgradeChanDisposition = HttpChannelDispositionUpgrade::cancel;
10508 } else if (!LoadUsedNetwork()) {
10509 chanDisposition = kHttpDisk;
10510 upgradeChanDisposition = HttpChannelDispositionUpgrade::disk;
10511 } else if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) && mResponseHead &&
10512 mResponseHead->Version() != HttpVersion::v0_9) {
10513 chanDisposition = kHttpNetOK;
10514 upgradeChanDisposition = HttpChannelDispositionUpgrade::netOk;
10515 } else if (!mTransferSize) {
10516 chanDisposition = kHttpNetEarlyFail;
10517 upgradeChanDisposition = HttpChannelDispositionUpgrade::netEarlyFail;
10518 } else {
10519 chanDisposition = kHttpNetLateFail;
10520 upgradeChanDisposition = HttpChannelDispositionUpgrade::netLateFail;
10521 }
10522 // Browser upgrading only happens on HTTPS pages for mixed passive content
10523 // when upgrading is enabled.
10524 nsCString upgradeKey;
10525 nsLiteralCString upgradeChanDispositionLabel =
10526 HttpChanDispositionToTelemetryLabel(upgradeChanDisposition);
10527 if (IsHTTPS()) {
10528 // Browser upgrading is disabled and the content is already HTTPS
10529 upgradeKey = "disabledNoReason"_ns;
10530 // Checks "security.mixed_content.upgrade_display_content" is true
10531 if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
10532 if (mLoadInfo->GetBrowserUpgradeInsecureRequests()) {
10533 // HTTP content the browser has upgraded to HTTPS
10534 mozilla::glean::networking::http_channel_disposition_enabled_upgrade
10535 .Get(upgradeChanDispositionLabel)
10536 .Add(1);
10537 upgradeKey = "enabledUpgrade"_ns;
10538 } else {
10539 // Content wasn't upgraded but is already HTTPS
10540 mozilla::glean::networking::http_channel_disposition_enabled_no_reason
10541 .Get(upgradeChanDispositionLabel)
10542 .Add(1);
10543 upgradeKey = "enabledNoReason"_ns;
10544 }
10545 } else {
10546 mozilla::glean::networking::http_channel_disposition_disabled_no_reason
10547 .Get(upgradeChanDispositionLabel)
10548 .Add(1);
10549 }
10550 // shift http to https disposition enums
10551 chanDisposition =
10552 static_cast<ChannelDisposition>(chanDisposition + kHttpsCanceled);
10553 } else if (mLoadInfo->GetBrowserWouldUpgradeInsecureRequests()) {
10554 // HTTP content the browser would upgrade to HTTPS if upgrading was
10555 // enabled
10556 mozilla::glean::networking::http_channel_disposition_disabled_upgrade
10557 .Get(upgradeChanDispositionLabel)
10558 .Add(1);
10559 upgradeKey = "disabledUpgrade"_ns;
10560 } else if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
10561 // HTTP content that wouldn't upgrade
10562 mozilla::glean::networking::http_channel_disposition_enabled_wont
10563 .Get(upgradeChanDispositionLabel)
10564 .Add(1);
10565 upgradeKey = "enabledWont"_ns;
10566 } else {
10567 mozilla::glean::networking::http_channel_disposition_disabled_wont
10568 .Get(upgradeChanDispositionLabel)
10569 .Add(1);
10570 upgradeKey = "disabledWont"_ns;
10571 }
10572
10573 glean::networking::http_channel_disposition_upgrade
10574 .Get(upgradeKey, upgradeChanDispositionLabel)
10575 .Add();
10576
10577 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)
10578 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)
;
10579 glean::http::channel_disposition.AccumulateSingleSample(chanDisposition);
10580 RecordHttpChanDispositionGlean(chanDisposition);
10581
10582 // if needed, check cache entry has all data we expect
10583 if (mCacheEntry && mCachePump && LoadConcurrentCacheAccess() &&
10584 aContentComplete) {
10585 int64_t size, contentLength;
10586 nsresult rv = CheckPartial(mCacheEntry, &size, &contentLength);
10587 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10588 if (size == int64_t(-1)) {
10589 // mayhemer TODO - we have to restart read from cache here at the size
10590 // offset
10591 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"
, 10591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")"
); do { MOZ_CrashSequence(__null, 10591); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10592 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)
10593 (" 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)
10594 "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)
;
10595 } else if (contentLength != int64_t(-1) && contentLength != size) {
10596 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)
;
10597 mCachedResponseHead = std::move(mResponseHead);
10598 // Ignore zero partial length because we also want to resume when
10599 // no data at all has been read from the cache.
10600 rv = MaybeSetupByteRangeRequest(size, contentLength, true);
10601 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest()) {
10602 // Prevent read from cache again
10603 StoreCachedContentIsValid(CachedContentValidity::Invalid);
10604 StoreCachedContentIsPartial(1);
10605
10606 // Perform the range request
10607 rv = ContinueConnect();
10608 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10609 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)
;
10610 mCachePump = nullptr;
10611 return NS_OK;
10612 }
10613 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)
10614 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)
;
10615 aStatus = NS_ERROR_NET_INTERRUPT;
10616 } else {
10617 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)
10618 ", 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)
10619 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)
;
10620 aStatus = NS_ERROR_NET_INTERRUPT;
10621 }
10622
10623 // Range-request recovery failed. Restore mResponseHead so that
10624 // it's available to late callers of Cancel (such as the ORB
10625 // async JS-validation callback)
10626 mResponseHead = std::move(mCachedResponseHead);
10627 }
10628 }
10629 }
10630
10631 StoreIsPending(false);
10632 mStatus = aStatus;
10633
10634 // perform any final cache operations before we close the cache entry.
10635 if (mCacheEntry && LoadRequestTimeInitialized()) {
10636 // New implementation just returns value of the !LoadCacheEntryIsReadOnly()
10637 // flag passed in. Old implementation checks on nsICache::ACCESS_WRITE
10638 // flag.
10639
10640 // Assume that write access is granted
10641 if (!LoadCacheEntryIsReadOnly()) {
10642 nsresult rv = FinalizeCacheEntry();
10643 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10644 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)
;
10645 }
10646 }
10647 }
10648
10649 // Register entry to the PerformanceStorage resource timing
10650 MaybeReportTimingData();
10651
10652 MaybeFlushConsoleReports();
10653
10654 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
10655 // These do allocations/frees/etc; avoid if not active
10656 mEndMarkerAdded = true;
10657
10658 nsAutoCString requestMethod;
10659 GetRequestMethod(requestMethod);
10660
10661 int32_t priority = PRIORITY_NORMAL;
10662 GetPriority(&priority);
10663
10664 uint64_t size = 0;
10665 GetEncodedBodySize(&size);
10666
10667 nsAutoCString contentType;
10668 mozilla::Maybe<mozilla::net::HttpVersion> httpVersion = Nothing();
10669 mozilla::Maybe<uint32_t> responseStatus = Nothing();
10670 if (mResponseHead) {
10671 mResponseHead->ContentType(contentType);
10672 httpVersion = Some(mResponseHead->Version());
10673 responseStatus = Some(mResponseHead->Status());
10674 }
10675
10676 profiler_add_network_marker(
10677 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_STOP,
10678 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
10679 mLoadInfo->GetInnerWindowID(),
10680 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
10681 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
10682 &mTransactionTimings, std::move(mSource),
10683 // Skip the version for a cached response: it reflects the original
10684 // fetch, not this request's connection.
10685 (mCacheDisposition == kCacheHit ||
10686 mCacheDisposition == kCacheHitViaReval)
10687 ? Nothing()
10688 : httpVersion,
10689 responseStatus, Some(nsDependentCString(contentType.get())));
10690 }
10691
10692 if (mAuthRetryPending &&
10693 StaticPrefs::network_auth_use_redirect_for_retries()) {
10694 nsresult rv = OpenRedirectChannel(aStatus);
10695 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)
10696 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)
;
10697 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10698 if (mListener) {
10699 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"
, 10700); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10700); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10700 "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"
, 10700); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10700); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10701 if (!LoadOnStartRequestCalled()) {
10702 nsCOMPtr<nsIStreamListener> listener(mListener);
10703 StoreOnStartRequestCalled(true);
10704 listener->OnStartRequest(this);
10705 }
10706 } else {
10707 StoreOnStartRequestCalled(true);
10708 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"
, 10708)
;
10709 }
10710 }
10711 mAuthRetryPending = false;
10712 }
10713
10714 if (LoadUsedNetwork() && !mReportedNEL) {
10715 MaybeGenerateNELReport();
10716 }
10717
10718 // notify "http-on-before-stop-request" observers
10719 gHttpHandler->OnBeforeStopRequest(this);
10720
10721 if (mListener) {
10722 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)
;
10723 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", 10724
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { MOZ_CrashSequence(__null, 10724); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10724 "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", 10724
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { MOZ_CrashSequence(__null, 10724); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10725 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"
, 10726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { MOZ_CrashSequence
(__null, 10726); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10726 "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"
, 10726); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { MOZ_CrashSequence
(__null, 10726); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10727 StoreOnStopRequestCalled(true);
10728 nsCOMPtr<nsIStreamListener> listener(mListener);
10729 listener->OnStopRequest(this, aStatus);
10730 }
10731 StoreOnStopRequestCalled(true);
10732
10733 // The prefetch needs to be released on the main thread
10734 mDNSPrefetch = nullptr;
10735
10736 mRedirectChannel = nullptr;
10737
10738 // notify "http-on-stop-request" observers
10739 gHttpHandler->OnStopRequest(this);
10740
10741 RemoveAsNonTailRequest();
10742
10743 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref &&
10744 mResponseHead) {
10745 mResponseHead->ClearHeaders();
10746 }
10747 // If a preferred alt-data type was set, this signals the consumer is
10748 // interested in reading and/or writing the alt-data representation.
10749 // We need to hold a reference to the cache entry in case the listener calls
10750 // openAlternativeOutputStream() after CloseCacheEntry() clears mCacheEntry.
10751 if (!mPreferredCachedAltDataTypes.IsEmpty()) {
10752 mAltDataCacheEntry = mCacheEntry;
10753 }
10754
10755 CloseCacheEntry(!aContentComplete);
10756 mWritingToCache = false;
10757
10758 if (mLoadGroup) {
10759 mLoadGroup->RemoveRequest(this, nullptr, aStatus);
10760 }
10761
10762 // We don't need this info anymore
10763 CleanRedirectCacheChainIfNecessary();
10764
10765 ReleaseListeners();
10766
10767 // Release mUploadStream to free some memory sooner.
10768 // We release this in background thread to avoid blocking I/O operations on
10769 // main thread See Bug 1940224
10770 (void)NS_DispatchBackgroundTask(NS_NewRunnableFunction(
10771 "release HttpBaseChannel::mUploadStream",
10772 [uploadStream = std::move(mUploadStream)]() { (void)uploadStream; }));
10773
10774 return NS_OK;
10775}
10776
10777//-----------------------------------------------------------------------------
10778// nsHttpChannel::nsIStreamListener
10779//-----------------------------------------------------------------------------
10780
10781class OnTransportStatusAsyncEvent : public Runnable {
10782 public:
10783 OnTransportStatusAsyncEvent(nsITransportEventSink* aEventSink,
10784 nsresult aTransportStatus, int64_t aProgress,
10785 int64_t aProgressMax)
10786 : Runnable("net::OnTransportStatusAsyncEvent"),
10787 mEventSink(aEventSink),
10788 mTransportStatus(aTransportStatus),
10789 mProgress(aProgress),
10790 mProgressMax(aProgressMax) {
10791 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"
, 10791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "Shouldn't be created on main thread" ")"); do { MOZ_CrashSequence
(__null, 10791); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10792 }
10793
10794 NS_IMETHODvirtual nsresult Run() override {
10795 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"
, 10795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should run on main thread" ")"); do { MOZ_CrashSequence
(__null, 10795); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10796 if (mEventSink) {
10797 mEventSink->OnTransportStatus(nullptr, mTransportStatus, mProgress,
10798 mProgressMax);
10799 }
10800 return NS_OK;
10801 }
10802
10803 private:
10804 nsCOMPtr<nsITransportEventSink> mEventSink;
10805 nsresult mTransportStatus;
10806 int64_t mProgress;
10807 int64_t mProgressMax;
10808};
10809
10810NS_IMETHODIMPnsresult
10811nsHttpChannel::OnDataAvailable(nsIRequest* request, nsIInputStream* input,
10812 uint64_t offset, uint32_t count) {
10813 nsresult rv;
10814 AUTO_PROFILER_LABEL("nsHttpChannel::OnDataAvailable", NETWORK)mozilla::AutoProfilerLabel raiiObject10814( "nsHttpChannel::OnDataAvailable"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
10815 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnDataAvailable", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10816( "nsHttpChannel::OnDataAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10816 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10816( "nsHttpChannel::OnDataAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10817
10818 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)
10819 " 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)
10820 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)
;
10821
10822 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)
10823 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)
;
10824
10825 // don't send out OnDataAvailable notifications if we've been canceled.
10826 if (mCanceled) return mStatus;
10827
10828 if (mAuthRetryPending ||
10829 (request == mTransactionPump && LoadTransactionReplaced())) {
10830 uint32_t n;
10831 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &n);
10832 }
10833
10834 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"
, 10834); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "No response head in ODA!!" ")"); do { MOZ_CrashSequence
(__null, 10834); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10835
10836 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"
, 10837); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { MOZ_CrashSequence
(__null, 10837); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10837 "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"
, 10837); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { MOZ_CrashSequence
(__null, 10837); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10838
10839 mIsReadingFromCache = (request == mCachePump);
10840
10841 if (mListener) {
10842 //
10843 // synthesize transport progress event. we do this here since we want
10844 // to delay OnProgress events until we start streaming data. this is
10845 // crucially important since it impacts the lock icon (see bug 240053).
10846 //
10847 nsresult transportStatus;
10848 if (request == mCachePump) {
10849 transportStatus = NS_NET_STATUS_READING;
10850 } else {
10851 transportStatus = NS_NET_STATUS_RECEIVING_FROM;
10852 }
10853
10854 // mResponseHead may reference new or cached headers, but either way it
10855 // holds our best estimate of the total content length. Even in the case
10856 // of a byte range request, the content length stored in the cached
10857 // response headers is what we want to use here.
10858
10859 int64_t progressMax = -1;
10860 rv = GetContentLength(&progressMax);
10861 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10862 NS_WARNING("GetContentLength failed")NS_DebugBreak(NS_DEBUG_WARNING, "GetContentLength failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10862
)
;
10863 }
10864 int64_t progress = mLogicalOffset + count;
10865
10866 if ((progress > progressMax) && (progressMax != -1)) {
10867 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10869)
10868 "unexpected progress values - "NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10869)
10869 "is server exceeding content length?")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10869)
;
10870 }
10871
10872 // make sure params are in range for js
10873 if (!InScriptableRange(progressMax)) {
10874 progressMax = -1;
10875 }
10876
10877 if (!InScriptableRange(progress)) {
10878 progress = -1;
10879 }
10880
10881 if (NS_IsMainThread()) {
10882 OnTransportStatus(nullptr, transportStatus, progress, progressMax);
10883 } else {
10884 rv = NS_DispatchToMainThread(new OnTransportStatusAsyncEvent(
10885 this, transportStatus, progress, progressMax));
10886 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"
, 10886); return rv; } } while (false)
;
10887 }
10888
10889 //
10890 // we have to manually keep the logical offset of the stream up-to-date.
10891 // we cannot depend solely on the offset provided, since we may have
10892 // already streamed some data from another source (see, for example,
10893 // OnDoneReadingPartialCacheEntry).
10894 //
10895 int64_t offsetBefore = 0;
10896 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(input);
10897 if (seekable && NS_FAILED(seekable->Tell(&offsetBefore))((bool)(__builtin_expect(!!(NS_FAILED_impl(seekable->Tell(
&offsetBefore))), 0)))
) {
10898 seekable = nullptr;
10899 }
10900
10901 if (nsIOService::UseSocketProcess() && mTransaction) {
10902 mOnDataAvailableStartTime = mTransaction->GetDataAvailableStartTime();
10903 if (!mOnDataAvailableStartTime.IsNull()) {
10904 PerfStats::RecordMeasurement(
10905 PerfStats::Metric::OnDataAvailableSocketToParent,
10906 TimeStamp::Now() - mOnDataAvailableStartTime);
10907 }
10908 } else {
10909 mOnDataAvailableStartTime = TimeStamp::Now();
10910 }
10911 nsCOMPtr<nsIStreamListener> listener = mListener;
10912 nsresult rv = listener->OnDataAvailable(this, input, mLogicalOffset, count);
10913 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10914 // by contract mListener must read all of "count" bytes, but
10915 // nsInputStreamPump is tolerant to seekable streams that violate that
10916 // and it will redeliver incompletely read data. So we need to do
10917 // the same thing when updating the progress counter to stay in sync.
10918 int64_t offsetAfter, delta;
10919 if (seekable && NS_SUCCEEDED(seekable->Tell(&offsetAfter))((bool)(__builtin_expect(!!(!NS_FAILED_impl(seekable->Tell
(&offsetAfter))), 1)))
) {
10920 delta = offsetAfter - offsetBefore;
10921 if (delta != count) {
10922 count = delta;
10923
10924 NS_WARNING("Listener OnDataAvailable contract violation")NS_DebugBreak(NS_DEBUG_WARNING, "Listener OnDataAvailable contract violation"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10924)
;
10925 nsCOMPtr<nsIConsoleService> consoleService;
10926 consoleService = mozilla::components::Console::Service();
10927 nsAutoString message(nsLiteralString(
10928 u"http channel Listener OnDataAvailable contract violation"));
10929 if (consoleService) {
10930 consoleService->LogStringMessage(message.get());
10931 }
10932 }
10933 }
10934 mLogicalOffset += count;
10935 }
10936
10937 return rv;
10938 }
10939
10940 return NS_ERROR_ABORT;
10941}
10942
10943//-----------------------------------------------------------------------------
10944// nsHttpChannel::nsIThreadRetargetableRequest
10945//-----------------------------------------------------------------------------
10946
10947NS_IMETHODIMPnsresult
10948nsHttpChannel::RetargetDeliveryTo(nsISerialEventTarget* aNewTarget) {
10949 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"
, 10949); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on main thread only" ")"); do { MOZ_CrashSequence
(__null, 10949); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10950
10951 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"
, 10951); return NS_ERROR_INVALID_ARG; } } while (false)
;
10952 if (aNewTarget->IsOnCurrentThread()) {
10953 NS_WARNING("Retargeting delivery to same thread")NS_DebugBreak(NS_DEBUG_WARNING, "Retargeting delivery to same thread"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10953)
;
10954 return NS_OK;
10955 }
10956 // Dictionary operations (saving, decompressing dcb/dcz, or using a
10957 // dictionary for decompression) require the main thread for hash
10958 // accumulation, origin metadata writes, and dictionary data access.
10959 if (mDictSaving || mIsDictionaryCompressed || mDictDecompress) {
10960 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)
10961 ("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)
10962 "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)
10963 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)
10964 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)
;
10965 return NS_ERROR_NOT_AVAILABLE;
10966 }
10967 if (!mTransactionPump && !mCachePump) {
10968 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)
10969 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)
;
10970 return NS_ERROR_NOT_AVAILABLE;
10971 }
10972
10973 nsresult rv = NS_OK;
10974 // If both cache pump and transaction pump exist, we're probably dealing
10975 // with partially cached content. So, we must be able to retarget both.
10976 nsCOMPtr<nsIThreadRetargetableRequest> retargetableCachePump;
10977 nsCOMPtr<nsIThreadRetargetableRequest> retargetableTransactionPump;
10978 if (mCachePump) {
10979 retargetableCachePump = do_QueryObject(mCachePump);
10980 // nsInputStreamPump should implement this interface.
10981 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", 10981
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableCachePump"
")"); do { MOZ_CrashSequence(__null, 10981); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10982 rv = retargetableCachePump->RetargetDeliveryTo(aNewTarget);
10983 }
10984 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mTransactionPump) {
10985 retargetableTransactionPump = do_QueryObject(mTransactionPump);
10986 // nsInputStreamPump should implement this interface.
10987 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", 10987
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableTransactionPump"
")"); do { MOZ_CrashSequence(__null, 10987); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10988 rv = retargetableTransactionPump->RetargetDeliveryTo(aNewTarget);
10989
10990 // If retarget fails for transaction pump, we must restore mCachePump.
10991 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && retargetableCachePump) {
10992 nsCOMPtr<nsISerialEventTarget> main = GetMainThreadSerialEventTarget();
10993 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", 10993
); return NS_ERROR_UNEXPECTED; } } while (false)
;
10994 rv = retargetableCachePump->RetargetDeliveryTo(main);
10995 }
10996 }
10997 return rv;
10998}
10999
11000NS_IMETHODIMPnsresult
11001nsHttpChannel::GetDeliveryTarget(nsISerialEventTarget** aEventTarget) {
11002 if (mCachePump) {
11003 return mCachePump->GetDeliveryTarget(aEventTarget);
11004 }
11005 if (mTransactionPump) {
11006 nsCOMPtr<nsIThreadRetargetableRequest> request =
11007 do_QueryInterface(mTransactionPump);
11008 return request->GetDeliveryTarget(aEventTarget);
11009 }
11010 return NS_ERROR_NOT_AVAILABLE;
11011}
11012
11013//-----------------------------------------------------------------------------
11014// nsHttpChannel::nsThreadRetargetableStreamListener
11015//-----------------------------------------------------------------------------
11016
11017NS_IMETHODIMPnsresult
11018nsHttpChannel::CheckListenerChain() {
11019 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"
, 11019); MOZ_PretendNoReturn(); } } while (0)
;
11020 nsresult rv = NS_OK;
11021 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
11022 do_QueryInterface(mListener, &rv);
11023 if (retargetableListener) {
11024 rv = retargetableListener->CheckListenerChain();
11025 }
11026 return rv;
11027}
11028
11029NS_IMETHODIMPnsresult
11030nsHttpChannel::OnDataFinished(nsresult aStatus) {
11031 nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
11032 do_QueryInterface(mListener);
11033
11034 if (listener) {
11035 return listener->OnDataFinished(aStatus);
11036 }
11037
11038 return NS_OK;
11039}
11040
11041//-----------------------------------------------------------------------------
11042// nsHttpChannel::nsITransportEventSink
11043//-----------------------------------------------------------------------------
11044
11045NS_IMETHODIMPnsresult
11046nsHttpChannel::OnTransportStatus(nsITransport* trans, nsresult status,
11047 int64_t progress, int64_t progressMax) {
11048 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"
, 11048); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be on main thread only" ")"); do { MOZ_CrashSequence
(__null, 11048); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11049 // cache the progress sink so we don't have to query for it each time.
11050 if (!mProgressSink) GetCallback(mProgressSink);
11051
11052 mLastTransportStatus = status;
11053 if (status == NS_NET_STATUS_CONNECTED_TO ||
11054 status == NS_NET_STATUS_WAITING_FOR) {
11055 bool isTrr = false;
11056 bool echConfigUsed = false;
11057 if (mTransaction) {
11058 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
11059 mEffectiveTRRMode, mTRRSkipReason,
11060 echConfigUsed);
11061
11062 } else {
11063 nsCOMPtr<nsISocketTransport> socketTransport = do_QueryInterface(trans);
11064 if (socketTransport) {
11065 socketTransport->GetPeerAddr(&mPeerAddr);
11066 socketTransport->GetSelfAddr(&mSelfAddr);
11067 socketTransport->ResolvedByTRR(&isTrr);
11068 socketTransport->GetEffectiveTRRMode(&mEffectiveTRRMode);
11069 socketTransport->GetEchConfigUsed(&echConfigUsed);
11070 }
11071 }
11072
11073 StoreResolvedByTRR(isTrr);
11074 StoreEchConfigUsed(echConfigUsed);
11075 }
11076
11077 // block socket status event after Cancel or OnStopRequest has been called.
11078 if (mProgressSink && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && LoadIsPending()) {
11079 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)
11080 " 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)
11081 (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)
11082 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)
;
11083
11084 nsAutoCString host;
11085 mURI->GetHost(host);
11086 nsCOMPtr<nsIProgressEventSink> progressSink(mProgressSink);
11087 if (!(mLoadFlags & LOAD_BACKGROUND)) {
11088 progressSink->OnStatus(this, status, NS_ConvertUTF8toUTF16(host).get());
11089 } else {
11090 nsCOMPtr<nsIParentChannel> parentChannel;
11091 NS_QueryNotificationCallbacks(this, parentChannel);
11092 // If the event sink is |HttpChannelParent|, we have to send status
11093 // events to it even if LOAD_BACKGROUND is set. |HttpChannelParent|
11094 // needs to be aware of whether the status is
11095 // |NS_NET_STATUS_RECEIVING_FROM| or |NS_NET_STATUS_READING|.
11096 // LOAD_BACKGROUND is checked again in |HttpChannelChild|, so the final
11097 // consumer won't get this event.
11098 if (SameCOMIdentity(parentChannel, mProgressSink)) {
11099 progressSink->OnStatus(this, status, NS_ConvertUTF8toUTF16(host).get());
11100 }
11101 }
11102
11103 if (progress > 0) {
11104 if ((progress > progressMax) && (progressMax != -1)) {
11105 NS_WARNING("unexpected progress values")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values",
nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11105)
;
11106 }
11107
11108 // Try to get mProgressSink if it was nulled out during OnStatus.
11109 if (!mProgressSink) {
11110 GetCallback(mProgressSink);
11111 progressSink = mProgressSink;
11112 }
11113 if (progressSink) {
11114 progressSink->OnProgress(this, progress, progressMax);
11115 }
11116 }
11117 }
11118
11119 return NS_OK;
11120}
11121
11122//-----------------------------------------------------------------------------
11123// nsHttpChannel::nsICacheInfoChannel
11124//-----------------------------------------------------------------------------
11125
11126NS_IMETHODIMPnsresult
11127nsHttpChannel::IsFromCache(bool* value) {
11128 if (!LoadIsPending()) return NS_ERROR_NOT_AVAILABLE;
11129
11130 // return false if reading a partial cache entry; the data isn't
11131 // entirely from the cache!
11132 *value = (mCachePump || (mLoadFlags & LOAD_ONLY_IF_MODIFIED)) &&
11133 CachedContentIsValid() && !LoadCachedContentIsPartial();
11134 return NS_OK;
11135}
11136
11137NS_IMETHODIMPnsresult
11138nsHttpChannel::HasCacheEntry(bool* value) {
11139 *value = !!mCacheEntry;
11140 return NS_OK;
11141}
11142
11143NS_IMETHODIMPnsresult
11144nsHttpChannel::GetCacheEntryId(uint64_t* aCacheEntryId) {
11145 if (!mCacheEntry || NS_FAILED(mCacheEntry->GetCacheEntryId(aCacheEntryId))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCacheEntry->GetCacheEntryId
(aCacheEntryId))), 0)))
) {
11146 return NS_ERROR_NOT_AVAILABLE;
11147 }
11148
11149 return NS_OK;
11150}
11151
11152NS_IMETHODIMPnsresult
11153nsHttpChannel::GetCacheTokenFetchCount(uint32_t* _retval) {
11154 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", 11154
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11155 nsCOMPtr<nsICacheEntry> cacheEntry =
11156 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11157 if (!cacheEntry) {
11158 return NS_ERROR_NOT_AVAILABLE;
11159 }
11160
11161 return cacheEntry->GetFetchCount(_retval);
11162}
11163
11164NS_IMETHODIMPnsresult
11165nsHttpChannel::GetCacheTokenExpirationTime(uint32_t* _retval) {
11166 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", 11166
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11167 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
11168
11169 return mCacheEntry->GetExpirationTime(_retval);
11170}
11171
11172NS_IMETHODIMPnsresult
11173nsHttpChannel::SetAllowStaleCacheContent(bool aAllowStaleCacheContent) {
11174 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)
11175 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)
;
11176 StoreAllowStaleCacheContent(aAllowStaleCacheContent);
11177 return NS_OK;
11178}
11179NS_IMETHODIMPnsresult
11180nsHttpChannel::GetAllowStaleCacheContent(bool* aAllowStaleCacheContent) {
11181 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"
, 11181); return NS_ERROR_INVALID_ARG; } } while (false)
;
11182 *aAllowStaleCacheContent = LoadAllowStaleCacheContent();
11183 return NS_OK;
11184}
11185
11186NS_IMETHODIMPnsresult
11187nsHttpChannel::SetForceValidateCacheContent(bool aForceValidateCacheContent) {
11188 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)
11189 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)
;
11190 StoreForceValidateCacheContent(aForceValidateCacheContent);
11191 return NS_OK;
11192}
11193NS_IMETHODIMPnsresult
11194nsHttpChannel::GetForceValidateCacheContent(bool* aForceValidateCacheContent) {
11195 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"
, 11195); return NS_ERROR_INVALID_ARG; } } while (false)
;
11196 *aForceValidateCacheContent = LoadForceValidateCacheContent();
11197 return NS_OK;
11198}
11199
11200NS_IMETHODIMPnsresult
11201nsHttpChannel::SetPreferCacheLoadOverBypass(bool aPreferCacheLoadOverBypass) {
11202 StorePreferCacheLoadOverBypass(aPreferCacheLoadOverBypass);
11203 return NS_OK;
11204}
11205NS_IMETHODIMPnsresult
11206nsHttpChannel::GetPreferCacheLoadOverBypass(bool* aPreferCacheLoadOverBypass) {
11207 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"
, 11207); return NS_ERROR_INVALID_ARG; } } while (false)
;
11208 *aPreferCacheLoadOverBypass = LoadPreferCacheLoadOverBypass();
11209 return NS_OK;
11210}
11211
11212NS_IMETHODIMPnsresult
11213nsHttpChannel::PreferAlternativeDataType(
11214 const nsACString& aType, const nsACString& aContentType,
11215 PreferredAlternativeDataDeliveryType aDeliverAltData) {
11216 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11216); 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"
, 11216, 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"
, 11216); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11216); 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"
, 11216); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
11217 mPreferredCachedAltDataTypes.AppendElement(PreferredAlternativeDataTypeParams(
11218 nsCString(aType), nsCString(aContentType), aDeliverAltData));
11219 return NS_OK;
11220}
11221
11222const nsTArray<PreferredAlternativeDataTypeParams>&
11223nsHttpChannel::PreferredAlternativeDataTypes() {
11224 return mPreferredCachedAltDataTypes;
11225}
11226
11227NS_IMETHODIMPnsresult
11228nsHttpChannel::GetAlternativeDataType(nsACString& aType) {
11229 // must be called during or after OnStartRequest
11230 if (!LoadAfterOnStartRequestBegun()) {
11231 return NS_ERROR_NOT_AVAILABLE;
11232 }
11233 aType = mAvailableCachedAltDataType;
11234 return NS_OK;
11235}
11236
11237class CacheEntryWriteHandle : public nsICacheEntryWriteHandle {
11238 virtual ~CacheEntryWriteHandle() = default;
11239
11240 public:
11241 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:
11242 NS_DECL_NSICACHEENTRYWRITEHANDLEvirtual nsresult OpenAlternativeOutputStream(const nsACString
& type, int64_t predictedSize, nsIAsyncOutputStream **_retval
) override;
11243
11244 explicit CacheEntryWriteHandle(nsICacheEntry* aCacheEntry)
11245 : mCacheEntry(aCacheEntry) {
11246 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"
, 11246); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 11246); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11247 }
11248
11249 private:
11250 nsCOMPtr<nsICacheEntry> mCacheEntry;
11251};
11252
11253NS_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"
, 11253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 11253
); __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"
, 11253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CacheEntryWriteHandle\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11253); __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; }
11254NS_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"
, 11254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 11254
); __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"
, 11254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CacheEntryWriteHandle\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11254); __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; }
11255NS_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"
, 11255); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
11256 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
11257 NS_INTERFACE_MAP_ENTRY(nsICacheEntryWriteHandle)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheEntryWriteHandle>)) foundInterface
= static_cast<nsICacheEntryWriteHandle*>(this); else
11258NS_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"
, 11258); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 11258); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); status
= NS_NOINTERFACE; } else { (foundInterface)->AddRef(); status
= NS_OK; } *aInstancePtr = foundInterface; return status; }
11259
11260NS_IMETHODIMPnsresult
11261CacheEntryWriteHandle::OpenAlternativeOutputStream(
11262 const nsACString& type, int64_t predictedSize,
11263 nsIAsyncOutputStream** _retval) {
11264 nsresult rv =
11265 mCacheEntry->OpenAlternativeOutputStream(type, predictedSize, _retval);
11266 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11267 mCacheEntry->SetMetaDataElement("alt-data-from-child", nullptr);
11268 }
11269 return rv;
11270}
11271
11272NS_IMETHODIMPnsresult
11273nsHttpChannel::GetCacheEntryWriteHandle(nsICacheEntryWriteHandle** _retval) {
11274 nsCOMPtr<nsICacheEntry> cacheEntry =
11275 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11276 if (!cacheEntry) {
11277 return NS_ERROR_NOT_AVAILABLE;
11278 }
11279
11280 nsCOMPtr<nsICacheEntryWriteHandle> handle =
11281 new CacheEntryWriteHandle(cacheEntry);
11282 handle.forget(_retval);
11283 return NS_OK;
11284}
11285
11286NS_IMETHODIMPnsresult
11287nsHttpChannel::OpenAlternativeOutputStream(const nsACString& type,
11288 int64_t predictedSize,
11289 nsIAsyncOutputStream** _retval) {
11290 // OnStopRequest will clear mCacheEntry, but we may use mAltDataCacheEntry
11291 // if the consumer called PreferAlternativeDataType()
11292 nsCOMPtr<nsICacheEntry> cacheEntry =
11293 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11294 if (!cacheEntry) {
11295 return NS_ERROR_NOT_AVAILABLE;
11296 }
11297 nsresult rv =
11298 cacheEntry->OpenAlternativeOutputStream(type, predictedSize, _retval);
11299 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11300 // Clear this metadata flag in case it exists.
11301 // The caller of this method may set it again.
11302 cacheEntry->SetMetaDataElement("alt-data-from-child", nullptr);
11303 }
11304 return rv;
11305}
11306
11307NS_IMETHODIMPnsresult
11308nsHttpChannel::GetOriginalInputStream(nsIInputStreamReceiver* aReceiver) {
11309 if (aReceiver == nullptr) {
11310 return NS_ERROR_INVALID_ARG;
11311 }
11312 nsCOMPtr<nsIInputStream> inputStream;
11313
11314 nsCOMPtr<nsICacheEntry> cacheEntry =
11315 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11316 if (cacheEntry) {
11317 cacheEntry->OpenInputStream(0, getter_AddRefs(inputStream));
11318 }
11319 aReceiver->OnInputStreamReady(inputStream);
11320 return NS_OK;
11321}
11322
11323NS_IMETHODIMPnsresult
11324nsHttpChannel::GetAlternativeDataInputStream(nsIInputStream** aInputStream) {
11325 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"
, 11325); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11326
11327 *aInputStream = nullptr;
11328
11329 nsCOMPtr<nsICacheEntry> cacheEntry =
11330 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11331 if (!mAvailableCachedAltDataType.IsEmpty() && cacheEntry) {
11332 nsresult rv = cacheEntry->OpenAlternativeInputStream(
11333 mAvailableCachedAltDataType, aInputStream);
11334 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"
, 11334); return rv; } } while (false)
;
11335 }
11336 return NS_OK;
11337}
11338
11339//-----------------------------------------------------------------------------
11340// nsHttpChannel::nsICachingChannel
11341//-----------------------------------------------------------------------------
11342
11343NS_IMETHODIMPnsresult
11344nsHttpChannel::GetCacheToken(nsISupports** token) {
11345 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", 11345
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11346 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
11347 return CallQueryInterface(mCacheEntry, token);
11348}
11349
11350NS_IMETHODIMPnsresult
11351nsHttpChannel::SetCacheToken(nsISupports* token) {
11352 return NS_ERROR_NOT_IMPLEMENTED;
11353}
11354
11355NS_IMETHODIMPnsresult
11356nsHttpChannel::GetCacheKey(uint32_t* key) {
11357 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"
, 11357); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11358
11359 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)
;
11360
11361 *key = mPostID;
11362 return NS_OK;
11363}
11364
11365NS_IMETHODIMPnsresult
11366nsHttpChannel::SetCacheKey(uint32_t key) {
11367 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)
;
11368
11369 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11369); 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"
, 11369, 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"
, 11369); } } 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", 11369
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 11369); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
11370
11371 mPostID = key;
11372 return NS_OK;
11373}
11374
11375NS_IMETHODIMPnsresult
11376nsHttpChannel::GetCacheOnlyMetadata(bool* aOnlyMetadata) {
11377 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"
, 11377); return NS_ERROR_INVALID_ARG; } } while (false)
;
11378 *aOnlyMetadata = LoadCacheOnlyMetadata();
11379 return NS_OK;
11380}
11381
11382NS_IMETHODIMPnsresult
11383nsHttpChannel::SetCacheOnlyMetadata(bool aOnlyMetadata) {
11384 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)
11385 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)
;
11386
11387 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11387); 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"
, 11387, 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"
, 11387); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11387); 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"
, 11387); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
11388
11389 StoreCacheOnlyMetadata(aOnlyMetadata);
11390 if (aOnlyMetadata) {
11391 mLoadFlags |= LOAD_ONLY_IF_MODIFIED;
11392 }
11393
11394 return NS_OK;
11395}
11396
11397NS_IMETHODIMPnsresult
11398nsHttpChannel::GetPin(bool* aPin) {
11399 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", 11399
); return NS_ERROR_INVALID_ARG; } } while (false)
;
11400 *aPin = LoadPinCacheContent();
11401 return NS_OK;
11402}
11403
11404NS_IMETHODIMPnsresult
11405nsHttpChannel::SetPin(bool aPin) {
11406 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)
;
11407
11408 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11408); 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"
, 11408, 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"
, 11408); } } 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", 11408
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 11408); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
11409
11410 StorePinCacheContent(aPin);
11411 return NS_OK;
11412}
11413
11414NS_IMETHODIMPnsresult
11415nsHttpChannel::ForceCacheEntryValidFor(uint32_t aSecondsToTheFuture) {
11416 if (!mCacheEntry) {
11417 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)
11418 ("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)
11419 "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)
11420 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)
;
11421 } else {
11422 mCacheEntry->ForceValidFor(aSecondsToTheFuture);
11423
11424 nsAutoCString key;
11425 mCacheEntry->GetKey(key);
11426
11427 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)
11428 ("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)
11429 "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)
11430 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)
;
11431 }
11432
11433 return NS_OK;
11434}
11435
11436//-----------------------------------------------------------------------------
11437// nsHttpChannel::nsIResumableChannel
11438//-----------------------------------------------------------------------------
11439
11440NS_IMETHODIMPnsresult
11441nsHttpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) {
11442 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)
11443 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)
;
11444 mEntityID = aEntityID;
11445 mStartPos = aStartPos;
11446 StoreResuming(true);
11447 return NS_OK;
11448}
11449
11450nsresult nsHttpChannel::DoAuthRetry(
11451 HttpTransactionShell* aTransWithStickyConn,
11452 const std::function<nsresult(nsHttpChannel*, nsresult)>&
11453 aContinueOnStopRequestFunc) {
11454 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)
11455 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)
;
11456
11457 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"
, 11457); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mTransaction"
") (" "should not have a transaction" ")"); do { MOZ_CrashSequence
(__null, 11457); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11458
11459 // Clear security info so it can be repopulated by the retried connection.
11460 mSecurityInfo = nullptr;
11461
11462 // Note that we don't have to toggle |IsPending| anymore. See the reasons
11463 // below.
11464 // 1. We can't suspend the channel during "http-on-modify-request"
11465 // when |IsPending| is false.
11466 // 2. We don't check |IsPending| in SetRequestHeader now.
11467
11468 // Reset RequestObserversCalled because we've probably called the request
11469 // observers once already.
11470 StoreRequestObserversCalled(false);
11471
11472 // fetch cookies, and add them to the request header.
11473 // the server response could have included cookies that must be sent with
11474 // this authentication attempt (bug 84794).
11475 // TODO: save cookies from auth response and send them here (bug 572151).
11476 AddCookiesToRequest();
11477
11478 // notify "http-on-modify-request" observers
11479 CallOnModifyRequestObservers();
11480
11481 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
11482 return CallOrWaitForResume(
11483 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
11484 return self->ContinueDoAuthRetry(trans, aContinueOnStopRequestFunc);
11485 });
11486}
11487
11488nsresult nsHttpChannel::ContinueDoAuthRetry(
11489 HttpTransactionShell* aTransWithStickyConn,
11490 const std::function<nsresult(nsHttpChannel*, nsresult)>&
11491 aContinueOnStopRequestFunc) {
11492 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)
;
11493 StoreIsPending(true);
11494
11495 // get rid of the old response headers
11496 mResponseHead = nullptr;
11497
11498 // rewind the upload stream
11499 if (mUploadStream) {
11500 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
11501 nsresult rv = NS_ERROR_NO_INTERFACE;
11502 if (seekable) {
11503 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
11504 }
11505
11506 // This should not normally happen, but it's possible that big memory
11507 // blobs originating in the other process can't be rewinded.
11508 // In that case we just fail the request, otherwise the content length
11509 // will not match and this load will never complete.
11510 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"
, 11510); return rv; } } while (false)
;
11511 }
11512
11513 // always set sticky connection flag
11514 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
11515 // and when needed, allow restart regardless the sticky flag
11516 if (LoadAuthConnectionRestartable()) {
11517 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)
;
11518 mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
11519 StoreAuthConnectionRestartable(false);
11520 } else {
11521 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)
;
11522 mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
11523 }
11524
11525 // notify "http-on-before-connect" observers
11526 gHttpHandler->OnBeforeConnect(this);
11527
11528 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
11529 return CallOrWaitForResume(
11530 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
11531 nsresult rv = self->DoConnect(trans);
11532 return aContinueOnStopRequestFunc(self, rv);
11533 });
11534}
11535
11536//-----------------------------------------------------------------------------
11537// nsHttpChannel::nsIAsyncVerifyRedirectCallback
11538//-----------------------------------------------------------------------------
11539
11540nsresult nsHttpChannel::WaitForRedirectCallback() {
11541 nsresult rv;
11542 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)
;
11543
11544 if (mTransactionPump) {
11545 rv = mTransactionPump->Suspend();
11546 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"
, 11546); return rv; } } while (false)
;
11547 }
11548 if (mCachePump) {
11549 rv = mCachePump->Suspend();
11550 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && mTransactionPump) {
11551#ifdef DEBUG1
11552 nsresult resume =
11553#endif
11554 mTransactionPump->Resume();
11555 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"
, 11555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(resume)), 1)))"
") (" "Failed to resume transaction pump" ")"); do { MOZ_CrashSequence
(__null, 11555); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11556 }
11557 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"
, 11557); return rv; } } while (false)
;
11558 }
11559
11560 StoreWaitingForRedirectCallback(true);
11561 return NS_OK;
11562}
11563
11564NS_IMETHODIMPnsresult
11565nsHttpChannel::OnRedirectVerifyCallback(nsresult result) {
11566 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)
11567 ("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)
11568 "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)
11569 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)
11570 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)
;
11571 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"
, 11572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { MOZ_CrashSequence(__null, 11572); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11572 "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"
, 11572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { MOZ_CrashSequence(__null, 11572); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11573 StoreWaitingForRedirectCallback(false);
11574
11575 if (mCanceled && NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) result = NS_BINDING_ABORTED;
11576
11577 for (uint32_t i = mRedirectFuncStack.Length(); i > 0;) {
11578 --i;
11579 // Pop the last function pushed to the stack
11580 nsContinueRedirectionFunc func = mRedirectFuncStack.PopLastElement();
11581
11582 // Call it with the result we got from the callback or the deeper
11583 // function call.
11584 result = (this->*func)(result);
11585
11586 // If a new function has been pushed to the stack and placed us in the
11587 // waiting state, we need to break the chain and wait for the callback
11588 // again.
11589 if (LoadWaitingForRedirectCallback()) break;
11590 }
11591
11592 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
11593 // First, cancel this channel if we are in failure state to set mStatus
11594 // and let it be propagated to pumps.
11595 Cancel(result);
11596 }
11597
11598 if (!LoadWaitingForRedirectCallback()) {
11599 // We are not waiting for the callback. At this moment we must release
11600 // reference to the redirect target channel, otherwise we may leak.
11601 // However, if we are redirecting due to auth retries, we open the
11602 // redirected channel after OnStopRequest. In that case we should not
11603 // release the reference
11604 if (!StaticPrefs::network_auth_use_redirect_for_retries() ||
11605 !mAuthRetryPending) {
11606 mRedirectChannel = nullptr;
11607 }
11608 }
11609
11610 // We always resume the pumps here. If all functions on stack have been
11611 // called we need OnStopRequest to be triggered, and if we broke out of the
11612 // loop above (and are thus waiting for a new callback) the suspension
11613 // count must be balanced in the pumps.
11614 if (mTransactionPump) mTransactionPump->Resume();
11615 if (mCachePump) mCachePump->Resume();
11616
11617 return result;
11618}
11619
11620void nsHttpChannel::PushRedirectAsyncFunc(nsContinueRedirectionFunc func) {
11621 mRedirectFuncStack.AppendElement(func);
11622}
11623
11624void nsHttpChannel::PopRedirectAsyncFunc(nsContinueRedirectionFunc func) {
11625 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"
, 11626); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { MOZ_CrashSequence(__null, 11626); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11626 "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"
, 11626); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { MOZ_CrashSequence(__null, 11626); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11627
11628 mRedirectFuncStack.RemoveLastElement();
11629}
11630
11631//-----------------------------------------------------------------------------
11632// nsIDNSListener functions
11633//-----------------------------------------------------------------------------
11634
11635NS_IMETHODIMPnsresult
11636nsHttpChannel::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
11637 nsresult status) {
11638 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"
, 11638); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { MOZ_CrashSequence
(__null, 11638); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11639
11640 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)
11641 ("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)
11642 "%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)
11643 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)
11644 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)
11645 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)
;
11646
11647 // Unset DNS cache refresh if it was requested,
11648 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
11649 mCaps &= ~NS_HTTP_REFRESH_DNS(1 << 3);
11650 if (mTransaction) {
11651 mTransaction->SetDNSWasRefreshed();
11652 }
11653 }
11654
11655 if (!mDNSBlockingPromise.IsEmpty()) {
11656 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
11657 nsCOMPtr<nsIDNSRecord> record(rec);
11658 mDNSBlockingPromise.Resolve(record, __func__);
11659 } else {
11660 mDNSBlockingPromise.Reject(status, __func__);
11661 }
11662 }
11663
11664 return NS_OK;
11665}
11666
11667void nsHttpChannel::OnHTTPSRRAvailable(nsIDNSHTTPSSVCRecord* aRecord) {
11668 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"
, 11668); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { MOZ_CrashSequence
(__null, 11668); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11669
11670 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)
11671 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)
;
11672
11673 if (mHTTPSSVCRecord) {
11674 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"
, 11674); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"OnHTTPSRRAvailable called twice!" ")"); do { MOZ_CrashSequence
(__null, 11674); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11675 return;
11676 }
11677
11678 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
11679 mHTTPSSVCRecord.emplace(std::move(record));
11680 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& httprr = mHTTPSSVCRecord.ref();
11681
11682 if (LoadWaitHTTPSSVCRecord()) {
11683 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", 11683
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mURI->SchemeIs(\"http\")"
")"); do { MOZ_CrashSequence(__null, 11683); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11684
11685 StoreWaitHTTPSSVCRecord(false);
11686 nsresult rv = ContinueOnBeforeConnect(!!httprr, mStatus, !!httprr);
11687 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11688 CloseCacheEntry(false);
11689 (void)AsyncAbort(rv);
11690 }
11691 } else {
11692 // This channel is not canceled and the transaction is not created.
11693 if (httprr && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mTransaction &&
11694 (mFirstResponseSource != RESPONSE_FROM_CACHE)) {
11695 bool hasIPAddress = false;
11696 (void)httprr->GetHasIPAddresses(&hasIPAddress);
11697 glean::http::dns_httpssvc_record_receiving_stage.AccumulateSingleSample(
11698 hasIPAddress ? HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_0
11699 : HTTPSSVC_WITHOUT_IPHINT_RECEIVED_STAGE_0);
11700 StoreHTTPSSVCTelemetryReported(true);
11701 }
11702 }
11703}
11704
11705//-----------------------------------------------------------------------------
11706// nsHttpChannel internal functions
11707//-----------------------------------------------------------------------------
11708
11709// Creates an URI to the given location using current URI for base and charset
11710nsresult nsHttpChannel::CreateNewURI(const char* loc, nsIURI** newURI) {
11711 nsCOMPtr<nsIIOService> ioService;
11712 nsresult rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
11713 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
11714
11715 return ioService->NewURI(nsDependentCString(loc), nullptr, mURI, newURI);
11716}
11717
11718void nsHttpChannel::MaybeInvalidateCacheEntryForSubsequentGet() {
11719 // See RFC 2616 section 5.1.1. These are considered valid
11720 // methods which DO NOT invalidate cache-entries for the
11721 // referred resource. POST, PUT and DELETE as well as any
11722 // other method not listed here will potentially invalidate
11723 // any cached copy of the resource
11724 if (mRequestHead.IsGet() || mRequestHead.IsOptions() ||
11725 mRequestHead.IsHead() || mRequestHead.IsTrace() ||
11726 mRequestHead.IsConnect()) {
11727 return;
11728 }
11729
11730 // Invalidate the request-uri.
11731 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
11732 nsAutoCString key;
11733 mURI->GetAsciiSpec(key);
11734 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)
11735 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)
;
11736 }
11737
11738 DoInvalidateCacheEntry(mURI);
11739
11740 // Invalidate Location-header if set
11741 nsAutoCString location;
11742 (void)mResponseHead->GetHeader(nsHttp::Location, location);
11743 if (!location.IsEmpty()) {
11744 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)
;
11745 InvalidateCacheEntryForLocation(location.get());
11746 }
11747
11748 // Invalidate Content-Location-header if set
11749 (void)mResponseHead->GetHeader(nsHttp::Content_Location, location);
11750 if (!location.IsEmpty()) {
11751 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)
;
11752 InvalidateCacheEntryForLocation(location.get());
11753 }
11754}
11755
11756void nsHttpChannel::InvalidateCacheEntryForLocation(const char* location) {
11757 nsAutoCString tmpCacheKey, tmpSpec;
11758 nsCOMPtr<nsIURI> resultingURI;
11759 nsresult rv = CreateNewURI(location, getter_AddRefs(resultingURI));
11760 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && HostPartIsTheSame(resultingURI)) {
11761 DoInvalidateCacheEntry(resultingURI);
11762 } else {
11763 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)
;
11764 }
11765}
11766
11767void nsHttpChannel::DoInvalidateCacheEntry(nsIURI* aURI) {
11768 // NOTE:
11769 // Following comments 24,32 and 33 in bug #327765, we only care about
11770 // the cache in the protocol-handler.
11771 // The logic below deviates from the original logic in OpenCacheEntry on
11772 // one point by using only READ_ONLY access-policy. I think this is safe.
11773
11774 nsresult rv;
11775
11776 nsAutoCString key;
11777 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
11778 aURI->GetAsciiSpec(key);
11779 }
11780
11781 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)
;
11782
11783 nsCOMPtr<nsICacheStorageService> cacheStorageService(
11784 components::CacheStorage::Service());
11785 rv = cacheStorageService ? NS_OK : NS_ERROR_FAILURE;
11786
11787 nsCOMPtr<nsICacheStorage> cacheStorage;
11788 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11789 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
11790 rv = cacheStorageService->DiskCacheStorage(info,
11791 getter_AddRefs(cacheStorage));
11792 }
11793
11794 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11795 rv = cacheStorage->AsyncDoomURI(aURI, ""_ns, nullptr);
11796 }
11797
11798 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)
11799 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)
;
11800}
11801
11802void nsHttpChannel::AsyncOnExamineCachedResponse() {
11803 gHttpHandler->OnExamineCachedResponse(this);
11804}
11805
11806void nsHttpChannel::UpdateAggregateCallbacks() {
11807 if (!mTransaction) {
11808 return;
11809 }
11810 nsCOMPtr<nsIInterfaceRequestor> callbacks;
11811 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
11812 GetCurrentSerialEventTarget(),
11813 getter_AddRefs(callbacks));
11814 mTransaction->SetSecurityCallbacks(callbacks);
11815}
11816
11817NS_IMETHODIMPnsresult
11818nsHttpChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
11819 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"
, 11819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { MOZ_CrashSequence(__null, 11819
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
11820
11821 nsresult rv = HttpBaseChannel::SetLoadGroup(aLoadGroup);
11822 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11823 UpdateAggregateCallbacks();
11824 }
11825 return rv;
11826}
11827
11828NS_IMETHODIMPnsresult
11829nsHttpChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
11830 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"
, 11830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { MOZ_CrashSequence(__null, 11830
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
11831
11832 nsresult rv = HttpBaseChannel::SetNotificationCallbacks(aCallbacks);
11833 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11834 UpdateAggregateCallbacks();
11835 }
11836 return rv;
11837}
11838
11839bool nsHttpChannel::AwaitingCacheCallbacks() {
11840 return LoadWaitForCacheEntry() != 0;
11841}
11842
11843// static
11844bool nsHttpChannel::IsRedirectStatus(uint32_t status) {
11845 // 305 disabled as a security measure (see bug 187996).
11846 return status == 301 || status == 302 || status == 303 || status == 307 ||
11847 status == 308;
11848}
11849
11850void nsHttpChannel::SetCouldBeSynthesized() {
11851 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", 11851
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
")"); do { MOZ_CrashSequence(__null, 11851); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11852 StoreResponseCouldBeSynthesized(true);
11853}
11854
11855NS_IMETHODIMPnsresult
11856nsHttpChannel::OnPreflightSucceeded() {
11857 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"
, 11857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { MOZ_CrashSequence
(__null, 11857); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11858 StoreIsCorsPreflightDone(1);
11859 mPreflightChannel = nullptr;
11860
11861 return ContinueConnect();
11862}
11863
11864NS_IMETHODIMPnsresult
11865nsHttpChannel::OnPreflightFailed(nsresult aError) {
11866 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"
, 11866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { MOZ_CrashSequence
(__null, 11866); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11867 StoreIsCorsPreflightDone(1);
11868 mPreflightChannel = nullptr;
11869
11870 CloseCacheEntry(false);
11871 (void)AsyncAbort(aError);
11872 return NS_OK;
11873}
11874
11875nsresult nsHttpChannel::CallOrWaitForResume(
11876 const std::function<nsresult(nsHttpChannel*)>& aFunc) {
11877 if (mCanceled) {
11878 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", 11878
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))"
")"); do { MOZ_CrashSequence(__null, 11878); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11879 return mStatus;
11880 }
11881
11882 if (mSuspendCount) {
11883 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)
;
11884 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", 11884
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume" ")"
); do { MOZ_CrashSequence(__null, 11884); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11885 mCallOnResume = aFunc;
11886 return NS_OK;
11887 }
11888
11889 return aFunc(this);
11890}
11891
11892// This is loosely based on:
11893// https://fetch.spec.whatwg.org/#serializing-a-request-origin
11894static bool HasNullRequestOrigin(nsHttpChannel* aChannel, nsIURI* aURI,
11895 bool isAddonRequest) {
11896 // Step 1. If request has a redirect-tainted origin, then return "null".
11897 if (aChannel->HasRedirectTaintedOrigin()) {
11898 return true;
11899 }
11900
11901 // Non-standard: Only allow HTTP and HTTPS origins.
11902 if (!ReferrerInfo::IsReferrerSchemeAllowed(aURI)) {
11903 // And moz-extension: for add-on initiated requests.
11904 if (!aURI->SchemeIs("moz-extension") || !isAddonRequest) {
11905 return true;
11906 }
11907 }
11908
11909 // Non-standard: Hide onion URLs.
11910 if (StaticPrefs::network_http_referer_hideOnionSource()) {
11911 nsAutoCString host;
11912 if (NS_SUCCEEDED(aURI->GetAsciiHost(host))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aURI->GetAsciiHost
(host))), 1)))
&&
11913 StringEndsWith(host, ".onion"_ns)) {
11914 return ReferrerInfo::IsCrossOriginRequest(aChannel);
11915 }
11916 }
11917
11918 // Step 2. Return request’s origin, serialized.
11919 return false;
11920}
11921
11922// Step 8.12. of HTTP-network-or-cache fetch
11923//
11924// https://fetch.spec.whatwg.org/#append-a-request-origin-header
11925void nsHttpChannel::SetOriginHeader() {
11926 auto* triggeringPrincipal =
11927 BasePrincipal::Cast(mLoadInfo->TriggeringPrincipal());
11928
11929 if (triggeringPrincipal->IsSystemPrincipal()) {
11930 // We can't infer an Origin header from the system principal,
11931 // this means system requests use whatever Origin header was specified.
11932 return;
11933 }
11934 bool isAddonRequest = triggeringPrincipal->AddonPolicy() ||
11935 triggeringPrincipal->ContentScriptAddonPolicy();
11936
11937 // Non-standard: Handle already existing Origin header.
11938 nsAutoCString existingHeader;
11939 (void)mRequestHead.GetHeader(nsHttp::Origin, existingHeader);
11940 if (!existingHeader.IsEmpty()) {
11941 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)
;
11942 auto const shouldNullifyOriginHeader =
11943 [&existingHeader, isAddonRequest](nsHttpChannel* aChannel) {
11944 nsCOMPtr<nsIURI> uri;
11945 nsresult rv = NS_NewURI(getter_AddRefs(uri), existingHeader);
11946 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11947 return false;
11948 }
11949
11950 if (HasNullRequestOrigin(aChannel, uri, isAddonRequest)) {
11951 return true;
11952 }
11953
11954 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
11955 if (info->GetTainting() == mozilla::LoadTainting::CORS) {
11956 return false;
11957 }
11958
11959 return ReferrerInfo::ShouldSetNullOriginHeader(aChannel, uri);
11960 };
11961
11962 if (!existingHeader.EqualsLiteral("null") &&
11963 shouldNullifyOriginHeader(this)) {
11964 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)
;
11965 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", 11966
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { MOZ_CrashSequence(__null, 11966); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
11966 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", 11966
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { MOZ_CrashSequence(__null, 11966); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
11967 }
11968 return;
11969 }
11970
11971 if (StaticPrefs::network_http_sendOriginHeader() == 0) {
11972 // Custom user setting: 0 means never send Origin header.
11973 return;
11974 }
11975
11976 // Step 2. Let serializedOrigin be the result of byte-serializing a request
11977 // origin with request.
11978 nsAutoCString serializedOrigin;
11979 nsCOMPtr<nsIURI> uri;
11980 {
11981 if (NS_FAILED(triggeringPrincipal->GetURI(getter_AddRefs(uri)))((bool)(__builtin_expect(!!(NS_FAILED_impl(triggeringPrincipal
->GetURI(getter_AddRefs(uri)))), 0)))
) {
11982 return;
11983 }
11984
11985 if (!uri) {
11986 if (isAddonRequest) {
11987 // For add-on compatibility prefer sending no header at all
11988 // instead of `Origin: null`.
11989 return;
11990 }
11991
11992 // Otherwise use "null" when the triggeringPrincipal's URI is nullptr.
11993 serializedOrigin.AssignLiteral("null");
11994 } else if (HasNullRequestOrigin(this, uri, isAddonRequest)) {
11995 serializedOrigin.AssignLiteral("null");
11996 } else {
11997 nsContentUtils::GetWebExposedOriginSerialization(uri, serializedOrigin);
11998 }
11999 }
12000
12001 // Step 3. If request’s response tainting is "cors" or request’s mode is
12002 // "websocket", then append (`Origin`, serializedOrigin) to request’s header
12003 // list.
12004 //
12005 // Note: We don't handle "websocket" here (yet?).
12006 if (mLoadInfo->GetTainting() == mozilla::LoadTainting::CORS) {
12007 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", 12008
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12008); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
12008 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", 12008
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12008); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12009 return;
12010 }
12011
12012 // Step 4. Otherwise, if request’s method is neither `GET` nor `HEAD`, then:
12013 if (mRequestHead.IsGet() || mRequestHead.IsHead()) {
12014 // Modified Step 4 in case storage-access-headers are enabled
12015 if (!StaticPrefs::dom_storage_access_enabled() ||
12016 !StaticPrefs::dom_storage_access_headers_enabled()) {
12017 // proceed with unmodified fetch spec
12018 return;
12019 } else {
12020 // the result of getting `Sec-Fetch-Storage-Access` from request’s header
12021 // list is "inactive"
12022 nsAutoCString storageAccess;
12023 nsresult rv =
12024 GetRequestHeader("Sec-Fetch-Storage-Access"_ns, storageAccess);
12025 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !storageAccess.EqualsLiteral("inactive")) {
12026 return;
12027 }
12028 }
12029 }
12030
12031 if (!serializedOrigin.EqualsLiteral("null")) {
12032 // Step 4.1. (Implemented by ReferrerInfo::ShouldSetNullOriginHeader)
12033 if (ReferrerInfo::ShouldSetNullOriginHeader(this, uri)) {
12034 serializedOrigin.AssignLiteral("null");
12035 } else if (StaticPrefs::network_http_sendOriginHeader() == 1) {
12036 // Non-standard: Restrict Origin to same-origin loads if requested by user
12037 nsAutoCString currentOrigin;
12038 nsContentUtils::GetWebExposedOriginSerialization(mURI, currentOrigin);
12039 if (!serializedOrigin.EqualsIgnoreCase(currentOrigin.get())) {
12040 // Origin header suppressed by user setting.
12041 serializedOrigin.AssignLiteral("null");
12042 }
12043 }
12044 }
12045
12046 // Step 4.2. Append (`Origin`, serializedOrigin) to request’s header list.
12047 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", 12048
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12048); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
12048 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", 12048
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12048); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12049}
12050
12051void nsHttpChannel::SetDoNotTrack() {
12052 /**
12053 * 'DoNotTrack' header should be added if 'privacy.donottrackheader.enabled'
12054 * is true.
12055 */
12056 if (StaticPrefs::privacy_donottrackheader_enabled()) {
12057 DebugOnly<nsresult> rv =
12058 mRequestHead.SetHeader(nsHttp::DoNotTrack, "1"_ns, false);
12059 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"
, 12059); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 12059); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12060 }
12061}
12062
12063void nsHttpChannel::SetGlobalPrivacyControl() {
12064 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"
, 12064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12064); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12065
12066 if (StaticPrefs::privacy_globalprivacycontrol_functionality_enabled() &&
12067 (StaticPrefs::privacy_globalprivacycontrol_enabled() ||
12068 (StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled() &&
12069 NS_UsePrivateBrowsing(this)))) {
12070 // Send the header with a value of 1 to indicate opting-out
12071 DebugOnly<nsresult> rv =
12072 mRequestHead.SetHeader(nsHttp::GlobalPrivacyControl, "1"_ns, false);
12073 }
12074}
12075
12076void nsHttpChannel::ReportSystemChannelTelemetry(nsresult status) {
12077 // Use status and httpStatus to determine
12078 // if it was successful, and if we had connectivity / offline in this time
12079 nsAutoCString domain;
12080 mOriginalURI->GetHost(domain);
12081
12082 if (!LoadUsedNetwork()) {
12083 // We're not really interested in any cached requests.
12084 return;
12085 }
12086
12087 if (!StringEndsWith(domain, ".mozilla.org"_ns) &&
12088 !StringEndsWith(domain, ".mozilla.com"_ns) &&
12089 mEssentialDomainCategory.isNothing()) {
12090 return;
12091 }
12092
12093 nsAutoCString label("ok"_ns);
12094 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
12095 if (mCanceled) {
12096 // The request was cancelled.
12097 label = "cancel"_ns;
12098 } else if (NS_IsOffline()) {
12099 // The error occured while all interfaces are offline
12100 label = "offline"_ns;
12101 } else if (!hasConnectivity()) {
12102 // The error occured while the browser didn't have connectivity
12103 label = "connectivity"_ns;
12104 } else if (status == NS_ERROR_UNKNOWN_HOST) {
12105 // The failure was a DNS error
12106 label = "dns"_ns;
12107 } else if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY21) {
12108 // The error was due to TLS
12109 label = "tls_fail"_ns;
12110 } else if (status == NS_ERROR_NET_RESET) {
12111 label = "reset"_ns;
12112 } else if (status == NS_ERROR_NET_TIMEOUT) {
12113 label = "timeout"_ns;
12114 } else if (status == NS_ERROR_CONNECTION_REFUSED) {
12115 label = "refused"_ns;
12116 } else if (status == NS_ERROR_NET_PARTIAL_TRANSFER) {
12117 label = "partial"_ns;
12118 } else {
12119 // Unspecified error. If this bucket is too big we might add other labels.
12120 label = "other"_ns;
12121 }
12122 } else if (mResponseHead && mResponseHead->Status() / 100 != 2) {
12123 // There was no channel error, but the server responded with a non-2XX
12124 // status code.
12125 label = "http_status";
12126 }
12127
12128 // This is the first time failure channel
12129 if (mEssentialDomainCategory.isNothing()) {
12130 auto category = GetEssentialDomainCategory(domain);
12131 switch (category) {
12132 case EssentialDomainCategory::SubAddonsMozillaOrg: {
12133 mozilla::glean::network::system_channel_addonversion_status.Get(label)
12134 .Add(1);
12135 return;
12136 }
12137 case EssentialDomainCategory::AddonsMozillaOrg: {
12138 mozilla::glean::network::system_channel_addon_status.Get(label).Add(1);
12139 return;
12140 }
12141 case EssentialDomainCategory::Aus5MozillaOrg: {
12142 mozilla::glean::network::system_channel_update_status.Get(label).Add(1);
12143 return;
12144 }
12145 case EssentialDomainCategory::RemoteSettings: {
12146 mozilla::glean::network::system_channel_remote_settings_status
12147 .Get(label)
12148 .Add(1);
12149 return;
12150 }
12151 case EssentialDomainCategory::Telemetry: {
12152 mozilla::glean::network::system_channel_telemetry_status.Get(label).Add(
12153 1);
12154 return;
12155 }
12156 default: {
12157 // Not one of the probes we recorded earlier.
12158 mozilla::glean::network::system_channel_other_status.Get(label).Add(1);
12159 return;
12160 }
12161 }
12162 }
12163
12164 // This is a retry.
12165 switch (mEssentialDomainCategory.ref()) {
12166 case EssentialDomainCategory::SubAddonsMozillaOrg: {
12167 mozilla::glean::network::retried_system_channel_addonversion_status
12168 .Get(label)
12169 .Add(1);
12170 return;
12171 }
12172 case EssentialDomainCategory::AddonsMozillaOrg: {
12173 mozilla::glean::network::retried_system_channel_addon_status.Get(label)
12174 .Add(1);
12175 return;
12176 }
12177 case EssentialDomainCategory::Aus5MozillaOrg: {
12178 mozilla::glean::network::retried_system_channel_update_status.Get(label)
12179 .Add(1);
12180 return;
12181 }
12182 case EssentialDomainCategory::RemoteSettings: {
12183 mozilla::glean::network::retried_system_channel_remote_settings_status
12184 .Get(label)
12185 .Add(1);
12186 return;
12187 }
12188 case EssentialDomainCategory::Telemetry: {
12189 mozilla::glean::network::retried_system_channel_telemetry_status
12190 .Get(label)
12191 .Add(1);
12192 return;
12193 }
12194 default: {
12195 // Not one of the probes we recorded earlier.
12196 mozilla::glean::network::retried_system_channel_other_status.Get(label)
12197 .Add(1);
12198 return;
12199 }
12200 }
12201}
12202
12203nsresult nsHttpChannel::TriggerNetwork() {
12204 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"
, 12204); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12204); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12205
12206 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)
;
12207
12208 if (mCanceled) {
12209 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)
;
12210 return mStatus;
12211 }
12212
12213 // If a network request has already gone out, there is no point in
12214 // doing this again.
12215 if (mNetworkTriggered) {
12216 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)
;
12217 return NS_OK;
12218 }
12219
12220 mNetworkTriggered = true;
12221
12222 // If we are waiting for a proxy request, that means we can't trigger
12223 // the next step just yet. We need for mConnectionInfo to be non-null
12224 // before we call ContinueConnect. OnProxyAvailable will trigger
12225 // BeginConnect, and Connect will call ContinueConnect even if it's
12226 // for the cache callbacks.
12227 if (mProxyRequest) {
12228 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)
;
12229 mWaitingForProxy = true;
12230 return NS_OK;
12231 }
12232
12233 return ContinueConnect();
12234}
12235
12236nsresult nsHttpChannel::OnSuspendTimeout() {
12237 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"
, 12237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12237); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12238
12239 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)
;
12240
12241 // If we're still suspended and have a cache entry, enable bypass mode
12242 // This allows any waiting or future listeners to continue
12243 if (mSuspendCount > 0 && mCacheEntry) {
12244 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)
;
12245 mCacheEntry->SetBypassWriterLock(true);
12246 mBypassCacheWriterSet = true;
12247 }
12248
12249 return NS_OK;
12250}
12251
12252nsHttpChannel::TimerCallback::TimerCallback(nsHttpChannel* aChannel)
12253 : mChannel(aChannel) {}
12254
12255NS_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"
, 12255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12255
); __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"
, 12255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12255); __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"
, 12255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12255
); __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"
, 12255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12255); __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"
, 12255); 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; }
12256
12257NS_IMETHODIMPnsresult
12258nsHttpChannel::TimerCallback::GetName(nsACString& aName) {
12259 aName.AssignLiteral("nsHttpChannel");
12260 return NS_OK;
12261}
12262
12263NS_IMETHODIMPnsresult
12264nsHttpChannel::TimerCallback::Notify(nsITimer* aTimer) {
12265 if (aTimer == mChannel->mSuspendTimer) {
12266 return mChannel->OnSuspendTimeout();
12267 }
12268 if (aTimer == mChannel->mCacheWaitTimer) {
12269 return mChannel->OnCacheWaitTimeout();
12270 }
12271 MOZ_CRASH("Unknown timer")do { do { } while (false); MOZ_ReportCrash("" "Unknown timer"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12271
); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown timer" ")"); do
{ MOZ_CrashSequence(__null, 12271); __attribute__((nomerge))
::abort(); } while (false); } while (false)
;
12272
12273 return NS_OK;
12274}
12275
12276void nsHttpChannel::MaybeStartCacheWaitTimer() {
12277 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", 12277
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12277); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12278
12279 uint32_t delay = StaticPrefs::network_cache_entry_wait_timeout_ms();
12280 if (!delay || mCacheWaitTimer || mCacheWaitTimedOut || mNetworkTriggered) {
12281 return;
12282 }
12283
12284 mCacheWaitTimer = NS_NewTimer();
12285 if (mCacheWaitTimer) {
12286 RefPtr<TimerCallback> timerCallback = new TimerCallback(this);
12287 mCacheWaitTimer->InitWithCallback(timerCallback, delay,
12288 nsITimer::TYPE_ONE_SHOT);
12289 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)
12290 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)
;
12291 }
12292}
12293
12294void nsHttpChannel::CancelCacheWaitTimer() {
12295 if (mCacheWaitTimer) {
12296 mCacheWaitTimer->Cancel();
12297 mCacheWaitTimer = nullptr;
12298 }
12299}
12300
12301nsresult nsHttpChannel::OnCacheWaitTimeout() {
12302 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", 12302
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12302); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12303
12304 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)
;
12305 mCacheWaitTimer = nullptr;
12306
12307 // Backstop for a wedged cache entry: if we're still parked waiting for a
12308 // cache entry callback that never arrived (e.g. a writer that was suspended
12309 // or cancelled without ever closing its output stream, so the entry stays
12310 // perpetually "being written"), stop waiting and race to the network so the
12311 // load can make progress instead of hanging forever.
12312 if (!LoadIsPending() || !AwaitingCacheCallbacks()) {
12313 return NS_OK;
12314 }
12315
12316 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)
;
12317 mCacheWaitTimedOut = true;
12318
12319 // Stop treating the outstanding cache open as blocking. A late
12320 // OnCacheEntryAvailable will be ignored (see mCacheWaitTimedOut).
12321 StoreWaitForCacheEntry(LoadWaitForCacheEntry() & ~WAIT_FOR_CACHE_ENTRY);
12322
12323 nsresult rv = TriggerNetwork();
12324 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12325 CloseCacheEntry(false);
12326 (void)AsyncAbort(rv);
12327 }
12328 return rv;
12329}
12330
12331bool nsHttpChannel::EligibleForTailing() {
12332 if (!(mClassOfService.Flags() & nsIClassOfService::Tail)) {
12333 return false;
12334 }
12335
12336 if (mClassOfService.Flags() &
12337 (nsIClassOfService::UrgentStart | nsIClassOfService::Leader |
12338 nsIClassOfService::TailForbidden)) {
12339 return false;
12340 }
12341
12342 if (mClassOfService.Flags() & nsIClassOfService::Unblocked &&
12343 !(mClassOfService.Flags() & nsIClassOfService::TailAllowed)) {
12344 return false;
12345 }
12346
12347 if (IsNavigation()) {
12348 return false;
12349 }
12350
12351 return true;
12352}
12353
12354bool nsHttpChannel::WaitingForTailUnblock() {
12355 nsresult rv;
12356
12357 if (!gHttpHandler->IsTailBlockingEnabled()) {
12358 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)
;
12359 return false;
12360 }
12361
12362 if (!EligibleForTailing()) {
12363 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)
;
12364 AddAsNonTailRequest();
12365 return false;
12366 }
12367
12368 if (!EnsureRequestContext()) {
12369 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)
;
12370 return false;
12371 }
12372
12373 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)
12374 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)
;
12375
12376 bool blocked;
12377 rv = mRequestContext->IsContextTailBlocked(this, &blocked);
12378 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12379 return false;
12380 }
12381
12382 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)
;
12383
12384 return blocked;
12385}
12386
12387//-----------------------------------------------------------------------------
12388// nsHttpChannel::nsIRequestTailUnblockCallback
12389//-----------------------------------------------------------------------------
12390
12391// Must be implemented in the leaf class because we don't have
12392// AsyncAbort in HttpBaseChannel.
12393NS_IMETHODIMPnsresult
12394nsHttpChannel::OnTailUnblock(nsresult rv) {
12395 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)
12396 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)
;
12397 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject12398( "nsHttpChannel::OnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
12398 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject12398( "nsHttpChannel::OnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
12399 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", 12399
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 12399); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12400
12401 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
12402 rv = mStatus;
12403 }
12404
12405 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12406 auto callback = mOnTailUnblock;
12407 mOnTailUnblock = nullptr;
12408 rv = (this->*callback)();
12409 }
12410
12411 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12412 CloseCacheEntry(false);
12413 return AsyncAbort(rv);
12414 }
12415
12416 return NS_OK;
12417}
12418
12419void nsHttpChannel::SetWarningReporter(
12420 HttpChannelSecurityWarningReporter* aReporter) {
12421 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)
;
12422 mWarningReporter = aReporter;
12423}
12424
12425HttpChannelSecurityWarningReporter* nsHttpChannel::GetWarningReporter() {
12426 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)
12427 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)
;
12428 return mWarningReporter.get();
12429}
12430
12431// The specification for ORB is currently being written:
12432// https://whatpr.org/fetch/1442.html#orb-algorithm
12433// The `opaque-response-safelist check` is implemented in:
12434// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff`
12435// * `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
12436// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff`
12437// * `OpaqueResponseBlocker::ValidateJavaScript`
12438//
12439// Should only be called by nsMediaSniffer::GetMIMETypeFromContent and
12440// imageLoader::GetMIMETypeFromContent when the content type can be
12441// recognized by these sniffers.
12442void nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck(
12443 SnifferType aType) {
12444 // https://whatpr.org/fetch/1442.html#orb-algorithm
12445 // This method covers steps, 8 and 10.
12446 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", 12446
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 12446); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12447
12448 if (NeedOpaqueResponseAllowedCheckAfterSniff()) {
12449 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"
, 12449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedOpaqueResponseBlockingPref"
")"); do { MOZ_CrashSequence(__null, 12449); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12450
12451 // If the sniffer type is media and the request comes from a media element,
12452 // we would like to check:
12453 // - Whether the information provided by the media element shows it's an
12454 // initial request.
12455 // - Whether the response's status is either 200 or 206.
12456 //
12457 // If any of the results is false, then we set
12458 // mBlockOpaqueResponseAfterSniff to true and block the response later.
12459 if (aType == SnifferType::Media) {
12460 // Step 8
12461 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"
, 12461); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo"
")"); do { MOZ_CrashSequence(__null, 12461); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12462
12463 auto noCorsMediaRequestState = NoCorsMediaRequestState();
12464 if (noCorsMediaRequestState !=
12465 dom::NoCorsMediaRequestState::NotAvailable) {
12466 if (noCorsMediaRequestState != dom::NoCorsMediaRequestState::Initial) {
12467 // Step 8.1
12468 BlockOpaqueResponseAfterSniff(
12469 u"media request after sniffing, but not initial request"_ns,
12470 OpaqueResponseBlockedTelemetryReason::eMediaNotInitial);
12471 return;
12472 }
12473
12474 if (mResponseHead->Status() != 200 && mResponseHead->Status() != 206) {
12475 // Step 8.2
12476 BlockOpaqueResponseAfterSniff(
12477 u"media request's response status is neither 200 nor 206"_ns,
12478 OpaqueResponseBlockedTelemetryReason::eMediaIncorrectResp);
12479 return;
12480 }
12481
12482 // At this point we've checked that the requested resource is media and
12483 // that the sniff passes. Any following requests for this resource
12484 // should be considered to be subsequent.
12485 RecordSubsequentNoCorsRequestState();
12486 }
12487 }
12488
12489 // Step 8.3 if `aType == SnifferType::Media`
12490 // Step 9 can be skipped, only `HTMLMediaElement` ever sets isMediaRequest.
12491 // Step 10 if `aType == SnifferType::Image`
12492 AllowOpaqueResponseAfterSniff();
12493 }
12494}
12495
12496namespace {
12497
12498class CopyNonDefaultHeaderVisitor final : public nsIHttpHeaderVisitor {
12499 nsCOMPtr<nsIHttpChannel> mTarget;
12500
12501 ~CopyNonDefaultHeaderVisitor() = default;
12502
12503 NS_IMETHODvirtual nsresult
12504 VisitHeader(const nsACString& aHeader, const nsACString& aValue) override {
12505 if (aValue.IsEmpty()) {
12506 return mTarget->SetEmptyRequestHeader(aHeader);
12507 }
12508 return mTarget->SetRequestHeader(aHeader, aValue, false /* merge */);
12509 }
12510
12511 public:
12512 explicit CopyNonDefaultHeaderVisitor(nsIHttpChannel* aTarget)
12513 : mTarget(aTarget) {
12514 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"
, 12514); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mTarget"
")"); do { MOZ_CrashSequence(__null, 12514); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12515 }
12516
12517 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:
12518};
12519
12520NS_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"
, 12520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12520
); __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"
, 12520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12520); __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"
, 12520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12520
); __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"
, 12520); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12520); __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"
, 12520); 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; }
12521
12522} // anonymous namespace
12523
12524nsresult nsHttpChannel::RedirectToInterceptedChannel() {
12525 nsCOMPtr<nsINetworkInterceptController> controller;
12526 GetCallback(controller);
12527
12528 RefPtr<InterceptedHttpChannel> intercepted =
12529 InterceptedHttpChannel::CreateForInterception(
12530 mChannelCreationTime, mChannelCreationTimestamp, mAsyncOpenTime);
12531
12532 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
12533 CloneLoadInfoForRedirect(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
12534
12535 nsresult rv = intercepted->Init(
12536 mURI, mCaps, static_cast<nsProxyInfo*>(mProxyInfo.get()),
12537 mProxyResolveFlags, mProxyURI, mChannelId, redirectLoadInfo);
12538
12539 rv = SetupReplacementChannel(mURI, intercepted, true,
12540 nsIChannelEventSink::REDIRECT_INTERNAL);
12541 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"
, 12541); return rv; } } while (false)
;
12542
12543 // Some APIs, like fetch(), allow content to set non-standard headers.
12544 // Normally these APIs are responsible for copying these headers across
12545 // redirects. In the e10s parent-side intercept case, though, we currently
12546 // "hide" the internal redirect to the InterceptedHttpChannel. So the
12547 // fetch() API does not have the opportunity to move headers over.
12548 // Therefore, we do it automatically here.
12549 //
12550 // Once child-side interception is removed and the internal redirect no
12551 // longer needs to be "hidden", then this header copying code can be
12552 // removed.
12553 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
12554 new CopyNonDefaultHeaderVisitor(intercepted);
12555 rv = VisitNonDefaultRequestHeaders(visitor);
12556 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"
, 12556); return rv; } } while (false)
;
12557
12558 mRedirectChannel = intercepted;
12559
12560 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
12561
12562 rv = gHttpHandler->AsyncOnChannelRedirect(
12563 this, intercepted, nsIChannelEventSink::REDIRECT_INTERNAL);
12564
12565 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12566 rv = WaitForRedirectCallback();
12567 }
12568
12569 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12570 AutoRedirectVetoNotifier notifier(this, rv);
12571
12572 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
12573 }
12574
12575 return rv;
12576}
12577
12578void nsHttpChannel::ReEvaluateReferrerAfterTrackingStatusIsKnown() {
12579 nsCOMPtr<nsICookieJarSettings> cjs;
12580 if (mLoadInfo) {
12581 (void)mLoadInfo->GetCookieJarSettings(getter_AddRefs(cjs));
12582 }
12583 if (!cjs) {
12584 cjs = net::CookieJarSettings::Create(mLoadInfo->GetLoadingPrincipal());
12585 }
12586 if (cjs->GetRejectThirdPartyContexts()) {
12587 bool isPrivate = mLoadInfo->GetOriginAttributes().IsPrivateBrowsing();
12588 // If our referrer has been set before, and our referrer policy is unset
12589 // (default policy) if we thought the channel wasn't a third-party
12590 // tracking channel, we may need to set our referrer with referrer policy
12591 // once again to ensure our defaults properly take effect now.
12592 if (mReferrerInfo) {
12593 ReferrerInfo* referrerInfo =
12594 static_cast<ReferrerInfo*>(mReferrerInfo.get());
12595
12596 if (referrerInfo->IsPolicyOverrided() &&
12597 referrerInfo->ReferrerPolicy() ==
12598 ReferrerInfo::GetDefaultReferrerPolicy(nullptr, nullptr,
12599 isPrivate)) {
12600 nsCOMPtr<nsIReferrerInfo> newReferrerInfo =
12601 referrerInfo->CloneWithNewPolicy(
12602 ReferrerInfo::GetDefaultReferrerPolicy(this, mURI, isPrivate));
12603 // The arguments passed to SetReferrerInfoInternal here should mirror
12604 // the arguments passed in
12605 // HttpChannelChild::RecvOverrideReferrerInfoDuringBeginConnect().
12606 SetReferrerInfoInternal(newReferrerInfo, false, true, true);
12607
12608 nsCOMPtr<nsIParentChannel> parentChannel;
12609 NS_QueryNotificationCallbacks(this, parentChannel);
12610 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
12611 if (httpParent) {
12612 httpParent->OverrideReferrerInfoDuringBeginConnect(newReferrerInfo);
12613 }
12614 }
12615 }
12616 }
12617}
12618
12619namespace {
12620
12621class BackgroundRevalidatingListener : public nsIStreamListener {
12622 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:
12623
12624 NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream
*aInputStream, uint64_t aOffset, uint32_t aCount) override;
12625 NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override
; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult
aStatusCode) override;
12626
12627 private:
12628 virtual ~BackgroundRevalidatingListener() = default;
12629};
12630
12631NS_IMETHODIMPnsresult
12632BackgroundRevalidatingListener::OnStartRequest(nsIRequest* request) {
12633 return NS_OK;
12634}
12635
12636NS_IMETHODIMPnsresult
12637BackgroundRevalidatingListener::OnDataAvailable(nsIRequest* request,
12638 nsIInputStream* input,
12639 uint64_t offset,
12640 uint32_t count) {
12641 uint32_t bytesRead = 0;
12642 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &bytesRead);
12643}
12644
12645NS_IMETHODIMPnsresult
12646BackgroundRevalidatingListener::OnStopRequest(nsIRequest* request,
12647 nsresult status) {
12648 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
12649 return status;
12650 }
12651
12652 nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(request));
12653 if (gHttpHandler) {
12654 gHttpHandler->OnBackgroundRevalidation(channel);
12655 }
12656 return NS_OK;
12657}
12658
12659NS_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"
, 12660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12660
); __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"
, 12660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12660); __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"
, 12660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12660
); __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"
, 12660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12660); __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", 12660
); 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<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
, 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; }
12660 nsIRequestObserver)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"
, 12660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12660
); __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"
, 12660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12660); __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"
, 12660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12660
); __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"
, 12660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12660); __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", 12660
); 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<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
, 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; }
12661
12662} // namespace
12663
12664void nsHttpChannel::PerformBackgroundCacheRevalidation() {
12665 if (!StaticPrefs::network_http_stale_while_revalidate_enabled()) {
12666 return;
12667 }
12668
12669 // This is a channel doing a revalidation. It shouldn't do it again.
12670 if (mStaleRevalidation) {
12671 return;
12672 }
12673
12674 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)
;
12675
12676 (void)NS_DispatchToMainThreadQueue(
12677 NewIdleRunnableMethod(
12678 "nsHttpChannel::PerformBackgroundCacheRevalidation", this,
12679 &nsHttpChannel::PerformBackgroundCacheRevalidationNow),
12680 EventQueuePriority::Idle);
12681}
12682
12683void nsHttpChannel::PerformBackgroundCacheRevalidationNow() {
12684 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)
;
12685
12686 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", 12686
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12686); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12687
12688 nsresult rv;
12689
12690 nsLoadFlags loadFlags = mLoadFlags | LOAD_ONLY_IF_MODIFIED | VALIDATE_ALWAYS |
12691 LOAD_BACKGROUND | LOAD_BYPASS_SERVICE_WORKER;
12692
12693 nsCOMPtr<nsIChannel> validatingChannel;
12694 rv = NS_NewChannelInternal(getter_AddRefs(validatingChannel), mURI, mLoadInfo,
12695 nullptr /* performance storage */, mLoadGroup,
12696 mCallbacks, loadFlags);
12697 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12698 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)
12699 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)
;
12700 return;
12701 }
12702
12703 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(validatingChannel));
12704 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"
, 12704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpChannel"
")"); do { MOZ_CrashSequence(__null, 12704); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12705 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
12706 new CopyNonDefaultHeaderVisitor(httpChannel);
12707 rv = VisitNonDefaultRequestHeaders(visitor);
12708 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12709 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)
12710 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)
;
12711 return;
12712 }
12713
12714 nsCOMPtr<nsISupportsPriority> priority(do_QueryInterface(validatingChannel));
12715 if (priority) {
12716 priority->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
12717 }
12718
12719 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(validatingChannel));
12720 if (cos) {
12721 cos->AddClassFlags(nsIClassOfService::Tail);
12722 }
12723
12724 RefPtr<nsHttpChannel> httpChan = do_QueryObject(validatingChannel);
12725 if (httpChan) {
12726 httpChan->mStaleRevalidation = true;
12727 }
12728
12729 RefPtr<BackgroundRevalidatingListener> listener =
12730 new BackgroundRevalidatingListener();
12731 rv = validatingChannel->AsyncOpen(listener);
12732 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12733 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)
;
12734 return;
12735 }
12736
12737 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)
12738 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)
;
12739}
12740
12741NS_IMETHODIMPnsresult
12742nsHttpChannel::SetEarlyHintObserver(nsIEarlyHintObserver* aObserver) {
12743 mEarlyHintObserver = aObserver;
12744 return NS_OK;
12745}
12746
12747NS_IMETHODIMPnsresult
12748nsHttpChannel::EarlyHint(const nsACString& aLinkHeader,
12749 const nsACString& aReferrerPolicy,
12750 const nsACString& aCspHeader) {
12751 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)
;
12752
12753 if (nsCOMPtr<nsIEarlyHintObserver> obs = mEarlyHintObserver) {
12754 if (nsContentUtils::ComputeIsSecureContext(this)) {
12755 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)
;
12756 obs->EarlyHint(aLinkHeader, aReferrerPolicy, aCspHeader);
12757 }
12758 }
12759 return NS_OK;
12760}
12761
12762NS_IMETHODIMPnsresult nsHttpChannel::SetResponseOverride(
12763 nsIReplacedHttpResponse* aReplacedHttpResponse) {
12764 mOverrideResponse = new nsMainThreadPtrHolder<nsIReplacedHttpResponse>(
12765 "nsIReplacedHttpResponse", aReplacedHttpResponse);
12766
12767 if (LoadRequireCORSPreflight()) {
12768 // Bug 1986615, Bug 1940738, responses provided via setResponseOverride will
12769 // be handled before the preflight can be sent, flag it as done.
12770 StoreIsCorsPreflightDone(true);
12771 }
12772
12773 return NS_OK;
12774}
12775
12776NS_IMETHODIMPnsresult nsHttpChannel::SetResponseStatus(uint32_t aStatus,
12777 const nsACString& aStatusText) {
12778 if (!mResponseHead) {
12779 return NS_ERROR_NOT_AVAILABLE;
12780 }
12781
12782 nsAutoCString statusText(aStatusText);
12783 nsAutoCString protocolVersion(
12784 nsHttp::GetProtocolVersion(mResponseHead->Version()));
12785 ToUpperCase(protocolVersion);
12786
12787 nsPrintfCString line("%s %u %s", protocolVersion.get(), aStatus,
12788 statusText.get());
12789
12790 return mResponseHead->ParseStatusLine(line);
12791}
12792
12793NS_IMETHODIMPnsresult nsHttpChannel::SetWebTransportSessionEventListener(
12794 WebTransportSessionEventListener* aListener) {
12795 mWebTransportSessionEventListener = aListener;
12796 return NS_OK;
12797}
12798
12799already_AddRefed<WebTransportSessionEventListener>
12800nsHttpChannel::GetWebTransportSessionEventListener() {
12801 RefPtr<WebTransportSessionEventListener> wt =
12802 mWebTransportSessionEventListener;
12803 return wt.forget();
12804}
12805
12806NS_IMETHODIMPnsresult nsHttpChannel::GetLastTransportStatus(
12807 nsresult* aLastTransportStatus) {
12808 *aLastTransportStatus = mLastTransportStatus;
12809 return NS_OK;
12810}
12811
12812NS_IMETHODIMPnsresult
12813nsHttpChannel::GetCacheDisposition(CacheDisposition* aDisposition) {
12814 if (!aDisposition) {
12815 return NS_ERROR_INVALID_ARG;
12816 }
12817 *aDisposition = mCacheDisposition;
12818 return NS_OK;
12819}
12820
12821} // namespace net
12822} // namespace mozilla