Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/netwerk/protocol/http/./../../../../netwerk/protocol/http/nsHttpChannel.cpp
Warning:line 5889, 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-08-224017-3544287-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->SetHttp3Policy((mCaps & NS_HTTP_DISALLOW_HTTP3(1 << 21))
1247 ? Http3Policy::Disabled
1248 : Http3Policy::Allowed);
1249 mConnectionInfo->SetAnonymousAllowClientCert(
1250 (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) != 0);
1251
1252 if (mWebTransportSessionEventListener) {
1253 nsTArray<RefPtr<nsIWebTransportHash>> aServerCertHashes;
1254 nsresult rv;
1255 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
1256 do_QueryInterface(mWebTransportSessionEventListener, &rv);
1257 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"
, 1257); return rv; } } while (false)
;
1258
1259 wtconSettings->GetServerCertificateHashes(aServerCertHashes);
1260 gHttpHandler->ConnMgr()->StoreServerCertHashes(
1261 mConnectionInfo, gHttpHandler->IsHttp2Excluded(mConnectionInfo),
1262 !Http3Allowed(), std::move(aServerCertHashes));
1263 }
1264
1265 if (ShouldIntercept()) {
1266 return RedirectToInterceptedChannel();
1267 }
1268
1269 // notify "http-on-before-connect" observers
1270 gHttpHandler->OnBeforeConnect(this);
1271
1272 return CallOrWaitForResume([](auto* self) { return self->Connect(); });
1273}
1274
1275class MOZ_STACK_CLASS AddResponseHeadersToResponseHead final
1276 : public nsIHttpHeaderVisitor {
1277 public:
1278 explicit AddResponseHeadersToResponseHead(nsHttpResponseHead* aResponseHead)
1279 : mResponseHead(aResponseHead) {}
1280
1281 NS_IMETHODvirtual nsresult VisitHeader(const nsACString& aHeader,
1282 const nsACString& aValue) override {
1283 nsAutoCString headerLine = aHeader + ": "_ns + aValue;
1284 DebugOnly<nsresult> rv = mResponseHead->ParseHeaderLine(headerLine);
1285 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"
, 1285); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1285); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1286
1287 return NS_OK;
1288 }
1289
1290 NS_IMETHODvirtual nsresult QueryInterface(REFNSIIDconst nsIID& aIID, void** aInstancePtr) override;
1291
1292 // Stub AddRef/Release since this is a stack class.
1293 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType AddRef(void) override {
1294 return ++mRefCnt;
1295 }
1296
1297 NS_IMETHOD_(MozExternalRefCountType)virtual MozExternalRefCountType Release(void) override {
1298 return --mRefCnt;
1299 }
1300
1301 virtual ~AddResponseHeadersToResponseHead() {
1302 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"
, 1302); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mRefCnt == 0"
")"); do { MOZ_CrashSequence(__null, 1302); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1303 }
1304
1305 private:
1306 nsHttpResponseHead* mResponseHead;
1307
1308 nsrefcnt mRefCnt = 0;
1309};
1310
1311NS_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"
, 1311); 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; }
1312
1313nsresult nsHttpChannel::HandleOverrideResponse() {
1314 // Start building a response with the data from mOverrideResponse.
1315 mResponseHead = MakeUnique<nsHttpResponseHead>();
1316
1317 // Apply override response status code and status text.
1318 uint32_t statusCode;
1319 nsresult rv = mOverrideResponse->GetResponseStatus(&statusCode);
1320 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"
, 1320); return rv; } } while (false)
;
1321
1322 nsAutoCString statusText;
1323 rv = mOverrideResponse->GetResponseStatusText(statusText);
1324 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"
, 1324); return rv; } } while (false)
;
1325
1326 // Hardcoding protocol HTTP/1.1
1327 nsPrintfCString line("HTTP/1.1 %u %s", statusCode, statusText.get());
1328 rv = mResponseHead->ParseStatusLine(line);
1329 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"
, 1329); return rv; } } while (false)
;
1330
1331 // Apply override response headers.
1332 AddResponseHeadersToResponseHead visitor(mResponseHead.get());
1333 rv = mOverrideResponse->VisitResponseHeaders(&visitor);
1334 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"
, 1334); return rv; } } while (false)
;
1335
1336 if (WillRedirect(*mResponseHead)) {
1337 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
1338 // to avoid event dispatching latency.
1339 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)
;
1340 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
1341 }
1342
1343 // This block parses the cookie header, collects any cookie changes,
1344 // and sends them to the parent actor.
1345 {
1346 RefPtr<HttpChannelParent> httpParent;
1347 RefPtr<CookieObserver> cookieObserver;
1348
1349 CookieServiceParent::CookieProcessingGuard cookieProcessingGuard;
1350 MaybeInitializeCookieProcessingGuard(
1351 this, cookieProcessingGuard, cookieObserver, httpParent, statusCode);
1352
1353 // Handle Set-Cookie headers as if the response was from networking.
1354 CookieVisitor cookieVisitor(mResponseHead.get());
1355 SetCookieHeaders(cookieVisitor.CookieHeaders());
1356
1357 if (cookieObserver) {
1358 nsTArray<CookieChange> cookieChanges;
1359 cookieObserver->StealChanges(cookieChanges);
1360
1361 if (!cookieChanges.IsEmpty()) {
1362 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"
, 1362); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpParent"
")"); do { MOZ_CrashSequence(__null, 1362); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1363 httpParent->SetCookieChanges(std::move(cookieChanges));
1364 }
1365 }
1366 }
1367
1368 rv = ProcessWAICTHeader();
1369 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1370 return rv;
1371 }
1372
1373 if (NS_FAILED(ProcessSecurityHeaders())((bool)(__builtin_expect(!!(NS_FAILED_impl(ProcessSecurityHeaders
())), 0)))
) {
1374 NS_WARNING("ProcessSecurityHeaders failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSecurityHeaders failed, continuing load."
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 1374)
;
1375 }
1376
1377 if ((statusCode < 500) && (statusCode != 421)) {
1378 ProcessAltService();
1379 }
1380
1381 nsAutoCString body;
1382 rv = mOverrideResponse->GetResponseBody(body);
1383 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"
, 1383); return rv; } } while (false)
;
1384
1385 nsCOMPtr<nsIInputStream> stringStream;
1386 rv = NS_NewCStringInputStream(getter_AddRefs(stringStream), body);
1387 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"
, 1387); return rv; } } while (false)
;
1388 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), stringStream, 0, 0,
1389 true);
1390 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1391 stringStream->Close();
1392 return rv;
1393 }
1394
1395 rv = mCachePump->AsyncRead(this);
1396 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1397
1398 return NS_OK;
1399}
1400
1401nsresult nsHttpChannel::Connect() {
1402 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)
;
1403
1404 if (mAPIRedirectTo) {
1405 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)
1406 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)
;
1407
1408 nsresult rv = StartRedirectChannelToURI(
1409 mAPIRedirectTo->first(),
1410 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_PERMANENT |
1411 nsIChannelEventSink::REDIRECT_TRANSPARENT
1412 : nsIChannelEventSink::REDIRECT_PERMANENT);
1413 mAPIRedirectTo = Nothing();
1414 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1415 return NS_OK;
1416 }
1417 return NS_ERROR_FAILURE;
1418 }
1419
1420 // If mOverrideResponse is set, bypass the rest of the connection and reply
1421 // immediately with a response built using the data from mOverrideResponse.
1422 if (mOverrideResponse) {
1423 return HandleOverrideResponse();
1424 }
1425
1426 // Don't allow resuming when cache must be used
1427 if (LoadResuming() && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
1428 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)
;
1429 return NS_ERROR_DOCUMENT_NOT_CACHED;
1430 }
1431
1432 // Step 8.18 of HTTP-network-or-cache fetch
1433 // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
1434 nsAutoCString rangeVal;
1435 if (NS_SUCCEEDED(GetRequestHeader("Range"_ns, rangeVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Range"_ns, rangeVal))), 1)))
) {
1436 SetRequestHeader("Accept-Encoding"_ns, "identity"_ns, false);
1437 }
1438
1439 if (mRequestHead.IsPost() || mRequestHead.IsPatch()) {
1440 // If the post id is already set then this is an attempt to replay
1441 // a post/patch transaction via the cache. Otherwise, we need a unique
1442 // post id for this transaction.
1443 if (mPostID == 0) {
1444 mPostID = gHttpHandler->GenerateUniqueID();
1445 }
1446
1447 if (StaticPrefs::network_http_idempotencyKey_enabled() &&
1448 !mRequestHead.HasHeader(nsHttp::Idempotency_Key)) {
1449 // check if we need to add
1450 // idempotency-key header
1451 // See Bug 1830022 for more details
1452 nsAutoCString key;
1453 gHttpHandler->GenerateIdempotencyKeyForPost(mPostID, mLoadInfo, key);
1454 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", 1455
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
")"); do { MOZ_CrashSequence(__null, 1455); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1455 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", 1455
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Idempotency_Key, key, false))"
")"); do { MOZ_CrashSequence(__null, 1455); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1456 }
1457 }
1458
1459#ifdef MOZ_WIDGET_ANDROID
1460 bool val = false;
1461 if (nsIOService::ShouldAddAdditionalSearchHeaders(mURI, &val)) {
1462 SetRequestHeader("X-Search-Subdivision"_ns, val ? "1"_ns : "0"_ns, false);
1463 }
1464#endif
1465
1466 bool isTrackingResource = IsThirdPartyTrackingResource();
1467 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)
1468 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)
1469 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)
;
1470
1471 if (isTrackingResource) {
1472 AddClassFlags(nsIClassOfService::Tail);
1473 }
1474
1475 if (WaitingForTailUnblock()) {
1476 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", 1476
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 1476); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1477 mOnTailUnblock = &nsHttpChannel::ConnectOnTailUnblock;
1478 return NS_OK;
1479 }
1480
1481 return ConnectOnTailUnblock();
1482}
1483
1484nsresult nsHttpChannel::ConnectOnTailUnblock() {
1485 nsresult rv;
1486
1487 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)
;
1488 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ConnectOnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject1489( "nsHttpChannel::ConnectOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
1489 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject1489( "nsHttpChannel::ConnectOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
1490
1491 // Consider opening a TCP connection right away.
1492 SpeculativeConnect();
1493
1494 // open a cache entry for this channel...
1495 rv = OpenCacheEntry(mURI->SchemeIs("https"));
1496
1497 // do not continue if asyncOpenCacheEntry is in progress
1498 if (AwaitingCacheCallbacks()) {
1499 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)
1500 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
1501 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"
, 1501); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
") (" "Unexpected state" ")"); do { MOZ_CrashSequence(__null
, 1501); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1502
1503 // Backstop against a wedged cache entry that never delivers its callback.
1504 MaybeStartCacheWaitTimer();
1505
1506 if (mNetworkTriggered && mWaitingForProxy) {
1507 // Someone has called TriggerNetwork(), meaning we are racing the
1508 // network with the cache.
1509 mWaitingForProxy = false;
1510 return ContinueConnect();
1511 }
1512
1513 return NS_OK;
1514 }
1515
1516 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1517 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)
1518 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)
;
1519 // if this channel is only allowed to pull from the cache, then
1520 // we must fail if we were unable to open a cache entry.
1521 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1522 return NS_ERROR_DOCUMENT_NOT_CACHED;
1523 }
1524 // otherwise, let's just proceed without using the cache.
1525 }
1526
1527 return TriggerNetwork();
1528}
1529
1530nsresult nsHttpChannel::ContinueConnect() {
1531 // If we need to start a CORS preflight, do it now!
1532 // Note that it is important to do this before the early returns below.
1533 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ContinueConnect", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject1534( "nsHttpChannel::ContinueConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
1534 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject1534( "nsHttpChannel::ContinueConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
1535 if (!LoadIsCorsPreflightDone() && LoadRequireCORSPreflight()) {
1536 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", 1536
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mPreflightChannel"
")"); do { MOZ_CrashSequence(__null, 1536); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1537 nsresult rv = nsCORSListenerProxy::StartCORSPreflight(
1538 this, this, mUnsafeHeaders, getter_AddRefs(mPreflightChannel));
1539 return rv;
1540 }
1541
1542 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"
, 1544); 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, 1544); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1543 "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"
, 1544); 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, 1544); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
1544 "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"
, 1544); 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, 1544); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1545
1546 RefPtr<mozilla::dom::BrowsingContext> bc;
1547 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
1548
1549 // we may or may not have a cache entry at this point
1550 if (mCacheEntry) {
1551 // read straight from the cache if possible...
1552 if (CachedContentIsValid()) {
1553 // If we're forced offline, and set to bypass the cache, return offline.
1554 if (bc && bc->Top()->GetForceOffline() &&
1555 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
1556 return NS_ERROR_OFFLINE;
1557 }
1558
1559 nsRunnableMethod<nsHttpChannel>* event = nullptr;
1560 nsresult rv;
1561 if (!LoadCachedContentIsPartial()) {
1562 rv = AsyncCall(&nsHttpChannel::AsyncOnExamineCachedResponse, &event);
1563 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1564 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)
;
1565 }
1566 }
1567 rv = ReadFromCache();
1568 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && event) {
1569 event->Revoke();
1570 }
1571
1572 AccumulateCacheHitTelemetry(kCacheHit, this);
1573 mCacheDisposition = kCacheHit;
1574
1575 return rv;
1576 }
1577 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1578 // the cache contains the requested resource, but it must be
1579 // validated before we can reuse it. since we are not allowed
1580 // to hit the net, there's nothing more to do. the document
1581 // is effectively not in the cache.
1582 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)
;
1583 return NS_ERROR_DOCUMENT_NOT_CACHED;
1584 }
1585 } else if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
1586 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)
;
1587 return NS_ERROR_DOCUMENT_NOT_CACHED;
1588 }
1589
1590 if (mLoadFlags & LOAD_NO_NETWORK_IO) {
1591 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)
;
1592 return NS_ERROR_DOCUMENT_NOT_CACHED;
1593 }
1594
1595 // We're about to hit the network. Don't if we're forced offline.
1596 if (bc && bc->Top()->GetForceOffline()) {
1597 return NS_ERROR_OFFLINE;
1598 }
1599
1600 // hit the net...
1601 nsresult rv = DoConnect(mTransactionSticky);
1602 mTransactionSticky = nullptr;
1603 return rv;
1604}
1605
1606nsresult nsHttpChannel::DoConnect(HttpTransactionShell* aTransWithStickyConn) {
1607 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
)
;
1608
1609 if (!mDNSBlockingPromise.IsEmpty()) {
1610 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)
;
1611
1612 // Transaction is passed only from auth retry for which we will definitely
1613 // not block on DNS to alter the origin server name for IP; it has already
1614 // been done.
1615 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", 1615
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTransWithStickyConn"
")"); do { MOZ_CrashSequence(__null, 1615); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1616 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", 1616
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDNSBlockingThenable"
")"); do { MOZ_CrashSequence(__null, 1616); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1617
1618 nsCOMPtr<nsISerialEventTarget> target(do_GetMainThread());
1619 RefPtr<nsHttpChannel> self(this);
1620 mDNSBlockingThenable->Then(
1621 target, __func__,
1622 [self](const nsCOMPtr<nsIDNSRecord>& aRec) {
1623 nsresult rv = self->DoConnectActual(nullptr);
1624 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1625 self->CloseCacheEntry(false);
1626 (void)self->AsyncAbort(rv);
1627 }
1628 },
1629 [self](nsresult err) {
1630 self->CloseCacheEntry(false);
1631 (void)self->AsyncAbort(err);
1632 });
1633
1634 // The connection will continue when the promise is resolved in
1635 // OnLookupComplete.
1636 return NS_OK;
1637 }
1638
1639 return DoConnectActual(aTransWithStickyConn);
1640}
1641
1642nsresult nsHttpChannel::DoConnectActual(
1643 HttpTransactionShell* aTransWithStickyConn) {
1644 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)
1645 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)
;
1646
1647 nsresult rv = SetupChannelForTransaction();
1648 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1649 return rv;
1650 }
1651
1652 return CallOrWaitForResume(
1653 [trans = RefPtr(aTransWithStickyConn)](auto* self) {
1654 return self->DispatchTransaction(trans);
1655 });
1656}
1657
1658nsresult nsHttpChannel::DispatchTransaction(
1659 HttpTransactionShell* aTransWithStickyConn) {
1660 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)
1661 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)
;
1662 nsresult rv = InitTransaction();
1663 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1664 return rv;
1665 }
1666 if (aTransWithStickyConn) {
1667 rv = gHttpHandler->InitiateTransactionWithStickyConn(
1668 mTransaction, mPriority, aTransWithStickyConn);
1669 } else {
1670 rv = gHttpHandler->InitiateTransaction(mTransaction, mPriority);
1671 }
1672
1673 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1674 return rv;
1675 }
1676
1677 rv = mTransaction->AsyncRead(this, getter_AddRefs(mTransactionPump));
1678 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1679 return rv;
1680 }
1681
1682 uint32_t suspendCount = mSuspendCount;
1683 if (LoadAsyncResumePending()) {
1684 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)
1685 (" 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)
1686 ", 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)
1687 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)
;
1688 ++suspendCount;
1689 }
1690 while (suspendCount--) {
1691 mTransactionPump->Suspend();
1692 }
1693
1694 return NS_OK;
1695}
1696
1697void nsHttpChannel::SpeculativeConnect() {
1698 // Before we take the latency hit of dealing with the cache, try and
1699 // get the TCP (and SSL) handshakes going so they can overlap.
1700
1701 // don't speculate if we are offline, when doing http upgrade (i.e.
1702 // websockets bootstrap), or if we can't do keep-alive (because then we
1703 // couldn't reuse the speculative connection anyhow).
1704 RefPtr<mozilla::dom::BrowsingContext> bc;
1705 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
1706
1707 if (gIOService->IsOffline() || mUpgradeProtocolCallback ||
1708 !(mCaps & NS_HTTP_ALLOW_KEEPALIVE(1 << 0)) ||
1709 (bc && bc->Top()->GetForceOffline())) {
1710 return;
1711 }
1712
1713 // LOAD_ONLY_FROM_CACHE and LOAD_NO_NETWORK_IO must not hit network.
1714 // LOAD_FROM_CACHE is unlikely to hit network, so skip preconnects for it.
1715 if (mLoadFlags &
1716 (LOAD_ONLY_FROM_CACHE | LOAD_FROM_CACHE | LOAD_NO_NETWORK_IO)) {
1717 return;
1718 }
1719
1720 if (LoadAllowStaleCacheContent()) {
1721 return;
1722 }
1723
1724 nsCOMPtr<nsIInterfaceRequestor> callbacks;
1725 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
1726 getter_AddRefs(callbacks));
1727 if (!callbacks) return;
1728 // Disable HTTPS RR, since the new HappyEyeballs implementation will handle
1729 // it.
1730 bool httpsRRAllowed = !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) &&
1731 !(mCaps & NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30));
1732 (void)gHttpHandler->MaybeSpeculativeConnectWithHTTPSRR(
1733 mConnectionInfo, callbacks,
1734 mCaps & (NS_HTTP_DISALLOW_SPDY(1 << 7) | NS_HTTP_TRR_MODE_MASK((1 << 19) | (1 << 20)) |
1735 NS_HTTP_DISABLE_IPV4(1 << 17) | NS_HTTP_DISABLE_IPV6(1 << 18) |
1736 NS_HTTP_DISALLOW_HTTP3(1 << 21) | NS_HTTP_REFRESH_DNS(1 << 3)),
1737 nsHttpHandler::EchConfigEnabled() && httpsRRAllowed);
1738}
1739
1740void nsHttpChannel::DoNotifyListenerCleanup() {
1741 // We don't need this info anymore
1742 CleanRedirectCacheChainIfNecessary();
1743}
1744
1745void nsHttpChannel::ReleaseListeners() {
1746 HttpBaseChannel::ReleaseListeners();
1747
1748 mChannelClassifier = nullptr;
1749 mWarningReporter = nullptr;
1750 mEarlyHintObserver = nullptr;
1751 mWebTransportSessionEventListener = nullptr;
1752
1753 for (StreamFilterRequest& request : mStreamFilterRequests) {
1754 request.mPromise->Reject(false, __func__);
1755 }
1756 mStreamFilterRequests.Clear();
1757}
1758
1759void nsHttpChannel::DoAsyncAbort(nsresult aStatus) {
1760 (void)AsyncAbort(aStatus);
1761}
1762
1763void nsHttpChannel::HandleAsyncRedirect() {
1764 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"
, 1764); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 1764); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1765
1766 if (mSuspendCount) {
1767 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)
;
1768 mCallOnResume = [](nsHttpChannel* self) {
1769 self->HandleAsyncRedirect();
1770 return NS_OK;
1771 };
1772 return;
1773 }
1774
1775 nsresult rv = NS_OK;
1776
1777 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)
;
1778
1779 // since this event is handled asynchronously, it is possible that this
1780 // channel could have been canceled, in which case there would be no point
1781 // in processing the redirect.
1782 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1)))) {
1783 PushRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1784 rv = AsyncProcessRedirection(mResponseHead->Status());
1785 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1786 PopRedirectAsyncFunc(&nsHttpChannel::ContinueHandleAsyncRedirect);
1787 // TODO: if !DoNotRender3xxBody(), render redirect body instead.
1788 // But first we need to cache 3xx bodies (bug 748510)
1789 rv = ContinueHandleAsyncRedirect(rv);
1790 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"
, 1790); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1790); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1791 }
1792 } else {
1793 rv = ContinueHandleAsyncRedirect(mStatus);
1794 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"
, 1794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1794); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1795 }
1796}
1797
1798nsresult nsHttpChannel::ContinueHandleAsyncRedirect(nsresult rv) {
1799 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1800 // If AsyncProcessRedirection fails, then we have to send out the
1801 // OnStart/OnStop notifications.
1802 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)
1803 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)
;
1804
1805 bool redirectsEnabled = !mLoadInfo->GetDontFollowRedirects();
1806
1807 if (redirectsEnabled) {
1808 // TODO: stop failing original channel if redirect vetoed?
1809 mStatus = rv;
1810
1811 DoNotifyListener();
1812
1813 // Blow away cache entry if we couldn't process the redirect
1814 // for some reason (the cache entry might be corrupt).
1815 if (mCacheEntry) {
1816 mCacheEntry->AsyncDoom(nullptr);
1817 }
1818 } else {
1819 DoNotifyListener();
1820 }
1821 }
1822
1823 CloseCacheEntry(true);
1824
1825 StoreIsPending(false);
1826
1827 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1828
1829 return NS_OK;
1830}
1831
1832void nsHttpChannel::HandleAsyncNotModified() {
1833 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"
, 1833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 1833); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
1834
1835 if (mSuspendCount) {
1836 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)
;
1837 mCallOnResume = [](nsHttpChannel* self) {
1838 self->HandleAsyncNotModified();
1839 return NS_OK;
1840 };
1841 return;
1842 }
1843
1844 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)
;
1845
1846 DoNotifyListener();
1847
1848 CloseCacheEntry(false);
1849
1850 StoreIsPending(false);
1851
1852 if (mLoadGroup) mLoadGroup->RemoveRequest(this, nullptr, mStatus);
1853}
1854
1855nsresult nsHttpChannel::SetupChannelForTransaction() {
1856 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)
1857 "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)
1858 "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)
1859 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)
;
1860
1861 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"
, 1861); return NS_ERROR_ALREADY_INITIALIZED; } } while (false
)
;
1862
1863 nsresult rv;
1864
1865 if (StaticPrefs::network_http_priority_header_enabled()) {
1866 SetPriorityHeader();
1867 }
1868
1869 StoreUsedNetwork(1);
1870
1871 if (!LoadAllowSpdy()) {
1872 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
1873 }
1874 if (!LoadAllowHttp3()) {
1875 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
1876 }
1877 if (LoadBeConservative()) {
1878 mCaps |= NS_HTTP_BE_CONSERVATIVE(1 << 11);
1879 }
1880
1881 if (mLoadFlags & LOAD_ANONYMOUS_ALLOW_CLIENT_CERT) {
1882 mCaps |= NS_HTTP_LOAD_ANONYMOUS_CONNECT_ALLOW_CLIENT_CERT(1 << 23);
1883 }
1884
1885 if (nsContentUtils::ShouldResistFingerprinting(this,
1886 RFPTarget::HttpUserAgent)) {
1887 mCaps |= NS_HTTP_USE_RFP(1 << 26);
1888 }
1889
1890 // Use the URI path if not proxying (transparent proxying such as proxy
1891 // CONNECT does not count here). Also figure out what HTTP version to use.
1892 nsAutoCString buf, path;
1893 nsCString* requestURI;
1894
1895 // This is the normal e2e H1 path syntax "/index.html"
1896 rv = mURI->GetPathQueryRef(path);
1897 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1898 return rv;
1899 }
1900
1901 // path may contain UTF-8 characters, so ensure that they're escaped.
1902 if (NS_EscapeURL(path.get(), path.Length(), esc_OnlyNonASCII | esc_Spaces,
1903 buf)) {
1904 requestURI = &buf;
1905 } else {
1906 requestURI = &path;
1907 }
1908
1909 // trim off the #ref portion if any...
1910 int32_t ref1 = requestURI->FindChar('#');
1911 if (ref1 != kNotFound) {
1912 requestURI->SetLength(ref1);
1913 }
1914
1915 if (mConnectionInfo->UsingConnect() || !mConnectionInfo->UsingHttpProxy()) {
1916 mRequestHead.SetVersion(gHttpHandler->HttpVersion());
1917 } else {
1918 mRequestHead.SetPath(*requestURI);
1919
1920 // RequestURI should be the absolute uri H1 proxy syntax
1921 // "http://foo/index.html" so we will overwrite the relative version in
1922 // requestURI
1923 rv = mURI->GetUserPass(buf);
1924 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1925 if (!buf.IsEmpty() && ((strncmp(mSpec.get(), "http:", 5) == 0) ||
1926 strncmp(mSpec.get(), "https:", 6) == 0)) {
1927 nsCOMPtr<nsIURI> tempURI = nsIOService::CreateExposableURI(mURI);
1928 rv = tempURI->GetAsciiSpec(path);
1929 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1930 requestURI = &path;
1931 } else {
1932 requestURI = &mSpec;
1933 }
1934
1935 // trim off the #ref portion if any...
1936 int32_t ref2 = requestURI->FindChar('#');
1937 if (ref2 != kNotFound) {
1938 requestURI->SetLength(ref2);
1939 }
1940
1941 mRequestHead.SetVersion(gHttpHandler->ProxyHttpVersion());
1942 }
1943
1944 mRequestHead.SetRequestURI(*requestURI);
1945
1946 // set the request time for cache expiration calculations
1947 mRequestTime = NowInSeconds()PRTimeToSeconds(PR_Now());
1948 StoreRequestTimeInitialized(true);
1949
1950 // if doing a reload, force end-to-end
1951 if (mLoadFlags & LOAD_BYPASS_CACHE) {
1952 // We need to send 'Pragma:no-cache' to inhibit proxy caching even if
1953 // no proxy is configured since we might be talking with a transparent
1954 // proxy, i.e. one that operates at the network level. See bug #14772.
1955 // But we should not touch Pragma if Cache-Control is already set
1956 // (https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A3)
1957 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1958 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
1959 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"
, 1959); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1959); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1960 }
1961 // If we're configured to speak HTTP/1.1 then also send 'Cache-control:
1962 // no-cache'. But likewise don't touch Cache-Control if it's already set.
1963 if (mRequestHead.Version() >= HttpVersion::v1_1 &&
1964 !mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1965 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "no-cache", true);
1966 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"
, 1966); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1966); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1967 }
1968 } else if (mLoadFlags & VALIDATE_ALWAYS) {
1969 // We need to send 'Cache-Control: max-age=0' to force each cache along
1970 // the path to the origin server to revalidate its own entry, if any,
1971 // with the next cache or server. See bug #84847.
1972 //
1973 // If we're configured to speak HTTP/1.0 then just send 'Pragma: no-cache'
1974 //
1975 // But don't send the headers if they're already set:
1976 // https://fetch.spec.whatwg.org/#ref-for-concept-request-cache-mode%E2%91%A2
1977 if (mRequestHead.Version() >= HttpVersion::v1_1) {
1978 if (!mRequestHead.HasHeader(nsHttp::Cache_Control)) {
1979 rv = mRequestHead.SetHeaderOnce(nsHttp::Cache_Control, "max-age=0",
1980 true);
1981 }
1982 } else {
1983 if (!mRequestHead.HasHeader(nsHttp::Pragma)) {
1984 rv = mRequestHead.SetHeaderOnce(nsHttp::Pragma, "no-cache", true);
1985 }
1986 }
1987 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"
, 1987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1987); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1988 }
1989
1990 if (LoadResuming()) {
1991 char byteRange[32];
1992 SprintfLiteral(byteRange, "bytes=%" PRIu64"l" "u" "-", mStartPos);
1993 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(byteRange));
1994 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"
, 1994); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 1994); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1995
1996 if (!mEntityID.IsEmpty()) {
1997 // Also, we want an error if this resource changed in the meantime
1998 // Format of the entity id is: escaped_etag/size/lastmod
1999 nsCString::const_iterator start, end, slash;
2000 mEntityID.BeginReading(start);
2001 mEntityID.EndReading(end);
2002 mEntityID.BeginReading(slash);
2003
2004 if (FindCharInReadable('/', slash, end)) {
2005 nsAutoCString ifMatch;
2006 rv = mRequestHead.SetHeader(
2007 nsHttp::If_Match,
2008 NS_UnescapeURL(Substring(start, slash), 0, ifMatch));
2009 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"
, 2009); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2009); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2010
2011 ++slash; // Incrementing, so that searching for '/' won't find
2012 // the same slash again
2013 }
2014
2015 if (FindCharInReadable('/', slash, end)) {
2016 rv = mRequestHead.SetHeader(nsHttp::If_Unmodified_Since,
2017 Substring(++slash, end));
2018 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"
, 2018); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2018); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2019 }
2020 }
2021 }
2022
2023 // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer.
2024 if (mLoadFlags & LOAD_ANONYMOUS) mCaps |= NS_HTTP_LOAD_ANONYMOUS(1 << 4);
2025
2026 if (mUpgradeProtocolCallback) {
2027 rv = mRequestHead.SetHeader(nsHttp::Upgrade, mUpgradeProtocol, false);
2028 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"
, 2028); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2028); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2029 rv = mRequestHead.SetHeaderOnce(nsHttp::Connection, nsHttp::Upgrade.get(),
2030 false);
2031 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"
, 2031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 2031); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2032 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
2033 mCaps &= ~NS_HTTP_ALLOW_KEEPALIVE(1 << 0);
2034 }
2035
2036 if (mWebTransportSessionEventListener) {
2037 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
2038 }
2039
2040 return NS_OK;
2041}
2042
2043// Updates mLNAPermission members based on existing permission and tracking
2044// flags in load info
2045LNAPermission nsHttpChannel::UpdateLocalNetworkAccessPermissions(
2046 const nsACString& aPermissionType) {
2047 // We should arrive at this point after LNA has been detected at the
2048 // transaction layer and has errored
2049
2050 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", 2051
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
")"); do { MOZ_CrashSequence(__null, 2051); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2051 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", 2051
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY || aPermissionType == LOCAL_NETWORK_PERMISSION_KEY"
")"); do { MOZ_CrashSequence(__null, 2051); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2052 LNAPermission userPerms = aPermissionType == LOOPBACK_NETWORK_PERMISSION_KEY
2053 ? mLNAPermission.mLocalHostPermission
2054 : mLNAPermission.mLocalNetworkPermission;
2055
2056 if (NS_WARN_IF(userPerms != LNAPermission::Pending)NS_warn_if_impl(userPerms != LNAPermission::Pending, "userPerms != LNAPermission::Pending"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2056
)
) {
2057 // Unexpected condition, we should not hit this case
2058 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"
, 2060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2060); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2059 "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"
, 2060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2060); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
2060 "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"
, 2060); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"UpdateLocalNetworkAccessPermissions called with non-pending "
"permission" ")"); do { MOZ_CrashSequence(__null, 2060); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
2061 return userPerms;
2062 }
2063
2064 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"
, 2064); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo->TriggeringPrincipal()"
") (" "need triggering principal" ")"); do { MOZ_CrashSequence
(__null, 2064); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2065
2066 // Skip LNA checks if the triggering principal and target are same origin.
2067 // Note: This could be a case where there is a network change or device
2068 // migration to a private or corporate network.
2069 //
2070 // This only holds when we connect directly to the origin's own endpoint. If
2071 // the connection was rerouted via Alt-Svc to a different host/port, a
2072 // same-origin URL no longer implies we are talking to the origin itself: a
2073 // public origin could steer same-origin traffic to an attacker-selected
2074 // private address. Don't grant the exemption in that case.
2075 bool reroutedElsewhere =
2076 mConnectionInfo && !mConnectionInfo->GetRoutedHost().IsEmpty() &&
2077 (!mConnectionInfo->GetRoutedHost().Equals(mConnectionInfo->GetOrigin()) ||
2078 mConnectionInfo->RoutedPort() != mConnectionInfo->OriginPort());
2079 // This exemption (same origin) should apply only to secure contexts.
2080 const bool triggeringPrincipalIsPotentiallyTrustworthy =
2081 mLoadInfo->TriggeringPrincipal()->GetIsOriginPotentiallyTrustworthy();
2082 bool isSameOrigin = false;
2083 nsresult rv =
2084 mLoadInfo->TriggeringPrincipal()->IsSameOrigin(mURI, &isSameOrigin);
2085 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && isSameOrigin && !reroutedElsewhere &&
2086 triggeringPrincipalIsPotentiallyTrustworthy) {
2087 userPerms = LNAPermission::Granted;
2088 return userPerms;
2089 }
2090
2091 // Skip LNA checks if captive portal is active
2092 nsCOMPtr<nsICaptivePortalService> cps = CaptivePortalService::GetSingleton();
2093 if (cps) {
2094 int32_t state = cps->State();
2095 if (state == nsICaptivePortalService::LOCKED_PORTAL &&
2096 aPermissionType == LOCAL_NETWORK_PERMISSION_KEY) {
2097 userPerms = LNAPermission::Granted;
2098 return userPerms;
2099 }
2100 }
2101
2102 // Step 1. Check for Existing Allow or Deny permission
2103 if (nsContentUtils::IsExactSitePermAllow(mLoadInfo->TriggeringPrincipal(),
2104 aPermissionType)) {
2105 userPerms = LNAPermission::Granted;
2106 return userPerms;
2107 }
2108
2109 if (nsContentUtils::IsExactSitePermDeny(mLoadInfo->TriggeringPrincipal(),
2110 aPermissionType)) {
2111 userPerms = LNAPermission::Denied;
2112 return userPerms;
2113 }
2114
2115 // Step 2.If this is from third Party Tracker, just block
2116 uint32_t flags = 0;
2117 using CF = nsIClassifiedChannel::ClassificationFlags;
2118 if (StaticPrefs::network_lna_block_trackers() &&
2119 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
2120 mLoadInfo->GetTriggeringThirdPartyClassificationFlags(&flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
&&
2121 (flags & (CF::CLASSIFIED_ANY_BASIC_TRACKING |
2122 CF::CLASSIFIED_ANY_SOCIAL_TRACKING)) != 0) {
2123 userPerms = LNAPermission::Denied;
2124 return userPerms;
2125 }
2126
2127 // Check if we should block LNA requests from insecure contexts
2128 if (StaticPrefs::network_lna_block_insecure_contexts() &&
2129 !triggeringPrincipalIsPotentiallyTrustworthy) {
2130 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)
2131 ("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)
2132 "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)
2133 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
2134 userPerms = LNAPermission::Denied;
2135 return userPerms;
2136 }
2137
2138 // Step 3
2139 // could not determine the permission, lets prompt user
2140 // for permission if lna blocking is enabled
2141 if (StaticPrefs::network_lna_blocking()) {
2142 return userPerms;
2143 }
2144
2145 // we dont have reasons to block the request so we allow this LNA request
2146 // Ideally we should not hit this case once the feature is fully shipped
2147 userPerms = LNAPermission::Granted;
2148 return userPerms;
2149}
2150
2151nsresult nsHttpChannel::InitTransaction() {
2152 nsresult rv;
2153 // create wrapper for this channel's notification callbacks
2154 nsCOMPtr<nsIInterfaceRequestor> callbacks;
2155 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
2156 getter_AddRefs(callbacks));
2157
2158 // create the transaction object
2159 if (nsIOService::UseSocketProcess()) {
2160 if (NS_WARN_IF(!gIOService->SocketProcessReady())NS_warn_if_impl(!gIOService->SocketProcessReady(), "!gIOService->SocketProcessReady()"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2160
)
) {
2161 return NS_ERROR_NOT_AVAILABLE;
2162 }
2163 RefPtr<SocketProcessParent> socketProcess =
2164 SocketProcessParent::GetSingleton();
2165 if (!socketProcess->CanSend()) {
2166 return NS_ERROR_NOT_AVAILABLE;
2167 }
2168
2169 nsCOMPtr<nsIParentChannel> parentChannel;
2170 NS_QueryNotificationCallbacks(this, parentChannel);
2171 RefPtr<DocumentLoadListener> documentChannelParent =
2172 do_QueryObject(parentChannel);
2173 // See HttpTransactionChild::CanSendODAToContentProcessDirectly() and
2174 // nsHttpChannel::CallOnStartRequest() for the reason why we need to know if
2175 // this is a document load. We only send ODA directly to child process for
2176 // non document loads.
2177 RefPtr<HttpTransactionParent> transParent =
2178 new HttpTransactionParent(!!documentChannelParent);
2179 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)
2180 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)
;
2181
2182 // Since OnStopRequest could be sent to child process from socket process
2183 // directly, we need to store these two values in HttpTransactionChild and
2184 // forward to child process until HttpTransactionChild::OnStopRequest is
2185 // called.
2186 transParent->SetRedirectTimestamp(mRedirectStartTimeStamp,
2187 mRedirectEndTimeStamp);
2188
2189 if (socketProcess) {
2190 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", 2191
); AnnotateMozCrashReason("MOZ_CRASH(" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")"); do { MOZ_CrashSequence(__null, 2191); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
2191 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", 2191
); AnnotateMozCrashReason("MOZ_CRASH(" "socketProcess->SendPHttpTransactionConstructor(transParent)"
")"); do { MOZ_CrashSequence(__null, 2191); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2192 }
2193 mTransaction = transParent;
2194 } else {
2195 mTransaction = new nsHttpTransaction();
2196 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)
2197 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)
;
2198 }
2199
2200 // Save the mapping of channel id and the channel. We need this mapping for
2201 // nsIHttpActivityObserver.
2202 gHttpHandler->AddHttpChannel(mChannelId, ToSupports(this));
2203
2204 EnsureBrowserId();
2205 EnsureRequestContext();
2206
2207 HttpTrafficCategory category = CreateTrafficCategory();
2208 mTransaction->SetIsForWebTransport(!!mWebTransportSessionEventListener);
2209
2210 RefPtr<mozilla::dom::BrowsingContext> bc;
2211 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
2212
2213 nsILoadInfo::IPAddressSpace parentAddressSpace =
2214 mozilla::net::GetParentIPAddressSpace(mLoadInfo);
2215
2216 // Check if this is a top-level navigation load and grant LNA permissions
2217 // to skip local network access verification for navigational loads
2218 if (mLoadInfo && StaticPrefs::network_lna_allow_top_level_navigation()) {
2219 ExtContentPolicyType contentPolicyType =
2220 mLoadInfo->GetExternalContentPolicyType();
2221 if (contentPolicyType == ExtContentPolicy::TYPE_DOCUMENT) {
2222 // Grant permissions for top-level navigation loads
2223 mLNAPermission.mLocalHostPermission = LNAPermission::Granted;
2224 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
2225 }
2226 }
2227
2228 // Grant LNA permissions for captive portal tabs to allow them to access
2229 // local network resources without prompting the user
2230 if (bc && bc->GetIsCaptivePortalTab()) {
2231 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
2232 }
2233
2234 rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead, mUploadStream,
2235 mReqContentLength, GetCurrentSerialEventTarget(),
2236 callbacks, this, mBrowserId, category,
2237 mRequestContext, mClassOfService, mInitialRwin,
2238 LoadResponseTimeoutEnabled(), mChannelId, nullptr,
2239 parentAddressSpace, mLNAPermission);
2240 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2241 mTransaction = nullptr;
2242 return rv;
2243 }
2244
2245 return rv;
2246}
2247
2248HttpTrafficCategory nsHttpChannel::CreateTrafficCategory() {
2249 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", 2250
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 2250); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2250 !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", 2250
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mFirstPartyClassificationFlags || !mThirdPartyClassificationFlags"
")"); do { MOZ_CrashSequence(__null, 2250); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2251
2252 if (!StaticPrefs::network_traffic_analyzer_enabled()) {
2253 return HttpTrafficCategory::eInvalid;
2254 }
2255
2256 HttpTrafficAnalyzer::ClassOfService cos;
2257 {
2258 if ((mClassOfService.Flags() & nsIClassOfService::Leader) &&
2259 mLoadInfo->GetExternalContentPolicyType() ==
2260 ExtContentPolicy::TYPE_SCRIPT) {
2261 cos = HttpTrafficAnalyzer::ClassOfService::eLeader;
2262 } else if (mLoadFlags & nsIRequest::LOAD_BACKGROUND) {
2263 cos = HttpTrafficAnalyzer::ClassOfService::eBackground;
2264 } else {
2265 cos = HttpTrafficAnalyzer::ClassOfService::eOther;
2266 }
2267 }
2268
2269 bool isThirdParty = AntiTrackingUtils::IsThirdPartyChannel(this);
2270
2271 HttpTrafficAnalyzer::TrackingClassification tc;
2272 {
2273 uint32_t flags = isThirdParty ? mThirdPartyClassificationFlags
2274 : mFirstPartyClassificationFlags;
2275
2276 using CF = nsIClassifiedChannel::ClassificationFlags;
2277 using TC = HttpTrafficAnalyzer::TrackingClassification;
2278
2279 if (flags & CF::CLASSIFIED_TRACKING_CONTENT) {
2280 tc = TC::eContent;
2281 } else if (flags & CF::CLASSIFIED_FINGERPRINTING_CONTENT) {
2282 tc = TC::eFingerprinting;
2283 } else if (flags & CF::CLASSIFIED_ANY_BASIC_TRACKING) {
2284 tc = TC::eBasic;
2285 } else {
2286 tc = TC::eNone;
2287 }
2288 }
2289
2290 bool isSystemPrincipal =
2291 mLoadInfo->GetLoadingPrincipal() &&
2292 mLoadInfo->GetLoadingPrincipal()->IsSystemPrincipal();
2293 return HttpTrafficAnalyzer::CreateTrafficCategory(
2294 NS_UsePrivateBrowsing(this), isSystemPrincipal, isThirdParty, cos, tc);
2295}
2296
2297void nsHttpChannel::SetCachedContentType() {
2298 if (!mResponseHead) {
2299 return;
2300 }
2301
2302 nsAutoCString contentTypeStr;
2303 mResponseHead->ContentType(contentTypeStr);
2304
2305 uint8_t contentType = nsICacheEntry::CONTENT_TYPE_OTHER;
2306 if (nsContentUtils::IsJavascriptMIMEType(
2307 NS_ConvertUTF8toUTF16(contentTypeStr))) {
2308 contentType = nsICacheEntry::CONTENT_TYPE_JAVASCRIPT;
2309 } else if (StringBeginsWith(contentTypeStr, "text/css"_ns) ||
2310 (mLoadInfo->GetExternalContentPolicyType() ==
2311 ExtContentPolicy::TYPE_STYLESHEET)) {
2312 contentType = nsICacheEntry::CONTENT_TYPE_STYLESHEET;
2313 } else if (StringBeginsWith(contentTypeStr, "application/wasm"_ns)) {
2314 contentType = nsICacheEntry::CONTENT_TYPE_WASM;
2315 } else if (StringBeginsWith(contentTypeStr, "image/"_ns)) {
2316 contentType = nsICacheEntry::CONTENT_TYPE_IMAGE;
2317 } else if (StringBeginsWith(contentTypeStr, "video/"_ns)) {
2318 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
2319 } else if (StringBeginsWith(contentTypeStr, "audio/"_ns)) {
2320 contentType = nsICacheEntry::CONTENT_TYPE_MEDIA;
2321 }
2322
2323 mCacheEntry->SetContentType(contentType);
2324}
2325
2326static bool ShouldSniffMisconfiguredType(nsHttpResponseHead* aResponseHead,
2327 nsILoadInfo* aLoadInfo) {
2328 if (!StaticPrefs::network_mimesniff_sniff_misconfigured_types()) {
2329 return false;
2330 }
2331
2332 // Only sniff document navigations, not subresources.
2333 // https://mimesniff.spec.whatwg.org/#sniffing-a-mislabeled-binary-resource
2334 auto type = aLoadInfo->GetExternalContentPolicyType();
2335 if (type != ExtContentPolicyType::TYPE_DOCUMENT &&
2336 type != ExtContentPolicyType::TYPE_SUBDOCUMENT) {
2337 return false;
2338 }
2339
2340 // Responses marked as attachments are already going to be downloaded
2341 // regardless of their content type, so there is no need to sniff them.
2342 nsAutoCString contentDisposition;
2343 if (NS_SUCCEEDED(aResponseHead->GetHeader(nsHttp::Content_Disposition,((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Content_Disposition, contentDisposition))),
1)))
2344 contentDisposition))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Content_Disposition, contentDisposition))),
1)))
&&
2345 !contentDisposition.IsEmpty() &&
2346 NS_GetContentDispositionFromHeader(contentDisposition) ==
2347 nsIChannel::DISPOSITION_ATTACHMENT) {
2348 return false;
2349 }
2350
2351 nsAutoCString contentTypeOptionsHeader;
2352 if (aResponseHead->GetContentTypeOptionsHeader(contentTypeOptionsHeader) &&
2353 contentTypeOptionsHeader.EqualsIgnoreCase("nosniff")) {
2354 return false;
2355 }
2356
2357 nsAutoCString contentType;
2358 aResponseHead->ContentType(contentType);
2359
2360 if (contentType.EqualsLiteral("text/plain")) {
2361 return true;
2362 }
2363
2364 if (contentType.EqualsLiteral(UNKNOWN_CONTENT_TYPE"application/x-unknown-content-type") ||
2365 contentType.IsEmpty()) {
2366 return true;
2367 }
2368
2369 return false;
2370}
2371
2372nsresult nsHttpChannel::CallOnStartRequest() {
2373 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)
;
2374
2375 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"
, 2377); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2377
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2376 "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"
, 2377); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2377
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
2377 "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"
, 2377); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!LoadRequireCORSPreflight() || LoadIsCorsPreflightDone()"
") (" "CORS preflight must have been finished by the time we "
"call OnStartRequest" ")"); do { MOZ_CrashSequence(__null, 2377
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
2378
2379 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"
, 2381); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2381); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
2380 "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"
, 2381); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2381); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
2381 "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"
, 2381); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mCanceled || LoadProcessCrossOriginSecurityHeadersCalled()"
") (" "Security headers need to have been processed before "
"calling CallOnStartRequest" ")"); do { MOZ_CrashSequence(__null
, 2381); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
2382
2383 mEarlyHintObserver = nullptr;
2384
2385 if (StaticPrefs::network_http_network_error_logging_enabled() &&
2386 mResponseHead && mResponseHead->HasHeader(nsHttp::NEL) &&
2387 LoadUsedNetwork()) {
2388 // If the policy gets cleared, but this response is still in the cache,
2389 // we probably don't want to reinstall the policy when the entry is
2390 // reloaded. That means it's important to only call RegisterPolicy when
2391 // LoadUsedNetwork() is true.
2392 if (nsCOMPtr<nsINetworkErrorLogging> nel =
2393 components::NetworkErrorLogging::Service()) {
2394 nel->RegisterPolicy(this);
2395 }
2396 }
2397
2398 if (LoadOnStartRequestCalled()) {
2399 // This can only happen when a range request loading rest of the data
2400 // after interrupted concurrent cache read asynchronously failed, e.g.
2401 // the response range bytes are not as expected or this channel has
2402 // been externally canceled.
2403 //
2404 // It's legal to bypass CallOnStartRequest for that case since we've
2405 // already called OnStartRequest on our listener and also added all
2406 // content converters before.
2407 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", 2407
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { MOZ_CrashSequence(__null, 2407); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2408 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)
;
2409 return mStatus;
2410 }
2411
2412 // Ensure mListener->OnStartRequest will be invoked before exiting
2413 // this function.
2414 auto onStartGuard = MakeScopeExit([&] {
2415 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)
2416 (" 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)
2417 "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)
2418 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)
;
2419 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", 2419
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 2419); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2420
2421 if (mListener) {
2422 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
2423 StoreOnStartRequestCalled(true);
2424 deleteProtector->OnStartRequest(this);
2425 }
2426 StoreOnStartRequestCalled(true);
2427 });
2428
2429 nsresult rv = ValidateMIMEType();
2430 // Since ODA and OnStopRequest could be sent from socket process directly, we
2431 // need to update the channel status before calling mListener->OnStartRequest.
2432 // This is the only way to let child process discard the already received ODA
2433 // messages.
2434 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2435 mStatus = rv;
2436 return mStatus;
2437 }
2438
2439 // EnsureOpaqueResponseIsAllowed and EnsureOpauqeResponseIsAllowedAfterSniff
2440 // are the checks for Opaque Response Blocking to ensure that we block as many
2441 // cross-origin responses with CORS headers as possible that are not either
2442 // Javascript or media to avoid leaking their contents through side channels.
2443 OpaqueResponse opaqueResponse =
2444 PerformOpaqueResponseSafelistCheckBeforeSniff();
2445 if (opaqueResponse == OpaqueResponse::Block) {
2446 SetChannelBlockedByOpaqueResponse();
2447 CancelWithReason(NS_ERROR_DOM_NETWORK_ERR,
2448 "OpaqueResponseBlocker::BlockResponse"_ns);
2449 return NS_BINDING_ABORTED;
2450 }
2451
2452 // We must ensure that any dcb/dcz content is decompressed in the parent
2453 // process, and removed from the Content-Encoding before it's sent down
2454 // to the content process. In most (all?) cases, this should have occurred
2455 // before this.
2456 if (mResponseHead && XRE_IsParentProcess() && !LoadHasAppliedConversion()) {
2457 nsAutoCString contentEncoding;
2458 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
2459 // Note: doesn't handle multiple compressors: "dcb, gzip" or
2460 // "gzip, dcb" (etc)
2461 if (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
2462 contentEncoding.LowerCaseEqualsLiteral("dcz")) {
2463 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)
2464 ("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)
2465 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)
;
2466 nsCOMPtr<nsIStreamListener> listener;
2467 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"
, 2467); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "LoadHasAppliedConversion() == false"
")"); do { MOZ_CrashSequence(__null, 2467); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2468 // Insist we install a converter. This should never be the case, but
2469 // if somehow it is, we need a converter; content can't be allowed
2470 // to see dcb/dcz since it can't convert them
2471 StoreHasAppliedConversion(false);
2472 // IMPORTANT: Must use DoApplyContentConversionsInternal with
2473 // aRemoveEncodings=true to clear Content-Encoding header. Otherwise,
2474 // decompressed data will be cached with dcb/dcz in metadata, causing
2475 // corruption on cache reads.
2476 rv = DoApplyContentConversionsInternal(
2477 mListener, getter_AddRefs(listener), true, nullptr);
2478 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2479 return rv;
2480 }
2481 if (listener) {
2482 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"
, 2485); 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, 2485); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2483 "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"
, 2485); 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, 2485); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2484 "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"
, 2485); 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, 2485); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2485 "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"
, 2485); 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, 2485); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2486 mListener = listener;
2487 mCompressListener = listener;
2488
2489 StoreHasAppliedConversion(true);
2490 } else {
2491 // Failed to install decompressor for dcb/dcz - this is a fatal error
2492 // as content cannot handle these encodings
2493 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)
2494 ("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)
2495 "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)
2496 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)
;
2497 return NS_ERROR_INVALID_CONTENT_ENCODING;
2498 }
2499 }
2500 }
2501
2502 // Allow consumers to override our content type
2503 if (mLoadFlags & LOAD_CALL_CONTENT_SNIFFERS) {
2504 // NOTE: We can have both a txn pump and a cache pump when the cache
2505 // content is partial. In that case, we need to read from the cache,
2506 // because that's the one that has the initial contents. If that fails
2507 // then give the transaction pump a shot.
2508
2509 nsIChannel* thisChannel = static_cast<nsIChannel*>(this);
2510
2511 bool typeSniffersCalled = false;
2512 if (mCachePump) {
2513 typeSniffersCalled =
2514 NS_SUCCEEDED(mCachePump->PeekStream(CallTypeSniffers, thisChannel))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mCachePump->PeekStream
(CallTypeSniffers, thisChannel))), 1)))
;
2515 }
2516
2517 if (!typeSniffersCalled && mTransactionPump) {
2518 RefPtr<nsInputStreamPump> pump = do_QueryObject(mTransactionPump);
2519 if (pump) {
2520 pump->PeekStream(CallTypeSniffers, thisChannel);
2521 } else {
2522 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"
, 2522); AnnotateMozCrashReason("MOZ_ASSERT" "(" "nsIOService::UseSocketProcess()"
")"); do { MOZ_CrashSequence(__null, 2522); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2523 RefPtr<HttpTransactionParent> trans = do_QueryObject(mTransactionPump);
2524 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"
, 2524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "trans" ")")
; do { MOZ_CrashSequence(__null, 2524); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2525 trans->SetSniffedTypeToChannel(CallTypeSniffers, thisChannel);
2526 }
2527 }
2528 }
2529
2530 // Note that the code below should be synced with the code in
2531 // HttpTransactionChild::CanSendODAToContentProcessDirectly(). We MUST make
2532 // sure HttpTransactionChild::CanSendODAToContentProcessDirectly() returns
2533 // false when a stream converter is applied.
2534 bool unknownDecoderStarted = false;
2535 bool shouldSniff = false;
2536 if (mResponseHead) {
2537 if (!mResponseHead->HasContentType()) {
2538 shouldSniff = true;
2539 } else {
2540 shouldSniff =
2541 ShouldSniffMisconfiguredType(mResponseHead.get(), mLoadInfo);
2542 }
2543 }
2544 if (shouldSniff) {
2545 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"
, 2545); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo"
") (" "Should have connection info here" ")"); do { MOZ_CrashSequence
(__null, 2545); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2546 if (!mContentTypeHint.IsEmpty()) {
2547 mResponseHead->SetContentType(mContentTypeHint);
2548 } else if (mResponseHead->Version() == HttpVersion::v0_9 &&
2549 mConnectionInfo->OriginPort() !=
2550 mConnectionInfo->DefaultPort()) {
2551 mResponseHead->SetContentType(nsLiteralCString(TEXT_PLAIN"text/plain"));
2552 } else if (!mLoadInfo->GetSkipContentSniffing() ||
2553 opaqueResponse == OpaqueResponse::Sniff) {
2554 // Uh-oh. We had better find out what type we are!
2555 mListener = new nsUnknownDecoder(mListener);
2556 unknownDecoderStarted = true;
2557 }
2558 }
2559
2560 // If unknownDecoder is not going to be launched, call
2561 // EnsureOpaqueResponseIsAllowedAfterSniff immediately.
2562 if (!unknownDecoderStarted) {
2563 if (opaqueResponse == OpaqueResponse::SniffCompressed) {
2564 mListener = new nsCompressedAudioVideoImageDetector(
2565 mListener, &HttpBaseChannel::CallTypeSniffers);
2566 } else if (opaqueResponse == OpaqueResponse::Sniff) {
2567 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"
, 2567); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mORB"
")"); do { MOZ_CrashSequence(__null, 2567); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2568 RefPtr<OpaqueResponseBlocker> orb(mORB);
2569 nsresult rv = orb->EnsureOpaqueResponseIsAllowedAfterSniff(this);
2570
2571 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2572 return rv;
2573 }
2574 }
2575 }
2576
2577 // If the content is multipart/x-mixed-replace, we'll insert a MIME decoder
2578 // in the pipeline to handle the content and pass it along to our
2579 // original listener. nsUnknownDecoder doesn't support detecting this type,
2580 // so we only need to insert this using the response header's mime type.
2581 //
2582 // We only do this for unwrapped document loads, since we might want to send
2583 // parts to the external protocol handler without leaving the parent process.
2584 bool mustRunStreamFilterInParent = false;
2585 nsCOMPtr<nsIParentChannel> parentChannel;
2586 NS_QueryNotificationCallbacks(this, parentChannel);
2587 RefPtr<DocumentLoadListener> docListener = do_QueryObject(parentChannel);
2588 if (mResponseHead && docListener && docListener->GetChannel() == this) {
2589 nsAutoCString contentType;
2590 mResponseHead->ContentType(contentType);
2591
2592 if (contentType.Equals("multipart/x-mixed-replace"_ns)) {
2593 nsCOMPtr<nsIStreamConverterService> convServ(
2594 mozilla::components::StreamConverter::Service(&rv));
2595 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2596 nsCOMPtr<nsIStreamListener> toListener(mListener);
2597 nsCOMPtr<nsIStreamListener> fromListener;
2598
2599 rv = convServ->AsyncConvertData("multipart/x-mixed-replace", "*/*",
2600 toListener, nullptr,
2601 getter_AddRefs(fromListener));
2602 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
2603 mListener = fromListener;
2604 mustRunStreamFilterInParent = true;
2605 }
2606 }
2607 }
2608 }
2609
2610 // If we installed a multipart converter, then we need to add StreamFilter
2611 // object before it, so that extensions see the un-parsed original stream.
2612 // We may want to add an option for extensions to opt-in to proper multipart
2613 // handling.
2614 // If not, then pass the StreamFilter promise on to DocumentLoadListener,
2615 // where it'll be added in the content process.
2616 for (StreamFilterRequest& request : mStreamFilterRequests) {
2617 if (mustRunStreamFilterInParent) {
2618 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
2619 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
2620 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
2621 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2622 request.mPromise->Reject(false, __func__);
2623 } else {
2624 extensions::StreamFilterParent::Attach(this, std::move(parent));
2625 request.mPromise->Resolve(std::move(child), __func__);
2626 }
2627 } else {
2628 if (docListener) {
2629 docListener->AttachStreamFilter()->ChainTo(request.mPromise.forget(),
2630 __func__);
2631 } else {
2632 request.mPromise->Reject(false, __func__);
2633 }
2634 }
2635 request.mPromise = nullptr;
2636 }
2637 mStreamFilterRequests.Clear();
2638 StoreTracingEnabled(false);
2639
2640 if (mResponseHead && !mResponseHead->HasContentCharset()) {
2641 mResponseHead->SetContentCharset(mContentCharsetHint);
2642 }
2643
2644 if (mCacheEntry && LoadCacheEntryIsWriteOnly()) {
2645 SetCachedContentType();
2646 }
2647
2648 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)
2649 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)
;
2650
2651 // About to call OnStartRequest, dismiss the guard object.
2652 onStartGuard.release();
2653
2654 if (mListener) {
2655 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"
, 2656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { MOZ_CrashSequence
(__null, 2656); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
2656 "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"
, 2656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OsStartRequest twice" ")"); do { MOZ_CrashSequence
(__null, 2656); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2657 nsCOMPtr<nsIStreamListener> deleteProtector(mListener);
2658 StoreOnStartRequestCalled(true);
2659 rv = deleteProtector->OnStartRequest(this);
2660 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2661 } else {
2662 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"
, 2662)
;
2663 StoreOnStartRequestCalled(true);
2664 }
2665
2666 // Install stream converter if required.
2667 // Normally, we expect the listener to disable content conversion during
2668 // OnStartRequest if it wants to handle it itself (which is common case with
2669 // HttpChannelParent, disabling so that it can be done in the content
2670 // process). If we've installed an nsUnknownDecoder, then we won't yet have
2671 // called OnStartRequest on the final listener (that happens after we send
2672 // OnDataAvailable to the nsUnknownDecoder), so it can't yet have disabled
2673 // content conversion.
2674 // In that case, assume that the listener will disable content conversion,
2675 // unless it's specifically told us that it won't.
2676 if (!unknownDecoderStarted || LoadListenerRequiresContentConversion()) {
2677 nsCOMPtr<nsIStreamListener> listener;
2678 rv =
2679 DoApplyContentConversions(mListener, getter_AddRefs(listener), nullptr);
2680 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2681 return rv;
2682 }
2683 if (listener) {
2684 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"
, 2687); 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, 2687); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2685 "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"
, 2687); 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, 2687); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2686 "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"
, 2687); 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, 2687); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2687 "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"
, 2687); 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, 2687); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2688 mListener = listener;
2689 mCompressListener = std::move(listener);
2690
2691 StoreHasAppliedConversion(true);
2692 }
2693 }
2694
2695 // if this channel is for a download, close off access to the cache.
2696 if (mCacheEntry && LoadChannelIsForDownload()) {
2697 mCacheEntry->AsyncDoom(nullptr);
2698
2699 // We must keep the cache entry in case of partial request.
2700 // Concurrent access is the same, we need the entry in
2701 // OnStopRequest.
2702 if (!LoadCachedContentIsPartial() && !LoadConcurrentCacheAccess()) {
2703 CloseCacheEntry(false);
2704 }
2705 }
2706
2707 return NS_OK;
2708}
2709
2710NS_IMETHODIMPnsresult nsHttpChannel::GetHttpProxyConnectResponseCode(
2711 int32_t* aResponseCode) {
2712 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"
, 2712); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2713 if (mProxyConnectResponseHead) {
2714 *aResponseCode = mProxyConnectResponseHead->Head().Status();
2715 } else if (mConnectionInfo && mConnectionInfo->UsingConnect()) {
2716 *aResponseCode = 0;
2717 } else {
2718 *aResponseCode = -1;
2719 }
2720 return NS_OK;
2721}
2722
2723NS_IMETHODIMPnsresult nsHttpChannel::GetHttpProxyResponseHeader(
2724 const nsACString& aHeader, nsACString& aValue) {
2725 if (mProxyConnectResponseHead) {
2726 return mProxyConnectResponseHead->Head().GetHeader(
2727 nsHttp::ResolveAtom(aHeader), aValue);
2728 }
2729 return NS_ERROR_NOT_AVAILABLE;
2730}
2731
2732nsresult nsHttpChannel::ProcessFailedProxyConnect(uint32_t httpStatus) {
2733 // Failure to set up a proxy tunnel via CONNECT means one of the following:
2734 // 1) Proxy wants authorization, or forbids.
2735 // 2) DNS at proxy couldn't resolve target URL.
2736 // 3) Proxy connection to target failed or timed out.
2737 // 4) Eve intercepted our CONNECT, and is replying with malicious HTML.
2738 //
2739 // Our current architecture would parse the proxy's response content with
2740 // the permission of the target URL. Given #4, we must avoid rendering the
2741 // body of the reply, and instead give the user a (hopefully helpful)
2742 // boilerplate error page, based on just the HTTP status of the reply.
2743
2744 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"
, 2745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ MOZ_CrashSequence(__null, 2745); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
2745 "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"
, 2745); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo->UsingConnect()"
") (" "proxy connect failed but not using CONNECT?" ")"); do
{ MOZ_CrashSequence(__null, 2745); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
2746 nsresult rv = HttpProxyResponseToErrorCode(httpStatus);
2747 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)
2748 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)
;
2749
2750 // Make sure the connection is thrown away as it can be in a bad state
2751 // and the proxy may just hang on the next request.
2752 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"
, 2752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { MOZ_CrashSequence(__null, 2752); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2753 mTransaction->DontReuseConnection();
2754
2755 Cancel(rv);
2756 {
2757 nsresult rv = CallOnStartRequest();
2758 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2759 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)
2760 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)
;
2761 }
2762 }
2763 return rv;
2764}
2765
2766static void GetSTSConsoleErrorTag(uint32_t failureResult,
2767 nsAString& consoleErrorTag) {
2768 switch (failureResult) {
2769 case nsISiteSecurityService::ERROR_COULD_NOT_PARSE_HEADER:
2770 consoleErrorTag = u"STSCouldNotParseHeader"_ns;
2771 break;
2772 case nsISiteSecurityService::ERROR_NO_MAX_AGE:
2773 consoleErrorTag = u"STSNoMaxAge"_ns;
2774 break;
2775 case nsISiteSecurityService::ERROR_MULTIPLE_MAX_AGES:
2776 consoleErrorTag = u"STSMultipleMaxAges"_ns;
2777 break;
2778 case nsISiteSecurityService::ERROR_INVALID_MAX_AGE:
2779 consoleErrorTag = u"STSInvalidMaxAge"_ns;
2780 break;
2781 case nsISiteSecurityService::ERROR_MULTIPLE_INCLUDE_SUBDOMAINS:
2782 consoleErrorTag = u"STSMultipleIncludeSubdomains"_ns;
2783 break;
2784 case nsISiteSecurityService::ERROR_INVALID_INCLUDE_SUBDOMAINS:
2785 consoleErrorTag = u"STSInvalidIncludeSubdomains"_ns;
2786 break;
2787 case nsISiteSecurityService::ERROR_COULD_NOT_SAVE_STATE:
2788 consoleErrorTag = u"STSCouldNotSaveState"_ns;
2789 break;
2790 default:
2791 consoleErrorTag = u"STSUnknownError"_ns;
2792 break;
2793 }
2794}
2795
2796/**
2797 * Process an HTTP Strict Transport Security (HSTS) header.
2798 */
2799nsresult nsHttpChannel::ProcessHSTSHeader(nsITransportSecurityInfo* aSecInfo) {
2800 nsHttpAtom atom(nsHttp::ResolveAtom("Strict-Transport-Security"_ns));
2801
2802 nsAutoCString securityHeader;
2803 nsresult rv = mResponseHead->GetHeader(atom, securityHeader);
2804 if (rv == NS_ERROR_NOT_AVAILABLE) {
2805 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)
;
2806 return NS_OK;
2807 }
2808 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"
, 2808)
) {
2809 return rv;
2810 }
2811
2812 if (!aSecInfo) {
2813 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)
;
2814 return NS_ERROR_INVALID_ARG;
2815 }
2816 nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
2817 rv = aSecInfo->GetOverridableErrorCategory(&overridableErrorCategory);
2818 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"
, 2818)
) {
2819 return rv;
2820 }
2821 if (overridableErrorCategory !=
2822 nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
2823 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)
2824 ("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)
2825 "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)
;
2826 return NS_ERROR_FAILURE;
2827 }
2828
2829 nsISiteSecurityService* sss = gHttpHandler->GetSSService();
2830 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"
, 2830); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2831
2832 OriginAttributes originAttributes;
2833 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2834
)
2834 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2834
)
) {
2835 return NS_ERROR_FAILURE;
2836 }
2837
2838 uint32_t failureResult;
2839 rv = sss->ProcessHeader(mURI, securityHeader, originAttributes, nullptr,
2840 nullptr, &failureResult);
2841 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2842 nsAutoString consoleErrorCategory(u"Invalid HSTS Headers"_ns);
2843 nsAutoString consoleErrorTag;
2844 GetSTSConsoleErrorTag(failureResult, consoleErrorTag);
2845 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2846 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)
2847 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)
;
2848 }
2849 return NS_OK;
2850}
2851
2852// https://github.com/rozbb/waict-integrity-draft/
2853nsresult nsHttpChannel::ProcessWAICTHeader() {
2854#ifdef NIGHTLY_BUILD1
2855 if (!StaticPrefs::security_waict_downgrade_protection_enable()) {
2856 return NS_OK;
2857 }
2858
2859 // The WAICT header is only relevant for document loads.
2860 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
2861 if (type != ExtContentPolicy::TYPE_DOCUMENT &&
2862 type != ExtContentPolicy::TYPE_SUBDOCUMENT) {
2863 return NS_OK;
2864 }
2865
2866 nsISiteIntegrityService* integrityService =
2867 gHttpHandler->GetSiteIntegrityService();
2868 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"
, 2868); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2869
2870 // Unlike HSTS, WAICT is supported for HTTP as well, so we need to use the
2871 // correct helper.
2872 OriginAttributes originAttributes;
2873 if (mURI->SchemeIs("https")) {
2874 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2875
)
2875 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHTTPSRR( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2875
)
) {
2876 return NS_ERROR_FAILURE;
2877 }
2878 } else {
2879 if (NS_WARN_IF(!StoragePrincipalHelper::GetOriginAttributesForHSTS(NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2880
)
2880 this, originAttributes))NS_warn_if_impl(!StoragePrincipalHelper::GetOriginAttributesForHSTS
( this, originAttributes), "!StoragePrincipalHelper::GetOriginAttributesForHSTS( this, originAttributes)"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 2880
)
) {
2881 return NS_ERROR_FAILURE;
2882 }
2883 }
2884
2885 nsAutoCString headerValue;
2886 nsresult rv =
2887 mResponseHead->GetHeader(nsHttp::Integrity_Policy_WAICT, headerValue);
2888 if (rv == NS_ERROR_NOT_AVAILABLE || headerValue.IsEmpty()) {
2889 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)
2890 ("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)
2891 "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)
;
2892
2893 bool isProtected = false;
2894 rv = integrityService->IsProtectedURI(mURI, originAttributes, &isProtected);
2895 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2896 return rv;
2897 }
2898
2899 if (isProtected) {
2900 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)
2901 ("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)
2902 "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)
;
2903 Cancel(NS_ERROR_CORRUPTED_CONTENT);
2904 DoNotifyListener();
2905 return NS_ERROR_CORRUPTED_CONTENT;
2906 }
2907
2908 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)
;
2909 return NS_OK;
2910 }
2911 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"
, 2911)
) {
2912 return rv;
2913 }
2914#endif
2915
2916 return NS_OK;
2917}
2918
2919/**
2920 * Decide whether or not to remember Strict-Transport-Security, and whether
2921 * or not to enforce channel integrity.
2922 *
2923 * @return NS_ERROR_FAILURE if there's security information missing even though
2924 * it's an HTTPS connection.
2925 */
2926nsresult nsHttpChannel::ProcessSecurityHeaders() {
2927 // If this channel is not loading securely, STS or PKP doesn't do anything.
2928 // In the case of HSTS, the upgrade to HTTPS takes place earlier in the
2929 // channel load process.
2930 if (!mURI->SchemeIs("https")) {
2931 return NS_OK;
2932 }
2933
2934 if (IsBrowsingContextDiscarded()) {
2935 return NS_OK;
2936 }
2937
2938 nsAutoCString asciiHost;
2939 nsresult rv = mURI->GetAsciiHost(asciiHost);
2940 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"
, 2940); return NS_OK; } } while (false)
;
2941
2942 // If the channel is not a hostname, but rather an IP, do not process STS
2943 // or PKP headers
2944 if (HostIsIPLiteral(asciiHost)) {
2945 return NS_OK;
2946 }
2947
2948 // mSecurityInfo may not always be present, and if it's not then it is okay
2949 // to just disregard any security headers since we know nothing about the
2950 // security of the connection.
2951 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"
, 2951); return NS_OK; } } while (false)
;
2952
2953 // Only process HSTS headers for first-party loads. This prevents a
2954 // proliferation of useless HSTS state for partitioned third parties.
2955 if (!mLoadInfo->GetIsThirdPartyContextToTopWindow()) {
2956 rv = ProcessHSTSHeader(mSecurityInfo);
2957 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"
, 2957); return rv; } } while (false)
;
2958 }
2959
2960 return NS_OK;
2961}
2962
2963bool nsHttpChannel::IsHTTPS() { return mURI->SchemeIs("https"); }
2964
2965void nsHttpChannel::ProcessSSLInformation() {
2966 // If this is HTTPS, record any use of RSA so that Key Exchange Algorithm
2967 // can be whitelisted for TLS False Start in future sessions. We could
2968 // do the same for DH but its rarity doesn't justify the lookup.
2969
2970 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) || !mSecurityInfo || !IsHTTPS() ||
2971 mPrivateBrowsing) {
2972 return;
2973 }
2974
2975 if (!mSecurityInfo) {
2976 return;
2977 }
2978
2979 uint32_t state;
2980 if (NS_SUCCEEDED(mSecurityInfo->GetSecurityState(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mSecurityInfo->
GetSecurityState(&state))), 1)))
&&
2981 (state & nsIWebProgressListener::STATE_IS_BROKEN)) {
2982 // Send weak crypto warnings to the web console
2983 if (state & nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
2984 nsString consoleErrorTag = u"WeakCipherSuiteWarning"_ns;
2985 nsString consoleErrorCategory = u"SSL"_ns;
2986 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2987 }
2988 }
2989
2990 uint16_t tlsVersion;
2991 nsresult rv = mSecurityInfo->GetProtocolVersion(&tlsVersion);
2992 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) &&
2993 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_2 &&
2994 tlsVersion != nsITransportSecurityInfo::TLS_VERSION_1_3) {
2995 nsString consoleErrorTag = u"DeprecatedTLSVersion2"_ns;
2996 nsString consoleErrorCategory = u"TLS"_ns;
2997 (void)AddSecurityMessage(consoleErrorTag, consoleErrorCategory);
2998 }
2999}
3000
3001void nsHttpChannel::ProcessAltService(nsHttpConnectionInfo* aTransConnInfo) {
3002 // e.g. Alt-Svc: h2=":443"; ma=60
3003 // e.g. Alt-Svc: h2="otherhost:443"
3004 // Alt-Svc = 1#( alternative *( OWS ";" OWS parameter ) )
3005 // alternative = protocol-id "=" alt-authority
3006 // protocol-id = token ; percent-encoded ALPN protocol identifier
3007 // alt-authority = quoted-string ; containing [ uri-host ] ":" port
3008
3009 if (!LoadAllowAltSvc()) { // per channel opt out
3010 return;
3011 }
3012
3013 if (mWebTransportSessionEventListener) {
3014 return;
3015 }
3016
3017 if (!gHttpHandler->AllowAltSvc() || (mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7))) {
3018 return;
3019 }
3020
3021 if (IsBrowsingContextDiscarded()) {
3022 return;
3023 }
3024
3025 nsAutoCString scheme;
3026 mURI->GetScheme(scheme);
3027 bool isHttp = scheme.EqualsLiteral("http");
3028 if (!isHttp && !scheme.EqualsLiteral("https")) {
3029 return;
3030 }
3031
3032 nsAutoCString altSvc;
3033 (void)mResponseHead->GetHeader(nsHttp::Alternate_Service, altSvc);
3034 if (altSvc.IsEmpty()) {
3035 return;
3036 }
3037
3038 if (!nsHttp::IsReasonableHeaderValue(altSvc)) {
3039 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)
;
3040 return;
3041 }
3042
3043 nsAutoCString originHost;
3044 int32_t originPort = 80;
3045 mURI->GetPort(&originPort);
3046 if (NS_FAILED(mURI->GetAsciiHost(originHost))((bool)(__builtin_expect(!!(NS_FAILED_impl(mURI->GetAsciiHost
(originHost))), 0)))
) {
3047 return;
3048 }
3049
3050 nsCOMPtr<nsIInterfaceRequestor> callbacks;
3051 nsCOMPtr<nsProxyInfo> proxyInfo;
3052 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
3053 getter_AddRefs(callbacks));
3054
3055 if (mProxyInfo) {
3056 proxyInfo = do_QueryInterface(mProxyInfo);
3057 }
3058
3059 OriginAttributes originAttributes;
3060 // Regular principal in case we have a proxy.
3061 if (proxyInfo &&
3062 !StaticPrefs::privacy_partition_network_state_connection_with_proxy()) {
3063 StoragePrincipalHelper::GetOriginAttributes(
3064 this, originAttributes, StoragePrincipalHelper::eRegularPrincipal);
3065 } else {
3066 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
3067 this, originAttributes);
3068 }
3069
3070 AltSvcMapping::ProcessHeader(altSvc, scheme, originHost, originPort,
3071 mUsername, mPrivateBrowsing, callbacks,
3072 proxyInfo, mCaps & NS_HTTP_DISALLOW_SPDY(1 << 7),
3073 originAttributes, aTransConnInfo);
3074}
3075
3076nsresult nsHttpChannel::ProcessResponse(nsHttpConnectionInfo* aConnInfo) {
3077 uint32_t httpStatus = mResponseHead->Status();
3078
3079 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)
3080 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)
;
3081
3082 // Gather data on whether the transaction and page (if this is
3083 // the initial page load) is being loaded with SSL.
3084 glean::http::transaction_is_ssl
3085 .EnumGet(static_cast<glean::http::TransactionIsSslLabel>(
3086 mConnectionInfo->EndToEndSSL()))
3087 .Add();
3088 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
3089 glean::http::pageload_is_ssl
3090 .EnumGet(static_cast<glean::http::PageloadIsSslLabel>(
3091 mConnectionInfo->EndToEndSSL()))
3092 .Add();
3093 }
3094
3095 if (Telemetry::CanRecordPrereleaseData()) {
3096 // Gather data on various response status to monitor any increased frequency
3097 // of auth failures due to Bug 1896350
3098 switch (httpStatus) {
3099 case 200:
3100 mozilla::glean::networking::http_response_status_code.Get("200_ok"_ns)
3101 .Add(1);
3102 break;
3103 case 301:
3104 mozilla::glean::networking::http_response_status_code
3105 .Get("301_moved_permanently"_ns)
3106 .Add(1);
3107 break;
3108 case 302:
3109 mozilla::glean::networking::http_response_status_code
3110 .Get("302_found"_ns)
3111 .Add(1);
3112 break;
3113 case 304:
3114 mozilla::glean::networking::http_response_status_code
3115 .Get("304_not_modified"_ns)
3116 .Add(1);
3117 break;
3118 case 307:
3119 mozilla::glean::networking::http_response_status_code
3120 .Get("307_temporary_redirect"_ns)
3121 .Add(1);
3122 break;
3123 case 308:
3124 mozilla::glean::networking::http_response_status_code
3125 .Get("308_permanent_redirect"_ns)
3126 .Add(1);
3127 break;
3128 case 400:
3129 mozilla::glean::networking::http_response_status_code
3130 .Get("400_bad_request"_ns)
3131 .Add(1);
3132 break;
3133 case 401:
3134 mozilla::glean::networking::http_response_status_code
3135 .Get("401_unauthorized"_ns)
3136 .Add(1);
3137 break;
3138 case 403:
3139 mozilla::glean::networking::http_response_status_code
3140 .Get("403_forbidden"_ns)
3141 .Add(1);
3142 break;
3143 case 404:
3144 mozilla::glean::networking::http_response_status_code
3145 .Get("404_not_found"_ns)
3146 .Add(1);
3147 break;
3148 case 421:
3149 mozilla::glean::networking::http_response_status_code
3150 .Get("421_misdirected_request"_ns)
3151 .Add(1);
3152 break;
3153 case 425:
3154 mozilla::glean::networking::http_response_status_code
3155 .Get("425_too_early"_ns)
3156 .Add(1);
3157 break;
3158 case 429:
3159 mozilla::glean::networking::http_response_status_code
3160 .Get("429_too_many_requests"_ns)
3161 .Add(1);
3162 break;
3163 case 500:
3164 mozilla::glean::networking::http_response_status_code
3165 .Get("other_5xx"_ns)
3166 .Add(1);
3167 break;
3168 default:
3169 if (httpStatus >= 400 && httpStatus < 500) {
3170 mozilla::glean::networking::http_response_status_code
3171 .Get("other_4xx"_ns)
3172 .Add(1);
3173 } else if (httpStatus > 500) {
3174 mozilla::glean::networking::http_response_status_code
3175 .Get("other_5xx"_ns)
3176 .Add(1);
3177 } else {
3178 mozilla::glean::networking::http_response_status_code.Get("other"_ns)
3179 .Add(1);
3180 }
3181 break;
3182 }
3183 }
3184
3185 // We use GetReferringPage because mReferrerInfo may not be set at all(this is
3186 // especially useful in xpcshell tests, where we don't have an actual pageload
3187 // to get a referrer from).
3188 // Only allow 407 (authentication required) to continue
3189 if (mTransaction && mTransaction->ProxyConnectFailed() && httpStatus != 407) {
3190 return ProcessFailedProxyConnect(httpStatus);
3191 }
3192
3193 ProcessSSLInformation();
3194
3195 // notify "http-on-examine-response" observers
3196 gHttpHandler->OnExamineResponse(this);
3197
3198 MaybeSuspendAfterExamineResponse();
3199
3200 return ContinueProcessResponse1(aConnInfo);
3201}
3202
3203void nsHttpChannel::AsyncContinueProcessResponse(
3204 nsHttpConnectionInfo* aConnInfo) {
3205 nsresult rv;
3206 rv = ContinueProcessResponse1(aConnInfo);
3207 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3208 // A synchronous failure here would normally be passed as the return
3209 // value from OnStartRequest, which would in turn cancel the request.
3210 // If we're continuing asynchronously, we need to cancel the request
3211 // ourselves.
3212 (void)Cancel(rv);
3213 }
3214}
3215
3216nsresult nsHttpChannel::ContinueProcessResponse1(
3217 nsHttpConnectionInfo* aConnInfo) {
3218 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"
, 3218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 3218); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
3219 nsresult rv = NS_OK;
3220
3221 if (mSuspendCount) {
3222 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)
3223 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3224 mCallOnResume = [connInfo = RefPtr{aConnInfo}](nsHttpChannel* self) {
3225 self->AsyncContinueProcessResponse(connInfo);
3226 return NS_OK;
3227 };
3228 return NS_OK;
3229 }
3230
3231 // Check if request was cancelled during http-on-examine-response.
3232 if (mCanceled) {
3233 return CallOnStartRequest();
3234 }
3235
3236 uint32_t httpStatus = mResponseHead->Status();
3237
3238 // STS, Cookies and Alt-Service should not be handled on proxy failure.
3239 // If proxy CONNECT response needs to complete, wait to process connection
3240 // for Strict-Transport-Security.
3241 if (!(mTransaction && mTransaction->ProxyConnectFailed()) &&
3242 (httpStatus != 407)) {
3243 // This block parses the cookie header, collects any cookie changes,
3244 // and sends them to the parent actor.
3245 {
3246 RefPtr<CookieObserver> cookieObserver;
3247 RefPtr<HttpChannelParent> httpParent;
3248 CookieServiceParent::CookieProcessingGuard cookieProcessingGuard;
3249
3250 // Skip parent channel interaction for background revalidating channels.
3251 if (!LoadOnStartRequestCalled() && !mStaleRevalidation) {
3252 // This can only happen when a range request is created again in
3253 // nsHttpChannel::ContinueOnStopRequest. If OnStartRequest is already
3254 // called, we shouldn't call SetCookieHeaders.
3255
3256 MaybeInitializeCookieProcessingGuard(this, cookieProcessingGuard,
3257 cookieObserver, httpParent,
3258 httpStatus);
3259 }
3260
3261 CookieVisitor cookieVisitor(mResponseHead.get());
3262 SetCookieHeaders(cookieVisitor.CookieHeaders());
3263
3264 if (cookieObserver) {
3265 nsTArray<CookieChange> cookieChanges;
3266 cookieObserver->StealChanges(cookieChanges);
3267
3268 if (!cookieChanges.IsEmpty()) {
3269 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"
, 3269); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpParent"
")"); do { MOZ_CrashSequence(__null, 3269); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3270 httpParent->SetCookieChanges(std::move(cookieChanges));
3271 }
3272 }
3273 }
3274
3275 rv = ProcessWAICTHeader();
3276 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3277 return rv;
3278 }
3279
3280 // Given a successful connection, process any STS or PKP data that's
3281 // relevant.
3282 if (NS_FAILED(ProcessSecurityHeaders())((bool)(__builtin_expect(!!(NS_FAILED_impl(ProcessSecurityHeaders
())), 0)))
) {
3283 NS_WARNING("ProcessSecurityHeaders failed, continuing load.")NS_DebugBreak(NS_DEBUG_WARNING, "ProcessSecurityHeaders failed, continuing load."
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 3283)
;
3284 }
3285
3286 if ((httpStatus < 500) && (httpStatus != 421)) {
3287 ProcessAltService(aConnInfo);
3288 }
3289 }
3290
3291 if (LoadConcurrentCacheAccess() && LoadCachedContentIsPartial() &&
3292 httpStatus != 206) {
3293 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)
3294 (" 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)
3295 "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)
;
3296 return NS_ERROR_CORRUPTED_CONTENT;
3297 }
3298
3299 if (httpStatus != 401 && httpStatus != 407) {
3300 // reset the authentication's current continuation state because ourvr
3301 // last authentication attempt has been completed successfully
3302 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", 3302
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3302); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3303 rv = mAuthProvider ? mAuthProvider->Disconnect(NS_ERROR_ABORT)
3304 : NS_ERROR_UNEXPECTED;
3305 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3306 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)
;
3307 }
3308 mAuthProvider = nullptr;
3309 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)
;
3310 }
3311
3312 gHttpHandler->OnAfterExamineResponse(this);
3313
3314 if (mResponseHead && mResponseHead->HasHeader(nsHttp::Clear_Site_Data)) {
3315 if (nsCOMPtr<nsIObserverService> obsService =
3316 services::GetObserverService()) {
3317 obsService->NotifyObservers(static_cast<nsIHttpChannel*>(this),
3318 "clear-site-data", nullptr);
3319 }
3320 }
3321
3322 // No process switch needed, continue as normal.
3323 return ContinueProcessResponse2(rv);
3324}
3325
3326nsresult nsHttpChannel::ContinueProcessResponse2(nsresult rv) {
3327 if (mSuspendCount) {
3328 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)
3329 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3330 mCallOnResume = [rv](nsHttpChannel* self) {
3331 (void)self->ContinueProcessResponse2(rv);
3332 return NS_OK;
3333 };
3334 return NS_OK;
3335 }
3336
3337 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCanceled) {
3338 // The process switch failed, cancel this channel.
3339 Cancel(rv);
3340 return CallOnStartRequest();
3341 }
3342
3343 if (mAPIRedirectTo && !mCanceled) {
3344 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", 3344
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 3344); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3345
3346 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
3347 rv = StartRedirectChannelToURI(
3348 mAPIRedirectTo->first(),
3349 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_TEMPORARY |
3350 nsIChannelEventSink::REDIRECT_TRANSPARENT
3351 : nsIChannelEventSink::REDIRECT_TEMPORARY);
3352 mAPIRedirectTo = Nothing();
3353 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3354 return NS_OK;
3355 }
3356 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse3);
3357 }
3358
3359 // Hack: ContinueProcessResponse3 uses NS_OK to detect successful
3360 // redirects, so we distinguish this codepath (a non-redirect that's
3361 // processing normally) by passing in a bogus error code.
3362 return ContinueProcessResponse3(NS_BINDING_FAILED);
3363}
3364
3365nsresult nsHttpChannel::ContinueProcessResponse3(nsresult rv) {
3366 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)
3367 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)
;
3368
3369 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3370 // redirectTo() has passed through, we don't want to go on with
3371 // this channel. It will now be canceled by the redirect handling
3372 // code that called this function.
3373 return NS_OK;
3374 }
3375
3376 rv = NS_OK;
3377
3378 uint32_t httpStatus = mResponseHead->Status();
3379 bool transactionRestarted = mTransaction->TakeRestartedState();
3380
3381 // handle different server response categories. Note that we handle
3382 // caching or not caching of error pages in
3383 // nsHttpResponseHead::MustValidate; if you change this switch, update that
3384 // one
3385 switch (httpStatus) {
3386 case 200:
3387 case 203:
3388 // Per RFC 2616, 14.35.2, "A server MAY ignore the Range header".
3389 // So if a server does that and sends 200 instead of 206 that we
3390 // expect, notify our caller.
3391 // However, if we wanted to start from the beginning, let it go through
3392 if (LoadResuming() && mStartPos != 0) {
3393 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)
;
3394 Cancel(NS_ERROR_NOT_RESUMABLE);
3395 rv = CallOnStartRequest();
3396 break;
3397 }
3398 // these can normally be cached
3399 rv = ProcessNormal();
3400 MaybeInvalidateCacheEntryForSubsequentGet();
3401 break;
3402 case 206:
3403 if (LoadCachedContentIsPartial()) { // an internal byte range request...
3404 auto func = [](auto* self, nsresult aRv) {
3405 return self->ContinueProcessResponseAfterPartialContent(aRv);
3406 };
3407 rv = ProcessPartialContent(func);
3408 // Directly call ContinueProcessResponseAfterPartialContent if channel
3409 // is not suspended or ProcessPartialContent throws.
3410 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3411 return ContinueProcessResponseAfterPartialContent(rv);
3412 }
3413 return NS_OK;
3414 } else {
3415 mCacheInputStream.CloseAndRelease();
3416 rv = ProcessNormal();
3417 }
3418 break;
3419 case 301:
3420 case 302:
3421 case 303:
3422 case 307:
3423 case 308:
3424#if 0
3425 case 305: // disabled as a security measure (see bug 187996).
3426#endif
3427 // RFC 9110: 303 responses are cacheable, but only with explicit
3428 // freshness information (max-age or Expires). Without these directives,
3429 // 303 should not be cached.
3430 if (httpStatus == 303) {
3431 uint32_t freshnessLifetime = 0;
3432 bool hasFreshness =
3433 (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
ComputeFreshnessLifetime(&freshnessLifetime))), 1)))
3434 mResponseHead->ComputeFreshnessLifetime(&freshnessLifetime))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
ComputeFreshnessLifetime(&freshnessLifetime))), 1)))
&&
3435 freshnessLifetime > 0) ||
3436 mResponseHead->HasHeader(nsHttp::Expires);
3437 if (mResponseHead->NoStore() || mResponseHead->NoCache() ||
3438 !hasFreshness) {
3439 CloseCacheEntry(false);
3440 }
3441 }
3442 // don't store the response body for redirects
3443 MaybeInvalidateCacheEntryForSubsequentGet();
3444 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
3445 rv = AsyncProcessRedirection(httpStatus);
3446 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3447 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessResponse4);
3448 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)
3449 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)
;
3450 // don't cache failed redirect responses.
3451 if (mCacheEntry) mCacheEntry->AsyncDoom(nullptr);
3452 if (DoNotRender3xxBody(rv)) {
3453 mStatus = rv;
3454 DoNotifyListener();
3455 } else {
3456 rv = ContinueProcessResponse4(rv);
3457 }
3458 }
3459 break;
3460 case 304:
3461 if (!ShouldBypassProcessNotModified()) {
3462 auto func = [](auto* self, nsresult aRv) {
3463 return self->ContinueProcessResponseAfterNotModified(aRv);
3464 };
3465 rv = ProcessNotModified(func);
3466 // Directly call ContinueProcessResponseAfterNotModified if channel
3467 // is not suspended or ProcessNotModified throws.
3468 if (!mSuspendCount || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3469 return ContinueProcessResponseAfterNotModified(rv);
3470 }
3471 return NS_OK;
3472 }
3473
3474 // Don't cache uninformative 304
3475 if (LoadCustomConditionalRequest()) {
3476 CloseCacheEntry(false);
3477 }
3478
3479 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3480 rv = ProcessNormal();
3481 }
3482 break;
3483 case 401:
3484 case 407:
3485 if (MOZ_UNLIKELY(httpStatus == 407 && transactionRestarted)(__builtin_expect(!!(httpStatus == 407 && transactionRestarted
), 0))
) {
3486 // The transaction has been internally restarted. We want to
3487 // authenticate to the proxy again, so reuse either cached credentials
3488 // or use default credentials for NTLM/Negotiate. This prevents
3489 // considering the previously used credentials as invalid.
3490 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", 3490
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3490); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3491 if (!mAuthProvider) {
3492 mStatus = NS_ERROR_UNEXPECTED;
3493 return ProcessNormal();
3494 }
3495 mAuthProvider->ClearProxyIdent();
3496 }
3497 if (!LoadAuthRedirectedChannel() &&
3498 MOZ_UNLIKELY(LoadCustomAuthHeader())(__builtin_expect(!!(LoadCustomAuthHeader()), 0)) && httpStatus == 401) {
3499 // When a custom auth header fails, we don't want to try
3500 // any cached credentials, nor we want to ask the user.
3501 // It's up to the consumer to re-try w/o setting a custom
3502 // auth header if cached credentials should be attempted.
3503 rv = NS_ERROR_FAILURE;
3504 } else if (httpStatus == 401 &&
3505 !nsContentSecurityUtils::CheckCSPFrameAncestorAndXFO(this)) {
3506 // CSP Frame Ancestor and X-Frame-Options check has failed
3507 // Do not prompt http auth - Bug 1629307
3508 rv = NS_ERROR_FAILURE;
3509 } else {
3510 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", 3510
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mAuthProvider"
")"); do { MOZ_CrashSequence(__null, 3510); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3511 rv = mAuthProvider
3512 ? mAuthProvider->ProcessAuthentication(
3513 httpStatus, mConnectionInfo->EndToEndSSL() &&
3514 mTransaction &&
3515 mTransaction->ProxyConnectFailed())
3516 : NS_ERROR_UNEXPECTED;
3517 }
3518 if (rv == NS_ERROR_IN_PROGRESS) {
3519 // authentication prompt has been invoked and result
3520 // is expected asynchronously
3521 mIsAuthChannel = true;
3522 mAuthRetryPending = true;
3523 if (httpStatus == 407 ||
3524 (mTransaction && mTransaction->ProxyConnectFailed())) {
3525 StoreProxyAuthPending(true);
3526 }
3527
3528 // suspend the transaction pump to stop receiving the
3529 // unauthenticated content data. We will throw that data
3530 // away when user provides credentials or resume the pump
3531 // when user refuses to authenticate.
3532 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)
3533 ("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)
3534 "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)
;
3535 Suspend();
3536
3537#ifdef DEBUG1
3538 // This is for test purposes only. See bug 1683176 for details.
3539 gHttpHandler->OnTransactionSuspendedDueToAuthentication(this);
3540#endif
3541 rv = NS_OK;
3542 } else if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3543 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)
3544 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)
;
3545 if (mTransaction && mTransaction->ProxyConnectFailed()) {
3546 return ProcessFailedProxyConnect(httpStatus);
3547 }
3548 if (rv == NS_ERROR_BASIC_HTTP_AUTH_DISABLED) {
3549 mStatus = rv;
3550 }
3551 rv = ProcessNormal();
3552 } else {
3553 mIsAuthChannel = true;
3554 mAuthRetryPending = true;
3555 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
3556 if (NS_SUCCEEDED(RedirectToNewChannelForAuthRetry())((bool)(__builtin_expect(!!(!NS_FAILED_impl(RedirectToNewChannelForAuthRetry
())), 1)))
) {
3557 return NS_OK;
3558 }
3559 mAuthRetryPending = false;
3560 rv = ProcessNormal();
3561 }
3562 }
3563 break;
3564
3565 case 408:
3566 case 425:
3567 case 429:
3568 // Do not cache 408, 425 and 429.
3569 CloseCacheEntry(false);
3570 [[fallthrough]]; // process normally
3571 default:
3572 rv = ProcessNormal();
3573 MaybeInvalidateCacheEntryForSubsequentGet();
3574 break;
3575 }
3576
3577 UpdateCacheDisposition(false, false);
3578 return rv;
3579}
3580
3581nsresult nsHttpChannel::ContinueProcessResponseAfterPartialContent(
3582 nsresult aRv) {
3583 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)
3584 ("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)
3585 "[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)
3586 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)
;
3587
3588 UpdateCacheDisposition(false, NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1))));
3589 return aRv;
3590}
3591
3592nsresult nsHttpChannel::ContinueProcessResponseAfterNotModified(nsresult aRv) {
3593 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)
3594 ("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)
3595 "[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)
3596 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)
;
3597
3598 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1)))) {
3599 StoreTransactionReplaced(true);
3600 UpdateCacheDisposition(true, false);
3601 return NS_OK;
3602 }
3603
3604 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)
3605 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)
;
3606
3607 // We cannot read from the cache entry, it might be in an
3608 // inconsistent state. Doom it and redirect the channel
3609 // to the same URI to reload from the network.
3610 mCacheInputStream.CloseAndRelease();
3611 if (mCacheEntry) {
3612 mCacheEntry->AsyncDoom(nullptr);
3613 mCacheEntry = nullptr;
3614 }
3615
3616 nsresult rv =
3617 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
3618 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3619 return NS_OK;
3620 }
3621
3622 // Don't cache uninformative 304
3623 if (LoadCustomConditionalRequest()) {
3624 CloseCacheEntry(false);
3625 }
3626
3627 if (ShouldBypassProcessNotModified() || NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3628 rv = ProcessNormal();
3629 }
3630
3631 UpdateCacheDisposition(false, false);
3632 return rv;
3633}
3634
3635static void ReportHttpResponseVersion(HttpVersion version) {
3636 if (Telemetry::CanRecordPrereleaseData()) {
3637 glean::http::response_version.AccumulateSingleSample(
3638 static_cast<uint32_t>(version));
3639 }
3640 mozilla::glean::networking::http_response_version
3641 .Get(HttpVersionToTelemetryLabel(version))
3642 .Add(1);
3643}
3644
3645void nsHttpChannel::UpdateCacheDisposition(bool aSuccessfulReval,
3646 bool aPartialContentUsed) {
3647 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)
3648 "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)
3649 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)
3650 !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)
3651 : (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)
;
3652 CacheDisposition cacheDisposition;
3653 if (!mDidReval) {
3654 cacheDisposition = kCacheMissed;
3655 } else if (aSuccessfulReval) {
3656 cacheDisposition = kCacheHitViaReval;
3657 } else {
3658 cacheDisposition = kCacheMissedViaReval;
3659 }
3660 mCacheDisposition = cacheDisposition;
3661
3662 if (Telemetry::CanRecordPrereleaseData()) {
3663 AccumulateCacheHitTelemetry(cacheDisposition, this);
3664 }
3665
3666 ReportHttpResponseVersion(mResponseHead->Version());
3667}
3668
3669// Only used for redirects (3XX responses)
3670nsresult nsHttpChannel::ContinueProcessResponse4(nsresult rv) {
3671 bool doNotRender = DoNotRender3xxBody(rv);
3672
3673 if (rv == NS_ERROR_DOM_BAD_URI && mRedirectURI &&
3674 !net::SchemeIsHttpOrHttps(mRedirectURI)) {
3675 // This was a blocked attempt to redirect and subvert the system by
3676 // redirecting to another protocol (perhaps javascript:)
3677 // In that case we want to throw an error instead of displaying the
3678 // non-redirected response body.
3679 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)
;
3680 doNotRender = true;
3681 rv = NS_ERROR_CORRUPTED_CONTENT;
3682 }
3683
3684 if (doNotRender) {
3685 Cancel(rv);
3686 DoNotifyListener();
3687 return rv;
3688 }
3689
3690 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3691 UpdateInhibitPersistentCachingFlag();
3692 (void)MaybeReplaceNoVarySearchAliasEntry();
3693
3694 if (mCacheEntry) {
3695 rv = UpdateExpirationTime();
3696 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3697 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)
3698 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)
;
3699 }
3700 }
3701 rv = InitCacheEntry();
3702 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3703 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)
3704 ("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)
3705 "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)
3706 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)
;
3707 }
3708 CloseCacheEntry(false);
3709 return NS_OK;
3710 }
3711
3712 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)
3713 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)
;
3714 if (mTransaction && mTransaction->ProxyConnectFailed()) {
3715 return ProcessFailedProxyConnect(mRedirectType);
3716 }
3717 return ProcessNormal();
3718}
3719
3720nsresult nsHttpChannel::ProcessNormal() {
3721 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)
;
3722
3723 return ContinueProcessNormal(NS_OK);
3724}
3725
3726nsresult nsHttpChannel::ContinueProcessNormal(nsresult rv) {
3727 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)
;
3728
3729 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3730 // Fill the failure status here, we have failed to fall back, thus we
3731 // have to report our status as failed.
3732 mStatus = rv;
3733 DoNotifyListener();
3734 return rv;
3735 }
3736
3737 rv = ProcessCrossOriginSecurityHeaders();
3738 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3739 mStatus = rv;
3740 HandleAsyncAbort();
3741 return rv;
3742 }
3743
3744 // if we're here, then any byte-range requests failed to result in a partial
3745 // response. we must clear this flag to prevent BufferPartialContent from
3746 // being called inside our OnDataAvailable (see bug 136678).
3747 StoreCachedContentIsPartial(false);
3748
3749 UpdateInhibitPersistentCachingFlag();
3750
3751 // We may need to install the cache listener before CallonStartRequest,
3752 // since InstallCacheListener can modify the Content-Encoding to remove
3753 // dcb/dcz (and perhaps others), and CallOnStartRequest() copies
3754 // Content-Encoding to send to the content process. If this doesn't
3755 // install a listener (because this isn't a dictionary or
3756 // dictionary-compressed), call it after CallOnStartRequest so that we
3757 // save the compressed data in the cache, and run the decompressor in the
3758 // content process.
3759 mIsDictionaryCompressed = false;
3760 nsAutoCString contentEncoding;
3761 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
3762 if (contentEncoding.LowerCaseEqualsLiteral("dcb") ||
3763 contentEncoding.LowerCaseEqualsLiteral("dcz")) {
3764 mIsDictionaryCompressed = true;
3765 } else if (contentEncoding.LowerCaseFindASCII("dcb") != -1 ||
3766 contentEncoding.LowerCaseFindASCII("dcz") != -1) {
3767 // Reject responses that combine dcb/dcz with other encodings
3768 // (e.g. "dcb, gzip" or "gzip, dcz"). We don't support chained
3769 // dictionary compression with other compression methods.
3770 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)
3771 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)
;
3772 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
3773 return NS_ERROR_INVALID_CONTENT_ENCODING;
3774 }
3775
3776 (void)MaybeReplaceNoVarySearchAliasEntry();
3777
3778 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3779 // Must update expiration time early - ParseDictionary reads it, and
3780 // it's no longer done in InitCacheEntry to avoid double calculation
3781 rv = UpdateExpirationTime();
3782 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3783 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)
;
3784 }
3785
3786 // XXX We may want to consider recompressing any dcb/dcz files to save space
3787 // and improve hitrate. Downside is CPU use, complexity and perhaps delay,
3788 // maybe.
3789 nsAutoCString dictionary;
3790 if (StaticPrefs::network_http_dictionaries_enable() && IsHTTPS()) {
3791 (void)mResponseHead->GetHeader(nsHttp::Use_As_Dictionary, dictionary);
3792 if (!dictionary.IsEmpty()) {
3793 if (!ParseDictionary(mCacheEntry, mResponseHead.get(), true)) {
3794 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)
;
3795 } else {
3796 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"
, 3796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDictSaving"
")"); do { MOZ_CrashSequence(__null, 3796); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3797
3798 // We need to record the hash as we save it
3799 mCacheEntry->SetDictionary(mDictSaving);
3800 }
3801 }
3802 }
3803
3804 // we would call DoInstallCacheListener() here, but it will close the
3805 // cache input stream, which causes problems if we going to be
3806 // suspended because we're replacing a active dictionary. Instead we'll
3807 // call it in ContinueProcessNormal2()
3808 } else {
3809 if (mIsDictionaryCompressed) {
3810 // We still need to decompress in the parent if it's dcb or dcz even if
3811 // not saving to the cache
3812 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)
3813 ("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)
;
3814 nsCOMPtr<nsIStreamListener> listener;
3815 // otherwise we won't convert in the parent process
3816 // XXX may be redundant, but safe
3817 SetApplyConversion(true);
3818 rv = DoApplyContentConversionsInternal(
3819 mListener, getter_AddRefs(listener), true, nullptr);
3820 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3821 return rv;
3822 }
3823 if (listener) {
3824 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)
3825 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)
;
3826 mListener = listener;
3827 mCompressListener = std::move(listener);
3828 StoreHasAppliedConversion(true);
3829 } else {
3830 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)
;
3831 // This should never happen for dictionary-compressed content (dcb/dcz)
3832 // as it MUST be decompressed in the parent process
3833 if (mIsDictionaryCompressed) {
3834 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)
3835 ("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)
3836 "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)
;
3837 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
3838 return NS_ERROR_INVALID_CONTENT_ENCODING;
3839 }
3840 }
3841 }
3842 } // else we'll call InstallCacheListener after CallOnStartRequest
3843
3844 // ParseDictionary may have resulted in our Suspend()ing this request
3845 // until the old dictionary we're replacing has been read from the cache.
3846 // If we continue we'll call InitCacheEntry() and Doom/truncate the entry
3847 // the old one is reading from.
3848 return ContinueProcessNormal2(rv);
3849}
3850
3851nsresult nsHttpChannel::ContinueProcessNormal2(nsresult rv) {
3852 if (mSuspendCount) {
3853 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)
3854 ("*** 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)
3855 "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)
3856 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)
;
3857 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)
3858 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3859 mCallOnResume = [rv](nsHttpChannel* self) {
3860 (void)self->ContinueProcessNormal2(rv);
3861 return NS_OK;
3862 };
3863 return NS_OK;
3864 }
3865
3866 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCanceled) {
3867 // The process switch failed, cancel this channel.
3868 Cancel(rv);
3869 return CallOnStartRequest();
3870 }
3871
3872 // this must be called before firing OnStartRequest, since http clients,
3873 // such as imagelib, expect our cache entry to already have the correct
3874 // expiration time (bug 87710).
3875 if (mCacheEntry) {
3876 rv = InitCacheEntry();
3877 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) CloseCacheEntry(true);
3878 }
3879
3880 // CRITICAL: Check if dictionary is ready BEFORE creating decompressor.
3881 // If we create the decompressor before the dictionary is ready, it will
3882 // be created without the dictionary attached, causing decompression to fail.
3883 // The dictionary prefetch callback (in PrepareToConnect) will call Resume()
3884 // when ready, which will re-invoke ContinueProcessNormal2 via mCallOnResume.
3885 if (mIsDictionaryCompressed && mDictDecompress && mUsingDictionary &&
3886 mShouldSuspendForDictionary && !mDictDecompress->DictionaryReady()) {
3887 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)
3888 ("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)
3889 "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)
3890 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)
;
3891 Suspend();
3892 mSuspendedForDictionary = true;
3893 // Set up callback to resume processing when dictionary loads
3894 mCallOnResume = [](nsHttpChannel* self) {
3895 return self->ContinueProcessNormal3();
3896 };
3897 return NS_OK;
3898 }
3899
3900 return ContinueProcessNormal3();
3901}
3902
3903nsresult nsHttpChannel::ContinueProcessNormal3() {
3904 if (mCanceled) {
3905 return CallOnStartRequest();
3906 }
3907 nsresult rv = NS_OK;
3908
3909 // Finish post-ParseDictionary work, must be done after waiting if Suspended
3910 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3911 if (mIsDictionaryCompressed || mDictSaving) {
3912 if (MOZ_LOG_TEST(mozilla::net::gDictionaryLog,(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
3913 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
) {
3914 nsAutoCString ceDebug;
3915 if (mResponseHead) {
3916 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, ceDebug);
3917 }
3918 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)
3919 ("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)
3920 "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)
3921 "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)
3922 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)
3923 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)
;
3924 }
3925 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)
;
3926 rv = DoInstallCacheListener(mIsDictionaryCompressed || mDictSaving, 0);
3927 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3928 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)
3929 ("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)
;
3930 // Cache entry is now corrupted - we set up headers with dcb/dcz
3931 // Content-Encoding but failed to install the decompressor that would
3932 // clear it. Doom the entry to prevent serving corrupted data.
3933 CloseCacheEntry(true);
3934 }
3935 }
3936 }
3937
3938 // Check that the server sent us what we were asking for
3939 if (LoadResuming()) {
3940 // Create an entity id from the response
3941 nsAutoCString id;
3942 rv = GetEntityID(id);
3943 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3944 // If creating an entity id is not possible -> error
3945 Cancel(NS_ERROR_NOT_RESUMABLE);
3946 } else if (mResponseHead->Status() != 206 &&
3947 mResponseHead->Status() != 200) {
3948 // Probably 404 Not Found, 412 Precondition Failed or
3949 // 416 Invalid Range -> error
3950 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)
3951 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
3952 Cancel(NS_ERROR_ENTITY_CHANGED);
3953 }
3954 // If we were passed an entity id, verify it's equal to the server's
3955 else if (!mEntityID.IsEmpty()) {
3956 if (!mEntityID.Equals(id)) {
3957 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)
3958 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)
;
3959 Cancel(NS_ERROR_ENTITY_CHANGED);
3960 }
3961 }
3962 }
3963
3964 rv = CallOnStartRequest();
3965 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3966
3967 // If we didn't install cache listeners to decompress above
3968 // install the cache listener now (so they'll get compressed data)
3969 if (!mIsDictionaryCompressed && !mDictSaving) {
3970 // install cache listener if we still have a cache entry open
3971 if (mCacheEntry && !LoadCacheEntryIsReadOnly()) {
3972 if (MOZ_LOG_TEST(mozilla::net::gDictionaryLog,(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
3973 mozilla::LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gDictionaryLog, mozilla::LogLevel::Debug)), 0))
&&
3974 mResponseHead) {
3975 nsAutoCString ceCheck;
3976 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, ceCheck);
3977 if (!ceCheck.IsEmpty()) {
3978 nsAutoCString uadCheck;
3979 (void)mResponseHead->GetHeader(nsHttp::Use_As_Dictionary, uadCheck);
3980 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)
3981 ("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)
3982 "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)
3983 "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)
3984 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)
3985 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)
;
3986 }
3987 }
3988 rv = InstallCacheListener();
3989 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
3990 }
3991 }
3992 return NS_OK;
3993}
3994
3995nsresult nsHttpChannel::PromptTempRedirect() {
3996 if (!gHttpHandler->PromptTempRedirect()) {
3997 return NS_OK;
3998 }
3999 nsresult rv;
4000 nsCOMPtr<nsIStringBundleService> bundleService;
4001 bundleService = mozilla::components::StringBundle::Service(&rv);
4002 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4003
4004 nsCOMPtr<nsIStringBundle> stringBundle;
4005 rv =
4006 bundleService->CreateBundle(NECKO_MSGS_URL"chrome://necko/locale/necko.properties", getter_AddRefs(stringBundle));
4007 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4008
4009 nsAutoString messageString;
4010 rv = stringBundle->GetStringFromName("RepostFormData", messageString);
4011 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4012 bool repost = false;
4013
4014 nsCOMPtr<nsIPrompt> prompt;
4015 GetCallback(prompt);
4016 if (!prompt) return NS_ERROR_NO_INTERFACE;
4017
4018 prompt->Confirm(nullptr, messageString.get(), &repost);
4019 if (!repost) return NS_ERROR_FAILURE;
4020 }
4021
4022 return rv;
4023}
4024
4025nsresult nsHttpChannel::ProxyFailover() {
4026 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)
;
4027
4028 nsresult rv;
4029
4030 nsCOMPtr<nsIProtocolProxyService> pps;
4031 pps = mozilla::components::ProtocolProxy::Service(&rv);
4032 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4033
4034 nsCOMPtr<nsIProxyInfo> pi;
4035 rv = pps->GetFailoverForProxy(mConnectionInfo->ProxyInfo(), mURI, mStatus,
4036 getter_AddRefs(pi));
4037#ifdef MOZ_PROXY_DIRECT_FAILOVER1
4038 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4039 if (!StaticPrefs::network_proxy_failover_direct()) {
4040 return rv;
4041 }
4042 // If this request used a failed proxy and there is no failover available,
4043 // fallback to DIRECT connections for conservative requests.
4044 if (LoadBeConservative()) {
4045 rv = pps->NewProxyInfo("direct"_ns, ""_ns, 0, ""_ns, ""_ns, 0, UINT32_MAX(4294967295U),
4046 nullptr, getter_AddRefs(pi));
4047 }
4048#endif
4049 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4050 return rv;
4051 }
4052#ifdef MOZ_PROXY_DIRECT_FAILOVER1
4053 }
4054#endif
4055
4056 // XXXbz so where does this codepath remove us from the loadgroup,
4057 // exactly?
4058 return AsyncDoReplaceWithProxy(pi);
4059}
4060
4061void nsHttpChannel::SetHTTPSSVCRecord(
4062 already_AddRefed<nsIDNSHTTPSSVCRecord> aRecord) {
4063 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)
;
4064 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
4065 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", 4065
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mHTTPSSVCRecord"
")"); do { MOZ_CrashSequence(__null, 4065); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4066 mHTTPSSVCRecord.emplace(std::move(record));
4067}
4068
4069void nsHttpChannel::HandleAsyncRedirectChannelToHttps() {
4070 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"
, 4070); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4070); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4071
4072 if (mSuspendCount) {
4073 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)
4074 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
4075 mCallOnResume = [](nsHttpChannel* self) {
4076 self->HandleAsyncRedirectChannelToHttps();
4077 return NS_OK;
4078 };
4079 return;
4080 }
4081
4082 nsresult rv = StartRedirectChannelToHttps();
4083 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4084 rv = ContinueAsyncRedirectChannelToURI(rv);
4085 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4086 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)
4087 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)
;
4088 }
4089 }
4090}
4091
4092nsresult nsHttpChannel::StartRedirectChannelToHttps() {
4093 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)
;
4094
4095 nsCOMPtr<nsIURI> upgradedURI;
4096 nsresult rv = NS_GetSecureUpgradedURI(mURI, getter_AddRefs(upgradedURI));
4097 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"
, 4097); return rv; } } while (false)
;
4098
4099 return StartRedirectChannelToURI(
4100 upgradedURI, nsIChannelEventSink::REDIRECT_PERMANENT |
4101 nsIChannelEventSink::REDIRECT_STS_UPGRADE);
4102}
4103
4104void nsHttpChannel::HandleAsyncAPIRedirect() {
4105 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"
, 4105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4105); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4106 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"
, 4106); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4106); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4107 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"
, 4107); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAPIRedirectTo->first()"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4107); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4108
4109 if (mSuspendCount) {
4110 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)
;
4111 mCallOnResume = [](nsHttpChannel* self) {
4112 self->HandleAsyncAPIRedirect();
4113 return NS_OK;
4114 };
4115 return;
4116 }
4117
4118 nsresult rv = StartRedirectChannelToURI(
4119 mAPIRedirectTo->first(),
4120 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_PERMANENT |
4121 nsIChannelEventSink::REDIRECT_TRANSPARENT
4122 : nsIChannelEventSink::REDIRECT_PERMANENT);
4123 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4124 rv = ContinueAsyncRedirectChannelToURI(rv);
4125 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4126 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)
4127 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)
;
4128 }
4129 }
4130}
4131
4132void nsHttpChannel::HandleAsyncRedirectToUnstrippedURI() {
4133 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"
, 4133); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume"
") (" "How did that happen?" ")"); do { MOZ_CrashSequence(__null
, 4133); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
4134
4135 if (mSuspendCount) {
4136 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)
4137 ("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)
4138 "[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)
4139 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
4140 mCallOnResume = [](nsHttpChannel* self) {
4141 self->HandleAsyncRedirectToUnstrippedURI();
4142 return NS_OK;
4143 };
4144 return;
4145 }
4146
4147 nsCOMPtr<nsIURI> unstrippedURI;
4148 mLoadInfo->GetUnstrippedURI(getter_AddRefs(unstrippedURI));
4149
4150 // Clear the unstripped URI from the loadInfo before starting redirect in case
4151 // endless redirect.
4152 mLoadInfo->SetUnstrippedURI(nullptr);
4153
4154 nsresult rv = StartRedirectChannelToURI(
4155 unstrippedURI, nsIChannelEventSink::REDIRECT_PERMANENT);
4156
4157 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4158 rv = ContinueAsyncRedirectChannelToURI(rv);
4159 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4160 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)
4161 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)
;
4162 }
4163 }
4164}
4165nsresult nsHttpChannel::RedirectToNewChannelForAuthRetry() {
4166 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)
;
4167 nsresult rv = NS_OK;
4168
4169 nsCOMPtr<nsILoadInfo> redirectLoadInfo = CloneLoadInfoForRedirect(
4170 mURI, nsIChannelEventSink::REDIRECT_INTERNAL |
4171 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4172
4173 nsCOMPtr<nsIIOService> ioService;
4174
4175 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
4176 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"
, 4176); return rv; } } while (false)
;
4177
4178 nsCOMPtr<nsIChannel> newChannel;
4179 rv = gHttpHandler->NewProxiedChannel(mURI, mProxyInfo, mProxyResolveFlags,
4180 mProxyURI, mLoadInfo,
4181 getter_AddRefs(newChannel));
4182
4183 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"
, 4183); return rv; } } while (false)
;
4184
4185 rv = SetupReplacementChannel(mURI, newChannel, true,
4186 nsIChannelEventSink::REDIRECT_INTERNAL |
4187 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4188 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"
, 4188); return rv; } } while (false)
;
4189
4190 // rewind the upload stream
4191 if (mUploadStream) {
4192 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
4193 nsresult rv = NS_ERROR_NO_INTERFACE;
4194 if (seekable) {
4195 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
4196 }
4197
4198 // This should not normally happen, but it's possible that big memory
4199 // blobs originating in the other process can't be rewinded.
4200 // In that case we just fail the request, otherwise the content length
4201 // will not match and this load will never complete.
4202 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"
, 4202); return rv; } } while (false)
;
4203 }
4204
4205 RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel);
4206
4207 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", 4207
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthProvider" ")"
); do { MOZ_CrashSequence(__null, 4207); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4208 httpChannelImpl->mAuthProvider = std::move(mAuthProvider);
4209
4210 httpChannelImpl->mProxyInfo = mProxyInfo;
4211
4212 if ((mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) ||
4213 mTransaction->HasStickyConnection()) {
4214 mConnectionInfo = mTransaction->GetConnInfo();
4215
4216 httpChannelImpl->mTransactionSticky = mTransaction;
4217
4218 if (mTransaction->Http2Disabled()) {
4219 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
4220 }
4221 if (mTransaction->Http3Disabled()) {
4222 httpChannelImpl->mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
4223 }
4224 }
4225 // always set sticky connection flag
4226 httpChannelImpl->mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
4227
4228 if (LoadAuthConnectionRestartable()) {
4229 httpChannelImpl->mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
4230 } else {
4231 httpChannelImpl->mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
4232 }
4233
4234 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", 4234
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mConnectionInfo" ")"
); do { MOZ_CrashSequence(__null, 4234); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4235 httpChannelImpl->mConnectionInfo = mConnectionInfo->Clone();
4236
4237 // we need to store the state to skip unnecessary checks in the new channel
4238 httpChannelImpl->StoreAuthRedirectedChannel(true);
4239
4240 // We must copy proxy and auth header to the new channel.
4241 // Although the new channel can populate auth headers from auth cache, we
4242 // would still like to use the auth headers generated in this channel. The
4243 // main reason for doing this is that certain connection-based/stateful auth
4244 // schemes like NTLM will fail when we try generate the credentials more than
4245 // the number of times the server has presented us the challenge due to the
4246 // usage of nonce in generating the credentials Copying the auth header will
4247 // bypass generation of the credentials
4248 nsAutoCString authVal;
4249 if (NS_SUCCEEDED(GetRequestHeader("Proxy-Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Proxy-Authorization"_ns, authVal))), 1)))
) {
4250 httpChannelImpl->SetRequestHeader("Proxy-Authorization"_ns, authVal, false);
4251 }
4252 if (NS_SUCCEEDED(GetRequestHeader("Authorization"_ns, authVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(GetRequestHeader(
"Authorization"_ns, authVal))), 1)))
) {
4253 httpChannelImpl->SetRequestHeader("Authorization"_ns, authVal, false);
4254 }
4255
4256 httpChannelImpl->SetBlockAuthPrompt(LoadBlockAuthPrompt());
4257 mRedirectChannel = newChannel;
4258
4259 rv = gHttpHandler->AsyncOnChannelRedirect(
4260 this, newChannel,
4261 nsIChannelEventSink::REDIRECT_INTERNAL |
4262 nsIChannelEventSink::REDIRECT_AUTH_RETRY);
4263
4264 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4265
4266 // redirected channel will be opened after we receive the OnStopRequest
4267
4268 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4269 AutoRedirectVetoNotifier notifier(this, rv);
4270 mRedirectChannel = nullptr;
4271 }
4272
4273 return rv;
4274}
4275
4276nsresult nsHttpChannel::StartRedirectChannelToURI(nsIURI* upgradedURI,
4277 uint32_t flags) {
4278 return StartRedirectChannelToURI(upgradedURI, flags, [](nsIChannel*) {});
4279}
4280
4281nsresult nsHttpChannel::StartRedirectChannelToURI(
4282 nsIURI* upgradedURI, uint32_t flags,
4283 std::function<void(nsIChannel*)>&& aCallback) {
4284 nsresult rv = NS_OK;
4285 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)
;
4286
4287 nsCOMPtr<nsIChannel> newChannel;
4288 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
4289 CloneLoadInfoForRedirect(upgradedURI, flags);
4290
4291 nsCOMPtr<nsIIOService> ioService;
4292 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
4293 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"
, 4293); return rv; } } while (false)
;
4294
4295 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), upgradedURI,
4296 redirectLoadInfo,
4297 nullptr, // PerformanceStorage
4298 nullptr, // aLoadGroup
4299 nullptr, // aCallbacks
4300 nsIRequest::LOAD_NORMAL, ioService);
4301 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"
, 4301); return rv; } } while (false)
;
4302
4303 rv = SetupReplacementChannel(upgradedURI, newChannel, true, flags);
4304 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"
, 4304); return rv; } } while (false)
;
4305
4306 if (mHTTPSSVCRecord) {
4307 RefPtr<nsHttpChannel> httpChan = do_QueryObject(newChannel);
4308 nsCOMPtr<nsIDNSHTTPSSVCRecord> rec = mHTTPSSVCRecord.ref();
4309 if (httpChan && rec) {
4310 httpChan->SetHTTPSSVCRecord(rec.forget());
4311 }
4312 }
4313
4314 // Inform consumers about this fake redirect
4315 mRedirectChannel = newChannel;
4316
4317 aCallback(newChannel);
4318
4319 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
4320 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
4321
4322 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4323
4324 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4325 AutoRedirectVetoNotifier notifier(this, rv);
4326
4327 /* Remove the async call to ContinueAsyncRedirectChannelToURI().
4328 * It is called directly by our callers upon return (to clean up
4329 * the failed redirect). */
4330 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
4331 }
4332
4333 return rv;
4334}
4335
4336nsresult nsHttpChannel::ContinueAsyncRedirectChannelToURI(nsresult rv) {
4337 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)
;
4338
4339 // Since we handle mAPIRedirectTo uri also after on-examine-response handler
4340 // rather drop it here to avoid any redirect loops, even just hypothetical.
4341 mAPIRedirectTo = Nothing();
4342
4343 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4344 rv = OpenRedirectChannel(rv);
4345 }
4346
4347 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4348 // Cancel the channel here, the update to https had been vetoed
4349 // but from the security reasons we have to discard the whole channel
4350 // load.
4351 Cancel(rv);
4352 }
4353
4354 if (mLoadGroup) {
4355 mLoadGroup->RemoveRequest(this, nullptr, mStatus);
4356 }
4357
4358 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && !mCachePump && !mTransactionPump) {
4359 // We have to manually notify the listener because there is not any pump
4360 // that would call our OnStart/StopRequest after resume from waiting for
4361 // the redirect callback.
4362 DoNotifyListener();
4363 }
4364
4365 return rv;
4366}
4367
4368nsresult nsHttpChannel::OpenRedirectChannel(nsresult rv) {
4369 AutoRedirectVetoNotifier notifier(this, rv);
4370
4371 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4372
4373 if (!mRedirectChannel) {
4374 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)
4375 "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)
;
4376 return NS_ERROR_FAILURE;
4377 }
4378
4379 // Make sure to do this after we received redirect veto answer,
4380 // i.e. after all sinks had been notified
4381 mRedirectChannel->SetOriginalURI(mOriginalURI);
4382
4383 // open new channel
4384 rv = mRedirectChannel->AsyncOpen(mListener);
4385
4386 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"
, 4386); return rv; } } while (false)
;
4387
4388 mStatus = NS_BINDING_REDIRECTED;
4389
4390 notifier.RedirectSucceeded();
4391
4392 ReleaseListeners();
4393
4394 return NS_OK;
4395}
4396
4397nsresult nsHttpChannel::AsyncDoReplaceWithProxy(nsIProxyInfo* pi) {
4398 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)
;
4399 nsresult rv;
4400
4401 nsCOMPtr<nsIChannel> newChannel;
4402 rv = gHttpHandler->NewProxiedChannel(mURI, pi, mProxyResolveFlags, mProxyURI,
4403 mLoadInfo, getter_AddRefs(newChannel));
4404 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4405
4406 uint32_t flags = nsIChannelEventSink::REDIRECT_INTERNAL;
4407
4408 rv = SetupReplacementChannel(mURI, newChannel, true, flags);
4409 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4410
4411 // Inform consumers about this fake redirect
4412 mRedirectChannel = newChannel;
4413
4414 PushRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
4415 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags);
4416
4417 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
4418
4419 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4420 AutoRedirectVetoNotifier notifier(this, rv);
4421 PopRedirectAsyncFunc(&nsHttpChannel::OpenRedirectChannel);
4422 }
4423
4424 return rv;
4425}
4426
4427nsresult nsHttpChannel::ResolveProxy() {
4428 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)
;
4429
4430 nsresult rv;
4431
4432 nsCOMPtr<nsIProtocolProxyService> pps;
4433 pps = mozilla::components::ProtocolProxy::Service(&rv);
4434 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4435
4436 // using the nsIProtocolProxyService2 allows a minor performance
4437 // optimization, but if an add-on has only provided the original interface
4438 // then it is ok to use that version.
4439 nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
4440 if (pps2) {
4441 rv = pps2->AsyncResolve2(this, mProxyResolveFlags, this, nullptr,
4442 getter_AddRefs(mProxyRequest));
4443 } else {
4444 rv = pps->AsyncResolve(static_cast<nsIChannel*>(this), mProxyResolveFlags,
4445 this, nullptr, getter_AddRefs(mProxyRequest));
4446 }
4447
4448 return rv;
4449}
4450
4451bool nsHttpChannel::ResponseWouldVary(nsICacheEntry* entry) {
4452 nsresult rv;
4453 nsAutoCString buf, metaKey;
4454 (void)mCachedResponseHead->GetHeader(nsHttp::Vary, buf);
4455
4456 constexpr auto prefix = "request-"_ns;
4457
4458 // enumerate the elements of the Vary header...
4459 for (const nsACString& token :
4460 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4461 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)
4462 ("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)
4463 "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)
4464 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)
;
4465 //
4466 // if "*", then assume response would vary. technically speaking,
4467 // "Vary: header, *" is not permitted, but we allow it anyways.
4468 //
4469 // We hash values of cookie-headers for the following reasons:
4470 //
4471 // 1- cookies can be very large in size
4472 //
4473 // 2- cookies may contain sensitive information. (for parity with
4474 // out policy of not storing Set-cookie headers in the cache
4475 // meta data, we likewise do not want to store cookie headers
4476 // here.)
4477 //
4478 if (token.EqualsLiteral("*")) {
4479 return true; // if we encounter this, just get out of here
4480 }
4481
4482 // build cache meta data key...
4483 metaKey = prefix + token;
4484
4485 // check the last value of the given request header to see if it has
4486 // since changed. if so, then indeed the cached response is invalid.
4487 nsCString lastVal;
4488 entry->GetMetaDataElement(metaKey.get(), getter_Copies(lastVal));
4489 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)
4490 ("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)
4491 "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)
4492 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)
;
4493
4494 // Look for value of "Cookie" in the request headers
4495 nsHttpAtom atom = nsHttp::ResolveAtom(token);
4496 nsAutoCString newVal;
4497 bool hasHeader = NS_SUCCEEDED(mRequestHead.GetHeader(atom, newVal))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(atom, newVal))), 1)))
;
4498 if (!lastVal.IsEmpty()) {
4499 // value for this header in cache, but no value in request
4500 if (!hasHeader) {
4501 return true; // yes - response would vary
4502 }
4503
4504 // If this is a cookie-header, stored metadata is not
4505 // the value itself but the hash. So we also hash the
4506 // outgoing value here in order to compare the hashes
4507 nsAutoCString hash;
4508 if (atom == nsHttp::Cookie) {
4509 rv = Hash(newVal.get(), hash);
4510 // If hash failed, be conservative (the cached hash
4511 // exists at this point) and claim response would vary
4512 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return true;
4513 newVal = std::move(hash);
4514
4515 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)
4516 ("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)
4517 "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)
4518 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)
;
4519 }
4520
4521 if (!newVal.Equals(lastVal)) {
4522 return true; // yes, response would vary
4523 }
4524
4525 } else if (hasHeader) { // old value is empty, but newVal is set
4526 return true;
4527 }
4528 }
4529
4530 return false;
4531}
4532
4533// Remove an entry from Vary header, if it exists
4534void RemoveFromVary(nsHttpResponseHead* aResponseHead,
4535 const nsACString& aRemove) {
4536 nsAutoCString buf;
4537 (void)aResponseHead->GetHeader(nsHttp::Vary, buf);
4538
4539 bool remove = false;
4540 for (const nsACString& token :
4541 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4542 if (token.EqualsIgnoreCase(aRemove)) {
4543 // Need to build a new string without aRemove
4544 remove = true;
4545 break;
4546 }
4547 }
4548 if (!remove) {
4549 return;
4550 }
4551 nsAutoCString newValue;
4552 for (const nsACString& token :
4553 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
4554 if (!token.EqualsIgnoreCase(aRemove)) {
4555 if (!newValue.IsEmpty()) {
4556 newValue += ","_ns;
4557 }
4558 newValue += token;
4559 }
4560 }
4561 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)
4562 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)
;
4563 (void)aResponseHead->SetHeaderOverride(nsHttp::Vary, newValue);
4564}
4565
4566// We need to have an implementation of this function just so that we can keep
4567// all references to mCallOnResume of type nsHttpChannel: it's not OK in C++
4568// to set a member function ptr to a base class function.
4569void nsHttpChannel::HandleAsyncAbort() {
4570 HttpAsyncAborter<nsHttpChannel>::HandleAsyncAbort();
4571}
4572
4573//-----------------------------------------------------------------------------
4574// nsHttpChannel <byte-range>
4575//-----------------------------------------------------------------------------
4576
4577bool nsHttpChannel::IsResumable(int64_t partialLen, int64_t contentLength,
4578 bool ignoreMissingPartialLen) const {
4579 bool hasContentEncoding =
4580 mCachedResponseHead->HasHeader(nsHttp::Content_Encoding);
4581
4582 nsAutoCString etag;
4583 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, etag);
4584 bool hasWeakEtag = !etag.IsEmpty() && StringBeginsWith(etag, "W/"_ns);
4585
4586 return (partialLen < contentLength) &&
4587 (partialLen > 0 || ignoreMissingPartialLen) && !hasContentEncoding &&
4588 !hasWeakEtag && mCachedResponseHead->IsResumable() &&
4589 !LoadCustomConditionalRequest() && !mCachedResponseHead->NoStore();
4590}
4591
4592nsresult nsHttpChannel::MaybeSetupByteRangeRequest(
4593 int64_t partialLen, int64_t contentLength, bool ignoreMissingPartialLen) {
4594 // Be pesimistic
4595 StoreIsPartialRequest(false);
4596
4597 if (!IsResumable(partialLen, contentLength, ignoreMissingPartialLen)) {
4598 return NS_ERROR_NOT_RESUMABLE;
4599 }
4600
4601 // looks like a partial entry we can reuse; add If-Range
4602 // and Range headers.
4603 nsresult rv = SetupByteRangeRequest(partialLen);
4604 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4605 // Make the request unconditional again.
4606 UntieByteRangeRequest();
4607 }
4608
4609 return rv;
4610}
4611
4612nsresult nsHttpChannel::SetupByteRangeRequest(int64_t partialLen) {
4613 // cached content has been found to be partial, add necessary request
4614 // headers to complete cache entry.
4615
4616 // use strongest validator available...
4617 nsAutoCString val;
4618 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, val);
4619 if (val.IsEmpty()) {
4620 (void)mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
4621 }
4622 if (val.IsEmpty()) {
4623 // if we hit this code it means mCachedResponseHead->IsResumable() is
4624 // either broken or not being called.
4625 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"
, 4625); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no cache validator" ")"); do { MOZ_CrashSequence
(__null, 4625); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4626 StoreIsPartialRequest(false);
4627 return NS_ERROR_FAILURE;
4628 }
4629
4630 char buf[64];
4631 SprintfLiteral(buf, "bytes=%" PRId64"l" "d" "-", partialLen);
4632
4633 DebugOnly<nsresult> rv{};
4634 rv = mRequestHead.SetHeader(nsHttp::Range, nsDependentCString(buf));
4635 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"
, 4635); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4635); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4636 rv = mRequestHead.SetHeader(nsHttp::If_Range, val);
4637 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"
, 4637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4637); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4638 StoreIsPartialRequest(true);
4639
4640 return NS_OK;
4641}
4642
4643void nsHttpChannel::UntieByteRangeRequest() {
4644 DebugOnly<nsresult> rv{};
4645 rv = mRequestHead.ClearHeader(nsHttp::Range);
4646 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"
, 4646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 4646); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4647 rv = mRequestHead.ClearHeader(nsHttp::If_Range);
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}
4650
4651nsresult nsHttpChannel::ProcessPartialContent(
4652 const std::function<nsresult(nsHttpChannel*, nsresult)>&
4653 aContinueProcessResponseFunc) {
4654 // ok, we've just received a 206
4655 //
4656 // we need to stream whatever data is in the cache out first, and then
4657 // pick up whatever data is on the wire, writing it into the cache.
4658
4659 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)
;
4660
4661 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"
, 4661); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4662 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"
, 4662); return NS_ERROR_NOT_INITIALIZED; } } while (false)
;
4663
4664 // Check if the content-encoding we now got is different from the one we
4665 // got before
4666 nsAutoCString contentEncoding, cachedContentEncoding;
4667 // It is possible that there is not such headers
4668 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
4669 (void)mCachedResponseHead->GetHeader(nsHttp::Content_Encoding,
4670 cachedContentEncoding);
4671 if (nsCRT::strcasecmp(contentEncoding.get(), cachedContentEncoding.get()) !=
4672 0) {
4673 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
4674 return CallOnStartRequest();
4675 }
4676
4677 nsresult rv;
4678
4679 int64_t cachedContentLength = mCachedResponseHead->ContentLength();
4680 int64_t entitySize = mResponseHead->TotalEntitySize();
4681
4682 nsAutoCString contentRange;
4683 (void)mResponseHead->GetHeader(nsHttp::Content_Range, contentRange);
4684 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)
4685 ("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)
4686 "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)
4687 ", 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)
4688 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)
4689 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)
;
4690
4691 if ((entitySize >= 0) && (cachedContentLength >= 0) &&
4692 (entitySize != cachedContentLength)) {
4693 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)
4694 ("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)
4695 "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)
4696 "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)
4697 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
4698
4699 mCacheEntry->AsyncDoom(nullptr);
4700 Cancel(NS_ERROR_CORRUPTED_CONTENT);
4701 return CallOnStartRequest();
4702 }
4703
4704 if (LoadConcurrentCacheAccess()) {
4705 // We started to read cached data sooner than its write has been done.
4706 // But the concurrent write has not finished completely, so we had to
4707 // do a range request. Now let the content coming from the network
4708 // be presented to consumers and also stored to the cache entry.
4709
4710 rv = InstallCacheListener(mLogicalOffset);
4711 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4712 } else {
4713 // suspend the current transaction
4714 rv = mTransactionPump->Suspend();
4715 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4716 }
4717
4718 // merge any new headers with the cached response headers
4719 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
4720
4721 // update the cached response head
4722 nsAutoCString head;
4723 mCachedResponseHead->Flatten(head, true);
4724 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
4725 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4726
4727 // make the cached response be the current response
4728 mResponseHead = std::move(mCachedResponseHead);
4729
4730 UpdateInhibitPersistentCachingFlag();
4731
4732 rv = UpdateExpirationTime();
4733 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4734
4735 // notify observers interested in looking at a response that has been
4736 // merged with any cached headers (http-on-examine-merged-response).
4737 gHttpHandler->OnExamineMergedResponse(this);
4738
4739 if (LoadConcurrentCacheAccess()) {
4740 StoreCachedContentIsPartial(false);
4741 // Leave the ConcurrentCacheAccess flag set, we want to use it
4742 // to prevent duplicate OnStartRequest call on the target listener
4743 // in case this channel is canceled before it gets its OnStartRequest
4744 // from the http transaction.
4745 return rv;
4746 }
4747
4748 // Now we continue reading the network response.
4749 // the cached content is valid, although incomplete.
4750 StoreCachedContentIsValid(CachedContentValidity::Valid);
4751 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
4752 nsresult rv = self->ReadFromCache();
4753 return aContinueProcessResponseFunc(self, rv);
4754 });
4755}
4756
4757nsresult nsHttpChannel::OnDoneReadingPartialCacheEntry(bool* streamDone) {
4758 nsresult rv;
4759
4760 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)
;
4761
4762 // by default, assume we would have streamed all data or failed...
4763 *streamDone = true;
4764
4765 // setup cache listener to append to cache entry
4766 int64_t size;
4767 rv = mCacheEntry->GetDataSize(&size);
4768 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4769
4770 rv = InstallCacheListener(size);
4771 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4772
4773 // Entry is valid, do it now, after the output stream has been opened,
4774 // otherwise when done earlier, pending readers would consider the cache
4775 // entry still as partial (CacheEntry::GetDataSize would return the partial
4776 // data size) and consumers would do the conditional request again.
4777 rv = mCacheEntry->SetValid();
4778 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4779
4780 // need to track the logical offset of the data being sent to our listener
4781 mLogicalOffset = size;
4782
4783 // we're now completing the cached content, so we can clear this flag.
4784 // this puts us in the state of a regular download.
4785 StoreCachedContentIsPartial(false);
4786 // The cache input stream pump is finished, we do not need it any more.
4787 // (see bug 1313923)
4788 mCachePump = nullptr;
4789
4790 // resume the transaction if it exists, otherwise the pipe contained the
4791 // remaining part of the document and we've now streamed all of the data.
4792 if (mTransactionPump) {
4793 rv = mTransactionPump->Resume();
4794 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) *streamDone = false;
4795 } else {
4796 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"
, 4796); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "no transaction" ")"); do { MOZ_CrashSequence
(__null, 4796); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4797 }
4798 return rv;
4799}
4800
4801//-----------------------------------------------------------------------------
4802// nsHttpChannel <cache>
4803//-----------------------------------------------------------------------------
4804
4805bool nsHttpChannel::ShouldBypassProcessNotModified() {
4806 if (LoadCustomConditionalRequest()) {
4807 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)
;
4808 return true;
4809 }
4810
4811 if (!mDidReval) {
4812 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)
4813 ("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)
4814 "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)
;
4815 return true;
4816 }
4817
4818 return false;
4819}
4820
4821void nsHttpChannel::MaybeGenerateNELReport() {
4822 if (!StaticPrefs::network_http_network_error_logging_enabled()) {
4823 return;
4824 }
4825
4826 nsCOMPtr<nsINetworkErrorReport> report;
4827 if (nsCOMPtr<nsINetworkErrorLogging> nel =
4828 components::NetworkErrorLogging::Service()) {
4829 nel->GenerateNELReport(this, getter_AddRefs(report));
4830 }
4831
4832 mReportedNEL = true;
4833
4834 // https://www.w3.org/TR/2023/WD-network-error-logging-20231005/#deliver-a-network-report
4835 // 4. Generate a network report given these parameters:
4836 // type: network-error
4837 // url
4838 // user_agent
4839 // body
4840
4841 if (!report) {
4842 return;
4843 }
4844
4845 nsCOMPtr<nsIScriptSecurityManager> ssm = nsContentUtils::GetSecurityManager();
4846 if (!ssm) {
4847 return;
4848 }
4849
4850 nsCOMPtr<nsIPrincipal> channelPrincipal;
4851 ssm->GetChannelResultPrincipal(this, getter_AddRefs(channelPrincipal));
4852 if (!channelPrincipal) {
4853 return;
4854 }
4855
4856 nsAutoCString body;
4857 nsAutoString group;
4858 nsAutoString url;
4859
4860 report->GetBody(body);
4861 report->GetGroup(group);
4862 report->GetUrl(url);
4863
4864 nsAutoCString endpointURL;
4865 ReportingHeader::GetEndpointForReportIncludeSubdomains(
4866 group, channelPrincipal, /* includeSubdomains */ true, endpointURL);
4867 if (endpointURL.IsEmpty()) {
4868 return;
4869 }
4870
4871 ReportDeliver::ReportData data;
4872 data.mType = u"network-error"_ns;
4873 data.mGroupName = std::move(group);
4874 data.mURL = std::move(url);
4875 data.mFailures = 0;
4876 data.mCreationTime = TimeStamp::Now();
4877
4878 data.mPrincipal = std::move(channelPrincipal);
4879 data.mEndpointURL = std::move(endpointURL);
4880 data.mReportBodyJSON = std::move(body);
4881 nsAutoCString userAgent;
4882 // XXX(valentin): Should this be the potentially user set value of the header
4883 // or the current value of user_agent from http handler?
4884 (void)mRequestHead.GetHeader(nsHttp::User_Agent, userAgent);
4885 data.mUserAgent = NS_ConvertUTF8toUTF16(userAgent);
4886
4887 // Enqueue the report to be delivered by the reporting API
4888 ReportDeliver::Fetch(data);
4889}
4890
4891nsresult nsHttpChannel::ProcessNotModified(
4892 const std::function<nsresult(nsHttpChannel*, nsresult)>&
4893 aContinueProcessResponseFunc) {
4894 nsresult rv;
4895
4896 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)
;
4897
4898 // Assert ShouldBypassProcessNotModified() has been checked before call to
4899 // ProcessNotModified().
4900 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"
, 4900); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!ShouldBypassProcessNotModified()"
")"); do { MOZ_CrashSequence(__null, 4900); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4901
4902 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", 4902
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedResponseHead"
")"); do { MOZ_CrashSequence(__null, 4902); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4903 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"
, 4903); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 4903); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4904 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", 4904
); return NS_ERROR_UNEXPECTED; } } while (false)
;
4905
4906 // If the 304 response contains a Last-Modified different than the
4907 // one in our cache that is pretty suspicious and is, in at least the
4908 // case of bug 716840, a sign of the server having previously corrupted
4909 // our cache with a bad response. Take the minor step here of just dooming
4910 // that cache entry so there is a fighting chance of getting things on the
4911 // right track.
4912
4913 nsAutoCString lastModifiedCached;
4914 nsAutoCString lastModified304;
4915
4916 rv =
4917 mCachedResponseHead->GetHeader(nsHttp::Last_Modified, lastModifiedCached);
4918 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4919 rv = mResponseHead->GetHeader(nsHttp::Last_Modified, lastModified304);
4920 }
4921
4922 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !lastModified304.Equals(lastModifiedCached)) {
4923 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)
4924 ("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)
4925 "[%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)
4926 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)
;
4927
4928 mCacheEntry->AsyncDoom(nullptr);
4929 glean::http::cache_lm_inconsistent
4930 .EnumGet(glean::http::CacheLmInconsistentLabel::eTrue)
4931 .Add();
4932 }
4933
4934 // merge any new headers with the cached response headers
4935 mCachedResponseHead->UpdateHeaders(mResponseHead.get());
4936
4937 // update the cached response head
4938 nsAutoCString head;
4939 mCachedResponseHead->Flatten(head, true);
4940 rv = mCacheEntry->SetMetaDataElement("response-head", head.get());
4941 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4942
4943 if (LoadUsedNetwork() && !mReportedNEL) {
4944 MaybeGenerateNELReport();
4945 }
4946
4947 // make the cached response be the current response
4948 mResponseHead = std::move(mCachedResponseHead);
4949
4950 UpdateInhibitPersistentCachingFlag();
4951
4952 rv = UpdateExpirationTime();
4953 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4954
4955 rv = AddCacheEntryHeaders(mCacheEntry, false);
4956 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4957
4958 // notify observers interested in looking at a reponse that has been
4959 // merged with any cached headers
4960 gHttpHandler->OnExamineMergedResponse(this);
4961
4962 StoreCachedContentIsValid(CachedContentValidity::Valid);
4963
4964 // Tell other consumers the entry is OK to use
4965 rv = mCacheEntry->SetValid();
4966 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
4967
4968 return CallOrWaitForResume([aContinueProcessResponseFunc](auto* self) {
4969 nsresult rv = self->ReadFromCache();
4970 return aContinueProcessResponseFunc(self, rv);
4971 });
4972}
4973
4974// Determines if a request is a byte range request for a subrange,
4975// i.e. is a byte range request, but not a 0- byte range request.
4976static bool IsSubRangeRequest(nsHttpRequestHead& aRequestHead) {
4977 nsAutoCString byteRange;
4978 if (NS_FAILED(aRequestHead.GetHeader(nsHttp::Range, byteRange))((bool)(__builtin_expect(!!(NS_FAILED_impl(aRequestHead.GetHeader
(nsHttp::Range, byteRange))), 0)))
) {
4979 return false;
4980 }
4981
4982 if (byteRange.EqualsLiteral("bytes=0-")) {
4983#ifndef ANDROID
4984 glean::network::byte_range_request.Get("cacheable"_ns).Add(1);
4985#endif
4986 return false;
4987 }
4988#ifndef ANDROID
4989 glean::network::byte_range_request.Get("not_cacheable"_ns).Add(1);
4990#endif
4991 return true;
4992}
4993
4994nsresult nsHttpChannel::OpenCacheEntry(bool isHttps) {
4995 // Drop this flag here
4996 StoreConcurrentCacheAccess(0);
4997
4998 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)
;
4999
5000 // make sure we're not abusing this function
5001 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"
, 5001); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheEntry"
") (" "cache entry already open" ")"); do { MOZ_CrashSequence
(__null, 5001); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5002 if (!mRequestHead.IsGet() && !mRequestHead.IsHead() &&
5003 !mRequestHead.IsPost() && !mRequestHead.IsPatch()) {
5004 // don't use the cache for other types of requests
5005 return NS_OK;
5006 }
5007
5008 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", 5008
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPostID > 0" ")"
); do { MOZ_CrashSequence(__null, 5008); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5009
5010 return OpenCacheEntryInternal(isHttps);
5011}
5012
5013nsresult nsHttpChannel::OpenCacheEntryInternal(bool isHttps) {
5014 nsresult rv;
5015
5016 if (LoadResuming()) {
5017 // We don't support caching for requests initiated
5018 // via nsIResumableChannel.
5019 return NS_OK;
5020 }
5021
5022 // Don't cache byte range requests which are subranges, only cache 0-
5023 // byte range requests.
5024 if (IsSubRangeRequest(mRequestHead)) {
5025 return NS_OK;
5026 }
5027
5028 // Handle correctly WaitForCacheEntry
5029 AutoCacheWaitFlags waitFlags(this);
5030
5031 nsAutoCString cacheKey;
5032
5033 nsCOMPtr<nsICacheStorage> cacheStorage;
5034 mCacheEntryURI = mURI;
5035
5036 uint32_t cacheEntryOpenFlags;
5037 bool offline = gIOService->IsOffline();
5038
5039 RefPtr<mozilla::dom::BrowsingContext> bc;
5040 mLoadInfo->GetBrowsingContext(getter_AddRefs(bc));
5041
5042 nsAutoCString cacheControlRequestHeader;
5043 (void)mRequestHead.GetHeader(nsHttp::Cache_Control,
5044 cacheControlRequestHeader);
5045 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
5046 if (cacheControlRequest.NoStore()) {
5047 return NS_OK;
5048 }
5049
5050 bool forceOffline = bc && bc->Top()->GetForceOffline();
5051 if (offline || (mLoadFlags & INHIBIT_CACHING) || forceOffline) {
5052 if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
&&
5053 !offline && !forceOffline) {
5054 return NS_OK;
5055 }
5056 cacheEntryOpenFlags = nsICacheStorage::OPEN_READONLY;
5057 StoreCacheEntryIsReadOnly(true);
5058 } else if (BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
) {
5059 cacheEntryOpenFlags = nsICacheStorage::OPEN_TRUNCATE;
5060 } else {
5061 cacheEntryOpenFlags =
5062 nsICacheStorage::OPEN_NORMALLY | nsICacheStorage::CHECK_MULTITHREADED;
5063 }
5064
5065 // Remember the request is a custom conditional request so that we can
5066 // process any 304 response correctly.
5067 StoreCustomConditionalRequest(
5068 mRequestHead.HasHeader(nsHttp::If_Modified_Since) ||
5069 mRequestHead.HasHeader(nsHttp::If_None_Match) ||
5070 mRequestHead.HasHeader(nsHttp::If_Unmodified_Since) ||
5071 mRequestHead.HasHeader(nsHttp::If_Match) ||
5072 mRequestHead.HasHeader(nsHttp::If_Range));
5073
5074 rv = GetCacheStorage(getter_AddRefs(cacheStorage));
5075 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"
, 5075); return rv; } } while (false)
;
5076
5077 if ((mClassOfService.Flags() & nsIClassOfService::Leader) ||
5078 (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)) {
5079 cacheEntryOpenFlags |= nsICacheStorage::OPEN_PRIORITY;
5080 }
5081
5082 // Only for backward compatibility with the old cache back end.
5083 // When removed, remove the flags and related code snippets.
5084 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
5085 cacheEntryOpenFlags |= nsICacheStorage::OPEN_BYPASS_IF_BUSY;
5086 }
5087
5088 if (mPostID) {
5089 mCacheIdExtension.AppendInt(mPostID);
5090 }
5091 if (LoadIsTRRServiceChannel()) {
5092 mCacheIdExtension.Append("TRR");
5093 }
5094 if (mRequestHead.IsHead()) {
5095 mCacheIdExtension.Append("HEAD");
5096 }
5097 bool isThirdParty = false;
5098 if (StaticPrefs::network_fetch_cache_partition_cross_origin() &&
5099 (NS_FAILED(mLoadInfo->TriggeringPrincipal()->IsThirdPartyChannel(((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
5100 this, &isThirdParty))((bool)(__builtin_expect(!!(NS_FAILED_impl(mLoadInfo->TriggeringPrincipal
()->IsThirdPartyChannel( this, &isThirdParty))), 0)))
||
5101 isThirdParty) &&
5102 (mLoadInfo->InternalContentPolicyType() == nsIContentPolicy::TYPE_FETCH ||
5103 mLoadInfo->InternalContentPolicyType() ==
5104 nsIContentPolicy::TYPE_XMLHTTPREQUEST ||
5105 mLoadInfo->InternalContentPolicyType() ==
5106 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_ASYNC ||
5107 mLoadInfo->InternalContentPolicyType() ==
5108 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_SYNC)) {
5109 mCacheIdExtension.Append("FETCH");
5110 }
5111
5112 mCacheOpenWithPriority = cacheEntryOpenFlags & nsICacheStorage::OPEN_PRIORITY;
5113 mCacheQueueSizeWhenOpen =
5114 CacheStorageService::CacheQueueSize(mCacheOpenWithPriority);
5115
5116 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"
, 5116); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 5116); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
5117 rv = cacheStorage->AsyncOpenURI(mCacheEntryURI, mCacheIdExtension,
5118 cacheEntryOpenFlags, this);
5119 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"
, 5119); return rv; } } while (false)
;
5120
5121 waitFlags.Keep(WAIT_FOR_CACHE_ENTRY);
5122
5123 return NS_OK;
5124}
5125
5126// We asked the cache for mCacheEntryURI, but the entry we got back may be
5127// stored under a different URL: on an exact-key miss the cache falls back to a
5128// No-Vary-Search secondary lookup, which can return a sibling entry whose URL
5129// is equivalent to ours under its No-Vary-Search header. Record which of the
5130// two happened, so that later code can tell whether the entry it holds is
5131// really ours to write to.
5132void nsHttpChannel::NoteCacheEntryKeyMatch(nsICacheEntry* aEntry) {
5133 StoreCacheEntryIsNoVarySearchMatch(false);
5134
5135 if (!aEntry || !mCacheEntryURI) {
5136 return;
5137 }
5138
5139 // Normalize the same way CacheStorage::AsyncOpenURI did to build the key.
5140 nsCOMPtr<nsIURI> noRefURI;
5141 nsAutoCString spec;
5142 if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetURIWithoutRef
(mCacheEntryURI, getter_AddRefs(noRefURI)))), 0)))
5143 NS_GetURIWithoutRef(mCacheEntryURI, getter_AddRefs(noRefURI)))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_GetURIWithoutRef
(mCacheEntryURI, getter_AddRefs(noRefURI)))), 0)))
||
5144 NS_FAILED(noRefURI->GetAsciiSpec(spec))((bool)(__builtin_expect(!!(NS_FAILED_impl(noRefURI->GetAsciiSpec
(spec))), 0)))
) {
5145 return;
5146 }
5147
5148 nsAutoCString key;
5149 if (NS_FAILED(aEntry->GetKey(key))((bool)(__builtin_expect(!!(NS_FAILED_impl(aEntry->GetKey(
key))), 0)))
) {
5150 return;
5151 }
5152
5153 if (!key.Equals(spec)) {
5154 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)
5155 ("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)
5156 "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)
5157 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)
;
5158 StoreCacheEntryIsNoVarySearchMatch(true);
5159 }
5160}
5161
5162// Picks the storage matching the channel's persistence flags as they stand
5163// right now. Called both when first opening the entry and when replacing an
5164// alias entry later, by which point a no-store response may have set
5165// INHIBIT_PERSISTENT_CACHING and the replacement must be memory-only.
5166nsresult nsHttpChannel::GetCacheStorage(nsICacheStorage** aStorage) {
5167 nsCOMPtr<nsICacheStorageService> service(components::CacheStorage::Service());
5168 if (!service) {
5169 return NS_ERROR_NOT_AVAILABLE;
5170 }
5171
5172 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
5173 if (!info) {
5174 return NS_ERROR_FAILURE;
5175 }
5176
5177 if (mLoadFlags & INHIBIT_PERSISTENT_CACHING) {
5178 return service->MemoryCacheStorage(info, // ? choose app cache as well...
5179 aStorage);
5180 }
5181 if (LoadPinCacheContent()) {
5182 return service->PinningCacheStorage(info, aStorage);
5183 }
5184 return service->DiskCacheStorage(info, aStorage);
5185}
5186
5187// Called before anything is written to mCacheEntry. When the entry we hold was
5188// found through No-Vary-Search it is stored under a different URL, and this
5189// response describes mCacheEntryURI only, so writing to it would put our
5190// content under someone else's key. Open a fresh entry of our own instead.
5191// Releasing the last handle on the borrowed entry reverts it from REVALIDATING
5192// back to READY, leaving its own representation untouched.
5193nsresult nsHttpChannel::MaybeReplaceNoVarySearchAliasEntry() {
5194 if (!LoadCacheEntryIsNoVarySearchMatch() || !mCacheEntry ||
5195 LoadCacheEntryIsReadOnly()) {
5196 return NS_OK;
5197 }
5198
5199 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)
;
5200
5201 nsCOMPtr<nsICacheStorage> storage;
5202 nsresult rv = GetCacheStorage(getter_AddRefs(storage));
5203 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5204 rv = storage->OpenTruncate(mCacheEntryURI, mCacheIdExtension,
5205 getter_AddRefs(mCacheEntry));
5206 }
5207
5208 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5209 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)
5210 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)
;
5211 mCacheEntry = nullptr;
5212 return rv;
5213 }
5214
5215 // We now hold an entry keyed on mCacheEntryURI, so it is ours to write to.
5216 StoreCacheEntryIsNoVarySearchMatch(false);
5217 StoreCacheEntryIsWriteOnly(true);
5218 // The alt-data belonged to the entry we just let go of.
5219 mAvailableCachedAltDataType.Truncate();
5220 StoreDeliveringAltData(false);
5221
5222 return NS_OK;
5223}
5224
5225nsresult nsHttpChannel::CheckPartial(nsICacheEntry* aEntry, int64_t* aSize,
5226 int64_t* aContentLength) {
5227 return nsHttp::CheckPartial(
5228 aEntry, aSize, aContentLength,
5229 mCachedResponseHead ? mCachedResponseHead.get() : mResponseHead.get());
5230}
5231
5232void nsHttpChannel::UntieValidationRequest() {
5233 DebugOnly<nsresult> rv{};
5234 // Make the request unconditional again.
5235 rv = mRequestHead.ClearHeader(nsHttp::If_Modified_Since);
5236 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"
, 5236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5236); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5237 rv = mRequestHead.ClearHeader(nsHttp::If_None_Match);
5238 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"
, 5238); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5238); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5239 rv = mRequestHead.ClearHeader(nsHttp::ETag);
5240 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"
, 5240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5240); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5241}
5242
5243NS_IMETHODIMPnsresult
5244nsHttpChannel::OnCacheEntryCheck(nsICacheEntry* entry, uint32_t* aResult) {
5245 nsresult rv = NS_OK;
5246
5247 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnCacheEntryCheck", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject5248( "nsHttpChannel::OnCacheEntryCheck"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
5248 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject5248( "nsHttpChannel::OnCacheEntryCheck"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
5249 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)
5250 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)
;
5251
5252 if (mCacheWaitTimedOut) {
5253 LOG((" cache entry check arrived after backstop timeout, declining"))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, " cache entry check arrived after backstop timeout, declining"
); } } while (0)
;
5254 *aResult = ENTRY_NOT_WANTED;
5255 return NS_OK;
5256 }
5257
5258 NoteCacheEntryKeyMatch(entry);
5259
5260 nsAutoCString cacheControlRequestHeader;
5261 (void)mRequestHead.GetHeader(nsHttp::Cache_Control,
5262 cacheControlRequestHeader);
5263 CacheControlParser cacheControlRequest(cacheControlRequestHeader);
5264
5265 if (cacheControlRequest.NoStore()) {
5266 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)
5267 ("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)
5268 "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)
;
5269 *aResult = ENTRY_NOT_WANTED;
5270 return NS_OK;
5271 }
5272
5273 // Be pessimistic: assume the cache entry has no useful data.
5274 *aResult = ENTRY_WANTED;
5275 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5276
5277 nsCString buf;
5278
5279 // Get the method that was used to generate the cached response
5280 rv = entry->GetMetaDataElement("request-method", getter_Copies(buf));
5281 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"
, 5281); return rv; } } while (false)
;
5282
5283 bool methodWasHead = buf.EqualsLiteral("HEAD");
5284 bool methodWasGet = buf.EqualsLiteral("GET");
5285
5286 if (methodWasHead) {
5287 // The cached response does not contain an entity. We can only reuse
5288 // the response if the current request is also HEAD.
5289 if (!mRequestHead.IsHead()) {
5290 *aResult = ENTRY_NOT_WANTED;
5291 return NS_OK;
5292 }
5293 }
5294 buf.Adopt(nullptr);
5295
5296 // We'll need this value in later computations...
5297 uint32_t lastModifiedTime;
5298 rv = entry->GetLastModified(&lastModifiedTime);
5299 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"
, 5299); return rv; } } while (false)
;
5300
5301 // Determine if this is the first time that this cache entry
5302 // has been accessed during this session.
5303 bool fromPreviousSession =
5304 (gHttpHandler->SessionStartTime() > lastModifiedTime);
5305
5306 // Get the cached HTTP response headers
5307 mCachedResponseHead = MakeUnique<nsHttpResponseHead>();
5308
5309 rv = nsHttp::GetHttpResponseHeadFromCacheEntry(entry,
5310 mCachedResponseHead.get());
5311 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"
, 5311); return rv; } } while (false)
;
5312
5313 // Purge stale cache entries that have dcb/dcz Content-Encoding in their
5314 // metadata. These were written by early compression dictionary code that
5315 // failed to clear Content-Encoding before writing cache metadata. The data
5316 // body is decompressed but the header is wrong; serving such entries would
5317 // cause crashes in content processes. Doom and re-fetch from network.
5318 {
5319 nsAutoCString cachedEncoding;
5320 (void)mCachedResponseHead->GetHeader(nsHttp::Content_Encoding,
5321 cachedEncoding);
5322 if (cachedEncoding.LowerCaseFindASCII("dcb") != -1 ||
5323 cachedEncoding.LowerCaseFindASCII("dcz") != -1) {
5324 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)
5325 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)
;
5326 glean::http3::stale_dcb_dcz_cache_entries_purged.Add(1);
5327 entry->AsyncDoom(nullptr);
5328 *aResult = ENTRY_NOT_WANTED;
5329 return NS_OK;
5330 }
5331 }
5332
5333 bool isCachedRedirect = WillRedirect(*mCachedResponseHead);
5334
5335 // Do not return 304 responses from the cache, and also do not return
5336 // any other non-redirect 3xx responses from the cache (see bug 759043).
5337 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"
, 5338); return NS_ERROR_ABORT; } } while (false)
5338 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"
, 5338); return NS_ERROR_ABORT; } } while (false)
;
5339
5340 if (mCachedResponseHead->NoStore() && LoadCacheEntryIsReadOnly()) {
5341 // This prevents loading no-store responses when navigating back
5342 // while the browser is set to work offline.
5343 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)
;
5344 mLoadFlags |= nsIRequest::INHIBIT_CACHING;
5345 }
5346
5347 // Don't bother to validate items that are read-only,
5348 // unless they are read-only because of INHIBIT_CACHING
5349 if ((LoadCacheEntryIsReadOnly() &&
5350 !(mLoadFlags & nsIRequest::INHIBIT_CACHING))) {
5351 int64_t size, contentLength;
5352 rv = CheckPartial(entry, &size, &contentLength);
5353 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"
, 5353); return rv; } } while (false)
;
5354
5355 if (contentLength != int64_t(-1) && contentLength != size) {
5356 *aResult = ENTRY_NOT_WANTED;
5357 return NS_OK;
5358 }
5359
5360 rv = OpenCacheInputStream(entry, true);
5361 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5362 StoreCachedContentIsValid(CachedContentValidity::Valid);
5363 }
5364 return rv;
5365 }
5366
5367 bool wantCompleteEntry = false;
5368
5369 if (!methodWasHead && !isCachedRedirect) {
5370 // If the cached content-length is set and it does not match the data
5371 // size of the cached content, then the cached response is partial...
5372 // either we need to issue a byte range request or we need to refetch
5373 // the entire document.
5374 //
5375 // We exclude redirects from this check because we (usually) strip the
5376 // entity when we store the cache entry, and even if we didn't, we
5377 // always ignore a cached redirect's entity anyway. See bug 759043.
5378 int64_t size, contentLength;
5379 rv = CheckPartial(entry, &size, &contentLength);
5380 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"
, 5380); return rv; } } while (false)
;
5381
5382 if (LoadCacheEntryIsNoVarySearchMatch() &&
5383 (size == int64_t(-1) ||
5384 (contentLength != int64_t(-1) && contentLength != size))) {
5385 // Completing this entry means appending our bytes to content stored
5386 // under a different URL, and unlike a full response we cannot divert
5387 // that to an entry of our own: the range request only makes sense
5388 // against what is already there. Refetch from scratch instead.
5389 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)
;
5390 *aResult = ENTRY_NOT_WANTED;
5391 return NS_OK;
5392 }
5393
5394 if (size == int64_t(-1)) {
5395 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)
;
5396 if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY) {
5397 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)
5398 (" 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)
5399 "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)
;
5400
5401 *aResult = ENTRY_NOT_WANTED;
5402 return NS_OK;
5403 }
5404
5405 // Ignore !(size > 0) from the resumability condition
5406 if (!IsResumable(size, contentLength, true)) {
5407 if (IsNavigation()) {
5408 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)
5409 (" 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)
5410 "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)
;
5411 *aResult = ENTRY_NOT_WANTED;
5412 return NS_OK;
5413 }
5414
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
, " wait for entry completion, " "response is not resumable"
); } } while (0)
5416 (" 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)
5417 "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)
;
5418
5419 wantCompleteEntry = true;
5420 } else {
5421 StoreConcurrentCacheAccess(1);
5422 }
5423 } else if (contentLength != int64_t(-1) && contentLength != size) {
5424 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)
5425 ("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)
5426 "[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)
5427 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)
;
5428
5429 rv = MaybeSetupByteRangeRequest(size, contentLength);
5430 StoreCachedContentIsPartial(NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest());
5431 if (LoadCachedContentIsPartial()) {
5432 rv = OpenCacheInputStream(entry, false);
5433 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5434 UntieByteRangeRequest();
5435 return rv;
5436 }
5437
5438 *aResult = ENTRY_NEEDS_REVALIDATION;
5439 return NS_OK;
5440 }
5441
5442 if (size == 0 && LoadCacheOnlyMetadata()) {
5443 // Don't break cache entry load when the entry's data size
5444 // is 0 and CacheOnlyMetadata flag is set. In that case we
5445 // want to proceed since the LOAD_ONLY_IF_MODIFIED flag is
5446 // also set.
5447 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", 5447
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadFlags & LOAD_ONLY_IF_MODIFIED"
")"); do { MOZ_CrashSequence(__null, 5447); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5448 } else {
5449 return rv;
5450 }
5451 }
5452 }
5453
5454 bool isHttps = mURI->SchemeIs("https");
5455
5456 bool doValidation = false;
5457 bool doBackgroundValidation = false;
5458 bool canAddImsHeader = true;
5459
5460 bool isForcedValid = false;
5461 entry->GetIsForcedValid(&isForcedValid);
5462
5463 bool weaklyFramed, isImmutable;
5464 nsHttp::DetermineFramingAndImmutability(entry, mCachedResponseHead.get(),
5465 isHttps, &weaklyFramed, &isImmutable);
5466
5467 // Cached entry is not the entity we request (see bug #633743)
5468 if (ResponseWouldVary(entry)) {
5469 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)
;
5470 canAddImsHeader = false;
5471 doValidation = true;
5472 } else {
5473 if (mCachedResponseHead->ExpiresInPast() ||
5474 mCachedResponseHead->MustValidateIfExpired()) {
5475 }
5476 doValidation = nsHttp::ValidationRequired(
5477 isForcedValid, mCachedResponseHead.get(), mLoadFlags,
5478 LoadAllowStaleCacheContent(), LoadForceValidateCacheContent(),
5479 isImmutable, LoadCustomConditionalRequest(), mRequestHead, entry,
5480 cacheControlRequest, fromPreviousSession, &doBackgroundValidation);
5481 }
5482
5483 nsAutoCString requestedETag;
5484 if (!doValidation &&
5485 NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::If_Match, requestedETag))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::If_Match, requestedETag))), 1)))
&&
5486 (methodWasGet || methodWasHead)) {
5487 nsAutoCString cachedETag;
5488 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, cachedETag);
5489 if (!cachedETag.IsEmpty() && (StringBeginsWith(cachedETag, "W/"_ns) ||
5490 !requestedETag.Equals(cachedETag))) {
5491 // User has defined If-Match header, if the cached entry is not
5492 // matching the provided header value or the cached ETag is weak,
5493 // force validation.
5494 doValidation = true;
5495 }
5496 }
5497
5498 // Previous error should not be propagated.
5499 rv = NS_OK;
5500
5501 if (!doValidation) {
5502 //
5503 // Check the authorization headers used to generate the cache entry.
5504 // We must validate the cache entry if:
5505 //
5506 // 1) the cache entry was generated prior to this session w/
5507 // credentials (see bug 103402).
5508 // 2) the cache entry was generated w/o credentials, but would now
5509 // require credentials (see bug 96705).
5510 //
5511 // NOTE: this does not apply to proxy authentication.
5512 //
5513 entry->GetMetaDataElement("auth", getter_Copies(buf));
5514 doValidation =
5515 (fromPreviousSession && !buf.IsEmpty()) ||
5516 (buf.IsEmpty() && mRequestHead.HasHeader(nsHttp::Authorization));
5517 }
5518
5519 // Bug #561276: We maintain a chain of cache-keys which returns cached
5520 // 3xx-responses (redirects) in order to detect cycles. If a cycle is
5521 // found, ignore the cached response and hit the net. Otherwise, use
5522 // the cached response and add the cache-key to the chain. Note that
5523 // a limited number of redirects (cached or not) is allowed and is
5524 // enforced independently of this mechanism
5525 if (!doValidation && isCachedRedirect) {
5526 nsAutoCString cacheKey;
5527 rv = GenerateCacheKey(mPostID, cacheKey);
5528 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"
, 5528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5529
5530 auto redirectedCachekeys = mRedirectedCachekeys.Lock();
5531 auto& ref = redirectedCachekeys.ref();
5532 if (!ref) {
5533 ref = MakeUnique<nsTArray<nsCString>>();
5534 } else if (ref->Contains(cacheKey)) {
5535 doValidation = true;
5536 }
5537
5538 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)
5539 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)
;
5540
5541 // Append cacheKey if not in the chain already
5542 if (!doValidation) {
5543 ref->AppendElement(cacheKey);
5544 }
5545 }
5546
5547 StoreCachedContentIsValid(!doValidation ? CachedContentValidity::Valid
5548 : CachedContentValidity::Invalid);
5549
5550 if (isForcedValid) {
5551 // Telemetry value is only useful if this was a prefetched item
5552 if (!doValidation) {
5553 // Could have gotten to a funky state with some of the if chain above
5554 // and in nsHttp::ValidationRequired. Make sure we get it right here.
5555 entry->MarkForcedValidUse();
5556 }
5557 }
5558
5559 if (doValidation) {
5560 //
5561 // now, we are definitely going to issue a HTTP request to the server.
5562 // make it conditional if possible.
5563 //
5564 // do not attempt to validate no-store content, since servers will not
5565 // expect it to be cached. (we only keep it in our cache for the
5566 // purposes of back/forward, etc.)
5567 //
5568 // the request method MUST be either GET or HEAD (see bug 175641) and
5569 // the cached response code must be < 400
5570 //
5571 // the cached content must not be weakly framed
5572 //
5573 // do not override conditional headers when consumer has defined its own
5574 if (!mCachedResponseHead->NoStore() &&
5575 (mRequestHead.IsGet() || mRequestHead.IsHead()) &&
5576 !LoadCustomConditionalRequest() && !weaklyFramed &&
5577 (mCachedResponseHead->Status() < 400)) {
5578 if (LoadConcurrentCacheAccess()) {
5579 // In case of concurrent read and also validation request we
5580 // must wait for the current writer to close the output stream
5581 // first. Otherwise, when the writer's job would have been interrupted
5582 // before all the data were downloaded, we'd have to do a range request
5583 // which would be a second request in line during this channel's
5584 // life-time. nsHttpChannel is not designed to do that, so rather
5585 // turn off concurrent read and wait for entry's completion.
5586 // Then only re-validation or range-re-validation request will go out.
5587 StoreConcurrentCacheAccess(0);
5588 // This will cause that OnCacheEntryCheck is called again with the same
5589 // entry after the writer is done.
5590 wantCompleteEntry = true;
5591 } else {
5592 nsAutoCString val;
5593 // Add If-Modified-Since header if a Last-Modified was given
5594 // and we are allowed to do this (see bugs 510359 and 269303)
5595 if (canAddImsHeader) {
5596 (void)mCachedResponseHead->GetHeader(nsHttp::Last_Modified, val);
5597 if (!val.IsEmpty()) {
5598 rv = mRequestHead.SetHeader(nsHttp::If_Modified_Since, val);
5599 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"
, 5599); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 5599); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5600 }
5601 }
5602 // Add If-None-Match header if an ETag was given in the response
5603 (void)mCachedResponseHead->GetHeader(nsHttp::ETag, val);
5604 if (!val.IsEmpty()) {
5605 rv = mRequestHead.SetHeader(nsHttp::If_None_Match, 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 mDidReval = true;
5609 }
5610 }
5611 }
5612
5613 bool valid = CachedContentIsValid();
5614 if (valid || mDidReval) {
5615 rv = OpenCacheInputStream(entry, valid);
5616 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5617 // If we can't get the entity then we have to act as though we
5618 // don't have the cache entry.
5619 if (mDidReval) {
5620 UntieValidationRequest();
5621 mDidReval = false;
5622 }
5623 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5624 }
5625 }
5626
5627 if (mDidReval) {
5628 *aResult = ENTRY_NEEDS_REVALIDATION;
5629 } else if (wantCompleteEntry) {
5630 *aResult = RECHECK_AFTER_WRITE_FINISHED;
5631 } else {
5632 *aResult = ENTRY_WANTED;
5633
5634 if (doBackgroundValidation) {
5635 PerformBackgroundCacheRevalidation();
5636 }
5637 }
5638
5639 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)
5640 ("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)
5641 "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)
5642 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)
;
5643 return rv;
5644}
5645
5646NS_IMETHODIMPnsresult
5647nsHttpChannel::OnCacheEntryAvailable(nsICacheEntry* entry, bool aNew,
5648 nsresult status) {
5649 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", 5649
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 5649); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5650
5651 nsresult rv;
5652
5653 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnCacheEntryAvailable", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject5654( "nsHttpChannel::OnCacheEntryAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
5654 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject5654( "nsHttpChannel::OnCacheEntryAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
5655 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)
5656 ("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)
5657 "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)
5658 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)
;
5659
5660 // The cache callback arrived (or we're tearing down); the backstop timer is
5661 // no longer needed.
5662 CancelCacheWaitTimer();
5663
5664 // if the channel's already fired onStopRequest, then we should ignore
5665 // this event.
5666 if (!LoadIsPending()) {
5667 mCacheInputStream.CloseAndRelease();
5668 return NS_OK;
5669 }
5670
5671 // If the backstop already fired we gave up on the cache and raced to the
5672 // network; ignore this late callback so we don't reprocess the entry.
5673 if (mCacheWaitTimedOut) {
5674 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)
5675 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
5676 mCacheInputStream.CloseAndRelease();
5677 return NS_OK;
5678 }
5679
5680 rv = OnCacheEntryAvailableInternal(entry, aNew, status);
5681 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5682 CloseCacheEntry(false);
5683 (void)AsyncAbort(rv);
5684 }
5685
5686 return NS_OK;
5687}
5688
5689nsresult nsHttpChannel::OnCacheEntryAvailableInternal(nsICacheEntry* entry,
5690 bool aNew,
5691 nsresult status) {
5692 nsresult rv;
5693
5694 if (mCanceled) {
5695 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)
5696 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)
;
5697 return mStatus;
5698 }
5699
5700 rv = OnNormalCacheEntryAvailable(entry, aNew, status);
5701
5702 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && (mLoadFlags & LOAD_ONLY_FROM_CACHE)) {
5703 return NS_ERROR_DOCUMENT_NOT_CACHED;
5704 }
5705
5706 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5707 return rv;
5708 }
5709
5710 // We may be waiting for more callbacks...
5711 if (AwaitingCacheCallbacks()) {
5712 return NS_OK;
5713 }
5714
5715 return TriggerNetwork();
5716}
5717
5718nsresult nsHttpChannel::OnNormalCacheEntryAvailable(nsICacheEntry* aEntry,
5719 bool aNew,
5720 nsresult aEntryStatus) {
5721 StoreWaitForCacheEntry(LoadWaitForCacheEntry() & ~WAIT_FOR_CACHE_ENTRY);
5722
5723 if (NS_FAILED(aEntryStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aEntryStatus)), 0)
))
|| aNew) {
5724 // Make sure this flag is dropped. It may happen the entry is doomed
5725 // between OnCacheEntryCheck and OnCacheEntryAvailable.
5726 StoreCachedContentIsValid(CachedContentValidity::Invalid);
5727
5728 // From the same reason remove any conditional headers added
5729 // in OnCacheEntryCheck.
5730 if (mDidReval) {
5731 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)
;
5732 UntieValidationRequest();
5733 mDidReval = false;
5734 }
5735
5736 if (LoadCachedContentIsPartial()) {
5737 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)
;
5738 UntieByteRangeRequest();
5739 StoreCachedContentIsPartial(false);
5740 }
5741
5742 if (mLoadFlags & LOAD_ONLY_FROM_CACHE) {
5743 // if this channel is only allowed to pull from the cache, then
5744 // we must fail if we were unable to open a cache entry for read.
5745 return NS_ERROR_DOCUMENT_NOT_CACHED;
5746 }
5747 }
5748
5749 if (NS_SUCCEEDED(aEntryStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aEntryStatus)), 1
)))
) {
5750 mCacheEntry = aEntry;
5751 StoreCacheEntryIsWriteOnly(aNew);
5752 NoteCacheEntryKeyMatch(aEntry);
5753 }
5754
5755 return NS_OK;
5756}
5757
5758// Generates the proper cache-key for this instance of nsHttpChannel
5759nsresult nsHttpChannel::GenerateCacheKey(uint32_t postID,
5760 nsACString& cacheKey) {
5761 AssembleCacheKey(mSpec.get(), postID, cacheKey);
5762 return NS_OK;
5763}
5764
5765// Assembles a cache-key from the given pieces of information and |mLoadFlags|
5766void nsHttpChannel::AssembleCacheKey(const char* spec, uint32_t postID,
5767 nsACString& cacheKey) {
5768 cacheKey.Truncate();
5769
5770 if (mLoadFlags & LOAD_ANONYMOUS) {
5771 cacheKey.AssignLiteral("anon&");
5772 }
5773
5774 if (postID) {
5775 char buf[32];
5776 SprintfLiteral(buf, "id=%x&", postID);
5777 cacheKey.Append(buf);
5778 }
5779
5780 if (!cacheKey.IsEmpty()) {
5781 cacheKey.AppendLiteral("uri=");
5782 }
5783
5784 // Strip any trailing #ref from the URL before using it as the key
5785 const char* p = strchr(spec, '#');
5786 if (p) {
5787 cacheKey.Append(spec, p - spec);
5788 } else {
5789 cacheKey.Append(spec);
5790 }
5791}
5792
5793nsresult DoUpdateExpirationTime(nsHttpChannel* aSelf,
5794 nsICacheEntry* aCacheEntry,
5795 nsHttpResponseHead* aResponseHead,
5796 uint32_t& aExpirationTime) {
5797 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", 5797
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aExpirationTime == 0"
")"); do { MOZ_CrashSequence(__null, 5797); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5798 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"
, 5798); return NS_ERROR_FAILURE; } } while (false)
;
5799
5800 nsresult rv;
5801
5802 if (!aResponseHead->MustValidate()) {
5803 // For stale-while-revalidate we use expiration time as the absolute base
5804 // for calculation of the stale window absolute end time. Hence, when the
5805 // entry may be served w/o revalidation, we need a non-zero value for the
5806 // expiration time. Let's set it to |now|, which basicly means "expired",
5807 // same as when set to 0.
5808 uint32_t now = NowInSeconds()PRTimeToSeconds(PR_Now());
5809 aExpirationTime = now;
5810
5811 uint32_t freshnessLifetime = 0;
5812
5813 rv = aResponseHead->ComputeFreshnessLifetime(&freshnessLifetime);
5814 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5815
5816 if (freshnessLifetime > 0) {
5817 uint32_t currentAge = 0;
5818
5819 rv = aResponseHead->ComputeCurrentAge(now, aSelf->GetRequestTime(),
5820 &currentAge);
5821 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
5822
5823 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)
5824 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)
;
5825
5826 if (freshnessLifetime > currentAge) {
5827 uint32_t timeRemaining = freshnessLifetime - currentAge;
5828 // be careful... now + timeRemaining may overflow
5829 if (now + timeRemaining < now) {
5830 aExpirationTime = uint32_t(-1);
5831 } else {
5832 aExpirationTime = now + timeRemaining;
5833 }
5834 }
5835 }
5836 }
5837
5838 rv = aCacheEntry->SetExpirationTime(aExpirationTime);
5839 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"
, 5839); return rv; } } while (false)
;
5840
5841 return rv;
5842}
5843
5844// UpdateExpirationTime is called when a new response comes in from the server.
5845// It updates the stored response-time and sets the expiration time on the
5846// cache entry.
5847//
5848// From section 13.2.4 of RFC2616, we compute expiration time as follows:
5849//
5850// timeRemaining = freshnessLifetime - currentAge
5851// expirationTime = now + timeRemaining
5852//
5853nsresult nsHttpChannel::UpdateExpirationTime() {
5854 uint32_t expirationTime = 0;
5855 nsresult rv = DoUpdateExpirationTime(this, mCacheEntry, mResponseHead.get(),
5856 expirationTime);
5857 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"
, 5857); return rv; } } while (false)
;
5858
5859 return NS_OK;
5860}
5861
5862nsresult nsHttpChannel::OpenCacheInputStream(nsICacheEntry* cacheEntry,
5863 bool startBuffering) {
5864 nsresult rv;
5865
5866 if (mURI->SchemeIs("https")) {
5867 rv = cacheEntry->GetSecurityInfo(getter_AddRefs(mCachedSecurityInfo));
5868 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5869 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)
5870 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)
;
5871 NS_WARNING("failed to parse security-info")NS_DebugBreak(NS_DEBUG_WARNING, "failed to parse security-info"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 5871)
;
5872 cacheEntry->AsyncDoom(nullptr);
5873 return rv;
5874 }
5875
5876 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", 5876
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedSecurityInfo"
")"); do { MOZ_CrashSequence(__null, 5876); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5877 if (!mCachedSecurityInfo) {
5878 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)
5879 ("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)
5880 "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)
5881 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)
;
5882 cacheEntry->AsyncDoom(nullptr);
5883 return NS_ERROR_UNEXPECTED; // XXX error code
5884 }
5885 }
5886
5887 // Keep the conditions below in sync with the conditions in ReadFromCache.
5888
5889 rv = NS_OK;
Value stored to 'rv' is never read
5890
5891 if (WillRedirect(*mCachedResponseHead)) {
5892 // Do not even try to read the entity for a redirect because we do not
5893 // return an entity to the application when we process redirects.
5894 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
)
;
5895 return NS_OK;
5896 }
5897
5898 if ((mLoadFlags & nsICachingChannel::LOAD_ONLY_IF_MODIFIED) &&
5899 !LoadCachedContentIsPartial()) {
5900 // For LOAD_ONLY_IF_MODIFIED, we usually don't have to deal with the
5901 // cached entity.
5902 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)
5903 ("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)
5904 "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)
;
5905 return NS_OK;
5906 }
5907
5908 // Open an input stream for the entity, so that the call to OpenInputStream
5909 // happens off the main thread.
5910 nsCOMPtr<nsIInputStream> stream;
5911
5912 // If an alternate representation was requested, try to open the alt
5913 // input stream.
5914 // If the entry has a "is-from-child" metadata, then only open the altdata
5915 // stream if the consumer is also from child.
5916 bool altDataFromChild = false;
5917 {
5918 nsCString value;
5919 rv = cacheEntry->GetMetaDataElement("alt-data-from-child",
5920 getter_Copies(value));
5921 altDataFromChild = !value.IsEmpty();
5922 }
5923
5924 nsAutoCString altDataType;
5925 (void)cacheEntry->GetAltDataType(altDataType);
5926
5927 nsAutoCString contentType;
5928 mCachedResponseHead->ContentType(contentType);
5929
5930 bool foundAltData = false;
5931 bool deliverAltData = true;
5932 if (!LoadDisableAltDataCache() && !altDataType.IsEmpty() &&
5933 !mPreferredCachedAltDataTypes.IsEmpty() &&
5934 altDataFromChild == LoadAltDataForChild()) {
5935 for (auto& pref : mPreferredCachedAltDataTypes) {
5936 if (pref.type() == altDataType &&
5937 (pref.contentType().IsEmpty() || pref.contentType() == contentType)) {
5938 foundAltData = true;
5939 deliverAltData =
5940 pref.deliverAltData() ==
5941 nsICacheInfoChannel::PreferredAlternativeDataDeliveryType::ASYNC;
5942 break;
5943 }
5944 }
5945 }
5946
5947 nsCOMPtr<nsIInputStream> altData;
5948 int64_t altDataSize = -1;
5949 if (foundAltData) {
5950 rv = cacheEntry->OpenAlternativeInputStream(altDataType,
5951 getter_AddRefs(altData));
5952 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5953 // We have succeeded.
5954 mAvailableCachedAltDataType = altDataType;
5955 StoreDeliveringAltData(deliverAltData);
5956
5957 // Set the correct data size on the channel.
5958 (void)cacheEntry->GetAltDataSize(&altDataSize);
5959 mAltDataLength = altDataSize;
5960
5961 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)
5962 ", 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)
5963 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)
;
5964
5965 if (deliverAltData) {
5966 stream = altData;
5967 }
5968 }
5969 }
5970
5971 if (!stream) {
5972 rv = cacheEntry->OpenInputStream(0, getter_AddRefs(stream));
5973 }
5974
5975 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5976 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)
5977 ("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)
5978 "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)
5979 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)
;
5980 return rv;
5981 }
5982
5983 if (startBuffering) {
5984 bool nonBlocking;
5985 rv = stream->IsNonBlocking(&nonBlocking);
5986 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && nonBlocking) startBuffering = false;
5987 }
5988
5989 if (!startBuffering) {
5990 // Bypass wrapping the input stream for the new cache back-end since
5991 // nsIStreamTransportService expects a blocking stream. Preloading of
5992 // the data must be done on the level of the cache backend, internally.
5993 //
5994 // We do not connect the stream to the stream transport service if we
5995 // have to validate the entry with the server. If we did, we would get
5996 // into a race condition between the stream transport service reading
5997 // the existing contents and the opening of the cache entry's output
5998 // stream to write the new contents in the case where we get a non-304
5999 // response.
6000 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)
6001 ("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)
6002 "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)
6003 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)
;
6004 mCacheInputStream.takeOver(stream);
6005 return rv;
6006 }
6007
6008 // Have the stream transport service start reading the entity on one of its
6009 // background threads.
6010
6011 nsCOMPtr<nsITransport> transport;
6012 nsCOMPtr<nsIInputStream> wrapper;
6013
6014 nsCOMPtr<nsIStreamTransportService> sts(
6015 components::StreamTransport::Service());
6016 rv = sts ? NS_OK : NS_ERROR_NOT_AVAILABLE;
6017 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6018 rv = sts->CreateInputTransport(stream, true, getter_AddRefs(transport));
6019 }
6020 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6021 rv = transport->OpenInputStream(0, 0, 0, getter_AddRefs(wrapper));
6022 }
6023 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6024 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)
6025 ("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)
6026 "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)
6027 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)
;
6028 } else {
6029 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)
6030 ("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)
6031 "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)
6032 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)
;
6033
6034 stream->Close();
6035 return rv;
6036 }
6037
6038 mCacheInputStream.takeOver(wrapper);
6039
6040 return NS_OK;
6041}
6042
6043// Actually process the cached response that we started to handle in CheckCache
6044// and/or StartBufferingCachedEntity.
6045nsresult nsHttpChannel::ReadFromCache(void) {
6046 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"
, 6046); return NS_ERROR_FAILURE; } } while (false)
;
6047 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"
, 6047); return NS_ERROR_FAILURE; } } while (false)
;
6048 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"
, 6048); return NS_OK; } } while (false)
; // already opened
6049
6050 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)
6051 ("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)
6052 "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)
6053 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)
;
6054
6055 if (mCachedResponseHead) mResponseHead = std::move(mCachedResponseHead);
6056
6057 UpdateInhibitPersistentCachingFlag();
6058
6059 // if we don't already have security info, try to get it from the cache
6060 // entry. there are two cases to consider here: 1) we are just reading
6061 // from the cache, or 2) this may be due to a 304 not modified response,
6062 // in which case we could have security info from a socket transport.
6063 if (!mSecurityInfo) mSecurityInfo = mCachedSecurityInfo;
6064
6065 nsresult rv;
6066
6067 // Keep the conditions below in sync with the conditions in
6068 // StartBufferingCachedEntity.
6069
6070 if (WillRedirect(*mResponseHead)) {
6071 // TODO: Bug 759040 - We should call HandleAsyncRedirect directly here,
6072 // to avoid event dispatching latency.
6073 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", 6073
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6073); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6074 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)
;
6075 return AsyncCall(&nsHttpChannel::HandleAsyncRedirect);
6076 }
6077
6078 if ((mLoadFlags & LOAD_ONLY_IF_MODIFIED) && !LoadCachedContentIsPartial()) {
6079 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)
6080 ("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)
6081 "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)
;
6082 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", 6082
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6082); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6083 // TODO: Bug 759040 - We should call HandleAsyncNotModified directly
6084 // here, to avoid event dispatching latency.
6085 return AsyncCall(&nsHttpChannel::HandleAsyncNotModified);
6086 }
6087
6088 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", 6088
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheInputStream"
")"); do { MOZ_CrashSequence(__null, 6088); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6089 if (!mCacheInputStream) {
6090 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"
, 6092); MOZ_PretendNoReturn(); } while (0)
6091 "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"
, 6092); MOZ_PretendNoReturn(); } while (0)
6092 "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"
, 6092); MOZ_PretendNoReturn(); } while (0)
;
6093 return NS_ERROR_UNEXPECTED;
6094 }
6095
6096 nsCOMPtr<nsIInputStream> inputStream = mCacheInputStream.forget();
6097
6098 rv = nsInputStreamPump::Create(getter_AddRefs(mCachePump), inputStream, 0, 0,
6099 true);
6100 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6101 inputStream->Close();
6102 return rv;
6103 }
6104
6105 rv = mCachePump->AsyncRead(this);
6106 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6107
6108 uint32_t suspendCount = mSuspendCount;
6109 if (LoadAsyncResumePending()) {
6110 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)
6111 (" 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)
6112 ", 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)
6113 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)
;
6114 ++suspendCount;
6115 }
6116 while (suspendCount--) {
6117 mCachePump->Suspend();
6118 }
6119
6120 return NS_OK;
6121}
6122
6123void nsHttpChannel::CloseCacheEntry(bool doomOnFailure) {
6124 CancelCacheWaitTimer();
6125 mCacheInputStream.CloseAndRelease();
6126
6127 if (!mCacheEntry) return;
6128
6129 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)
6130 " 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)
6131 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)
6132 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)
;
6133
6134 // If we have begun to create or replace a cache entry, and that cache
6135 // entry is not complete and not resumable, then it needs to be doomed.
6136 // Otherwise, CheckCache will make the mistake of thinking that the
6137 // partial cache entry is complete.
6138
6139 bool doom = false;
6140 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref) {
6141 // A response blocked by ORB is fully written to the cache before the block
6142 // decision is made, so it must be doomed here; otherwise it lingers as a
6143 // complete entry that a same-partition request (e.g. a navigation reusing a
6144 // prefetch) could consume.
6145 doom = true;
6146 } else if (LoadInitedCacheEntry()) {
6147 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"
, 6147); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "oops" ")"); do { MOZ_CrashSequence(__null, 6147); __attribute__
((nomerge)) ::abort(); } while (false); } } while (false)
;
6148 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) && doomOnFailure && LoadCacheEntryIsWriteOnly() &&
6149 (!mResponseHead || !mResponseHead->IsResumable())) {
6150 doom = true;
6151 }
6152 } else if (LoadCacheEntryIsWriteOnly()) {
6153 doom = true;
6154 }
6155
6156 if (doom) {
6157 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)
;
6158 mCacheEntry->AsyncDoom(nullptr);
6159 } else {
6160 // Store updated security info, makes cached EV status race less likely
6161 // (see bug 1040086). On a plain cache hit ReadFromCache() adopted the info
6162 // this very entry handed us in OpenCacheInputStream(), so storing it back
6163 // would only re-serialize the certificate chain and rewrite the entry file.
6164 if (mSecurityInfo && mSecurityInfo != mCachedSecurityInfo) {
6165 mCacheEntry->SetSecurityInfo(mSecurityInfo);
6166 }
6167
6168 // For prefetch requests without cache headers, force the cache entry
6169 // to remain valid so that subsequent navigations reuse the prefetched
6170 // response instead of re-fetching. See bug 1527334.
6171 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && mResponseHead) {
6172 if (StringBeginsWith(GetSecPurpose(), "prefetch"_ns) &&
6173 !mResponseHead->MustValidate()) {
6174 nsAutoCString expires;
6175 (void)mResponseHead->GetHeader(nsHttp::Expires, expires);
6176 nsAutoCString cacheControlHeader;
6177 (void)mResponseHead->GetHeader(nsHttp::Cache_Control,
6178 cacheControlHeader);
6179 CacheControlParser cacheControl(cacheControlHeader);
6180 uint32_t maxAge;
6181 if (!cacheControl.MaxAge(&maxAge) && expires.IsEmpty()) {
6182 uint32_t forceValidFor =
6183 StaticPrefs::network_prefetch_next_force_valid_for();
6184 if (forceValidFor > 0) {
6185 mCacheEntry->ForceValidFor(forceValidFor);
6186 }
6187 }
6188 }
6189 }
6190
6191 // ORB's JavaScript validation finishes asynchronously, after this point,
6192 // so the response may yet be blocked. Keep a reference to the committed
6193 // entry so CancelInternal() can doom it if that happens.
6194 if (mORB && mORB->IsSniffing()) {
6195 mORBValidationCacheEntry = mCacheEntry;
6196 }
6197 }
6198
6199 mCachedResponseHead = nullptr;
6200
6201 mCachePump = nullptr;
6202 // This releases the entry for other consumers to use.
6203 // We call Dismiss() in case someone still keeps a reference
6204 // to this entry handle.
6205 mCacheEntry->Dismiss();
6206 mCacheEntry = nullptr;
6207 StoreCacheEntryIsWriteOnly(false);
6208 StoreInitedCacheEntry(false);
6209}
6210
6211void nsHttpChannel::OnOpaqueResponseAllowed() {
6212 // mORBValidationCacheEntry is only ever touched on the main thread; this
6213 // relies on ORB delivering its validation verdict there.
6214 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", 6214
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 6214); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6215 // ORB allowed the response, so the entry we kept in case it had to be doomed
6216 // (see CloseCacheEntry) can stay in the cache; drop our reference to it.
6217 mORBValidationCacheEntry = nullptr;
6218}
6219
6220// Initialize the cache entry for writing.
6221// - finalize storage policy
6222// - store security info
6223// - update expiration time
6224// - store headers and other meta data
6225nsresult nsHttpChannel::InitCacheEntry() {
6226 nsresult rv;
6227
6228 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"
, 6228); return NS_ERROR_UNEXPECTED; } } while (false)
;
6229 // if only reading, nothing to be done here.
6230 if (LoadCacheEntryIsReadOnly()) return NS_OK;
6231
6232 // Don't cache the response again if already cached...
6233 if (CachedContentIsValid()) return NS_OK;
6234
6235 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)
6236 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)
;
6237
6238 // Normally already handled before the response was applied to the entry, but
6239 // recreating an alias entry would doom and rewrite another URL's entry, so
6240 // never reach Recreate() below while the flag is still set.
6241 rv = MaybeReplaceNoVarySearchAliasEntry();
6242 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return NS_OK;
6243
6244 bool recreate = !LoadCacheEntryIsWriteOnly();
6245 bool dontPersist = mLoadFlags & INHIBIT_PERSISTENT_CACHING;
6246
6247 if (!recreate && dontPersist) {
6248 // If the current entry is persistent but we inhibit peristence
6249 // then force recreation of the entry as memory/only.
6250 rv = mCacheEntry->GetPersistent(&recreate);
6251 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6252 }
6253
6254 if (recreate) {
6255 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)
6256 (" 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)
6257 "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)
;
6258 // clean the altData cache and reset this to avoid wrong content length
6259 mAvailableCachedAltDataType.Truncate();
6260 StoreDeliveringAltData(false);
6261
6262 nsCOMPtr<nsICacheEntry> currentEntry;
6263 currentEntry.swap(mCacheEntry);
6264 rv = currentEntry->Recreate(dontPersist, getter_AddRefs(mCacheEntry));
6265 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6266 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)
;
6267 return NS_OK;
6268 }
6269
6270 StoreCacheEntryIsWriteOnly(true);
6271
6272 // Since we recreated, the new entry doesn't have expiration set yet.
6273 // UpdateExpirationTime was called before ParseDictionary on the old entry,
6274 // but we need to set it on this new entry too.
6275 rv = UpdateExpirationTime();
6276 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6277 }
6278
6279 // mark this weakly framed until a response body is seen
6280 mCacheEntry->SetMetaDataElement("strongly-framed", "0");
6281
6282 rv = AddCacheEntryHeaders(mCacheEntry, false);
6283 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6284
6285 StoreInitedCacheEntry(true);
6286
6287 // Don't perform the check when writing (doesn't make sense)
6288 StoreConcurrentCacheAccess(0);
6289
6290 return NS_OK;
6291}
6292
6293void nsHttpChannel::UpdateInhibitPersistentCachingFlag() {
6294 // The no-store directive within the 'Cache-Control:' header indicates
6295 // that we must not store the response in a persistent cache.
6296 if (mResponseHead->NoStore()) {
6297 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6298 return;
6299 }
6300
6301 if (!StaticPrefs::network_cache_persist_permanent_redirects_http() &&
6302 mURI->SchemeIs("http") &&
6303 nsHttp::IsPermanentRedirect(mResponseHead->Status())) {
6304 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6305 return;
6306 }
6307
6308 // Only cache SSL content on disk if the pref is set
6309 if (!gHttpHandler->IsPersistentHttpsCachingEnabled() &&
6310 mURI->SchemeIs("https")) {
6311 mLoadFlags |= INHIBIT_PERSISTENT_CACHING;
6312 }
6313}
6314
6315nsresult DoAddCacheEntryHeaders(nsHttpChannel* self, nsICacheEntry* entry,
6316 nsHttpRequestHead* requestHead,
6317 nsHttpResponseHead* responseHead,
6318 nsITransportSecurityInfo* securityInfo,
6319 bool aModified) {
6320 nsresult rv;
6321
6322 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)
;
6323 // Store secure data in memory only
6324 if (securityInfo) {
6325 entry->SetSecurityInfo(securityInfo);
6326 }
6327
6328 // Note: if aModified == false, then we're processing a 304 Not Modified,
6329 // and we *shouldn't* have any change to the Dictionary (and won't be
6330 // replacing the DictionaryEntry, though if the Match/Match-dest/Id/Type
6331 // changed, we may need to rewrite it. XXX?
6332
6333 // Store the HTTP request method with the cache entry so we can distinguish
6334 // for example GET and HEAD responses.
6335 nsAutoCString method;
6336 requestHead->Method(method);
6337 rv = entry->SetMetaDataElement("request-method", method.get());
6338 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6339
6340 // Store the HTTP authorization scheme used if any...
6341 rv = StoreAuthorizationMetaData(entry, requestHead);
6342 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6343
6344 rv = self->UpdateCacheEntryHeaders(entry, nullptr);
6345 return rv;
6346}
6347
6348nsresult nsHttpChannel::AddCacheEntryHeaders(nsICacheEntry* entry,
6349 bool aModified) {
6350 return DoAddCacheEntryHeaders(this, entry, &mRequestHead, mResponseHead.get(),
6351 mSecurityInfo, aModified);
6352}
6353
6354nsresult nsHttpChannel::UpdateCacheEntryHeaders(nsICacheEntry* entry,
6355 const nsHttpAtom* aAtom) {
6356 nsresult rv = NS_OK;
6357
6358 // Iterate over the headers listed in the Vary response header, and
6359 // store the value of the corresponding request header so we can verify
6360 // that it has not varied when we try to re-use the cached response at
6361 // a later time. Take care to store "Cookie" headers only as hashes
6362 // due to security considerations and the fact that they can be pretty
6363 // large (bug 468426). We take care of "Vary: cookie" in ResponseWouldVary.
6364 //
6365 // NOTE: if "Vary: accept, cookie", then we will store the "accept" header
6366 // in the cache. we could try to avoid needlessly storing the "accept"
6367 // header in this case, but it doesn't seem worth the extra code to perform
6368 // the check.
6369 {
6370 nsAutoCString buf, metaKey;
6371 (void)mResponseHead->GetHeader(nsHttp::Vary, buf);
6372
6373 constexpr auto prefix = "request-"_ns;
6374
6375 for (const nsACString& token :
6376 nsCCharSeparatedTokenizer(buf, NS_HTTP_HEADER_SEP',').ToRange()) {
6377 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)
6378 ("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)
6379 "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)
6380 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)
;
6381 if (!token.EqualsLiteral("*")) {
6382 nsHttpAtom atom = nsHttp::ResolveAtom(token);
6383 if (!aAtom || atom == *aAtom) {
6384 nsAutoCString val;
6385 nsAutoCString hash;
6386 if (NS_SUCCEEDED(mRequestHead.GetHeader(atom, val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(atom, val))), 1)))
) {
6387 // If cookie-header, store a hash of the value
6388 if (atom == nsHttp::Cookie) {
6389 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)
6390 ("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)
6391 "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)
6392 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)
;
6393 rv = Hash(val.get(), hash);
6394 // If hash failed, store a string not very likely
6395 // to be the result of subsequent hashes
6396 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6397 val = "<hash failed>"_ns;
6398 } else {
6399 val = std::move(hash);
6400 }
6401
6402 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)
;
6403 }
6404
6405 // build cache meta data key and set meta data element...
6406 metaKey = prefix + token;
6407 entry->SetMetaDataElement(metaKey.get(), val.get());
6408 } else {
6409 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)
6410 ("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)
6411 "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)
6412 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)
;
6413 metaKey = prefix + token;
6414 entry->SetMetaDataElement(metaKey.get(), nullptr);
6415 }
6416 }
6417 }
6418 }
6419 }
6420 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6421 return rv;
6422 }
6423 // Store the received HTTP head with the cache entry as an element of
6424 // the meta data.
6425 nsAutoCString head;
6426 mResponseHead->Flatten(head, true);
6427 rv = entry->SetMetaDataElement("response-head", head.get());
6428 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6429 head.Truncate();
6430 mResponseHead->FlattenNetworkOriginalHeaders(head);
6431 rv = entry->SetMetaDataElement("original-response-headers", head.get());
6432 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6433
6434 // Store No-Vary-Search header in cache metadata and notify the secondary
6435 // index so variant URLs can match this entry on future cache lookups.
6436 nsAutoCString noVarySearch;
6437 if (StaticPrefs::network_cache_no_vary_search() &&
6438 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::No_Vary_Search, noVarySearch))), 1)))
6439 mResponseHead->GetHeader(nsHttp::No_Vary_Search, noVarySearch))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::No_Vary_Search, noVarySearch))), 1)))
&&
6440 !noVarySearch.IsEmpty()) {
6441 glean::network::no_vary_search_header_received.Add(1);
6442 bool parseError = false;
6443 auto data = ParseNoVarySearchHeader(noVarySearch, &parseError);
6444 glean::network::no_vary_search_rule_type
6445 .Get(NoVarySearchRuleLabel(data.paramsRule))
6446 .Add(1);
6447 if (parseError) {
6448 glean::network::no_vary_search_parse_error.Add(1);
6449 }
6450
6451 rv = entry->SetMetaDataElement("no-vary-search", noVarySearch.get());
6452 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6453 return rv;
6454 }
6455
6456 if (mCacheEntryURI) {
6457 if (auto* svc = CacheStorageService::Self()) {
6458 svc->NoteNoVarySearchEntry(entry, mCacheEntryURI);
6459 }
6460 }
6461 }
6462
6463 // Indicate we have successfully finished setting metadata on the cache
6464 // entry.
6465 return entry->MetaDataReady();
6466}
6467
6468bool nsHttpChannel::ParseDictionary(nsICacheEntry* aEntry,
6469 nsHttpResponseHead* aResponseHead,
6470 bool aModified) {
6471 nsAutoCString val;
6472 if (NS_SUCCEEDED(aResponseHead->GetHeader(nsHttp::Use_As_Dictionary, val))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aResponseHead->
GetHeader(nsHttp::Use_As_Dictionary, val))), 1)))
) {
6473 nsAutoCStringN<128> matchVal;
6474 nsAutoCStringN<64> matchIdVal;
6475 nsTArray<nsCString> matchDestItems;
6476 nsAutoCString typeVal;
6477
6478 if (!NS_ParseUseAsDictionary(val, matchVal, matchIdVal, matchDestItems,
6479 typeVal)) {
6480 return false;
6481 }
6482
6483 nsCString key;
6484 nsresult rv;
6485 if (NS_FAILED(rv = aEntry->GetKey(key))((bool)(__builtin_expect(!!(NS_FAILED_impl(rv = aEntry->GetKey
(key))), 0)))
) {
6486 return false;
6487 }
6488
6489 // Verify if the matchVal has regexp groups. If so, reject it
6490 UrlPatternGlue pattern;
6491 UrlPatternOptions options{};
6492 if (!urlpattern_parse_pattern_from_string(&matchVal, &mSpec, options,
6493 &pattern)) {
6494 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)
6495 ("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)
;
6496 return false;
6497 }
6498
6499 auto freePattern = MakeScopeExit([&] { urlpattern_pattern_free(pattern); });
6500 if (urlpattern_get_has_regexp_groups(pattern)) {
6501 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)
;
6502 return false;
6503 }
6504
6505 nsCString hash;
6506 // Available now for use
6507 RefPtr<DictionaryCache> dicts(DictionaryCache::GetInstance());
6508 if (!dicts) {
6509 // Shutdown has occurred, cannot add dictionary
6510 return false;
6511 }
6512 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)
6513 ("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)
6514 "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)
6515 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)
6516 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)
6517 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)
;
6518
6519 uint32_t expTime = 0;
6520 (void)GetCacheTokenExpirationTime(&expTime);
6521
6522 dicts->AddEntry(mURI, key, matchVal, matchDestItems, matchIdVal, Some(hash),
6523 aModified, expTime, getter_AddRefs(mDictSaving));
6524 // If this was 304 Not Modified, then we don't need the dictionary data
6525 // (though we may update the dictionary entry if the match/id/etc changed).
6526 // If this is 304, mDictSaving will be cleared by AddEntry.
6527 if (mDictSaving) {
6528 if (mDictSaving->ShouldSuspendUntilCacheRead()) {
6529 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)
;
6530 Suspend();
6531 mDictSaving->CallbackOnCacheRead([self = RefPtr(this)](nsresult) {
6532 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)
;
6533 self->Resume();
6534 });
6535 }
6536 }
6537 return true;
6538 }
6539 return true; // succeeded, no use-as-dictionary
6540}
6541
6542inline void GetAuthType(const char* challenge, nsCString& authType) {
6543 const char* p;
6544
6545 // get the challenge type
6546 if ((p = strchr(challenge, ' ')) != nullptr) {
6547 authType.Assign(challenge, p - challenge);
6548 } else {
6549 authType.Assign(challenge);
6550 }
6551}
6552
6553nsresult StoreAuthorizationMetaData(nsICacheEntry* entry,
6554 nsHttpRequestHead* requestHead) {
6555 // Not applicable to proxy authorization...
6556 nsAutoCString val;
6557 if (NS_FAILED(requestHead->GetHeader(nsHttp::Authorization, val))((bool)(__builtin_expect(!!(NS_FAILED_impl(requestHead->GetHeader
(nsHttp::Authorization, val))), 0)))
) {
6558 return NS_OK;
6559 }
6560
6561 // eg. [Basic realm="wally world"]
6562 nsAutoCString buf;
6563 GetAuthType(val.get(), buf);
6564 return entry->SetMetaDataElement("auth", buf.get());
6565}
6566
6567// Finalize the cache entry
6568// - may need to rewrite response headers if any headers changed
6569// - may need to recalculate the expiration time if any headers changed
6570// - called only for freshly written cache entries
6571nsresult nsHttpChannel::FinalizeCacheEntry() {
6572 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)
;
6573
6574 // Don't update this meta-data on 304
6575 if (LoadStronglyFramed() && !CachedContentIsValid() && mCacheEntry) {
6576 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)
6577 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
6578 mCacheEntry->SetMetaDataElement("strongly-framed", "1");
6579 }
6580
6581 if (mResponseHead && LoadResponseHeadersModified()) {
6582 // Set the expiration time for this cache entry
6583 nsresult rv = UpdateExpirationTime();
6584 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6585 }
6586 return NS_OK;
6587}
6588
6589nsresult nsHttpChannel::InstallCacheListener(int64_t offset) {
6590 return DoInstallCacheListener(false, offset);
6591}
6592
6593// Open an output stream to the cache entry and insert a listener tee into
6594// the chain of response listeners, so the data will go the cache and the
6595// normal listener chain, which often will eventually include a
6596// decompressor. If the Content-Encoding is dcb or dcz, we'll include a
6597// decompressor *before* the tee, so the cache will see decompressed data
6598// (we can't decompress dcb/dcz when reading from the cache). Also, if an
6599// entry is being used as a dictionary (Use-As-Dictionary), we want the data
6600// to in the cache to be decompressed, so we should install a decompressor
6601// before the tee as well.
6602nsresult nsHttpChannel::DoInstallCacheListener(bool aSaveDecompressed,
6603 int64_t offset) {
6604 nsresult rv;
6605
6606 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)
;
6607
6608 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"
, 6608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 6608); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6609 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", 6609
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadCacheEntryIsWriteOnly() || LoadCachedContentIsPartial()"
")"); do { MOZ_CrashSequence(__null, 6609); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6610 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"
, 6610); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mListener" ")"
); do { MOZ_CrashSequence(__null, 6610); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6611
6612 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)
;
6613
6614 // We must close the input stream first because cache entries do not
6615 // correctly handle having an output stream and input streams open at
6616 // the same time.
6617 mCacheInputStream.CloseAndRelease();
6618
6619 int64_t predictedSize = mResponseHead->TotalEntitySize();
6620 if (predictedSize != -1) {
6621 predictedSize -= offset;
6622 }
6623
6624 nsCOMPtr<nsIOutputStream> out;
6625 rv =
6626 mCacheEntry->OpenOutputStream(offset, predictedSize, getter_AddRefs(out));
6627 if (rv == NS_ERROR_NOT_AVAILABLE) {
6628 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)
;
6629 // Entry is already doomed.
6630 // This may happen when expiration time is set to past and the entry
6631 // has been removed by the background eviction logic.
6632 return NS_OK;
6633 }
6634 if (rv == NS_ERROR_FILE_TOO_BIG) {
6635 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)
6636 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
6637 mCacheEntry->AsyncDoom(nullptr);
6638 return NS_OK;
6639 }
6640 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6641
6642 if (LoadCacheOnlyMetadata()) {
6643 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
)
;
6644 // We must open and then close the output stream of the cache entry.
6645 // This way we indicate the content has been written (despite with zero
6646 // length) and the entry is now in the ready state with "having data".
6647
6648 out->Close();
6649 return NS_OK;
6650 }
6651
6652 // XXX disk cache does not support overlapped i/o yet
6653#if 0
6654 // Mark entry valid inorder to allow simultaneous reading...
6655 rv = mCacheEntry->MarkValid();
6656 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6657#endif
6658
6659 nsCOMPtr<nsIStreamListenerTee> tee =
6660 do_CreateInstance(kStreamListenerTeeCID, &rv);
6661 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6662
6663 rv = tee->Init(mListener, out, nullptr);
6664 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)
6665 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)
;
6666 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6667 mListener = tee;
6668
6669 mWritingToCache = true;
6670 // If this is Use-As-Dictionary we need to be able to read it quickly for
6671 // dictionary use, OR if it's encoded in dcb or dcz (using a dictionary),
6672 // we must decompress it before storing since we won't have the dictionary
6673 // when we go to read it out later.
6674 // In this case, we hook an nsHTTPCompressConv instance in before the tee
6675 // since we don't want to have to decompress it here and again in the content
6676 // process (if it's not dcb/dcz); if it is dcb/dcz we must decompress it
6677 // before the content process gets to see it
6678 // XXX We could recompress this with e.g. gzip to save space and improve
6679 // hitrate, at the cost of some CPU.
6680
6681 // Note: this doesn't handle cases like "dcb, gzip" or (worse?) "gzip, dcb".
6682 // We could in theory handle them.
6683 if (aSaveDecompressed) {
6684 nsCOMPtr<nsIStreamListener> listener;
6685 // otherwise we won't convert in the parent process
6686 SetApplyConversion(true);
6687 rv = DoApplyContentConversionsInternal(mListener, getter_AddRefs(listener),
6688 true, nullptr);
6689 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6690 return rv;
6691 }
6692 // Remove Available-Dictionary from Vary header if present. This
6693 // avoids us refusing to match on a future load, for example if this
6694 // dictionary was decoded from an earlier version using a dictionary
6695 // (i.e. the update jquery to new version using the old version as a
6696 // dictionary; no future load will use that old version).
6697
6698 // XXX It would be slightly more efficient to remove all at once
6699 // instead of sequentially by passing an array of strings
6700 RemoveFromVary(mResponseHead.get(), "available-dictionary"_ns);
6701 RemoveFromVary(mResponseHead.get(), "accept-encoding"_ns);
6702
6703 if (listener) {
6704 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)
6705 ("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)
;
6706 mListener = listener;
6707 mCompressListener = std::move(listener);
6708 StoreHasAppliedConversion(true);
6709
6710 } else {
6711 nsAutoCString contentEncoding;
6712 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, contentEncoding);
6713 if (contentEncoding.IsEmpty()) {
6714 // No Content-Encoding — data is already raw. Normal for dictionary
6715 // responses served without transfer encoding.
6716 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)
6717 ("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)
;
6718 } else if (mIsDictionaryCompressed) {
6719 // dcb/dcz can only be decompressed in the parent process with
6720 // the dictionary. If we can't install the decompressor, this is
6721 // fatal — the content process can't decode it.
6722 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)
6723 ("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)
6724 "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)
6725 "[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)
6726 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)
6727 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)
;
6728 Cancel(NS_ERROR_INVALID_CONTENT_ENCODING);
6729 return NS_ERROR_INVALID_CONTENT_ENCODING;
6730 } else if (mDictSaving) {
6731 // Saving a dictionary but can't install a decompressor — we'd store
6732 // compressed data with a hash computed over compressed bytes. Cancel
6733 // the dictionary save but leave Content-Encoding for downstream
6734 // decompression.
6735 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)
6736 ("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)
6737 "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)
6738 "[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)
6739 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)
6740 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)
;
6741 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"
, 6741); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "Can't save dictionary uncompressed" ")"); do { MOZ_CrashSequence
(__null, 6741); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6742 mCacheEntry->SetDictionary(nullptr);
6743 DictionaryCache::RemoveDictionary(nsCString(mDictSaving->GetURI()));
6744 mDictSaving = nullptr;
6745 }
6746 }
6747 // We may have modified Content-Encoding; make sure cache metadata
6748 // reflects that. Pass nullptr so we pick up the Vary updates above
6749 rv = UpdateCacheEntryHeaders(mCacheEntry, nullptr);
6750 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6751 mCacheEntry->AsyncDoom(nullptr);
6752 return rv;
6753 }
6754 }
6755
6756#ifdef DEBUG1
6757 // Verify that Content-Encoding was properly cleared
6758 nsAutoCString verifyEncoding;
6759 (void)mResponseHead->GetHeader(nsHttp::Content_Encoding, verifyEncoding);
6760 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"
, 6761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
") (" "Content-Encoding should have been cleared for dcb/dcz"
")"); do { MOZ_CrashSequence(__null, 6761); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6761 "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"
, 6761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!verifyEncoding.Equals(\"dcb\") && !verifyEncoding.Equals(\"dcz\")"
") (" "Content-Encoding should have been cleared for dcb/dcz"
")"); do { MOZ_CrashSequence(__null, 6761); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6762 if (aSaveDecompressed) {
6763 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"
, 6765); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6765); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6764 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"
, 6765); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6765); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6765 "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"
, 6765); AnnotateMozCrashReason("MOZ_ASSERT" "(" "verifyEncoding.IsEmpty()"
") (" "Content-Encoding should have been cleared for dictionary resources"
")"); do { MOZ_CrashSequence(__null, 6765); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6766 }
6767#endif
6768 return NS_OK;
6769}
6770
6771//-----------------------------------------------------------------------------
6772// nsHttpChannel <redirect>
6773//-----------------------------------------------------------------------------
6774
6775nsresult nsHttpChannel::SetupReplacementChannel(nsIURI* newURI,
6776 nsIChannel* newChannel,
6777 bool preserveMethod,
6778 uint32_t redirectFlags) {
6779 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)
6780 ("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)
6781 "[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)
6782 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)
;
6783
6784 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
6785 mEndMarkerAdded = true;
6786
6787 nsAutoCString requestMethod;
6788 GetRequestMethod(requestMethod);
6789
6790 int32_t priority = PRIORITY_NORMAL;
6791 GetPriority(&priority);
6792
6793 TimingStruct timings;
6794 if (mTransaction) {
6795 timings = mTransaction->Timings();
6796 }
6797
6798 uint64_t size = 0;
6799 GetEncodedBodySize(&size);
6800
6801 nsAutoCString contentType;
6802 mozilla::Maybe<mozilla::net::HttpVersion> httpVersion = Nothing();
6803 mozilla::Maybe<uint32_t> responseStatus = Nothing();
6804 if (mResponseHead) {
6805 mResponseHead->ContentType(contentType);
6806 httpVersion = Some(mResponseHead->Version());
6807 responseStatus = Some(mResponseHead->Status());
6808 }
6809
6810 RefPtr<nsIIdentChannel> newIdentChannel = do_QueryObject(newChannel);
6811 uint64_t channelId = 0;
6812 if (newIdentChannel) {
6813 channelId = newIdentChannel->ChannelId();
6814 }
6815 profiler_add_network_marker(
6816 mURI, requestMethod, priority, mChannelId,
6817 NetworkLoadType::LOAD_REDIRECT, mLastStatusReported, TimeStamp::Now(),
6818 size, mCacheDisposition, mLoadInfo->GetInnerWindowID(),
6819 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
6820 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
6821 &timings, std::move(mSource), httpVersion, responseStatus,
6822 Some(nsDependentCString(contentType.get())), newURI, redirectFlags,
6823 channelId);
6824 }
6825
6826 nsresult rv = HttpBaseChannel::SetupReplacementChannel(
6827 newURI, newChannel, preserveMethod, redirectFlags);
6828 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
6829
6830 nsAutoCString uriHost;
6831 mURI->GetAsciiHost(uriHost);
6832 // disable https-rr when encountering a downgrade from https to http.
6833 // If the host would have https-rr dns-entries, it would be misconfigured
6834 // due to giving us mixed signals:
6835 // 1. the signal to upgrade all http requests to https,
6836 // 2. but also downgrading to http on https via redirects.
6837 // Add to exclude list for that reason
6838 if (!gHttpHandler->IsHostExcludedForHTTPSRR(uriHost) &&
6839 nsHTTPSOnlyUtils::IsUpgradeDowngradeEndlessLoop(
6840 mURI, newURI, mLoadInfo,
6841 {nsHTTPSOnlyUtils::UpgradeDowngradeEndlessLoopOptions::
6842 EnforceForHTTPSRR})) {
6843 // Add the host to a excluded list because:
6844 // 1. We don't need to do the same check again.
6845 // 2. Other subresources in the same host will be also excluded.
6846 gHttpHandler->ExcludeHTTPSRRHost(uriHost);
6847 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)
;
6848 }
6849
6850 rv = CheckRedirectLimit(newURI, redirectFlags);
6851 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"
, 6851); return rv; } } while (false)
;
6852
6853 // pass on the early hint observer to be able to process `103 Early Hints`
6854 // responses after cross origin redirects
6855 if (mEarlyHintObserver) {
6856 if (RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(newChannel)) {
6857 httpChannelImpl->SetEarlyHintObserver(mEarlyHintObserver);
6858 }
6859 mEarlyHintObserver = nullptr;
6860 }
6861
6862 // We don't support redirection for WebTransport for now.
6863 mWebTransportSessionEventListener = nullptr;
6864
6865 nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel);
6866 if (!httpChannel) return NS_OK; // no other options to set
6867
6868 // convey the ApplyConversion flag (bug 91862)
6869 nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(httpChannel);
6870 if (encodedChannel) encodedChannel->SetApplyConversion(LoadApplyConversion());
6871
6872 // transfer the resume information
6873 if (LoadResuming()) {
6874 nsCOMPtr<nsIResumableChannel> resumableChannel(
6875 do_QueryInterface(newChannel));
6876 if (!resumableChannel) {
6877 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Got asked to resume, but redirected to non-resumable channel!"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 6878)
6878 "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"
, 6878)
;
6879 return NS_ERROR_NOT_RESUMABLE;
6880 }
6881 resumableChannel->ResumeAt(mStartPos, mEntityID);
6882 }
6883
6884 nsCOMPtr<nsIHttpChannelInternal> internalChannel =
6885 do_QueryInterface(newChannel, &rv);
6886 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6887 TimeStamp timestamp;
6888 rv = GetNavigationStartTimeStamp(&timestamp);
6889 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"
, 6889)
) {
6890 return rv;
6891 }
6892 if (timestamp) {
6893 (void)internalChannel->SetNavigationStartTimeStamp(timestamp);
6894 }
6895 }
6896
6897 return NS_OK;
6898}
6899
6900nsresult nsHttpChannel::AsyncProcessRedirection(uint32_t redirectType) {
6901 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)
6902 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)
;
6903
6904 nsresult rv = ProcessCrossOriginSecurityHeaders();
6905 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6906 mStatus = rv;
6907 HandleAsyncAbort();
6908 return rv;
6909 }
6910
6911 nsAutoCString location;
6912
6913 // if a location header was not given, then we can't perform the redirect,
6914 // so just carry on as though this were a normal response.
6915 if (NS_FAILED(mResponseHead->GetHeader(nsHttp::Location, location))((bool)(__builtin_expect(!!(NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Location, location))), 0)))
) {
6916 return NS_ERROR_FAILURE;
6917 }
6918
6919 // If we were told to not follow redirects automatically, then again
6920 // carry on as though this were a normal response.
6921 if (mLoadInfo->GetDontFollowRedirects()) {
6922 return NS_ERROR_FAILURE;
6923 }
6924
6925 // make sure non-ASCII characters in the location header are escaped.
6926 nsAutoCString locationBuf;
6927 if (NS_EscapeURL(location.get(), -1, esc_OnlyNonASCII | esc_Spaces,
6928 locationBuf)) {
6929 location = std::move(locationBuf);
6930 }
6931
6932 mRedirectType = redirectType;
6933
6934 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)
6935 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)
;
6936
6937 rv = CreateNewURI(location.get(), getter_AddRefs(mRedirectURI));
6938
6939 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6940 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)
;
6941 return NS_ERROR_CORRUPTED_CONTENT;
6942 }
6943
6944 if (!StaticPrefs::network_allow_redirect_to_data() &&
6945 !mLoadInfo->GetAllowInsecureRedirectToDataURI() &&
6946 mRedirectURI->SchemeIs("data")) {
6947 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)
;
6948 nsContentSecurityManager::ReportBlockedDataURI(mRedirectURI, mLoadInfo,
6949 true);
6950 return NS_ERROR_DOM_BAD_URI;
6951 }
6952
6953 // Perform the URL query string stripping for redirects. We will only strip
6954 // the query string if it is redirecting to a third-party URI in the top
6955 // level.
6956 if (StaticPrefs::privacy_query_stripping_redirect()) {
6957 ThirdPartyUtil* thirdPartyUtil = ThirdPartyUtil::GetInstance();
6958 bool isThirdPartyRedirectURI = true;
6959 thirdPartyUtil->IsThirdPartyURI(mURI, mRedirectURI,
6960 &isThirdPartyRedirectURI);
6961 if (isThirdPartyRedirectURI && mLoadInfo->GetExternalContentPolicyType() ==
6962 ExtContentPolicy::TYPE_DOCUMENT) {
6963 glean::contentblocking::query_stripping_count
6964 .EnumGet(glean::contentblocking::QueryStrippingCountLabel::eRedirect)
6965 .Add();
6966
6967 nsCOMPtr<nsIPrincipal> prin;
6968 ContentBlockingAllowList::RecomputePrincipal(
6969 mRedirectURI, mLoadInfo->GetOriginAttributes(), getter_AddRefs(prin));
6970
6971 bool isRedirectURIInAllowList = false;
6972 if (prin) {
6973 ContentBlockingAllowList::Check(prin, mPrivateBrowsing,
6974 isRedirectURIInAllowList);
6975 }
6976
6977 if (!isRedirectURIInAllowList) {
6978 nsCOMPtr<nsIURI> strippedURI;
6979
6980 nsCOMPtr<nsIURLQueryStringStripper> queryStripper;
6981 queryStripper =
6982 mozilla::components::URLQueryStringStripper::Service(&rv);
6983 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"
, 6983); return rv; } } while (false)
;
6984
6985 uint32_t numStripped;
6986
6987 rv = queryStripper->Strip(mRedirectURI, mPrivateBrowsing,
6988 getter_AddRefs(strippedURI), &numStripped);
6989 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"
, 6989); return rv; } } while (false)
;
6990
6991 if (numStripped) {
6992 mUnstrippedRedirectURI = mRedirectURI;
6993 mRedirectURI = strippedURI;
6994
6995 // Record telemetry, but only if we stripped any query params.
6996 glean::contentblocking::query_stripping_count
6997 .EnumGet(glean::contentblocking::QueryStrippingCountLabel::
6998 eStripforredirect)
6999 .Add();
7000 glean::contentblocking::query_stripping_param_count
7001 .AccumulateSingleSample(numStripped);
7002 }
7003 }
7004 }
7005 }
7006
7007 // if we have a Set-Login header, we should try to handle it here
7008 nsAutoCString setLogin;
7009 if (NS_SUCCEEDED(mResponseHead->GetHeader(nsHttp::Set_Login, setLogin))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mResponseHead->
GetHeader(nsHttp::Set_Login, setLogin))), 1)))
) {
7010 bool isDocument = mLoadInfo->GetExternalContentPolicyType() ==
7011 ExtContentPolicy::TYPE_DOCUMENT;
7012 if (isDocument) {
7013 auto ssm = nsContentUtils::GetSecurityManager();
7014 if (ssm) {
7015 nsCOMPtr<nsIPrincipal> documentPrincipal;
7016 nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
7017 this, getter_AddRefs(documentPrincipal));
7018 dom::NavigatorLogin::SetLoginStatus(documentPrincipal, setLogin);
7019 }
7020 } else {
7021 bool inThirdPartyContext = mLoadInfo->GetIsInThirdPartyContext();
7022 nsIPrincipal* loadingPrincipal = mLoadInfo->GetLoadingPrincipal();
7023 if (loadingPrincipal) {
7024 bool isSameOriginToLoadingPrincipal =
7025 loadingPrincipal->IsSameOrigin(mURI);
7026 if (!inThirdPartyContext && isSameOriginToLoadingPrincipal) {
7027 dom::NavigatorLogin::SetLoginStatus(loadingPrincipal, setLogin);
7028 }
7029 }
7030 }
7031 }
7032
7033 if (NS_WARN_IF(!mRedirectURI)NS_warn_if_impl(!mRedirectURI, "!mRedirectURI", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7033)
) {
7034 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)
;
7035 return NS_ERROR_FAILURE;
7036 }
7037
7038 return ContinueProcessRedirectionAfterFallback(NS_OK);
7039}
7040
7041nsresult nsHttpChannel::ContinueProcessRedirectionAfterFallback(nsresult rv) {
7042 // Kill the current cache entry if we are redirecting
7043 // back to ourself.
7044 bool redirectingBackToSameURI = false;
7045 if (mCacheEntry && LoadCacheEntryIsWriteOnly() &&
7046 NS_SUCCEEDED(mURI->Equals(mRedirectURI, &redirectingBackToSameURI))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mURI->Equals(mRedirectURI
, &redirectingBackToSameURI))), 1)))
&&
7047 redirectingBackToSameURI) {
7048 mCacheEntry->AsyncDoom(nullptr);
7049 }
7050
7051 // move the reference of the old location to the new one if the new
7052 // one has none.
7053 PropagateReferenceIfNeeded(mURI, mRedirectURI);
7054
7055 bool rewriteToGET =
7056 ShouldRewriteRedirectToGET(mRedirectType, mRequestHead.ParsedMethod());
7057
7058 // prompt if the method is not safe (such as POST, PUT, DELETE, ...)
7059 if (!rewriteToGET && !mRequestHead.IsSafeMethod()) {
7060 rv = PromptTempRedirect();
7061 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7062 }
7063
7064 uint32_t redirectFlags;
7065 if (nsHttp::IsPermanentRedirect(mRedirectType)) {
7066 redirectFlags = nsIChannelEventSink::REDIRECT_PERMANENT;
7067 } else {
7068 redirectFlags = nsIChannelEventSink::REDIRECT_TEMPORARY;
7069 }
7070
7071 nsCOMPtr<nsIIOService> ioService;
7072 rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
7073 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7074
7075 nsCOMPtr<nsIChannel> newChannel;
7076 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
7077 CloneLoadInfoForRedirect(mRedirectURI, redirectFlags);
7078
7079 // Propagate the unstripped redirect URI.
7080 redirectLoadInfo->SetUnstrippedURI(mUnstrippedRedirectURI);
7081
7082 rv = NS_NewChannelInternal(getter_AddRefs(newChannel), mRedirectURI,
7083 redirectLoadInfo,
7084 nullptr, // PerformanceStorage
7085 nullptr, // aLoadGroup
7086 nullptr, // aCallbacks
7087 nsIRequest::LOAD_NORMAL, ioService);
7088 // If this fails, it usually means that the URI was invalid. Treat this as if
7089 // it were a CreateNewURI failure.
7090 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"
, 7090)
) {
7091 return NS_ERROR_CORRUPTED_CONTENT;
7092 }
7093
7094 rv = SetupReplacementChannel(mRedirectURI, newChannel, !rewriteToGET,
7095 redirectFlags);
7096 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7097
7098 // verify that this is a legal redirect
7099 mRedirectChannel = newChannel;
7100
7101 PushRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
7102 rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, redirectFlags);
7103
7104 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = WaitForRedirectCallback();
7105
7106 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7107 AutoRedirectVetoNotifier notifier(this, rv);
7108 PopRedirectAsyncFunc(&nsHttpChannel::ContinueProcessRedirection);
7109 }
7110
7111 return rv;
7112}
7113
7114nsresult nsHttpChannel::ContinueProcessRedirection(nsresult rv) {
7115 AutoRedirectVetoNotifier notifier(this, rv);
7116
7117 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)
7118 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)
;
7119 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
7120
7121 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"
, 7121); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRedirectChannel"
") (" "No redirect channel?" ")"); do { MOZ_CrashSequence(__null
, 7121); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
7122
7123 // Make sure to do this after we received redirect veto answer,
7124 // i.e. after all sinks had been notified
7125 mRedirectChannel->SetOriginalURI(mOriginalURI);
7126
7127 // XXX we used to talk directly with the script security manager, but that
7128 // should really be handled by the event sink implementation.
7129
7130 // begin loading the new channel
7131 rv = mRedirectChannel->AsyncOpen(mListener);
7132 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)
;
7133 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"
, 7133); return rv; } } while (false)
;
7134
7135 // close down this channel
7136 Cancel(NS_BINDING_REDIRECTED);
7137
7138 notifier.RedirectSucceeded();
7139
7140 ReleaseListeners();
7141
7142 return NS_OK;
7143}
7144
7145//-----------------------------------------------------------------------------
7146// nsHttpChannel <auth>
7147//-----------------------------------------------------------------------------
7148
7149NS_IMETHODIMPnsresult nsHttpChannel::OnAuthAvailable() {
7150 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)
;
7151
7152 // setting mAuthRetryPending flag and resuming the transaction
7153 // triggers process of throwing away the unauthenticated data already
7154 // coming from the network
7155 mIsAuthChannel = true;
7156 mAuthRetryPending = true;
7157 StoreProxyAuthPending(false);
7158 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)
;
7159 if (mTransactionPump) {
7160 Resume();
7161 }
7162
7163 if (StaticPrefs::network_auth_use_redirect_for_retries()) {
7164 return CallOrWaitForResume(
7165 [](auto* self) { return self->RedirectToNewChannelForAuthRetry(); });
7166 }
7167
7168 return NS_OK;
7169}
7170
7171NS_IMETHODIMPnsresult nsHttpChannel::OnAuthCancelled(bool userCancel) {
7172 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)
;
7173 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"
, 7173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAuthRetryPending"
") (" "OnAuthCancelled should not be called twice" ")"); do {
MOZ_CrashSequence(__null, 7173); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
7174
7175 if (mTransactionPump) {
7176 // If the channel is trying to authenticate to a proxy and
7177 // that was canceled we cannot show the http response body
7178 // from the 40x as that might mislead the user into thinking
7179 // it was a end host response instead of a proxy reponse.
7180 // This must check explicitly whether a proxy auth was being done
7181 // because we do want to show the content if this is an error from
7182 // the origin server.
7183 if (LoadProxyAuthPending()) Cancel(NS_ERROR_PROXY_CONNECTION_REFUSED);
7184
7185 // Make sure to process security headers before calling CallOnStartRequest.
7186 nsresult rv = ProcessCrossOriginSecurityHeaders();
7187 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7188 mStatus = rv;
7189 HandleAsyncAbort();
7190 return rv;
7191 }
7192
7193 // ensure call of OnStartRequest of the current listener here,
7194 // it would not be called otherwise at all
7195 rv = CallOnStartRequest();
7196
7197 // drop mAuthRetryPending flag and resume the transaction
7198 // this resumes load of the unauthenticated content data (which
7199 // may have been canceled if we don't want to show it)
7200 mAuthRetryPending = false;
7201 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)
;
7202 Resume();
7203
7204 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) mTransactionPump->Cancel(rv);
7205 }
7206
7207 StoreProxyAuthPending(false);
7208 return NS_OK;
7209}
7210
7211NS_IMETHODIMPnsresult nsHttpChannel::CloseStickyConnection() {
7212 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)
;
7213
7214 // Require we are between OnStartRequest and OnStopRequest, because
7215 // what we do here takes effect in OnStopRequest (not reusing the
7216 // connection for next authentication round).
7217 if (!LoadIsPending()) {
7218 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)
;
7219 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7221); MOZ_PretendNoReturn(); } while (0)
7220 "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"
, 7221); MOZ_PretendNoReturn(); } while (0)
7221 "effect")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "CloseStickyConnection not called before OnStopRequest, won't have any "
"effect", "Error", "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 7221); MOZ_PretendNoReturn(); } while (0)
;
7222 return NS_ERROR_UNEXPECTED;
7223 }
7224
7225 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"
, 7225); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mTransaction"
")"); do { MOZ_CrashSequence(__null, 7225); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7226 if (!mTransaction) {
7227 return NS_ERROR_UNEXPECTED;
7228 }
7229
7230 if (!(mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
7231 mTransaction->HasStickyConnection())) {
7232 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)
;
7233 return NS_OK;
7234 }
7235
7236 mTransaction->DontReuseConnection();
7237 return NS_OK;
7238}
7239
7240NS_IMETHODIMPnsresult nsHttpChannel::ConnectionRestartable(bool aRestartable) {
7241 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)
7242 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)
;
7243 StoreAuthConnectionRestartable(aRestartable);
7244 return NS_OK;
7245}
7246
7247//-----------------------------------------------------------------------------
7248// nsHttpChannel::nsISupports
7249//-----------------------------------------------------------------------------
7250
7251NS_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; }
7252bool nsHttpChannel::DispatchRelease() {
7253 if (NS_IsMainThread()) {
7254 return false;
7255 }
7256
7257 NS_DispatchToMainThread(
7258 NewNonOwningRunnableMethod("net::nsHttpChannel::Release", this,
7259 &nsHttpChannel::Release),
7260 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
7261
7262 return true;
7263}
7264
7265NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
7266nsHttpChannel::Release() {
7267 nsrefcnt count = mRefCnt - 1;
7268 if (DispatchRelease()) {
7269 // Redispatched to the main thread.
7270 return count;
7271 }
7272
7273 NS_IMPL_RELEASE_INHERITED_GUTS(nsHttpChannel, HttpBaseChannel)nsrefcnt r = HttpBaseChannel::Release(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<nsHttpChannel>) { NS_LogRelease
((this), (r), ("nsHttpChannel")); } return r
;
7274}
7275
7276NS_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"
, 7276); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
7277 NS_INTERFACE_MAP_ENTRY(nsIRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequest>)) foundInterface = static_cast
<nsIRequest*>(this); else
7278 NS_INTERFACE_MAP_ENTRY(nsIChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIChannel>)) foundInterface = static_cast
<nsIChannel*>(this); else
7279 NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestObserver>)) foundInterface
= static_cast<nsIRequestObserver*>(this); else
7280 NS_INTERFACE_MAP_ENTRY(nsIStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIStreamListener>)) foundInterface
= static_cast<nsIStreamListener*>(this); else
7281 NS_INTERFACE_MAP_ENTRY(nsIHttpChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannel>)) foundInterface =
static_cast<nsIHttpChannel*>(this); else
7282 NS_INTERFACE_MAP_ENTRY(nsICacheInfoChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheInfoChannel>)) foundInterface
= static_cast<nsICacheInfoChannel*>(this); else
7283 NS_INTERFACE_MAP_ENTRY(nsICachingChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICachingChannel>)) foundInterface
= static_cast<nsICachingChannel*>(this); else
7284 NS_INTERFACE_MAP_ENTRY(nsIClassOfService)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIClassOfService>)) foundInterface
= static_cast<nsIClassOfService*>(this); else
7285 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel>)) foundInterface
= static_cast<nsIUploadChannel*>(this); else
7286 NS_INTERFACE_MAP_ENTRY(nsIFormPOSTActionChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIFormPOSTActionChannel>)) foundInterface
= static_cast<nsIFormPOSTActionChannel*>(this); else
7287 NS_INTERFACE_MAP_ENTRY(nsIUploadChannel2)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIUploadChannel2>)) foundInterface
= static_cast<nsIUploadChannel2*>(this); else
7288 NS_INTERFACE_MAP_ENTRY(nsICacheEntryOpenCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheEntryOpenCallback>)) foundInterface
= static_cast<nsICacheEntryOpenCallback*>(this); else
7289 NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpChannelInternal>)) foundInterface
= static_cast<nsIHttpChannelInternal*>(this); else
7290 NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIResumableChannel>)) foundInterface
= static_cast<nsIResumableChannel*>(this); else
7291 NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsITransportEventSink>)) foundInterface
= static_cast<nsITransportEventSink*>(this); else
7292 NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsPriority>)) foundInterface
= static_cast<nsISupportsPriority*>(this); else
7293 NS_INTERFACE_MAP_ENTRY(nsIProtocolProxyCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProtocolProxyCallback>)) foundInterface
= static_cast<nsIProtocolProxyCallback*>(this); else
7294 NS_INTERFACE_MAP_ENTRY(nsIProxiedChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIProxiedChannel>)) foundInterface
= static_cast<nsIProxiedChannel*>(this); else
7295 NS_INTERFACE_MAP_ENTRY(nsIHttpAuthenticableChannel)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIHttpAuthenticableChannel>)) foundInterface
= static_cast<nsIHttpAuthenticableChannel*>(this); else
7296 NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIAsyncVerifyRedirectCallback>))
foundInterface = static_cast<nsIAsyncVerifyRedirectCallback
*>(this); else
7297 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableRequest)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableRequest>)) foundInterface
= static_cast<nsIThreadRetargetableRequest*>(this); else
7298 NS_INTERFACE_MAP_ENTRY(nsIThreadRetargetableStreamListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIThreadRetargetableStreamListener>
)) foundInterface = static_cast<nsIThreadRetargetableStreamListener
*>(this); else
7299 NS_INTERFACE_MAP_ENTRY(nsIDNSListener)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIDNSListener>)) foundInterface =
static_cast<nsIDNSListener*>(this); else
7300 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupportsWeakReference>)) foundInterface
= static_cast<nsISupportsWeakReference*>(this); else
7301 NS_INTERFACE_MAP_ENTRY(nsICorsPreflightCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICorsPreflightCallback>)) foundInterface
= static_cast<nsICorsPreflightCallback*>(this); else
7302 NS_INTERFACE_MAP_ENTRY(nsIRequestTailUnblockCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIRequestTailUnblockCallback>)) foundInterface
= static_cast<nsIRequestTailUnblockCallback*>(this); else
7303 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
7304 NS_INTERFACE_MAP_ENTRY(nsIEarlyHintObserver)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIEarlyHintObserver>)) foundInterface
= static_cast<nsIEarlyHintObserver*>(this); else
7305NS_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; }
7306
7307//-----------------------------------------------------------------------------
7308// nsHttpChannel::nsIRequest
7309//-----------------------------------------------------------------------------
7310
7311NS_IMETHODIMPnsresult nsHttpChannel::SetCanceledReason(const nsACString& aReason) {
7312 return SetCanceledReasonImpl(aReason);
7313}
7314
7315NS_IMETHODIMPnsresult nsHttpChannel::GetCanceledReason(nsACString& aReason) {
7316 return GetCanceledReasonImpl(aReason);
7317}
7318
7319NS_IMETHODIMPnsresult
7320nsHttpChannel::CancelWithReason(nsresult aStatus, const nsACString& aReason) {
7321 return CancelWithReasonImpl(aStatus, aReason);
7322}
7323
7324NS_IMETHODIMPnsresult
7325nsHttpChannel::Cancel(nsresult status) {
7326 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", 7326
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7326); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7327 // We should never have a pump open while a CORS preflight is in progress.
7328 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"
, 7328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7328); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7329#ifdef DEBUG1
7330 // We want to perform this check only when the chanel is being cancelled the
7331 // first time with a URL classifier blocking error code. If mStatus is
7332 // already set to such an error code then Cancel() may be called for some
7333 // other reason, for example because we've received notification about our
7334 // parent process side channel being canceled, in which case we cannot expect
7335 // that CancelByURLClassifier() would have handled this case.
7336 if (ChannelClassifierUtils::IsClassifierBlockingErrorCode(status) &&
7337 !ChannelClassifierUtils::IsClassifierBlockingErrorCode(mStatus)) {
7338 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"
, 7340, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
7339 " 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"
, 7340, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
7340 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"
, 7340, MOZ_CrashPrintf("" "Blocking classifier error %" "x" " need to be handled by CancelByURLClassifier()"
, static_cast<uint32_t>(status))); } while (false)
;
7341 }
7342#endif
7343
7344 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)
7345 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)
;
7346 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)
7347 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)
;
7348
7349 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", 7351
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7351); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7350 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", 7351
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7351); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
7351 !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", 7351
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!AllowedErrorForTransactionRetry(status)"
")"); do { MOZ_CrashSequence(__null, 7351); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7352
7353 mEarlyHintObserver = nullptr;
7354 mWebTransportSessionEventListener = nullptr;
7355
7356 if (mCanceled) {
7357 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)
;
7358 return NS_OK;
7359 }
7360
7361 LogCallingScriptLocation(this);
7362
7363 if (LoadWaitingForRedirectCallback()) {
7364 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)
;
7365 }
7366
7367 return CancelInternal(status);
7368}
7369
7370NS_IMETHODIMPnsresult
7371nsHttpChannel::CancelByURLClassifier(nsresult aErrorCode) {
7372 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", 7372
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 7372); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7373 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", 7373
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7373); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7374 // We should never have a pump open while a CORS preflight is in progress.
7375 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"
, 7375); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7375); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7376
7377 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)
;
7378
7379 if (mCanceled) {
7380 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)
;
7381 return NS_OK;
7382 }
7383
7384 // We are being canceled by the channel classifier because of tracking
7385 // protection, but we haven't yet had a chance to dispatch the
7386 // "http-on-modify-request" notifications yet (this would normally be
7387 // done in PrepareToConnect()). So do that now, before proceeding to
7388 // cancel.
7389 //
7390 // Note that running these observers can itself result in the channel
7391 // being canceled. In that case, we accept that cancelation code as
7392 // the cause of the cancelation, as if the classification of the channel
7393 // would have occurred past this point!
7394
7395 // notify "http-on-modify-request" observers
7396 CallOnModifyRequestObservers();
7397
7398 // Check if request was cancelled during on-modify-request
7399 if (mCanceled) {
7400 return mStatus;
7401 }
7402
7403 if (mSuspendCount) {
7404 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)
;
7405 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", 7405
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume" ")"
); do { MOZ_CrashSequence(__null, 7405); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7406 StoreChannelClassifierCancellationPending(1);
7407 mCallOnResume = [aErrorCode](nsHttpChannel* self) {
7408 self->HandleContinueCancellingByURLClassifier(aErrorCode);
7409 return NS_OK;
7410 };
7411 return NS_OK;
7412 }
7413
7414 // Check to see if we should redirect this channel elsewhere by
7415 // nsIHttpChannel.redirectTo API request
7416 if (mAPIRedirectTo) {
7417 StoreChannelClassifierCancellationPending(1);
7418 return AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
7419 }
7420
7421 return CancelInternal(aErrorCode);
7422}
7423
7424void nsHttpChannel::ContinueCancellingByURLClassifier(nsresult aErrorCode) {
7425 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", 7425
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ChannelClassifierUtils::IsClassifierBlockingErrorCode(aErrorCode)"
")"); do { MOZ_CrashSequence(__null, 7425); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7426 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", 7426
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7426); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7427 // We should never have a pump open while a CORS preflight is in progress.
7428 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"
, 7428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCachePump"
")"); do { MOZ_CrashSequence(__null, 7428); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
7429
7430 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)
;
7431 if (mCanceled) {
7432 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)
;
7433 return;
7434 }
7435
7436 // Check to see if we should redirect this channel elsewhere by
7437 // nsIHttpChannel.redirectTo API request
7438 if (mAPIRedirectTo) {
7439 (void)AsyncCall(&nsHttpChannel::HandleAsyncAPIRedirect);
7440 return;
7441 }
7442
7443 (void)CancelInternal(aErrorCode);
7444}
7445
7446nsresult nsHttpChannel::CancelInternal(nsresult status) {
7447 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)
;
7448 bool channelClassifierCancellationPending =
7449 !!LoadChannelClassifierCancellationPending();
7450 if (ChannelClassifierUtils::IsClassifierBlockingErrorCode(status)) {
7451 StoreChannelClassifierCancellationPending(0);
7452 }
7453
7454 mEarlyHintObserver = nullptr;
7455 mWebTransportSessionEventListener = nullptr;
7456 mCanceled = true;
7457 mStatus = NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) ? status : NS_ERROR_ABORT;
7458
7459 // If ORB blocked this response, doom the entry that was committed to the
7460 // cache before the (asynchronous) block decision, so it can't be reused
7461 // later (e.g. a navigation consuming a prefetched, ORB-blocked cross-origin
7462 // document). See bug 2045809.
7463 if (mChannelBlockedByOpaqueResponse && mORBValidationCacheEntry) {
7464 mORBValidationCacheEntry->AsyncDoom(nullptr);
7465 mORBValidationCacheEntry = nullptr;
7466 }
7467
7468 // If we're waiting for LNA permission result and the channel is being
7469 // cancelled, we need to call OnPermissionPromptResult with permission denied
7470 // to resume the channel properly
7471 if (mWaitingForLNAPermission) {
7472 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)
7473 ("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)
7474 "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)
7475 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
7476 // Determine permission key dynamically from transaction
7477 const nsACString& permissionKey =
7478 (mTransaction && mTransaction->GetTargetIPAddressSpace() ==
7479 nsILoadInfo::IPAddressSpace::Local)
7480 ? LOOPBACK_NETWORK_PERMISSION_KEY
7481 : LOCAL_NETWORK_PERMISSION_KEY;
7482 OnPermissionPromptResult(false, permissionKey);
7483 return NS_OK;
7484 }
7485
7486 if (LoadUsedNetwork() && !mReportedNEL) {
7487 MaybeGenerateNELReport();
7488 }
7489
7490 // We don't want the content process to see any header values
7491 // when the request is blocked by ORB
7492 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref &&
7493 mResponseHead) {
7494 mResponseHead->ClearHeaders();
7495 }
7496
7497 if (mLastStatusReported && !mEndMarkerAdded &&
7498 profiler_thread_is_being_profiled_for_markers()) {
7499 // These do allocations/frees/etc; avoid if not active
7500 // mLastStatusReported can be null if Cancel is called before we added the
7501 // start marker.
7502 mEndMarkerAdded = true;
7503
7504 nsAutoCString requestMethod;
7505 GetRequestMethod(requestMethod);
7506
7507 int32_t priority = PRIORITY_NORMAL;
7508 GetPriority(&priority);
7509
7510 uint64_t size = 0;
7511 GetEncodedBodySize(&size);
7512
7513 profiler_add_network_marker(
7514 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_CANCEL,
7515 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
7516 mLoadInfo->GetInnerWindowID(),
7517 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
7518 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
7519 &mTransactionTimings, std::move(mSource));
7520 }
7521
7522 // If we don't have mTransactionPump and mCachePump, we need to call
7523 // AsyncAbort to make sure this channel's listener got notified.
7524 bool needAsyncAbort = !mTransactionPump && !mCachePump;
7525
7526 if (mProxyRequest) mProxyRequest->Cancel(status);
7527 CancelNetworkRequest(status);
7528 mCacheInputStream.CloseAndRelease();
7529 if (mCachePump) mCachePump->Cancel(status);
7530 if (mAuthProvider) mAuthProvider->Cancel(status);
7531 if (mPreflightChannel) mPreflightChannel->Cancel(status);
7532 if (mRequestContext && mOnTailUnblock) {
7533 mOnTailUnblock = nullptr;
7534 mRequestContext->CancelTailedRequest(this);
7535 CloseCacheEntry(false);
7536 needAsyncAbort = false;
7537 (void)AsyncAbort(status);
7538 } else if (channelClassifierCancellationPending) {
7539 // If mCallOnResume is not null here, it's set in
7540 // nsHttpChannel::CancelByURLClassifier. We can override mCallOnResume since
7541 // mCanceled is true and nsHttpChannel::ContinueCancellingByURLClassifier
7542 // does nothing.
7543 if (mCallOnResume) {
7544 mCallOnResume = nullptr;
7545 }
7546 // If we're coming from an asynchronous path when canceling a channel due
7547 // to safe-browsing protection, we need to AsyncAbort the channel now.
7548 needAsyncAbort = false;
7549 (void)AsyncAbort(status);
7550 }
7551
7552 // If we suspended after examining the response to await asynchronous
7553 // tracking-protection annotation (bug 2030021), a cancel while suspended
7554 // would otherwise defer the terminal teardown below (CloseCacheEntry /
7555 // AsyncAbort) to a Resume() that may never arrive. For a cache writer that
7556 // leaves the entry perpetually "being written" -- its output stream never
7557 // closed and the entry never doomed -- wedging every later same-URL
7558 // revalidating consumer forever (bug 2052908). Undo the annotation
7559 // suspension now so the cancelled pump delivers OnStopRequest and the
7560 // write-only entry is closed/doomed normally. Safe if we only primed but
7561 // never actually suspended.
7562 CancelSuspendOrResumeAfterExamineResponse();
7563
7564 // If suspended waiting for dictionary prefetch, unblock it so the channel
7565 // can proceed to cleanup. The prefetch callback may never fire, so we must
7566 // not rely on it to call Resume().
7567 if (mSuspendedForDictionary) {
7568 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)
7569 ("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)
7570 "[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)
7571 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
7572 mSuspendedForDictionary = false;
7573 mCallOnResume = nullptr;
7574 // Null out the already-cancelled pumps so Resume() won't re-trigger
7575 // their OnStopRequest before AsyncAbort's DoNotifyListener can call
7576 // OnStartRequest on our listener.
7577 mTransactionPump = nullptr;
7578 mCachePump = nullptr;
7579 Resume();
7580 needAsyncAbort = true;
7581 }
7582
7583 // If we already have mCallOnResume, AsyncAbort will be called in
7584 // ResumeInternal.
7585 if (needAsyncAbort && !mCallOnResume && !mSuspendCount) {
7586 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)
;
7587 CloseCacheEntry(false);
7588 (void)AsyncAbort(status);
7589 }
7590 return NS_OK;
7591}
7592
7593void nsHttpChannel::CancelNetworkRequest(nsresult aStatus) {
7594 if (mTransaction) {
7595 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, aStatus);
7596 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7597 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)
;
7598 }
7599 }
7600 if (mTransactionPump) mTransactionPump->Cancel(aStatus);
7601
7602 mEarlyHintObserver = nullptr;
7603 mWebTransportSessionEventListener = nullptr;
7604}
7605
7606NS_IMETHODIMPnsresult
7607nsHttpChannel::Suspend() {
7608 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", 7608
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7608); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7609 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"
, 7609); return NS_ERROR_NOT_AVAILABLE; } } while (false)
;
7610
7611 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
)
7612 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
)
;
7613 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)
;
7614 LogCallingScriptLocation(this);
7615
7616 ++mSuspendCount;
7617
7618 if (mSuspendCount == 1) {
7619 mSuspendTimestamp = TimeStamp::NowLoRes();
7620
7621 // Start timer to detect if we're suspended too long
7622 // This helps unblock waiting cache listeners when a channel is suspended
7623 // for an unreasonably long time.
7624 uint32_t delay = StaticPrefs::network_cache_suspended_writer_delay_ms();
7625 if (!mSuspendTimer && delay) {
7626 mSuspendTimer = NS_NewTimer();
7627 }
7628
7629 if (mSuspendTimer && delay) {
7630 RefPtr<TimerCallback> timerCallback = new TimerCallback(this);
7631 mSuspendTimer->InitWithCallback(timerCallback, delay,
7632 nsITimer::TYPE_ONE_SHOT);
7633 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)
;
7634 }
7635 }
7636
7637 nsresult rvTransaction = NS_OK;
7638 if (mTransactionPump) {
7639 rvTransaction = mTransactionPump->Suspend();
7640 }
7641 nsresult rvCache = NS_OK;
7642 if (mCachePump) {
7643 rvCache = mCachePump->Suspend();
7644 }
7645
7646 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
7647}
7648
7649// static
7650void nsHttpChannel::StaticSuspend(nsHttpChannel* aChan) { aChan->Suspend(); }
7651
7652NS_IMETHODIMPnsresult
7653nsHttpChannel::Resume() {
7654 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", 7654
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7654); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7655 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"
, 7655); return NS_ERROR_UNEXPECTED; } } while (false)
;
7656
7657 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::Resume", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7658( "nsHttpChannel::Resume"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7658 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7658( "nsHttpChannel::Resume"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7659 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)
;
7660 LogCallingScriptLocation(this);
7661
7662 if (--mSuspendCount == 0) {
7663 mSuspendTotalTime += TimeStamp::NowLoRes() - mSuspendTimestamp;
7664
7665 // Cancel suspend timer since we're resuming
7666 if (mSuspendTimer) {
7667 mSuspendTimer->Cancel();
7668 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)
;
7669 }
7670
7671 // Reset bypass flag since the writer is resuming
7672 if (mBypassCacheWriterSet && mCacheEntry) {
7673 mCacheEntry->SetBypassWriterLock(false);
7674 mBypassCacheWriterSet = false;
7675 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)
;
7676 }
7677
7678 if (mCallOnResume) {
7679 // Resume the interrupted procedure first, then resume
7680 // the pump to continue process the input stream.
7681 // Any newly created pump MUST be suspended to prevent calling
7682 // its OnStartRequest before OnStopRequest of any pre-existing
7683 // pump. AsyncResumePending ensures that.
7684 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", 7684
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7684); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7685 StoreAsyncResumePending(1);
7686
7687 std::function<nsresult(nsHttpChannel*)> callOnResume = nullptr;
7688 std::swap(callOnResume, mCallOnResume);
7689
7690 RefPtr<nsHttpChannel> self(this);
7691 nsCOMPtr<nsIRequest> transactionPump = mTransactionPump;
7692 RefPtr<nsInputStreamPump> cachePump = mCachePump;
7693
7694 nsresult rv = NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7695 "nsHttpChannel::CallOnResume",
7696 [callOnResume{std::move(callOnResume)}, self{std::move(self)},
7697 transactionPump{std::move(transactionPump)},
7698 cachePump{std::move(cachePump)}]() {
7699 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"
, 7699); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7699); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7700 nsresult rv = self->CallOrWaitForResume(callOnResume);
7701 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7702 self->CloseCacheEntry(false);
7703 (void)self->AsyncAbort(rv);
7704 }
7705 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"
, 7705); AnnotateMozCrashReason("MOZ_ASSERT" "(" "self->LoadAsyncResumePending()"
")"); do { MOZ_CrashSequence(__null, 7705); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7706
7707 self->StoreAsyncResumePending(0);
7708
7709 // And now actually resume the previously existing pumps.
7710 if (transactionPump) {
7711 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)
7712 ("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)
7713 "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)
7714 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)
;
7715 transactionPump->Resume();
7716 }
7717 if (cachePump) {
7718 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)
7719 ("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)
7720 "%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)
7721 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)
;
7722 cachePump->Resume();
7723 }
7724
7725 // Any newly created pumps were suspended once because of
7726 // AsyncResumePending. Problem is that the stream listener
7727 // notification is already pending in the queue right now, because
7728 // AsyncRead doesn't (regardless if called after Suspend) respect
7729 // the suspend coutner and the right order would not be preserved.
7730 // Hence, we do another dispatch round to actually Resume after
7731 // the notification from the original pump.
7732 if (transactionPump != self->mTransactionPump &&
7733 self->mTransactionPump) {
7734 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)
7735 ("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)
7736 "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)
7737 "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)
7738 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)
;
7739
7740 nsCOMPtr<nsIRequest> pump = self->mTransactionPump;
7741 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7742 "nsHttpChannel::CallOnResume new transaction",
7743 [pump{std::move(pump)}]() { pump->Resume(); }));
7744 }
7745 if (cachePump != self->mCachePump && self->mCachePump) {
7746 LOG(do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__builtin_expect(!!(mozilla::detail::log_test
(moz_real_module, mozilla::LogLevel::Verbose)), 0))) { mozilla
::detail::log_print(moz_real_module, mozilla::LogLevel::Verbose
, "nsHttpChannel::CallOnResume async-resuming new cache pump "
"%p, this=%p", self->mCachePump.get(), self.get()); } } while
(0)
7747 ("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)
7748 "%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)
7749 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)
;
7750
7751 RefPtr<nsInputStreamPump> pump = self->mCachePump;
7752 NS_DispatchToCurrentThread(NS_NewRunnableFunction(
7753 "nsHttpChannel::CallOnResume new pump",
7754 [pump{std::move(pump)}]() { pump->Resume(); }));
7755 }
7756 }));
7757 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"
, 7757); return rv; } } while (false)
;
7758 return rv;
7759 }
7760 }
7761
7762 nsresult rvTransaction = NS_OK;
7763 if (mTransactionPump) {
7764 rvTransaction = mTransactionPump->Resume();
7765 }
7766
7767 nsresult rvCache = NS_OK;
7768 if (mCachePump) {
7769 rvCache = mCachePump->Resume();
7770 }
7771
7772 return NS_FAILED(rvTransaction)((bool)(__builtin_expect(!!(NS_FAILED_impl(rvTransaction)), 0
)))
? rvTransaction : rvCache;
7773}
7774
7775//-----------------------------------------------------------------------------
7776// nsHttpChannel::nsIChannel
7777//-----------------------------------------------------------------------------
7778
7779NS_IMETHODIMPnsresult
7780nsHttpChannel::GetSecurityInfo(nsITransportSecurityInfo** securityInfo) {
7781 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"
, 7781); return NS_ERROR_INVALID_POINTER; } } while (false)
;
7782 *securityInfo = do_AddRef(mSecurityInfo).take();
7783 return NS_OK;
7784}
7785
7786// If any of the functions that AsyncOpen calls returns immediately an error
7787// AsyncAbort(which calls onStart/onStopRequest) does not need to be call.
7788// To be sure that they are not call ReleaseListeners() is called.
7789// If AsyncOpen returns NS_OK, after that point AsyncAbort must be called on
7790// any error.
7791NS_IMETHODIMPnsresult
7792nsHttpChannel::AsyncOpen(nsIStreamListener* aListener) {
7793 // doContentSecurityCheck and OnOpeningRequest fire observers that may
7794 // spin nested event loops; hold a strong ref to this.
7795 RefPtr<nsHttpChannel> self(this);
7796
7797 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpen", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7798( "nsHttpChannel::AsyncOpen"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7798 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7798( "nsHttpChannel::AsyncOpen"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7799 nsCOMPtr<nsIStreamListener> listener = aListener;
7800 nsresult rv =
7801 nsContentSecurityManager::doContentSecurityCheck(this, listener);
7802 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"
, 7802)
) {
7803 ReleaseListeners();
7804 return rv;
7805 }
7806
7807 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"
, 7814); 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, 7814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7808 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"
, 7814); 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, 7814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7809 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"
, 7814); 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, 7814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7810 (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"
, 7814); 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, 7814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7811 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"
, 7814); 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, 7814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7812 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"
, 7814); 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, 7814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7813 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"
, 7814); 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, 7814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
7814 "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"
, 7814); 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, 7814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7815
7816 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
)
;
7817 mOpenerCallingScriptLocation = CallingScriptLocationString();
7818 LogCallingScriptLocation(this, mOpenerCallingScriptLocation);
7819 NS_CompareLoadInfoAndLoadContext(this);
7820
7821#ifdef DEBUG1
7822 AssertPrivateBrowsingId();
7823#endif
7824
7825 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", 7825
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
7826 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"
, 7826); return NS_ERROR_IN_PROGRESS; } } while (false)
;
7827 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"
, 7827); return NS_ERROR_ALREADY_OPENED; } } while (false)
;
7828
7829 if (mCanceled) {
7830 ReleaseListeners();
7831 return NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) ? mStatus : NS_ERROR_FAILURE;
7832 }
7833
7834 if (MaybeWaitForUploadStreamNormalization(listener, nullptr)) {
7835 return NS_OK;
7836 }
7837
7838 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", 7838
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 7838); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7839
7840 if (!gHttpHandler->Active()) {
7841 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)
;
7842 ReleaseListeners();
7843 return NS_ERROR_NOT_AVAILABLE;
7844 }
7845
7846 rv = NS_CheckPortSafety(mURI);
7847 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7848 ReleaseListeners();
7849 return rv;
7850 }
7851
7852 // If no one called SetLoadGroup or SetNotificationCallbacks, the private
7853 // state has not been updated on PrivateBrowsingChannel (which we derive
7854 // from) Same if the loadinfo has changed since the creation of the channel.
7855 // Hence, we have to call UpdatePrivateBrowsing() here
7856 UpdatePrivateBrowsing();
7857
7858 AntiTrackingUtils::UpdateAntiTrackingInfoForChannel(this);
7859
7860 // Recalculate the default userAgent header after the AntiTrackingInfo gets
7861 // updated because we can only know whether the site is exempted from
7862 // fingerprinting protection after we have the AntiTracking Info.
7863 //
7864 // Note that we don't recalculate the header if it has been modified since the
7865 // channel was created because we want to preserve the modified header.
7866 if (!LoadIsUserAgentHeaderModified()) {
7867 rv = mRequestHead.SetHeader(
7868 nsHttp::User_Agent,
7869 gHttpHandler->UserAgent(nsContentUtils::ShouldResistFingerprinting(
7870 this, RFPTarget::HttpUserAgent)),
7871 false, nsHttpHeaderArray::eVarietyRequestEnforceDefault);
7872 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"
, 7872); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 7872); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7873 }
7874
7875 if (WaitingForTailUnblock()) {
7876 // This channel is marked as Tail and is part of a request context
7877 // that has positive number of non-tailed requestst, hence this channel
7878 // has been put to a queue.
7879 // When tail is unblocked, OnTailUnblock on this channel will be called
7880 // to continue AsyncOpen.
7881 mListener = listener;
7882 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", 7882
); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "!mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 7882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7883 mOnTailUnblock = &nsHttpChannel::AsyncOpenOnTailUnblock;
7884
7885 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)
;
7886 return NS_OK;
7887 }
7888
7889 // Remember the cookie header that was set, if any
7890 nsAutoCString cookieHeader;
7891 if (NS_SUCCEEDED(mRequestHead.GetHeader(nsHttp::Cookie, cookieHeader))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mRequestHead.GetHeader
(nsHttp::Cookie, cookieHeader))), 1)))
) {
7892 // if this is a cache revalidaing channel (mIsStaleRevalidation), then this
7893 // represents both user cookies and cookies from cookieService
7894 mUserSetCookieHeader = std::move(cookieHeader);
7895 }
7896
7897 // Set user agent override, do so before OnOpeningRequest notification
7898 // since we want to allow consumers of that notification change or remove
7899 // the User-Agent request header.
7900 HttpBaseChannel::SetDocshellUserAgentOverride();
7901
7902 // After we notify any observers (on-opening-request, loadGroup, etc) we
7903 // must return NS_OK and return any errors asynchronously via
7904 // OnStart/OnStopRequest. Observers may add a reference to the channel
7905 // and expect to get OnStopRequest so they know when to drop the reference,
7906 // etc.
7907
7908 // notify "http-on-opening-request" observers, but not if this is a redirect
7909 if (!(mLoadFlags & LOAD_REPLACE)) {
7910 gHttpHandler->OnOpeningRequest(this);
7911 }
7912
7913 StoreIsPending(true);
7914 StoreWasOpened(true);
7915
7916 mListener = std::move(listener);
7917
7918 if (nsIOService::UseSocketProcess() &&
7919 !gIOService->IsSocketProcessLaunchComplete()) {
7920 RefPtr<nsHttpChannel> self = this;
7921 gIOService->CallOrWaitForSocketProcess(
7922 [self]() { self->AsyncOpenFinal(TimeStamp::Now()); });
7923 return NS_OK;
7924 }
7925
7926 AsyncOpenFinal(TimeStamp::Now());
7927
7928 return NS_OK;
7929}
7930
7931void nsHttpChannel::AsyncOpenFinal(TimeStamp aTimeStamp) {
7932 // We save this timestamp from outside of the if block in case we enable the
7933 // profiler after AsyncOpen().
7934 mLastStatusReported = TimeStamp::Now();
7935 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpenFinal", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject7936( "nsHttpChannel::AsyncOpenFinal"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
7936 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject7936( "nsHttpChannel::AsyncOpenFinal"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
7937 if (profiler_thread_is_being_profiled_for_markers()) {
7938 nsAutoCString requestMethod;
7939 GetRequestMethod(requestMethod);
7940
7941 profiler_add_network_marker(
7942 mURI, requestMethod, mPriority, mChannelId, NetworkLoadType::LOAD_START,
7943 mChannelCreationTimestamp, mLastStatusReported, 0, mCacheDisposition,
7944 mLoadInfo->GetInnerWindowID(),
7945 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
7946 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch());
7947 }
7948
7949 // Added due to PauseTask/DelayHttpChannel
7950 if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr);
7951
7952 // record asyncopen time unconditionally and clear it if we
7953 // don't want it after OnModifyRequest() weighs in. But waiting for
7954 // that to complete would mean we don't include proxy resolution in the
7955 // timing.
7956 if (!LoadAsyncOpenTimeOverriden()) {
7957 mAsyncOpenTime = aTimeStamp;
7958 }
7959
7960 // Remember we have Authorization header set here. We need to check on it
7961 // just once and early, AsyncOpen is the best place.
7962 StoreCustomAuthHeader(mRequestHead.HasHeader(nsHttp::Authorization));
7963
7964 bool willCallback = false;
7965 // We are about to do an async lookup to check if the URI is a tracker. If
7966 // yes, this channel will be canceled by channel classifier. Chances are the
7967 // lookup is not needed so CheckIsTrackerWithLocalTable() will return an
7968 // error and then we can MaybeResolveProxyAndBeginConnect() right away.
7969 // We skip the check in case this is an internal redirected channel
7970 if (NS_ShouldClassifyChannel(this, ClassifyType::ETP)) {
7971 RefPtr<nsHttpChannel> self = this;
7972 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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7973 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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7974 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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7975 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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7976 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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7977
7978 // 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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7979 // 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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7980 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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7981
7982 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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
7983 }))((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"
, 7976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "uri" ")"); do
{ MOZ_CrashSequence(__null, 7976); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false); FinishAntiTrackingRedirectHeuristic
(self, uri); self->MaybeResolveProxyAndBeginConnect(); }))
), 1)))
;
7984 }
7985
7986 if (!willCallback) {
7987 // We can do MaybeResolveProxyAndBeginConnect immediately if
7988 // CheckIsTrackerWithLocalTable is failed. Note that we don't need to
7989 // handle the failure because BeginConnect() will return synchronously and
7990 // the caller will be responsible for handling it.
7991 MaybeResolveProxyAndBeginConnect();
7992 }
7993}
7994
7995void nsHttpChannel::MaybeResolveProxyAndBeginConnect() {
7996 nsresult rv;
7997
7998 // The common case for HTTP channels is to begin proxy resolution and return
7999 // at this point. The only time we know mProxyInfo already is if we're
8000 // proxying a non-http protocol like ftp. We don't need to discover proxy
8001 // settings if we are never going to make a network connection.
8002 if (!mProxyInfo &&
8003 !(mLoadFlags & (LOAD_ONLY_FROM_CACHE | LOAD_NO_NETWORK_IO)) &&
8004 !BypassProxy()) {
8005 nsCOMPtr<nsIProtocolProxyService> pps =
8006 mozilla::components::ProtocolProxy::Service();
8007 nsCOMPtr<nsIProtocolProxyService2> pps2 = do_QueryInterface(pps);
8008 if (pps2 && pps2->IsEffectivelyDirect()) {
8009 mozilla::glean::networking::proxy_fast_path_used.Add(1);
8010 MaybeStartDNSPrefetch();
8011 } else if (NS_SUCCEEDED(ResolveProxy())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ResolveProxy())),
1)))
) {
8012 return;
8013 }
8014 }
8015
8016 if (!gHttpHandler->Active()) {
8017 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)
8018 ("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)
8019 "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)
8020 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
8021 rv = NS_ERROR_NOT_AVAILABLE;
8022 } else {
8023 rv = BeginConnect();
8024 }
8025 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8026 CloseCacheEntry(false);
8027 (void)AsyncAbort(rv);
8028 }
8029}
8030
8031nsresult nsHttpChannel::AsyncOpenOnTailUnblock() {
8032 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::AsyncOpenOnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject8033( "nsHttpChannel::AsyncOpenOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
8033 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject8033( "nsHttpChannel::AsyncOpenOnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
8034 return AsyncOpen(mListener);
8035}
8036
8037already_AddRefed<nsChannelClassifier>
8038nsHttpChannel::GetOrCreateChannelClassifier() {
8039 if (!mChannelClassifier) {
8040 mChannelClassifier = new nsChannelClassifier(this);
8041 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)
8042 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)
;
8043 }
8044
8045 RefPtr<nsChannelClassifier> classifier = mChannelClassifier;
8046 return classifier.forget();
8047}
8048
8049nsIHttpChannelInternal::ProxyDNSStrategy
8050nsHttpChannel::ComputeProxyDNSStrategy() {
8051 // When network_dns_force_use_https_rr is true, return DNS_PREFETCH_ORIGIN.
8052 // This ensures that we always perform HTTPS RR query.
8053 nsCOMPtr<nsProxyInfo> proxyInfo(static_cast<nsProxyInfo*>(mProxyInfo.get()));
8054 if (!proxyInfo || StaticPrefs::network_dns_force_use_https_rr()) {
8055 return nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN;
8056 }
8057
8058 // If the proxy is not to perform name resolution itself.
8059 return GetProxyDNSStrategyHelper(proxyInfo->Type(), proxyInfo->Flags());
8060}
8061
8062NS_IMETHODIMPnsresult
8063nsHttpChannel::GetProxyDNSStrategy(
8064 nsIHttpChannelInternal::ProxyDNSStrategy* aStrategy) {
8065 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", 8065
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
8066 *aStrategy = ComputeProxyDNSStrategy();
8067 return NS_OK;
8068}
8069
8070// BeginConnect() SHOULD NOT call AsyncAbort(). AsyncAbort will be called by
8071// functions that called BeginConnect if needed. Only
8072// MaybeResolveProxyAndBeginConnect and OnProxyAvailable ever call
8073// BeginConnect.
8074nsresult nsHttpChannel::BeginConnect() {
8075 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)
;
8076
8077 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::BeginConnect", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject8078( "nsHttpChannel::BeginConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
8078 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject8078( "nsHttpChannel::BeginConnect"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
8079 nsresult rv;
8080
8081 // It is the caller's responsibility to not call us late in shutdown.
8082 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", 8082
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "gHttpHandler->Active()"
")"); do { MOZ_CrashSequence(__null, 8082); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8083
8084 // Construct connection info object
8085 nsAutoCString host;
8086 nsAutoCString scheme;
8087 int32_t port = -1;
8088 bool isHttps = mURI->SchemeIs("https");
8089
8090 rv = mURI->GetScheme(scheme);
8091 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiHost(host);
8092 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetPort(&port);
8093 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) rv = mURI->GetAsciiSpec(mSpec);
8094 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8095 return rv;
8096 }
8097
8098 // Just a warning here because some nsIURIs do not implement this method.
8099 (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", 8099
)
;
8100
8101 // Reject the URL if it doesn't specify a host
8102 if (host.IsEmpty()) {
8103 rv = NS_ERROR_MALFORMED_URI;
8104 return rv;
8105 }
8106 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)
;
8107 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)
;
8108
8109 nsCOMPtr<nsProxyInfo> proxyInfo;
8110 if (mProxyInfo) proxyInfo = do_QueryInterface(mProxyInfo);
8111
8112 if (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) {
8113 if (!proxyInfo) {
8114 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)
;
8115 return NS_ERROR_FAILURE;
8116 }
8117
8118 if (!proxyInfo->IsHTTP() && !proxyInfo->IsHTTPS()) {
8119 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)
;
8120 return NS_ERROR_FAILURE;
8121 }
8122 }
8123
8124 mRequestHead.SetHTTPS(isHttps);
8125 mRequestHead.SetOrigin(scheme, host, port);
8126
8127 AddStorageAccessHeadersToRequest();
8128 SetOriginHeader();
8129 SetDoNotTrack();
8130 SetGlobalPrivacyControl();
8131
8132 OriginAttributes originAttributes;
8133 // Regular principal in case we have a proxy.
8134 if (proxyInfo &&
8135 !StaticPrefs::privacy_partition_network_state_connection_with_proxy()) {
8136 StoragePrincipalHelper::GetOriginAttributes(
8137 this, originAttributes, StoragePrincipalHelper::eRegularPrincipal);
8138 } else {
8139 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
8140 this, originAttributes);
8141 }
8142
8143 // Adjust mCaps according to our request headers:
8144 // - If "Connection: close" is set as a request header, then do not bother
8145 // trying to establish a keep-alive connection.
8146 if (mRequestHead.HasHeaderValue(nsHttp::Connection, "close")) {
8147 mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE(1 << 0));
8148 StoreAllowHttp3(false);
8149 }
8150
8151 gHttpHandler->MaybeAddAltSvcForTesting(mURI, mUsername, mPrivateBrowsing,
8152 mCallbacks, originAttributes);
8153
8154 RefPtr<nsHttpConnectionInfo> connInfo;
8155#ifdef FUZZING
8156 if (StaticPrefs::fuzzing_necko_http3()) {
8157 connInfo =
8158 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8159 originAttributes, host, port, true);
8160 } else {
8161#endif
8162 if (mWebTransportSessionEventListener) {
8163 connInfo =
8164 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8165 originAttributes, isHttps, true, true);
8166 bool dedicated = true;
8167 nsresult rv;
8168 nsCOMPtr<WebTransportConnectionSettings> wtconSettings =
8169 do_QueryInterface(mWebTransportSessionEventListener, &rv);
8170 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"
, 8170); return rv; } } while (false)
;
8171 nsIWebTransport::HTTPVersion httpVersion;
8172 (void)wtconSettings->GetHttpVersion(&httpVersion);
8173 if (httpVersion == nsIWebTransport::HTTPVersion::h2) {
8174 connInfo =
8175 new nsHttpConnectionInfo(host, port, "h2"_ns, mUsername, proxyInfo,
8176 originAttributes, isHttps, false, true);
8177 } else {
8178 connInfo =
8179 new nsHttpConnectionInfo(host, port, "h3"_ns, mUsername, proxyInfo,
8180 originAttributes, isHttps, true, true);
8181 }
8182 wtconSettings->GetDedicated(&dedicated);
8183 if (dedicated) {
8184 connInfo->SetWebTransportId(
8185 nsHttpConnectionInfo::GenerateNewWebTransportId());
8186 }
8187 } else {
8188 connInfo = new nsHttpConnectionInfo(host, port, ""_ns, mUsername,
8189 proxyInfo, originAttributes, isHttps);
8190 }
8191#ifdef FUZZING
8192 }
8193#endif
8194
8195 bool http2Allowed = !gHttpHandler->IsHttp2Excluded(connInfo);
8196
8197 bool http3Allowed = Http3Allowed();
8198 if (!http3Allowed) {
8199 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
8200 }
8201
8202 RefPtr<AltSvcMapping> mapping;
8203 if (!mConnectionInfo && LoadAllowAltSvc() && // per channel
8204 !mWebTransportSessionEventListener && (http2Allowed || http3Allowed) &&
8205 !(mLoadFlags & LOAD_FRESH_CONNECTION) &&
8206 AltSvcMapping::AcceptableProxy(proxyInfo) &&
8207 (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) &&
8208 (mapping = gHttpHandler->GetAltServiceMapping(
8209 scheme, host, port, mPrivateBrowsing, originAttributes, http2Allowed,
8210 http3Allowed))) {
8211 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)
8212 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)
8213 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)
;
8214
8215 if (!(mLoadFlags & LOAD_ANONYMOUS) && !mPrivateBrowsing) {
8216 nsAutoCString altUsedLine(mapping->AlternateHost());
8217 bool defaultPort =
8218 mapping->AlternatePort() ==
8219 (isHttps ? NS_HTTPS_DEFAULT_PORT443 : NS_HTTP_DEFAULT_PORT80);
8220 if (!defaultPort) {
8221 altUsedLine.AppendLiteral(":");
8222 altUsedLine.AppendInt(mapping->AlternatePort());
8223 }
8224 // Like what we did for 'Authorization' header, we need to do the same for
8225 // 'Alt-Used' for avoiding this header being shown in the ServiceWorker
8226 // FetchEvent.
8227 (void)mRequestHead.ClearHeader(nsHttp::Alternate_Service_Used);
8228 rv = mRequestHead.SetHeader(nsHttp::Alternate_Service_Used, altUsedLine,
8229 false,
8230 nsHttpHeaderArray::eVarietyRequestDefault);
8231 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"
, 8231); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 8231); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8232 }
8233
8234 nsCOMPtr<nsIConsoleService> consoleService;
8235 consoleService = mozilla::components::Console::Service();
8236 if (consoleService && !host.Equals(mapping->AlternateHost())) {
8237 nsAutoString message(u"Alternate Service Mapping found: "_ns);
8238 AppendASCIItoUTF16(scheme, message);
8239 message.AppendLiteral(u"://");
8240 AppendASCIItoUTF16(host, message);
8241 message.AppendLiteral(u":");
8242 message.AppendInt(port);
8243 message.AppendLiteral(u" to ");
8244 AppendASCIItoUTF16(scheme, message);
8245 message.AppendLiteral(u"://");
8246 AppendASCIItoUTF16(mapping->AlternateHost(), message);
8247 message.AppendLiteral(u":");
8248 message.AppendInt(mapping->AlternatePort());
8249 consoleService->LogStringMessage(message.get());
8250 }
8251
8252 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)
;
8253 mapping->GetConnectionInfo(getter_AddRefs(mConnectionInfo), proxyInfo,
8254 originAttributes);
8255 glean::http::transaction_use_altsvc
8256 .EnumGet(glean::http::TransactionUseAltsvcLabel::eTrue)
8257 .Add();
8258 if (mConnectionInfo->IsHttp3() &&
8259 StaticPrefs::
8260 network_http_http3_force_use_alt_svc_mapping_for_testing()) {
8261 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
8262 }
8263 } else if (mConnectionInfo) {
8264 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)
;
8265 glean::http::transaction_use_altsvc
8266 .EnumGet(glean::http::TransactionUseAltsvcLabel::eFalse)
8267 .Add();
8268 } else {
8269 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)
;
8270
8271 mConnectionInfo = connInfo;
8272 glean::http::transaction_use_altsvc
8273 .EnumGet(glean::http::TransactionUseAltsvcLabel::eFalse)
8274 .Add();
8275 }
8276
8277 bool trrEnabled = false;
8278 auto dnsStrategy = ComputeProxyDNSStrategy();
8279 bool httpsRRAllowed =
8280 !LoadBeConservative() && !(mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11)) &&
8281 !(mLoadInfo->TriggeringPrincipal()->IsSystemPrincipal() &&
8282 mLoadInfo->GetExternalContentPolicyType() !=
8283 ExtContentPolicy::TYPE_DOCUMENT) &&
8284 dnsStrategy == nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN &&
8285 !mConnectionInfo->UsingConnect() && canUseHTTPSRRonNetwork(trrEnabled) &&
8286 StaticPrefs::network_dns_use_https_rr_as_altsvc();
8287 if (!httpsRRAllowed) {
8288 DisallowHTTPSRR(mCaps);
8289 } else if (trrEnabled) {
8290 if (nsIRequest::GetTRRMode() != nsIRequest::TRR_DISABLED_MODE) {
8291 mCaps |= NS_HTTP_FORCE_WAIT_HTTP_RR(1 << 22);
8292 }
8293 }
8294
8295 auto canUseHappyEyeballs = [&]() {
8296 if (!StaticPrefs::network_http_happy_eyeballs_enabled()) {
8297 return false;
8298 }
8299
8300 if (LoadBeConservative() || (mCaps & NS_HTTP_BE_CONSERVATIVE(1 << 11))) {
8301 return false;
8302 }
8303
8304 if (mProxyInfo) {
8305 return false;
8306 }
8307
8308 // WebSocket and WebTransport upgrades share the same rollout pref.
8309 if ((mUpgradeProtocolCallback || mWebTransportSessionEventListener) &&
8310 !StaticPrefs::network_http_happy_eyeballs_upgrade_enabled()) {
8311 return false;
8312 }
8313
8314 // Connect-only requests need the extended-CONNECT tunnel path, which is
8315 // untested with Happy Eyeballs. These only reach us via a proxy today
8316 // (already excluded above), but guard explicitly against a future
8317 // non-proxied consumer.
8318 if (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) {
8319 return false;
8320 }
8321
8322 return true;
8323 };
8324
8325 if (canUseHappyEyeballs()) {
8326 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)
;
8327 mCaps |= NS_HTTP_USE_HAPPY_EYEBALLS(1 << 30);
8328 mCaps &= ~NS_HTTP_FORCE_WAIT_HTTP_RR(1 << 22);
8329 mConnectionInfo->SetHappyEyeballsEnabled(true);
8330 }
8331
8332 // No need to lookup HTTPSSVC record if mHTTPSSVCRecord already contains a
8333 // value.
8334 StoreUseHTTPSSVC(StaticPrefs::network_dns_upgrade_with_https_rr() &&
8335 httpsRRAllowed && mHTTPSSVCRecord.isNothing());
8336
8337 // Need to re-ask the handler, since mConnectionInfo may not be the connInfo
8338 // we used earlier
8339 if (!mConnectionInfo->IsHttp3() &&
8340 gHttpHandler->IsHttp2Excluded(mConnectionInfo)) {
8341 StoreAllowSpdy(0);
8342 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
8343 mConnectionInfo->SetNoSpdy(true);
8344 }
8345
8346 // We can be passed with the auth provider if this channel was
8347 // a result of redirect due to auth retry
8348 if (!mAuthProvider) {
8349 mAuthProvider = new nsHttpChannelAuthProvider();
8350 }
8351
8352 rv = mAuthProvider->Init(this);
8353 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8354 return rv;
8355 }
8356
8357 // check to see if authorization headers should be included
8358 // CustomAuthHeader is set in AsyncOpen if we find Authorization header
8359 rv = mAuthProvider->AddAuthorizationHeaders(LoadCustomAuthHeader());
8360 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8361 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)
8362 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)
;
8363 }
8364
8365 // if this somehow fails we can go on without it
8366 (void)gHttpHandler->AddConnectionHeader(&mRequestHead, mCaps);
8367
8368 if (!LoadIsTRRServiceChannel() &&
8369 ((mLoadFlags & LOAD_FRESH_CONNECTION) ||
8370 (!StaticPrefs::network_dns_only_refresh_on_fresh_connection() &&
8371 (mLoadFlags & VALIDATE_ALWAYS ||
8372 BYPASS_LOCAL_CACHE(mLoadFlags, LoadPreferCacheLoadOverBypass())((mLoadFlags) & (nsIRequest::LOAD_BYPASS_CACHE | nsICachingChannel
::LOAD_BYPASS_LOCAL_CACHE) && !(((mLoadFlags) & nsIRequest
::LOAD_FROM_CACHE) && (LoadPreferCacheLoadOverBypass(
))))
)))) {
8373 mCaps |= NS_HTTP_REFRESH_DNS(1 << 3);
8374 }
8375
8376 if (gHttpHandler->CriticalRequestPrioritization()) {
8377 if (mClassOfService.Flags() & nsIClassOfService::Leader) {
8378 mCaps |= NS_HTTP_LOAD_AS_BLOCKING(1 << 6);
8379 }
8380 if (mClassOfService.Flags() & nsIClassOfService::Unblocked) {
8381 mCaps |= NS_HTTP_LOAD_UNBLOCKED(1 << 8);
8382 }
8383 if (mClassOfService.Flags() & nsIClassOfService::UrgentStart &&
8384 gHttpHandler->IsUrgentStartEnabled()) {
8385 mCaps |= NS_HTTP_URGENT_START(1 << 12);
8386 SetPriority(nsISupportsPriority::PRIORITY_HIGHEST);
8387 }
8388 }
8389
8390 // Force-Reload should reset the persistent connection pool for this host
8391 if (mLoadFlags & LOAD_FRESH_CONNECTION) {
8392 // just the initial document resets the whole pool
8393 if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI) {
8394 gHttpHandler->AltServiceCache()->ClearAltServiceMappings();
8395 rv = gHttpHandler->DoShiftReloadConnectionCleanupWithConnInfo(
8396 mConnectionInfo);
8397 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8398 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)
8399 "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)
8400 "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)
8401 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)
;
8402 }
8403 }
8404 }
8405
8406 // We may have been cancelled already, either by on-modify-request
8407 // listeners or load group observers; in that case, we should not send the
8408 // request to the server
8409 if (mCanceled) {
8410 return mStatus;
8411 }
8412 // skip classifier checks if this channel was the result of internal auth
8413 // redirect
8414 bool shouldBeClassifiedForTracker =
8415 NS_ShouldClassifyChannel(this, ClassifyType::ETP);
8416
8417 if (shouldBeClassifiedForTracker) {
8418 if (LoadChannelClassifierCancellationPending()) {
8419 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)
8420 ("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)
8421 "[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)
8422 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; 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)
;
8423 return NS_OK;
8424 }
8425
8426 ReEvaluateReferrerAfterTrackingStatusIsKnown();
8427 }
8428
8429 MaybeStartDNSPrefetch();
8430
8431 // Update whether the channel is on the third-party cookie blocking exception
8432 // list.
8433 CookieService::Update3PCBExceptionInfo(this);
8434
8435 rv = CallOrWaitForResume(
8436 [](nsHttpChannel* self) { return self->PrepareToConnect(); });
8437 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8438 return rv;
8439 }
8440
8441 bool shouldBeClassifiedForSafeBrowsing =
8442 NS_ShouldClassifyChannel(this, ClassifyType::SafeBrowsing);
8443
8444 if (shouldBeClassifiedForTracker) {
8445 PrimeSuspendAfterExamineResponse();
8446 RefPtr<nsHttpChannel> self(this);
8447 nsresult rv =
8448 AntiTrackingChannelClassifierUtils::CheckChannelBeforeProcessResponse(
8449 this,
8450 [self]() { self->CancelSuspendOrResumeAfterExamineResponse(); });
8451 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8452 CancelSuspendOrResumeAfterExamineResponse();
8453 }
8454 }
8455
8456 if (shouldBeClassifiedForSafeBrowsing) {
8457 // Start nsChannelClassifier to catch phishing and malware URIs.
8458 RefPtr<nsChannelClassifier> channelClassifier =
8459 GetOrCreateChannelClassifier();
8460 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)
8461 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)
;
8462 channelClassifier->Start();
8463 }
8464
8465 return NS_OK;
8466}
8467
8468void nsHttpChannel::MaybeStartDNSPrefetch() {
8469 // Start a DNS lookup very early in case the real open is queued the DNS can
8470 // happen in parallel. Do not do so in the presence of an HTTP proxy as
8471 // all lookups other than for the proxy itself are done by the proxy.
8472 // Also we don't do a lookup if the LOAD_NO_NETWORK_IO or
8473 // LOAD_ONLY_FROM_CACHE flags are set.
8474 //
8475 // We keep the DNS prefetch object around so that we can retrieve
8476 // timing information from it. There is no guarantee that we actually
8477 // use the DNS prefetch data for the real connection, but as we keep
8478 // this data around for 3 minutes by default, this should almost always
8479 // be correct, and even when it isn't, the timing still represents _a_
8480 // valid DNS lookup timing for the site, even if it is not _the_
8481 // timing we used.
8482 if (mDNSPrefetch) {
8483 return;
8484 }
8485 if ((mLoadFlags & (LOAD_NO_NETWORK_IO | LOAD_ONLY_FROM_CACHE)) ||
8486 LoadAuthRedirectedChannel()) {
8487 return;
8488 }
8489
8490 auto dnsStrategy = ComputeProxyDNSStrategy();
8491
8492 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)
8493 ("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)
8494 "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)
8495 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)
8496 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)
;
8497
8498 if (dnsStrategy == nsIHttpChannelInternal::PROXY_DNS_STRATEGY_ORIGIN) {
8499 OriginAttributes originAttributes;
8500 StoragePrincipalHelper::GetOriginAttributesForNetworkState(
8501 this, originAttributes);
8502
8503 mDNSPrefetch = new nsDNSPrefetch(mURI, originAttributes,
8504 nsIRequest::GetTRRMode(), this, true);
8505 nsIDNSService::DNSFlags dnsFlags = nsIDNSService::RESOLVE_DEFAULT_FLAGS;
8506 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
8507 dnsFlags |= nsIDNSService::RESOLVE_BYPASS_CACHE;
8508 }
8509
8510 bool unused;
8511 if (StaticPrefs::network_dns_use_https_rr_as_altsvc() && !mHTTPSSVCRecord &&
8512 !(mCaps & NS_HTTP_DISALLOW_HTTPS_RR(1 << 24)) &&
8513 canUseHTTPSRRonNetwork(unused)) {
8514 (void)mDNSPrefetch->FetchHTTPSSVC(mCaps & NS_HTTP_REFRESH_DNS(1 << 3), true,
8515 [](nsIDNSHTTPSSVCRecord*) {
8516 // Do nothing. This is a DNS prefetch.
8517 });
8518 }
8519
8520 // Issue per-family prefetches (A and AAAA) so Happy Eyeballs can reuse
8521 // them instead of starting its own lookups. Skip a family that won't be
8522 // queried; with IPv6 disabled the AAAA request collapses to A, so skip it
8523 // to avoid a duplicate.
8524 bool skipIPv4 = mCaps & NS_HTTP_DISABLE_IPV4(1 << 17);
8525 bool skipIPv6 = (mCaps & NS_HTTP_DISABLE_IPV6(1 << 18)) ||
8526 StaticPrefs::network_dns_disableIPv6();
8527 (void)mDNSPrefetch->PrefetchHighPerFamily(dnsFlags, skipIPv4, skipIPv6);
8528 }
8529}
8530
8531NS_IMETHODIMPnsresult
8532nsHttpChannel::GetEncodedBodySize(uint64_t* aEncodedBodySize) {
8533 if (mCacheEntry && !LoadCacheEntryIsWriteOnly()) {
8534 int64_t dataSize = 0;
8535 mCacheEntry->GetDataSize(&dataSize);
8536 *aEncodedBodySize = dataSize;
8537 } else {
8538 *aEncodedBodySize = mLogicalOffset;
8539 }
8540 return NS_OK;
8541}
8542
8543NS_IMETHODIMPnsresult
8544nsHttpChannel::GetDecompressDictionary(DictionaryCacheEntry** aDictionary) {
8545 *aDictionary = do_AddRef(mDictDecompress).take();
8546 return NS_OK;
8547}
8548
8549NS_IMETHODIMPnsresult
8550nsHttpChannel::SetDecompressDictionary(DictionaryCacheEntry* aDictionary) {
8551 if (!aDictionary) {
8552 if (mDictDecompress && mUsingDictionary) {
8553 mDictDecompress->UseCompleted();
8554 }
8555 mUsingDictionary = false;
8556 } else {
8557 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", 8557
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mDictDecompress"
")"); do { MOZ_CrashSequence(__null, 8557); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8558 aDictionary->InUse();
8559 mUsingDictionary = true;
8560 }
8561 mDictDecompress = aDictionary;
8562 return NS_OK;
8563}
8564
8565//-----------------------------------------------------------------------------
8566// nsHttpChannel::nsIHttpChannelInternal
8567//-----------------------------------------------------------------------------
8568
8569NS_IMETHODIMPnsresult
8570nsHttpChannel::GetIsAuthChannel(bool* aIsAuthChannel) {
8571 *aIsAuthChannel = mIsAuthChannel;
8572 return NS_OK;
8573}
8574
8575NS_IMETHODIMPnsresult
8576nsHttpChannel::SetChannelIsForDownload(bool aChannelIsForDownload) {
8577 if (aChannelIsForDownload) {
8578 AddClassFlags(nsIClassOfService::Throttleable);
8579 } else {
8580 ClearClassFlags(nsIClassOfService::Throttleable);
8581 }
8582
8583 return HttpBaseChannel::SetChannelIsForDownload(aChannelIsForDownload);
8584}
8585
8586base::ProcessId nsHttpChannel::ProcessId() {
8587 nsCOMPtr<nsIParentChannel> parentChannel;
8588 NS_QueryNotificationCallbacks(this, parentChannel);
8589 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
8590 return httpParent->OtherPid();
8591 }
8592 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
8593 return docParent->OtherPid();
8594 }
8595 return base::GetCurrentProcId();
8596}
8597
8598auto nsHttpChannel::AttachStreamFilter() -> RefPtr<ChildEndpointPromise> {
8599 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)
;
8600 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", 8600
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 8600); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8601
8602 if (!ProcessId()) {
8603 return ChildEndpointPromise::CreateAndReject(false, __func__);
8604 }
8605
8606 nsCOMPtr<nsIParentChannel> parentChannel;
8607 NS_QueryNotificationCallbacks(this, parentChannel);
8608
8609 // If our listener is a DocumentLoadListener, then we might handle
8610 // multi-part responses here in the parent process. The current extension
8611 // API doesn't understand the parsed multipart format, so we defer responding
8612 // here until CallOnStartRequest, and attach the StreamFilter before the
8613 // multipart handler (in the parent process!) if applicable.
8614 if (RefPtr<DocumentLoadListener> docParent = do_QueryObject(parentChannel)) {
8615 StreamFilterRequest* request = mStreamFilterRequests.AppendElement();
8616 request->mPromise = new ChildEndpointPromise::Private(__func__);
8617 return request->mPromise;
8618 }
8619
8620 mozilla::ipc::Endpoint<extensions::PStreamFilterParent> parent;
8621 mozilla::ipc::Endpoint<extensions::PStreamFilterChild> child;
8622 nsresult rv = extensions::PStreamFilter::CreateEndpoints(&parent, &child);
8623 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8624 return ChildEndpointPromise::CreateAndReject(false, __func__);
8625 }
8626
8627 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
8628 return httpParent->AttachStreamFilter(std::move(parent), std::move(child));
8629 }
8630
8631 extensions::StreamFilterParent::Attach(this, std::move(parent));
8632 return ChildEndpointPromise::CreateAndResolve(std::move(child), __func__);
8633}
8634
8635NS_IMETHODIMPnsresult
8636nsHttpChannel::GetNavigationStartTimeStamp(TimeStamp* aTimeStamp) {
8637 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)
;
8638 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"
, 8638); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTimeStamp"
")"); do { MOZ_CrashSequence(__null, 8638); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8639 *aTimeStamp = mNavigationStartTimeStamp;
8640 return NS_OK;
8641}
8642
8643NS_IMETHODIMPnsresult
8644nsHttpChannel::SetNavigationStartTimeStamp(TimeStamp aTimeStamp) {
8645 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)
;
8646 mNavigationStartTimeStamp = aTimeStamp;
8647 return NS_OK;
8648}
8649
8650//-----------------------------------------------------------------------------
8651// nsHttpChannel::nsISupportsPriority
8652//-----------------------------------------------------------------------------
8653
8654NS_IMETHODIMPnsresult
8655nsHttpChannel::SetPriority(int32_t value) {
8656 int16_t newValue = std::clamp<int32_t>(value, INT16_MIN(-32767-1), INT16_MAX(32767));
8657 if (mPriority == newValue) return NS_OK;
8658
8659 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)
;
8660
8661 mPriority = newValue;
8662 if (mTransaction) {
8663 nsresult rv = gHttpHandler->RescheduleTransaction(mTransaction, mPriority);
8664 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8665 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)
8666 ("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)
8667 "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)
8668 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)
;
8669 }
8670 }
8671
8672 // If this channel is the real channel for an e10s channel, notify the
8673 // child side about the priority change as well.
8674 nsCOMPtr<nsIParentChannel> parentChannel;
8675 NS_QueryNotificationCallbacks(this, parentChannel);
8676 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
8677 if (httpParent) {
8678 httpParent->DoSendSetPriority(newValue);
8679 }
8680
8681 return NS_OK;
8682}
8683
8684//-----------------------------------------------------------------------------
8685// HttpChannel::nsIClassOfService
8686//-----------------------------------------------------------------------------
8687
8688void nsHttpChannel::OnClassOfServiceUpdated() {
8689 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)
8690 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)
;
8691
8692 if (mTransaction) {
8693 gHttpHandler->UpdateClassOfServiceOnTransaction(mTransaction,
8694 mClassOfService);
8695 }
8696 if (EligibleForTailing()) {
8697 RemoveAsNonTailRequest();
8698 } else {
8699 AddAsNonTailRequest();
8700 }
8701}
8702
8703NS_IMETHODIMPnsresult
8704nsHttpChannel::SetClassFlags(uint32_t inFlags) {
8705 uint32_t previous = mClassOfService.Flags();
8706 mClassOfService.SetFlags(inFlags);
8707 if (previous != mClassOfService.Flags()) {
8708 OnClassOfServiceUpdated();
8709 }
8710 return NS_OK;
8711}
8712
8713NS_IMETHODIMPnsresult
8714nsHttpChannel::AddClassFlags(uint32_t inFlags) {
8715 uint32_t previous = mClassOfService.Flags();
8716 mClassOfService.SetFlags(inFlags | mClassOfService.Flags());
8717 if (previous != mClassOfService.Flags()) {
8718 OnClassOfServiceUpdated();
8719 }
8720 return NS_OK;
8721}
8722
8723NS_IMETHODIMPnsresult
8724nsHttpChannel::ClearClassFlags(uint32_t inFlags) {
8725 uint32_t previous = mClassOfService.Flags();
8726 mClassOfService.SetFlags(~inFlags & mClassOfService.Flags());
8727 if (previous != mClassOfService.Flags()) {
8728 OnClassOfServiceUpdated();
8729 }
8730 return NS_OK;
8731}
8732
8733NS_IMETHODIMPnsresult
8734nsHttpChannel::SetClassOfService(ClassOfService cos) {
8735 ClassOfService previous = mClassOfService;
8736 mClassOfService = cos;
8737 if (previous != mClassOfService) {
8738 OnClassOfServiceUpdated();
8739 }
8740 return NS_OK;
8741}
8742
8743NS_IMETHODIMPnsresult
8744nsHttpChannel::SetIncremental(bool incremental) {
8745 bool previous = mClassOfService.Incremental();
8746 mClassOfService.SetIncremental(incremental);
8747 if (previous != mClassOfService.Incremental()) {
8748 OnClassOfServiceUpdated();
8749 }
8750 return NS_OK;
8751}
8752
8753//-----------------------------------------------------------------------------
8754// nsHttpChannel::nsIProtocolProxyCallback
8755//-----------------------------------------------------------------------------
8756
8757NS_IMETHODIMPnsresult
8758nsHttpChannel::OnProxyAvailable(nsICancelable* request, nsIChannel* channel,
8759 nsIProxyInfo* pi, nsresult status) {
8760 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)
8761 " 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)
8762 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)
8763 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)
;
8764 mProxyRequest = nullptr;
8765
8766 nsresult rv;
8767
8768 // If status is a failure code, then it means that we failed to resolve
8769 // proxy info. That is a non-fatal error assuming it wasn't because the
8770 // request was canceled. We just failover to DIRECT when proxy resolution
8771 // fails (failure can mean that the PAC URL could not be loaded).
8772
8773 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
8774 mProxyInfo = pi;
8775
8776 if (mProxyInfo) {
8777 nsAutoCStringN<8> type;
8778 mProxyInfo->GetType(type);
8779 uint32_t flags = 0;
8780 mProxyInfo->GetFlags(&flags);
8781
8782 if (type.EqualsLiteral("socks")) {
8783 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
8784 glean::networking::proxy_info_type
8785 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5h)
8786 .Add(1);
8787 } else {
8788 glean::networking::proxy_info_type
8789 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks5)
8790 .Add(1);
8791 }
8792 } else if (type.EqualsLiteral("socks4")) {
8793 if (flags & nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST) {
8794 glean::networking::proxy_info_type
8795 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4a)
8796 .Add(1);
8797 } else {
8798 glean::networking::proxy_info_type
8799 .EnumGet(glean::networking::ProxyInfoTypeLabel::eSocks4)
8800 .Add(1);
8801 }
8802 } else if (type.EqualsLiteral("http")) {
8803 glean::networking::proxy_info_type
8804 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttp)
8805 .Add(1);
8806 } else if (type.EqualsLiteral("https")) {
8807 glean::networking::proxy_info_type
8808 .EnumGet(glean::networking::ProxyInfoTypeLabel::eHttps)
8809 .Add(1);
8810 } else if (type.EqualsLiteral("direct")) {
8811 glean::networking::proxy_info_type
8812 .EnumGet(glean::networking::ProxyInfoTypeLabel::eDirect)
8813 .Add(1);
8814 } else {
8815 glean::networking::proxy_info_type
8816 .EnumGet(glean::networking::ProxyInfoTypeLabel::eUnknown)
8817 .Add(1);
8818 }
8819 }
8820 }
8821
8822 if (!gHttpHandler->Active()) {
8823 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)
8824 ("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)
8825 "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)
8826 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
8827 rv = NS_ERROR_NOT_AVAILABLE;
8828 } else {
8829 rv = BeginConnect();
8830 }
8831
8832 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
8833 CloseCacheEntry(false);
8834 (void)AsyncAbort(rv);
8835 }
8836 return rv;
8837}
8838
8839//-----------------------------------------------------------------------------
8840// nsHttpChannel::nsIProxiedChannel
8841//-----------------------------------------------------------------------------
8842
8843NS_IMETHODIMPnsresult
8844nsHttpChannel::GetProxyInfo(nsIProxyInfo** result) {
8845 if (!mConnectionInfo) {
8846 *result = do_AddRef(mProxyInfo).take();
8847 } else {
8848 *result = do_AddRef(mConnectionInfo->ProxyInfo()).take();
8849 }
8850 return NS_OK;
8851}
8852
8853//-----------------------------------------------------------------------------
8854// nsHttpChannel::nsITimedChannel
8855//-----------------------------------------------------------------------------
8856
8857NS_IMETHODIMPnsresult
8858nsHttpChannel::GetDomainLookupStart(TimeStamp* _retval) {
8859 if (mTransaction) {
8860 *_retval = mTransaction->GetDomainLookupStart();
8861 } else {
8862 *_retval = mTransactionTimings.domainLookupStart;
8863 }
8864 return NS_OK;
8865}
8866
8867NS_IMETHODIMPnsresult
8868nsHttpChannel::GetDomainLookupEnd(TimeStamp* _retval) {
8869 if (mTransaction) {
8870 *_retval = mTransaction->GetDomainLookupEnd();
8871 } else {
8872 *_retval = mTransactionTimings.domainLookupEnd;
8873 }
8874 return NS_OK;
8875}
8876
8877NS_IMETHODIMPnsresult
8878nsHttpChannel::GetConnectStart(TimeStamp* _retval) {
8879 if (mTransaction) {
8880 *_retval = mTransaction->GetConnectStart();
8881 } else {
8882 *_retval = mTransactionTimings.connectStart;
8883 }
8884 return NS_OK;
8885}
8886
8887NS_IMETHODIMPnsresult
8888nsHttpChannel::GetTcpConnectEnd(TimeStamp* _retval) {
8889 if (mTransaction) {
8890 *_retval = mTransaction->GetTcpConnectEnd();
8891 } else {
8892 *_retval = mTransactionTimings.tcpConnectEnd;
8893 }
8894 return NS_OK;
8895}
8896
8897NS_IMETHODIMPnsresult
8898nsHttpChannel::GetSecureConnectionStart(TimeStamp* _retval) {
8899 if (mTransaction) {
8900 *_retval = mTransaction->GetSecureConnectionStart();
8901 } else {
8902 *_retval = mTransactionTimings.secureConnectionStart;
8903 }
8904 return NS_OK;
8905}
8906
8907NS_IMETHODIMPnsresult
8908nsHttpChannel::GetConnectEnd(TimeStamp* _retval) {
8909 if (mTransaction) {
8910 *_retval = mTransaction->GetConnectEnd();
8911 } else {
8912 *_retval = mTransactionTimings.connectEnd;
8913 }
8914 return NS_OK;
8915}
8916
8917NS_IMETHODIMPnsresult
8918nsHttpChannel::GetRequestStart(TimeStamp* _retval) {
8919 if (mTransaction) {
8920 *_retval = mTransaction->GetRequestStart();
8921 } else {
8922 *_retval = mTransactionTimings.requestStart;
8923 }
8924 return NS_OK;
8925}
8926
8927NS_IMETHODIMPnsresult
8928nsHttpChannel::GetResponseStart(TimeStamp* _retval) {
8929 if (mTransaction) {
8930 *_retval = mTransaction->GetResponseStart();
8931 } else {
8932 *_retval = mTransactionTimings.responseStart;
8933 }
8934 return NS_OK;
8935}
8936
8937NS_IMETHODIMPnsresult
8938nsHttpChannel::GetFirstInterimResponseStart(TimeStamp* _retval) {
8939 if (mTransaction) {
8940 *_retval = mTransaction->GetFirstInterimResponseStart();
8941 } else {
8942 *_retval = mTransactionTimings.firstInterimResponseStart;
8943 }
8944 return NS_OK;
8945}
8946
8947NS_IMETHODIMPnsresult
8948nsHttpChannel::GetFinalResponseHeadersStart(TimeStamp* _retval) {
8949 if (mTransaction) {
8950 *_retval = mTransaction->GetFinalResponseHeadersStart();
8951 } else {
8952 *_retval = mTransactionTimings.finalResponseHeadersStart;
8953 }
8954 return NS_OK;
8955}
8956
8957NS_IMETHODIMPnsresult
8958nsHttpChannel::GetResponseEnd(TimeStamp* _retval) {
8959 if (mTransaction) {
8960 *_retval = mTransaction->GetResponseEnd();
8961 } else {
8962 *_retval = mTransactionTimings.responseEnd;
8963 }
8964 return NS_OK;
8965}
8966
8967NS_IMETHODIMPnsresult
8968nsHttpChannel::GetTransactionPending(TimeStamp* _retval) {
8969 if (mTransaction) {
8970 *_retval = mTransaction->GetPendingTime();
8971 } else {
8972 *_retval = mTransactionTimings.transactionPending;
8973 }
8974 return NS_OK;
8975}
8976
8977//-----------------------------------------------------------------------------
8978// nsHttpChannel::nsIHttpAuthenticableChannel
8979//-----------------------------------------------------------------------------
8980
8981NS_IMETHODIMPnsresult
8982nsHttpChannel::GetIsSSL(bool* aIsSSL) {
8983 // this attribute is really misnamed - it wants to know if
8984 // https:// is being used. SSL might be used to cover http://
8985 // in some circumstances (proxies, http/2, etc..)
8986 return mURI->SchemeIs("https", aIsSSL);
8987}
8988
8989NS_IMETHODIMPnsresult
8990nsHttpChannel::GetProxyMethodIsConnect(bool* aProxyMethodIsConnect) {
8991 *aProxyMethodIsConnect = mConnectionInfo->UsingConnect();
8992 return NS_OK;
8993}
8994
8995NS_IMETHODIMPnsresult
8996nsHttpChannel::GetServerResponseHeader(nsACString& value) {
8997 if (!mResponseHead) return NS_ERROR_NOT_AVAILABLE;
8998 return mResponseHead->GetHeader(nsHttp::Server, value);
8999}
9000
9001NS_IMETHODIMPnsresult
9002nsHttpChannel::GetProxyChallenges(nsACString& value) {
9003 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
9004 return mResponseHead->GetHeader(nsHttp::Proxy_Authenticate, value);
9005}
9006
9007NS_IMETHODIMPnsresult
9008nsHttpChannel::GetWWWChallenges(nsACString& value) {
9009 if (!mResponseHead) return NS_ERROR_UNEXPECTED;
9010 return mResponseHead->GetHeader(nsHttp::WWW_Authenticate, value);
9011}
9012
9013NS_IMETHODIMPnsresult
9014nsHttpChannel::SetProxyCredentials(const nsACString& value) {
9015 return mRequestHead.SetHeader(nsHttp::Proxy_Authorization, value);
9016}
9017
9018NS_IMETHODIMPnsresult
9019nsHttpChannel::SetWWWCredentials(const nsACString& value) {
9020 // This method is called when various browser initiated authorization
9021 // code sets the credentials. We need to flag this header as the
9022 // "browser default" so it does not show up in the ServiceWorker
9023 // FetchEvent. This may actually get called more than once, though,
9024 // so we clear the header first since "default" headers are not
9025 // allowed to overwrite normally.
9026 (void)mRequestHead.ClearHeader(nsHttp::Authorization);
9027 return mRequestHead.SetHeader(nsHttp::Authorization, value, false,
9028 nsHttpHeaderArray::eVarietyRequestDefault);
9029}
9030
9031//-----------------------------------------------------------------------------
9032// Methods that nsIHttpAuthenticableChannel dupes from other IDLs, which we
9033// get from HttpBaseChannel, must be explicitly forwarded, because C++ sucks.
9034//-----------------------------------------------------------------------------
9035
9036NS_IMETHODIMPnsresult
9037nsHttpChannel::GetLoadFlags(nsLoadFlags* aLoadFlags) {
9038 return HttpBaseChannel::GetLoadFlags(aLoadFlags);
9039}
9040
9041NS_IMETHODIMPnsresult
9042nsHttpChannel::GetURI(nsIURI** aURI) { return HttpBaseChannel::GetURI(aURI); }
9043
9044NS_IMETHODIMPnsresult
9045nsHttpChannel::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks) {
9046 return HttpBaseChannel::GetNotificationCallbacks(aCallbacks);
9047}
9048
9049NS_IMETHODIMPnsresult
9050nsHttpChannel::GetLoadGroup(nsILoadGroup** aLoadGroup) {
9051 return HttpBaseChannel::GetLoadGroup(aLoadGroup);
9052}
9053
9054NS_IMETHODIMPnsresult
9055nsHttpChannel::GetRequestMethod(nsACString& aMethod) {
9056 return HttpBaseChannel::GetRequestMethod(aMethod);
9057}
9058
9059//-----------------------------------------------------------------------------
9060// nsHttpChannel::nsIRequestObserver
9061//-----------------------------------------------------------------------------
9062
9063void nsHttpChannel::RecordOnStartTelemetry(nsresult aStatus,
9064 bool aIsNavigation) {
9065 glean::http::channel_onstart_success
9066 .EnumGet(static_cast<glean::http::ChannelOnstartSuccessLabel>(
9067 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))))
9068 .Add();
9069
9070 mozilla::glean::networking::http_channel_onstart_status
9071 .Get(NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) ? "successful"_ns : "fail"_ns)
9072 .Add(1);
9073
9074 if (mTransaction) {
9075 glean::networking::http3_channel_onstart_success
9076 .Get((mTransaction->IsHttp3Used()) ? "http3"_ns : "no_http3"_ns,
9077 NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) ? "true"_ns : "false"_ns)
9078 .Add();
9079 }
9080
9081 enum class HttpOnStartState : uint32_t {
9082 Success = 0,
9083 DNSError = 1,
9084 Others = 2,
9085 };
9086
9087 if (TRRService::Get() && TRRService::Get()->IsConfirmed()) {
9088 // Note this telemetry probe is not working when DNS resolution is done in
9089 // the socket process.
9090 HttpOnStartState state = HttpOnStartState::Others;
9091 if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
9092 state = HttpOnStartState::Success;
9093 } else if (aStatus == NS_ERROR_UNKNOWN_HOST ||
9094 aStatus == NS_ERROR_UNKNOWN_PROXY_HOST) {
9095 state = HttpOnStartState::DNSError;
9096 }
9097
9098 if (aIsNavigation) {
9099 glean::http::channel_page_onstart_success_trr
9100 .Get(TRRService::ProviderKey())
9101 .AccumulateSingleSample(static_cast<uint32_t>(state));
9102 } else {
9103 glean::http::channel_sub_onstart_success_trr
9104 .Get(TRRService::ProviderKey())
9105 .AccumulateSingleSample(static_cast<uint32_t>(state));
9106 }
9107 }
9108
9109 if (nsIOService::UseSocketProcess() && mTransaction) {
9110 const TimeStamp now = TimeStamp::Now();
9111 TimeStamp responseEnd = mTransaction->GetResponseEnd();
9112 if (!responseEnd.IsNull()) {
9113 PerfStats::RecordMeasurement(PerfStats::Metric::ResponseEndSocketToParent,
9114 now - responseEnd);
9115 }
9116
9117 mOnStartRequestStartTime = mTransaction->GetOnStartRequestStartTime();
9118 if (!mOnStartRequestStartTime.IsNull()) {
9119 PerfStats::RecordMeasurement(
9120 PerfStats::Metric::OnStartRequestSocketToParent,
9121 now - mOnStartRequestStartTime);
9122 }
9123 } else {
9124 mOnStartRequestStartTime = TimeStamp::Now();
9125 }
9126}
9127
9128static bool hasConnectivity() {
9129 if (RefPtr<NetworkConnectivityService> ncs =
9130 NetworkConnectivityService::GetSingleton()) {
9131 nsINetworkConnectivityService::ConnectivityState state;
9132 if (NS_SUCCEEDED(ncs->GetIPv4(&state))((bool)(__builtin_expect(!!(!NS_FAILED_impl(ncs->GetIPv4(&
state))), 1)))
&&
9133 state == nsINetworkConnectivityService::OK) {
9134 return true;
9135 }
9136 // We should also check for IPv6 connectivity here, but since
9137 // quite a few mozilla domains don't have IPv6 records yet,
9138 // we might incorrectly fallback to a backup domain on
9139 // IPv6 only networks.
9140 // When bug 1665605 gets fixed we can also return true when only IPv6 is OK.
9141 }
9142
9143 return false;
9144};
9145
9146static already_AddRefed<nsIURI> GetFallbackURI(nsIURI* aURI) {
9147 nsresult rv;
9148 nsAutoCString host;
9149 aURI->GetHost(host);
9150 nsCOMPtr<nsIURI> backupURI;
9151
9152 nsAutoCString fallbackDomain;
9153 if (!gIOService->GetFallbackDomain(host, fallbackDomain)) {
9154 return nullptr;
9155 }
9156
9157 rv = NS_MutateURI(aURI).SetHost(fallbackDomain).Finalize(backupURI);
9158 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9159 return nullptr;
9160 }
9161
9162 return backupURI.forget();
9163}
9164
9165// The essential domain fallback only targets Firefox's own internal requests
9166// Opening a link from browser UI or a priviledged page still carries the
9167// system principal so we need to exclude these regular pageloads.
9168static bool IsInternalSystemLoad(nsILoadInfo* aLoadInfo) {
9169 if (!aLoadInfo->TriggeringPrincipal()->IsSystemPrincipal()) {
9170 return false;
9171 }
9172
9173 ExtContentPolicyType type = aLoadInfo->GetExternalContentPolicyType();
9174 return type != ExtContentPolicy::TYPE_DOCUMENT &&
9175 type != ExtContentPolicy::TYPE_SUBDOCUMENT;
9176}
9177
9178// static
9179nsHttpChannel::EssentialDomainCategory
9180nsHttpChannel::GetEssentialDomainCategory(nsCString& domain) {
9181 if (StringEndsWith(domain, ".addons.mozilla.org"_ns)) {
9182 return EssentialDomainCategory::SubAddonsMozillaOrg;
9183 }
9184 if (domain == "addons.mozilla.org"_ns) {
9185 return EssentialDomainCategory::AddonsMozillaOrg;
9186 }
9187 if (domain == "aus5.mozilla.org"_ns) {
9188 return EssentialDomainCategory::Aus5MozillaOrg;
9189 }
9190 if (domain == "firefox.settings.services.mozilla.com"_ns ||
9191 domain == "firefox-settings-attachments.cdn.mozilla.net"_ns ||
9192 domain == "content-signature-2.cdn.mozilla.net"_ns) {
9193 return EssentialDomainCategory::RemoteSettings;
9194 }
9195 if (domain == "incoming.telemetry.mozilla.com"_ns) {
9196 return EssentialDomainCategory::Telemetry;
9197 }
9198 return EssentialDomainCategory::Other;
9199}
9200
9201// Helper function to send LNA access info to child process for console logging
9202// The child process has access to CallingScriptLocationString() which requires
9203// JS context
9204static void ReportLNAAccessToConsole(nsHttpChannel* aChannel,
9205 const char* aMessageName,
9206 const nsACString& aPromptAction = ""_ns) {
9207 // Send IPC to child process to log to console with script location
9208 nsCOMPtr<nsIParentChannel> parentChannel;
9209 NS_QueryNotificationCallbacks(aChannel, parentChannel);
9210 if (RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel)) {
9211 NetAddr peerAddr = aChannel->GetPeerAddr();
9212
9213 // Fetch top-level site URI in parent process and pass via IPC.
9214 // We need to fetch this here because with Fission (site isolation),
9215 // cross-site iframes run in separate content processes and cannot
9216 // access the top-level document in a different process.
9217 nsAutoCString topLevelSite;
9218 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
9219 if (loadInfo) {
9220 RefPtr<mozilla::dom::BrowsingContext> bc;
9221 loadInfo->GetBrowsingContext(getter_AddRefs(bc));
9222 if (bc && bc->Top() && bc->Top()->Canonical()) {
9223 RefPtr<mozilla::dom::WindowGlobalParent> topWindowGlobal =
9224 bc->Top()->Canonical()->GetCurrentWindowGlobal();
9225 if (topWindowGlobal) {
9226 nsIPrincipal* topPrincipal = topWindowGlobal->DocumentPrincipal();
9227 if (topPrincipal) {
9228 nsCOMPtr<nsIURI> topURI = topPrincipal->GetURI();
9229 if (topURI) {
9230 (void)topURI->GetSpec(topLevelSite);
9231 }
9232 }
9233 }
9234 }
9235 }
9236
9237 httpParent->DoSendReportLNAToConsole(peerAddr, nsCString(aMessageName),
9238 nsCString(aPromptAction),
9239 topLevelSite);
9240 }
9241}
9242
9243nsresult nsHttpChannel::ProcessLNAActions() {
9244 if (!mTransaction) {
9245 return NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED;
9246 }
9247
9248 // Suspend to block any notification to the channel.
9249 // This will get resumed in
9250 // nsHttpChannel::OnPermissionPromptResult
9251 UpdateCurrentIpAddressSpace();
9252 mWaitingForLNAPermission = true;
9253 Suspend();
9254 auto targetAddressSpace = mTransaction->GetTargetIPAddressSpace();
9255 auto permissionKey = targetAddressSpace == nsILoadInfo::IPAddressSpace::Local
9256 ? LOOPBACK_NETWORK_PERMISSION_KEY
9257 : LOCAL_NETWORK_PERMISSION_KEY;
9258 LNAPermission permissionUpdateResult =
9259 UpdateLocalNetworkAccessPermissions(permissionKey);
9260
9261 if (LNAPermission::Granted == permissionUpdateResult) {
9262 // permission granted (auto-allow via permanent permission)
9263 mLNAPromptAction.AssignLiteral("auto_allow");
9264 return OnPermissionPromptResult(true, permissionKey);
9265 }
9266
9267 if (LNAPermission::Denied == permissionUpdateResult) {
9268 // permission denied (auto-deny via permanent permission)
9269 mLNAPromptAction.AssignLiteral("auto_deny");
9270 return OnPermissionPromptResult(false, permissionKey);
9271 }
9272
9273 // If we get here, we don't have any permission to access the local
9274 // host/network. We need to prompt the user for action
9275 auto permissionPromptCallback =
9276 [self = RefPtr{this}](bool aPermissionGranted, const nsACString& aType,
9277 bool aPromptShown) -> void {
9278 // Set mLNAPromptAction based on whether prompt was shown and user response
9279 if (aPromptShown) {
9280 if (aPermissionGranted) {
9281 self->mLNAPromptAction.AssignLiteral("prompt_allow");
9282 } else {
9283 self->mLNAPromptAction.AssignLiteral("prompt_deny");
9284 }
9285 } else {
9286 if (aPermissionGranted) {
9287 self->mLNAPromptAction.AssignLiteral("auto_allow");
9288 } else {
9289 self->mLNAPromptAction.AssignLiteral("auto_deny");
9290 }
9291 }
9292 self->OnPermissionPromptResult(aPermissionGranted, aType);
9293 };
9294
9295 RefPtr<LNAPermissionRequest> request = new LNAPermissionRequest(
9296 std::move(permissionPromptCallback), mLoadInfo, permissionKey);
9297
9298 // Log to console before requesting permission
9299 ReportLNAAccessToConsole(this, "LocalNetworkAccessPermissionRequired");
9300
9301 // This invokes callback nsHttpChannel::OnPermissionPromptResult
9302 // synchronously if the permission is already granted or denied
9303 // if permission is not available we prompt the user and in that case
9304 // nsHttpChannel::OnPermissionPromptResult is invoked asynchronously once
9305 // the user responds to the prompt
9306 return request->RequestPermission();
9307}
9308
9309void nsHttpChannel::UpdateCurrentIpAddressSpace() {
9310 if (!mTransaction) {
9311 return;
9312 }
9313
9314 if (mPeerAddr.GetIpAddressSpace() == nsILoadInfo::IPAddressSpace::Unknown) {
9315 // fetch peer address from transaction
9316 bool isTrr;
9317 bool echConfigUsed;
9318 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
9319 mEffectiveTRRMode, mTRRSkipReason,
9320 echConfigUsed);
9321 }
9322
9323 nsILoadInfo::IPAddressSpace docAddressSpace = mPeerAddr.GetIpAddressSpace();
9324 mLoadInfo->SetIpAddressSpace(docAddressSpace);
9325 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
9326 if (type == ExtContentPolicy::TYPE_DOCUMENT ||
9327 type == ExtContentPolicy::TYPE_SUBDOCUMENT) {
9328 RefPtr<mozilla::dom::BrowsingContext> bc;
9329 mLoadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
9330 if (bc) {
9331 bc->SetCurrentIPAddressSpace(docAddressSpace);
9332 }
9333
9334 if (mCacheEntry) {
9335 // store the ipaddr information into the cache metadata entry
9336 if (mPeerAddr.GetIpAddressSpace() !=
9337 nsILoadInfo::IPAddressSpace::Unknown) {
9338 uint16_t port;
9339 mPeerAddr.GetPort(&port);
9340 mCacheEntry->SetMetaDataElement("peer-ip-address",
9341 mPeerAddr.ToString().get());
9342 mCacheEntry->SetMetaDataElement("peer-port", ToString(port).c_str());
9343 }
9344 }
9345 }
9346}
9347
9348NS_IMETHODIMPnsresult
9349nsHttpChannel::OnStartRequest(nsIRequest* request) {
9350 nsresult rv;
9351
9352 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"
, 9352); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequestObserversCalled()"
")"); do { MOZ_CrashSequence(__null, 9352); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9353
9354 AUTO_PROFILER_LABEL("nsHttpChannel::OnStartRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject9354( "nsHttpChannel::OnStartRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
9355 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnStartRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject9356( "nsHttpChannel::OnStartRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
9356 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject9356( "nsHttpChannel::OnStartRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
9357
9358 if (!(mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))))) {
9359 // capture the request's status, so our consumers will know ASAP of any
9360 // connection failures, etc - bug 93581
9361 nsresult status;
9362 request->GetStatus(&status);
9363 mStatus = status;
9364 }
9365
9366 if (mStatus == NS_ERROR_NON_LOCAL_CONNECTION_REFUSED) {
9367 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"
, 9373, _profileOrCrashReason.get()); } while (false)
9368 "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"
, 9373, _profileOrCrashReason.get()); } while (false)
9369 "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"
, 9373, _profileOrCrashReason.get()); } while (false)
9370 "[%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"
, 9373, _profileOrCrashReason.get()); } while (false)
9371 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"
, 9373, _profileOrCrashReason.get()); } while (false)
9372 : "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"
, 9373, _profileOrCrashReason.get()); } while (false)
9373 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"
, 9373, _profileOrCrashReason.get()); } while (false)
;
9374 }
9375
9376 if (mStatus == NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED) {
9377 return ProcessLNAActions();
9378 }
9379
9380 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)
9381 "]\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)
9382 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)
;
9383
9384 RecordOnStartTelemetry(mStatus, IsNavigation());
9385
9386 // Make sure things are what we expect them to be...
9387 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"
, 9388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { MOZ_CrashSequence(__null
, 9388); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
9388 "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"
, 9388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request == mCachePump || request == mTransactionPump"
") (" "Unexpected request" ")"); do { MOZ_CrashSequence(__null
, 9388); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
9389
9390 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"
, 9394); 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, 9394); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9391 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"
, 9394); 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, 9394); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9392 "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"
, 9394); 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, 9394); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9393 "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"
, 9394); 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, 9394); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
9394 "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"
, 9394); 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, 9394); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9395
9396 StoreAfterOnStartRequestBegun(true);
9397 if (mOnStartRequestTimestamp.IsNull()) {
9398 mOnStartRequestTimestamp = TimeStamp::Now();
9399 }
9400
9401 mozilla::glean::networking::http_onstart_suspend_total_time
9402 .AccumulateRawDuration(mSuspendTotalTime);
9403
9404 if (mTransaction) {
9405 mProxyConnectResponseHead = mTransaction->GetProxyConnectResponseHead();
9406 if (request == mTransactionPump) {
9407 StoreDataSentToChildProcess(mTransaction->DataSentToChildProcess());
9408 }
9409
9410 if (!mSecurityInfo && !mCachePump) {
9411 // grab the security info from the connection object; the transaction
9412 // is guaranteed to own a reference to the connection.
9413 mSecurityInfo = mTransaction->SecurityInfo();
9414 }
9415
9416 uint32_t stage = mTransaction->HTTPSSVCReceivedStage();
9417 if (!LoadHTTPSSVCTelemetryReported() && stage != HTTPSSVC_NOT_USED) {
9418 glean::http::dns_httpssvc_record_receiving_stage.AccumulateSingleSample(
9419 stage);
9420 }
9421
9422 if (HTTPS_RR_IS_USED(stage)(stage > HTTPSSVC_NOT_PRESENT && stage < HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_2
)
) {
9423 nsAutoCString suffix(LoadEchConfigUsed() ? "_ech_used" : "");
9424 // Determine the result string based on the status.
9425 nsAutoCString result(NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) ? "success" : "failure");
9426 result.Append(suffix);
9427
9428 mozilla::glean::networking::http_channel_onstart_success_https_rr
9429 .Get(result)
9430 .Add(1);
9431 StoreHasHTTPSRR(true);
9432 }
9433
9434 StoreLoadedBySocketProcess(mTransaction->AsHttpTransactionParent() !=
9435 nullptr);
9436
9437 bool isTrr;
9438 bool echConfigUsed;
9439 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
9440 mEffectiveTRRMode, mTRRSkipReason,
9441 echConfigUsed);
9442 // update IP AddressSpace for non-proxy connections and tests
9443 // We need to update the browsing context for tests as browser tests
9444 // uses local proxy to connect to
9445 // external domains
9446 if (!mProxyInfo || xpc::IsInAutomation()) {
9447 // If this is main document load or iframe store the IP Address space in
9448 // the browsing context
9449 UpdateCurrentIpAddressSpace();
9450 }
9451
9452 StoreResolvedByTRR(isTrr);
9453 StoreEchConfigUsed(echConfigUsed);
9454 } else { // !mTransaction
9455 MaybeUpdateDocumentIPAddressSpaceFromCache();
9456 }
9457
9458 if (!mCanceled && mTransaction && IsInternalSystemLoad(mLoadInfo)) {
9459 // We have to report telemetry before we actually attempt to redirect to
9460 // the fallback domain because doing so will change mStatus
9461 ReportSystemChannelTelemetry(mStatus);
9462 }
9463
9464 // don't enter this block if we're reading from the cache...
9465 if (NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mCachePump && mTransaction) {
9466 // mTransactionPump doesn't hit OnInputStreamReady and call this until
9467 // all of the response headers have been acquired, so we can take
9468 // ownership of them from the transaction.
9469 RefPtr<nsHttpConnectionInfo> connInfo;
9470 mResponseHead =
9471 mTransaction->TakeResponseHeadAndConnInfo(getter_AddRefs(connInfo));
9472 mSupportsHTTP3 = mTransaction->GetSupportsHTTP3();
9473 // the response head may be null if the transaction was cancelled. in
9474 // which case we just need to call OnStartRequest/OnStopRequest.
9475 if (mResponseHead) {
9476 if (AntiTrackingUtils::ProcessStorageAccessHeadersShouldRetry(this)) {
9477 // force reload. Doom cache to avoid redirect loop
9478 if (mCacheEntry) {
9479 mCacheEntry->AsyncDoom(nullptr);
9480 }
9481
9482 auto storeAllowStorageAccess = [&](nsIChannel* aRedirectedChannel) {
9483 RefPtr<nsHttpChannel> httpChan = do_QueryObject(aRedirectedChannel);
9484 if (httpChan) {
9485 httpChan->StoreStorageAccessReloadChannel(true);
9486 }
9487 };
9488
9489 rv = StartRedirectChannelToURI(mURI,
9490 nsIChannelEventSink::REDIRECT_INTERNAL,
9491 storeAllowStorageAccess);
9492 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9493 Cancel(rv);
9494 return CallOnStartRequest();
9495 }
9496 return NS_OK;
9497 }
9498 return ProcessResponse(connInfo);
9499 }
9500
9501 NS_WARNING("No response head in OnStartRequest")NS_DebugBreak(NS_DEBUG_WARNING, "No response head in OnStartRequest"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 9501)
;
9502 }
9503
9504 // cache file could be deleted on our behalf, it could contain errors or
9505 // it failed to allocate memory, reload from network here.
9506 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)
) {
9507 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)
;
9508 mCacheEntry->AsyncDoom(nullptr);
9509 rv =
9510 StartRedirectChannelToURI(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
9511 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) return NS_OK;
9512 }
9513
9514 // If this is a system principal request to an essential domain and we
9515 // currently have connectivity, then check if there's a fallback domain we
9516 // can use to retry. If so we redirect to the fallback domain.
9517 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0))) && !mCanceled && IsInternalSystemLoad(mLoadInfo)) {
9518 if (StaticPrefs::network_essential_domains_fallback() &&
9519 hasConnectivity()) {
9520 auto passDomainCategory = [&](nsIChannel* aRedirectedChannel) {
9521 RefPtr<nsHttpChannel> httpChan = do_QueryObject(aRedirectedChannel);
9522 if (httpChan) {
9523 nsAutoCString host;
9524 mURI->GetHost(host);
9525 httpChan->mEssentialDomainCategory =
9526 Some(GetEssentialDomainCategory(host));
9527 }
9528 };
9529
9530 if (nsCOMPtr<nsIURI> fallbackURI = GetFallbackURI(mURI)) {
9531 rv = StartRedirectChannelToURI(fallbackURI,
9532 nsIChannelEventSink::REDIRECT_INTERNAL,
9533 passDomainCategory);
9534 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9535 nsCOMPtr<nsIObserverService> obsService =
9536 services::GetObserverService();
9537 if (obsService)
9538 obsService->NotifyObservers(static_cast<nsIHttpChannel*>(this),
9539 "httpchannel-fallback", nullptr);
9540 return NS_OK;
9541 }
9542 }
9543 }
9544 }
9545
9546 // avoid crashing if mListener happens to be null...
9547 if (!mListener) {
9548 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"
, 9548); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "mListener is null" ")"); do { MOZ_CrashSequence
(__null, 9548); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9549 return NS_OK;
9550 }
9551
9552 rv = ProcessCrossOriginSecurityHeaders();
9553 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
9554 mStatus = rv;
9555 HandleAsyncAbort();
9556 return rv;
9557 }
9558
9559 // No process change is needed, so continue on to ContinueOnStartRequest1.
9560 return ContinueOnStartRequest1(rv);
9561}
9562
9563void nsHttpChannel::MaybeUpdateDocumentIPAddressSpaceFromCache() {
9564 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"
, 9564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo" ")"
); do { MOZ_CrashSequence(__null, 9564); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9565 ExtContentPolicyType type = mLoadInfo->GetExternalContentPolicyType();
9566
9567 // Update the IPAddressSpace in the BrowsingContext only for main or sub
9568 // document
9569 if (type != ExtContentPolicy::TYPE_DOCUMENT &&
9570 type != ExtContentPolicy::TYPE_SUBDOCUMENT) {
9571 return;
9572 }
9573
9574 RefPtr<mozilla::dom::BrowsingContext> bc;
9575 mLoadInfo->GetTargetBrowsingContext(getter_AddRefs(bc));
9576
9577 if (!bc || !mCacheEntry) {
9578 return;
9579 }
9580
9581 nsAutoCString ipAddrStr, portStr;
9582 mCacheEntry->GetMetaDataElement("peer-ip-address", getter_Copies(ipAddrStr));
9583 mCacheEntry->GetMetaDataElement("peer-port", getter_Copies(portStr));
9584
9585 nsresult rv;
9586 uint32_t port = portStr.ToInteger(&rv);
9587
9588 if (!ipAddrStr.IsEmpty() && NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9589 NetAddr ipAddr;
9590 rv = ipAddr.InitFromString(ipAddrStr, port);
9591 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"
, 9591); return; } } while (false)
;
9592 mLoadInfo->SetIpAddressSpace(ipAddr.GetIpAddressSpace());
9593 bc->SetCurrentIPAddressSpace(ipAddr.GetIpAddressSpace());
9594 }
9595}
9596
9597nsresult nsHttpChannel::OnPermissionPromptResult(bool aGranted,
9598 const nsACString& aType) {
9599 mWaitingForLNAPermission = false;
9600
9601 if (aGranted) {
9602 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)
9603 ("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)
9604 "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)
9605 "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)
9606 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
9607 // we need to cache this data as permission manager is updated async and
9608 // might not be reflected immediately
9609 if (aType == LOOPBACK_NETWORK_PERMISSION_KEY) {
9610 mLNAPermission.mLocalHostPermission = LNAPermission::Granted;
9611 }
9612
9613 if (aType == LOCAL_NETWORK_PERMISSION_KEY) {
9614 mLNAPermission.mLocalNetworkPermission = LNAPermission::Granted;
9615 }
9616 // reset the transaction
9617 mTransaction = nullptr;
9618
9619 // resets streams and listener. Ensures we dont get any more callbacks to
9620 // nsHttpChannel from the pumps
9621 RefPtr<nsInputStreamPump> pump = do_QueryObject(mTransactionPump);
9622 if (pump) {
9623 pump->Reset();
9624 }
9625 mTransactionPump = nullptr;
9626
9627 // reset the status as we are going to replay the transaction
9628 mStatus = nsresult::NS_OK;
9629
9630 // allow notifications for the channel
9631 Resume();
9632 // replay the transaction with permisions granted
9633 return CallOrWaitForResume(
9634 [](auto* self) -> nsresult { return self->DoConnect(nullptr); });
9635 }
9636
9637 // permission denied
9638 // resume the transaction pump, we should get the OnStopRequest Notification
9639 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)
9640 ("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)
9641 "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)
9642 "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)
9643 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
9644
9645 Resume();
9646
9647 if (aType == LOOPBACK_NETWORK_PERMISSION_KEY) {
9648 mLNAPermission.mLocalHostPermission = LNAPermission::Denied;
9649 }
9650
9651 if (aType == LOCAL_NETWORK_PERMISSION_KEY) {
9652 mLNAPermission.mLocalNetworkPermission = LNAPermission::Denied;
9653 }
9654
9655 if (!mSuspendCount) {
9656 return ContinueOnStartRequest1(
9657 nsresult::NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED);
9658 }
9659 // channel is suspended state. We will continue when the channel is
9660 // resumed
9661 return CallOrWaitForResume([](auto* self) {
9662 return self->ContinueOnStartRequest1(
9663 nsresult::NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED);
9664 });
9665}
9666
9667nsresult nsHttpChannel::ContinueOnStartRequest1(nsresult result) {
9668 nsresult rv;
9669
9670 // if process selection failed, cancel this load.
9671 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
9672 Cancel(result);
9673 return CallOnStartRequest();
9674 }
9675
9676 // before we start any content load, check for redirectTo being called
9677 // this code is executed mainly before we start load from the cache
9678 if (mAPIRedirectTo && !mCanceled) {
9679 nsAutoCString redirectToSpec;
9680 mAPIRedirectTo->first()->GetAsciiSpec(redirectToSpec);
9681 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)
;
9682
9683 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", 9683
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
")"); do { MOZ_CrashSequence(__null, 9683); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9684 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
9685 rv = StartRedirectChannelToURI(
9686 mAPIRedirectTo->first(),
9687 mAPIRedirectTo->second() ? nsIChannelEventSink::REDIRECT_TEMPORARY |
9688 nsIChannelEventSink::REDIRECT_TRANSPARENT
9689 : nsIChannelEventSink::REDIRECT_TEMPORARY);
9690 mAPIRedirectTo = Nothing();
9691 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
9692 return NS_OK;
9693 }
9694 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest2);
9695 }
9696
9697 // Hack: ContinueOnStartRequest2 uses NS_OK to detect successful redirects,
9698 // so we distinguish this codepath (a non-redirect that's processing
9699 // normally) by passing in a bogus error code.
9700 return ContinueOnStartRequest2(NS_BINDING_FAILED);
9701}
9702
9703nsresult nsHttpChannel::ContinueOnStartRequest2(nsresult result) {
9704 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
9705 // Redirect has passed through, we don't want to go on with this
9706 // channel. It will now be canceled by the redirect handling code
9707 // that called this function.
9708 return NS_OK;
9709 }
9710
9711 // on proxy errors, try to failover
9712 if (mConnectionInfo->ProxyInfo() &&
9713 (mStatus == NS_ERROR_PROXY_CONNECTION_REFUSED ||
9714 mStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
9715 mStatus == NS_ERROR_NET_TIMEOUT || mStatus == NS_ERROR_NET_RESET)) {
9716 PushRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
9717 if (NS_SUCCEEDED(ProxyFailover())((bool)(__builtin_expect(!!(!NS_FAILED_impl(ProxyFailover()))
, 1)))
) {
9718 mProxyConnectResponseHead = nullptr;
9719 return NS_OK;
9720 }
9721 PopRedirectAsyncFunc(&nsHttpChannel::ContinueOnStartRequest3);
9722 }
9723
9724 // Hack: ContinueOnStartRequest3 uses NS_OK to detect successful redirects,
9725 // so we distinguish this codepath (a non-redirect that's processing
9726 // normally) by passing in a bogus error code.
9727 return ContinueOnStartRequest3(NS_BINDING_FAILED);
9728}
9729
9730nsresult nsHttpChannel::ContinueOnStartRequest3(nsresult result) {
9731 if (NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) {
9732 // Redirect has passed through, we don't want to go on with this
9733 // channel. It will now be canceled by the redirect handling code
9734 // that called this function.
9735 return NS_OK;
9736 }
9737
9738 return CallOnStartRequest();
9739}
9740
9741static void ReportHTTPSRRTelemetry(
9742 const Maybe<nsCOMPtr<nsIDNSHTTPSSVCRecord>>& aMaybeRecord) {
9743 bool hasHTTPSRR = aMaybeRecord && (aMaybeRecord.ref() != nullptr);
9744 if (!hasHTTPSRR) {
9745 mozilla::glean::networking::https_rr_presented.Get("none"_ns).Add(1);
9746 return;
9747 }
9748
9749 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& record = aMaybeRecord.ref();
9750 nsCOMPtr<nsISVCBRecord> svcbRecord;
9751 if (NS_SUCCEEDED(record->GetServiceModeRecord(false, false,((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
9752 getter_AddRefs(svcbRecord)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(record->GetServiceModeRecord
(false, false, getter_AddRefs(svcbRecord)))), 1)))
) {
9753 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"
, 9753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "svcbRecord"
")"); do { MOZ_CrashSequence(__null, 9753); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9754
9755 Maybe<std::tuple<nsCString, SupportedAlpnRank>> alpn =
9756 svcbRecord->GetAlpn();
9757 bool isHttp3 = alpn ? IsHttp3(std::get<1>(*alpn)) : false;
9758 mozilla::glean::networking::https_rr_presented
9759 .Get(isHttp3 ? "presented_with_http3"_ns : "presented"_ns)
9760 .Add(1);
9761 }
9762}
9763
9764static void RecordHttpChanDispositionGlean(ChannelDisposition chanDisposition) {
9765 switch (chanDisposition) {
9766 case kHttpCanceled:
9767 mozilla::glean::networking::http_channel_disposition
9768 .Get("http_cancelled"_ns)
9769 .Add(1);
9770 break;
9771 case kHttpDisk:
9772 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
9773 .Add(1);
9774 break;
9775 case kHttpNetOK:
9776 mozilla::glean::networking::http_channel_disposition.Get("http_net_ok"_ns)
9777 .Add(1);
9778 break;
9779 case kHttpNetEarlyFail:
9780 mozilla::glean::networking::http_channel_disposition
9781 .Get("http_net_early_fail"_ns)
9782 .Add(1);
9783 break;
9784 case kHttpNetLateFail:
9785 mozilla::glean::networking::http_channel_disposition
9786 .Get("http_net_late_fail"_ns)
9787 .Add(1);
9788 break;
9789 case kHttpsCanceled:
9790 mozilla::glean::networking::http_channel_disposition
9791 .Get("https_cancelled"_ns)
9792 .Add(1);
9793 break;
9794 case kHttpsDisk:
9795 mozilla::glean::networking::http_channel_disposition.Get("http_disk"_ns)
9796 .Add(1);
9797 break;
9798 case kHttpsNetOK:
9799 mozilla::glean::networking::http_channel_disposition
9800 .Get("https_net_ok"_ns)
9801 .Add(1);
9802 break;
9803 case kHttpsNetEarlyFail:
9804 mozilla::glean::networking::http_channel_disposition
9805 .Get("https_net_early_fail"_ns)
9806 .Add(1);
9807 break;
9808 case kHttpsNetLateFail:
9809 mozilla::glean::networking::http_channel_disposition
9810 .Get("https_net_late_fail"_ns)
9811 .Add(1);
9812 break;
9813 default:
9814 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"
, 9814); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for chanDisposition"
")"); do { MOZ_CrashSequence(__null, 9814); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9815 }
9816}
9817
9818enum class HttpChannelDispositionUpgrade {
9819 cancel,
9820 disk,
9821 netOk,
9822 netEarlyFail,
9823 netLateFail,
9824};
9825
9826static nsLiteralCString HttpChanDispositionToTelemetryLabel(
9827 HttpChannelDispositionUpgrade upgradeChanDisposition) {
9828 switch (upgradeChanDisposition) {
9829 case HttpChannelDispositionUpgrade::cancel:
9830 return "cancel"_ns;
9831 case HttpChannelDispositionUpgrade::disk:
9832 return "disk"_ns;
9833 case HttpChannelDispositionUpgrade::netOk:
9834 return "net_ok"_ns;
9835 case HttpChannelDispositionUpgrade::netEarlyFail:
9836 return "net_early_fail"_ns;
9837 case HttpChannelDispositionUpgrade::netLateFail:
9838 return "net_late_fail"_ns;
9839 }
9840
9841 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"
, 9841); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown value for upgradeChanDecomposition"
")"); do { MOZ_CrashSequence(__null, 9841); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9842 return "other"_ns;
9843}
9844
9845nsresult nsHttpChannel::LogConsoleError(const char* aTag) {
9846 nsCOMPtr<nsIConsoleService> console(mozilla::components::Console::Service());
9847 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", 9847
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9848
9849 nsCOMPtr<nsILoadInfo> loadInfo = LoadInfo();
9850 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", 9850
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9851 uint64_t innerWindowID = loadInfo->GetInnerWindowID();
9852
9853 nsAutoString errorText;
9854 nsresult rv = nsContentUtils::GetLocalizedString(
9855 PropertiesFile::NECKO_PROPERTIES, aTag, errorText);
9856 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"
, 9856); return rv; } } while (false)
;
9857
9858 nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID"@mozilla.org/scripterror;1"));
9859 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", 9859
); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
9860
9861 rv =
9862 error->InitWithSourceURI(errorText, mURI, 0, 0, nsIScriptError::errorFlag,
9863 "Invalid HTTP Status Lines"_ns, innerWindowID);
9864 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"
, 9864); return rv; } } while (false)
;
9865 console->LogMessage(error);
9866 return NS_OK;
9867}
9868
9869static void RecordHTTPSUpgradeTelemetry(nsIURI* aURI, nsILoadInfo* aLoadInfo) {
9870 // we record https telemetry only for top-level loads
9871 if (aLoadInfo->GetExternalContentPolicyType() !=
9872 ExtContentPolicy::TYPE_DOCUMENT) {
9873 return;
9874 }
9875
9876 // exempt loopback addresses because we only want to record telemetry
9877 // for actual web requests
9878 if (nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackURL(aURI)) {
9879 return;
9880 }
9881
9882 // todo: for now we don't record form submissions, only
9883 // top-level document loads. Once Bug 1720500 is fixed, we can
9884 // consider recording form submissions too.
9885 if (aLoadInfo->GetIsFormSubmission()) {
9886 return;
9887 }
9888
9889 bool isHTTPS = aURI->SchemeIs("https");
9890
9891 nsILoadInfo::HTTPSUpgradeTelemetryType httpsTelemetry =
9892 aLoadInfo->GetHttpsUpgradeTelemetry();
9893 switch (httpsTelemetry) {
9894 case nsILoadInfo::NOT_INITIALIZED: {
9895 if (isHTTPS) {
9896 // Bug 1912222: We should never encounter NOT_INITIALIZED values,
9897 // though we still want to know whether those loads are HTTPS
9898 // or not. Eventually we'll want to remove this if-clause
9899 // again and only report "not_initialized".
9900 mozilla::glean::networking::http_to_https_upgrade_reason
9901 .Get("not_initialized_https"_ns)
9902 .Add(1);
9903 return;
9904 }
9905 mozilla::glean::networking::http_to_https_upgrade_reason
9906 .Get("not_initialized"_ns)
9907 .Add(1);
9908 break;
9909 }
9910 case nsILoadInfo::NO_UPGRADE: {
9911 if (isHTTPS) {
9912 // Bug 1912222: We should rearely encounter NO_UPGRADE values, though
9913 // we still want to ensure those are not HTTPS. Eventually we'll want
9914 // to remove this if-clause again and only report "no_upgrade".
9915 mozilla::glean::networking::http_to_https_upgrade_reason
9916 .Get("no_upgrade_https"_ns)
9917 .Add(1);
9918 return;
9919 }
9920 mozilla::glean::networking::http_to_https_upgrade_reason
9921 .Get("no_upgrade"_ns)
9922 .Add(1);
9923 break;
9924 }
9925 case nsILoadInfo::ALREADY_HTTPS:
9926 mozilla::glean::networking::http_to_https_upgrade_reason
9927 .Get("already_https"_ns)
9928 .Add(1);
9929 break;
9930 case nsILoadInfo::HSTS:
9931 mozilla::glean::networking::http_to_https_upgrade_reason.Get("hsts"_ns)
9932 .Add(1);
9933 break;
9934 case nsILoadInfo::HTTPS_ONLY_UPGRADE:
9935 mozilla::glean::networking::http_to_https_upgrade_reason
9936 .Get("https_only_upgrade"_ns)
9937 .Add(1);
9938 break;
9939 case nsILoadInfo::HTTPS_ONLY_UPGRADE_DOWNGRADE:
9940 mozilla::glean::networking::http_to_https_upgrade_reason
9941 .Get("https_only_upgrade_downgrade"_ns)
9942 .Add(1);
9943 break;
9944 case nsILoadInfo::HTTPS_FIRST_UPGRADE:
9945 mozilla::glean::networking::http_to_https_upgrade_reason
9946 .Get("https_first_upgrade"_ns)
9947 .Add(1);
9948 break;
9949 case nsILoadInfo::HTTPS_FIRST_UPGRADE_DOWNGRADE:
9950 mozilla::glean::networking::http_to_https_upgrade_reason
9951 .Get("https_first_upgrade_downgrade"_ns)
9952 .Add(1);
9953 break;
9954 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE:
9955 mozilla::glean::networking::http_to_https_upgrade_reason
9956 .Get("https_first_schemeless_upgrade"_ns)
9957 .Add(1);
9958 break;
9959 case nsILoadInfo::HTTPS_FIRST_SCHEMELESS_UPGRADE_DOWNGRADE:
9960 mozilla::glean::networking::http_to_https_upgrade_reason
9961 .Get("https_first_schemeless_upgrade_downgrade"_ns)
9962 .Add(1);
9963 break;
9964 case nsILoadInfo::CSP_UIR:
9965 mozilla::glean::networking::http_to_https_upgrade_reason.Get("csp_uir"_ns)
9966 .Add(1);
9967 break;
9968 case nsILoadInfo::HTTPS_RR:
9969 mozilla::glean::networking::http_to_https_upgrade_reason
9970 .Get("https_rr"_ns)
9971 .Add(1);
9972 break;
9973 case nsILoadInfo::WEB_EXTENSION_UPGRADE:
9974 mozilla::glean::networking::http_to_https_upgrade_reason
9975 .Get("web_extension_upgrade"_ns)
9976 .Add(1);
9977 break;
9978 case nsILoadInfo::UPGRADE_EXCEPTION:
9979 mozilla::glean::networking::http_to_https_upgrade_reason
9980 .Get("upgrade_exception"_ns)
9981 .Add(1);
9982 break;
9983 case nsILoadInfo::SKIP_HTTPS_UPGRADE:
9984 mozilla::glean::networking::http_to_https_upgrade_reason
9985 .Get("skip_upgrade"_ns)
9986 .Add(1);
9987 break;
9988 default:
9989 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"
, 9989); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"what telemetry flag is set to end up here?" ")"); do { MOZ_CrashSequence
(__null, 9989); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
9990 }
9991}
9992
9993static void RecordIPAddressSpaceTelemetry(bool aLoadSuccess, nsIURI* aURI,
9994 nsILoadInfo* aLoadInfo,
9995 NetAddr& aPeerAddr) {
9996 // if the load was not successful, then there is nothing to record here
9997 if (!aLoadSuccess) {
9998 return;
9999 }
10000
10001 // we record https telemetry only for top-level loads
10002 if (aLoadInfo->GetExternalContentPolicyType() !=
10003 ExtContentPolicy::TYPE_DOCUMENT) {
10004 return;
10005 }
10006
10007 if (aURI->SchemeIs("https")) {
10008 mozilla::glean::networking::https_http_or_local.Get("load_is_https"_ns)
10009 .Add(1);
10010 return;
10011 }
10012
10013 if (aURI->SchemeIs("http")) {
10014 if (aPeerAddr.IsIPAddrLocal() || aPeerAddr.IsLoopbackAddr()) {
10015 mozilla::glean::networking::https_http_or_local
10016 .Get("load_is_http_for_local_domain"_ns)
10017 .Add(1);
10018 } else {
10019 mozilla::glean::networking::https_http_or_local.Get("load_is_http"_ns)
10020 .Add(1);
10021 }
10022 return;
10023 }
10024}
10025
10026static void RecordLNATelemetry(nsHttpChannel* aChannel, bool aLoadSuccess) {
10027 // Extract data from channel
10028 nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo();
10029 nsCOMPtr<nsIURI> uri;
10030 aChannel->GetURI(getter_AddRefs(uri));
10031 NetAddr peerAddr = aChannel->GetPeerAddr();
10032 const nsACString& promptAction = aChannel->GetLNAPromptAction();
10033
10034 if (!loadInfo || !uri) {
10035 return;
10036 }
10037
10038 RefPtr<mozilla::dom::BrowsingContext> bc;
10039 loadInfo->GetBrowsingContext(getter_AddRefs(bc));
10040
10041 nsILoadInfo::IPAddressSpace parentAddressSpace =
10042 mozilla::net::GetParentIPAddressSpace(loadInfo);
10043
10044 // Early return if NOT LNA - don't record telemetry or log
10045 if (!mozilla::net::IsLocalOrPrivateNetworkAccess(
10046 parentAddressSpace, loadInfo->GetIpAddressSpace())) {
10047 return;
10048 }
10049
10050 if (aLoadSuccess) {
10051 mozilla::glean::networking::local_network_access.Get("success"_ns).Add(1);
10052 } else {
10053 mozilla::glean::networking::local_network_access.Get("failure"_ns).Add(1);
10054 }
10055
10056 uint16_t port = 0;
10057 peerAddr.GetPort(&port);
10058
10059 // label format is <parentAddressSpace>_to_<targetAddressSpace>_<scheme>
10060 // At this point we are sure that the request is a LNA,
10061 // Hence we can safely assume few conditions to construct the label
10062 nsAutoCString glean_lna_label;
10063 if (parentAddressSpace == nsILoadInfo::IPAddressSpace::Public) {
10064 glean_lna_label.Append("public_to_"_ns);
10065 } else {
10066 glean_lna_label.Append("private_to_"_ns);
10067 }
10068 if (loadInfo->GetIpAddressSpace() == nsILoadInfo::IPAddressSpace::Private) {
10069 glean_lna_label.Append("private_"_ns);
10070 } else {
10071 glean_lna_label.Append("local_"_ns);
10072 }
10073 if (uri->SchemeIs("https")) {
10074 glean_lna_label.Append("https"_ns);
10075 } else {
10076 glean_lna_label.Append("http"_ns);
10077 }
10078
10079 mozilla::glean::networking::local_network_access.Get(glean_lna_label).Add(1);
10080
10081 // Get top-level site (main window principal) - TLD+1
10082 nsAutoCString topLevelSite;
10083 if (bc && bc->Top()) {
10084 if (bc->Top()->Canonical()) {
10085 RefPtr<mozilla::dom::WindowGlobalParent> topWindowGlobal =
10086 bc->Top()->Canonical()->GetCurrentWindowGlobal();
10087 if (topWindowGlobal) {
10088 nsCOMPtr<nsIPrincipal> topPrincipal =
10089 topWindowGlobal->DocumentPrincipal();
10090 if (topPrincipal) {
10091 (void)topPrincipal->GetBaseDomain(topLevelSite);
10092 }
10093 }
10094 }
10095 }
10096
10097 // Get initiator (triggering principal) - TLD+1
10098 nsAutoCString initiator;
10099 nsCOMPtr<nsIPrincipal> triggeringPrincipal;
10100 loadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
10101 if (triggeringPrincipal) {
10102 (void)triggeringPrincipal->GetBaseDomain(initiator);
10103 }
10104
10105 bool isSecureContext =
10106 triggeringPrincipal
10107 ? triggeringPrincipal->GetIsOriginPotentiallyTrustworthy()
10108 : false;
10109
10110 // Get target host - TLD+1
10111 nsCOMPtr<nsIEffectiveTLDService> eTLDService =
10112 mozilla::components::EffectiveTLD::Service();
10113 nsAutoCString targetHost;
10114 if (eTLDService) {
10115 (void)eTLDService->GetBaseDomain(uri, 0, targetHost);
10116 }
10117
10118 // Get target IP address
10119 nsCString targetIp = peerAddr.ToString();
10120
10121 // Determine protocol from LoadInfo
10122 nsAutoCString protocol;
10123 ExtContentPolicyType contentType = loadInfo->GetExternalContentPolicyType();
10124 switch (contentType) {
10125 case ExtContentPolicyType::TYPE_WEBSOCKET:
10126 protocol.AssignLiteral("websocket");
10127 break;
10128 case ExtContentPolicyType::TYPE_WEB_TRANSPORT:
10129 protocol.AssignLiteral("webtransport");
10130 break;
10131 case ExtContentPolicyType::TYPE_FETCH:
10132 protocol.AssignLiteral("fetch");
10133 break;
10134 case ExtContentPolicyType::TYPE_XMLHTTPREQUEST:
10135 protocol.AssignLiteral("xhr");
10136 break;
10137 default:
10138 if (uri->SchemeIs("https")) {
10139 protocol.AssignLiteral("https");
10140 } else {
10141 protocol.AssignLiteral("http");
10142 }
10143 break;
10144 }
10145
10146 // Record the event
10147 glean::networking::LocalNetworkAccessConnectionExtra extra = {
10148 .initiator = initiator.IsEmpty() ? Nothing() : Some(initiator),
10149 .isSecureContext = Some(isSecureContext),
10150 .loadSuccess = Some(aLoadSuccess),
10151 .promptAction =
10152 promptAction.IsEmpty() ? Nothing() : Some(nsCString(promptAction)),
10153 .protocol = Some(protocol),
10154 .targetHost = targetHost.IsEmpty() ? Nothing() : Some(targetHost),
10155 .targetIp = Some(targetIp),
10156 .targetPort = Some(port),
10157 .topLevelSite = topLevelSite.IsEmpty() ? Nothing() : Some(topLevelSite),
10158
10159 };
10160 glean::networking::local_network_access_connection.Record(Some(extra));
10161
10162 ReportLNAAccessToConsole(aChannel, "LocalNetworkAccessDetected",
10163 promptAction);
10164}
10165
10166NS_IMETHODIMPnsresult
10167nsHttpChannel::OnStopRequest(nsIRequest* request, nsresult status) {
10168 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", 10168
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncOpenTime.IsNull()"
")"); do { MOZ_CrashSequence(__null, 10168); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10169 AUTO_PROFILER_LABEL("nsHttpChannel::OnStopRequest", NETWORK)mozilla::AutoProfilerLabel raiiObject10169( "nsHttpChannel::OnStopRequest"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
10170 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnStopRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10171( "nsHttpChannel::OnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10171 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10171( "nsHttpChannel::OnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10172
10173 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)
10174 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)
;
10175
10176 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)
10177 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)
;
10178
10179 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"
, 10180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { MOZ_CrashSequence(__null, 10180); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10180 "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"
, 10180); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "OnStopRequest should only be called from the main thread"
")"); do { MOZ_CrashSequence(__null, 10180); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10181
10182 if (mStatus == NS_ERROR_PARSING_HTTP_STATUS_LINE) {
10183 (void)LogConsoleError("InvalidHTTPResponseStatusLine");
10184 }
10185
10186 // It's possible that LoadUseHTTPSSVC() is false, but we already have
10187 // mHTTPSSVCRecord.
10188 if (LoadUseHTTPSSVC() || mHTTPSSVCRecord) {
10189 ReportHTTPSRRTelemetry(mHTTPSSVCRecord);
10190 }
10191
10192 // If this load failed because of a security error, it may be because we
10193 // are in a captive portal - trigger an async check to make sure.
10194 int32_t nsprError = -1 * NS_ERROR_GET_CODE(status);
10195 if (mozilla::psm::IsNSSErrorCode(nsprError) && IsHTTPS()) {
10196 gIOService->RecheckCaptivePortal();
10197 }
10198
10199 if (request == mCachePump) {
10200 mCacheReadEnd = TimeStamp::Now();
10201 }
10202
10203 // allow content to be cached if it was loaded successfully (bug #482935)
10204 bool contentComplete = NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)));
10205
10206 // honor the cancelation status even if the underlying transaction
10207 // completed.
10208 if (mCanceled || NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) status = mStatus;
10209
10210 if (LoadCachedContentIsPartial()) {
10211 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
10212 // mTransactionPump should be suspended
10213 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"
, 10214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ MOZ_CrashSequence(__null, 10214); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
10214 "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"
, 10214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "request != mTransactionPump"
") (" "byte-range transaction finished prematurely" ")"); do
{ MOZ_CrashSequence(__null, 10214); __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
10215
10216 if (request == mCachePump) {
10217 bool streamDone;
10218 status = OnDoneReadingPartialCacheEntry(&streamDone);
10219 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) && !streamDone) return status;
10220 // otherwise, fall through and fire OnStopRequest...
10221 } else if (request == mTransactionPump) {
10222 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", 10222
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadConcurrentCacheAccess()"
")"); do { MOZ_CrashSequence(__null, 10222); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10223 } else {
10224 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"
, 10224); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected request" ")"); do { MOZ_CrashSequence
(__null, 10224); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10225 }
10226 }
10227 // Do not to leave the transaction in a suspended state in error cases.
10228 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0))) && mTransaction) {
10229 nsresult rv = gHttpHandler->CancelTransaction(mTransaction, status);
10230 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10231 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)
;
10232 }
10233 }
10234 }
10235
10236 nsCOMPtr<nsICompressConvStats> conv = do_QueryInterface(mCompressListener);
10237 if (conv) {
10238 uint64_t decodedDataLength = 0;
10239 conv->GetDecodedDataLength(&decodedDataLength);
10240 mDecodedBodySize = decodedDataLength;
10241 }
10242
10243 bool isFromNet = request == mTransactionPump;
10244
10245 if (mTransaction) {
10246 // determine if we should call DoAuthRetry
10247 bool authRetry = (mAuthRetryPending && NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1))) &&
10248 // we should only auth retry in this channel if are not
10249 // redirecting a new channel for authentication retries
10250 !StaticPrefs::network_auth_use_redirect_for_retries());
10251
10252 StoreStronglyFramed(mTransaction->ResponseIsComplete());
10253 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)
10254 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)
;
10255
10256 // Save the reference of |mTransaction| to |transactionWithStickyConn|
10257 // when it has a sticky connection.
10258 // In the case we need to retry an authentication request, we need to
10259 // reuse the connection of |transactionWithStickyConn|.
10260 RefPtr<HttpTransactionShell> transactionWithStickyConn;
10261 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2) ||
10262 mTransaction->HasStickyConnection()) {
10263 transactionWithStickyConn = mTransaction;
10264 // Make sure we use the updated caps and connection info from transaction.
10265 // We read these values when the transaction is already closed, so there
10266 // should be no race.
10267 if (mTransaction->Http2Disabled()) {
10268 mCaps |= NS_HTTP_DISALLOW_SPDY(1 << 7);
10269 }
10270 if (mTransaction->Http3Disabled()) {
10271 mCaps |= NS_HTTP_DISALLOW_HTTP3(1 << 21);
10272 }
10273 mConnectionInfo = mTransaction->GetConnInfo();
10274 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)
10275 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)
;
10276 }
10277
10278 // this code relies on the code in nsHttpTransaction::Close, which
10279 // tests for NS_HTTP_STICKY_CONNECTION to determine whether or not to
10280 // keep the connection around after the transaction is finished.
10281 //
10282 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)
10283 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)
10284 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)
;
10285 // We must check caps for stickinness also on the transaction because it
10286 // might have been updated by the transaction itself during inspection of
10287 // the reposnse headers yet on the socket thread (found connection based
10288 // auth schema).
10289
10290 if ((NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) && transactionWithStickyConn) {
10291 // Close (don't reuse) the sticky connection if this channel has been
10292 // cancelled. There are proxy servers known to get confused when we send
10293 // a new request over such a half-stated connection.
10294 if (!LoadAuthConnectionRestartable()) {
10295 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)
;
10296 transactionWithStickyConn->DontReuseConnection();
10297 }
10298 }
10299
10300 if (mCaps & NS_HTTP_STICKY_CONNECTION(1 << 2)) {
10301 mTransaction->SetH2WSConnRefTaken();
10302 }
10303
10304 mTransferSize = mTransaction->GetTransferSize();
10305 mRequestSize = mTransaction->GetRequestSize();
10306
10307 RecordHTTPSUpgradeTelemetry(mURI, mLoadInfo);
10308
10309 RecordIPAddressSpaceTelemetry(NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))), mURI, mLoadInfo,
10310 mPeerAddr);
10311 RecordLNATelemetry(this, NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))));
10312
10313 uint32_t flags;
10314 if (mStatus == NS_ERROR_LOCAL_NETWORK_ACCESS_DENIED &&
10315 StaticPrefs::network_lna_block_trackers() &&
10316 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
10317 mLoadInfo->GetTriggeringThirdPartyClassificationFlags(&flags))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mLoadInfo->GetTriggeringThirdPartyClassificationFlags
(&flags))), 1)))
&&
10318 flags != 0) {
10319 mozilla::glean::networking::local_network_blocked_tracker.Add(1);
10320 }
10321
10322 // If we are using the transaction to serve content, we also save the
10323 // time since async open in the cache entry so we can compare telemetry
10324 // between cache and net response.
10325 // Do not store the time of conditional requests because even if we
10326 // fetch the data from the server, the time includes loading of the old
10327 // cache entry which would skew the network load time.
10328 if (request == mTransactionPump && mCacheEntry && !mDidReval &&
10329 !LoadCustomConditionalRequest() && !mAsyncOpenTime.IsNull() &&
10330 !mOnStartRequestTimestamp.IsNull()) {
10331 uint64_t onStartTime =
10332 (mOnStartRequestTimestamp - mAsyncOpenTime).ToMilliseconds();
10333 uint64_t onStopTime =
10334 (TimeStamp::Now() - mAsyncOpenTime).ToMilliseconds();
10335 (void)mCacheEntry->SetNetworkTimes(onStartTime, onStopTime);
10336 }
10337
10338 mResponseTrailers = mTransaction->TakeResponseTrailers();
10339
10340 if (nsIOService::UseSocketProcess() && mTransaction) {
10341 mOnStopRequestStartTime = mTransaction->GetOnStopRequestStartTime();
10342 if (!mOnStopRequestStartTime.IsNull()) {
10343 PerfStats::RecordMeasurement(
10344 PerfStats::Metric::OnStopRequestSocketToParent,
10345 TimeStamp::Now() - mOnStopRequestStartTime);
10346 }
10347 } else {
10348 mOnStopRequestStartTime = TimeStamp::Now();
10349 }
10350
10351 // at this point, we're done with the transaction
10352 mTransactionTimings = mTransaction->Timings();
10353 mTransaction = nullptr;
10354 mTransactionPump = nullptr;
10355
10356 // We no longer need the dns prefetch object
10357 if (mDNSPrefetch && mDNSPrefetch->TimingsValid() &&
10358 !mTransactionTimings.requestStart.IsNull() &&
10359 !mTransactionTimings.connectStart.IsNull() &&
10360 mDNSPrefetch->EndTimestamp() <= mTransactionTimings.connectStart) {
10361 // We only need the domainLookup timestamps when not using a
10362 // persistent connection, meaning if the endTimestamp < connectStart
10363 mTransactionTimings.domainLookupStart = mDNSPrefetch->StartTimestamp();
10364 mTransactionTimings.domainLookupEnd = mDNSPrefetch->EndTimestamp();
10365 }
10366 mDNSPrefetch = nullptr;
10367
10368 // handle auth retry...
10369 if (authRetry) {
10370 mAuthRetryPending = false;
10371 auto continueOSR = [authRetry, isFromNet, contentComplete,
10372 transactionWithStickyConn](auto* self,
10373 nsresult aStatus) {
10374 return self->ContinueOnStopRequestAfterAuthRetry(
10375 aStatus, authRetry, isFromNet, contentComplete,
10376 transactionWithStickyConn);
10377 };
10378 status = DoAuthRetry(transactionWithStickyConn, continueOSR);
10379 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
10380 return NS_OK;
10381 }
10382 }
10383 return ContinueOnStopRequestAfterAuthRetry(status, authRetry, isFromNet,
10384 contentComplete,
10385 transactionWithStickyConn);
10386 }
10387
10388 return ContinueOnStopRequest(status, isFromNet, contentComplete);
10389}
10390
10391nsresult nsHttpChannel::ContinueOnStopRequestAfterAuthRetry(
10392 nsresult aStatus, bool aAuthRetry, bool aIsFromNet, bool aContentComplete,
10393 HttpTransactionShell* aTransWithStickyConn) {
10394 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)
10395 ("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)
10396 "[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)
10397 " 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)
10398 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)
10399 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)
;
10400
10401 if (aAuthRetry && NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1)))) {
10402 return NS_OK;
10403 }
10404
10405 // If DoAuthRetry failed, or if we have been cancelled since showing
10406 // the auth. dialog, then we need to send OnStartRequest now
10407 if (aAuthRetry || (mAuthRetryPending && NS_FAILED(aStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0))))) {
10408 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"
, 10408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(aStatus)), 0)))"
") (" "should have a failure code here" ")"); do { MOZ_CrashSequence
(__null, 10408); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10409 // NOTE: since we have a failure status, we can ignore the return
10410 // value from onStartRequest.
10411 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)
10412 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)
;
10413 if (mListener) {
10414 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"
, 10415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10415); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10415 "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"
, 10415); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10415); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10416 if (!LoadOnStartRequestCalled()) {
10417 nsCOMPtr<nsIStreamListener> listener(mListener);
10418 StoreOnStartRequestCalled(true);
10419 listener->OnStartRequest(this);
10420 }
10421 } else {
10422 StoreOnStartRequestCalled(true);
10423 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"
, 10423)
;
10424 }
10425 mAuthRetryPending = false;
10426 }
10427
10428 // if this transaction has been replaced, then bail.
10429 if (LoadTransactionReplaced()) {
10430 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)
;
10431 // This was just the network check for a 304 response.
10432 mFirstResponseSource = RESPONSE_PENDING;
10433 return NS_OK;
10434 }
10435
10436 bool upgradeWebsocket = mUpgradeProtocolCallback && aTransWithStickyConn &&
10437 mResponseHead &&
10438 ((mResponseHead->Status() == 101 &&
10439 mResponseHead->Version() == HttpVersion::v1_1) ||
10440 (mResponseHead->Status() == 200 &&
10441 mResponseHead->Version() == HttpVersion::v2_0));
10442
10443 bool upgradeConnect = mUpgradeProtocolCallback && aTransWithStickyConn &&
10444 (mCaps & NS_HTTP_CONNECT_ONLY(1 << 16)) && mResponseHead &&
10445 mResponseHead->Status() == 200;
10446
10447 if (upgradeWebsocket || upgradeConnect) {
10448 if (nsIOService::UseSocketProcess() && upgradeConnect) {
10449 // TODO: Support connection upgrade for socket process in bug 1632809.
10450 (void)mUpgradeProtocolCallback->OnUpgradeFailed(NS_ERROR_NOT_IMPLEMENTED);
10451 return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
10452 }
10453
10454 nsresult rv = gHttpHandler->CompleteUpgrade(aTransWithStickyConn,
10455 mUpgradeProtocolCallback);
10456 mUpgradeProtocolCallback = nullptr;
10457 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10458 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)
10459 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)
;
10460
10461 // This ensures that WebSocketChannel::OnStopRequest will be
10462 // called with an error so the session is properly aborted.
10463 aStatus = rv;
10464 }
10465 }
10466
10467 return ContinueOnStopRequest(aStatus, aIsFromNet, aContentComplete);
10468}
10469
10470nsresult nsHttpChannel::ContinueOnStopRequest(nsresult aStatus, bool aIsFromNet,
10471 bool aContentComplete) {
10472 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)
10473 ("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)
10474 "[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)
10475 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)
;
10476
10477 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::ContinueOnStopRequest", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10478( "nsHttpChannel::ContinueOnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10478 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10478( "nsHttpChannel::ContinueOnStopRequest"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10479 // HTTP_CHANNEL_DISPOSITION TELEMETRY
10480 ChannelDisposition chanDisposition = kHttpCanceled;
10481 // HTTP_CHANNEL_DISPOSITION_UPGRADE TELEMETRY
10482 HttpChannelDispositionUpgrade upgradeChanDisposition =
10483 HttpChannelDispositionUpgrade::cancel;
10484
10485 // HTTP 0.9 is more likely to be an error than really 0.9, so count it that
10486 // way
10487 if (mCanceled) {
10488 chanDisposition = kHttpCanceled;
10489 upgradeChanDisposition = HttpChannelDispositionUpgrade::cancel;
10490 } else if (!LoadUsedNetwork()) {
10491 chanDisposition = kHttpDisk;
10492 upgradeChanDisposition = HttpChannelDispositionUpgrade::disk;
10493 } else if (NS_SUCCEEDED(aStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aStatus)), 1))) && mResponseHead &&
10494 mResponseHead->Version() != HttpVersion::v0_9) {
10495 chanDisposition = kHttpNetOK;
10496 upgradeChanDisposition = HttpChannelDispositionUpgrade::netOk;
10497 } else if (!mTransferSize) {
10498 chanDisposition = kHttpNetEarlyFail;
10499 upgradeChanDisposition = HttpChannelDispositionUpgrade::netEarlyFail;
10500 } else {
10501 chanDisposition = kHttpNetLateFail;
10502 upgradeChanDisposition = HttpChannelDispositionUpgrade::netLateFail;
10503 }
10504 // Browser upgrading only happens on HTTPS pages for mixed passive content
10505 // when upgrading is enabled.
10506 nsCString upgradeKey;
10507 nsLiteralCString upgradeChanDispositionLabel =
10508 HttpChanDispositionToTelemetryLabel(upgradeChanDisposition);
10509 if (IsHTTPS()) {
10510 // Browser upgrading is disabled and the content is already HTTPS
10511 upgradeKey = "disabledNoReason"_ns;
10512 // Checks "security.mixed_content.upgrade_display_content" is true
10513 if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
10514 if (mLoadInfo->GetBrowserUpgradeInsecureRequests()) {
10515 // HTTP content the browser has upgraded to HTTPS
10516 mozilla::glean::networking::http_channel_disposition_enabled_upgrade
10517 .Get(upgradeChanDispositionLabel)
10518 .Add(1);
10519 upgradeKey = "enabledUpgrade"_ns;
10520 } else {
10521 // Content wasn't upgraded but is already HTTPS
10522 mozilla::glean::networking::http_channel_disposition_enabled_no_reason
10523 .Get(upgradeChanDispositionLabel)
10524 .Add(1);
10525 upgradeKey = "enabledNoReason"_ns;
10526 }
10527 } else {
10528 mozilla::glean::networking::http_channel_disposition_disabled_no_reason
10529 .Get(upgradeChanDispositionLabel)
10530 .Add(1);
10531 }
10532 // shift http to https disposition enums
10533 chanDisposition =
10534 static_cast<ChannelDisposition>(chanDisposition + kHttpsCanceled);
10535 } else if (mLoadInfo->GetBrowserWouldUpgradeInsecureRequests()) {
10536 // HTTP content the browser would upgrade to HTTPS if upgrading was
10537 // enabled
10538 mozilla::glean::networking::http_channel_disposition_disabled_upgrade
10539 .Get(upgradeChanDispositionLabel)
10540 .Add(1);
10541 upgradeKey = "disabledUpgrade"_ns;
10542 } else if (StaticPrefs::security_mixed_content_upgrade_display_content()) {
10543 // HTTP content that wouldn't upgrade
10544 mozilla::glean::networking::http_channel_disposition_enabled_wont
10545 .Get(upgradeChanDispositionLabel)
10546 .Add(1);
10547 upgradeKey = "enabledWont"_ns;
10548 } else {
10549 mozilla::glean::networking::http_channel_disposition_disabled_wont
10550 .Get(upgradeChanDispositionLabel)
10551 .Add(1);
10552 upgradeKey = "disabledWont"_ns;
10553 }
10554
10555 glean::networking::http_channel_disposition_upgrade
10556 .Get(upgradeKey, upgradeChanDispositionLabel)
10557 .Add();
10558
10559 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)
10560 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)
;
10561 glean::http::channel_disposition.AccumulateSingleSample(chanDisposition);
10562 RecordHttpChanDispositionGlean(chanDisposition);
10563
10564 // if needed, check cache entry has all data we expect
10565 if (mCacheEntry && mCachePump && LoadConcurrentCacheAccess() &&
10566 aContentComplete) {
10567 int64_t size, contentLength;
10568 nsresult rv = CheckPartial(mCacheEntry, &size, &contentLength);
10569 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10570 if (size == int64_t(-1)) {
10571 // mayhemer TODO - we have to restart read from cache here at the size
10572 // offset
10573 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"
, 10573); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ")"
); do { MOZ_CrashSequence(__null, 10573); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
10574 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)
10575 (" 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)
10576 "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)
;
10577 } else if (contentLength != int64_t(-1) && contentLength != size) {
10578 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)
;
10579 mCachedResponseHead = std::move(mResponseHead);
10580 // Ignore zero partial length because we also want to resume when
10581 // no data at all has been read from the cache.
10582 rv = MaybeSetupByteRangeRequest(size, contentLength, true);
10583 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && LoadIsPartialRequest()) {
10584 // Prevent read from cache again
10585 StoreCachedContentIsValid(CachedContentValidity::Invalid);
10586 StoreCachedContentIsPartial(1);
10587
10588 // Perform the range request
10589 rv = ContinueConnect();
10590 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10591 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)
;
10592 mCachePump = nullptr;
10593 return NS_OK;
10594 }
10595 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)
10596 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)
;
10597 aStatus = NS_ERROR_NET_INTERRUPT;
10598 } else {
10599 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)
10600 ", 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)
10601 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)
;
10602 aStatus = NS_ERROR_NET_INTERRUPT;
10603 }
10604
10605 // Range-request recovery failed. Restore mResponseHead so that
10606 // it's available to late callers of Cancel (such as the ORB
10607 // async JS-validation callback)
10608 mResponseHead = std::move(mCachedResponseHead);
10609 }
10610 }
10611 }
10612
10613 StoreIsPending(false);
10614 mStatus = aStatus;
10615
10616 // perform any final cache operations before we close the cache entry.
10617 if (mCacheEntry && LoadRequestTimeInitialized()) {
10618 // New implementation just returns value of the !LoadCacheEntryIsReadOnly()
10619 // flag passed in. Old implementation checks on nsICache::ACCESS_WRITE
10620 // flag.
10621
10622 // Assume that write access is granted
10623 if (!LoadCacheEntryIsReadOnly()) {
10624 nsresult rv = FinalizeCacheEntry();
10625 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10626 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)
;
10627 }
10628 }
10629 }
10630
10631 // Register entry to the PerformanceStorage resource timing
10632 MaybeReportTimingData();
10633
10634 MaybeFlushConsoleReports();
10635
10636 if (!mEndMarkerAdded && profiler_thread_is_being_profiled_for_markers()) {
10637 // These do allocations/frees/etc; avoid if not active
10638 mEndMarkerAdded = true;
10639
10640 nsAutoCString requestMethod;
10641 GetRequestMethod(requestMethod);
10642
10643 int32_t priority = PRIORITY_NORMAL;
10644 GetPriority(&priority);
10645
10646 uint64_t size = 0;
10647 GetEncodedBodySize(&size);
10648
10649 nsAutoCString contentType;
10650 mozilla::Maybe<mozilla::net::HttpVersion> httpVersion = Nothing();
10651 mozilla::Maybe<uint32_t> responseStatus = Nothing();
10652 if (mResponseHead) {
10653 mResponseHead->ContentType(contentType);
10654 httpVersion = Some(mResponseHead->Version());
10655 responseStatus = Some(mResponseHead->Status());
10656 }
10657
10658 profiler_add_network_marker(
10659 mURI, requestMethod, priority, mChannelId, NetworkLoadType::LOAD_STOP,
10660 mLastStatusReported, TimeStamp::Now(), size, mCacheDisposition,
10661 mLoadInfo->GetInnerWindowID(),
10662 mLoadInfo->GetOriginAttributes().IsPrivateBrowsing(), this, mStatus,
10663 GetSecPurpose(), mLoadInfo->GetActivatedFromNavigationalPrefetch(),
10664 &mTransactionTimings, std::move(mSource),
10665 // Skip the version for a cached response: it reflects the original
10666 // fetch, not this request's connection.
10667 (mCacheDisposition == kCacheHit ||
10668 mCacheDisposition == kCacheHitViaReval)
10669 ? Nothing()
10670 : httpVersion,
10671 responseStatus, Some(nsDependentCString(contentType.get())));
10672 }
10673
10674 if (mAuthRetryPending &&
10675 StaticPrefs::network_auth_use_redirect_for_retries()) {
10676 nsresult rv = OpenRedirectChannel(aStatus);
10677 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)
10678 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)
;
10679 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10680 if (mListener) {
10681 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"
, 10682); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10682); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10682 "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"
, 10682); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStartRequestCalled()"
") (" "We should not call OnStartRequest twice." ")"); do { MOZ_CrashSequence
(__null, 10682); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10683 if (!LoadOnStartRequestCalled()) {
10684 nsCOMPtr<nsIStreamListener> listener(mListener);
10685 StoreOnStartRequestCalled(true);
10686 listener->OnStartRequest(this);
10687 }
10688 } else {
10689 StoreOnStartRequestCalled(true);
10690 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"
, 10690)
;
10691 }
10692 }
10693 mAuthRetryPending = false;
10694 }
10695
10696 if (LoadUsedNetwork() && !mReportedNEL) {
10697 MaybeGenerateNELReport();
10698 }
10699
10700 // notify "http-on-before-stop-request" observers
10701 gHttpHandler->OnBeforeStopRequest(this);
10702
10703 if (mListener) {
10704 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)
;
10705 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", 10706
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { MOZ_CrashSequence(__null, 10706); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10706 "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", 10706
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadOnStartRequestCalled()"
") (" "OnStartRequest should be called before OnStopRequest"
")"); do { MOZ_CrashSequence(__null, 10706); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10707 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"
, 10708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { MOZ_CrashSequence
(__null, 10708); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10708 "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"
, 10708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!LoadOnStopRequestCalled()"
") (" "We should not call OnStopRequest twice" ")"); do { MOZ_CrashSequence
(__null, 10708); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10709 StoreOnStopRequestCalled(true);
10710 nsCOMPtr<nsIStreamListener> listener(mListener);
10711 listener->OnStopRequest(this, aStatus);
10712 }
10713 StoreOnStopRequestCalled(true);
10714
10715 // The prefetch needs to be released on the main thread
10716 mDNSPrefetch = nullptr;
10717
10718 mRedirectChannel = nullptr;
10719
10720 // notify "http-on-stop-request" observers
10721 gHttpHandler->OnStopRequest(this);
10722
10723 RemoveAsNonTailRequest();
10724
10725 if (mChannelBlockedByOpaqueResponse && mCachedOpaqueResponseBlockingPref &&
10726 mResponseHead) {
10727 mResponseHead->ClearHeaders();
10728 }
10729 // If a preferred alt-data type was set, this signals the consumer is
10730 // interested in reading and/or writing the alt-data representation.
10731 // We need to hold a reference to the cache entry in case the listener calls
10732 // openAlternativeOutputStream() after CloseCacheEntry() clears mCacheEntry.
10733 if (!mPreferredCachedAltDataTypes.IsEmpty()) {
10734 mAltDataCacheEntry = mCacheEntry;
10735 }
10736
10737 CloseCacheEntry(!aContentComplete);
10738 mWritingToCache = false;
10739
10740 if (mLoadGroup) {
10741 mLoadGroup->RemoveRequest(this, nullptr, aStatus);
10742 }
10743
10744 // We don't need this info anymore
10745 CleanRedirectCacheChainIfNecessary();
10746
10747 ReleaseListeners();
10748
10749 // Release mUploadStream to free some memory sooner.
10750 // We release this in background thread to avoid blocking I/O operations on
10751 // main thread See Bug 1940224
10752 (void)NS_DispatchBackgroundTask(NS_NewRunnableFunction(
10753 "release HttpBaseChannel::mUploadStream",
10754 [uploadStream = std::move(mUploadStream)]() { (void)uploadStream; }));
10755
10756 return NS_OK;
10757}
10758
10759//-----------------------------------------------------------------------------
10760// nsHttpChannel::nsIStreamListener
10761//-----------------------------------------------------------------------------
10762
10763class OnTransportStatusAsyncEvent : public Runnable {
10764 public:
10765 OnTransportStatusAsyncEvent(nsITransportEventSink* aEventSink,
10766 nsresult aTransportStatus, int64_t aProgress,
10767 int64_t aProgressMax)
10768 : Runnable("net::OnTransportStatusAsyncEvent"),
10769 mEventSink(aEventSink),
10770 mTransportStatus(aTransportStatus),
10771 mProgress(aProgress),
10772 mProgressMax(aProgressMax) {
10773 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"
, 10773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
") (" "Shouldn't be created on main thread" ")"); do { MOZ_CrashSequence
(__null, 10773); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10774 }
10775
10776 NS_IMETHODvirtual nsresult Run() override {
10777 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"
, 10777); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should run on main thread" ")"); do { MOZ_CrashSequence
(__null, 10777); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10778 if (mEventSink) {
10779 mEventSink->OnTransportStatus(nullptr, mTransportStatus, mProgress,
10780 mProgressMax);
10781 }
10782 return NS_OK;
10783 }
10784
10785 private:
10786 nsCOMPtr<nsITransportEventSink> mEventSink;
10787 nsresult mTransportStatus;
10788 int64_t mProgress;
10789 int64_t mProgressMax;
10790};
10791
10792NS_IMETHODIMPnsresult
10793nsHttpChannel::OnDataAvailable(nsIRequest* request, nsIInputStream* input,
10794 uint64_t offset, uint32_t count) {
10795 nsresult rv;
10796 AUTO_PROFILER_LABEL("nsHttpChannel::OnDataAvailable", NETWORK)mozilla::AutoProfilerLabel raiiObject10796( "nsHttpChannel::OnDataAvailable"
, nullptr, JS::ProfilingCategoryPair::NETWORK)
;
10797 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnDataAvailable", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject10798( "nsHttpChannel::OnDataAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
10798 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject10798( "nsHttpChannel::OnDataAvailable"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
10799
10800 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)
10801 " 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)
10802 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)
;
10803
10804 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)
10805 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)
;
10806
10807 // don't send out OnDataAvailable notifications if we've been canceled.
10808 if (mCanceled) return mStatus;
10809
10810 if (mAuthRetryPending ||
10811 (request == mTransactionPump && LoadTransactionReplaced())) {
10812 uint32_t n;
10813 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &n);
10814 }
10815
10816 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"
, 10816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mResponseHead"
") (" "No response head in ODA!!" ")"); do { MOZ_CrashSequence
(__null, 10816); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10817
10818 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"
, 10819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { MOZ_CrashSequence
(__null, 10819); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
10819 "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"
, 10819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(LoadCachedContentIsPartial() && (request == mTransactionPump))"
") (" "transaction pump not suspended" ")"); do { MOZ_CrashSequence
(__null, 10819); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10820
10821 mIsReadingFromCache = (request == mCachePump);
10822
10823 if (mListener) {
10824 //
10825 // synthesize transport progress event. we do this here since we want
10826 // to delay OnProgress events until we start streaming data. this is
10827 // crucially important since it impacts the lock icon (see bug 240053).
10828 //
10829 nsresult transportStatus;
10830 if (request == mCachePump) {
10831 transportStatus = NS_NET_STATUS_READING;
10832 } else {
10833 transportStatus = NS_NET_STATUS_RECEIVING_FROM;
10834 }
10835
10836 // mResponseHead may reference new or cached headers, but either way it
10837 // holds our best estimate of the total content length. Even in the case
10838 // of a byte range request, the content length stored in the cached
10839 // response headers is what we want to use here.
10840
10841 int64_t progressMax = -1;
10842 rv = GetContentLength(&progressMax);
10843 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
10844 NS_WARNING("GetContentLength failed")NS_DebugBreak(NS_DEBUG_WARNING, "GetContentLength failed", nullptr
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 10844
)
;
10845 }
10846 int64_t progress = mLogicalOffset + count;
10847
10848 if ((progress > progressMax) && (progressMax != -1)) {
10849 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10851)
10850 "unexpected progress values - "NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10851)
10851 "is server exceeding content length?")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values - "
"is server exceeding content length?", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10851)
;
10852 }
10853
10854 // make sure params are in range for js
10855 if (!InScriptableRange(progressMax)) {
10856 progressMax = -1;
10857 }
10858
10859 if (!InScriptableRange(progress)) {
10860 progress = -1;
10861 }
10862
10863 if (NS_IsMainThread()) {
10864 OnTransportStatus(nullptr, transportStatus, progress, progressMax);
10865 } else {
10866 rv = NS_DispatchToMainThread(new OnTransportStatusAsyncEvent(
10867 this, transportStatus, progress, progressMax));
10868 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"
, 10868); return rv; } } while (false)
;
10869 }
10870
10871 //
10872 // we have to manually keep the logical offset of the stream up-to-date.
10873 // we cannot depend solely on the offset provided, since we may have
10874 // already streamed some data from another source (see, for example,
10875 // OnDoneReadingPartialCacheEntry).
10876 //
10877 int64_t offsetBefore = 0;
10878 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(input);
10879 if (seekable && NS_FAILED(seekable->Tell(&offsetBefore))((bool)(__builtin_expect(!!(NS_FAILED_impl(seekable->Tell(
&offsetBefore))), 0)))
) {
10880 seekable = nullptr;
10881 }
10882
10883 if (nsIOService::UseSocketProcess() && mTransaction) {
10884 mOnDataAvailableStartTime = mTransaction->GetDataAvailableStartTime();
10885 if (!mOnDataAvailableStartTime.IsNull()) {
10886 PerfStats::RecordMeasurement(
10887 PerfStats::Metric::OnDataAvailableSocketToParent,
10888 TimeStamp::Now() - mOnDataAvailableStartTime);
10889 }
10890 } else {
10891 mOnDataAvailableStartTime = TimeStamp::Now();
10892 }
10893 nsCOMPtr<nsIStreamListener> listener = mListener;
10894 nsresult rv = listener->OnDataAvailable(this, input, mLogicalOffset, count);
10895 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
10896 // by contract mListener must read all of "count" bytes, but
10897 // nsInputStreamPump is tolerant to seekable streams that violate that
10898 // and it will redeliver incompletely read data. So we need to do
10899 // the same thing when updating the progress counter to stay in sync.
10900 int64_t offsetAfter, delta;
10901 if (seekable && NS_SUCCEEDED(seekable->Tell(&offsetAfter))((bool)(__builtin_expect(!!(!NS_FAILED_impl(seekable->Tell
(&offsetAfter))), 1)))
) {
10902 delta = offsetAfter - offsetBefore;
10903 if (delta != count) {
10904 count = delta;
10905
10906 NS_WARNING("Listener OnDataAvailable contract violation")NS_DebugBreak(NS_DEBUG_WARNING, "Listener OnDataAvailable contract violation"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10906)
;
10907 nsCOMPtr<nsIConsoleService> consoleService;
10908 consoleService = mozilla::components::Console::Service();
10909 nsAutoString message(nsLiteralString(
10910 u"http channel Listener OnDataAvailable contract violation"));
10911 if (consoleService) {
10912 consoleService->LogStringMessage(message.get());
10913 }
10914 }
10915 }
10916 mLogicalOffset += count;
10917 }
10918
10919 return rv;
10920 }
10921
10922 return NS_ERROR_ABORT;
10923}
10924
10925//-----------------------------------------------------------------------------
10926// nsHttpChannel::nsIThreadRetargetableRequest
10927//-----------------------------------------------------------------------------
10928
10929NS_IMETHODIMPnsresult
10930nsHttpChannel::RetargetDeliveryTo(nsISerialEventTarget* aNewTarget) {
10931 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"
, 10931); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be called on main thread only" ")"); do { MOZ_CrashSequence
(__null, 10931); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
10932
10933 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"
, 10933); return NS_ERROR_INVALID_ARG; } } while (false)
;
10934 if (aNewTarget->IsOnCurrentThread()) {
10935 NS_WARNING("Retargeting delivery to same thread")NS_DebugBreak(NS_DEBUG_WARNING, "Retargeting delivery to same thread"
, nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 10935)
;
10936 return NS_OK;
10937 }
10938 // Dictionary operations (saving, decompressing dcb/dcz, or using a
10939 // dictionary for decompression) require the main thread for hash
10940 // accumulation, origin metadata writes, and dictionary data access.
10941 if (mDictSaving || mIsDictionaryCompressed || mDictDecompress) {
10942 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)
10943 ("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)
10944 "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)
10945 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)
10946 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)
;
10947 return NS_ERROR_NOT_AVAILABLE;
10948 }
10949 if (!mTransactionPump && !mCachePump) {
10950 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)
10951 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)
;
10952 return NS_ERROR_NOT_AVAILABLE;
10953 }
10954
10955 nsresult rv = NS_OK;
10956 // If both cache pump and transaction pump exist, we're probably dealing
10957 // with partially cached content. So, we must be able to retarget both.
10958 nsCOMPtr<nsIThreadRetargetableRequest> retargetableCachePump;
10959 nsCOMPtr<nsIThreadRetargetableRequest> retargetableTransactionPump;
10960 if (mCachePump) {
10961 retargetableCachePump = do_QueryObject(mCachePump);
10962 // nsInputStreamPump should implement this interface.
10963 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", 10963
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableCachePump"
")"); do { MOZ_CrashSequence(__null, 10963); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10964 rv = retargetableCachePump->RetargetDeliveryTo(aNewTarget);
10965 }
10966 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && mTransactionPump) {
10967 retargetableTransactionPump = do_QueryObject(mTransactionPump);
10968 // nsInputStreamPump should implement this interface.
10969 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", 10969
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "retargetableTransactionPump"
")"); do { MOZ_CrashSequence(__null, 10969); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10970 rv = retargetableTransactionPump->RetargetDeliveryTo(aNewTarget);
10971
10972 // If retarget fails for transaction pump, we must restore mCachePump.
10973 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && retargetableCachePump) {
10974 nsCOMPtr<nsISerialEventTarget> main = GetMainThreadSerialEventTarget();
10975 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", 10975
); return NS_ERROR_UNEXPECTED; } } while (false)
;
10976 rv = retargetableCachePump->RetargetDeliveryTo(main);
10977 }
10978 }
10979 return rv;
10980}
10981
10982NS_IMETHODIMPnsresult
10983nsHttpChannel::GetDeliveryTarget(nsISerialEventTarget** aEventTarget) {
10984 if (mCachePump) {
10985 return mCachePump->GetDeliveryTarget(aEventTarget);
10986 }
10987 if (mTransactionPump) {
10988 nsCOMPtr<nsIThreadRetargetableRequest> request =
10989 do_QueryInterface(mTransactionPump);
10990 return request->GetDeliveryTarget(aEventTarget);
10991 }
10992 return NS_ERROR_NOT_AVAILABLE;
10993}
10994
10995//-----------------------------------------------------------------------------
10996// nsHttpChannel::nsThreadRetargetableStreamListener
10997//-----------------------------------------------------------------------------
10998
10999NS_IMETHODIMPnsresult
11000nsHttpChannel::CheckListenerChain() {
11001 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"
, 11001); MOZ_PretendNoReturn(); } } while (0)
;
11002 nsresult rv = NS_OK;
11003 nsCOMPtr<nsIThreadRetargetableStreamListener> retargetableListener =
11004 do_QueryInterface(mListener, &rv);
11005 if (retargetableListener) {
11006 rv = retargetableListener->CheckListenerChain();
11007 }
11008 return rv;
11009}
11010
11011NS_IMETHODIMPnsresult
11012nsHttpChannel::OnDataFinished(nsresult aStatus) {
11013 nsCOMPtr<nsIThreadRetargetableStreamListener> listener =
11014 do_QueryInterface(mListener);
11015
11016 if (listener) {
11017 return listener->OnDataFinished(aStatus);
11018 }
11019
11020 return NS_OK;
11021}
11022
11023//-----------------------------------------------------------------------------
11024// nsHttpChannel::nsITransportEventSink
11025//-----------------------------------------------------------------------------
11026
11027NS_IMETHODIMPnsresult
11028nsHttpChannel::OnTransportStatus(nsITransport* trans, nsresult status,
11029 int64_t progress, int64_t progressMax) {
11030 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"
, 11030); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Should be on main thread only" ")"); do { MOZ_CrashSequence
(__null, 11030); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11031 // cache the progress sink so we don't have to query for it each time.
11032 if (!mProgressSink) GetCallback(mProgressSink);
11033
11034 mLastTransportStatus = status;
11035 if (status == NS_NET_STATUS_CONNECTED_TO ||
11036 status == NS_NET_STATUS_WAITING_FOR) {
11037 bool isTrr = false;
11038 bool echConfigUsed = false;
11039 if (mTransaction) {
11040 mTransaction->GetNetworkAddresses(mSelfAddr, mPeerAddr, isTrr,
11041 mEffectiveTRRMode, mTRRSkipReason,
11042 echConfigUsed);
11043
11044 } else {
11045 nsCOMPtr<nsISocketTransport> socketTransport = do_QueryInterface(trans);
11046 if (socketTransport) {
11047 socketTransport->GetPeerAddr(&mPeerAddr);
11048 socketTransport->GetSelfAddr(&mSelfAddr);
11049 socketTransport->ResolvedByTRR(&isTrr);
11050 socketTransport->GetEffectiveTRRMode(&mEffectiveTRRMode);
11051 socketTransport->GetEchConfigUsed(&echConfigUsed);
11052 }
11053 }
11054
11055 StoreResolvedByTRR(isTrr);
11056 StoreEchConfigUsed(echConfigUsed);
11057 }
11058
11059 // block socket status event after Cancel or OnStopRequest has been called.
11060 if (mProgressSink && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && LoadIsPending()) {
11061 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)
11062 " 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)
11063 (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)
11064 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)
;
11065
11066 nsAutoCString host;
11067 mURI->GetHost(host);
11068 nsCOMPtr<nsIProgressEventSink> progressSink(mProgressSink);
11069 if (!(mLoadFlags & LOAD_BACKGROUND)) {
11070 progressSink->OnStatus(this, status, NS_ConvertUTF8toUTF16(host).get());
11071 } else {
11072 nsCOMPtr<nsIParentChannel> parentChannel;
11073 NS_QueryNotificationCallbacks(this, parentChannel);
11074 // If the event sink is |HttpChannelParent|, we have to send status
11075 // events to it even if LOAD_BACKGROUND is set. |HttpChannelParent|
11076 // needs to be aware of whether the status is
11077 // |NS_NET_STATUS_RECEIVING_FROM| or |NS_NET_STATUS_READING|.
11078 // LOAD_BACKGROUND is checked again in |HttpChannelChild|, so the final
11079 // consumer won't get this event.
11080 if (SameCOMIdentity(parentChannel, mProgressSink)) {
11081 progressSink->OnStatus(this, status, NS_ConvertUTF8toUTF16(host).get());
11082 }
11083 }
11084
11085 if (progress > 0) {
11086 if ((progress > progressMax) && (progressMax != -1)) {
11087 NS_WARNING("unexpected progress values")NS_DebugBreak(NS_DEBUG_WARNING, "unexpected progress values",
nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11087)
;
11088 }
11089
11090 // Try to get mProgressSink if it was nulled out during OnStatus.
11091 if (!mProgressSink) {
11092 GetCallback(mProgressSink);
11093 progressSink = mProgressSink;
11094 }
11095 if (progressSink) {
11096 progressSink->OnProgress(this, progress, progressMax);
11097 }
11098 }
11099 }
11100
11101 return NS_OK;
11102}
11103
11104//-----------------------------------------------------------------------------
11105// nsHttpChannel::nsICacheInfoChannel
11106//-----------------------------------------------------------------------------
11107
11108NS_IMETHODIMPnsresult
11109nsHttpChannel::IsFromCache(bool* value) {
11110 if (!LoadIsPending()) return NS_ERROR_NOT_AVAILABLE;
11111
11112 // return false if reading a partial cache entry; the data isn't
11113 // entirely from the cache!
11114 *value = (mCachePump || (mLoadFlags & LOAD_ONLY_IF_MODIFIED)) &&
11115 CachedContentIsValid() && !LoadCachedContentIsPartial();
11116 return NS_OK;
11117}
11118
11119NS_IMETHODIMPnsresult
11120nsHttpChannel::HasCacheEntry(bool* value) {
11121 *value = !!mCacheEntry;
11122 return NS_OK;
11123}
11124
11125NS_IMETHODIMPnsresult
11126nsHttpChannel::GetCacheEntryId(uint64_t* aCacheEntryId) {
11127 if (!mCacheEntry || NS_FAILED(mCacheEntry->GetCacheEntryId(aCacheEntryId))((bool)(__builtin_expect(!!(NS_FAILED_impl(mCacheEntry->GetCacheEntryId
(aCacheEntryId))), 0)))
) {
11128 return NS_ERROR_NOT_AVAILABLE;
11129 }
11130
11131 return NS_OK;
11132}
11133
11134NS_IMETHODIMPnsresult
11135nsHttpChannel::GetCacheTokenFetchCount(uint32_t* _retval) {
11136 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", 11136
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11137 nsCOMPtr<nsICacheEntry> cacheEntry =
11138 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11139 if (!cacheEntry) {
11140 return NS_ERROR_NOT_AVAILABLE;
11141 }
11142
11143 return cacheEntry->GetFetchCount(_retval);
11144}
11145
11146NS_IMETHODIMPnsresult
11147nsHttpChannel::GetCacheTokenExpirationTime(uint32_t* _retval) {
11148 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", 11148
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11149 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
11150
11151 return mCacheEntry->GetExpirationTime(_retval);
11152}
11153
11154NS_IMETHODIMPnsresult
11155nsHttpChannel::SetAllowStaleCacheContent(bool aAllowStaleCacheContent) {
11156 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)
11157 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)
;
11158 StoreAllowStaleCacheContent(aAllowStaleCacheContent);
11159 return NS_OK;
11160}
11161NS_IMETHODIMPnsresult
11162nsHttpChannel::GetAllowStaleCacheContent(bool* aAllowStaleCacheContent) {
11163 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"
, 11163); return NS_ERROR_INVALID_ARG; } } while (false)
;
11164 *aAllowStaleCacheContent = LoadAllowStaleCacheContent();
11165 return NS_OK;
11166}
11167
11168NS_IMETHODIMPnsresult
11169nsHttpChannel::SetForceValidateCacheContent(bool aForceValidateCacheContent) {
11170 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)
11171 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)
;
11172 StoreForceValidateCacheContent(aForceValidateCacheContent);
11173 return NS_OK;
11174}
11175NS_IMETHODIMPnsresult
11176nsHttpChannel::GetForceValidateCacheContent(bool* aForceValidateCacheContent) {
11177 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"
, 11177); return NS_ERROR_INVALID_ARG; } } while (false)
;
11178 *aForceValidateCacheContent = LoadForceValidateCacheContent();
11179 return NS_OK;
11180}
11181
11182NS_IMETHODIMPnsresult
11183nsHttpChannel::SetPreferCacheLoadOverBypass(bool aPreferCacheLoadOverBypass) {
11184 StorePreferCacheLoadOverBypass(aPreferCacheLoadOverBypass);
11185 return NS_OK;
11186}
11187NS_IMETHODIMPnsresult
11188nsHttpChannel::GetPreferCacheLoadOverBypass(bool* aPreferCacheLoadOverBypass) {
11189 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"
, 11189); return NS_ERROR_INVALID_ARG; } } while (false)
;
11190 *aPreferCacheLoadOverBypass = LoadPreferCacheLoadOverBypass();
11191 return NS_OK;
11192}
11193
11194NS_IMETHODIMPnsresult
11195nsHttpChannel::PreferAlternativeDataType(
11196 const nsACString& aType, const nsACString& aContentType,
11197 PreferredAlternativeDataDeliveryType aDeliverAltData) {
11198 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11198); 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"
, 11198, 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"
, 11198); } } while (0); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11198); 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"
, 11198); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
11199 mPreferredCachedAltDataTypes.AppendElement(PreferredAlternativeDataTypeParams(
11200 nsCString(aType), nsCString(aContentType), aDeliverAltData));
11201 return NS_OK;
11202}
11203
11204const nsTArray<PreferredAlternativeDataTypeParams>&
11205nsHttpChannel::PreferredAlternativeDataTypes() {
11206 return mPreferredCachedAltDataTypes;
11207}
11208
11209NS_IMETHODIMPnsresult
11210nsHttpChannel::GetAlternativeDataType(nsACString& aType) {
11211 // must be called during or after OnStartRequest
11212 if (!LoadAfterOnStartRequestBegun()) {
11213 return NS_ERROR_NOT_AVAILABLE;
11214 }
11215 aType = mAvailableCachedAltDataType;
11216 return NS_OK;
11217}
11218
11219class CacheEntryWriteHandle : public nsICacheEntryWriteHandle {
11220 virtual ~CacheEntryWriteHandle() = default;
11221
11222 public:
11223 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:
11224 NS_DECL_NSICACHEENTRYWRITEHANDLEvirtual nsresult OpenAlternativeOutputStream(const nsACString
& type, int64_t predictedSize, nsIAsyncOutputStream **_retval
) override;
11225
11226 explicit CacheEntryWriteHandle(nsICacheEntry* aCacheEntry)
11227 : mCacheEntry(aCacheEntry) {
11228 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"
, 11228); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCacheEntry"
")"); do { MOZ_CrashSequence(__null, 11228); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11229 }
11230
11231 private:
11232 nsCOMPtr<nsICacheEntry> mCacheEntry;
11233};
11234
11235NS_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"
, 11235); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 11235
); __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"
, 11235); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CacheEntryWriteHandle\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11235); __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; }
11236NS_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"
, 11236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 11236
); __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"
, 11236); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CacheEntryWriteHandle\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 11236); __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; }
11237NS_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"
, 11237); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
11238 NS_INTERFACE_MAP_ENTRY(nsISupports)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(this); else
11239 NS_INTERFACE_MAP_ENTRY(nsICacheEntryWriteHandle)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICacheEntryWriteHandle>)) foundInterface
= static_cast<nsICacheEntryWriteHandle*>(this); else
11240NS_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"
, 11240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 11240); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); status
= NS_NOINTERFACE; } else { (foundInterface)->AddRef(); status
= NS_OK; } *aInstancePtr = foundInterface; return status; }
11241
11242NS_IMETHODIMPnsresult
11243CacheEntryWriteHandle::OpenAlternativeOutputStream(
11244 const nsACString& type, int64_t predictedSize,
11245 nsIAsyncOutputStream** _retval) {
11246 nsresult rv =
11247 mCacheEntry->OpenAlternativeOutputStream(type, predictedSize, _retval);
11248 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11249 mCacheEntry->SetMetaDataElement("alt-data-from-child", nullptr);
11250 }
11251 return rv;
11252}
11253
11254NS_IMETHODIMPnsresult
11255nsHttpChannel::GetCacheEntryWriteHandle(nsICacheEntryWriteHandle** _retval) {
11256 nsCOMPtr<nsICacheEntry> cacheEntry =
11257 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11258 if (!cacheEntry) {
11259 return NS_ERROR_NOT_AVAILABLE;
11260 }
11261
11262 nsCOMPtr<nsICacheEntryWriteHandle> handle =
11263 new CacheEntryWriteHandle(cacheEntry);
11264 handle.forget(_retval);
11265 return NS_OK;
11266}
11267
11268NS_IMETHODIMPnsresult
11269nsHttpChannel::OpenAlternativeOutputStream(const nsACString& type,
11270 int64_t predictedSize,
11271 nsIAsyncOutputStream** _retval) {
11272 // OnStopRequest will clear mCacheEntry, but we may use mAltDataCacheEntry
11273 // if the consumer called PreferAlternativeDataType()
11274 nsCOMPtr<nsICacheEntry> cacheEntry =
11275 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11276 if (!cacheEntry) {
11277 return NS_ERROR_NOT_AVAILABLE;
11278 }
11279 nsresult rv =
11280 cacheEntry->OpenAlternativeOutputStream(type, predictedSize, _retval);
11281 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11282 // Clear this metadata flag in case it exists.
11283 // The caller of this method may set it again.
11284 cacheEntry->SetMetaDataElement("alt-data-from-child", nullptr);
11285 }
11286 return rv;
11287}
11288
11289NS_IMETHODIMPnsresult
11290nsHttpChannel::GetOriginalInputStream(nsIInputStreamReceiver* aReceiver) {
11291 if (aReceiver == nullptr) {
11292 return NS_ERROR_INVALID_ARG;
11293 }
11294 nsCOMPtr<nsIInputStream> inputStream;
11295
11296 nsCOMPtr<nsICacheEntry> cacheEntry =
11297 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11298 if (cacheEntry) {
11299 cacheEntry->OpenInputStream(0, getter_AddRefs(inputStream));
11300 }
11301 aReceiver->OnInputStreamReady(inputStream);
11302 return NS_OK;
11303}
11304
11305NS_IMETHODIMPnsresult
11306nsHttpChannel::GetAlternativeDataInputStream(nsIInputStream** aInputStream) {
11307 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"
, 11307); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11308
11309 *aInputStream = nullptr;
11310
11311 nsCOMPtr<nsICacheEntry> cacheEntry =
11312 mCacheEntry ? mCacheEntry : mAltDataCacheEntry;
11313 if (!mAvailableCachedAltDataType.IsEmpty() && cacheEntry) {
11314 nsresult rv = cacheEntry->OpenAlternativeInputStream(
11315 mAvailableCachedAltDataType, aInputStream);
11316 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"
, 11316); return rv; } } while (false)
;
11317 }
11318 return NS_OK;
11319}
11320
11321//-----------------------------------------------------------------------------
11322// nsHttpChannel::nsICachingChannel
11323//-----------------------------------------------------------------------------
11324
11325NS_IMETHODIMPnsresult
11326nsHttpChannel::GetCacheToken(nsISupports** token) {
11327 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", 11327
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11328 if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
11329 return CallQueryInterface(mCacheEntry, token);
11330}
11331
11332NS_IMETHODIMPnsresult
11333nsHttpChannel::SetCacheToken(nsISupports* token) {
11334 return NS_ERROR_NOT_IMPLEMENTED;
11335}
11336
11337NS_IMETHODIMPnsresult
11338nsHttpChannel::GetCacheKey(uint32_t* key) {
11339 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"
, 11339); return NS_ERROR_INVALID_POINTER; } } while (false)
;
11340
11341 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)
;
11342
11343 *key = mPostID;
11344 return NS_OK;
11345}
11346
11347NS_IMETHODIMPnsresult
11348nsHttpChannel::SetCacheKey(uint32_t key) {
11349 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)
;
11350
11351 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11351); 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"
, 11351, 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"
, 11351); } } 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", 11351
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 11351); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
11352
11353 mPostID = key;
11354 return NS_OK;
11355}
11356
11357NS_IMETHODIMPnsresult
11358nsHttpChannel::GetCacheOnlyMetadata(bool* aOnlyMetadata) {
11359 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"
, 11359); return NS_ERROR_INVALID_ARG; } } while (false)
;
11360 *aOnlyMetadata = LoadCacheOnlyMetadata();
11361 return NS_OK;
11362}
11363
11364NS_IMETHODIMPnsresult
11365nsHttpChannel::SetCacheOnlyMetadata(bool aOnlyMetadata) {
11366 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)
11367 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)
;
11368
11369 ENSURE_CALLED_BEFORE_ASYNC_OPEN()do { if (LoadIsPending() || LoadWasOpened()) { nsPrintfCString
msg("'%s' called after AsyncOpen: %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); } do { if ((__builtin_expect(!!(!(!LoadIsPending
())), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!LoadIsPending()" ") failed", nullptr, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11369); 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"
, 11369); return NS_ERROR_ALREADY_OPENED; } } while (false); }
while (0)
;
11370
11371 StoreCacheOnlyMetadata(aOnlyMetadata);
11372 if (aOnlyMetadata) {
11373 mLoadFlags |= LOAD_ONLY_IF_MODIFIED;
11374 }
11375
11376 return NS_OK;
11377}
11378
11379NS_IMETHODIMPnsresult
11380nsHttpChannel::GetPin(bool* aPin) {
11381 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", 11381
); return NS_ERROR_INVALID_ARG; } } while (false)
;
11382 *aPin = LoadPinCacheContent();
11383 return NS_OK;
11384}
11385
11386NS_IMETHODIMPnsresult
11387nsHttpChannel::SetPin(bool aPin) {
11388 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)
;
11389
11390 ENSURE_CALLED_BEFORE_CONNECT()do { if (LoadRequestObserversCalled()) { nsPrintfCString msg(
"'%s' called too late: %s +%d", __FUNCTION__, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp"
, 11390); 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"
, 11390, 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"
, 11390); } } 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", 11390
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWasOpened()" ")"
); do { MOZ_CrashSequence(__null, 11390); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); return NS_ERROR_ALREADY_OPENED
; } } while (0)
;
11391
11392 StorePinCacheContent(aPin);
11393 return NS_OK;
11394}
11395
11396NS_IMETHODIMPnsresult
11397nsHttpChannel::ForceCacheEntryValidFor(uint32_t aSecondsToTheFuture) {
11398 if (!mCacheEntry) {
11399 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)
11400 ("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)
11401 "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)
11402 this))do { const ::mozilla::LogModule* moz_real_module = mozilla::net
::gHttpLog; if ((__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)
;
11403 } else {
11404 mCacheEntry->ForceValidFor(aSecondsToTheFuture);
11405
11406 nsAutoCString key;
11407 mCacheEntry->GetKey(key);
11408
11409 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)
11410 ("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)
11411 "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)
11412 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)
;
11413 }
11414
11415 return NS_OK;
11416}
11417
11418//-----------------------------------------------------------------------------
11419// nsHttpChannel::nsIResumableChannel
11420//-----------------------------------------------------------------------------
11421
11422NS_IMETHODIMPnsresult
11423nsHttpChannel::ResumeAt(uint64_t aStartPos, const nsACString& aEntityID) {
11424 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)
11425 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)
;
11426 mEntityID = aEntityID;
11427 mStartPos = aStartPos;
11428 StoreResuming(true);
11429 return NS_OK;
11430}
11431
11432nsresult nsHttpChannel::DoAuthRetry(
11433 HttpTransactionShell* aTransWithStickyConn,
11434 const std::function<nsresult(nsHttpChannel*, nsresult)>&
11435 aContinueOnStopRequestFunc) {
11436 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)
11437 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)
;
11438
11439 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"
, 11439); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mTransaction"
") (" "should not have a transaction" ")"); do { MOZ_CrashSequence
(__null, 11439); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11440
11441 // Clear security info so it can be repopulated by the retried connection.
11442 mSecurityInfo = nullptr;
11443
11444 // Note that we don't have to toggle |IsPending| anymore. See the reasons
11445 // below.
11446 // 1. We can't suspend the channel during "http-on-modify-request"
11447 // when |IsPending| is false.
11448 // 2. We don't check |IsPending| in SetRequestHeader now.
11449
11450 // Reset RequestObserversCalled because we've probably called the request
11451 // observers once already.
11452 StoreRequestObserversCalled(false);
11453
11454 // fetch cookies, and add them to the request header.
11455 // the server response could have included cookies that must be sent with
11456 // this authentication attempt (bug 84794).
11457 // TODO: save cookies from auth response and send them here (bug 572151).
11458 AddCookiesToRequest();
11459
11460 // notify "http-on-modify-request" observers
11461 CallOnModifyRequestObservers();
11462
11463 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
11464 return CallOrWaitForResume(
11465 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
11466 return self->ContinueDoAuthRetry(trans, aContinueOnStopRequestFunc);
11467 });
11468}
11469
11470nsresult nsHttpChannel::ContinueDoAuthRetry(
11471 HttpTransactionShell* aTransWithStickyConn,
11472 const std::function<nsresult(nsHttpChannel*, nsresult)>&
11473 aContinueOnStopRequestFunc) {
11474 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)
;
11475 StoreIsPending(true);
11476
11477 // get rid of the old response headers
11478 mResponseHead = nullptr;
11479
11480 // rewind the upload stream
11481 if (mUploadStream) {
11482 nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mUploadStream);
11483 nsresult rv = NS_ERROR_NO_INTERFACE;
11484 if (seekable) {
11485 rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
11486 }
11487
11488 // This should not normally happen, but it's possible that big memory
11489 // blobs originating in the other process can't be rewinded.
11490 // In that case we just fail the request, otherwise the content length
11491 // will not match and this load will never complete.
11492 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"
, 11492); return rv; } } while (false)
;
11493 }
11494
11495 // always set sticky connection flag
11496 mCaps |= NS_HTTP_STICKY_CONNECTION(1 << 2);
11497 // and when needed, allow restart regardless the sticky flag
11498 if (LoadAuthConnectionRestartable()) {
11499 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)
;
11500 mCaps |= NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
11501 StoreAuthConnectionRestartable(false);
11502 } else {
11503 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)
;
11504 mCaps &= ~NS_HTTP_CONNECTION_RESTARTABLE(1 << 13);
11505 }
11506
11507 // notify "http-on-before-connect" observers
11508 gHttpHandler->OnBeforeConnect(this);
11509
11510 RefPtr<HttpTransactionShell> trans(aTransWithStickyConn);
11511 return CallOrWaitForResume(
11512 [trans{std::move(trans)}, aContinueOnStopRequestFunc](auto* self) {
11513 nsresult rv = self->DoConnect(trans);
11514 return aContinueOnStopRequestFunc(self, rv);
11515 });
11516}
11517
11518//-----------------------------------------------------------------------------
11519// nsHttpChannel::nsIAsyncVerifyRedirectCallback
11520//-----------------------------------------------------------------------------
11521
11522nsresult nsHttpChannel::WaitForRedirectCallback() {
11523 nsresult rv;
11524 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)
;
11525
11526 if (mTransactionPump) {
11527 rv = mTransactionPump->Suspend();
11528 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"
, 11528); return rv; } } while (false)
;
11529 }
11530 if (mCachePump) {
11531 rv = mCachePump->Suspend();
11532 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && mTransactionPump) {
11533#ifdef DEBUG1
11534 nsresult resume =
11535#endif
11536 mTransactionPump->Resume();
11537 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"
, 11537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(resume)), 1)))"
") (" "Failed to resume transaction pump" ")"); do { MOZ_CrashSequence
(__null, 11537); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11538 }
11539 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"
, 11539); return rv; } } while (false)
;
11540 }
11541
11542 StoreWaitingForRedirectCallback(true);
11543 return NS_OK;
11544}
11545
11546NS_IMETHODIMPnsresult
11547nsHttpChannel::OnRedirectVerifyCallback(nsresult result) {
11548 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)
11549 ("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)
11550 "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)
11551 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)
11552 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)
;
11553 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"
, 11554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { MOZ_CrashSequence(__null, 11554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
11554 "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"
, 11554); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadWaitingForRedirectCallback()"
") (" "Someone forgot to call WaitForRedirectCallback() ?!" ")"
); do { MOZ_CrashSequence(__null, 11554); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11555 StoreWaitingForRedirectCallback(false);
11556
11557 if (mCanceled && NS_SUCCEEDED(result)((bool)(__builtin_expect(!!(!NS_FAILED_impl(result)), 1)))) result = NS_BINDING_ABORTED;
11558
11559 for (uint32_t i = mRedirectFuncStack.Length(); i > 0;) {
11560 --i;
11561 // Pop the last function pushed to the stack
11562 nsContinueRedirectionFunc func = mRedirectFuncStack.PopLastElement();
11563
11564 // Call it with the result we got from the callback or the deeper
11565 // function call.
11566 result = (this->*func)(result);
11567
11568 // If a new function has been pushed to the stack and placed us in the
11569 // waiting state, we need to break the chain and wait for the callback
11570 // again.
11571 if (LoadWaitingForRedirectCallback()) break;
11572 }
11573
11574 if (NS_FAILED(result)((bool)(__builtin_expect(!!(NS_FAILED_impl(result)), 0))) && !mCanceled) {
11575 // First, cancel this channel if we are in failure state to set mStatus
11576 // and let it be propagated to pumps.
11577 Cancel(result);
11578 }
11579
11580 if (!LoadWaitingForRedirectCallback()) {
11581 // We are not waiting for the callback. At this moment we must release
11582 // reference to the redirect target channel, otherwise we may leak.
11583 // However, if we are redirecting due to auth retries, we open the
11584 // redirected channel after OnStopRequest. In that case we should not
11585 // release the reference
11586 if (!StaticPrefs::network_auth_use_redirect_for_retries() ||
11587 !mAuthRetryPending) {
11588 mRedirectChannel = nullptr;
11589 }
11590 }
11591
11592 // We always resume the pumps here. If all functions on stack have been
11593 // called we need OnStopRequest to be triggered, and if we broke out of the
11594 // loop above (and are thus waiting for a new callback) the suspension
11595 // count must be balanced in the pumps.
11596 if (mTransactionPump) mTransactionPump->Resume();
11597 if (mCachePump) mCachePump->Resume();
11598
11599 return result;
11600}
11601
11602void nsHttpChannel::PushRedirectAsyncFunc(nsContinueRedirectionFunc func) {
11603 mRedirectFuncStack.AppendElement(func);
11604}
11605
11606void nsHttpChannel::PopRedirectAsyncFunc(nsContinueRedirectionFunc func) {
11607 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"
, 11608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { MOZ_CrashSequence(__null, 11608); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11608 "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"
, 11608); AnnotateMozCrashReason("MOZ_ASSERT" "(" "func == mRedirectFuncStack.LastElement()"
") (" "Trying to pop wrong method from redirect async stack!"
")"); do { MOZ_CrashSequence(__null, 11608); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11609
11610 mRedirectFuncStack.RemoveLastElement();
11611}
11612
11613//-----------------------------------------------------------------------------
11614// nsIDNSListener functions
11615//-----------------------------------------------------------------------------
11616
11617NS_IMETHODIMPnsresult
11618nsHttpChannel::OnLookupComplete(nsICancelable* request, nsIDNSRecord* rec,
11619 nsresult status) {
11620 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"
, 11620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { MOZ_CrashSequence
(__null, 11620); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11621
11622 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)
11623 ("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)
11624 "%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)
11625 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)
11626 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)
11627 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)
;
11628
11629 // Unset DNS cache refresh if it was requested,
11630 if (mCaps & NS_HTTP_REFRESH_DNS(1 << 3)) {
11631 mCaps &= ~NS_HTTP_REFRESH_DNS(1 << 3);
11632 if (mTransaction) {
11633 mTransaction->SetDNSWasRefreshed();
11634 }
11635 }
11636
11637 if (!mDNSBlockingPromise.IsEmpty()) {
11638 if (NS_SUCCEEDED(status)((bool)(__builtin_expect(!!(!NS_FAILED_impl(status)), 1)))) {
11639 nsCOMPtr<nsIDNSRecord> record(rec);
11640 mDNSBlockingPromise.Resolve(record, __func__);
11641 } else {
11642 mDNSBlockingPromise.Reject(status, __func__);
11643 }
11644 }
11645
11646 return NS_OK;
11647}
11648
11649void nsHttpChannel::OnHTTPSRRAvailable(nsIDNSHTTPSSVCRecord* aRecord) {
11650 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"
, 11650); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Expecting DNS callback on main thread." ")"); do { MOZ_CrashSequence
(__null, 11650); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11651
11652 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)
11653 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)
;
11654
11655 if (mHTTPSSVCRecord) {
11656 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"
, 11656); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"OnHTTPSRRAvailable called twice!" ")"); do { MOZ_CrashSequence
(__null, 11656); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11657 return;
11658 }
11659
11660 nsCOMPtr<nsIDNSHTTPSSVCRecord> record = aRecord;
11661 mHTTPSSVCRecord.emplace(std::move(record));
11662 const nsCOMPtr<nsIDNSHTTPSSVCRecord>& httprr = mHTTPSSVCRecord.ref();
11663
11664 if (LoadWaitHTTPSSVCRecord()) {
11665 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", 11665
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mURI->SchemeIs(\"http\")"
")"); do { MOZ_CrashSequence(__null, 11665); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11666
11667 StoreWaitHTTPSSVCRecord(false);
11668 nsresult rv = ContinueOnBeforeConnect(!!httprr, mStatus, !!httprr);
11669 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11670 CloseCacheEntry(false);
11671 (void)AsyncAbort(rv);
11672 }
11673 } else {
11674 // This channel is not canceled and the transaction is not created.
11675 if (httprr && NS_SUCCEEDED(mStatus)((bool)(__builtin_expect(!!(!NS_FAILED_impl(mStatus)), 1))) && !mTransaction &&
11676 (mFirstResponseSource != RESPONSE_FROM_CACHE)) {
11677 bool hasIPAddress = false;
11678 (void)httprr->GetHasIPAddresses(&hasIPAddress);
11679 glean::http::dns_httpssvc_record_receiving_stage.AccumulateSingleSample(
11680 hasIPAddress ? HTTPSSVC_WITH_IPHINT_RECEIVED_STAGE_0
11681 : HTTPSSVC_WITHOUT_IPHINT_RECEIVED_STAGE_0);
11682 StoreHTTPSSVCTelemetryReported(true);
11683 }
11684 }
11685}
11686
11687//-----------------------------------------------------------------------------
11688// nsHttpChannel internal functions
11689//-----------------------------------------------------------------------------
11690
11691// Creates an URI to the given location using current URI for base and charset
11692nsresult nsHttpChannel::CreateNewURI(const char* loc, nsIURI** newURI) {
11693 nsCOMPtr<nsIIOService> ioService;
11694 nsresult rv = gHttpHandler->GetIOService(getter_AddRefs(ioService));
11695 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
11696
11697 return ioService->NewURI(nsDependentCString(loc), nullptr, mURI, newURI);
11698}
11699
11700void nsHttpChannel::MaybeInvalidateCacheEntryForSubsequentGet() {
11701 // See RFC 2616 section 5.1.1. These are considered valid
11702 // methods which DO NOT invalidate cache-entries for the
11703 // referred resource. POST, PUT and DELETE as well as any
11704 // other method not listed here will potentially invalidate
11705 // any cached copy of the resource
11706 if (mRequestHead.IsGet() || mRequestHead.IsOptions() ||
11707 mRequestHead.IsHead() || mRequestHead.IsTrace() ||
11708 mRequestHead.IsConnect()) {
11709 return;
11710 }
11711
11712 // Invalidate the request-uri.
11713 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
11714 nsAutoCString key;
11715 mURI->GetAsciiSpec(key);
11716 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)
11717 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)
;
11718 }
11719
11720 DoInvalidateCacheEntry(mURI);
11721
11722 // Invalidate Location-header if set
11723 nsAutoCString location;
11724 (void)mResponseHead->GetHeader(nsHttp::Location, location);
11725 if (!location.IsEmpty()) {
11726 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)
;
11727 InvalidateCacheEntryForLocation(location.get());
11728 }
11729
11730 // Invalidate Content-Location-header if set
11731 (void)mResponseHead->GetHeader(nsHttp::Content_Location, location);
11732 if (!location.IsEmpty()) {
11733 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)
;
11734 InvalidateCacheEntryForLocation(location.get());
11735 }
11736}
11737
11738void nsHttpChannel::InvalidateCacheEntryForLocation(const char* location) {
11739 nsAutoCString tmpCacheKey, tmpSpec;
11740 nsCOMPtr<nsIURI> resultingURI;
11741 nsresult rv = CreateNewURI(location, getter_AddRefs(resultingURI));
11742 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && HostPartIsTheSame(resultingURI)) {
11743 DoInvalidateCacheEntry(resultingURI);
11744 } else {
11745 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)
;
11746 }
11747}
11748
11749void nsHttpChannel::DoInvalidateCacheEntry(nsIURI* aURI) {
11750 // NOTE:
11751 // Following comments 24,32 and 33 in bug #327765, we only care about
11752 // the cache in the protocol-handler.
11753 // The logic below deviates from the original logic in OpenCacheEntry on
11754 // one point by using only READ_ONLY access-policy. I think this is safe.
11755
11756 nsresult rv;
11757
11758 nsAutoCString key;
11759 if (LOG_ENABLED()(__builtin_expect(!!(mozilla::detail::log_test(mozilla::net::
gHttpLog, mozilla::LogLevel::Verbose)), 0))
) {
11760 aURI->GetAsciiSpec(key);
11761 }
11762
11763 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)
;
11764
11765 nsCOMPtr<nsICacheStorageService> cacheStorageService(
11766 components::CacheStorage::Service());
11767 rv = cacheStorageService ? NS_OK : NS_ERROR_FAILURE;
11768
11769 nsCOMPtr<nsICacheStorage> cacheStorage;
11770 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11771 RefPtr<LoadContextInfo> info = GetLoadContextInfo(this);
11772 rv = cacheStorageService->DiskCacheStorage(info,
11773 getter_AddRefs(cacheStorage));
11774 }
11775
11776 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11777 rv = cacheStorage->AsyncDoomURI(aURI, ""_ns, nullptr);
11778 }
11779
11780 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)
11781 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)
;
11782}
11783
11784void nsHttpChannel::AsyncOnExamineCachedResponse() {
11785 gHttpHandler->OnExamineCachedResponse(this);
11786}
11787
11788void nsHttpChannel::UpdateAggregateCallbacks() {
11789 if (!mTransaction) {
11790 return;
11791 }
11792 nsCOMPtr<nsIInterfaceRequestor> callbacks;
11793 NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
11794 GetCurrentSerialEventTarget(),
11795 getter_AddRefs(callbacks));
11796 mTransaction->SetSecurityCallbacks(callbacks);
11797}
11798
11799NS_IMETHODIMPnsresult
11800nsHttpChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) {
11801 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"
, 11801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { MOZ_CrashSequence(__null, 11801
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
11802
11803 nsresult rv = HttpBaseChannel::SetLoadGroup(aLoadGroup);
11804 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11805 UpdateAggregateCallbacks();
11806 }
11807 return rv;
11808}
11809
11810NS_IMETHODIMPnsresult
11811nsHttpChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
11812 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"
, 11812); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Wrong thread." ")"); do { MOZ_CrashSequence(__null, 11812
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
11813
11814 nsresult rv = HttpBaseChannel::SetNotificationCallbacks(aCallbacks);
11815 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
11816 UpdateAggregateCallbacks();
11817 }
11818 return rv;
11819}
11820
11821bool nsHttpChannel::AwaitingCacheCallbacks() {
11822 return LoadWaitForCacheEntry() != 0;
11823}
11824
11825// static
11826bool nsHttpChannel::IsRedirectStatus(uint32_t status) {
11827 // 305 disabled as a security measure (see bug 187996).
11828 return status == 301 || status == 302 || status == 303 || status == 307 ||
11829 status == 308;
11830}
11831
11832void nsHttpChannel::SetCouldBeSynthesized() {
11833 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", 11833
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!BypassServiceWorker()"
")"); do { MOZ_CrashSequence(__null, 11833); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11834 StoreResponseCouldBeSynthesized(true);
11835}
11836
11837NS_IMETHODIMPnsresult
11838nsHttpChannel::OnPreflightSucceeded() {
11839 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"
, 11839); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { MOZ_CrashSequence
(__null, 11839); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11840 StoreIsCorsPreflightDone(1);
11841 mPreflightChannel = nullptr;
11842
11843 return ContinueConnect();
11844}
11845
11846NS_IMETHODIMPnsresult
11847nsHttpChannel::OnPreflightFailed(nsresult aError) {
11848 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"
, 11848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "LoadRequireCORSPreflight()"
") (" "Why did a preflight happen?" ")"); do { MOZ_CrashSequence
(__null, 11848); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
11849 StoreIsCorsPreflightDone(1);
11850 mPreflightChannel = nullptr;
11851
11852 CloseCacheEntry(false);
11853 (void)AsyncAbort(aError);
11854 return NS_OK;
11855}
11856
11857nsresult nsHttpChannel::CallOrWaitForResume(
11858 const std::function<nsresult(nsHttpChannel*)>& aFunc) {
11859 if (mCanceled) {
11860 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", 11860
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))"
")"); do { MOZ_CrashSequence(__null, 11860); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11861 return mStatus;
11862 }
11863
11864 if (mSuspendCount) {
11865 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)
;
11866 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", 11866
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mCallOnResume" ")"
); do { MOZ_CrashSequence(__null, 11866); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
11867 mCallOnResume = aFunc;
11868 return NS_OK;
11869 }
11870
11871 return aFunc(this);
11872}
11873
11874// This is loosely based on:
11875// https://fetch.spec.whatwg.org/#serializing-a-request-origin
11876static bool HasNullRequestOrigin(nsHttpChannel* aChannel, nsIURI* aURI,
11877 bool isAddonRequest) {
11878 // Step 1. If request has a redirect-tainted origin, then return "null".
11879 if (aChannel->HasRedirectTaintedOrigin()) {
11880 return true;
11881 }
11882
11883 // Non-standard: Only allow HTTP and HTTPS origins.
11884 if (!ReferrerInfo::IsReferrerSchemeAllowed(aURI)) {
11885 // And moz-extension: for add-on initiated requests.
11886 if (!aURI->SchemeIs("moz-extension") || !isAddonRequest) {
11887 return true;
11888 }
11889 }
11890
11891 // Non-standard: Hide onion URLs.
11892 if (StaticPrefs::network_http_referer_hideOnionSource()) {
11893 nsAutoCString host;
11894 if (NS_SUCCEEDED(aURI->GetAsciiHost(host))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aURI->GetAsciiHost
(host))), 1)))
&&
11895 StringEndsWith(host, ".onion"_ns)) {
11896 return ReferrerInfo::IsCrossOriginRequest(aChannel);
11897 }
11898 }
11899
11900 // Step 2. Return request’s origin, serialized.
11901 return false;
11902}
11903
11904// Step 8.12. of HTTP-network-or-cache fetch
11905//
11906// https://fetch.spec.whatwg.org/#append-a-request-origin-header
11907void nsHttpChannel::SetOriginHeader() {
11908 auto* triggeringPrincipal =
11909 BasePrincipal::Cast(mLoadInfo->TriggeringPrincipal());
11910
11911 if (triggeringPrincipal->IsSystemPrincipal()) {
11912 // We can't infer an Origin header from the system principal,
11913 // this means system requests use whatever Origin header was specified.
11914 return;
11915 }
11916 bool isAddonRequest = triggeringPrincipal->AddonPolicy() ||
11917 triggeringPrincipal->ContentScriptAddonPolicy();
11918
11919 // Non-standard: Handle already existing Origin header.
11920 nsAutoCString existingHeader;
11921 (void)mRequestHead.GetHeader(nsHttp::Origin, existingHeader);
11922 if (!existingHeader.IsEmpty()) {
11923 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)
;
11924 auto const shouldNullifyOriginHeader =
11925 [&existingHeader, isAddonRequest](nsHttpChannel* aChannel) {
11926 nsCOMPtr<nsIURI> uri;
11927 nsresult rv = NS_NewURI(getter_AddRefs(uri), existingHeader);
11928 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
11929 return false;
11930 }
11931
11932 if (HasNullRequestOrigin(aChannel, uri, isAddonRequest)) {
11933 return true;
11934 }
11935
11936 nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
11937 if (info->GetTainting() == mozilla::LoadTainting::CORS) {
11938 return false;
11939 }
11940
11941 return ReferrerInfo::ShouldSetNullOriginHeader(aChannel, uri);
11942 };
11943
11944 if (!existingHeader.EqualsLiteral("null") &&
11945 shouldNullifyOriginHeader(this)) {
11946 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)
;
11947 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", 11948
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { MOZ_CrashSequence(__null, 11948); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
11948 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", 11948
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, \"null\"_ns, false ))"
")"); do { MOZ_CrashSequence(__null, 11948); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
11949 }
11950 return;
11951 }
11952
11953 if (StaticPrefs::network_http_sendOriginHeader() == 0) {
11954 // Custom user setting: 0 means never send Origin header.
11955 return;
11956 }
11957
11958 // Step 2. Let serializedOrigin be the result of byte-serializing a request
11959 // origin with request.
11960 nsAutoCString serializedOrigin;
11961 nsCOMPtr<nsIURI> uri;
11962 {
11963 if (NS_FAILED(triggeringPrincipal->GetURI(getter_AddRefs(uri)))((bool)(__builtin_expect(!!(NS_FAILED_impl(triggeringPrincipal
->GetURI(getter_AddRefs(uri)))), 0)))
) {
11964 return;
11965 }
11966
11967 if (!uri) {
11968 if (isAddonRequest) {
11969 // For add-on compatibility prefer sending no header at all
11970 // instead of `Origin: null`.
11971 return;
11972 }
11973
11974 // Otherwise use "null" when the triggeringPrincipal's URI is nullptr.
11975 serializedOrigin.AssignLiteral("null");
11976 } else if (HasNullRequestOrigin(this, uri, isAddonRequest)) {
11977 serializedOrigin.AssignLiteral("null");
11978 } else {
11979 nsContentUtils::GetWebExposedOriginSerialization(uri, serializedOrigin);
11980 }
11981 }
11982
11983 // Step 3. If request’s response tainting is "cors" or request’s mode is
11984 // "websocket", then append (`Origin`, serializedOrigin) to request’s header
11985 // list.
11986 //
11987 // Note: We don't handle "websocket" here (yet?).
11988 if (mLoadInfo->GetTainting() == mozilla::LoadTainting::CORS) {
11989 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", 11990
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 11990); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
11990 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", 11990
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 11990); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
11991 return;
11992 }
11993
11994 // Step 4. Otherwise, if request’s method is neither `GET` nor `HEAD`, then:
11995 if (mRequestHead.IsGet() || mRequestHead.IsHead()) {
11996 // Modified Step 4 in case storage-access-headers are enabled
11997 if (!StaticPrefs::dom_storage_access_enabled() ||
11998 !StaticPrefs::dom_storage_access_headers_enabled()) {
11999 // proceed with unmodified fetch spec
12000 return;
12001 } else {
12002 // the result of getting `Sec-Fetch-Storage-Access` from request’s header
12003 // list is "inactive"
12004 nsAutoCString storageAccess;
12005 nsresult rv =
12006 GetRequestHeader("Sec-Fetch-Storage-Access"_ns, storageAccess);
12007 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !storageAccess.EqualsLiteral("inactive")) {
12008 return;
12009 }
12010 }
12011 }
12012
12013 if (!serializedOrigin.EqualsLiteral("null")) {
12014 // Step 4.1. (Implemented by ReferrerInfo::ShouldSetNullOriginHeader)
12015 if (ReferrerInfo::ShouldSetNullOriginHeader(this, uri)) {
12016 serializedOrigin.AssignLiteral("null");
12017 } else if (StaticPrefs::network_http_sendOriginHeader() == 1) {
12018 // Non-standard: Restrict Origin to same-origin loads if requested by user
12019 nsAutoCString currentOrigin;
12020 nsContentUtils::GetWebExposedOriginSerialization(mURI, currentOrigin);
12021 if (!serializedOrigin.EqualsIgnoreCase(currentOrigin.get())) {
12022 // Origin header suppressed by user setting.
12023 serializedOrigin.AssignLiteral("null");
12024 }
12025 }
12026 }
12027
12028 // Step 4.2. Append (`Origin`, serializedOrigin) to request’s header list.
12029 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", 12030
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12030); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
12030 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", 12030
); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mRequestHead.SetHeader(nsHttp::Origin, serializedOrigin, false ))"
")"); do { MOZ_CrashSequence(__null, 12030); __attribute__((
nomerge)) ::abort(); } while (false); } while (false); } } while
(false)
;
12031}
12032
12033void nsHttpChannel::SetDoNotTrack() {
12034 /**
12035 * 'DoNotTrack' header should be added if 'privacy.donottrackheader.enabled'
12036 * is true.
12037 */
12038 if (StaticPrefs::privacy_donottrackheader_enabled()) {
12039 DebugOnly<nsresult> rv =
12040 mRequestHead.SetHeader(nsHttp::DoNotTrack, "1"_ns, false);
12041 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"
, 12041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { MOZ_CrashSequence(__null, 12041); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12042 }
12043}
12044
12045void nsHttpChannel::SetGlobalPrivacyControl() {
12046 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"
, 12046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12046); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12047
12048 if (StaticPrefs::privacy_globalprivacycontrol_functionality_enabled() &&
12049 (StaticPrefs::privacy_globalprivacycontrol_enabled() ||
12050 (StaticPrefs::privacy_globalprivacycontrol_pbmode_enabled() &&
12051 NS_UsePrivateBrowsing(this)))) {
12052 // Send the header with a value of 1 to indicate opting-out
12053 DebugOnly<nsresult> rv =
12054 mRequestHead.SetHeader(nsHttp::GlobalPrivacyControl, "1"_ns, false);
12055 }
12056}
12057
12058void nsHttpChannel::ReportSystemChannelTelemetry(nsresult status) {
12059 // Use status and httpStatus to determine
12060 // if it was successful, and if we had connectivity / offline in this time
12061 nsAutoCString domain;
12062 mOriginalURI->GetHost(domain);
12063
12064 if (!LoadUsedNetwork()) {
12065 // We're not really interested in any cached requests.
12066 return;
12067 }
12068
12069 if (!StringEndsWith(domain, ".mozilla.org"_ns) &&
12070 !StringEndsWith(domain, ".mozilla.com"_ns) &&
12071 mEssentialDomainCategory.isNothing()) {
12072 return;
12073 }
12074
12075 nsAutoCString label("ok"_ns);
12076 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
12077 if (mCanceled) {
12078 // The request was cancelled.
12079 label = "cancel"_ns;
12080 } else if (NS_IsOffline()) {
12081 // The error occured while all interfaces are offline
12082 label = "offline"_ns;
12083 } else if (!hasConnectivity()) {
12084 // The error occured while the browser didn't have connectivity
12085 label = "connectivity"_ns;
12086 } else if (status == NS_ERROR_UNKNOWN_HOST) {
12087 // The failure was a DNS error
12088 label = "dns"_ns;
12089 } else if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY21) {
12090 // The error was due to TLS
12091 label = "tls_fail"_ns;
12092 } else if (status == NS_ERROR_NET_RESET) {
12093 label = "reset"_ns;
12094 } else if (status == NS_ERROR_NET_TIMEOUT) {
12095 label = "timeout"_ns;
12096 } else if (status == NS_ERROR_CONNECTION_REFUSED) {
12097 label = "refused"_ns;
12098 } else if (status == NS_ERROR_NET_PARTIAL_TRANSFER) {
12099 label = "partial"_ns;
12100 } else {
12101 // Unspecified error. If this bucket is too big we might add other labels.
12102 label = "other"_ns;
12103 }
12104 } else if (mResponseHead && mResponseHead->Status() / 100 != 2) {
12105 // There was no channel error, but the server responded with a non-2XX
12106 // status code.
12107 label = "http_status";
12108 }
12109
12110 // This is the first time failure channel
12111 if (mEssentialDomainCategory.isNothing()) {
12112 auto category = GetEssentialDomainCategory(domain);
12113 switch (category) {
12114 case EssentialDomainCategory::SubAddonsMozillaOrg: {
12115 mozilla::glean::network::system_channel_addonversion_status.Get(label)
12116 .Add(1);
12117 return;
12118 }
12119 case EssentialDomainCategory::AddonsMozillaOrg: {
12120 mozilla::glean::network::system_channel_addon_status.Get(label).Add(1);
12121 return;
12122 }
12123 case EssentialDomainCategory::Aus5MozillaOrg: {
12124 mozilla::glean::network::system_channel_update_status.Get(label).Add(1);
12125 return;
12126 }
12127 case EssentialDomainCategory::RemoteSettings: {
12128 mozilla::glean::network::system_channel_remote_settings_status
12129 .Get(label)
12130 .Add(1);
12131 return;
12132 }
12133 case EssentialDomainCategory::Telemetry: {
12134 mozilla::glean::network::system_channel_telemetry_status.Get(label).Add(
12135 1);
12136 return;
12137 }
12138 default: {
12139 // Not one of the probes we recorded earlier.
12140 mozilla::glean::network::system_channel_other_status.Get(label).Add(1);
12141 return;
12142 }
12143 }
12144 }
12145
12146 // This is a retry.
12147 switch (mEssentialDomainCategory.ref()) {
12148 case EssentialDomainCategory::SubAddonsMozillaOrg: {
12149 mozilla::glean::network::retried_system_channel_addonversion_status
12150 .Get(label)
12151 .Add(1);
12152 return;
12153 }
12154 case EssentialDomainCategory::AddonsMozillaOrg: {
12155 mozilla::glean::network::retried_system_channel_addon_status.Get(label)
12156 .Add(1);
12157 return;
12158 }
12159 case EssentialDomainCategory::Aus5MozillaOrg: {
12160 mozilla::glean::network::retried_system_channel_update_status.Get(label)
12161 .Add(1);
12162 return;
12163 }
12164 case EssentialDomainCategory::RemoteSettings: {
12165 mozilla::glean::network::retried_system_channel_remote_settings_status
12166 .Get(label)
12167 .Add(1);
12168 return;
12169 }
12170 case EssentialDomainCategory::Telemetry: {
12171 mozilla::glean::network::retried_system_channel_telemetry_status
12172 .Get(label)
12173 .Add(1);
12174 return;
12175 }
12176 default: {
12177 // Not one of the probes we recorded earlier.
12178 mozilla::glean::network::retried_system_channel_other_status.Get(label)
12179 .Add(1);
12180 return;
12181 }
12182 }
12183}
12184
12185nsresult nsHttpChannel::TriggerNetwork() {
12186 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"
, 12186); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12186); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12187
12188 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)
;
12189
12190 if (mCanceled) {
12191 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)
;
12192 return mStatus;
12193 }
12194
12195 // If a network request has already gone out, there is no point in
12196 // doing this again.
12197 if (mNetworkTriggered) {
12198 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)
;
12199 return NS_OK;
12200 }
12201
12202 mNetworkTriggered = true;
12203
12204 // If we are waiting for a proxy request, that means we can't trigger
12205 // the next step just yet. We need for mConnectionInfo to be non-null
12206 // before we call ContinueConnect. OnProxyAvailable will trigger
12207 // BeginConnect, and Connect will call ContinueConnect even if it's
12208 // for the cache callbacks.
12209 if (mProxyRequest) {
12210 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)
;
12211 mWaitingForProxy = true;
12212 return NS_OK;
12213 }
12214
12215 return ContinueConnect();
12216}
12217
12218nsresult nsHttpChannel::OnSuspendTimeout() {
12219 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"
, 12219); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
") (" "Must be called on the main thread" ")"); do { MOZ_CrashSequence
(__null, 12219); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12220
12221 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)
;
12222
12223 // If we're still suspended and have a cache entry, enable bypass mode
12224 // This allows any waiting or future listeners to continue
12225 if (mSuspendCount > 0 && mCacheEntry) {
12226 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)
;
12227 mCacheEntry->SetBypassWriterLock(true);
12228 mBypassCacheWriterSet = true;
12229 }
12230
12231 return NS_OK;
12232}
12233
12234nsHttpChannel::TimerCallback::TimerCallback(nsHttpChannel* aChannel)
12235 : mChannel(aChannel) {}
12236
12237NS_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"
, 12237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12237
); __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"
, 12237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12237); __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"
, 12237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12237
); __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"
, 12237); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsHttpChannel::TimerCallback\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12237); __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"
, 12237); 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; }
12238
12239NS_IMETHODIMPnsresult
12240nsHttpChannel::TimerCallback::GetName(nsACString& aName) {
12241 aName.AssignLiteral("nsHttpChannel");
12242 return NS_OK;
12243}
12244
12245NS_IMETHODIMPnsresult
12246nsHttpChannel::TimerCallback::Notify(nsITimer* aTimer) {
12247 if (aTimer == mChannel->mSuspendTimer) {
12248 return mChannel->OnSuspendTimeout();
12249 }
12250 if (aTimer == mChannel->mCacheWaitTimer) {
12251 return mChannel->OnCacheWaitTimeout();
12252 }
12253 MOZ_CRASH("Unknown timer")do { do { } while (false); MOZ_ReportCrash("" "Unknown timer"
, "./../../../../netwerk/protocol/http/nsHttpChannel.cpp", 12253
); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown timer" ")"); do
{ MOZ_CrashSequence(__null, 12253); __attribute__((nomerge))
::abort(); } while (false); } while (false)
;
12254
12255 return NS_OK;
12256}
12257
12258void nsHttpChannel::MaybeStartCacheWaitTimer() {
12259 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", 12259
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12259); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12260
12261 uint32_t delay = StaticPrefs::network_cache_entry_wait_timeout_ms();
12262 if (!delay || mCacheWaitTimer || mCacheWaitTimedOut || mNetworkTriggered) {
12263 return;
12264 }
12265
12266 mCacheWaitTimer = NS_NewTimer();
12267 if (mCacheWaitTimer) {
12268 RefPtr<TimerCallback> timerCallback = new TimerCallback(this);
12269 mCacheWaitTimer->InitWithCallback(timerCallback, delay,
12270 nsITimer::TYPE_ONE_SHOT);
12271 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)
12272 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)
;
12273 }
12274}
12275
12276void nsHttpChannel::CancelCacheWaitTimer() {
12277 if (mCacheWaitTimer) {
12278 mCacheWaitTimer->Cancel();
12279 mCacheWaitTimer = nullptr;
12280 }
12281}
12282
12283nsresult nsHttpChannel::OnCacheWaitTimeout() {
12284 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", 12284
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12284); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12285
12286 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)
;
12287 mCacheWaitTimer = nullptr;
12288
12289 // Backstop for a wedged cache entry: if we're still parked waiting for a
12290 // cache entry callback that never arrived (e.g. a writer that was suspended
12291 // or cancelled without ever closing its output stream, so the entry stays
12292 // perpetually "being written"), stop waiting and race to the network so the
12293 // load can make progress instead of hanging forever.
12294 if (!LoadIsPending() || !AwaitingCacheCallbacks()) {
12295 return NS_OK;
12296 }
12297
12298 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)
;
12299 mCacheWaitTimedOut = true;
12300
12301 // Stop treating the outstanding cache open as blocking. We stay registered
12302 // as a callback on the entry, but a late OnCacheEntryCheck or
12303 // OnCacheEntryAvailable will be declined/ignored (see mCacheWaitTimedOut).
12304 StoreWaitForCacheEntry(LoadWaitForCacheEntry() & ~WAIT_FOR_CACHE_ENTRY);
12305
12306 mCacheInputStream.CloseAndRelease();
12307 mAvailableCachedAltDataType.Truncate();
12308 StoreDeliveringAltData(false);
12309 mAltDataLength = -1;
12310
12311 nsresult rv = TriggerNetwork();
12312 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12313 CloseCacheEntry(false);
12314 (void)AsyncAbort(rv);
12315 }
12316 return rv;
12317}
12318
12319bool nsHttpChannel::EligibleForTailing() {
12320 if (!(mClassOfService.Flags() & nsIClassOfService::Tail)) {
12321 return false;
12322 }
12323
12324 if (mClassOfService.Flags() &
12325 (nsIClassOfService::UrgentStart | nsIClassOfService::Leader |
12326 nsIClassOfService::TailForbidden)) {
12327 return false;
12328 }
12329
12330 if (mClassOfService.Flags() & nsIClassOfService::Unblocked &&
12331 !(mClassOfService.Flags() & nsIClassOfService::TailAllowed)) {
12332 return false;
12333 }
12334
12335 if (IsNavigation()) {
12336 return false;
12337 }
12338
12339 return true;
12340}
12341
12342bool nsHttpChannel::WaitingForTailUnblock() {
12343 nsresult rv;
12344
12345 if (!gHttpHandler->IsTailBlockingEnabled()) {
12346 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)
;
12347 return false;
12348 }
12349
12350 if (!EligibleForTailing()) {
12351 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)
;
12352 AddAsNonTailRequest();
12353 return false;
12354 }
12355
12356 if (!EnsureRequestContext()) {
12357 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)
;
12358 return false;
12359 }
12360
12361 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)
12362 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)
;
12363
12364 bool blocked;
12365 rv = mRequestContext->IsContextTailBlocked(this, &blocked);
12366 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12367 return false;
12368 }
12369
12370 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)
;
12371
12372 return blocked;
12373}
12374
12375//-----------------------------------------------------------------------------
12376// nsHttpChannel::nsIRequestTailUnblockCallback
12377//-----------------------------------------------------------------------------
12378
12379// Must be implemented in the leaf class because we don't have
12380// AsyncAbort in HttpBaseChannel.
12381NS_IMETHODIMPnsresult
12382nsHttpChannel::OnTailUnblock(nsresult rv) {
12383 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)
12384 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)
;
12385 AUTO_PROFILER_FLOW_MARKER("nsHttpChannel::OnTailUnblock", NETWORK,::mozilla::AutoProfilerFlowMarker raiiObject12386( "nsHttpChannel::OnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
12386 Flow::FromPointer(this))::mozilla::AutoProfilerFlowMarker raiiObject12386( "nsHttpChannel::OnTailUnblock"
, ::mozilla::baseprofiler::category::NETWORK, Flow::FromPointer
(this))
;
12387 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", 12387
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mOnTailUnblock"
")"); do { MOZ_CrashSequence(__null, 12387); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12388
12389 if (NS_FAILED(mStatus)((bool)(__builtin_expect(!!(NS_FAILED_impl(mStatus)), 0)))) {
12390 rv = mStatus;
12391 }
12392
12393 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12394 auto callback = mOnTailUnblock;
12395 mOnTailUnblock = nullptr;
12396 rv = (this->*callback)();
12397 }
12398
12399 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12400 CloseCacheEntry(false);
12401 return AsyncAbort(rv);
12402 }
12403
12404 return NS_OK;
12405}
12406
12407void nsHttpChannel::SetWarningReporter(
12408 HttpChannelSecurityWarningReporter* aReporter) {
12409 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)
;
12410 mWarningReporter = aReporter;
12411}
12412
12413HttpChannelSecurityWarningReporter* nsHttpChannel::GetWarningReporter() {
12414 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)
12415 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)
;
12416 return mWarningReporter.get();
12417}
12418
12419// The specification for ORB is currently being written:
12420// https://whatpr.org/fetch/1442.html#orb-algorithm
12421// The `opaque-response-safelist check` is implemented in:
12422// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckBeforeSniff`
12423// * `nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck`
12424// * `HttpBaseChannel::PerformOpaqueResponseSafelistCheckAfterSniff`
12425// * `OpaqueResponseBlocker::ValidateJavaScript`
12426//
12427// Should only be called by nsMediaSniffer::GetMIMETypeFromContent and
12428// imageLoader::GetMIMETypeFromContent when the content type can be
12429// recognized by these sniffers.
12430void nsHttpChannel::DisableIsOpaqueResponseAllowedAfterSniffCheck(
12431 SnifferType aType) {
12432 // https://whatpr.org/fetch/1442.html#orb-algorithm
12433 // This method covers steps, 8 and 10.
12434 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", 12434
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "XRE_IsParentProcess()"
")"); do { MOZ_CrashSequence(__null, 12434); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12435
12436 if (NeedOpaqueResponseAllowedCheckAfterSniff()) {
12437 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"
, 12437); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mCachedOpaqueResponseBlockingPref"
")"); do { MOZ_CrashSequence(__null, 12437); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12438
12439 // If the sniffer type is media and the request comes from a media element,
12440 // we would like to check:
12441 // - Whether the information provided by the media element shows it's an
12442 // initial request.
12443 // - Whether the response's status is either 200 or 206.
12444 //
12445 // If any of the results is false, then we set
12446 // mBlockOpaqueResponseAfterSniff to true and block the response later.
12447 if (aType == SnifferType::Media) {
12448 // Step 8
12449 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"
, 12449); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mLoadInfo"
")"); do { MOZ_CrashSequence(__null, 12449); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12450
12451 auto noCorsMediaRequestState = NoCorsMediaRequestState();
12452 if (noCorsMediaRequestState !=
12453 dom::NoCorsMediaRequestState::NotAvailable) {
12454 if (noCorsMediaRequestState != dom::NoCorsMediaRequestState::Initial) {
12455 // Step 8.1
12456 BlockOpaqueResponseAfterSniff(
12457 u"media request after sniffing, but not initial request"_ns,
12458 OpaqueResponseBlockedTelemetryReason::eMediaNotInitial);
12459 return;
12460 }
12461
12462 if (mResponseHead->Status() != 200 && mResponseHead->Status() != 206) {
12463 // Step 8.2
12464 BlockOpaqueResponseAfterSniff(
12465 u"media request's response status is neither 200 nor 206"_ns,
12466 OpaqueResponseBlockedTelemetryReason::eMediaIncorrectResp);
12467 return;
12468 }
12469
12470 // At this point we've checked that the requested resource is media and
12471 // that the sniff passes. Any following requests for this resource
12472 // should be considered to be subsequent.
12473 RecordSubsequentNoCorsRequestState();
12474 }
12475 }
12476
12477 // Step 8.3 if `aType == SnifferType::Media`
12478 // Step 9 can be skipped, only `HTMLMediaElement` ever sets isMediaRequest.
12479 // Step 10 if `aType == SnifferType::Image`
12480 AllowOpaqueResponseAfterSniff();
12481 }
12482}
12483
12484namespace {
12485
12486class CopyNonDefaultHeaderVisitor final : public nsIHttpHeaderVisitor {
12487 nsCOMPtr<nsIHttpChannel> mTarget;
12488
12489 ~CopyNonDefaultHeaderVisitor() = default;
12490
12491 NS_IMETHODvirtual nsresult
12492 VisitHeader(const nsACString& aHeader, const nsACString& aValue) override {
12493 if (aValue.IsEmpty()) {
12494 return mTarget->SetEmptyRequestHeader(aHeader);
12495 }
12496 return mTarget->SetRequestHeader(aHeader, aValue, false /* merge */);
12497 }
12498
12499 public:
12500 explicit CopyNonDefaultHeaderVisitor(nsIHttpChannel* aTarget)
12501 : mTarget(aTarget) {
12502 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"
, 12502); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "mTarget"
")"); do { MOZ_CrashSequence(__null, 12502); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12503 }
12504
12505 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:
12506};
12507
12508NS_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"
, 12508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12508
); __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"
, 12508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12508); __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"
, 12508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12508
); __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"
, 12508); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CopyNonDefaultHeaderVisitor\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12508); __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"
, 12508); 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; }
12509
12510} // anonymous namespace
12511
12512nsresult nsHttpChannel::RedirectToInterceptedChannel() {
12513 nsCOMPtr<nsINetworkInterceptController> controller;
12514 GetCallback(controller);
12515
12516 RefPtr<InterceptedHttpChannel> intercepted =
12517 InterceptedHttpChannel::CreateForInterception(
12518 mChannelCreationTime, mChannelCreationTimestamp, mAsyncOpenTime);
12519
12520 nsCOMPtr<nsILoadInfo> redirectLoadInfo =
12521 CloneLoadInfoForRedirect(mURI, nsIChannelEventSink::REDIRECT_INTERNAL);
12522
12523 nsresult rv = intercepted->Init(
12524 mURI, mCaps, static_cast<nsProxyInfo*>(mProxyInfo.get()),
12525 mProxyResolveFlags, mProxyURI, mChannelId, redirectLoadInfo);
12526
12527 rv = SetupReplacementChannel(mURI, intercepted, true,
12528 nsIChannelEventSink::REDIRECT_INTERNAL);
12529 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"
, 12529); return rv; } } while (false)
;
12530
12531 // Some APIs, like fetch(), allow content to set non-standard headers.
12532 // Normally these APIs are responsible for copying these headers across
12533 // redirects. In the e10s parent-side intercept case, though, we currently
12534 // "hide" the internal redirect to the InterceptedHttpChannel. So the
12535 // fetch() API does not have the opportunity to move headers over.
12536 // Therefore, we do it automatically here.
12537 //
12538 // Once child-side interception is removed and the internal redirect no
12539 // longer needs to be "hidden", then this header copying code can be
12540 // removed.
12541 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
12542 new CopyNonDefaultHeaderVisitor(intercepted);
12543 rv = VisitNonDefaultRequestHeaders(visitor);
12544 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"
, 12544); return rv; } } while (false)
;
12545
12546 mRedirectChannel = intercepted;
12547
12548 PushRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
12549
12550 rv = gHttpHandler->AsyncOnChannelRedirect(
12551 this, intercepted, nsIChannelEventSink::REDIRECT_INTERNAL);
12552
12553 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
12554 rv = WaitForRedirectCallback();
12555 }
12556
12557 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12558 AutoRedirectVetoNotifier notifier(this, rv);
12559
12560 PopRedirectAsyncFunc(&nsHttpChannel::ContinueAsyncRedirectChannelToURI);
12561 }
12562
12563 return rv;
12564}
12565
12566void nsHttpChannel::ReEvaluateReferrerAfterTrackingStatusIsKnown() {
12567 nsCOMPtr<nsICookieJarSettings> cjs;
12568 if (mLoadInfo) {
12569 (void)mLoadInfo->GetCookieJarSettings(getter_AddRefs(cjs));
12570 }
12571 if (!cjs) {
12572 cjs = net::CookieJarSettings::Create(mLoadInfo->GetLoadingPrincipal());
12573 }
12574 if (cjs->GetRejectThirdPartyContexts()) {
12575 bool isPrivate = mLoadInfo->GetOriginAttributes().IsPrivateBrowsing();
12576 // If our referrer has been set before, and our referrer policy is unset
12577 // (default policy) if we thought the channel wasn't a third-party
12578 // tracking channel, we may need to set our referrer with referrer policy
12579 // once again to ensure our defaults properly take effect now.
12580 if (mReferrerInfo) {
12581 ReferrerInfo* referrerInfo =
12582 static_cast<ReferrerInfo*>(mReferrerInfo.get());
12583
12584 if (referrerInfo->IsPolicyOverrided() &&
12585 referrerInfo->ReferrerPolicy() ==
12586 ReferrerInfo::GetDefaultReferrerPolicy(nullptr, nullptr,
12587 isPrivate)) {
12588 nsCOMPtr<nsIReferrerInfo> newReferrerInfo =
12589 referrerInfo->CloneWithNewPolicy(
12590 ReferrerInfo::GetDefaultReferrerPolicy(this, mURI, isPrivate));
12591 // The arguments passed to SetReferrerInfoInternal here should mirror
12592 // the arguments passed in
12593 // HttpChannelChild::RecvOverrideReferrerInfoDuringBeginConnect().
12594 SetReferrerInfoInternal(newReferrerInfo, false, true, true);
12595
12596 nsCOMPtr<nsIParentChannel> parentChannel;
12597 NS_QueryNotificationCallbacks(this, parentChannel);
12598 RefPtr<HttpChannelParent> httpParent = do_QueryObject(parentChannel);
12599 if (httpParent) {
12600 httpParent->OverrideReferrerInfoDuringBeginConnect(newReferrerInfo);
12601 }
12602 }
12603 }
12604 }
12605}
12606
12607namespace {
12608
12609class BackgroundRevalidatingListener : public nsIStreamListener {
12610 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:
12611
12612 NS_DECL_NSISTREAMLISTENERvirtual nsresult OnDataAvailable(nsIRequest *aRequest, nsIInputStream
*aInputStream, uint64_t aOffset, uint32_t aCount) override;
12613 NS_DECL_NSIREQUESTOBSERVERvirtual nsresult OnStartRequest(nsIRequest *aRequest) override
; virtual nsresult OnStopRequest(nsIRequest *aRequest, nsresult
aStatusCode) override;
12614
12615 private:
12616 virtual ~BackgroundRevalidatingListener() = default;
12617};
12618
12619NS_IMETHODIMPnsresult
12620BackgroundRevalidatingListener::OnStartRequest(nsIRequest* request) {
12621 return NS_OK;
12622}
12623
12624NS_IMETHODIMPnsresult
12625BackgroundRevalidatingListener::OnDataAvailable(nsIRequest* request,
12626 nsIInputStream* input,
12627 uint64_t offset,
12628 uint32_t count) {
12629 uint32_t bytesRead = 0;
12630 return input->ReadSegments(NS_DiscardSegment, nullptr, count, &bytesRead);
12631}
12632
12633NS_IMETHODIMPnsresult
12634BackgroundRevalidatingListener::OnStopRequest(nsIRequest* request,
12635 nsresult status) {
12636 if (NS_FAILED(status)((bool)(__builtin_expect(!!(NS_FAILED_impl(status)), 0)))) {
12637 return status;
12638 }
12639
12640 nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(request));
12641 if (gHttpHandler) {
12642 gHttpHandler->OnBackgroundRevalidation(channel);
12643 }
12644 return NS_OK;
12645}
12646
12647NS_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"
, 12648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12648
); __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"
, 12648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12648); __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"
, 12648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12648
); __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"
, 12648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12648); __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", 12648
); 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; }
12648 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"
, 12648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 12648
); __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"
, 12648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12648); __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"
, 12648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 12648
); __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"
, 12648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"BackgroundRevalidatingListener\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 12648); __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", 12648
); 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; }
12649
12650} // namespace
12651
12652void nsHttpChannel::PerformBackgroundCacheRevalidation() {
12653 if (!StaticPrefs::network_http_stale_while_revalidate_enabled()) {
12654 return;
12655 }
12656
12657 // This is a channel doing a revalidation. It shouldn't do it again.
12658 if (mStaleRevalidation) {
12659 return;
12660 }
12661
12662 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)
;
12663
12664 (void)NS_DispatchToMainThreadQueue(
12665 NewIdleRunnableMethod(
12666 "nsHttpChannel::PerformBackgroundCacheRevalidation", this,
12667 &nsHttpChannel::PerformBackgroundCacheRevalidationNow),
12668 EventQueuePriority::Idle);
12669}
12670
12671void nsHttpChannel::PerformBackgroundCacheRevalidationNow() {
12672 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)
;
12673
12674 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", 12674
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { MOZ_CrashSequence(__null, 12674); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12675
12676 nsresult rv;
12677
12678 nsLoadFlags loadFlags = mLoadFlags | LOAD_ONLY_IF_MODIFIED | VALIDATE_ALWAYS |
12679 LOAD_BACKGROUND | LOAD_BYPASS_SERVICE_WORKER;
12680
12681 nsCOMPtr<nsIChannel> validatingChannel;
12682 rv = NS_NewChannelInternal(getter_AddRefs(validatingChannel), mURI, mLoadInfo,
12683 nullptr /* performance storage */, mLoadGroup,
12684 mCallbacks, loadFlags);
12685 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12686 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)
12687 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)
;
12688 return;
12689 }
12690
12691 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(validatingChannel));
12692 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"
, 12692); AnnotateMozCrashReason("MOZ_ASSERT" "(" "httpChannel"
")"); do { MOZ_CrashSequence(__null, 12692); __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12693 nsCOMPtr<nsIHttpHeaderVisitor> visitor =
12694 new CopyNonDefaultHeaderVisitor(httpChannel);
12695 rv = VisitNonDefaultRequestHeaders(visitor);
12696 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12697 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)
12698 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)
;
12699 return;
12700 }
12701
12702 nsCOMPtr<nsISupportsPriority> priority(do_QueryInterface(validatingChannel));
12703 if (priority) {
12704 priority->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
12705 }
12706
12707 nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(validatingChannel));
12708 if (cos) {
12709 cos->AddClassFlags(nsIClassOfService::Tail);
12710 }
12711
12712 RefPtr<nsHttpChannel> httpChan = do_QueryObject(validatingChannel);
12713 if (httpChan) {
12714 httpChan->mStaleRevalidation = true;
12715 }
12716
12717 RefPtr<BackgroundRevalidatingListener> listener =
12718 new BackgroundRevalidatingListener();
12719 rv = validatingChannel->AsyncOpen(listener);
12720 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
12721 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)
;
12722 return;
12723 }
12724
12725 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)
12726 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)
;
12727}
12728
12729NS_IMETHODIMPnsresult
12730nsHttpChannel::SetEarlyHintObserver(nsIEarlyHintObserver* aObserver) {
12731 mEarlyHintObserver = aObserver;
12732 return NS_OK;
12733}
12734
12735NS_IMETHODIMPnsresult
12736nsHttpChannel::EarlyHint(const nsACString& aLinkHeader,
12737 const nsACString& aReferrerPolicy,
12738 const nsACString& aCspHeader) {
12739 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)
;
12740
12741 if (nsCOMPtr<nsIEarlyHintObserver> obs = mEarlyHintObserver) {
12742 if (nsContentUtils::ComputeIsSecureContext(this)) {
12743 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)
;
12744 obs->EarlyHint(aLinkHeader, aReferrerPolicy, aCspHeader);
12745 }
12746 }
12747 return NS_OK;
12748}
12749
12750NS_IMETHODIMPnsresult nsHttpChannel::SetResponseOverride(
12751 nsIReplacedHttpResponse* aReplacedHttpResponse) {
12752 mOverrideResponse = new nsMainThreadPtrHolder<nsIReplacedHttpResponse>(
12753 "nsIReplacedHttpResponse", aReplacedHttpResponse);
12754
12755 if (LoadRequireCORSPreflight()) {
12756 // Bug 1986615, Bug 1940738, responses provided via setResponseOverride will
12757 // be handled before the preflight can be sent, flag it as done.
12758 StoreIsCorsPreflightDone(true);
12759 }
12760
12761 return NS_OK;
12762}
12763
12764NS_IMETHODIMPnsresult nsHttpChannel::SetResponseStatus(uint32_t aStatus,
12765 const nsACString& aStatusText) {
12766 if (!mResponseHead) {
12767 return NS_ERROR_NOT_AVAILABLE;
12768 }
12769
12770 nsAutoCString statusText(aStatusText);
12771 nsAutoCString protocolVersion(
12772 nsHttp::GetProtocolVersion(mResponseHead->Version()));
12773 ToUpperCase(protocolVersion);
12774
12775 nsPrintfCString line("%s %u %s", protocolVersion.get(), aStatus,
12776 statusText.get());
12777
12778 return mResponseHead->ParseStatusLine(line);
12779}
12780
12781NS_IMETHODIMPnsresult nsHttpChannel::SetWebTransportSessionEventListener(
12782 WebTransportSessionEventListener* aListener) {
12783 mWebTransportSessionEventListener = aListener;
12784 return NS_OK;
12785}
12786
12787already_AddRefed<WebTransportSessionEventListener>
12788nsHttpChannel::GetWebTransportSessionEventListener() {
12789 RefPtr<WebTransportSessionEventListener> wt =
12790 mWebTransportSessionEventListener;
12791 return wt.forget();
12792}
12793
12794NS_IMETHODIMPnsresult nsHttpChannel::GetLastTransportStatus(
12795 nsresult* aLastTransportStatus) {
12796 *aLastTransportStatus = mLastTransportStatus;
12797 return NS_OK;
12798}
12799
12800NS_IMETHODIMPnsresult
12801nsHttpChannel::GetCacheDisposition(CacheDisposition* aDisposition) {
12802 if (!aDisposition) {
12803 return NS_ERROR_INVALID_ARG;
12804 }
12805 *aDisposition = mCacheDisposition;
12806 return NS_OK;
12807}
12808
12809} // namespace net
12810} // namespace mozilla